Alchemy
Loading...
Searching...
No Matches

colorfx.c

Go to the documentation of this file.
4#include "battle.h"
5#include "keystate.h"
6#include "debug.h"
7#include "field.h"
8#include "game.h"
9#include "graphics.h"
10#include "menu.h"
11#include "minigame.h"
12#include "sound.h"
13#include "system.h"
14#include "battle_effect_work.h"
15#include "heap_state.h"
16#include "game_state.h"
17#include "types.h"
18#include "macros.h"
19#include "dma.h"
20#include "iwram_call.h"
21#include "resource.h"
22#include "io_reg.h"
23#include "songs.h"
24#include "mem.h"
25#include "fixed_math.h"
26#include "effect_step.h"
27#include "battle_effect.h"
28#include "callback_scheduler.h"
29#include "map_scroll.h"
30#include "ram_buffer.h"
31#include "resource_ids.h"
32#include "tbs_edition.h"
33#include "text/msg_ids.h"
34#include "lzpack.h"
35#include "frame.h"
36#include "oambuf.h"
37#include "item_ids.h"
38
39//--------------------------------------------------------------------------
40// The slot machine (the reel game): its palette steps, canvas transfers and
41// line drawing, and an LZ packer.
42//--------------------------------------------------------------------------
43
44/// The sparks of the jackpot, kept in the map cell buffer.
45#define REEL_SPARKS ((struct EffectStep *)Ram_MapCellBuffer)
46
47/// The slot machine's own work block (struct ReelWork), beside the battle
48/// effect blocks it borrows.
49#define REEL_HEAP_SLOT 45
50
51/// The paylines' canvas: 256 x 128 pixels of 8-bit colour, shown on BG2 from
52/// its tile 212, where the third row of its map begins.
53#define REEL_CANVAS_SIZE (256 * 128)
54#define REEL_CANVAS_TILES (BG_CHAR_BLOCK(0) + 0x3500)
55
56/// Plays the slot machine: blanks the screen, seeds the random numbers with the
57/// play time and runs the game. Returns 0.
63 return 0;
64}
65
66/// Writes count RGB555 colours from src to dst scaled by scale (16.16, 0x10000
67/// keeps them). Returns 0.
68s32 Graphics_ScaleRgb555(u16 *src, u16 *dst, s32 scale, s32 count) {
69 s32 n;
70 u32 redMask;
71 u32 greenMask;
72 u32 blueMask;
73 u32 col;
74 u32 r;
75 u32 g;
76 u32 b;
77
78 if (count > 0) {
79 redMask = 0x1f;
80 greenMask = 0x3e0;
81 blueMask = 0x7c00;
82 n = count;
83 do {
84 // Scale each channel where it stands and keep the top 16 bits.
85 col = *src;
86 r = col & redMask;
87 g = col & greenMask;
88 b = blueMask & col;
89 r *= scale;
90 g *= scale;
91 b *= scale;
92 col = ((r >> 16) & redMask) | ((g >> 16) & greenMask);
93 col |= (b >> 16) & blueMask;
94 *dst = col;
95 src++;
96 dst++;
97 n--;
98 } while (n != 0);
99 }
100 return 0;
101}
102
103/// A scheduler callback: on a frame whose canvas is ready (transferPending),
104/// sends the canvas to its tiles in VRAM (REEL_CANVAS_TILES), then clears it
105/// or fades it into trails as transferMode says.
107 struct BattleEffectWork *work;
108 u8 *buf;
109
110 work = gBattleFxWork[0];
111 if (work->transferPending == 1) {
112 buf = gBattleFxWork[1];
113 switch (work->transferMode) {
114 case 1:
115 // Then fill the canvas with transferValue.
116 Dma_Set(buf, (void *)REEL_CANVAS_TILES,
119 break;
120 case 2:
121 // Trails: fade nonzero colour numbers to 1/2 or 3/4.
122 if (work->transferValue == 50)
125 else
128 break;
129 }
130 work->transferPending = 0;
131 work->framesSinceTransfer = 1;
132 } else {
133 (work->framesSinceTransfer)++;
134 }
135}
136
137/// Darkens the screen one step: lowers each channel of the 16 colours of BG
138/// palette 10 and of OBJ colours 1 to 239 by 1.
140 u16 *col;
141 s32 i;
142
143 col = (u16 *)&BG_PLTT_COLOR(10, 0);
144 for (i = 0; i != 16; i++) {
145 s32 b = (*col >> 10) & 0x1f;
146 s32 g = (*col >> 5) & 0x1f;
147 s32 r = *col & 0x1f;
148
149 b--;
150 g--;
151 r--;
152
153 if (b < 0)
154 b = 0;
155 if (g < 0)
156 g = 0;
157 if (r < 0)
158 r = 0;
159 *col++ = RGB(r, g, b);
160 }
161 col = (u16 *)&OBJ_PLTT[1];
162 for (i = 0; i != 239; i++) {
163 s32 b = (*col >> 10) & 0x1f;
164 s32 g = (*col >> 5) & 0x1f;
165 s32 r = *col & 0x1f;
166
167 b--;
168 g--;
169 r--;
170
171 if (b < 0)
172 b = 0;
173 if (g < 0)
174 g = 0;
175 if (r < 0)
176 r = 0;
177 *col++ = RGB(r, g, b);
178 }
179}
180
181/// Moves the first 64 BG colours one step toward the palette of resource; the
182/// backdrop colour is not written back.
184 u16 dst[64];
185 u16 *col = (u16 *)BG_PLTT;
186 s32 i;
187
188 Dma_Set(Resource_GetTableEntry(resource), dst,
189 (DMA_ENABLE | DMA_32BIT) << 16 | 0x20, REG_DMA3);
190 for (i = 0; i != 64; i++, col++) {
191 s32 r = *col & 0x1f;
192 s32 g = (*col >> 5) & 0x1f;
193 s32 b = (*col >> 10) & 0x1f;
194 s32 targetRed = dst[i] & 0x1f;
195 s32 targetGreen = (dst[i] >> 5) & 0x1f;
196 s32 targetBlue = (dst[i] >> 10) & 0x1f;
197
198 if (r < targetRed)
199 r++;
200 else if (r > targetRed)
201 r--;
202 if (g < targetGreen)
203 g++;
204 else if (g > targetGreen)
205 g--;
206 if (b < targetBlue)
207 b++;
208 else if (b > targetBlue)
209 b--;
210 dst[i] = RGB(r, g, b);
211 }
212 Dma_Set(dst + 1, (void *)&BG_PLTT[1], (DMA_ENABLE << 16) | 63, REG_DMA3);
213}
214
215/// Draws a line from (x0, y0) to (x1, y1) on the 256 x 128 8bpp canvas (32
216/// tiles across), writing only over lower colour numbers.
217void ReelGame_DrawCanvasLine(s32 x0, s32 y0, s32 x1, s32 y1, s32 color) {
218 s32 dx = x1 - x0;
219 s32 dy = y1 - y0;
220 s32 frac = 0x80; // 0.5 in 8-bit fixed point
221 u8 *canvas = ((u8 **)gBattleFxWork)[1];
222 s32 step;
223 s32 i;
224 s32 x;
225 s32 y;
226 s32 tmp;
227 u32 offset;
228
229 if (ABS(dx) < ABS(dy)) {
230 // Steep: step y one pixel at a time and follow x in fixed point.
231 if (dy < 0) {
232 tmp = x0;
233 x0 = x1;
234 x1 = tmp;
235 tmp = y0;
236 y0 = y1;
237 y1 = tmp;
238 dx = x1 - x0;
239 dy = y1 - y0;
240 }
241 step = (ABS(x1 - x0) << 8) / ABS(y1 - y0);
242 x = x0;
243 for (i = y0; i != y1; i++) {
244 offset = (((((u32)i >> 3) << 5) + ((u32)x >> 3)) << 3) + (i & 7);
245 offset = (offset << 3) + (x & 7);
246 if (canvas[offset] < color)
247 canvas[offset] = color;
248 frac += step;
249 if (frac & 0x100) {
250 if (dx > 0)
251 x++;
252 else
253 x--;
254 frac &= ~0x100;
255 }
256 }
257 } else {
258 // Shallow: step x one pixel at a time and follow y in fixed point.
259 if (dx < 0) {
260 tmp = x0;
261 x0 = x1;
262 x1 = tmp;
263 tmp = y0;
264 y0 = y1;
265 y1 = tmp;
266 dx = x1 - x0;
267 dy = y1 - y0;
268 }
269 step = (ABS(y1 - y0) << 8) / ABS(x1 - x0);
270 y = y0;
271 for (i = x0; i != x1; i++) {
272 offset = (((((u32)y >> 3) << 5) + ((u32)i >> 3)) << 3) + (y & 7);
273 offset = (offset << 3) + (i & 7);
274 if (canvas[offset] < color)
275 canvas[offset] = color;
276 frac += step;
277 if (frac & 0x100) {
278 if (dy > 0)
279 y++;
280 else
281 y--;
282 frac &= ~0x100;
283 }
284 }
285 }
286}
287
288/// One of the slot machine's five reels: how far it has turned, its 21
289/// symbols, whether it is held, and the countdown to its stop (-1 until one
290/// starts).
291struct Reel {
292 s32 position; ///< pixels, 16 a symbol
295 s8 stop; ///< frames
296};
297
298struct UiWindow;
299
300/// The slot machine's states (ReelWork.state).
302 REEL_BETTING = 0, ///< Up and Down change the bet, A spins, B leaves
303 REEL_SPINNING = 1, ///< the reels spin until R or time stops each
304 REEL_WON = 2, ///< a payline won: a pause
305 REEL_SHOWING_WIN = 3, ///< the win is shown until A
306 REEL_CHOOSING_HOLDS = 5, ///< choose reels to hold, or pull the lever
307 REEL_DONE = 10, ///< the game ends
308 REEL_NO_WIN = 11, ///< no payline won: A to choose holds
309 REEL_OUT_OF_SPINS = 20, ///< the fourth spin lost: a pause, then the end
310};
311
312/// The slot machine's work in heap slot 45: its reels, state, bet and spins,
313/// keys, timer, winning lines, sprites and windows.
314struct ReelWork {
315 struct Reel reels[5];
327 struct OamShadow obj[128];
332#if TBS_PATCH_1
334#endif
335};
336
337/// gGameState seen from +12, the base the bytes load: wonPrizes is
338/// gGameState.wonPrizes (through the field itself ReelGame_RunFrame differs 12)
339struct ReelSave {
340 u8 unk000[0x120];
342};
343
345
346/// The slot machine's frame callback: reads the keys, runs the game's state
347/// (betting, spinning and stopping the reels, scoring the paylines, choosing
348/// reels to hold, showing a win) and builds all 128 sprites: the cursor, the
349/// title letters of a win, the frame, the hold lamps, the spin counter, the
350/// paylines, the reel symbols, the lever and the bottom bar.
352 /* FAKEMATCH(volatile): struct OamShadow's volatile words (oambuf.h) keep
353 * each list loop's offset givs; as plain u32 words, 675 of 1729
354 * instructions differ in tbs-en. */
355 struct ReelWork *work;
356 struct BattleEffectWork *fx;
357 volatile u16 *dma;
358 s32 sprite;
359 s32 objMode;
360 u16 keys;
361 u32 dpad;
362 s32 tickets;
363 s32 allHeld;
364 s32 stoppedReels;
365 s32 col;
366 s32 v;
367 s32 x;
368 s32 y;
369 s32 lever;
370 s32 k;
371 s32 i;
372
373 work = ((struct ReelWork **)
375 fx = gBattleFxWork[0];
376 sprite = 0;
377 objMode = 0x400;
378
379 Random16();
380
381 dma = REG_DMA0;
383 dma[5] &= ~DMA_ENABLE;
384 (void)dma[5];
385 // One halfword at each HBlank (repeating, destination reloaded).
386 Dma_Set(work->scanlineOffsets, (void *)&REG_BLDY,
387 DMA_HBLANK_HALFWORD_PER_LINE, (volatile u32 *)dma);
388
389 keys = gKeysHeld;
390 dpad = gKeysHeld & KEYS_DPAD;
391 work->pressed = keys & ~work->keys;
392 work->direction = dpad;
393 if ((work->keys & KEYS_DPAD) == work->direction) {
394 if (work->repeat > 12)
395 work->repeat = 12;
396 if (work->repeat == 0) {
397 work->repeat = 4;
398 } else {
399 work->repeat--;
400 work->direction = sprite; // 0: no sprite is built yet
401 }
402 } else {
403 work->repeat = 12;
404 }
405 work->keys = keys;
406
407 if (gDebugPaused == 0) {
408 if (work->state == REEL_BETTING) {
411 work->subWindow, REEL_COIN_X, 0);
412 UiText_DrawNumberInWindowFar(work->bet, 2, work->subWindow, 64, 8);
413 if (work->pressed & KEY_B) {
414 struct ReelSave *save = (struct ReelSave *)((u8 *)&gGameState + 12);
415
416 work->state = REEL_DONE;
417 save->wonPrizes[0] = -2;
418 UiWork_FinalizeFar(work->window, 1);
419 } else {
420 if (work->pressed & KEY_UP) {
421 if (work->bet <= 3 && tickets > work->bet) {
422 work->bet++;
424 } else {
426 }
427 }
428 if (work->pressed & KEY_DOWN) {
429 if (work->bet > 1) {
430 work->bet--;
432 } else {
434 }
435 }
437 REG_BLDALPHA = BLEND_ALPHA(16, 0);
438 if (work->pressed & KEY_A) {
439 work->state = REEL_SPINNING;
440 fx->frame = 0;
441 UiWork_FinalizeFar(work->window, 1);
442 for (k = 0; k != work->bet; k++)
446 }
447 }
448 } else if (work->state == REEL_CHOOSING_HOLDS) {
449 allHeld = 0;
450 work->timer++;
451 for (k = 0; k != 5 && work->reels[k].held != 0; k++)
452 ;
453 if (k == 5)
454 allHeld = 1;
455 if (work->pressed & KEY_A) {
456 work->timer = 0;
457 fx->frame = 0;
458 if (work->spins == 4) {
459 work->spins = 0;
460 work->cursor = 0;
461 work->state = REEL_BETTING;
462 for (i = 0; i != 5; i++) {
463 work->reels[i].held = 0;
464 work->reels[i].stop = -1;
465 }
466 } else if (work->cursor <= 4) {
468 work->reels[work->cursor].held ^= 1;
469 } else if (allHeld == 0) {
471 work->state = REEL_SPINNING;
472 work->cursor = 0;
473 for (i = 0; i != 5; i++)
474 work->reels[i].stop = -1;
475 work->spins++;
476 } else {
478 }
479 } else {
480 if (work->direction & KEY_RIGHT) {
481 work->cursor = (work->cursor + 1) % 6;
483 }
484 if (work->direction & KEY_LEFT) {
485 work->cursor = (work->cursor + 5) % 6;
487 }
488 }
489
490 if (work->state == REEL_CHOOSING_HOLDS) {
491#if TBS_PATCH_1
492 if (work->cursor == 5) {
493 if (allHeld != 0) {
494 if (work->phase != 1 && work->phase != 2) {
495 UiWork_FinalizeFar(work->window, 1);
497 REEL_ALL_HELD_WIDTH, 4, 6);
498 UiText_DrawCharacterAtOffsetFar(MsgSlotsAllHeld, work->window, 0,
499 0);
500 work->phase = 1;
501 } else if (work->phase == 1) {
502 UiText_DrawCharacterAtOffsetFar(MsgSlotsCannotPull, work->window,
503 0, 8);
504 work->phase = 2;
505 }
506 } else {
507 if (work->phase != 3) {
508 UiWork_FinalizeFar(work->window, 1);
509 work->window =
511 UiText_DrawCharacterAtOffsetFar(MsgSlotsStart, work->window, 0,
512 0);
513 }
514 work->phase = 3;
515 }
516 } else if (work->reels[work->cursor].held == 0) {
517 if (work->phase != 4) {
518 UiWork_FinalizeFar(work->window, 1);
519 work->window =
521 UiText_DrawCharacterAtOffsetFar(MsgSlotsHold, work->window, 0, 0);
522 }
523 work->phase = 4;
524 } else {
525 if (work->phase != 5) {
526 UiWork_FinalizeFar(work->window, 1);
527 work->window =
529 UiText_DrawCharacterAtOffsetFar(MsgSlotsRelease, work->window, 0,
530 0);
531 }
532 work->phase = 5;
533 }
534#else
535 UiWork_FinalizeFar(work->window, 1);
536 if (work->cursor == 5) {
537 if (allHeld != 0) {
538 work->window = UiWindow_CreateFar(12, 0, 18, 3, 6);
539 UiText_DrawCharacterAtOffsetFar(MsgSlotsAllHeld, work->window, 0,
540 0);
541 } else {
542 work->window = UiWindow_CreateFar(18, 0, 12, 3, 6);
543 UiText_DrawCharacterAtOffsetFar(MsgSlotsStart, work->window, 0, 0);
544 }
545 } else {
546 work->window = UiWindow_CreateFar(18, 0, 12, 3, 6);
547 if (work->reels[work->cursor].held == 0)
548 UiText_DrawCharacterAtOffsetFar(MsgSlotsHold, work->window, 0, 0);
549 else
550 UiText_DrawCharacterAtOffsetFar(MsgSlotsRelease, work->window, 0,
551 0);
552 }
553#endif
554 } else {
555 UiWork_FinalizeFar(work->window, 1);
556 }
557 } else if (work->state == REEL_WON) {
558 work->timer++;
559 objMode = 0;
560 if (work->timer == 60) {
561 work->state = REEL_SHOWING_WIN;
563 work->timer = 0;
565 REG_BLDALPHA = BLEND_ALPHA(16, 16);
566 fx->transferMode = 2;
567 fx->transferValue = 75;
568 }
569 } else if (work->state == REEL_SHOWING_WIN) {
570 work->timer++;
571 objMode = 0;
572 if (work->pressed & KEY_A) {
573 work->state = REEL_DONE;
575 }
576 } else if (work->state == REEL_NO_WIN) {
577#if TBS_PATCH_1
578 if (work->phase == 0) {
579 work->phase = 1;
580 UiText_DrawCharacterAtOffsetFar(MsgSlotsPullLever, work->window, 0, 8);
581 }
582#endif
583 if (work->pressed & KEY_A) {
585#if TBS_PATCH_1
586 work->phase = 0;
587#endif
589 UiWork_FinalizeFar(work->window, 1);
590 }
591 } else if (work->state == REEL_OUT_OF_SPINS) {
592 work->timer++;
593 if (work->timer == 45)
594 work->state = REEL_DONE;
595 } else if (work->state != REEL_DONE) {
596 if (work->timer == 4) {
597 work->window =
599 UiText_DrawCharacterAtOffsetFar(MsgSlotsStopReels, work->window, 0, 0);
600 }
601 if (work->timer == 16)
603 if (work->timer > 56) {
604 if (fx->frame > 31 || (work->pressed & KEY_R)) {
605 fx->frame = 0;
606 for (i = 0; i != 5; i++) {
607 if (work->reels[i].held == 0 && work->reels[i].stop == -1) {
608 work->reels[i].stop = (Random16() & 3) + 4;
610 break;
611 }
612 }
613 }
614 }
615
616 for (i = 0; i != 5; i++) {
617 if (work->reels[i].stop > 0)
618 work->reels[i].stop--;
619 }
620
621 stoppedReels = 0;
622 for (i = 0; i != 5; i++) {
623 if (work->reels[i].held == 1)
624 stoppedReels++;
625 else if (work->reels[i].stop == 0 &&
626 (work->reels[i].position & 15) == 8)
627 stoppedReels++;
628 }
629
630 if (stoppedReels == 5) {
631 struct ReelSave *save = (struct ReelSave *)((u8 *)&gGameState + 12);
632 s32 hits = 0;
633
634 for (col = 0; col != 7; col++) {
635 s32 mixed;
636 s32 found;
637
638 found = -1;
639 mixed = 0;
640 work->winningLines[col] = 0;
641 if (col > 3 - work->bet && col < work->bet + 3) {
642 for (i = 0; i != 5; i++) {
643 s32 sym;
644
645 if (col == 0)
646 sym =
647 work->reels[i]
648 .symbols[(i - work->reels[i].position / 16 + 22) % 21];
649 else if (col == 6)
650 sym =
651 work->reels[i]
652 .symbols[(-i - work->reels[i].position / 16 + 26) % 21];
653 else
654 sym = work->reels[i]
655 .symbols[(col - work->reels[i].position / 16 + 21) %
656 21];
657 if (sym != 5) {
658 if (found == -1)
659 found = sym;
660 else if (found != sym)
661 mixed = 1;
662 }
663 }
664 if (mixed == 0) {
665 work->winningLines[col] = 1;
666 save->wonPrizes[hits] = gReelGame_SymbolPrizes[found];
667 hits++;
668 }
669 }
670 }
671 work->timer = 0;
672 if (hits != 0) {
673 save->wonPrizes[hits] = -1;
674 work->state = REEL_WON;
676 fx->transferMode = 1;
677 fx->transferValue = 0;
678 REG_BLDCNT = 0;
679 UiWork_FinalizeFar(work->window, 1);
680 } else {
681 work->state = REEL_NO_WIN;
682#if TBS_PATCH_1
683 work->phase = 0;
684 UiWork_FinalizeFar(work->window, 1);
685#if REEL_HINT_BEFORE_LAST_SPIN
686 if (work->spins <= 3)
687#endif
688 {
689 work->window = UiWindow_CreateFar(3, 16, 24, 4, 6);
690 UiText_DrawCharacterAtOffsetFar(MsgSlotsChooseHeld, work->window, 0,
691 0);
692 }
693#else
694 UiWork_FinalizeFar(work->window, 1);
695 {
696 s32 message;
697
698 work->window = UiWindow_CreateFar(7, 16, 16, 4, 6);
699 message = MsgSlotsChooseHeld;
700 UiText_DrawCharacterAtOffsetFar(message, work->window, 0, 0);
701 UiText_DrawCharacterAtOffsetFar(message + 1, work->window, 0, 8);
702 }
703#endif
704 if (work->spins == 4) {
706 struct UiWindow *window;
707 s32 message;
708
709 if (left > 0)
710 work->state = REEL_OUT_OF_SPINS;
711 else
712 work->state = REEL_OUT_OF_SPINS;
713 if (work->bet > left)
714 work->bet = left;
715 work->spins = 0;
716 work->cursor = 0;
717 for (i = 0; i != 5; i++) {
718 work->reels[i].held = 0;
719 work->reels[i].stop = -1;
720 }
721 fx->transferMode = 1;
722 fx->transferValue = 0;
723 REG_BLDCNT = 0;
724 window = UiWindow_CreateFar(18, 0, 12, 4, 6);
725 work->subWindow = window;
726 message = MsgSlotsBet;
727 UiText_DrawCharacterAtOffsetFar(message, window, 0, 8);
728 UiText_DrawCharacterAtOffsetFar(message - 1, work->subWindow, 0, 0);
729 }
730 }
731 }
732
733 if (work->state == REEL_SPINNING) {
734 for (i = 0; i != 5; i++) {
735 struct Reel *reel = &work->reels[i];
736
737 if (reel->held == 0) {
738 if (reel->stop != 0)
739 reel->position += 8;
740 else if ((reel->position & 15) != 8)
741 reel->position += 8;
742 if (reel->position == 336)
743 reel->position = 0;
744 }
745 }
746 }
747 (fx->frame)++;
748 work->timer++;
749 }
750 }
751
752 if (work->state == REEL_CHOOSING_HOLDS) {
753 x = work->cursor * 36 + 36;
754 y = 128;
755 v = 0;
756 if ((work->timer & 15) <= 7)
757 v = 1;
758 if (work->cursor == 5) {
759 x = 208;
760 y = 32;
761 }
762 work->obj[sprite].attr01 =
763 ((x - 12) << 16) | objMode | (y + 8) | 0x80006000;
764 work->obj[sprite].attr2 = (v << 4) + 0x2b0;
765 sprite++;
766 work->obj[sprite].attr01 =
767 ((x + 12) << 16) | objMode | (y + 8) | 0x90006000;
768 work->obj[sprite].attr2 = (v << 4) + 0x2b0;
769 sprite++;
770 work->obj[sprite].attr01 = (x << 16) | objMode | y | 0x80002000;
771 work->obj[sprite].attr2 = 0x1f0;
772 sprite++;
773 }
774
775 if (work->state == REEL_SHOWING_WIN) {
776 for (i = 0; i != REEL_TITLE_LETTERS; i++) {
777 struct EffectStep *p = &fx->particles[i];
778
779#if (LANGUAGE == LANGUAGE_SPANISH)
780 if (i == 0)
781 work->obj[sprite].attr01 =
782 (((*(s16 *)((u8 *)&p->x + 2) + 0x1f0) & 0x1ff) << 16) | objMode |
783 ((*(s16 *)((u8 *)&p->y + 2) + 0x108) & 255) | 0xb0000000;
784 else
785#endif
786 work->obj[sprite].attr01 = (*(s16 *)((u8 *)&p->x + 2) << 16) | objMode |
787 ((*(s16 *)((u8 *)&p->y + 2) + 256) & 255) |
788 0x80000000;
789 work->obj[sprite].attr2 =
790 ((gReelGame_TitleLetterTiles[i] << 4) + REEL_TITLE_TILES) | 0xf000;
791 p->y += p->velocityY;
792 p->velocityY += 0x4000;
793 if (work->timer % 256 == i * 4 + 200) {
794 p->velocityY = 0x60000;
795 p->variant = 0;
796 }
797 if (p->y > 0x400000) {
798 p->y = 0x400000;
799 if (p->variant <= 1)
800 p->velocityY = -p->velocityY / 2;
801 p->variant++;
802 }
803 sprite++;
804 }
805 }
806
807 for (k = 0; k != 14; k++) {
808 work->obj[sprite].attr01 = (gReelGame_FrameSpriteX[k] << 16) | objMode |
809 gReelGame_FrameSpriteY[k] | 0x80006000;
810 if (k <= 3)
811 work->obj[sprite].attr2 = 0x4e0;
812 else
813 work->obj[sprite].attr2 = 0x4e8;
814 sprite++;
815 }
816
817 for (i = 0; i != 5; i++) {
818 if (work->reels[i].held == 0) {
819 work->obj[sprite].attr01 = objMode | ((i * 36 + 32) << 16) | 0x8000207c;
820 work->obj[sprite].attr2 = 0x460;
821 } else {
822 work->obj[sprite].attr01 = objMode | ((i * 36 + 32) << 16) | 0x8000207c;
823 work->obj[sprite].attr2 = 0x480;
824 }
825 sprite++;
826 }
827
828 for (i = 0; i != 5; i++) {
829 work->obj[sprite].attr01 = objMode | ((i * 16 + 32) << 16) | 0x80006003;
830 if (i == work->spins)
831 work->obj[sprite].attr2 = (i * 32 + 0x210) | 0x400;
832 else
833 work->obj[sprite].attr2 = (i * 32 + 0x220) | 0x400;
834 sprite++;
835 }
836
837 for (col = 0; col != 7; col++) {
838 work->obj[sprite].attr01 = (((0x204 - ((col & 1) << 3)) & 0x1ff) << 16) |
839 objMode | (col * 16 + 5) | 0x80002000;
840 if (col > 3 - work->bet && col < work->bet + 3)
841 work->obj[sprite].attr2 = 0x5d0;
842 else
843 work->obj[sprite].attr2 = 0x510;
844 sprite++;
845 }
846
847 for (i = 0; i != 5; i++) {
848 struct Reel *reel = &work->reels[i];
849
850 for (col = 0; col != 7; col++) {
851 work->obj[sprite].attr01 = (col * 16 + reel->position % 16 + 4) |
852 ((i * 32 + 40) << 16) | 0x80006000;
853 work->obj[sprite].attr2 =
854 (reel->symbols[(col - reel->position / 16 + 21) % 21] << 4) | 0x800;
855 sprite++;
856 }
857 }
858
859 lever = 40;
860 if (work->state == REEL_SPINNING) {
861 if (work->timer <= 47)
862 lever = ((Trig_Sin(work->timer * 682) << 6) >> 16) + 40;
863 else if (work->timer <= 55)
864 lever = ((Trig_Sin((work->timer << 12) - 0x30000) << 2) >> 16) + 40;
865 }
866 work->obj[sprite].attr01 = lever | objMode | 0x80d06000;
867 work->obj[sprite].attr2 = 0x500;
868 sprite++;
869
870 for (k = 0; k != 8; k++) {
871 work->obj[sprite].attr01 = objMode | (k * 16 + 12) | 0x80ce6000;
872 if (k == 0)
873 work->obj[sprite].attr2 = 0x540;
874 else if (k == 1)
875 work->obj[sprite].attr2 = 0x550;
876 else if (k == 6)
877 work->obj[sprite].attr2 = 0x570;
878 else if (k == 7)
879 work->obj[sprite].attr2 = 0x580;
880 else
881 work->obj[sprite].attr2 = 0x560;
882 sprite++;
883 }
884
885 while (sprite != 128) {
886 work->obj[sprite].attr01 = 0x40f02000;
887 work->obj[sprite].attr2 = 0;
888 sprite++;
889 }
890
891 Dma_Set(work->obj, OAM, (sprite * 2) | (DMA_ENABLE | DMA_32BIT) << 16,
892 REG_DMA3);
893}
894
895/// Sets up the bouncing title letters of a win, the brightness wave of the
896/// screen's lines and the betting window, and starts at betting.
898 struct ReelWork *state;
899 struct BattleEffectWork *work;
900 struct EffectStep *letter;
901 const u8 *width;
902 s32 left;
903 s32 step;
904 s32 y;
905 s32 i;
906 s32 angle;
907 struct UiWindow *window;
908 s32 message;
909
910 state = ((struct ReelWork **)
912 work = gBattleFxWork[0];
913 left = 0;
914 for (i = 0; i != 0x800; i++)
915 REEL_SPARKS[i].variant = 0;
916
917 letter = work->particles;
918 y = -0x200000;
920 for (i = 0; i != REEL_TITLE_LETTERS; i++) {
921 letter[i].x = (left + REEL_TITLE_X) << 16;
922 step = *width;
923 width++;
924 left += step;
925 letter[i].y = y;
926 letter[i].velocityY = 0;
927 letter[i].variant = 0;
928 y += -0x80000;
929 }
930
931 for (i = 0; i != 160; i++)
932 state->scanlineOffsets[i] = 0;
933
934 for (i = 0; i != 40; i++) {
935 angle = i * 0x199;
936 state->scanlineOffsets[23 + i] = (u32)(Trig_Cos(angle) * 3) >> 15;
937 state->scanlineOffsets[110 - i] = (u32)(Trig_Cos(angle) * 3) >> 15;
938 }
939
940 state->spins = 0;
941 state->state = REEL_BETTING;
942 state->cursor = 0;
943 work->transferMode = 1;
944 work->transferValue = 0;
945 REG_BLDCNT = 0;
946 window = UiWindow_CreateFar(18, 0, 12, 4, 6);
947 state->subWindow = window;
948 message = MsgSlotsBet;
950 UiText_DrawCharacterAtOffsetFar(message - 1, state->subWindow, 0, 0);
951}
952
953/// The slot machine: loads its backgrounds, sprites and palettes, fills each of
954/// the five reels with 21 random symbols (with eight placed symbols of rank 0
955/// to 5), then runs until the player leaves: fading in, drawing the paylines
956/// on the canvas while betting or winning, and the jackpot's sparks and
957/// colour cycle while showing a win. Then fades out and frees its memory.
958void ReelGame_Run(void) {
959 s32 picks[8];
960 s32 litLines[7];
961 DrawRectangle draw[2];
962 u8 *sheet;
963 void *canvas;
964 struct BattleEffectWork *work;
965 struct ReelWork *state;
966 struct ReelSave *save;
967 u8 *entry;
968 u8 *tiles;
969 s32 frame;
970 u32 count;
971 s32 i;
972 s32 j;
973 s32 k;
974
978 sizeof(struct BattleEffectWork));
979 state = Runtime_AllocateBlock(REEL_HEAP_SLOT, sizeof(struct ReelWork));
980 tiles = Ram_MapCellBuffer;
981 save = (struct ReelSave *)((u8 *)&gGameState + 12);
983 save->wonPrizes[0] = -1;
984 state->repeat = 0;
985 state->bet = 1;
987 gOamCopyEnabled = 0;
988
989 count = 0;
990 j = 0;
991 for (k = 0; k != 20; k++) {
992 for (i = 0; i != 32; i++, j += 2) {
993 if (i >= 5 && i <= 24 && k > 2 && k <= 13) {
994 *(volatile u16 *)(BG_SCREEN_BLOCK(5) + j) = 0xa1a6;
995 } else if (i > 29) {
996 *(volatile u16 *)(BG_SCREEN_BLOCK(5) + j) = 0;
997 } else {
998 *(volatile u16 *)(BG_SCREEN_BLOCK(5) + j) = 0xa1a8 + count;
999 count++;
1000 }
1001 }
1002 }
1006 Dma_Set(entry, (void *)&BG_PLTT_COLOR(10, 0),
1007 (DMA_ENABLE | DMA_32BIT) << 16 | 8, REG_DMA3);
1008 entry += 32;
1009 Resource_DecodeType01(entry, tiles);
1010 j = 0;
1011 for (k = 0; k != 20; k++) {
1012 for (i = 0; i != 30; i++) {
1013 if (!(i >= 5 && i <= 24 && k > 2 && k <= 13)) {
1014 Dma_Set(tiles + (k * 30 + i) * 32,
1015 (void *)(BG_CHAR_BLOCK(2) + 0x3500 + j),
1016 (DMA_ENABLE | DMA_32BIT) << 16 | 8, REG_DMA3);
1017 j += 32;
1018 }
1019 }
1020 }
1021 Iwram_ClearWords(BG_SCREEN_BLOCK(5) + 0x500, 0x300);
1022 j = 0;
1023 for (k = 0; k != 20; k++) {
1024 for (i = 0; i != 32; i++, j += 2) {
1025 if (k < 2 || k > 16)
1026 *(volatile u16 *)(BG_SCREEN_BLOCK(6) + j) = 0xbf;
1027 else
1028 *(volatile u16 *)(BG_SCREEN_BLOCK(6) + j) = k * 32 + i + 148;
1029 }
1030 }
1033 gBgScroll[0].x = 0;
1034 gBgScroll[0].y = 0;
1035 gBgScroll[1].x = 0;
1036 gBgScroll[1].y = 0;
1037 gBgScroll[2].x = 0;
1038 gBgScroll[2].y = 0;
1046 REG_BLDALPHA = BLEND_ALPHA(16, 16);
1047 REG_BG1HOFS = 0;
1048 REG_BG2HOFS = 0;
1049 REG_BG1VOFS = 0xff60;
1050 REG_BG2VOFS = 0xff60;
1051 REG_WIN0H = WIN_RANGE(40, 200);
1052 REG_WIN0V = WIN_RANGE(24, 120);
1053 REG_WIN0H = WIN_RANGE(0, 240);
1054 REG_WIN0V = WIN_RANGE(0, 160);
1055 REG_WIN1H = WIN_RANGE(0, 240);
1056 REG_WIN1V = WIN_RANGE(0, 160);
1057
1058 {
1059 u16 *shade = (u16 *)(work->sheet + 0x200);
1060 s32 size = REEL_CANVAS_SIZE;
1061
1062 state->state = REEL_BETTING;
1063 state->cursor = 0;
1064 state->spins = 0;
1065 work->frame = 0;
1066 state->timer = 0;
1068 (void *)BG_PLTT, (DMA_ENABLE | DMA_32BIT) << 16 | 32, REG_DMA3);
1069 // The paylines' two greens, colours 64 and 65 on the canvas.
1070 BG_PLTT_COLOR(4, 0) = RGB(11, 28, 11);
1071 BG_PLTT_COLOR(4, 1) = RGB(22, 31, 22);
1073 Dma_Set(entry, (void *)OBJ_PLTT, (DMA_ENABLE | DMA_32BIT) << 16 | 480 / 4,
1074 REG_DMA3);
1075 entry += 480;
1076 Resource_DecodeType01(entry, tiles);
1077 Dma_Set(tiles, (void *)OBJ_VRAM0, (DMA_ENABLE | DMA_32BIT) << 16 | 0x1b30,
1078 REG_DMA3);
1080 Dma_Set(entry, (void *)&OBJ_PLTT_COLOR(15, 0),
1081 (DMA_ENABLE | DMA_32BIT) << 16 | 8, REG_DMA3);
1082 entry += 32;
1083 Resource_DecodeType01(entry, tiles);
1087
1088 for (i = 0; i != 5; i++) {
1089 struct Reel *reel = &state->reels[i];
1090
1091 reel->position = 8;
1092 reel->held = 0;
1093 reel->stop = -1;
1094 for (k = 0; k != 21; k++)
1095 reel->symbols[k] = Random16() % 5;
1096 }
1097 for (i = 0; i != 5; i++) {
1098 struct Reel *reel = &state->reels[i];
1099
1100 for (j = 0; j != 8; j++) {
1101 picks[j] = Random16() % 21;
1102 for (k = 0; k != j; k++) {
1103 if (picks[j] == picks[k]) {
1104 j--;
1105 break;
1106 }
1107 }
1108 }
1109 for (k = 0; k != 8; k++) {
1110 s32 rank = k;
1111
1112 if (rank > 5)
1113 rank = 5;
1114 reel->symbols[picks[k]] = rank;
1115 }
1116 }
1117
1119 draw[0] = gWorkSlot[HEAP_SLOT_BLITTER];
1122 Iwram_FillWords(canvas, size, 0);
1123 Dma_Set(canvas, (void *)REEL_CANVAS_TILES,
1125 Dma_Set((void *)BG_PLTT, work, (DMA_ENABLE | DMA_32BIT) << 16 | 0x80,
1126 REG_DMA3);
1127 Dma_Set((void *)OBJ_PLTT, shade, (DMA_ENABLE | DMA_32BIT) << 16 | 0x80,
1128 REG_DMA3);
1129 Graphics_ScaleRgb555(shade, (u16 *)OBJ_PLTT, 0, 0x100);
1130 Graphics_ScaleRgb555((u16 *)work, (u16 *)BG_PLTT, 0, 0x100);
1134 struct UiWindow *window = UiWindow_CreateFar(6, 16, 18, 3, 6);
1135
1136 state->window = window;
1137 UiText_DrawCharacterAtOffsetFar(MsgSlotsControls, window, 0, 0);
1138 } else {
1139 struct UiWindow *window = UiWindow_CreateFar(
1141 s32 message;
1142
1143 state->window = window;
1144 message = MsgSlotsChangeBet;
1145 UiText_DrawCharacterAtOffsetFar(message, window, 0, 0);
1146 UiText_DrawCharacterAtOffsetFar(message + 1, state->window, 0, 8);
1147 }
1148 work->transferPending = 0;
1151
1152 for (frame = 0; state->state != REEL_DONE; frame++) {
1153 if (frame <= 16) {
1154 Graphics_ScaleRgb555(shade, (u16 *)OBJ_PLTT, frame << 12, 0x100);
1155 Graphics_ScaleRgb555((u16 *)work, (u16 *)BG_PLTT, frame << 12, 0x100);
1156 }
1157 if (state->state == REEL_SHOWING_WIN) {
1158 s32 phase = frame % 80;
1159
1160 if (phase <= 15)
1162 else if (phase <= 31)
1164 else if (phase <= 47)
1166 else if (phase <= 63)
1168 else
1170 if (state->timer <= 15)
1172 if (state->timer > 16 && (frame & 7) == 0) {
1173 s32 x = (Random16() & 127) + 56;
1174 s32 y = (Random16() & 31) + 48;
1175 struct EffectStep *spark = &REEL_SPARKS[(frame / 8 & 3) * 256];
1176
1177 for (j = 0; j != 256; j++) {
1178 s32 speed;
1179 s32 angle;
1180
1181 speed = 255;
1182 speed &= Random16();
1183 angle = Random16() & 0xffff;
1184 spark->x = x << 16;
1185 spark->y = y << 16;
1186 spark->velocityX = Trig_Sin(angle) * (speed + 64) >> 6;
1187 spark->velocityY = -(Trig_Cos(angle) * (speed + 64)) >> 6;
1188 spark->variant = (Random16() & 15) + 16;
1189 spark++;
1190 }
1191 }
1192 for (j = 0; j != 1024; j++) {
1193 struct EffectStep *spark = &REEL_SPARKS[j];
1194
1195 if (spark->variant > 0) {
1196 s32 x;
1197
1198 spark->variant--;
1199 x = spark->x;
1200 if (x >= 0 && x <= 0xffffff) {
1201 s32 y = spark->y;
1202
1203 if (y <= 0x7fffff) {
1204 if (y >= 0) {
1205 s32 px = x >> 16;
1206 s32 py = y >> 16;
1207 s32 size = spark->variant / 12 + 1;
1208
1209 draw[j & 1](canvas,
1210 sheet + gReelGame_SparkCellOffsets[size - 1],
1211 px - size, py - size, size * 2, size * 2);
1212 }
1213 }
1214 }
1215 spark->x += spark->velocityX;
1216 spark->y += spark->velocityY;
1217 spark->velocityX = spark->velocityX * 60 / 64;
1218 spark->velocityY = spark->velocityY * 60 / 64;
1219 }
1220 }
1221 }
1222 if (state->state == REEL_BETTING || state->state == REEL_WON) {
1223 for (j = 0; j != 7; j++)
1224 litLines[j] = 0;
1225 if (state->state == REEL_BETTING) {
1226 litLines[3] = 1;
1227 if (state->bet > 1) {
1228 litLines[4] = 1;
1229 litLines[2] = 1;
1230 }
1231 if (state->bet > 2) {
1232 litLines[5] = 1;
1233 litLines[1] = 1;
1234 }
1235 if (state->bet > 3) {
1236 litLines[6] = 1;
1237 litLines[0] = 1;
1238 }
1239 } else if ((frame & 7) <= 3) {
1240 for (j = 0; j != 7; j++)
1241 litLines[j] = state->winningLines[j];
1242 }
1243 for (j = 0; j != 3; j++) {
1244 s32 color = j != 1;
1245
1246 color = 65 - color;
1247 if (litLines[1])
1248 ReelGame_DrawCanvasLine(20, j + 19, 200, j + 19, color);
1249 if (litLines[2])
1250 ReelGame_DrawCanvasLine(28, j + 35, 200, j + 35, color);
1251 if (litLines[3])
1252 ReelGame_DrawCanvasLine(20, j + 51, 200, j + 51, color);
1253 if (litLines[4])
1254 ReelGame_DrawCanvasLine(28, j + 67, 200, j + 67, color);
1255 if (litLines[5])
1256 ReelGame_DrawCanvasLine(20, j + 83, 200, j + 83, color);
1257 if (litLines[0])
1258 ReelGame_DrawCanvasLine(28, j + 5, 200, j + 91, color);
1259 if (litLines[6])
1260 ReelGame_DrawCanvasLine(28, j + 97, 200, j + 11, color);
1261 }
1262 }
1263 work->transferPending = 1;
1264 WaitFrames(1);
1265 }
1266
1267 for (j = 0; j != 17; j++) {
1268 Graphics_ScaleRgb555(shade, (u16 *)OBJ_PLTT, 0x10000 - (j << 12), 0x100);
1269 Graphics_ScaleRgb555((u16 *)work, (u16 *)BG_PLTT, 0x10000 - (j << 12),
1270 0x100);
1271 WaitFrames(1);
1272 }
1281 }
1282}
1283
1284// The LZ packer: a window of 1024 bytes, matches of up to PACK_MATCH_MAX
1285// bytes at most PACK_DISTANCE_MAX back, and PACK_LOOKAHEAD bytes read ahead.
1286#define PACK_WINDOW_MASK 0x3ff
1287#define PACK_MATCH_MAX 272
1288#define PACK_DISTANCE_MAX 63
1289#define PACK_LOOKAHEAD 672
1290
1291/// The LZ packer below: empties its 256 hash chains (one per byte value) and
1292/// numbers its 1024 window nodes.
1294 s32 index;
1295 struct LzPackNode **bucket;
1296
1297 for (index = 0; index < 0x400; index++) {
1298 gFlash_Handler3->nodes[index].slot = index;
1299 gFlash_Handler3->nodes[index].prev = NULL;
1300 }
1301 bucket = gFlash_Handler3->bucket;
1302 for (index = 0xFF; index >= 0; index--) {
1303 *bucket++ = NULL;
1304 }
1305}
1306
1307/// Adds window position index to the chain of the byte it holds.
1309 struct LzPackWork *work = gFlash_Handler3;
1310
1311 work->nodes[index].prev =
1312 (struct LzPackNode *)&work->bucket[work->bucketBySlot[index]];
1313 work->nodes[index].next = work->bucket[work->bucketBySlot[index]];
1314 work->bucket[work->bucketBySlot[index]] = &work->nodes[index];
1315 if (work->nodes[index].next != NULL)
1316 work->nodes[index].next->prev = &work->nodes[index];
1317}
1318
1319/// Removes window position slot from its chain.
1321 if (gFlash_Handler3->nodes[slot].prev != NULL) {
1322 if (gFlash_Handler3->nodes[slot].next != NULL)
1323 gFlash_Handler3->nodes[slot].next->prev =
1324 gFlash_Handler3->nodes[slot].prev;
1325 gFlash_Handler3->nodes[slot].prev->next = gFlash_Handler3->nodes[slot].next;
1326 }
1327}
1328
1329/// Reads count more input bytes into the window from position start, dropping
1330/// the bytes they replace from their chains; past the end of the input the
1331/// positions are marked empty (-1).
1332void LzPack_ConsumeSlotBytes(s32 start, s32 count, const u8 *input) {
1333 s32 limit = count;
1334 s32 current = 0;
1335 u32 base = start;
1336
1337 if (current < limit) {
1338 u32 mask = PACK_WINDOW_MASK;
1339 u32 removal = base + 0x124;
1340
1341 do {
1342 u32 slot = base + current;
1343 struct LzPackWork *state;
1344 u32 readOffset;
1345 u32 nextOffset;
1346 u8 value;
1347
1348 LzPack_RemoveSlotNode(removal & mask);
1349 state = gFlash_Handler3;
1350 readOffset = state->inputCursor;
1351 value = input[readOffset];
1352 nextOffset = readOffset + 1;
1353 state->inputCursor = nextOffset;
1354 if (nextOffset == state->inputLimit) {
1355 state->bucketBySlot[slot & mask] = -1;
1356 break;
1357 }
1358
1359 state->bucketBySlot[slot & mask] = value;
1360 current++;
1361 LzPack_InsertSlotNode(slot & mask);
1362 removal++;
1363 } while (current < limit);
1364 }
1365
1366 current++;
1367 if (current < limit) {
1368 u32 mask = PACK_WINDOW_MASK;
1369 struct LzPackWork **root = &gFlash_Handler3;
1370 s32 empty = -1;
1371
1372 do {
1373 u32 slot = (base + current) & mask;
1374 struct LzPackWork *state;
1375
1377 state = *root;
1378 current++;
1379 state->bucketBySlot[slot] = empty;
1380 } while (current < limit);
1381 }
1382}
1383
1384/// Appends the finished group (a flag byte and up to eight items) to the
1385/// output.
1386void LzPack_CopyBufferedBytes(u8 *destination) {
1387 struct LzPackWork *work = gFlash_Handler3;
1388 s32 index;
1389
1390 for (index = 0; index != work->outCnt; index++) {
1391 destination[work->outTotal] = work->outBuf[index];
1392 work->outTotal++;
1393 }
1394}
1395
1396/// Finds the longest earlier match (up to PACK_MATCH_MAX bytes, at most
1397/// PACK_DISTANCE_MAX back) for the bytes at window position start; matchLen
1398/// stays 1 for none.
1399static __inline__ void LzPack_FindWindowMatch(s32 start) {
1400 struct LzPackNode *node;
1401 s32 len;
1402
1403 gFlash_Handler3->matchLen = 1;
1404 if (gFlash_Handler3->bucketBySlot[start] == -1) {
1405 return;
1406 }
1407 node = gFlash_Handler3->bucket[gFlash_Handler3->bucketBySlot[start]];
1408 if (start + PACK_MATCH_MAX > PACK_WINDOW_MASK) {
1409 while (node != NULL) {
1410 s32 dist = (start - node->slot) & PACK_WINDOW_MASK;
1411
1412 if (dist > 0 && dist <= PACK_DISTANCE_MAX) {
1413 for (len = 1; len < PACK_MATCH_MAX; len++) {
1414 if (gFlash_Handler3->bucketBySlot[(start + len) & PACK_WINDOW_MASK] !=
1416 ->bucketBySlot[(node->slot + len) & PACK_WINDOW_MASK]) {
1417 break;
1418 }
1419 }
1420 if (gFlash_Handler3->matchLen < len) {
1421 gFlash_Handler3->matchOffset = dist;
1422 gFlash_Handler3->matchLen = len;
1423 if (len == PACK_MATCH_MAX) {
1424 return;
1425 }
1426 }
1427 }
1428 node = node->next;
1429 }
1430 } else {
1431 while (node != NULL) {
1432 s32 dist = (start - node->slot) & PACK_WINDOW_MASK;
1433
1434 if (dist > 0 && dist <= PACK_DISTANCE_MAX) {
1435 for (len = 1; len < PACK_MATCH_MAX; len++) {
1436 if (gFlash_Handler3->bucketBySlot[start + len] !=
1438 ->bucketBySlot[(node->slot + len) & PACK_WINDOW_MASK]) {
1439 break;
1440 }
1441 }
1442 if (gFlash_Handler3->matchLen < len) {
1443 gFlash_Handler3->matchOffset = dist;
1444 gFlash_Handler3->matchLen = len;
1445 if (len == PACK_MATCH_MAX) {
1446 return;
1447 }
1448 }
1449 }
1450 node = node->next;
1451 }
1452 }
1453}
1454
1455/// Packs size bytes of input into dst with a small LZ scheme and returns the
1456/// packed size. Each group starts with a flag byte, a set bit marking a match:
1457/// two bytes of distance and length (lengths 2 to 16), or three for lengths up
1458/// to 272; a match is put off by one byte when the next position matches
1459/// further. A zero match ends the stream. Nothing in this game calls it.
1460UNUSED s32 LzPack_PackStream(const u8 *input, u8 *dst, s32 size) {
1461 s32 defer;
1462 s32 len;
1463 s32 saveOffset;
1464 s32 saveLen;
1465 s32 reach[2];
1466 s16 code;
1467
1468 defer = 0;
1471 gFlash_Handler3->inputLimit = size;
1472 gFlash_Handler3->pos = 0;
1473 gFlash_Handler3->inputCursor = 0;
1474 gFlash_Handler3->outTotal = 0;
1475 gFlash_Handler3->flagMask = 0x80;
1476 gFlash_Handler3->outBuf[0] = 0;
1477 gFlash_Handler3->outCnt = 1;
1479
1480 while (gFlash_Handler3->bucketBySlot[gFlash_Handler3->pos] != -1) {
1482 if (defer == 0) {
1483 len = gFlash_Handler3->matchLen;
1484 if (gFlash_Handler3->matchLen > 1) {
1485 saveOffset = gFlash_Handler3->matchOffset;
1486 saveLen = len;
1488 if (gFlash_Handler3->matchLen > 2) {
1489 reach[0] = gFlash_Handler3->matchLen + 1;
1492 reach[1] = gFlash_Handler3->matchLen + len;
1493 if (reach[0] >= reach[1]) {
1494 saveLen = 1;
1495 defer = 1;
1496 }
1497 }
1498 gFlash_Handler3->matchOffset = saveOffset;
1499 gFlash_Handler3->matchLen = saveLen;
1500 }
1501 }
1502
1503 if (gFlash_Handler3->matchLen > 1) {
1504 defer = 0;
1505 gFlash_Handler3->outBuf[0] |= gFlash_Handler3->flagMask;
1506 if (gFlash_Handler3->matchLen <= 16) {
1507 code = ((gFlash_Handler3->matchOffset << 4) & ~0xfff) |
1508 (gFlash_Handler3->matchOffset & 0xff) |
1509 (((gFlash_Handler3->matchLen - 1) << 8) & 0xf00);
1510 gFlash_Handler3->outBuf[gFlash_Handler3->outCnt++] = (u16)code >> 8;
1511 gFlash_Handler3->outBuf[gFlash_Handler3->outCnt++] = code;
1512 } else {
1513 code = ((gFlash_Handler3->matchOffset << 4) & ~0xfff) |
1514 (gFlash_Handler3->matchOffset & 0xff);
1515 gFlash_Handler3->outBuf[gFlash_Handler3->outCnt++] = (u16)code >> 8;
1516 gFlash_Handler3->outBuf[gFlash_Handler3->outCnt++] = code;
1517 gFlash_Handler3->outBuf[gFlash_Handler3->outCnt++] =
1518 gFlash_Handler3->matchLen - 17;
1519 }
1520 } else {
1521 gFlash_Handler3->outBuf[gFlash_Handler3->outCnt++] =
1522 gFlash_Handler3->bucketBySlot[gFlash_Handler3->pos];
1523 gFlash_Handler3->matchLen = 1;
1524 }
1525
1527 gFlash_Handler3->matchLen, input);
1528 gFlash_Handler3->pos =
1530 gFlash_Handler3->flagMask >>= 1;
1531 if (gFlash_Handler3->flagMask == 0) {
1533 gFlash_Handler3->flagMask = 0x80;
1534 gFlash_Handler3->outBuf[0] = 0;
1535 gFlash_Handler3->outCnt = 1;
1536 }
1537 }
1538
1539 gFlash_Handler3->outBuf[0] |= gFlash_Handler3->flagMask;
1540 gFlash_Handler3->outBuf[gFlash_Handler3->outCnt++] = 0;
1541 gFlash_Handler3->outBuf[gFlash_Handler3->outCnt++] = 0;
1543 return gFlash_Handler3->outTotal;
1544}
The sound driver's command masks, cue controls and the routines and globals it shares with the engine...
void * gBattleFxWork[]
u32 gRandomSeed
The battle effect argument and the rectangle-drawing routines effects call.
BattleEffectDrawRectangle DrawRectangle
BattleEffectWork, the running battle effect's work, and its animation objects.
The task scheduler: tasks, their order and the scheduler's state.
void ReelGame_DrawCanvasLine(s32 x0, s32 y0, s32 x1, s32 y1, s32 color)
Draws a line from (x0, y0) to (x1, y1) on the 256 x 128 8bpp canvas (32 tiles across),...
Definition colorfx.c:217
#define REEL_HEAP_SLOT
The slot machine's own work block (struct ReelWork), beside the battle effect blocks it borrows.
Definition colorfx.c:49
#define REEL_CANVAS_TILES
Definition colorfx.c:54
s32 ReelGame_Start(void)
Plays the slot machine: blanks the screen, seeds the random numbers with the play time and runs the g...
Definition colorfx.c:58
static __inline__ void LzPack_FindWindowMatch(s32 start)
Finds the longest earlier match (up to PACK_MATCH_MAX bytes, at most PACK_DISTANCE_MAX back) for the ...
Definition colorfx.c:1399
void ReelGame_TransferCanvas(void)
A scheduler callback: on a frame whose canvas is ready (transferPending), sends the canvas to its til...
Definition colorfx.c:106
void Palette_StepTowardResource(s32 resource)
Moves the first 64 BG colours one step toward the palette of resource; the backdrop colour is not wri...
Definition colorfx.c:183
#define PACK_DISTANCE_MAX
Definition colorfx.c:1288
s32 Graphics_ScaleRgb555(u16 *src, u16 *dst, s32 scale, s32 count)
Writes count RGB555 colours from src to dst scaled by scale (16.16, 0x10000 keeps them).
Definition colorfx.c:68
void LzPack_CopyBufferedBytes(u8 *destination)
Appends the finished group (a flag byte and up to eight items) to the output.
Definition colorfx.c:1386
#define REEL_SPARKS
The sparks of the jackpot, kept in the map cell buffer.
Definition colorfx.c:45
void LzPack_ResetSlotBuckets(void)
The LZ packer below: empties its 256 hash chains (one per byte value) and numbers its 1024 window nod...
Definition colorfx.c:1293
ReelGameState
The slot machine's states (ReelWork.state).
Definition colorfx.c:301
@ REEL_NO_WIN
no payline won: A to choose holds
Definition colorfx.c:308
@ REEL_WON
a payline won: a pause
Definition colorfx.c:304
@ REEL_SHOWING_WIN
the win is shown until A
Definition colorfx.c:305
@ REEL_BETTING
Up and Down change the bet, A spins, B leaves.
Definition colorfx.c:302
@ REEL_CHOOSING_HOLDS
choose reels to hold, or pull the lever
Definition colorfx.c:306
@ REEL_OUT_OF_SPINS
the fourth spin lost: a pause, then the end
Definition colorfx.c:309
@ REEL_SPINNING
the reels spin until R or time stops each
Definition colorfx.c:303
@ REEL_DONE
the game ends
Definition colorfx.c:307
UNUSED s32 LzPack_PackStream(const u8 *input, u8 *dst, s32 size)
Packs size bytes of input into dst with a small LZ scheme and returns the packed size.
Definition colorfx.c:1460
#define PACK_WINDOW_MASK
Definition colorfx.c:1286
void LzPack_RemoveSlotNode(s32 slot)
Removes window position slot from its chain.
Definition colorfx.c:1320
#define REEL_CANVAS_SIZE
The paylines' canvas: 256 x 128 pixels of 8-bit colour, shown on BG2 from its tile 212,...
Definition colorfx.c:53
void LzPack_InsertSlotNode(s32 index)
Adds window position index to the chain of the byte it holds.
Definition colorfx.c:1308
void ReelGame_Run(void)
The slot machine: loads its backgrounds, sprites and palettes, fills each of the five reels with 21 r...
Definition colorfx.c:958
void ReelGame_InitTitle(void)
Sets up the bouncing title letters of a win, the brightness wave of the screen's lines and the bettin...
Definition colorfx.c:897
#define PACK_LOOKAHEAD
Definition colorfx.c:1289
#define PACK_MATCH_MAX
Definition colorfx.c:1287
void Palette_DarkenSceneStep(void)
Darkens the screen one step: lowers each channel of the 16 colours of BG palette 10 and of OBJ colour...
Definition colorfx.c:139
void LzPack_ConsumeSlotBytes(s32 start, s32 count, const u8 *input)
Reads count more input bytes into the window from position start, dropping the bytes they replace fro...
Definition colorfx.c:1332
void ReelGame_RunFrame(void)
The slot machine's frame callback: reads the keys, runs the game's state (betting,...
Definition colorfx.c:351
u16 gFlash_Handler3
Credits scroll position in pixels, in the low half of a flash work cell.
The engine calls the debug menus import, and their palette swatch tiles.
DMA channel registers, and the DMA and CPU fills.
static __inline__ void Dma_Set(const volatile void *source, volatile void *destination, u32 control, volatile u32 *channel)
Starts a DMA transfer: stores the source, destination and control words into channel's registers with...
Definition dma.h:62
EffectStep and EffectPosition, the positions effects move through.
s32 BattleEffect_LoadWorkFar(s32 slot, s32 width_shift, s32 height_shift, s32 flags, u32 mode)
Far call to BattleFx_BuildBlitter.
s32 PartyInventory_CountItemFar(s32 item_id)
s32 PartyInventory_RemoveFar(s32 item_id)
void AudioCommand_PlayFar(s32 id)
struct UiWindow * UiWindow_CreateFar(s32 x, s32 y, s32 width, s32 height, s32 attrs)
void UiText_DrawNumberInWindowFar(s32 arg0, s32 arg1, struct UiWindow *arg2, s32 arg3, s32 arg4)
void UiText_DrawCharacterAtOffsetFar(s32 character, const struct UiWindow *position, u32 offsetX, u32 offsetY)
void UiWork_FinalizeFar(struct UiWindow *work, s32 release)
void UiWork_InitializeWithResourceCountersFar(void)
16.16 fixed-point constants, sine and cosine, and the library division.
s32 Trig_Cos(s32 angle)
s32 Trig_Sin(s32 angle)
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
The frame loop's globals: lag counts, the CPU load display and the VBlank flags.
u8 gOamCopyEnabled
The VBlank handler copies the OAM list only while it is set; scenes clear it to keep their own sprite...
u8 gDebugPaused
The debug pause is on.
GameState, the game's state: play time, coins, the scene and the leader's position,...
struct GameState gGameState
struct EffectStep gMapCellBuffer[]
Map cells; battle effects reuse this as a particle array.
The screen blend's globals and the graphics routines.
void * Runtime_AllocateBlock(s32 kind, s32 size)
As Runtime_AllocateHeapBlock, but tries EWRAM first, for blocks that need room more than speed: the b...
Definition heap.c:80
void * Runtime_AllocateHeapBlock(s32 kind, s32 size)
Returns heap slot kind's block, first allocating size bytes for it (rounded up to words),...
Definition heap.c:47
The heap's work slots and HeapState.
@ HEAP_SLOT_BATTLE_EFFECT
Definition heap_state.h:42
@ HEAP_SLOT_BLITTER_ALTERNATE
Definition heap_state.h:47
@ HEAP_SLOT_BATTLE_SHEET
Definition heap_state.h:44
@ HEAP_SLOT_BLITTER
Definition heap_state.h:46
@ HEAP_SLOT_BATTLE_CANVAS
Definition heap_state.h:43
The hardware's I/O registers and their bits, as pret names them.
#define REG_WIN1H
Definition io_reg.h:75
#define WINOUT_WINOBJ_BG2
Definition io_reg.h:112
#define BGCNT_CHAR_BASE(block)
Definition io_reg.h:25
#define REG_WININ
Definition io_reg.h:81
#define OBJ_PLTT
Definition io_reg.h:159
#define BGCNT_256_COLORS
Definition io_reg.h:27
#define BGCNT_PRIORITY(n)
Definition io_reg.h:24
#define WININ_WIN0_BG1
Definition io_reg.h:87
#define BLDCNT_TGT1_OBJ
Definition io_reg.h:127
#define BG_SCREEN_BLOCK(n)
Definition io_reg.h:167
#define WININ_WIN0_CLR
Definition io_reg.h:91
#define WINOUT_WIN01_BG1
Definition io_reg.h:104
#define DMA_HBLANK_HALFWORD_PER_LINE
Definition io_reg.h:228
#define REG_BG1VOFS
Definition io_reg.h:50
#define RGB(r, g, b)
A 15-bit colour from its red, green and blue levels (0 to 31 each), as the palette stores it: blue in...
Definition io_reg.h:164
#define BLDCNT_TGT1_BG2
Definition io_reg.h:125
#define BG_CHAR_BLOCK(n)
Definition io_reg.h:166
#define OAM
Definition io_reg.h:239
#define BLDCNT_EFFECT_DARKEN
towards black by REG_BLDY
Definition io_reg.h:133
#define REG_DMA0
Definition io_reg.h:151
#define REG_WIN0H
Definition io_reg.h:74
#define DMA_START_TIMING_DRQ_REPEAT
A DMA control's start timing (bits 12 and 13), cartridge request (bit 11) and repeat (bit 9): the bit...
Definition io_reg.h:220
#define REG_BLDY
Definition io_reg.h:146
#define WININ_WIN1_BG0
Definition io_reg.h:93
#define OBJ_VRAM0
Sprite tile memory, as pret names it: the 32 KB from 0x06010000.
Definition io_reg.h:170
#define WININ_WIN1_CLR
Definition io_reg.h:98
#define REG_BG2HOFS
Definition io_reg.h:51
#define WININ_WIN0_BG0
Definition io_reg.h:86
@ DISPCNT_OBJ_ON
Definition io_reg.h:44
@ DISPCNT_WIN0_ON
Definition io_reg.h:45
@ DISPCNT_BG0_ON
Definition io_reg.h:40
@ DISPCNT_OBJ_1D_MAP
Definition io_reg.h:39
@ DISPCNT_BG2_ON
Definition io_reg.h:42
@ DISPCNT_BG1_ON
Definition io_reg.h:41
@ KEY_UP
Definition io_reg.h:249
@ KEY_B
Definition io_reg.h:244
@ KEYS_DPAD
Definition io_reg.h:255
@ KEY_LEFT
Definition io_reg.h:248
@ KEY_RIGHT
Definition io_reg.h:247
@ KEY_R
Definition io_reg.h:251
@ KEY_A
Definition io_reg.h:243
@ KEY_DOWN
Definition io_reg.h:250
#define DMA_32BIT
Definition io_reg.h:210
#define REG_DISPCNT
Definition io_reg.h:9
#define OBJ_PLTT_COLOR(palette, color)
Definition io_reg.h:160
#define BLDCNT_EFFECT_BLEND
weighted by REG_BLDALPHA
Definition io_reg.h:131
#define BLDCNT_TGT2_ALL
Definition io_reg.h:140
#define REG_DMA3
Definition io_reg.h:153
#define REG_BG1HOFS
Definition io_reg.h:49
#define WINOUT_WINOBJ_BG1
Definition io_reg.h:111
#define BLEND_ALPHA(top, bottom)
A REG_BLDALPHA value: top and bottom are the two targets' weights, out of 16.
Definition io_reg.h:145
#define WINOUT_WIN01_BG2
Definition io_reg.h:105
#define WININ_WIN0_OBJ
Definition io_reg.h:90
#define BGCNT_SCREEN_BASE(block)
Definition io_reg.h:28
#define WINOUT_WINOBJ_CLR
Definition io_reg.h:115
#define REG_BG2CNT
Definition io_reg.h:21
#define REG_BLDALPHA
Definition io_reg.h:142
#define REG_WINOUT
Definition io_reg.h:82
#define WIN_RANGE(start, end)
A REG_WINxH or REG_WINxV value: the window covers start up to, but not including, end.
Definition io_reg.h:80
#define WININ_WIN1_BG1
Definition io_reg.h:94
#define BG_PLTT
Definition io_reg.h:157
#define WINOUT_WIN01_BG0
Definition io_reg.h:103
#define REG_BG2VOFS
Definition io_reg.h:52
#define WININ_WIN1_OBJ
Definition io_reg.h:97
#define WINOUT_WIN01_CLR
Definition io_reg.h:108
#define WINOUT_WINOBJ_BG0
Definition io_reg.h:110
#define REG_BLDCNT
Definition io_reg.h:119
#define REG_BG1CNT
Definition io_reg.h:20
#define BG_PLTT_COLOR(palette, color)
Definition io_reg.h:158
#define DMA_ENABLE
Definition io_reg.h:217
#define REG_WIN1V
Definition io_reg.h:77
#define WININ_WIN1_BG2
Definition io_reg.h:95
#define WININ_WIN0_BG2
Definition io_reg.h:88
#define REG_WIN0V
Definition io_reg.h:76
Item numbers, named from the English release.
@ ITEM_GAME_TICKET
Definition item_ids.h:69
The IWRAM call layer: the routines the game keeps resident in IWRAM, each at its fixed address,...
static s32 Iwram_FillWords(void *destination, s32 size, u32 value)
Definition iwram_call.h:59
static s32 Iwram_ClearWords(void *destination, s32 size)
Definition iwram_call.h:55
The keypad state the VBlank interrupt keeps.
volatile u32 gKeysHeld
Keys down now.
The LZ packer's work: hash chains over a 1024-byte window, one chain per byte value,...
Small statement macros both games use for positions, velocities and bounds.
#define ABS(v)
The magnitude of v. v is read twice.
Definition macros.h:32
The map layers' scroll work and the background scroll values.
struct BgScroll gBgScroll[]
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
Definition math.c:10
The heaps: allocating and freeing blocks.
void Runtime_ReleaseHeapBlock(s32 slot)
The reel game's title lettering.
OamShadow, a sprite entry a routine builds by hand and DMA copies to OAM.
The work pointers in the gWorkSlot table, by name.
#define Ram_MapCellBuffer
Definition ram_buffer.h:10
The reel game's tables, the same in both games.
const u8 gReelGame_FrameSpriteX[]
The positions of the frame's sprites.
Definition reel_tables.h:27
const u8 gReelGame_TitleLetterTiles[REEL_TITLE_LETTERS]
The tile of each title letter.
Definition reel_tables.h:13
const u8 gReelGame_SymbolPrizes[]
The prize of each reel symbol.
Definition reel_tables.h:10
const u8 gReelGame_TitleLetterWidths[REEL_TITLE_LETTERS]
The advance of each title letter.
Definition reel_tables.h:33
const u8 gReelGame_FrameSpriteY[]
Definition reel_tables.h:29
const u16 gReelGame_SparkCellOffsets[]
Where each spark cell (a square 2 to 20 pixels on a side) starts.
Definition reel_tables.h:6
Resource numbers, named where their contents are known.
char ResourceId_LimePalette
char ResourceId_VenusDjinnSheet
char ResourceId_SlotsIcons
char ResourceId_EffectFarCalls
char ResourceId_ParticleSpritesD
char ResourceId_SlotsJackpot
char ResourceId_JupiterDjinnSheet
char ResourceId_SlotsFramePicture
char ResourceId_EmberStreakSheet
char ResourceId_MercuryDjinnSheet
s32 Resource_DecodeType01(const void *source, void *destination)
Decodes a type-01 resource and returns its unpacked byte count.
Definition decompress.c:31
void ColorBuffer_BackupAndHalveNonzero(u8 *buffer, u8 *backup, u32 bytes)
Halves every pixel, skipping all-zero groups.
Definition decompress.c:114
void ColorBuffer_BackupAndScaleNonzeroThreeQuarters(u8 *buffer, u8 *backup, u32 bytes)
Scales every pixel to three quarters, skipping all-zero groups.
Definition decompress.c:103
s32 Scheduler_AddOrUpdateCallback(SchedulerCallback callback, s32 order)
Schedules callback with order, or gives a task already running it the new order, and re-sorts the tab...
Definition scheduler.c:102
void Scheduler_ResetTaskTable(void)
Empties the task table: every slot gets no routine, order 0xffff (sorted last) and no flags.
Definition scheduler.c:19
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
Definition scheduler.c:146
Song and sound effect ids, indices into gSound_SongTable.
#define SE_MENU_CANCEL
Definition songs.h:106
#define SE_MENU_CURSOR_MOVE
Definition songs.h:104
#define SE_307
Definition songs.h:295
#define SE_306
Definition songs.h:294
#define SE_171
Definition songs.h:166
#define SE_304
Definition songs.h:292
#define MUS_093
Definition songs.h:91
#define SE_MENU_CONFIRM
Definition songs.h:105
#define SE_305
Definition songs.h:293
#define MUS_009
Definition songs.h:19
#define NULL
Definition bilibin.h:6
void * gWorkSlot[]
The running battle effect's work: its canvas image, 64 particles, the display registers it stages and...
s32 frame
frame counter some effects keep, from 0
s32 framesSinceTransfer
1 on a canvas copy's frame, then counts up
s32 transferPending
1 once the effect has drawn a frame (EFFECT_PRESENT_FRAME); the canvas transfer callback copies the c...
s32 transferMode
How the canvas transfer callbacks treat the canvas after each copy (enum CanvasTransferMode in effect...
s32 transferValue
The transfer mode's argument: the fill value, the share kept (50 or 75 percent) or the darken or brig...
struct EffectStep particles[64]
free while variant is -1
u16 y
pixels
Definition map_scroll.h:65
A moving point of an effect: its position, its velocity and a value each effect uses its own way (a s...
Definition effect_step.h:13
s32 velocityX
16.16 fixed-point pixels per frame
Definition effect_step.h:28
s32 variant
each effect's own: a size, a countdown, -1 for idle
Definition effect_step.h:31
s32 x
16.16 fixed-point pixels
Definition effect_step.h:24
s32 y
16.16 fixed-point pixels
Definition effect_step.h:25
s32 velocityY
16.16 fixed-point pixels per frame
Definition effect_step.h:29
u32 playTime
frames, copied from gPlayTimeFrames when saving
Definition game_state.h:18
A position of the LZ packer's window in the chain of the byte value it holds.
Definition lzpack.h:16
s32 slot
Definition lzpack.h:19
struct LzPackNode * prev
Previous node, or the bucket field at the head.
Definition lzpack.h:18
struct LzPackNode * next
Next node with the same value.
Definition lzpack.h:17
The LZ packer's work: a node per window position, a chain head per byte value, the byte at each posit...
Definition lzpack.h:24
u8 outBuf[0x24]
Definition lzpack.h:30
s32 outCnt
Definition lzpack.h:29
s32 outTotal
Definition lzpack.h:35
s32 bucketBySlot[0x400]
Definition lzpack.h:28
struct LzPackNode * bucket[0x100]
Definition lzpack.h:26
u32 inputCursor
Definition lzpack.h:34
u32 inputLimit
Definition lzpack.h:36
struct LzPackNode nodes[0x400]
Definition lzpack.h:25
OAM buffer: sprite entries a routine builds by hand and DMA copies to OAM.
Definition oambuf.h:18
volatile u32 attr2
attr2 | affine value << 16
Definition oambuf.h:20
volatile u32 attr01
attr0 | attr1 << 16
Definition oambuf.h:19
gGameState seen from +12, the base the bytes load: wonPrizes is gGameState.wonPrizes (through the fie...
Definition colorfx.c:339
s8 wonPrizes[16]
Definition colorfx.c:341
u8 unk000[0x120]
Definition colorfx.c:340
The slot machine's work in heap slot 45: its reels, state, bet and spins, keys, timer,...
Definition colorfx.c:314
struct Reel reels[5]
Definition colorfx.c:315
s32 bet
Definition colorfx.c:319
u16 keys
Definition colorfx.c:320
u8 unk0a4[4]
Definition colorfx.c:324
u16 direction
Definition colorfx.c:321
u16 scanlineOffsets[160]
Definition colorfx.c:331
u16 repeat
Definition colorfx.c:323
struct UiWindow * subWindow
Definition colorfx.c:329
s32 timer
Definition colorfx.c:325
struct UiWindow * window
Definition colorfx.c:328
s32 winningLines[7]
Definition colorfx.c:326
s32 phase
Definition colorfx.c:333
s32 state
Definition colorfx.c:316
s32 spins
Definition colorfx.c:318
u8 unk4d0[8]
Definition colorfx.c:330
s32 cursor
Definition colorfx.c:317
struct OamShadow obj[128]
Definition colorfx.c:327
u16 pressed
Definition colorfx.c:322
One of the slot machine's five reels: how far it has turned, its 21 symbols, whether it is held,...
Definition colorfx.c:291
u8 symbols[21]
Definition colorfx.c:293
s8 stop
frames
Definition colorfx.c:295
s32 position
pixels, 16 a symbol
Definition colorfx.c:292
u8 held
Definition colorfx.c:294
A window: a framed rectangle of the tilemap with its sprite outputs, its opening or closing animation...
Definition uiwindow.h:11
u16 frame
The zoom's step: counts down from 7 to 0 while opening, and up from 0 to duration while closing.
Definition uiwindow.h:28
u16 y
tiles
Definition uiwindow.h:16
u16 state
0 while a message channel is typing into the window; 1 once its text has ended or closed the window,...
Definition uiwindow.h:24
u16 x
tiles
Definition uiwindow.h:15
void * Resource_GetTableEntry(s32 index)
Returns the ROM address of resource index from the resource directory.
Definition system.c:150
void RuntimeDispatch_NoOpHook(s32 unused)
An exported stub that does nothing with its argument.
Definition system.c:146
The system's routines and globals: interrupts, BIOS sound bias, random numbers and sleep.
Values that differ by patch level or language, chosen once for their code.
#define REEL_COIN_X
#define REEL_START_X
#define REEL_HELP_WINDOW_WIDTH
#define REEL_STOP_WIDTH
#define REEL_JACKPOT_COPY
#define REEL_TITLE_X
#define REEL_HELP_WINDOW_X
#define REEL_RELEASE_WIDTH
#define REEL_HOLD_WIDTH
#define REEL_STOP_X
#define REEL_JACKPOT_TILES
#define REEL_TITLE_TILES
#define REEL_ALL_HELD_X
#define REEL_ALL_HELD_WIDTH
#define REEL_HOLD_X
#define REEL_COIN_DIGITS
#define REEL_TITLE_LETTERS
#define REEL_RELEASE_X
#define REEL_START_WIDTH
The integer types, TRUE, UNUSED and the fixed-address macros.
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed char s8
Definition types.h:10
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11