summaryrefslogtreecommitdiff
path: root/engine/gfx
diff options
context:
space:
mode:
Diffstat (limited to 'engine/gfx')
-rwxr-xr-xengine/gfx/hp_bar.asm8
-rwxr-xr-xengine/gfx/mon_icons.asm20
-rwxr-xr-xengine/gfx/palettes.asm579
-rw-r--r--[-rwxr-xr-x]engine/gfx/screen_effects.asm10
-rw-r--r--engine/gfx/sprite_oam.asm163
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"