123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642 |
- _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 VICTREEBEL + 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 UNKNOWN_DUNGEON_2
- 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"
|