diff options
Diffstat (limited to 'engine/gfx')
-rwxr-xr-x | engine/gfx/hp_bar.asm | 8 | ||||
-rwxr-xr-x | engine/gfx/mon_icons.asm | 20 | ||||
-rwxr-xr-x | engine/gfx/palettes.asm | 579 | ||||
-rw-r--r--[-rwxr-xr-x] | engine/gfx/screen_effects.asm | 10 | ||||
-rw-r--r-- | engine/gfx/sprite_oam.asm | 163 |
5 files changed, 655 insertions, 125 deletions
diff --git a/engine/gfx/hp_bar.asm b/engine/gfx/hp_bar.asm index b7bd97f2..b47b1fbd 100755 --- a/engine/gfx/hp_bar.asm +++ b/engine/gfx/hp_bar.asm @@ -213,13 +213,11 @@ UpdateHPBar_PrintHPNumber: ld a, [wHPBarOldHP + 1] ld [wHPBarTempHP], a push hl - ldh a, [hFlagsFFF6] + ld de, $15 + ldh a, [hFlagsFFFA] bit 0, a - jr z, .asm_fb15 + jr z, .next ld de, $9 - jr .next -.asm_fb15 - ld de, $15 .next add hl, de push hl diff --git a/engine/gfx/mon_icons.asm b/engine/gfx/mon_icons.asm index 16409640..6e2cf0ba 100755 --- a/engine/gfx/mon_icons.asm +++ b/engine/gfx/mon_icons.asm @@ -91,7 +91,7 @@ PartyMonSpeeds: LoadMonPartySpriteGfx: ; Load mon party sprite tile patterns into VRAM during V-blank. ld hl, MonPartySpritePointers - ld a, $1c + ld a, $1e LoadAnimSpriteGfx: ; Load animated sprite tile patterns into VRAM during V-blank. hl is the address @@ -130,7 +130,7 @@ LoadMonPartySpriteGfxWithLCDDisabled: ; LCD. call DisableLCD ld hl, MonPartySpritePointers - ld a, $1c + ld a, $1e ld bc, $0 .loop push af @@ -151,7 +151,7 @@ LoadMonPartySpriteGfxWithLCDDisabled: inc hl ld d, [hl] pop hl - call FarCopyData2 + call FarCopyData pop hl pop bc ld a, $6 @@ -170,6 +170,8 @@ WriteMonPartySpriteOAMByPartyIndex: push de push bc ldh a, [hPartyMonIndex] + cp $ff + jr z, .asm_7191f ld hl, wPartySpecies ld e, a ld d, 0 @@ -183,6 +185,16 @@ WriteMonPartySpriteOAMByPartyIndex: pop hl ret +.asm_7191f + ld hl, wOAMBuffer + ld de, wMonPartySpritesSavedOAM + ld bc, $60 + call CopyData + pop bc + pop de + pop hl + ret + WriteMonPartySpriteOAMBySpecies: ; Write OAM blocks for the party sprite of the species in ; [wMonPartySpriteSpecies]. @@ -204,7 +216,7 @@ UnusedPartyMonSpriteFunction: ld hl, vSprites tile $00 call .LoadTilePatterns pop af - add $54 + add $5A ld hl, vSprites tile $04 call .LoadTilePatterns xor a diff --git a/engine/gfx/palettes.asm b/engine/gfx/palettes.asm index f25ff215..dd723afa 100755 --- a/engine/gfx/palettes.asm +++ b/engine/gfx/palettes.asm @@ -19,7 +19,7 @@ _RunPaletteCommand: push de jp hl -SetPal_BattleBlack: +SetPal_Black: ld hl, PalPacket_Black ld de, BlkPacket_Battle ret @@ -30,11 +30,19 @@ SetPal_Battle: ld de, wPalPacket ld bc, $10 call CopyData - ld a, [wPlayerBattleStatus3] + ;ld a, [wPlayerBattleStatus3] ld hl, wBattleMonSpecies + ld a, [hl] + and a + jr z, .asm_71ef9 + ld hl, wPartyMon1 + ld a, [wPlayerMonNumber] + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes +.asm_71ef9 call DeterminePaletteID ld b, a - ld a, [wEnemyBattleStatus3] + ;ld a, [wEnemyBattleStatus3] ld hl, wEnemyMonSpecies2 call DeterminePaletteID ld c, a @@ -110,7 +118,7 @@ SetPal_Slots: ld de, BlkPacket_Slots ret -SetPal_TitleScreen: +SetPal_Titlescreen: ld hl, PalPacket_Titlescreen ld de, BlkPacket_Titlescreen ret @@ -155,6 +163,10 @@ SetPal_Overworld: jr z, .Lorelei cp BRUNOS_ROOM jr z, .caveOrBruno + cp TRADE_CENTER + jr z, .trade_center_colosseum + cp COLOSSEUM + jr z, .trade_center_colosseum .normalDungeonOrBuilding ld a, [wLastMap] ; town or route that current dungeon or building is located .townOrRoute @@ -178,6 +190,9 @@ SetPal_Overworld: .Lorelei xor a jr .town +.trade_center_colosseum + ld a, PAL_GREYMON - 1 + jr .town ; used when a Pokemon is the only thing on the screen ; such as evolution, trading and the Hall of Fame @@ -240,15 +255,25 @@ SetPal_TrainerCard: ld de, wTrainerCardBlkPacket ret +SendUnknownPalPacket_7205d:: + ld hl, UnknownPalPacket_72811 + ld de, BlkPacket_WholeScreen + ret + +SendUnknownPalPacket_72064:: + ld hl, UnknownPalPacket_72821 + ld de, UnknownPacket_72751 + ret + SetPalFunctions: ; entries correspond to SET_PAL_* constants - dw SetPal_BattleBlack + dw SetPal_Black dw SetPal_Battle dw SetPal_TownMap dw SetPal_StatusScreen dw SetPal_Pokedex dw SetPal_Slots - dw SetPal_TitleScreen + dw SetPal_Titlescreen dw SetPal_NidorinoIntro dw SetPal_Generic dw SetPal_Overworld @@ -256,6 +281,8 @@ SetPalFunctions: dw SetPal_PokemonWholeScreen dw SetPal_GameFreakIntro dw SetPal_TrainerCard + dw SendUnknownPalPacket_7205d + dw SendUnknownPalPacket_72064 ; The length of the blk data of each badge on the Trainer Card. ; The Rainbow Badge has 3 entries because of its many colors. @@ -270,9 +297,6 @@ BadgeBlkDataLengths: db 6 ; Earth Badge DeterminePaletteID: - bit TRANSFORMED, a ; a is battle status 3 - ld a, PAL_GREYMON ; if the mon has used Transform, use Ditto's palette - ret nz ld a, [hl] DeterminePaletteIDOutOfBattle: ld [wd11e], a @@ -290,6 +314,132 @@ DeterminePaletteIDOutOfBattle: ld a, [hl] ret +YellowIntroPaletteAction:: + ld a, e + and a + jr nz, .asm_720bd + ld hl, PalPacket_Generic + ldh a, [hGBC] + and a + jp z, SendSGBPacket + jp InitGBCPalettes + +.asm_720bd + ld hl, UnknownPalPacket_72811 + ldh a, [hGBC] + and a + jp z, SendSGBPacket + call InitGBCPalettes + ld hl, PalPacket_Generic + inc hl + ld a, [hli] + call GetGBCBasePalAddress + ld a, e + ld [wGBCBasePalPointers + 2], a + ld a, d + ld [wGBCBasePalPointers + 2 + 1], a + xor a ; CONVERT_BGP + call DMGPalToGBCPal + ld a, 1 + call TransferCurBGPData + ret + +LoadOverworldPikachuFrontpicPalettes:: + ld hl, PalPacket_Empty + ld de, wPalPacket + ld bc, $10 + call CopyData + call GetPal_Pikachu + ld hl, wPartyMenuBlkPacket + ld [hl], a + ld hl, wPartyMenuBlkPacket + 2 + ld a, $26 + ld [hl], a + ld hl, wPalPacket + ldh a, [hGBC] + and a + jr nz, .cgb_1 + call SendSGBPacket + jr .okay_1 + +.cgb_1 + call InitGBCPalettes +.okay_1 + ld hl, BlkPacket_WholeScreen + ld de, wPalPacket + ld bc, $10 + call CopyData + ld hl, wPartyMenuBlkPacket + 2 + ld a, $5 + ld [hli], a + ld a, $7 + ld [hli], a + ld a, $6 + ld [hli], a + ld a, $b + ld [hli], a + ld a, $a + ld [hl], a + ld hl, wPalPacket + ldh a, [hGBC] + and a + jr nz, .cgb_2 + call SendSGBPacket + jr .okay_2 + +.cgb_2 + call InitGBCPalettes +.okay_2 + ret + +GetPal_Pikachu:: +; similar to SetPal_Overworld + ld a, [wCurMapTileset] + cp CEMETERY + jr z, .PokemonTowerOrAgatha + cp CAVERN + jr z, .caveOrBruno + ld a, [wCurMap] + cp REDS_HOUSE_1F + jr c, .townOrRoute + cp CERULEAN_CAVE_2F + jr c, .normalDungeonOrBuilding + cp NAME_RATERS_HOUSE + jr c, .caveOrBruno + cp LORELEIS_ROOM + jr z, .Lorelei + cp BRUNOS_ROOM + jr z, .caveOrBruno + cp TRADE_CENTER + jr z, .battleOrTradeCenter + cp COLOSSEUM + jr z, .battleOrTradeCenter +.normalDungeonOrBuilding + ld a, [wLastMap] ; town or route that current dungeon or building is located +.townOrRoute + cp SAFFRON_CITY + 1 + jr c, .town + ld a, PAL_ROUTE - 1 +.town + inc a ; a town's pallete ID is its map ID + 1 + ret + +.PokemonTowerOrAgatha + ld a, PAL_GREYMON - 1 + jr .town + +.caveOrBruno + ld a, PAL_CAVE - 1 + jr .town + +.Lorelei + xor a ; PAL_PALLET - 1 + jr .town + +.battleOrTradeCenter + ld a, PAL_GREYMON - 1 + jr .town + InitPartyMenuBlkPacket: ld hl, BlkPacket_PartyMenu ld de, wPartyMenuBlkPacket @@ -325,6 +475,14 @@ UpdatePartyMenuBlkPacket: ret SendSGBPacket: + ld a, 1 + ldh [hDisableJoypadPolling], a ; don't poll joypad while sending packet + call _SendSGBPacket + xor a + ldh [hDisableJoypadPolling], a + ret + +_SendSGBPacket: ;check number of packets ld a, [hl] and $07 @@ -334,9 +492,6 @@ SendSGBPacket: .loop2 ; save B for later use push bc -; disable ReadJoypad to prevent it from interfering with sending the packet - ld a, 1 - ldh [hDisableJoypadPolling], a ; send RESET signal (P14=LOW, P15=LOW) xor a ldh [rJOYP], a @@ -353,10 +508,10 @@ SendSGBPacket: ld d, a .nextBit0 bit 0, d -; if 0th bit is not zero set P14=HIGH,P15=LOW (send bit 1) +; if 0th bit is not zero set P14=HIGH, P15=LOW (send bit 1) ld a, $10 jr nz, .next0 -; else (if 0th bit is zero) set P14=LOW,P15=HIGH (send bit 0) +; else (if 0th bit is zero) set P14=LOW, P15=HIGH (send bit 0) ld a, $20 .next0 ldh [rJOYP], a @@ -364,7 +519,7 @@ SendSGBPacket: ld a, $30 ldh [rJOYP], a ; rotation will put next bit in 0th position (so we can always use command -; "bit 0,d" to fetch the bit that has to be sent) +; "bit 0, d" to fetch the bit that has to be sent) rr d ; decrease bit counter so we know when we have sent all 8 bits of current byte dec e @@ -377,8 +532,6 @@ SendSGBPacket: ; set P14=HIGH,P15=HIGH ld a, $30 ldh [rJOYP], a - xor a - ldh [hDisableJoypadPolling], a ; wait for about 70000 cycles call Wait7000 ; restore (previously pushed) number of packets @@ -393,14 +546,17 @@ LoadSGB: xor a ld [wOnSGB], a call CheckSGB - ret nc - ld a, 1 - ld [wOnSGB], a - ld a, [wGBC] + jr c, .onSGB + ldh a, [hGBC] and a - jr z, .notGBC + jr z, .onDMG + ld a, $1 + ld [wOnSGB], a +.onDMG ret -.notGBC +.onSGB + ld a, $1 + ld [wOnSGB], a di call PrepareSuperNintendoVRAMTransfer ei @@ -443,23 +599,19 @@ PrepareSuperNintendoVRAMTransfer: .packetPointers ; Only the first packet is needed. dw MaskEnFreezePacket - dw DataSnd_72548 - dw DataSnd_72558 - dw DataSnd_72568 - dw DataSnd_72578 - dw DataSnd_72588 - dw DataSnd_72598 - dw DataSnd_725a8 - dw DataSnd_725b8 + dw DataSnd_728a1 + dw DataSnd_728b1 + dw DataSnd_728c1 + dw DataSnd_728d1 + dw DataSnd_728e1 + dw DataSnd_728f1 + dw DataSnd_72901 + dw DataSnd_72911 CheckSGB: ; Returns whether the game is running on an SGB in carry. ld hl, MltReq2Packet - di call SendSGBPacket - ld a, 1 - ldh [hDisableJoypadPolling], a - ei call Wait7000 ldh a, [rJOYP] and $3 @@ -515,6 +667,7 @@ CopyGfxToSuperNintendoVRAM: call DisableLCD ld a, $e4 ldh [rBGP], a + call _UpdateGBCPal_BGP_CheckDMG ld de, vChars1 ld a, [wCopyingSGBTileData] and a @@ -545,6 +698,7 @@ CopyGfxToSuperNintendoVRAM: call SendSGBPacket xor a ldh [rBGP], a + call _UpdateGBCPal_BGP_CheckDMG ei ret @@ -562,13 +716,17 @@ Wait7000: ret SendSGBPackets: - ld a, [wGBC] + ldh a, [hGBC] and a jr z, .notGBC push de call InitGBCPalettes pop hl - call EmptyFunc3 + call InitGBCPalettes + ldh a, [rLCDC] + and rLCDC_ENABLE_MASK + ret z + call Delay3 ret .notGBC push de @@ -577,30 +735,349 @@ SendSGBPackets: jp SendSGBPacket InitGBCPalettes: - ld a, $80 ; index 0 with auto-increment - ldh [rBGPI], a - inc hl - ld c, $20 -.loop - ld a, [hli] + ld a, [hl] + and $f8 + cp $20 + jp z, TranslatePalPacketToBGMapAttributes + inc hl + +index = 0 + + REPT NUM_ACTIVE_PALS + IF index > 0 + pop hl + ENDC + + ld a, [hli] + inc hl + + IF index < (NUM_ACTIVE_PALS + -1) + push hl + ENDC + + call GetGBCBasePalAddress + ld a, e + ld [wGBCBasePalPointers + index * 2], a + ld a, d + ld [wGBCBasePalPointers + index * 2 + 1], a + + xor a ; CONVERT_BGP + call DMGPalToGBCPal + ld a, index + call TransferCurBGPData + + ld a, CONVERT_OBP0 + call DMGPalToGBCPal + ld a, index + call TransferCurOBPData + + ld a, CONVERT_OBP1 + call DMGPalToGBCPal + ld a, index + 4 + call TransferCurOBPData + +index = index + 1 + ENDR + + ret + +GetGBCBasePalAddress:: +; Input: a = palette ID +; Output: de = palette address + push hl + ld l, a + xor a + ld h, a + add hl, hl + add hl, hl + add hl, hl + ld de, GBCBasePalettes + add hl, de + ld a, l + ld e, a + ld a, h + ld d, a + pop hl + ret + +DMGPalToGBCPal:: +; Populate wGBCPal with colors from a base palette, selected using one of the +; DMG palette registers. +; Input: +; a = which DMG palette register +; de = address of GBC base palette + and a + jr nz, .notBGP + ldh a, [rBGP] + ld [wLastBGP], a + jr .convert +.notBGP + dec a + jr nz, .notOBP0 + ldh a, [rOBP0] + ld [wLastOBP0], a + jr .convert +.notOBP0 + ldh a, [rOBP1] + ld [wLastOBP1], a +.convert +color_index = 0 + REPT NUM_COLORS + ld b, a + and %11 + call .GetColorAddress + ld a, [hli] + ld [wGBCPal + color_index * 2], a + ld a, [hl] + ld [wGBCPal + color_index * 2 + 1], a + + IF color_index < (NUM_COLORS + -1) + ld a, b + rrca + rrca + ENDC + +color_index = color_index + 1 + ENDR + ret + +.GetColorAddress: + add a + ld l, a + xor a + ld h, a + add hl, de + ret + +TransferCurBGPData:: + push de + add a + add a + add a + or $80 ; auto-increment + ldh [rBGPI], a + ld de, rBGPD + ld hl, wGBCPal + ld b, %10 ; mask for non-V-blank/non-H-blank STAT mode + ldh a, [rLCDC] + and rLCDC_ENABLE_MASK + jr nz, .lcdEnabled + rept NUM_COLORS + call TransferPalColorLCDDisabled + endr + jr .done +.lcdEnabled + rept NUM_COLORS + call TransferPalColorLCDEnabled + endr +.done + pop de + ret + +BufferBGPPal:: +; Copy wGBCPal to palette a in wBGPPalsBuffer. + push de add a add a add a - ld de, SuperPalettes - add e - jr nc, .noCarry - inc d -.noCarry + ld l, a + xor a + ld h, a + ld de, wBGPPalsBuffer + add hl, de + ld de, wGBCPal + ld c, PAL_SIZE +.loop ld a, [de] - ldh [rBGPD], a + ld [hli], a + inc de + dec c + jr nz, .loop + pop de + ret + +TransferBGPPals:: +; Transfer the buffered BG palettes. + ldh a, [rLCDC] + and rLCDC_ENABLE_MASK + jr z, .lcdDisabled + di +.waitLoop + ldh a, [rLY] + cp 144 + jr c, .waitLoop +.lcdDisabled + call .DoTransfer + ei + ret + +.DoTransfer: + xor a + or $80 ; auto-increment + ldh [rBGPI], a + ld de, rBGPD + ld hl, wBGPPalsBuffer + ld c, 4 * PAL_SIZE +.loop + ld a, [hli] + ld [de], a dec c jr nz, .loop ret -EmptyFunc3: +TransferCurOBPData: + push de + add a + add a + add a + or $80 ; auto-increment + ldh [rOBPI], a + ld de, rOBPD + ld hl, wGBCPal + ld b, %10 ; mask for non-V-blank/non-H-blank STAT mode + ldh a, [rLCDC] + and rLCDC_ENABLE_MASK + jr nz, .lcdEnabled + rept NUM_COLORS + call TransferPalColorLCDDisabled + endr + jr .done +.lcdEnabled + rept NUM_COLORS + call TransferPalColorLCDEnabled + endr +.done + pop de ret +TransferPalColorLCDEnabled: +; Transfer a palette color while the LCD is enabled. + +; In case we're already in H-blank or V-blank, wait for it to end. This is a +; precaution so that the transfer doesn't extend past the blanking period. + ldh a, [rSTAT] + and b + jr z, TransferPalColorLCDEnabled + +; Wait for H-blank or V-blank to begin. +.notInBlankingPeriod + ldh a, [rSTAT] + and b + jr nz, .notInBlankingPeriod +; fall through + +TransferPalColorLCDDisabled: +; Transfer a palette color while the LCD is disabled. + ld a, [hli] + ld [de], a + ld a, [hli] + ld [de], a + ret + +_UpdateGBCPal_BGP_CheckDMG:: + ldh a, [hGBC] + and a + ret z +; fall through + +_UpdateGBCPal_BGP:: +index = 0 + + REPT NUM_ACTIVE_PALS + ld a, [wGBCBasePalPointers + index * 2] + ld e, a + ld a, [wGBCBasePalPointers + index * 2 + 1] + ld d, a + xor a ; CONVERT_BGP + call DMGPalToGBCPal + ld a, index + call BufferBGPPal + +index = index + 1 + ENDR + + call TransferBGPPals + ret + +_UpdateGBCPal_OBP:: +index = 0 + + REPT NUM_ACTIVE_PALS + ld a, [wGBCBasePalPointers + index * 2] + ld e, a + ld a, [wGBCBasePalPointers + index * 2 + 1] + ld d, a + ld a, c + call DMGPalToGBCPal + ld a, c + dec a + rlca + rlca + + IF index > 0 + IF index == 1 + inc a + ELSE + add index + ENDC + ENDC + + call TransferCurOBPData + +index = index + 1 + ENDR + + ret + +TranslatePalPacketToBGMapAttributes:: +; translate the SGB pal packets into something usable for the GBC + push hl + pop de + ld hl, PalPacketPointers + ld a, [hli] + ld c, a +.loop + ld a, e +.innerLoop + cp [hl] + jr z, .checkHighByte + inc hl + inc hl + dec c + jr nz, .innerLoop + ret +.checkHighByte +; the low byte of pointer matched, so check the high byte + inc hl + ld a, d + cp [hl] + jr z, .foundMatchingPointer + inc hl + dec c + jr nz, .loop + ret +.foundMatchingPointer + farcall LoadBGMapAttributes + ret + +PalPacketPointers:: + db (palPacketPointersEnd - palPacketPointers) / 2 +palPacketPointers: + dw BlkPacket_WholeScreen + dw BlkPacket_Battle + dw BlkPacket_StatusScreen + dw BlkPacket_Pokedex + dw BlkPacket_Slots + dw BlkPacket_Titlescreen + dw BlkPacket_NidorinoIntro + dw wPartyMenuBlkPacket + dw wTrainerCardBlkPacket + dw BlkPacket_GameFreakIntro + dw wPalPacket + dw UnknownPacket_72751 +palPacketPointersEnd: + CopySGBBorderTiles: ; SGB tile data is stored in a 4BPP planar format. ; Each tile is 32 bytes. The first 16 bytes contain bit planes 1 and 2, while @@ -608,9 +1085,7 @@ CopySGBBorderTiles: ; This function converts 2BPP planar data into this format by mapping ; 2BPP colors 0-3 to 4BPP colors 0-3. 4BPP colors 4-15 are not used. ld b, 128 - .tileLoop - ; Copy bit planes 1 and 2 of the tile data. ld c, 16 .copyLoop diff --git a/engine/gfx/screen_effects.asm b/engine/gfx/screen_effects.asm index e8648901..973a951a 100755..100644 --- a/engine/gfx/screen_effects.asm +++ b/engine/gfx/screen_effects.asm @@ -1,14 +1,16 @@ -; b = new colour for BG colour 0 (usually white) for 4 frames +; inverts the BGP for 4 (6 on CGB due to lag) frames ChangeBGPalColor0_4Frames: - call GetPredefRegisters + call GetPredefRegisters ; leftover of red/blue, has no use here ldh a, [rBGP] - or b + xor $ff ldh [rBGP], a + call UpdateGBCPal_BGP ld c, 4 call DelayFrames ldh a, [rBGP] - and %11111100 + xor $ff ldh [rBGP], a + call UpdateGBCPal_BGP ret PredefShakeScreenVertically: diff --git a/engine/gfx/sprite_oam.asm b/engine/gfx/sprite_oam.asm index b3c07ecd..01b2c412 100644 --- a/engine/gfx/sprite_oam.asm +++ b/engine/gfx/sprite_oam.asm @@ -1,6 +1,8 @@ PrepareOAMData:: ; Determine OAM data for currently visible ; sprites and write it to wOAMBuffer. +; Yellow code has been changed to use registers more efficiently +; as well as tweaking the code to show gbc palettes ld a, [wUpdateSpritesEnabled] dec a @@ -18,9 +20,9 @@ PrepareOAMData:: .spriteLoop ldh [hSpriteOffset2], a - ld d, HIGH(wSpriteStateData1) - ldh a, [hSpriteOffset2] ld e, a + ld d, HIGH(wSpriteStateData1) + ld a, [de] ; [x#SPRITESTATEDATA1_PICTUREID] and a jp z, .nextSprite @@ -40,16 +42,22 @@ PrepareOAMData:: jr c, .usefacing ; unchanging - and $f - add $10 ; skip to the second half of the table which doesn't account for facing direction + ld a, $0 jr .next .usefacing and $f .next +; read the entry from the table + ld c, a + ld b, 0 + ld hl, SpriteFacingAndAnimationTable + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] ld l, a - ; get sprite priority push de inc d @@ -61,65 +69,46 @@ PrepareOAMData:: ldh [hSpritePriority], a ; temp store sprite priority pop de -; read the entry from the table - ld h, 0 - ld bc, SpriteFacingAndAnimationTable - add hl, hl - add hl, hl - add hl, bc - ld a, [hli] - ld c, a - ld a, [hli] - ld b, a - ld a, [hli] - ld h, [hl] - ld l, a call GetSpriteScreenXY ldh a, [hOAMBufferOffset] + add [hl] + cp $a0 + jr z, .hidden + jr nc, .asm_4a41 +.hidden + call Func_4a7b + ld [wd5cd], a + ldh a, [hOAMBufferOffset] + ld e, a ld d, HIGH(wOAMBuffer) .tileLoop + ld a, [hli] + ld c, a +.loop ldh a, [hSpriteScreenY] ; temp for sprite Y position add $10 ; Y=16 is top of screen (Y=0 is invisible) add [hl] ; add Y offset from table ld [de], a ; write new sprite OAM Y position inc hl + inc e ldh a, [hSpriteScreenX] ; temp for sprite X position add $8 ; X=8 is left of screen (X=0 is invisible) add [hl] ; add X offset from table + ld [de], a + inc hl inc e - ld [de], a ; write new sprite OAM X position - inc e - ld a, [bc] ; read pattern number offset (accommodates orientation (offset 0,4 or 8) and animation (offset 0 or $80)) - inc bc - push bc + ld a, [wd5cd] + add [hl] + cp $80 + jr c, .asm_4a1c ld b, a - - ld a, [wd5cd] ; temp copy of [x#SPRITESTATEDATA1_IMAGEINDEX] - swap a ; high nybble determines sprite used (0 is always player sprite, next are some npcs) - and $f - - ; Sprites $a and $b have one face (and therefore 4 tiles instead of 12). - ; As a result, sprite $b's tile offset is less than normal. - cp $b - jr nz, .notFourTileSprite - ld a, $a * 12 + 4 - jr .next2 - -.notFourTileSprite - ; a *= 12 - sla a - sla a - ld c, a - sla a - add c - -.next2 - add b ; add the tile offset from the table (based on frame and facing direction) - pop bc + ldh a, [hFFFC] + add b +.asm_4a1c ld [de], a ; tile id inc hl inc e @@ -129,15 +118,19 @@ PrepareOAMData:: ldh a, [hSpritePriority] or [hl] .skipPriority - inc hl + and $f0 + bit 4, a ; OBP0 or OBP1 + jr z, .spriteusesOBP0 + or %100 ; palettes 4-7 are OBP1 +.spriteusesOBP0 ld [de], a + inc hl inc e - bit 0, a ; OAMFLAG_ENDOFDATA - jr z, .tileLoop + dec c + jr nz, .loop ld a, e ldh [hOAMBufferOffset], a - .nextSprite ldh a, [hSpriteOffset2] add $10 @@ -145,26 +138,31 @@ PrepareOAMData:: jp nz, .spriteLoop ; Clear unused OAM. - ldh a, [hOAMBufferOffset] - ld l, a - ld h, HIGH(wOAMBuffer) - ld de, $4 - ld b, $a0 +.asm_4a41 ld a, [wd736] bit 6, a ; jumping down ledge or fishing animation? - ld a, $a0 + ld c, $a0 jr z, .clear ; Don't clear the last 4 entries because they are used for the shadow in the ; jumping down ledge animation and the rod in the fishing animation. - ld a, $90 + ld c, $90 .clear - cp l - ret z + ldh a, [hOAMBufferOffset] + cp c + ret nc + ld l, a + ld h, wOAMBuffer / $100 + ld a, c + ld de, $4 ; entry size + ld b, $a0 +.clearLoop ld [hl], b add hl, de - jr .clear + cp l + jr nz, .clearLoop + ret GetSpriteScreenXY: inc e @@ -187,3 +185,48 @@ GetSpriteScreenXY: and $f0 ld [de], a ; [x#SPRITESTATEDATA1_XADJUSTED] ret + +Func_4a7b: + push bc + ld a, [wd5cd] ; temp copy of [x#SPRITESTATEDATA1_IMAGEINDEX] + swap a ; high nybble determines sprite used (0 is always player sprite, next are some npcs) + and $f + + ; Sprites $a and $b have one face (and therefore 4 tiles instead of 12). + ; As a result, sprite $b's tile offset is less than normal. + cp $b + jr nz, .notFourTileSprite + ld a, $a * 12 + 4 ; $7c + jr .done + +.notFourTileSprite + ; a *= 12 + add a + add a + ld c, a + add a + add c +.done + pop bc + ret + +INCLUDE "engine/gfx/oam_dma.asm" + +_IsTilePassable:: + ld hl, wTilesetCollisionPtr ; pointer to list of passable tiles + ld a, [hli] + ld h, [hl] + ld l, a ; hl now points to passable tiles +.loop + ld a, [hli] + cp a, $ff + jr z, .tileNotPassable + cp c + jr nz, .loop + xor a + ret +.tileNotPassable + scf + ret + +INCLUDE "data/tilesets/collision_tile_ids.asm" |