summaryrefslogtreecommitdiff
path: root/engine/gfx/palettes.asm
diff options
context:
space:
mode:
authorRangi <35663410+Rangi42@users.noreply.github.com>2020-07-03 09:38:52 -0400
committerGitHub <noreply@github.com>2020-07-03 09:38:52 -0400
commitc85050497c1bd062e9cd40bf5b32fa3beca366cc (patch)
tree9593ddd3ab820223ab580d5fc0ae133b485b8315 /engine/gfx/palettes.asm
parent5559d51c863b6fb529ea0494d857950a36fe85b7 (diff)
parent87ef75c173b5d5f227912860487600b6f53d1d1f (diff)
Merge pull request #256 from Rangi42/master
Add subdirectories to engine/ similar to pokecrystal
Diffstat (limited to 'engine/gfx/palettes.asm')
-rwxr-xr-xengine/gfx/palettes.asm641
1 files changed, 641 insertions, 0 deletions
diff --git a/engine/gfx/palettes.asm b/engine/gfx/palettes.asm
new file mode 100755
index 00000000..39991d48
--- /dev/null
+++ b/engine/gfx/palettes.asm
@@ -0,0 +1,641 @@
+_RunPaletteCommand:
+ call GetPredefRegisters
+ ld a, b
+ cp $ff
+ jr nz, .next
+ ld a, [wDefaultPaletteCommand] ; use default command if command ID is $ff
+.next
+ cp UPDATE_PARTY_MENU_BLK_PACKET
+ jp z, UpdatePartyMenuBlkPacket
+ ld l, a
+ ld h, 0
+ add hl, hl
+ ld de, SetPalFunctions
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld de, SendSGBPackets
+ push de
+ jp hl
+
+SetPal_BattleBlack:
+ ld hl, PalPacket_Black
+ ld de, BlkPacket_Battle
+ ret
+
+; uses PalPacket_Empty to build a packet based on mon IDs and health color
+SetPal_Battle:
+ ld hl, PalPacket_Empty
+ ld de, wPalPacket
+ ld bc, $10
+ call CopyData
+ ld a, [wPlayerBattleStatus3]
+ ld hl, wBattleMonSpecies
+ call DeterminePaletteID
+ ld b, a
+ ld a, [wEnemyBattleStatus3]
+ ld hl, wEnemyMonSpecies2
+ call DeterminePaletteID
+ ld c, a
+ ld hl, wPalPacket + 1
+ ld a, [wPlayerHPBarColor]
+ add PAL_GREENBAR
+ ld [hli], a
+ inc hl
+ ld a, [wEnemyHPBarColor]
+ add PAL_GREENBAR
+ ld [hli], a
+ inc hl
+ ld a, b
+ ld [hli], a
+ inc hl
+ ld a, c
+ ld [hl], a
+ ld hl, wPalPacket
+ ld de, BlkPacket_Battle
+ ld a, SET_PAL_BATTLE
+ ld [wDefaultPaletteCommand], a
+ ret
+
+SetPal_TownMap:
+ ld hl, PalPacket_TownMap
+ ld de, BlkPacket_WholeScreen
+ ret
+
+; uses PalPacket_Empty to build a packet based the mon ID
+SetPal_StatusScreen:
+ ld hl, PalPacket_Empty
+ ld de, wPalPacket
+ ld bc, $10
+ call CopyData
+ ld a, [wcf91]
+ cp NUM_POKEMON_INDEXES + 1
+ jr c, .pokemon
+ ld a, $1 ; not pokemon
+.pokemon
+ call DeterminePaletteIDOutOfBattle
+ push af
+ ld hl, wPalPacket + 1
+ ld a, [wStatusScreenHPBarColor]
+ add PAL_GREENBAR
+ ld [hli], a
+ inc hl
+ pop af
+ ld [hl], a
+ ld hl, wPalPacket
+ ld de, BlkPacket_StatusScreen
+ ret
+
+SetPal_PartyMenu:
+ ld hl, PalPacket_PartyMenu
+ ld de, wPartyMenuBlkPacket
+ ret
+
+SetPal_Pokedex:
+ ld hl, PalPacket_Pokedex
+ ld de, wPalPacket
+ ld bc, $10
+ call CopyData
+ ld a, [wcf91]
+ call DeterminePaletteIDOutOfBattle
+ ld hl, wPalPacket + 3
+ ld [hl], a
+ ld hl, wPalPacket
+ ld de, BlkPacket_Pokedex
+ ret
+
+SetPal_Slots:
+ ld hl, PalPacket_Slots
+ ld de, BlkPacket_Slots
+ ret
+
+SetPal_TitleScreen:
+ ld hl, PalPacket_Titlescreen
+ ld de, BlkPacket_Titlescreen
+ ret
+
+; used mostly for menus and the Oak intro
+SetPal_Generic:
+ ld hl, PalPacket_Generic
+ ld de, BlkPacket_WholeScreen
+ ret
+
+SetPal_NidorinoIntro:
+ ld hl, PalPacket_NidorinoIntro
+ ld de, BlkPacket_NidorinoIntro
+ ret
+
+SetPal_GameFreakIntro:
+ ld hl, PalPacket_GameFreakIntro
+ ld de, BlkPacket_GameFreakIntro
+ ld a, SET_PAL_GENERIC
+ ld [wDefaultPaletteCommand], a
+ ret
+
+; uses PalPacket_Empty to build a packet based on the current map
+SetPal_Overworld:
+ ld hl, PalPacket_Empty
+ ld de, wPalPacket
+ ld bc, $10
+ call CopyData
+ 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
+.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 palette ID is its map ID + 1
+ ld hl, wPalPacket + 1
+ ld [hld], a
+ ld de, BlkPacket_WholeScreen
+ ld a, SET_PAL_OVERWORLD
+ ld [wDefaultPaletteCommand], a
+ ret
+.PokemonTowerOrAgatha
+ ld a, PAL_GREYMON - 1
+ jr .town
+.caveOrBruno
+ ld a, PAL_CAVE - 1
+ jr .town
+.Lorelei
+ xor a
+ jr .town
+
+; used when a Pokemon is the only thing on the screen
+; such as evolution, trading and the Hall of Fame
+SetPal_PokemonWholeScreen:
+ push bc
+ ld hl, PalPacket_Empty
+ ld de, wPalPacket
+ ld bc, $10
+ call CopyData
+ pop bc
+ ld a, c
+ and a
+ ld a, PAL_BLACK
+ jr nz, .next
+ ld a, [wWholeScreenPaletteMonSpecies]
+ call DeterminePaletteIDOutOfBattle
+.next
+ ld [wPalPacket + 1], a
+ ld hl, wPalPacket
+ ld de, BlkPacket_WholeScreen
+ ret
+
+SetPal_TrainerCard:
+ ld hl, BlkPacket_TrainerCard
+ ld de, wTrainerCardBlkPacket
+ ld bc, $40
+ call CopyData
+ ld de, BadgeBlkDataLengths
+ ld hl, wTrainerCardBlkPacket + 2
+ ld a, [wObtainedBadges]
+ ld c, 8
+.badgeLoop
+ srl a
+ push af
+ jr c, .haveBadge
+; The player doens't have the badge, so zero the badge's blk data.
+ push bc
+ ld a, [de]
+ ld c, a
+ xor a
+.zeroBadgeDataLoop
+ ld [hli], a
+ dec c
+ jr nz, .zeroBadgeDataLoop
+ pop bc
+ jr .nextBadge
+.haveBadge
+; The player does have the badge, so skip past the badge's blk data.
+ ld a, [de]
+.skipBadgeDataLoop
+ inc hl
+ dec a
+ jr nz, .skipBadgeDataLoop
+.nextBadge
+ pop af
+ inc de
+ dec c
+ jr nz, .badgeLoop
+ ld hl, PalPacket_TrainerCard
+ ld de, wTrainerCardBlkPacket
+ ret
+
+SetPalFunctions:
+ dw SetPal_BattleBlack
+ dw SetPal_Battle
+ dw SetPal_TownMap
+ dw SetPal_StatusScreen
+ dw SetPal_Pokedex
+ dw SetPal_Slots
+ dw SetPal_TitleScreen
+ dw SetPal_NidorinoIntro
+ dw SetPal_Generic
+ dw SetPal_Overworld
+ dw SetPal_PartyMenu
+ dw SetPal_PokemonWholeScreen
+ dw SetPal_GameFreakIntro
+ dw SetPal_TrainerCard
+
+; The length of the blk data of each badge on the Trainer Card.
+; The Rainbow Badge has 3 entries because of its many colors.
+BadgeBlkDataLengths:
+ db 6 ; Boulder Badge
+ db 6 ; Cascade Badge
+ db 6 ; Thunder Badge
+ db 6 * 3 ; Rainbow Badge
+ db 6 ; Soul Badge
+ db 6 ; Marsh Badge
+ db 6 ; Volcano Badge
+ 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
+ and a ; is the mon index 0?
+ jr z, .skipDexNumConversion
+ push bc
+ predef IndexToPokedex
+ pop bc
+ ld a, [wd11e]
+.skipDexNumConversion
+ ld e, a
+ ld d, 0
+ ld hl, MonsterPalettes ; not just for Pokemon, Trainers use it too
+ add hl, de
+ ld a, [hl]
+ ret
+
+InitPartyMenuBlkPacket:
+ ld hl, BlkPacket_PartyMenu
+ ld de, wPartyMenuBlkPacket
+ ld bc, $30
+ jp CopyData
+
+UpdatePartyMenuBlkPacket:
+; Update the blk packet with the palette of the HP bar that is
+; specified in [wWhichPartyMenuHPBar].
+ ld hl, wPartyMenuHPBarColors
+ ld a, [wWhichPartyMenuHPBar]
+ ld e, a
+ ld d, 0
+ add hl, de
+ ld e, l
+ ld d, h
+ ld a, [de]
+ and a
+ ld e, (1 << 2) | 1 ; green
+ jr z, .next
+ dec a
+ ld e, (2 << 2) | 2 ; yellow
+ jr z, .next
+ ld e, (3 << 2) | 3 ; red
+.next
+ push de
+ ld hl, wPartyMenuBlkPacket + 8 + 1
+ ld bc, 6
+ ld a, [wWhichPartyMenuHPBar]
+ call AddNTimes
+ pop de
+ ld [hl], e
+ ret
+
+SendSGBPacket:
+;check number of packets
+ ld a, [hl]
+ and $07
+ ret z
+; store number of packets in B
+ ld b, a
+.loop2
+; save B for later use
+ push bc
+; disable ReadJoypad to prevent it from interfering with sending the packet
+ ld a, 1
+ ld [hDisableJoypadPolling], a
+; send RESET signal (P14=LOW, P15=LOW)
+ xor a
+ ld [rJOYP], a
+; set P14=HIGH, P15=HIGH
+ ld a, $30
+ ld [rJOYP], a
+;load length of packets (16 bytes)
+ ld b, $10
+.nextByte
+;set bit counter (8 bits per byte)
+ ld e, $08
+; get next byte in the packet
+ ld a, [hli]
+ ld d, a
+.nextBit0
+ bit 0, d
+; 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)
+ ld a, $20
+.next0
+ ld [rJOYP], a
+; must set P14=HIGH,P15=HIGH between each "pulse"
+ ld a, $30
+ ld [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)
+ rr d
+; decrease bit counter so we know when we have sent all 8 bits of current byte
+ dec e
+ jr nz, .nextBit0
+ dec b
+ jr nz, .nextByte
+; send bit 1 as a "stop bit" (end of parameter data)
+ ld a, $20
+ ld [rJOYP], a
+; set P14=HIGH,P15=HIGH
+ ld a, $30
+ ld [rJOYP], a
+ xor a
+ ld [hDisableJoypadPolling], a
+; wait for about 70000 cycles
+ call Wait7000
+; restore (previously pushed) number of packets
+ pop bc
+ dec b
+; return if there are no more packets
+ ret z
+; else send 16 more bytes
+ jr .loop2
+
+LoadSGB:
+ xor a
+ ld [wOnSGB], a
+ call CheckSGB
+ ret nc
+ ld a, 1
+ ld [wOnSGB], a
+ ld a, [wGBC]
+ and a
+ jr z, .notGBC
+ ret
+.notGBC
+ di
+ call PrepareSuperNintendoVRAMTransfer
+ ei
+ ld a, 1
+ ld [wCopyingSGBTileData], a
+ ld de, ChrTrnPacket
+ ld hl, SGBBorderGraphics
+ call CopyGfxToSuperNintendoVRAM
+ xor a
+ ld [wCopyingSGBTileData], a
+ ld de, PctTrnPacket
+ ld hl, BorderPalettes
+ call CopyGfxToSuperNintendoVRAM
+ xor a
+ ld [wCopyingSGBTileData], a
+ ld de, PalTrnPacket
+ ld hl, SuperPalettes
+ call CopyGfxToSuperNintendoVRAM
+ call ClearVram
+ ld hl, MaskEnCancelPacket
+ jp SendSGBPacket
+
+PrepareSuperNintendoVRAMTransfer:
+ ld hl, .packetPointers
+ ld c, 9
+.loop
+ push bc
+ ld a, [hli]
+ push hl
+ ld h, [hl]
+ ld l, a
+ call SendSGBPacket
+ pop hl
+ inc hl
+ pop bc
+ dec c
+ jr nz, .loop
+ ret
+
+.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
+
+CheckSGB:
+; Returns whether the game is running on an SGB in carry.
+ ld hl, MltReq2Packet
+ di
+ call SendSGBPacket
+ ld a, 1
+ ld [hDisableJoypadPolling], a
+ ei
+ call Wait7000
+ ld a, [rJOYP]
+ and $3
+ cp $3
+ jr nz, .isSGB
+ ld a, $20
+ ld [rJOYP], a
+ ld a, [rJOYP]
+ ld a, [rJOYP]
+ call Wait7000
+ call Wait7000
+ ld a, $30
+ ld [rJOYP], a
+ call Wait7000
+ call Wait7000
+ ld a, $10
+ ld [rJOYP], a
+ ld a, [rJOYP]
+ ld a, [rJOYP]
+ ld a, [rJOYP]
+ ld a, [rJOYP]
+ ld a, [rJOYP]
+ ld a, [rJOYP]
+ call Wait7000
+ call Wait7000
+ ld a, $30
+ ld [rJOYP], a
+ ld a, [rJOYP]
+ ld a, [rJOYP]
+ ld a, [rJOYP]
+ call Wait7000
+ call Wait7000
+ ld a, [rJOYP]
+ and $3
+ cp $3
+ jr nz, .isSGB
+ call SendMltReq1Packet
+ and a
+ ret
+.isSGB
+ call SendMltReq1Packet
+ scf
+ ret
+
+SendMltReq1Packet:
+ ld hl, MltReq1Packet
+ call SendSGBPacket
+ jp Wait7000
+
+CopyGfxToSuperNintendoVRAM:
+ di
+ push de
+ call DisableLCD
+ ld a, $e4
+ ld [rBGP], a
+ ld de, vChars1
+ ld a, [wCopyingSGBTileData]
+ and a
+ jr z, .notCopyingTileData
+ call CopySGBBorderTiles
+ jr .next
+.notCopyingTileData
+ ld bc, $1000
+ call CopyData
+.next
+ ld hl, vBGMap0
+ ld de, $c
+ ld a, $80
+ ld c, $d
+.loop
+ ld b, $14
+.innerLoop
+ ld [hli], a
+ inc a
+ dec b
+ jr nz, .innerLoop
+ add hl, de
+ dec c
+ jr nz, .loop
+ ld a, $e3
+ ld [rLCDC], a
+ pop hl
+ call SendSGBPacket
+ xor a
+ ld [rBGP], a
+ ei
+ ret
+
+Wait7000:
+; Each loop takes 9 cycles so this routine actually waits 63000 cycles.
+ ld de, 7000
+.loop
+ nop
+ nop
+ nop
+ dec de
+ ld a, d
+ or e
+ jr nz, .loop
+ ret
+
+SendSGBPackets:
+ ld a, [wGBC]
+ and a
+ jr z, .notGBC
+ push de
+ call InitGBCPalettes
+ pop hl
+ call EmptyFunc5
+ ret
+.notGBC
+ push de
+ call SendSGBPacket
+ pop hl
+ jp SendSGBPacket
+
+InitGBCPalettes:
+ ld a, $80 ; index 0 with auto-increment
+ ld [rBGPI], a
+ inc hl
+ ld c, $20
+.loop
+ ld a, [hli]
+ inc hl
+ add a
+ add a
+ add a
+ ld de, SuperPalettes
+ add e
+ jr nc, .noCarry
+ inc d
+.noCarry
+ ld a, [de]
+ ld [rBGPD], a
+ dec c
+ jr nz, .loop
+ ret
+
+EmptyFunc5:
+ ret
+
+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
+; the second 16 bytes contain bit planes 3 and 4.
+; 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
+ ld a, [hli]
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .copyLoop
+
+; Zero bit planes 3 and 4.
+ ld c, 16
+ xor a
+.zeroLoop
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .zeroLoop
+
+ dec b
+ jr nz, .tileLoop
+ ret
+
+INCLUDE "data/sgb_packets.asm"
+
+INCLUDE "data/mon_palettes.asm"
+
+INCLUDE "data/super_palettes.asm"
+
+INCLUDE "data/sgb_border.asm"