ref: 354fefaefbba77a3408fa9edb5cc4393b9c702ab
dir: /engine/games/unown_puzzle.asm/
DEF PUZZLE_BORDER EQU $ee DEF PUZZLE_VOID EQU $ef DEF puzcoord EQUS "* 6 +" _UnownPuzzle: ldh a, [hInMenu] push af ld a, $1 ldh [hInMenu], a call ClearBGPalettes call ClearTilemap call ClearSprites xor a ldh [hBGMapMode], a call DisableLCD ld hl, STARTOF("Miscellaneous") ; includes wPuzzlePieces ld bc, SIZEOF("Miscellaneous") xor a call ByteFill ld hl, UnownPuzzleCursorGFX ld de, vTiles0 tile $e0 ld bc, 4 tiles call CopyBytes ld hl, UnownPuzzleStartCancelLZ ld de, vTiles0 tile $ed call Decompress call LoadUnownPuzzlePiecesGFX hlcoord 0, 0 ld bc, SCREEN_WIDTH * SCREEN_HEIGHT ld a, PUZZLE_BORDER call ByteFill hlcoord 4, 3 lb bc, 12, 12 ld a, PUZZLE_VOID call UnownPuzzle_FillBox call InitUnownPuzzlePiecePositions call UnownPuzzle_UpdateTilemap call PlaceStartCancelBox xor a ldh [hSCY], a ldh [hSCX], a ldh [rWY], a ld [wJumptableIndex], a ld [wHoldingUnownPuzzlePiece], a ld [wUnownPuzzleCursorPosition], a ld [wUnownPuzzleHeldPiece], a ld a, %10010011 ldh [rLCDC], a call WaitBGMap ld b, SCGB_UNOWN_PUZZLE call GetSGBLayout ld a, $e4 call DmgToCgbBGPals ld a, $24 call DmgToCgbObjPal0 xor a ld [wSolvedUnownPuzzle], a call DelayFrame .loop call JoyTextDelay ld a, [wJumptableIndex] bit 7, a jr nz, .quit call UnownPuzzleJumptable ld a, [wHoldingUnownPuzzlePiece] and a jr nz, .holding_piece ldh a, [hVBlankCounter] and $10 jr z, .clear .holding_piece call RedrawUnownPuzzlePieces jr .next .clear call ClearSprites .next call DelayFrame jr .loop .quit pop af ldh [hInMenu], a call ClearBGPalettes call ClearTilemap call ClearSprites ld a, LCDC_DEFAULT ldh [rLCDC], a ret InitUnownPuzzlePiecePositions: ld c, 1 ld b, 16 .load_loop call Random and $f ld hl, .PuzzlePieceInitialPositions ld e, a ld d, 0 add hl, de ld e, [hl] ld hl, wPuzzlePieces add hl, de ld a, [hl] and a jr nz, .load_loop ld [hl], c inc c dec b jr nz, .load_loop ret .PuzzlePieceInitialPositions: MACRO initpuzcoord rept _NARG / 2 db \1 puzcoord \2 shift 2 endr ENDM initpuzcoord 0,0, 0,1, 0,2, 0,3, 0,4, 0,5 initpuzcoord 1,0, 1,5 initpuzcoord 2,0, 2,5 initpuzcoord 3,0, 3,5 initpuzcoord 4,0, 4,5 initpuzcoord 5,0, 5,5 ; START > CANCEL PlaceStartCancelBox: call PlaceStartCancelBoxBorder hlcoord 5, 16 ld a, $f6 ld c, 10 .loop ld [hli], a inc a dec c jr nz, .loop ret PlaceStartCancelBoxBorder: hlcoord 4, 15 ld a, $f0 ld [hli], a ld bc, 10 ld a, $f1 call ByteFill hlcoord 15, 15 ld a, $f2 ld [hli], a hlcoord 4, 16 ld a, $f3 ld [hli], a ld bc, 10 ld a, PUZZLE_VOID call ByteFill hlcoord 15, 16 ld a, $f3 ld [hli], a hlcoord 4, 17 ld a, $f4 ld [hli], a ld bc, 10 ld a, $f1 call ByteFill hlcoord 15, 17 ld a, $f5 ld [hl], a ret UnownPuzzleJumptable: jumptable .Jumptable, wJumptableIndex .Jumptable: ; redundant one-entry jumptable dw .Function .Function: ldh a, [hJoyPressed] and START jp nz, UnownPuzzle_Quit ldh a, [hJoyPressed] and A_BUTTON jp nz, UnownPuzzle_A ld hl, hJoyLast ld a, [hl] and D_UP jr nz, .d_up ld a, [hl] and D_DOWN jr nz, .d_down ld a, [hl] and D_LEFT jr nz, .d_left ld a, [hl] and D_RIGHT jr nz, .d_right ret .d_up ld hl, wUnownPuzzleCursorPosition ld a, [hl] cp 1 puzcoord 0 ret c sub 6 ld [hl], a jr .done_joypad .d_down ld hl, wUnownPuzzleCursorPosition ld a, [hl] cp 4 puzcoord 1 ret z cp 4 puzcoord 2 ret z cp 4 puzcoord 3 ret z cp 4 puzcoord 4 ret z cp 5 puzcoord 0 ret nc add 6 ld [hl], a jr .done_joypad .d_left ld hl, wUnownPuzzleCursorPosition ld a, [hl] and a ret z cp 1 puzcoord 0 ret z cp 2 puzcoord 0 ret z cp 3 puzcoord 0 ret z cp 4 puzcoord 0 ret z cp 5 puzcoord 0 ret z cp 5 puzcoord 5 jr z, .left_overflow dec [hl] jr .done_joypad .left_overflow ld [hl], 5 puzcoord 0 jr .done_joypad .d_right ld hl, wUnownPuzzleCursorPosition ld a, [hl] cp 0 puzcoord 5 ret z cp 1 puzcoord 5 ret z cp 2 puzcoord 5 ret z cp 3 puzcoord 5 ret z cp 4 puzcoord 5 ret z cp 5 puzcoord 5 ret z cp 5 puzcoord 0 jr z, .right_overflow inc [hl] jr .done_joypad .right_overflow ld [hl], 5 puzcoord 5 .done_joypad ld a, [wHoldingUnownPuzzlePiece] and a jr nz, .holding_piece ld de, SFX_POUND jr .play_sfx .holding_piece ld de, SFX_MOVE_PUZZLE_PIECE .play_sfx call PlaySFX ret UnownPuzzle_A: ld a, [wHoldingUnownPuzzlePiece] and a jr nz, .TryPlacePiece call UnownPuzzle_CheckCurrentTileOccupancy and a jr z, UnownPuzzle_InvalidAction ld de, SFX_MEGA_KICK call PlaySFX ld [hl], 0 ld [wUnownPuzzleHeldPiece], a call RedrawUnownPuzzlePieces call FillUnoccupiedPuzzleSpace call WaitBGMap call WaitSFX ld a, TRUE ld [wHoldingUnownPuzzlePiece], a ret .TryPlacePiece: call UnownPuzzle_CheckCurrentTileOccupancy and a jr nz, UnownPuzzle_InvalidAction ld de, SFX_PLACE_PUZZLE_PIECE_DOWN call PlaySFX ld a, [wUnownPuzzleHeldPiece] ld [hl], a call PlaceUnownPuzzlePieceGFX call WaitBGMap xor a ld [wUnownPuzzleHeldPiece], a call RedrawUnownPuzzlePieces xor a ld [wHoldingUnownPuzzlePiece], a call WaitSFX call CheckSolvedUnownPuzzle ret nc ; You solved the puzzle! call PlaceStartCancelBoxBorder call ClearSprites ld de, SFX_1ST_PLACE call PlaySFX call WaitSFX call SimpleWaitPressAorB ld a, TRUE ld [wSolvedUnownPuzzle], a UnownPuzzle_Quit: ld hl, wJumptableIndex set 7, [hl] ret UnownPuzzle_InvalidAction: ld de, SFX_WRONG call PlaySFX call WaitSFX ret UnownPuzzle_FillBox: ld de, SCREEN_WIDTH .row push bc push hl .col ld [hli], a dec c jr nz, .col pop hl add hl, de pop bc dec b jr nz, .row ret UnownPuzzle_UpdateTilemap: xor a ld [wUnownPuzzleCursorPosition], a ld c, 6 * 6 .loop push bc call UnownPuzzle_CheckCurrentTileOccupancy ld [wUnownPuzzleHeldPiece], a and a jr z, .not_holding_piece call PlaceUnownPuzzlePieceGFX jr .next .not_holding_piece call FillUnoccupiedPuzzleSpace .next ld hl, wUnownPuzzleCursorPosition inc [hl] pop bc dec c jr nz, .loop ret PlaceUnownPuzzlePieceGFX: ld a, $2 ; tilemap coords call GetUnownPuzzleCoordData ld a, [hli] ld h, [hl] ld l, a push hl call GetCurrentPuzzlePieceVTileCorner pop hl ld de, SCREEN_WIDTH ld b, 3 .row ld c, 3 push hl .col ld [hli], a inc a dec c jr nz, .col add 9 pop hl add hl, de dec b jr nz, .row ret FillUnoccupiedPuzzleSpace: ld a, 2 ; tilemap coords call GetUnownPuzzleCoordData ld a, [hli] ld h, [hl] ld l, a push hl ld a, 4 ; tile call GetUnownPuzzleCoordData ld a, [hl] pop hl ld de, SCREEN_WIDTH ld b, 3 .row ld c, 3 push hl .col ld [hli], a dec c jr nz, .col pop hl add hl, de dec b jr nz, .row ret GetUnownPuzzleCoordData: ld e, a ld d, 0 ld hl, UnownPuzzleCoordData add hl, de ld a, [wUnownPuzzleCursorPosition] ld e, a rept 6 add hl, de endr ret UnownPuzzle_CheckCurrentTileOccupancy: ld hl, wPuzzlePieces ld a, [wUnownPuzzleCursorPosition] ld e, a ld d, 0 add hl, de ld a, [hl] ret GetCurrentPuzzlePieceVTileCorner: ld a, [wUnownPuzzleHeldPiece] ld hl, .Corners add l ld l, a ld a, $0 adc h ld h, a ld a, [hl] ret .Corners: ; 00, 01, 02 ; 0c, 0d, 0e ; 18, 19, 1a db $e0 ; no piece selected db $00, $03, $06, $09 db $24, $27, $2a, $2d db $48, $4b, $4e, $51 db $6c, $6f, $72, $75 CheckSolvedUnownPuzzle: ld hl, .SolvedPuzzleConfiguration ld de, wPuzzlePieces ld c, 6 * 6 .loop ld a, [de] cp [hl] jr nz, .not_solved inc de inc hl dec c jr nz, .loop scf ret .not_solved and a ret .SolvedPuzzleConfiguration: db $00, $00, $00, $00, $00, $00 db $00, $01, $02, $03, $04, $00 db $00, $05, $06, $07, $08, $00 db $00, $09, $0a, $0b, $0c, $00 db $00, $0d, $0e, $0f, $10, $00 db $00, $00, $00, $00, $00, $00 RedrawUnownPuzzlePieces: call GetCurrentPuzzlePieceVTileCorner ld [wUnownPuzzleCornerTile], a xor a call GetUnownPuzzleCoordData ; get pixel positions ld a, [hli] ld b, [hl] ld c, a ld a, [wUnownPuzzleCornerTile] cp $e0 jr z, .NoPiece ld hl, .OAM_HoldingPiece jr .load .NoPiece: ld hl, .OAM_NotHoldingPiece .load ld de, wShadowOAMSprite00 .loop ld a, [hli] cp -1 ret z add b ld [de], a ; y inc de ld a, [hli] add c ld [de], a ; x inc de ld a, [wUnownPuzzleCornerTile] add [hl] ld [de], a ; tile id inc hl inc de ld a, [hli] ld [de], a ; attributes inc de jr .loop .OAM_HoldingPiece: dbsprite -1, -1, -4, -4, $00, 0 dbsprite 0, -1, -4, -4, $01, 0 dbsprite 0, -1, 4, -4, $02, 0 dbsprite -1, 0, -4, -4, $0c, 0 dbsprite 0, 0, -4, -4, $0d, 0 dbsprite 0, 0, 4, -4, $0e, 0 dbsprite -1, 0, -4, 4, $18, 0 dbsprite 0, 0, -4, 4, $19, 0 dbsprite 0, 0, 4, 4, $1a, 0 db -1 .OAM_NotHoldingPiece: dbsprite -1, -1, -4, -4, $00, 0 dbsprite 0, -1, -4, -4, $01, 0 dbsprite 0, -1, 4, -4, $00, 0 | X_FLIP dbsprite -1, 0, -4, -4, $02, 0 dbsprite 0, 0, -4, -4, $03, 0 dbsprite 0, 0, 4, -4, $02, 0 | X_FLIP dbsprite -1, 0, -4, 4, $00, 0 | Y_FLIP dbsprite 0, 0, -4, 4, $01, 0 | Y_FLIP dbsprite 0, 0, 4, 4, $00, 0 | X_FLIP | Y_FLIP db -1 UnownPuzzleCoordData: MACRO puzzle_coords dbpixel \1, \2, \3, \4 dwcoord \5, \6 db \7, \8 ENDM ; OAM coords, tilemap coords, vacant tile, filler puzzle_coords 3, 3, 4, 4, 1, 0, PUZZLE_BORDER, 0 puzzle_coords 6, 3, 4, 4, 4, 0, PUZZLE_BORDER, 0 puzzle_coords 9, 3, 4, 4, 7, 0, PUZZLE_BORDER, 0 puzzle_coords 12, 3, 4, 4, 10, 0, PUZZLE_BORDER, 0 puzzle_coords 15, 3, 4, 4, 13, 0, PUZZLE_BORDER, 0 puzzle_coords 18, 3, 4, 4, 16, 0, PUZZLE_BORDER, 0 puzzle_coords 3, 6, 4, 4, 1, 3, PUZZLE_BORDER, 0 puzzle_coords 6, 6, 4, 4, 4, 3, PUZZLE_VOID, 0 puzzle_coords 9, 6, 4, 4, 7, 3, PUZZLE_VOID, 0 puzzle_coords 12, 6, 4, 4, 10, 3, PUZZLE_VOID, 0 puzzle_coords 15, 6, 4, 4, 13, 3, PUZZLE_VOID, 0 puzzle_coords 18, 6, 4, 4, 16, 3, PUZZLE_BORDER, 0 puzzle_coords 3, 9, 4, 4, 1, 6, PUZZLE_BORDER, 0 puzzle_coords 6, 9, 4, 4, 4, 6, PUZZLE_VOID, 0 puzzle_coords 9, 9, 4, 4, 7, 6, PUZZLE_VOID, 0 puzzle_coords 12, 9, 4, 4, 10, 6, PUZZLE_VOID, 0 puzzle_coords 15, 9, 4, 4, 13, 6, PUZZLE_VOID, 0 puzzle_coords 18, 9, 4, 4, 16, 6, PUZZLE_BORDER, 0 puzzle_coords 3, 12, 4, 4, 1, 9, PUZZLE_BORDER, 0 puzzle_coords 6, 12, 4, 4, 4, 9, PUZZLE_VOID, 0 puzzle_coords 9, 12, 4, 4, 7, 9, PUZZLE_VOID, 0 puzzle_coords 12, 12, 4, 4, 10, 9, PUZZLE_VOID, 0 puzzle_coords 15, 12, 4, 4, 13, 9, PUZZLE_VOID, 0 puzzle_coords 18, 12, 4, 4, 16, 9, PUZZLE_BORDER, 0 puzzle_coords 3, 15, 4, 4, 1, 12, PUZZLE_BORDER, 0 puzzle_coords 6, 15, 4, 4, 4, 12, PUZZLE_VOID, 0 puzzle_coords 9, 15, 4, 4, 7, 12, PUZZLE_VOID, 0 puzzle_coords 12, 15, 4, 4, 10, 12, PUZZLE_VOID, 0 puzzle_coords 15, 15, 4, 4, 13, 12, PUZZLE_VOID, 0 puzzle_coords 18, 15, 4, 4, 16, 12, PUZZLE_BORDER, 0 puzzle_coords 3, 18, 4, 4, 1, 15, PUZZLE_BORDER, 0 puzzle_coords 6, 18, 4, 4, 4, 15, PUZZLE_BORDER, 0 puzzle_coords 9, 18, 4, 4, 7, 15, PUZZLE_BORDER, 0 puzzle_coords 12, 18, 4, 4, 10, 15, PUZZLE_BORDER, 0 puzzle_coords 15, 18, 4, 4, 13, 15, PUZZLE_BORDER, 0 puzzle_coords 18, 18, 4, 4, 16, 15, PUZZLE_BORDER, 0 ConvertLoadedPuzzlePieces: ld hl, vTiles2 ld de, vTiles0 ld b, 6 .loop push bc push hl push hl call .EnlargePuzzlePieceTiles pop hl ld bc, 1 tiles / 2 add hl, bc call .EnlargePuzzlePieceTiles pop hl ld bc, 6 tiles add hl, bc pop bc dec b jr nz, .loop call UnownPuzzle_AddPuzzlePieceBorders ret .EnlargePuzzlePieceTiles: ; double size ld c, 6 .loop1 push bc push hl push hl ld c, 4 .loop2 push bc ld a, [hli] and $f0 swap a call .GetEnlargedTile ld c, a ld a, [hli] and $f0 swap a call .GetEnlargedTile ld b, a ld a, c ld [de], a inc de ld a, b ld [de], a inc de ld a, c ld [de], a inc de ld a, b ld [de], a inc de pop bc dec c jr nz, .loop2 pop hl ld c, 4 .loop3 push bc ld a, [hli] and $f call .GetEnlargedTile ld c, a ld a, [hli] and $f call .GetEnlargedTile ld b, a ld a, c ld [de], a inc de ld a, b ld [de], a inc de ld a, c ld [de], a inc de ld a, b ld [de], a inc de pop bc dec c jr nz, .loop3 pop hl ld bc, 1 tiles add hl, bc pop bc dec c jr nz, .loop1 ret .GetEnlargedTile: push hl ld hl, .EnlargedTiles add l ld l, a ld a, 0 adc h ld h, a ld a, [hl] pop hl ret .EnlargedTiles: for x, 16 db ((x & %1000) * %11000) + ((x & %0100) * %1100) + ((x & %0010) * %110) + ((x & %0001) * %11) endr UnownPuzzle_AddPuzzlePieceBorders: ld hl, PuzzlePieceBorderData ld a, 8 .loop push af push hl ld a, [hli] ld e, a ld a, [hli] ld d, a ld a, [hli] ld h, [hl] ld l, a call .LoadGFX pop hl rept 4 inc hl endr pop af dec a jr nz, .loop ret .LoadGFX: lb bc, 4, 4 .loop1 push bc .loop2 push de push hl ld b, 1 tiles .loop3 ld a, [de] or [hl] ld [hli], a inc de dec b jr nz, .loop3 pop hl ld de, 3 tiles add hl, de pop de dec c jr nz, .loop2 ld bc, 24 tiles add hl, bc pop bc dec b jr nz, .loop1 ret PuzzlePieceBorderData: dw .TileBordersGFX + 0 tiles, vTiles0 tile $00 dw .TileBordersGFX + 1 tiles, vTiles0 tile $01 dw .TileBordersGFX + 2 tiles, vTiles0 tile $02 dw .TileBordersGFX + 3 tiles, vTiles0 tile $0c dw .TileBordersGFX + 4 tiles, vTiles0 tile $0e dw .TileBordersGFX + 5 tiles, vTiles0 tile $18 dw .TileBordersGFX + 6 tiles, vTiles0 tile $19 dw .TileBordersGFX + 7 tiles, vTiles0 tile $1a .TileBordersGFX: INCBIN "gfx/unown_puzzle/tile_borders.2bpp" LoadUnownPuzzlePiecesGFX: ld a, [wScriptVar] maskbits NUM_UNOWN_PUZZLES ld e, a ld d, 0 ld hl, .LZPointers add hl, de add hl, de ld a, [hli] ld h, [hl] ld l, a ld de, vTiles2 call Decompress call ConvertLoadedPuzzlePieces ret .LZPointers: ; entries correspond to UNOWNPUZZLE_* constants dw KabutoPuzzleLZ dw OmanytePuzzleLZ dw AerodactylPuzzleLZ dw HoOhPuzzleLZ UnownPuzzleCursorGFX: INCBIN "gfx/unown_puzzle/cursor.2bpp" UnownPuzzleStartCancelLZ: INCBIN "gfx/unown_puzzle/start_cancel.2bpp.lz" HoOhPuzzleLZ: INCBIN "gfx/unown_puzzle/hooh.2bpp.lz" AerodactylPuzzleLZ: INCBIN "gfx/unown_puzzle/aerodactyl.2bpp.lz" KabutoPuzzleLZ: INCBIN "gfx/unown_puzzle/kabuto.2bpp.lz" OmanytePuzzleLZ: INCBIN "gfx/unown_puzzle/omanyte.2bpp.lz"