diff options
author | Daniel Harding <33dannye@gmail.com> | 2021-02-23 21:07:01 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-23 21:07:01 -0600 |
commit | 5fdf423da5fdcc24d73e88ea21cc98f58c448c96 (patch) | |
tree | d1a7ed19e75e8a85a96b71ce532b1f2fa4a174fa | |
parent | 8a37415c695b81b3bf434d3a2fe2a911f68acc28 (diff) | |
parent | b7569adb2dd7f30f198afc62c29dda05e5491ae0 (diff) |
Merge pull request #101 from ElectroDeoxys/master
Card Pop! and Printer (bank$06)
-rw-r--r-- | src/constants.asm | 1 | ||||
-rw-r--r-- | src/constants/charmaps.asm | 2 | ||||
-rw-r--r-- | src/constants/misc_constants.asm | 16 | ||||
-rw-r--r-- | src/engine/bank01.asm | 64 | ||||
-rw-r--r-- | src/engine/bank04.asm | 60 | ||||
-rw-r--r-- | src/engine/bank06.asm | 1745 | ||||
-rw-r--r-- | src/engine/bank20.asm | 22 | ||||
-rw-r--r-- | src/engine/home.asm | 32 | ||||
-rw-r--r-- | src/sram.asm | 47 | ||||
-rw-r--r-- | src/text/text1.asm | 14 | ||||
-rw-r--r-- | src/text/text2.asm | 12 | ||||
-rw-r--r-- | src/text/text_offsets.asm | 26 | ||||
-rw-r--r-- | src/wram.asm | 98 | ||||
-rw-r--r-- | tools/tcgdisasm.py | 2 |
14 files changed, 2064 insertions, 77 deletions
diff --git a/src/constants.asm b/src/constants.asm index 5fcb2ac..96361c9 100644 --- a/src/constants.asm +++ b/src/constants.asm @@ -13,6 +13,7 @@ INCLUDE "constants/music_constants.asm" INCLUDE "constants/name_constants.asm" INCLUDE "constants/npc_constants.asm" INCLUDE "constants/palette_constants.asm" +INCLUDE "constants/printer_constants.asm" INCLUDE "constants/scene_constants.asm" INCLUDE "constants/script_constants.asm" INCLUDE "constants/sgb_constants.asm" diff --git a/src/constants/charmaps.asm b/src/constants/charmaps.asm index 9fd0e05..2b8eb40 100644 --- a/src/constants/charmaps.asm +++ b/src/constants/charmaps.asm @@ -339,7 +339,7 @@ ENDM txsymbol PARALYZED ; $0b txsymbol CURSOR_U ; $0c txsymbol POKEMON ; $0d - txsymbol ATK_DESCR ; $0e + txsymbol ATK_DESCR ; $0e txsymbol CURSOR_R ; $0f txsymbol HP ; $10 txsymbol Lv ; $11 diff --git a/src/constants/misc_constants.asm b/src/constants/misc_constants.asm index 45d8bf2..8649881 100644 --- a/src/constants/misc_constants.asm +++ b/src/constants/misc_constants.asm @@ -50,6 +50,22 @@ OWMODE_MOVE EQU 1 OWMODE_START_SCRIPT EQU 2 OWMODE_SCRIPT EQU 3 +; max number of player names that +; can be written to sCardPopNameList +CARDPOP_NAME_LIST_MAX_ELEMS EQU 16 +CARDPOP_NAME_LIST_SIZE EQUS "CARDPOP_NAME_LIST_MAX_ELEMS * NAME_BUFFER_LENGTH" + +; commands transmitted through IR to be +; executed by the other device +; (see ExecuteReceivedIRCommands) + const_def + const IRCMD_CLOSE ; $0 + const IRCMD_RETURN_WO_CLOSING ; $1 + const IRCMD_TRANSMIT_DATA ; $2 + const IRCMD_RECEIVE_DATA ; $3 + const IRCMD_CALL_FUNCTION ; $4 +NUM_IR_COMMANDS EQU const_value + NULL EQU $0000 FALSE EQU 0 diff --git a/src/engine/bank01.asm b/src/engine/bank01.asm index 82ccfc5..4380e2f 100644 --- a/src/engine/bank01.asm +++ b/src/engine/bank01.asm @@ -4372,6 +4372,8 @@ DisplayCardPage_PokemonOverview: ; 5b7d (1:5b7d) ; print the name, damage, and energy cost of each attack and/or Pokemon power that exists ; first attack at 5,10 and second at 5,12 lb bc, 5, 10 + +.attacks ld e, c ld hl, wLoadedCard1Atk1Name call PrintAttackOrPkmnPowerInformation @@ -8441,10 +8443,59 @@ PlayAttackAnimation: ; 7494 (1:7494) ret ; 0x74dc - INCROM $74dc, $7571 +Func_74dc: ; 74dc (1:74dc) + call EmptyScreen + call EnableLCD + ld a, GRASS_ENERGY + ld [wce9a], a +.wait_input + call DoFrame + ldh a, [hDPadHeld] + ld b, a + ld a, [wce9a] +; left + bit D_LEFT_F, b + jr z, .right + dec a ; previous card +.right + bit D_RIGHT_F, b + jr z, .up + inc a ; next card +.up + bit D_UP_F, b + jr z, .down + add 10 +.down + bit D_DOWN_F, b + jr z, .got_card_id + sub 10 -Func_7571: ; 7571 (1:7571) - farcall Func_19c20 +.got_card_id + ld [wce9a], a + lb bc, 5, 5 + bank1call WriteTwoByteNumberInTxSymbolFormat + ldh a, [hKeysPressed] + and START + jr z, .wait_input + ld a, [wce9a] + ld e, a + ld d, $0 +.asm_751b + call LoadCardDataToBuffer1_FromCardID + ret c ; card not found + push de + ld a, e + call Func_758a + pop de + inc de + jr .asm_751b +; 0x7528 + + INCROM $7528, $7571 + +; handles all the Card Pop! functionality +DoCardPop: ; 7571 (1:7571) + farcall _DoCardPop ret Func_7576: ; 7576 (1:7576) @@ -8452,7 +8503,12 @@ Func_7576: ; 7576 (1:7576) ret ; 0x757b - INCROM $757b, $758f + INCROM $757b, $758a + +Func_758a: ; 758a (1:758a) + farcall Func_19eb4 + ret +; 0x758f Func_758f: ; 758f (1:758f) farcall Func_1a4cf diff --git a/src/engine/bank04.asm b/src/engine/bank04.asm index 7a6c0b5..f1d31c1 100644 --- a/src/engine/bank04.asm +++ b/src/engine/bank04.asm @@ -1089,7 +1089,31 @@ Func_11238: ; 11238 (4:5238) INCROM $11238, $1124d Func_1124d: ; 1124d (4:524d) - INCROM $1124d, $11320 + INCROM $1124d, $1127f + +; writes in de total num of cards collected +; and in (de + 1) total num of cards to collect +; also updates wTotalNumCardsCollected and wTotalNumCardsToCollect +UpdateAlbumProgress: ; 1127f (4:527f) + push hl + push de + push de + call GetCardAlbumProgress + call EnableSRAM + pop hl + ld a, d + ld [wTotalNumCardsCollected], a + ld [hli], a + ld a, e + ld [wTotalNumCardsToCollect], a + ld [hl], a + call DisableSRAM + pop de + pop hl + ret +; 0x11299 + + INCROM $11299, $11320 Func_11320: ; 11320 (4:5320) INCROM $11320, $11343 @@ -1246,8 +1270,36 @@ _SaveGame: ; 1157c (4:557c) call Func_11238 ret -Func_115a3: ; 115a3 (4:55a3) - INCROM $115a3, $1162a +_AddCardToCollectionAndUpdateAlbumProgress: ; 115a3 (4:55a3) + ld [wCardToAddToCollection], a + push hl + push bc + push de + ldh a, [hBankSRAM] + push af + ld a, BANK(sAlbumProgress) + call BankswitchSRAM + ld a, [wCardToAddToCollection] + call AddCardToCollection + ld de, sAlbumProgress + call UpdateAlbumProgress + pop af + call BankswitchSRAM + call DisableSRAM ; unnecessary + +; unintentional? runs the same write operation +; on the same address but on the current SRAM bank + ld a, [wCardToAddToCollection] + call AddCardToCollection + ld de, $b8fe + call UpdateAlbumProgress + pop de + pop bc + pop hl + ret +; 0x115d4 + + INCROM $115d4, $1162a INCLUDE "data/map_scripts.asm" @@ -2825,7 +2877,7 @@ MainMenu_ContinueFromDiary: ; 12741 (4:6741) MainMenu_CardPop: ; 12768 (4:6768) ld a, MUSIC_CARD_POP call PlaySong - bank1call Func_7571 + bank1call DoCardPop farcall WhiteOutDMGPals call DoFrameIfLCDEnabled ld a, MUSIC_STOP diff --git a/src/engine/bank06.asm b/src/engine/bank06.asm index 539c858..debb73e 100644 --- a/src/engine/bank06.asm +++ b/src/engine/bank06.asm @@ -1406,7 +1406,595 @@ Func_191a3: ; 191a3 (6:51a3) INCLUDE "data/attack_animations.asm" - INCROM $19674, $1991f +; if carry flag is set, only delays +; if carry not set: +; - set rRP to $c1, wait; +; - set rRP to $c0, wait; +; - return +Func_19674: ; 19674 (6:5674) + jr c, .delay_once + ld [hl], $c1 + ld a, 5 + jr .loop_delay_1 ; jump to possibly to add more cycles? +.loop_delay_1 + dec a + jr nz, .loop_delay_1 + ld [hl], $c0 + ld a, 14 + jr .loop_delay_2 ; jump to possibly to add more cycles? +.loop_delay_2 + dec a + jr nz, .loop_delay_2 + ret + +.delay_once + ld a, 21 + jr .loop_delay_3 ; jump to possibly to add more cycles? +.loop_delay_3 + dec a + jr nz, .loop_delay_3 + nop + ret +; 0x19692 + +; input a = byte to transmit through IR +TransmitByteThroughIR: ; 19692 (6:5692) + push hl + ld hl, rRP + push de + push bc + ld b, a + scf ; carry set + call Func_19674 + or a ; carry not set + call Func_19674 + ld c, 8 + ld c, 8 ; number of input bits +.loop + ld a, $00 + rr b + call Func_19674 + dec c + jr nz, .loop + pop bc + pop de + pop hl + ldh a, [rJOYP] + bit 1, a ; P11 + jr z, ReturnZFlagUnsetAndCarryFlagSet + xor a ; return z set + ret + +; same as ReceiveByteThroughIR but +; returns $0 in a if there's an error in IR +ReceiveByteThroughIR_ZeroIfUnsuccessful: ; 196ba (6:56ba) + call ReceiveByteThroughIR + ret nc + xor a + ret +; 0x196c0 + +; returns carry if there's some time out +; and output in register a of $ff +; otherwise returns in a some sequence of bits +; related to how rRP sets/unsets bit 1 +ReceiveByteThroughIR: ; 196c0 (6:56c0) + push de + push bc + push hl + +; waits for bit 1 in rRP to be unset +; up to $100 loops + ld b, 0 + ld hl, rRP +.wait_ir + bit 1, [hl] + jr z, .ok + dec b + jr nz, .wait_ir + ; looped around $100 times + ; return $ff and carry set + pop hl + pop bc + pop de + scf + ld a, $ff + ret + +.ok +; delay for some cycles + ld a, 15 +.loop_delay + dec a + jr nz, .loop_delay + +; loop for each bit + ld e, 8 +.loop + ld a, $01 + ; possibly delay cycles? + ld b, 9 + ld b, 9 + ld b, 9 + ld b, 9 + +; checks for bit 1 in rRP +; if in any of the checks it is unset, +; then a is set to 0 +; this is done a total of 9 times + bit 1, [hl] + jr nz, .asm_196ec + xor a +.asm_196ec + bit 1, [hl] + jr nz, .asm_196f1 + xor a +.asm_196f1 + dec b + jr nz, .asm_196ec + ; one bit received + rrca + rr d + dec e + jr nz, .loop + ld a, d ; has bits set for each "cycle" that bit 1 was not unset + pop hl + pop bc + pop de + or a + ret +; 0x19700 + +ReturnZFlagUnsetAndCarryFlagSet: ; 19700 (6:5700) + ld a, $ff + or a ; z not set + scf ; carry set + ret +; 0x19705 + +; called when expecting to transmit data +Func_19705: ; 19705 (6:5705) + ld hl, rRP +.asm_19708 + ldh a, [rJOYP] + bit 1, a + jr z, ReturnZFlagUnsetAndCarryFlagSet + ld a, $aa ; request + call TransmitByteThroughIR + push hl + pop hl + call ReceiveByteThroughIR_ZeroIfUnsuccessful + cp $33 ; acknowledge + jr nz, .asm_19708 + xor a + ret +; 0x1971e + +; called when expecting to receive data +Func_1971e: ; 1971e (6:571e) + ld hl, rRP +.asm_19721 + ldh a, [rJOYP] + bit 1, a + jr z, ReturnZFlagUnsetAndCarryFlagSet + call ReceiveByteThroughIR_ZeroIfUnsuccessful + cp $aa ; request + jr nz, .asm_19721 + ld a, $33 ; acknowledge + call TransmitByteThroughIR + xor a + ret +; 0x19735 + +ReturnZFlagUnsetAndCarryFlagSet2: ; 19735 (6:5735) + jp ReturnZFlagUnsetAndCarryFlagSet +; 0x19738 + +TransmitIRDataBuffer: ; 19738 (6:5738) + call Func_19705 + jr c, ReturnZFlagUnsetAndCarryFlagSet2 + ld a, $49 + call TransmitByteThroughIR + ld a, $52 + call TransmitByteThroughIR + ld hl, wIRDataBuffer + ld c, 8 + jr TransmitNBytesFromHLThroughIR + +ReceiveIRDataBuffer: ; 1974e (6:5738) + call Func_1971e + jr c, ReturnZFlagUnsetAndCarryFlagSet2 + call ReceiveByteThroughIR + cp $49 + jr nz, ReceiveIRDataBuffer + call ReceiveByteThroughIR + cp $52 + jr nz, ReceiveIRDataBuffer + ld hl, wIRDataBuffer + ld c, 8 + jr ReceiveNBytesToHLThroughIR + +; hl = start of data to transmit +; c = number of bytes to transmit +TransmitNBytesFromHLThroughIR: ; 19768 (6:5768) + ld b, $0 +.loop_data_bytes + ld a, b + add [hl] + ld b, a + ld a, [hli] + call TransmitByteThroughIR + jr c, .asm_1977c + dec c + jr nz, .loop_data_bytes + ld a, b + cpl + inc a + call TransmitByteThroughIR +.asm_1977c + ret + +; hl = address to write received data +; c = number of bytes to be received +ReceiveNBytesToHLThroughIR: ; 1977d (6:577d) + ld b, 0 +.loop_data_bytes + call ReceiveByteThroughIR + jr c, ReturnZFlagUnsetAndCarryFlagSet2 + ld [hli], a + add b + ld b, a + dec c + jr nz, .loop_data_bytes + call ReceiveByteThroughIR + add b + or a + jr nz, ReturnZFlagUnsetAndCarryFlagSet2 + ret +; 0x19792 + +; disables interrupts, and sets joypad and IR communication port +; switches to CGB normal speed +InitiateIRCommunications: ; 19792 (6:5792) + di + call SwitchToCGBNormalSpeed + ld a, P14 + ldh [rJOYP], a + ld a, $c0 + ldh [rRP], a + ret +; 0x1979f + +; reenables interrupts, and switches CGB back to double speed +CloseIRCommunications: ; 1979f (6:579f) + ld a, P14 | P15 + ldh [rJOYP], a +.wait_vblank_on + ldh a, [rSTAT] + and STAT_LCDC_STATUS + cp STAT_ON_VBLANK + jr z, .wait_vblank_on +.wait_vblank_off + ldh a, [rSTAT] + and STAT_LCDC_STATUS + cp STAT_ON_VBLANK + jr nz, .wait_vblank_off + call SwitchToCGBDoubleSpeed + ei + ret +; 0x197b8 + +; set rRP to 0 +ClearRP: ; 197b8 (6:57b8) + ld a, $00 + ldh [rRP], a + ret +; 0x197bd + +; expects to receive a command (IRCMD_* constant) +; in wIRDataBuffer + 1, then calls the subroutine +; corresponding to that command +ExecuteReceivedIRCommands: ; 197bd (6:57bd) + call InitiateIRCommunications +.loop_commands + call ReceiveIRDataBuffer + jr c, .error + jr nz, .loop_commands + ld hl, wIRDataBuffer + 1 + ld a, [hl] + ld hl, .CmdPointerTable + cp NUM_IR_COMMANDS + jr nc, .loop_commands ; invalid command + call .JumpToCmdPointer ; execute command + jr .loop_commands +.error + call CloseIRCommunications + xor a + scf + ret + +.JumpToCmdPointer + add a ; *2 + add l + ld l, a + ld a, 0 + adc h + ld h, a + ld a, [hli] + ld h, [hl] + ld l, a +.jp_hl + jp hl + +.CmdPointerTable + dw .Close ; IRCMD_CLOSE + dw .ReturnWithoutClosing ; IRCMD_RETURN_WO_CLOSING + dw .TransmitData ; IRCMD_TRANSMIT_DATA + dw .ReceiveData ; IRCMD_RECEIVE_DATA + dw .CallFunction ; IRCMD_CALL_FUNCTION + +; closes the IR communications +; pops hl so that the sp points +; to the return address of ExecuteReceivedIRCommands +.Close + pop hl + call CloseIRCommunications + or a + ret + +; returns without closing the IR communications +; will continue the command loop +.ReturnWithoutClosing + or a + ret + +; receives an address and number of bytes +; and transmits starting at that address +.TransmitData + call Func_19705 + ret c + call LoadRegistersFromIRDataBuffer + jp TransmitNBytesFromHLThroughIR + +; receives an address and number of bytes +; and writes the data received to that address +.ReceiveData + call LoadRegistersFromIRDataBuffer + ld l, e + ld h, d + call ReceiveNBytesToHLThroughIR + jr c, .asm_19812 + sub b + call TransmitByteThroughIR +.asm_19812 + ret + +; receives an address to call, then stores +; the registers in the IR data buffer +.CallFunction + call LoadRegistersFromIRDataBuffer + call .jp_hl + call StoreRegistersInIRDataBuffer + ret +; 0x1981d + +Func_1981d: ; 1981d (6:581d) + call InitiateIRCommunications + ld hl, rRP + ld c, 4 +.asm_19825 + ld a, $aa ; request + push bc + call TransmitByteThroughIR + push bc + pop bc + call ReceiveByteThroughIR_ZeroIfUnsuccessful + pop bc + cp $33 ; acknowledgement + jr z, .asm_1983b + dec c + jr nz, .asm_19825 + scf + jr .asm_1983c +.asm_1983b + xor a +.asm_1983c + push af + call CloseIRCommunications + pop af + ret +; 0x19842 + +Func_19842: ; 19842 (6:5842) + call InitiateIRCommunications + ld hl, rRP +.asm_19848 + call ReceiveByteThroughIR_ZeroIfUnsuccessful + cp $aa ; request + jr z, .asm_19859 + ldh a, [rJOYP] + cpl + and P10 | P11 + jr z, .asm_19848 + scf + jr .asm_1985f +.asm_19859 + ld a, $33 ; acknowledgement + call TransmitByteThroughIR + xor a +.asm_1985f + push af + call CloseIRCommunications + pop af + ret +; 0x19865 + +; sends request for other device to close current communication +RequestCloseIRCommunication: ; 19865 (6:5865) + call InitiateIRCommunications + ld a, IRCMD_CLOSE + ld [wIRDataBuffer + 1], a + call TransmitIRDataBuffer +; fallthrough + +; calls CloseIRCommunications while perserving af +SafelyCloseIRCommunications: ; 19870 (6:5870) + push af + call CloseIRCommunications + pop af + ret +; 0x19876 + +; sends a request for data to be transmitted +; from the other device +; hl = start of data to request to transmit +; de = address to write data received +; c = length of data +RequestDataTransmissionThroughIR: ; 19876 (6:5876) + ld a, IRCMD_TRANSMIT_DATA + call TransmitRegistersThroughIR + push de + push bc + call Func_1971e + pop bc + pop hl + jr c, SafelyCloseIRCommunications + call ReceiveNBytesToHLThroughIR + jr SafelyCloseIRCommunications +; 0x19889 + +; transmits data to be written in the other device +; hl = start of data to transmit +; de = address for other device to write data +; c = length of data +RequestDataReceivalThroughIR: ; 19889 (6:5889) + ld a, IRCMD_RECEIVE_DATA + call TransmitRegistersThroughIR + call TransmitNBytesFromHLThroughIR + jr c, SafelyCloseIRCommunications + call ReceiveByteThroughIR + jr c, SafelyCloseIRCommunications + add b + jr nz, .asm_1989e + xor a + jr SafelyCloseIRCommunications +.asm_1989e + call ReturnZFlagUnsetAndCarryFlagSet + jr SafelyCloseIRCommunications +; 0x198a3 + +; first stores all the current registers in wIRDataBuffer +; then transmits it through IR +TransmitRegistersThroughIR: ; 198a3 (6:58a3) + push hl + push de + push bc + call StoreRegistersInIRDataBuffer + call InitiateIRCommunications + call TransmitIRDataBuffer + pop bc + pop de + pop hl + ret nc + inc sp + inc sp + jr SafelyCloseIRCommunications +; 0x198b7 + +; stores af, hl, de and bc in wIRDataBuffer +StoreRegistersInIRDataBuffer: ; 198b7 (6:58b7) + push de + push hl + push af + ld hl, wIRDataBuffer + pop de + ld [hl], e ; <- f + inc hl + ld [hl], d ; <- a + inc hl + pop de + ld [hl], e ; <- l + inc hl + ld [hl], d ; <- h + inc hl + pop de + ld [hl], e ; <- e + inc hl + ld [hl], d ; <- d + inc hl + ld [hl], c ; <- c + inc hl + ld [hl], b ; <- b + ret +; 0x198d0 + +; loads all the registers that were stored +; from StoreRegistersInIRDataBuffer +LoadRegistersFromIRDataBuffer: ; 198d0 (6:58d0) + ld hl, wIRDataBuffer + ld e, [hl] + inc hl + ld d, [hl] + inc hl + push de + ld e, [hl] + inc hl + ld d, [hl] + inc hl + push de + ld e, [hl] + inc hl + ld d, [hl] + inc hl + ld c, [hl] + inc hl + ld b, [hl] + pop hl + pop af + ret +; 0x198e7 + +; empties screen and replaces +; wVBlankFunctionTrampoline with Func_3cb4 +Func_198e7: ; 198e7 (6:58e7) + call EmptyScreen + call Set_OBJ_8x8 + call Func_3ca4 + lb de, $38, $7f + call SetupText + ld hl, wVBlankFunctionTrampoline + 1 + ld de, wVBlankFunctionTrampolineBackup + call BackupVBlankFunctionTrampoline + di + ld [hl], LOW(Func_3cb4) + inc hl + ld [hl], HIGH(Func_3cb4) + ei + ret +; 0x19907 + +Func_19907: ; 19907 (6:5907) + ld hl, wVBlankFunctionTrampolineBackup + ld de, wVBlankFunctionTrampoline + 1 + call BackupVBlankFunctionTrampoline + call Func_3ca4 + bank1call ZeroObjectPositionsAndToggleOAMCopy + ret +; 0x19917 + +; copies 2 bytes from hl to de while interrupts are disabled +; used to load or store wVBlankFunctionTrampoline +; to wVBlankFunctionTrampolineBackup +BackupVBlankFunctionTrampoline: ; 19917 (6:5917) + di + ld a, [hli] + ld [de], a + inc de + ld a, [hld] + ld [de], a + ei + ret +; 0x1991f Func_1991f: ; 1991f (6:591f) add a @@ -1490,7 +2078,8 @@ Func_1996e: ; 1996e (6:596e) ld [hli], a ld [hli], a ld [hl], a - ld hl, $bb00 + + ld hl, sCardPopNameList ld c, $10 .asm_199b2 ld [hl], $0 @@ -1507,7 +2096,7 @@ Func_1996e: ; 1996e (6:596e) ld [sAnimationsDisabled], a ld [s0a009], a ld [s0a004], a - ld [s0a005], a + ld [sTotalCardPopsDone], a ld [s0a00a], a farcall Func_8cf9 call DisableSRAM @@ -1560,10 +2149,1154 @@ Func_19a12: ; 19a12 (6:5a12) ret ; 0x19a1f - INCROM $19a1f, $19c20 + INCROM $19a1f, $19a55 -Func_19c20: ; 19c20 (6:5c20) - INCROM $19c20, $1a4cf +; prepares data for Card Pop! communications +InitializeCardPopCommunications: ; 19a55 (6:5a55) + ld hl, wc5eb + ld [hl], a + inc hl + ld [hl], $50 + inc hl + ld [hl], $4b + inc hl + ld [hl], $31 + ld a, $ff + ld [wc5ea], a + ld a, PLAYER_TURN + ldh [hWhoseTurn], a +; clear wNameBuffer and wOpponentName + xor a + ld [wNameBuffer], a + ld hl, wOpponentName + ld [hli], a + ld [hl], a +; loads player's name from SRAM +; to wDefaultText + call EnableSRAM + ld hl, sPlayerName + ld de, wDefaultText + ld c, NAME_BUFFER_LENGTH +.loop + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .loop + call DisableSRAM + ret +; 0x19a89 + + INCROM $19a89, $19ab7 + +Func_19ab7: ; 19ab7 (6:5ab7) + ld hl, wc5eb + ld de, wc5ef + ld c, 4 + call RequestDataTransmissionThroughIR + jr c, .error + ld hl, wc5ef + 1 + ld a, [hli] + cp $50 + jr nz, .error + ld a, [hli] + cp $4b + jr nz, .error + ld a, [wc5eb] + ld hl, wc5ef + cp [hl] + jr nz, .asm_19af9 + +; receives wDefaultText from other device +; and writes it to wNameBuffer + ld hl, wDefaultText + ld de, wNameBuffer + ld c, NAME_BUFFER_LENGTH + call RequestDataTransmissionThroughIR + jr c, .error +; transmits wDefaultText to be +; written in wNameBuffer in the other device + ld hl, wDefaultText + ld de, wNameBuffer + ld c, NAME_BUFFER_LENGTH + call RequestDataReceivalThroughIR + jr c, .error + or a + ret + +.error + xor a + scf + ret + +.asm_19af9 + ld hl, wc5ea + ld [hl], $01 + ld de, wc5ea + ld c, 1 + call RequestDataReceivalThroughIR + call RequestCloseIRCommunication + ld a, $01 + scf + ret +; 0x19b0d + +Func_19b0d: ; 19b0d (6:5b0d) + ld hl, wc5eb + ld [hl], $00 + ld de, wc5ea + ld c, 1 + call RequestDataReceivalThroughIR + ret c + call RequestCloseIRCommunication + or a + ret +; 0x19b20 + + INCROM $19b20, $19c20 + +_DoCardPop: ; 19c20 (6:5c20) +; loads scene for Card Pop! screen +; then checks if console is SGB +; and issues an error message in case it is + call Func_198e7 + ld a,SCENE_CARD_POP + lb bc, 0, 0 + call LoadScene + ldtx hl, AreYouBothReadyToCardPopText + call PrintScrollableText_NoTextBoxLabel + call Func_19907 + ldtx hl, CardPopCannotBePlayedWithTheGameBoyText + ld a, [wConsole] + cp CONSOLE_SGB + jr z, .error + +; initiate the communications + call PauseSong + call Func_198e7 + ld a, SCENE_GAMEBOY_LINK_CONNECTING + lb bc, 0, 0 + call LoadScene + ldtx hl, PositionGameBoyColorsAndPressAButtonText + call DrawWideTextBox_PrintText + call EnableLCD + call HandleCardPopCommunications + push af + push hl + call ClearRP + call Func_19907 + pop hl + pop af + jr c, .error + +; show the received card detail page +; and play the corresponding song + ld a, [wLoadedCard1ID] + call AddCardToCollectionAndUpdateAlbumProgress + ld hl, wLoadedCard1Name + ld a, [hli] + ld h, [hl] + ld l, a + call LoadTxRam2 + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + ld a, SFX_5D + call PlaySFX +.wait_sfx + call AssertSFXFinished + or a + jr nz, .wait_sfx + ld a, [wCardPopCardObtainSong] + call PlaySong + ldtx hl, ReceivedThroughCardPopText + bank1call _DisplayCardDetailScreen + call ResumeSong + lb de, $38, $9f + call SetupText + bank1call OpenCardPage_FromHand + ret + +.error +; show Card Pop! error scene +; and print text in hl + push hl + call ResumeSong + call Func_198e7 + ld a, SCENE_CARD_POP_ERROR + lb bc, 0, 0 + call LoadScene + pop hl + call PrintScrollableText_NoTextBoxLabel + call Func_19907 + ret +; 0x19cb2 + +; handles all communications to the other device to do Card Pop! +; returns carry if Card Pop! is unsuccessful +; and returns in hl the corresponding error text ID +HandleCardPopCommunications: ; 19cb2 (6:5cb2) +; copy CardPopNameList from SRAM to WRAM + call EnableSRAM + ld hl, sCardPopNameList + ld de, wCardPopNameList + ld bc, CARDPOP_NAME_LIST_SIZE + call CopyDataHLtoDE + call DisableSRAM + + ld a, $01 + call InitializeCardPopCommunications +.asm_19cc9 + call Func_19842 ; send request + jr nc, .asm_19d05 + bit 1, a + jr nz, .fail + call Func_1981d ; receive request + jr c, .asm_19cc9 + +; do the player name search, then transmit the result + call Func_19ab7 + jr c, .fail + ld hl, wCardPopNameList + ld de, wOtherPlayerCardPopNameList + ld c, 0 ; $100 bytes = CARDPOP_NAME_LIST_SIZE + call RequestDataTransmissionThroughIR + jr c, .fail + call LookUpNameInCardPopNameList + ld hl, wCardPopNameSearchResult + ld de, wCardPopNameSearchResult + ld c, 1 + call RequestDataReceivalThroughIR + jr c, .fail + call Func_19b0d + jr c, .fail + call ExecuteReceivedIRCommands + jr c, .fail + jr .check_search_result + +.asm_19d05 + call ExecuteReceivedIRCommands + ld a, [wc5ea] + or a + jr nz, .fail + call RequestCloseIRCommunication + jr c, .fail + +.check_search_result + ld a, [wCardPopNameSearchResult] + or a + jr z, .success + ; not $00, means the name was found in the list + ldtx hl, CannotCardPopWithFriendPreviouslyPoppedWithText + scf + ret + +.success + call DecideCardToReceiveFromCardPop + +; increment number of times Card Pop! was done +; and write the other player's name to sCardPopNameList +; the spot where this is written in the list is derived +; from the lower nybble of sTotalCardPopsDone +; that means that after 16 Card Pop!, the older +; names start to get overwritten + call EnableSRAM + ld hl, sTotalCardPopsDone + ld a, [hl] + inc [hl] + and $0f + swap a ; *NAME_BUFFER_LENGTH + ld l, a + ld h, $0 + ld de, sCardPopNameList + add hl, de + ld de, wNameBuffer + ld c, NAME_BUFFER_LENGTH +.loop_write_name + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .loop_write_name + call DisableSRAM + or a + ret + +.fail + ldtx hl, ThePopWasntSuccessfulText + scf + ret +; 0x19d49 + +; looks up the name in wNameBuffer in wCardPopNameList +; used to know whether this save file has done Card Pop! +; with the other player already +; returns carry and wCardPopNameSearchResult = $ff if the name was found; +; returns no carry and wCardPopNameSearchResult = $00 otherwise +LookUpNameInCardPopNameList: ; 19d49 (6:5d49) +; searches for other player's name in this game's name list + ld hl, wCardPopNameList + ld c, CARDPOP_NAME_LIST_MAX_ELEMS +.loop_own_card_pop_name_list + push hl + ld de, wNameBuffer + call .CompareNames + pop hl + jr nc, .found_name + ld de, NAME_BUFFER_LENGTH + add hl, de + dec c + jr nz, .loop_own_card_pop_name_list + +; name was not found in wCardPopNameList + +; searches for this player's name in the other game's name list +; this is useless since it discards the result from the name comparisons +; as a result this loop will always return no carry + call EnableSRAM + ld hl, wOtherPlayerCardPopNameList + ld c, CARDPOP_NAME_LIST_MAX_ELEMS +.loop_other_card_pop_name_list + push hl + ld de, sPlayerName + call .CompareNames ; discards result from comparison + pop hl + ld de, NAME_BUFFER_LENGTH + add hl, de + dec c + jr nz, .loop_other_card_pop_name_list + xor a + jr .no_carry + +.found_name + ld a, $ff + scf +.no_carry + call DisableSRAM + ld [wCardPopNameSearchResult], a ; $00 if name was not found, $ff otherwise + ret + +; compares names in hl and de +; if they are different, return carry +.CompareNames + ld b, NAME_BUFFER_LENGTH +.loop_chars + ld a, [de] + inc de + cp [hl] + jr nz, .not_same + inc hl + dec b + jr nz, .loop_chars + or a + ret +.not_same + scf + ret +; 0x19d92 + +; loads in wLoadedCard1 a random card to be received +; this selection is done based on the rarity that is +; decided from the names of both participants +; the card will always be a Pokemon card that is not +; from a Promotional set, with the exception +; of Venusaur1 and Mew2 +; output: +; - e = card ID chosen +DecideCardToReceiveFromCardPop: ; 19d92 (6:5d92) + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + call EnableSRAM + ld hl, sPlayerName + call CalculateNameHash + call DisableSRAM + push de + ld hl, wNameBuffer + call CalculateNameHash + pop bc + +; de = other player's name hash +; bc = this player's name hash + +; updates RNG values to subtraction of these two hashes + ld hl, wRNG1 + ld a, b + sub d + ld d, a ; b - d + ld [hli], a ; wRNG1 + ld a, c + sub e + ld e, a ; c - e + ld [hli], a ; wRNG2 + ld [hl], $0 ; wRNGCounter + +; depending on the values obtained from the hashes, +; determine which rarity card to give to the player +; along with the song to play with each rarity +; the probabilites of each possibility can be calculated +; as follows (given 2 random player names): +; 101/256 ~ 39% for Circle +; 90/256 ~ 35% for Diamond +; 63/256 ~ 25% for Star +; 1/256 ~ .4% for Venusaur1 or Mew2 + ld a, e + cp 5 + jr z, .venusaur1_or_mew2 + cp 64 + jr c, .star_rarity ; < 64 + cp 154 + jr c, .diamond_rarity ; < 154 + ; >= 154 + + ld a, MUSIC_BOOSTER_PACK + ld b, CIRCLE + jr .got_rarity +.diamond_rarity + ld a, MUSIC_BOOSTER_PACK + ld b, DIAMOND + jr .got_rarity +.star_rarity + ld a, MUSIC_MATCH_VICTORY + ld b, STAR +.got_rarity + ld [wCardPopCardObtainSong], a + ld a, b + call CreateCardPopCandidateList + ; shuffle candidates and pick first from list + call ShuffleCards + ld a, [hl] + ld e, a +.got_card_id + ld d, $0 + call LoadCardDataToBuffer1_FromCardID + ld a, e + ret + +.venusaur1_or_mew2 +; choose either Venusaur1 or Mew2 +; depending on whether the lower +; bit of d is unset or set, respectively + ld a, MUSIC_MEDAL + ld [wCardPopCardObtainSong], a + ld e, VENUSAUR1 + ld a, d + and $1 ; get lower bit + jr z, .got_card_id + ld e, MEW2 + jr .got_card_id +; 0x19df7 + +; lists in wCardPopCardCandidates all cards that: +; - are Pokemon cards; +; - have the same rarity as input register a; +; - are not from Promotional set. +; input: +; - a = card rarity +; output: +; - a = number of candidates +CreateCardPopCandidateList: ; 19df7 (6:5df7) + ld hl, wPlayerDeck + push hl + push de + push bc + ld b, a + + lb de, 0, GRASS_ENERGY +.loop_card_ids + call LoadCardDataToBuffer1_FromCardID + jr c, .count ; no more card IDs + ld a, [wLoadedCard1Type] + and TYPE_ENERGY + jr nz, .next_card_id ; not Pokemon card + ld a, [wLoadedCard1Rarity] + cp b + jr nz, .next_card_id ; not equal rarity + ld a, [wLoadedCard1Set] + and $f0 + cp PROMOTIONAL + jr z, .next_card_id ; no promos + ld [hl], e + inc hl +.next_card_id + inc de + jr .loop_card_ids + +; count all the cards that were listed +; and return it in a +.count + ld [hl], $00 ; invalid card ID as end of list + ld hl, wPlayerDeck + ld c, -1 +.loop_count + inc c + ld a, [hli] + or a + jr nz, .loop_count + ld a, c + pop bc + pop de + pop hl + ret +; 0x19e32 + +; creates a unique two-byte hash from the name given in hl +; the low byte is calculated by simply adding up all characters +; the high byte is calculated by xoring all characters together +; input: +; - hl = points to the start of the name buffer +; output: +; - de = hash +CalculateNameHash: ; 19e32 (6:5e32) + ld c, NAME_BUFFER_LENGTH + ld de, $0 +.loop + ld a, e + add [hl] + ld e, a + ld a, d + xor [hl] + ld d, a + inc hl + dec c + jr nz, .loop + ret +; 0x19e42 + + INCROM $19e42, $19e5a + +; shows message on screen depending on wPrinterStatus +; also shows SCENE_GAMEBOY_PRINTER_NOT_CONNECTED. +HandlePrinterError: ; 19e5a (6:5e5a) + ld a, [wPrinterStatus] + cp $ff + jr z, .cable_or_printer_switch + or a + jr z, .interrupted + bit PRINTER_ERROR_BATTERIES_LOST_CHARGE, a + jr nz, .batteries_lost_charge + bit PRINTER_ERROR_CABLE_PRINTER_SWITCH, a + jr nz, .cable_or_printer_switch + bit PRINTER_ERROR_PAPER_JAMMED, a + jr nz, .jammed_printer + + ldtx hl, PrinterPacketErrorText + ld a, $04 + jr .got_text +.cable_or_printer_switch + ldtx hl, CheckCableOrPrinterSwitchText + ld a, $02 + jr .got_text +.jammed_printer + ldtx hl, PrinterPaperIsJammedText + ld a, $03 + jr .got_text +.batteries_lost_charge + ldtx hl, BatteriesHaveLostTheirChargeText + ld a, $01 + jr .got_text +.interrupted + ldtx hl, PrintingWasInterruptedText + call DrawWideTextBox_WaitForInput + scf + ret + + ldtx hl, PrinterIsNotConnectedText + ld a, $02 +.got_text + push hl + ; unnecessary loading TxRam, since the text data + ; already incorporate the error number + ld l, a + ld h, $00 + call LoadTxRam3 + + call Func_198e7 + ld a, SCENE_GAMEBOY_PRINTER_NOT_CONNECTED + lb bc, 0, 0 + call LoadScene + pop hl + call DrawWideTextBox_WaitForInput + call Func_19907 + scf + ret +; 0x19eb4 + +; main card printer function +Func_19eb4: ; 19eb4 (6:5eb4) + ld e, a + ld d, $0 + call LoadCardDataToBuffer1_FromCardID + call Func_198e7 + ld a, SCENE_GAMEBOY_PRINTER_TRANSMITTING + lb bc, 0, 0 + call LoadScene + ld a, 20 + call CopyCardNameAndLevel + ld [hl], TX_END + ld hl, $0 + call LoadTxRam2 + ldtx hl, NowPrintingText + call DrawWideTextBox_PrintText + call EnableLCD + call Func_1a035 + call DrawTopCardInfoInSRAMGfxBuffer0 + call Func_19f87 + call DrawCardPicInSRAMGfxBuffer2 + call Func_19f99 + jr c, .error + call DrawBottomCardInfoInSRAMGfxBuffer0 + call Func_1a011 + jr c, .error + call Func_19907 + call Func_1a06b + or a + ret +.error + call Func_19907 + call Func_1a06b + jp HandlePrinterError +; 0x19f05 + +DrawCardPicInSRAMGfxBuffer2: ; 19f05 (6:5f05) + ld hl, wLoadedCard1Gfx + ld a, [hli] + ld h, [hl] + ld l, a + ld de, sGfxBuffer2 + call Func_37a5 + ; draw card's picture in sGfxBuffer2 + ld a, $40 + lb hl, 12, 1 + lb de, 2, 68 + lb bc, 16, 12 + call FillRectangle + ret +; 0x19f20 + +; writes the tiles necessary to draw +; the card's information in sGfxBuffer0 +; this includes card's type, lv, HP and attacks if Pokemon card +; or otherwise just the card's name and type symbol +DrawTopCardInfoInSRAMGfxBuffer0: ; 19f20 (6:5f20) + call Func_1a025 + call Func_212f + + ; draw empty text box frame + ld hl, sGfxBuffer0 + ld a, $34 + lb de, $30, $31 + ld b, 20 + call CopyLine + ld c, 15 +.loop_lines + xor a ; SYM_SPACE + lb de, $36, $37 + ld b, 20 + call CopyLine + dec c + jr nz, .loop_lines + + ; draw card type symbol + ld a, $38 + lb hl, 1, 2 + lb de, 1, 65 + lb bc, 2, 2 + call FillRectangle + ; print card's name + lb de, 4, 65 + ld hl, wLoadedCard1Name + call InitTextPrinting_ProcessTextFromPointerToID + +; prints card's type, lv, HP and attacks if it's a Pokemon card + ld a, [wLoadedCard1Type] + cp TYPE_ENERGY + jr nc, .skip_pokemon_data + inc a ; symbol corresponding to card's type (color) + lb bc, 18, 65 + call WriteByteToBGMap0 + ld a, SYM_Lv + lb bc, 11, 66 + call WriteByteToBGMap0 + ld a, [wLoadedCard1Level] + lb bc, 12, 66 + bank1call WriteTwoDigitNumberInTxSymbolFormat + ld a, SYM_HP + lb bc, 15, 66 + call WriteByteToBGMap0 + ld a, [wLoadedCard1EffectCommands] + inc b + bank1call WriteTwoByteNumberInTxSymbolFormat +.skip_pokemon_data + ret +; 0x19f87 + +Func_19f87: ; 19f87 (6:5f87) + call Func_1a089 + ret c + ld hl, sGfxBuffer0 + call Func_1a0cc + ret c + call Func_1a0cc + call Func_1a111 + ret +; 0x19f99 + +Func_19f99: ; 19f99 (6:5f99) + call Func_1a089 + ret c + ld hl, sGfxBuffer0 + $8 tiles + ld c, $06 +.asm_19fa2 + call Func_1a0cc + ret c + dec c + jr nz, .asm_19fa2 + call Func_1a111 + ret +; 0x19fad + +; writes the tiles necessary to draw +; the card's information in sGfxBuffer0 +; this includes card's Retreat cost, Weakness, Resistance, +; and attack if it's Pokemon card +; or otherwise just the card's description. +DrawBottomCardInfoInSRAMGfxBuffer0: ; 19fad (6:5fad) + call Func_1a025 + xor a + ld [wCardPageType], a + ld hl, sGfxBuffer0 + ld b, 20 + ld c, 9 +.loop_lines + xor a ; SYM_SPACE + lb de, $36, $37 + call CopyLine + dec c + jr nz, .loop_lines + ld a, $35 + lb de, $32, $33 + call CopyLine + + ld a, [wLoadedCard1Type] + cp TYPE_ENERGY + jr nc, .not_pkmn_card + ld hl, RetreatWeakResistData + call PlaceTextItems + ld c, 66 + bank1call DisplayCardPage_PokemonOverview.attacks + ld a, SYM_No + lb bc, 15, 72 + call WriteByteToBGMap0 + inc b + ld a, [wLoadedCard1PokedexNumber] + bank1call WriteTwoByteNumberInTxSymbolFormat + ret + +.not_pkmn_card + bank1call SetNoLineSeparation + lb de, 1, 66 + ld a, SYM_No + call InitTextPrintingInTextbox + ld hl, wLoadedCard1NonPokemonDescription + call ProcessTextFromPointerToID + bank1call SetOneLineSeparation + ret +; 0x1a004 + +RetreatWeakResistData: ; 1a004 (6:6004) + textitem 1, 70, RetreatText + textitem 1, 71, WeaknessText + textitem 1, 72, ResistanceText + db $ff +; 0x1a011 + +Func_1a011: ; 1a011 (6:6011) + call Func_1a089 + ret c + ld hl, sGfxBuffer0 + ld c, $05 +.asm_1a01a + call Func_1a0cc + ret c + dec c + jr nz, .asm_1a01a + call Func_1a108 + ret +; 0x1a025 + +; calls setup text and sets wTilePatternSelector +Func_1a025: ; 1a025 (6:6025) + lb de, $40, $bf + call SetupText + ld a, $a4 + ld [wTilePatternSelector], a + xor a + ld [wTilePatternSelectorCorrection], a + ret +; 0x1a035 + +; switches to CGB normal speed, resets serial +; enables SRAM and switches to SRAM1 +; and clears sGfxBuffer0 +Func_1a035: ; 1a035 (6:6035) + call SwitchToCGBNormalSpeed + call ResetSerial + ld a, $10 + ld [wce9b], a + call EnableSRAM + ld a, [s0a003] + ld [wce99], a + call DisableSRAM + ldh a, [hBankSRAM] + ld [wce8f], a + ld a, BANK("SRAM1") + call BankswitchSRAM + call EnableSRAM + ; clear sGfxBuffer0 + ld hl, sGfxBuffer0 + ld bc, $400 +.loop + xor a + ld [hli], a + dec bc + ld a, c + or b + jr nz, .loop + xor a + ld [wce9f], a + ret +; 0x1a06b + +Func_1a06b: ; 1a06b (6:606b) + push af + call SwitchToCGBDoubleSpeed + ld a, [wce8f] + call BankswitchSRAM + call DisableSRAM + lb de, $30, $bf + call SetupText + pop af + ret +; 0x1a080 + + INCROM $1a080, $1a089 + +; returns carry if operation was cancelled +; or serial transfer took long +Func_1a089: ; 1a089 (6:6089) + xor a + ld [wce9e], a +.wait_input + call DoFrame + ldh a, [hKeysHeld] + and B_BUTTON + jr nz, .b_button + ld bc, $0 + ld de, $f00 + call Func_312d + jr c, .delay + and $0a + jr nz, .wait_input + +.asm_1a0a5 + ld bc, $0 + ld de, $100 + call Func_312d + jr nc, .no_carry + ld hl, wce9e + inc [hl] + ld a, [hl] + cp 3 + jr c, .wait_input + ; time out + scf + ret +.no_carry + ret + +.b_button + xor a + ld [wPrinterStatus], a + scf + ret + +.delay + ld c, 10 +.delay_loop + call DoFrame + dec c + jr nz, .delay_loop + jr .asm_1a0a5 +; 0x1a0cc + +; loads tiles given by map in hl to sGfxBuffer5 +; copies first 20 tiles, then offsets by 2 tiles +; and copies another 20 +Func_1a0cc: ; 1a0cc (6:60cc) + push bc + ld de, sGfxBuffer5 + call .Copy20Tiles + call .Copy20Tiles + push hl + call CompressDataForSerialTransfer + call Func_312d + pop hl + pop bc + ret + +; copies 20 tiles given by hl to de +; then adds 2 tiles to hl +.Copy20Tiles ; 1a0e0 (6:60e0) + push hl + ld c, 20 +.loop_tiles + ld a, [hli] + call .CopyTile + dec c + jr nz, .loop_tiles + pop hl + ld bc, 2 tiles + add hl, bc + ret + +; copies a tile to de +; a = tile to get from sGfxBuffer1 +.CopyTile ; 1a0f0 (6:60f0) + push hl + push bc + ld l, a + ld h, $00 + add hl, hl + add hl, hl + add hl, hl + add hl, hl ; *TILE_SIZE + ld bc, sGfxBuffer1 + add hl, bc + ld c, TILE_SIZE +.loop_copy + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .loop_copy + pop bc + pop hl + ret +; 0x1a108 + +Func_1a108: ; 1a108 (6:6108) + call Func_1a138 + push hl + ld hl, $301 + jr Func_1a11e + +Func_1a111: ; 1a111 (6:6111) + call Func_1a138 + push hl + ld hl, wce9b + ld a, [hl] + ld [hl], $00 + ld h, a + ld l, $01 +; fallthrough + +Func_1a11e: ; 1a11e (6:611e) + push hl + ld bc, $0 + ld de, $400 + call Func_312d + jr c, .asm_1a135 + ld hl, sp+$00 + ld bc, $4 + ld de, $200 + call Func_312d +.asm_1a135 + pop hl + pop hl + ret + +Func_1a138: ; 1a138 (6:6138) + ld a, [wce99] + ld e, a + ld d, $00 + ld hl, .unknown_1a146 + add hl, de + ld h, [hl] + ld l, $e4 + ret + +.unknown_1a146 + db $00, $20, $40, $60 +; 0x1a14a + + INCROM $1a14a, $1a435 + +; compresses $28 tiles in sGfxBuffer5 +; and writes it in sGfxBuffer5 + $28 tiles. +; compressed data has 2 commands to instruct on how to decompress it. +; - a command byte with bit 7 not set, means to copy that many + 1 +; bytes that are following it literally. +; - a command byte with bit 7 set, means to copy the following byte +; that many times + 2 (after masking the top bit of command byte). +; returns in bc the size of the compressed data and +; in de the address of where it starts. +CompressDataForSerialTransfer: ; 1a435 (6:6435) + ld hl, sGfxBuffer5 + ld de, sGfxBuffer5 + $28 tiles + ld bc, $28 tiles +.loop_remaining_data + ld a, $ff + inc b + dec b + jr nz, .check_compression + ld a, c +.check_compression + push bc + push de + ld c, a + call CheckDataCompression + ld a, e + ld c, e + pop de + jr c, .copy_byte + ld a, c + ld b, c + dec a + ld [de], a ; number of bytes to copy literally - 1 + inc de +.copy_literal_sequence + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .copy_literal_sequence + ld c, b + jr .sub_added_bytes + +.copy_byte + ld a, c + dec a + dec a + or %10000000 ; set high bit + ld [de], a ; = (n times to copy - 2) | %10000000 + inc de + ld a, [hl] ; byte to copy n times + ld [de], a + inc de + ld b, $0 + add hl, bc + +.sub_added_bytes + ld a, c + cpl + inc a + pop bc + add c + ld c, a + ld a, $ff + adc b + ld b, a + or c + jr nz, .loop_remaining_data + + ld hl, $10000 - (sGfxBuffer5 + $28 tiles) + add hl, de ; gets the size of the compressed data + ld c, l + ld b, h + ld hl, sGfxBuffer5 + $28 tiles + ld de, $401 + ret +; 0x1a485 + +; checks whether the next byte sequence in hl, up to c bytes, can be compressed +; returns carry if the next sequence of bytes can be compressed, +; i.e. has at least 3 consecutive bytes with the same value. +; in that case, returns in e the number of consecutive +; same value bytes that were found. +; if there are no bytes with same value, then count as many bytes left +; as possible until either there are no more remaining data bytes, +; or until a sequence of 3 bytes with the same value are found. +; in that case, the number of bytes in this sequence is returned in e. +CheckDataCompression: ; 1a485 (6:6485) + push hl + ld e, c + ld a, c +; if number of remaining bytes is less than 4 +; then no point in compressing + cp 4 + jr c, .no_carry + +; check first if there are at least +; 3 consecutive bytes with the same value + ld b, c + ld a, [hli] + cp [hl] + inc hl + jr nz, .literal_copy ; not same + cp [hl] + inc hl + jr nz, .literal_copy ; not same + +; 3 consecutive bytes were found with same value +; keep track of how many consecutive bytes +; with the same value there are in e + dec c + dec c + dec c + ld e, 3 +.loop_same_value + cp [hl] + jr nz, .set_carry ; exit when a different byte is found + inc hl + inc e + dec c + jr z, .set_carry ; exit when there is no more remaining data + bit 5, e + ; exit if number of consecutive bytes >= $20 + jr z, .loop_same_value +.set_carry + pop hl + scf + ret + +.literal_copy +; consecutive bytes are not the same value +; count the number of bytes there are left +; until a sequence of 3 bytes with the same value is found + pop hl + push hl + ld c, b ; number of remaining bytes + ld e, 1 + ld a, [hli] + dec c + jr z, .no_carry ; exit if no more data +.reset_same_value_count + ld d, 2 ; number of consecutive same value bytes to exit +.next_byte + inc e + dec c + jr z, .no_carry + bit 7, e + jr nz, .no_carry ; exit if >= $80 + cp [hl] + jr z, .same_consecutive_value + ld a, [hli] + jr .reset_same_value_count +.no_carry + pop hl + or a + ret + +.same_consecutive_value + inc hl + dec d + jr nz, .next_byte + ; 3 consecutive bytes with same value found + ; discard the last 3 bytes in the sequence + dec e + dec e + dec e + jr .no_carry +; 0x1a4cf Func_1a4cf: ; 1a4cf (6:64cf) INCROM $1a4cf, $1a61f diff --git a/src/engine/bank20.asm b/src/engine/bank20.asm index 951a699..daf4004 100644 --- a/src/engine/bank20.asm +++ b/src/engine/bank20.asm @@ -256,7 +256,7 @@ Func_80148: ; 80148 (20:4148) ; to either VRAM or SRAM, depending on wWriteBGMapToSRAM ; de is the target address in VRAM, ; if SRAM is the target address to copy, -; copies data to sBGMap0 or sBGMap1 +; copies data to sGfxBuffer0 or sGfxBuffer1 ; for VRAM0 or VRAM1 respectively CopyBGDataToVRAMOrSRAM: ; 8016e (20:416e) ld a, [wWriteBGMapToSRAM] @@ -272,11 +272,11 @@ CopyBGDataToVRAMOrSRAM: ; 8016e (20:416e) ld a, BANK("SRAM1") call BankswitchSRAM push hl - ld hl, sBGMap0 - v0BGMap0 + ld hl, sGfxBuffer0 - v0BGMap0 ldh a, [hBankVRAM] or a jr z, .got_pointer - ld hl, sBGMap1 - v1BGMap0 + ld hl, sGfxBuffer1 - v1BGMap0 .got_pointer add hl, de ld e, l @@ -297,8 +297,8 @@ CopyBGDataToVRAMOrSRAM: ; 8016e (20:416e) ret ; safely copies $20 bytes at a time -; sBGMap0 -> v0BGMap0 -; sBGMap1 -> v0BGMap1 (if in CGB) +; sGfxBuffer0 -> v0BGMap0 +; sGfxBuffer1 -> v0BGMap1 (if in CGB) SafelyCopyBGMapFromSRAMToVRAM: ; 801a1 (20:41a1) push hl push bc @@ -307,7 +307,7 @@ SafelyCopyBGMapFromSRAMToVRAM: ; 801a1 (20:41a1) push af ld a, BANK("SRAM1") call BankswitchSRAM - ld hl, sBGMap0 + ld hl, sGfxBuffer0 ld de, v0BGMap0 ld c, $20 .loop @@ -323,7 +323,7 @@ SafelyCopyBGMapFromSRAMToVRAM: ; 801a1 (20:41a1) pop hl push hl push de - ld bc, sBGMap1 - sBGMap0 ; $400 + ld bc, sGfxBuffer1 - sGfxBuffer0 ; $400 add hl, bc call BankswitchVRAM1 ld b, $20 @@ -350,16 +350,16 @@ SafelyCopyBGMapFromSRAMToVRAM: ; 801a1 (20:41a1) pop hl ret -; clears sBGMap0 and sBGMap1 +; clears sGfxBuffer0 and sGfxBuffer1 ClearSRAMBGMaps: ; 801f1 (20:41f1) push hl push bc ldh a, [hBankSRAM] push af - ld a, BANK(sBGMap0) ; SRAM 1 + ld a, BANK(sGfxBuffer0) ; SRAM 1 call BankswitchSRAM - ld hl, sBGMap0 - ld bc, $800 ; sBGMap0 + sBGMap1 + ld hl, sGfxBuffer0 + ld bc, $800 ; sGfxBuffer0 + sGfxBuffer1 xor a call FillMemoryWithA pop af diff --git a/src/engine/home.asm b/src/engine/home.asm index 0651e8d..621afd4 100644 --- a/src/engine/home.asm +++ b/src/engine/home.asm @@ -2310,7 +2310,7 @@ SerialTimerHandler: ; 0c91 (0:0c91) ld [hl], $0 ret -Func_0cc5: ; 0cc5 (0:0cc5) +Func_cc5: ; 0cc5 (0:0cc5) ld hl, wSerialRecvCounter or a jr nz, .asm_cdc @@ -6267,13 +6267,15 @@ CopyFontsOrDuelGraphicsTiles: ; 2121 (0:2121) ; this function copies gfx data into sram Func_212f: ; 212f (0:212f) +; loads symbols fonts to sGfxBuffer1 ld hl, SymbolsFont - $4000 - ld de, $a400 + ld de, sGfxBuffer1 ld b, $30 call CopyFontsOrDuelGraphicsTiles - ld hl, DuelOtherGraphics + $150 - ld de, $a700 - ld b, $08 +; text box frame tiles + ld hl, DuelOtherGraphics + $15 tiles + ld de, sGfxBuffer1 + $30 tiles + ld b, $8 call CopyFontsOrDuelGraphicsTiles call GetCardSymbolData sub $d0 @@ -6282,14 +6284,14 @@ Func_212f: ; 212f (0:212f) add hl, hl add hl, hl add hl, hl - add hl, hl + add hl, hl ; *16 ld de, DuelDmgSgbSymbolGraphics - $4000 add hl, de - ld de, $a780 - ld b, $04 + ld de, sGfxBuffer1 + $38 tiles + ld b, $4 call CopyFontsOrDuelGraphicsTiles ld hl, DuelDmgSgbSymbolGraphics - $4000 - ld de, $b100 + ld de, sGfxBuffer4 + $10 tiles ld b, $30 jr CopyFontsOrDuelGraphicsTiles @@ -9393,7 +9395,7 @@ Func_312d: ; 312d (0:312d) ld a, [wce6e] cp $81 jr nz, .asm_3182 - ld a, [wce6f] + ld a, [wPrinterStatus] ld l, a and $f1 ld a, l @@ -9402,7 +9404,7 @@ Func_312d: ; 312d (0:312d) ret .asm_3182 ld a, $ff - ld [wce6f], a + ld [wPrinterStatus], a scf ret @@ -9484,7 +9486,7 @@ Func_31ef: ; 31ef (0:31ef) Func_31f2: ; 31f2 (0:31f2) ldh a, [rSB] - ld [wce6f], a + ld [wPrinterStatus], a xor a ld [wce63], a ret @@ -10973,8 +10975,10 @@ Func_3a45: ; 3a45 (0:3a45) farcall Func_11343 ret -Func_3a4a: ; 3a4a (0:3a4a) - farcall Func_115a3 +; adds card with card ID in register a to collection +; and updates album progress in RAM +AddCardToCollectionAndUpdateAlbumProgress: ; 3a4a (0:3a4a) + farcall _AddCardToCollectionAndUpdateAlbumProgress ret SaveGame: ; 3a4f (0:3a4f) diff --git a/src/sram.asm b/src/sram.asm index dfcf9c9..481c8e4 100644 --- a/src/sram.asm +++ b/src/sram.asm @@ -7,8 +7,12 @@ s0a003:: ; a003 ds $1 s0a004:: ; a004 ds $1 -s0a005:: ; a005 + +; keeps track of the number of times Card Pop! +; was done successfully within this save file +sTotalCardPopsDone:: ; a005 ds $1 + sTextSpeed:: ; a006 ds $1 @@ -197,16 +201,47 @@ sba57:: ; ba57 sba68:: ; ba68 ds $1 + ds $97 + +; keeps track of last 16 player's names that +; this save file has done Card Pop! with +sCardPopNameList:: ; bb00 + ds CARDPOP_NAME_LIST_SIZE + SECTION "SRAM1", SRAM -; from VRAM0 -sBGMap0:: ds $400 ; a000 -; from VRAM1 -sBGMap1:: ds $400 ; a400 +; buffers used to temporary store gfx related data +; such as tiles or BG maps +sGfxBuffer0:: ; a000 + ds $400 + +sGfxBuffer1:: ; a400 + ds $400 + +sGfxBuffer2:: ; a800 + ds $400 + +sGfxBuffer3:: ; ac00 + ds $400 + +sGfxBuffer4:: ; b000 + ds $400 + +sGfxBuffer5:: ; b400 + ds $400 SECTION "SRAM2", SRAM - ds $1c00 + ds $18fe + +; byte 1 = total number of cards collected +; byte 2 = total number of cards to collect +; (doesn't count Phantom cards unless they +; have been collected already) +sAlbumProgress:: ; b8fe + ds $2 + + ds $300 ; saved data of the current duel, including a two-byte checksum ; see SaveDuelDataToDE diff --git a/src/text/text1.asm b/src/text/text1.asm index e94cb49..2b683d8 100644 --- a/src/text/text1.asm +++ b/src/text/text1.asm @@ -1002,36 +1002,36 @@ BackUpIsBrokenText: ; 37a59 (d:7a59) text "Back Up is broken." done -Text00d7: ; 37a6d (d:7a6d) +PrinterIsNotConnectedText: ; 37a6d (d:7a6d) text "Error No. 02:" line "Printer is not connected." done -Text00d8: ; 37a96 (d:7a96) +BatteriesHaveLostTheirChargeText: ; 37a96 (d:7a96) text "Error No. 01:" line "Batteries have lost their charge." done -Text00d9: ; 37ac7 (d:7ac7) +PrinterPaperIsJammedText: ; 37ac7 (d:7ac7) text "Error No. 03:" line "Printer paper is jammed." done -Text00da: ; 37aef (d:7aef) +CheckCableOrPrinterSwitchText: ; 37aef (d:7aef) text "Error No. 02:" line "Check cable or printer switch." done -Text00db: ; 37b1d (d:7b1d) +PrinterPacketErrorText: ; 37b1d (d:7b1d) text "Error No. 04:" line "Printer Packet Error." done -Text00dc: ; 37b42 (d:7b42) +PrintingWasInterruptedText: ; 37b42 (d:7b42) text "Printing was interrupted." done -Text00dd: ; 37b5d (d:7b5d) +CardPopCannotBePlayedWithTheGameBoyText: ; 37b5d (d:7b5d) text "Card Pop! cannot be played" line "with the Game Boy." line "Please use a" diff --git a/src/text/text2.asm b/src/text/text2.asm index 3da7115..55a08b4 100644 --- a/src/text/text2.asm +++ b/src/text/text2.asm @@ -784,27 +784,27 @@ Text0189: ; 39d1b (e:5d1b) line "with <RAMNAME>." done -Text018a: ; 39d39 (e:5d39) +AreYouBothReadyToCardPopText: ; 39d39 (e:5d39) text "Are you both ready" line "to Card Pop! ?" done -Text018b: ; 39d5c (e:5d5c) +ThePopWasntSuccessfulText: ; 39d5c (e:5d5c) text "The Pop! wasn't successful." line "Please try again." done -Text018c: ; 39d8b (e:5d8b) +CannotCardPopWithFriendPreviouslyPoppedWithText: ; 39d8b (e:5d8b) text "You cannot Card Pop! with a" line "friend you previously Popped! with." done -Text018d: ; 39dcc (e:5dcc) +PositionGameBoyColorsAndPressAButtonText: ; 39dcc (e:5dcc) text "Position the Game Boy Colors" line "and press the A Button." done -Text018e: ; 39e02 (e:5e02) +ReceivedThroughCardPopText: ; 39e02 (e:5e02) text "Received <RAMTEXT>" line "through Card Pop!" done @@ -898,7 +898,7 @@ Text01a1: ; 3a0e1 (e:60e1) line "wasn't successful." done -Text01a2: ; 3a111 (e:6111) +NowPrintingText: ; 3a111 (e:6111) text "Now printing..." done diff --git a/src/text/text_offsets.asm b/src/text/text_offsets.asm index a62e8e7..f37c395 100644 --- a/src/text/text_offsets.asm +++ b/src/text/text_offsets.asm @@ -216,13 +216,13 @@ TextOffsets:: ; 34000 (d:4000) textpointer UnableDueToToxicGasText ; 0x00d4 textpointer Text00d5 ; 0x00d5 textpointer BackUpIsBrokenText ; 0x00d6 - textpointer Text00d7 ; 0x00d7 - textpointer Text00d8 ; 0x00d8 - textpointer Text00d9 ; 0x00d9 - textpointer Text00da ; 0x00da - textpointer Text00db ; 0x00db - textpointer Text00dc ; 0x00dc - textpointer Text00dd ; 0x00dd + textpointer PrinterIsNotConnectedText ; 0x00d7 + textpointer BatteriesHaveLostTheirChargeText ; 0x00d8 + textpointer PrinterPaperIsJammedText ; 0x00d9 + textpointer CheckCableOrPrinterSwitchText ; 0x00da + textpointer PrinterPacketErrorText ; 0x00db + textpointer PrintingWasInterruptedText ; 0x00dc + textpointer CardPopCannotBePlayedWithTheGameBoyText ; 0x00dd textpointer SandAttackCheckText ; 0x00de textpointer SmokescreenCheckText ; 0x00df textpointer ParalysisCheckText ; 0x00e0 @@ -395,11 +395,11 @@ TextOffsets:: ; 34000 (d:4000) textpointer Text0187 ; 0x0187 textpointer Text0188 ; 0x0188 textpointer Text0189 ; 0x0189 - textpointer Text018a ; 0x018a - textpointer Text018b ; 0x018b - textpointer Text018c ; 0x018c - textpointer Text018d ; 0x018d - textpointer Text018e ; 0x018e + textpointer AreYouBothReadyToCardPopText ; 0x018a + textpointer ThePopWasntSuccessfulText ; 0x018b + textpointer CannotCardPopWithFriendPreviouslyPoppedWithText ; 0x018c + textpointer PositionGameBoyColorsAndPressAButtonText ; 0x018d + textpointer ReceivedThroughCardPopText ; 0x018e textpointer ReceivedCardText ; 0x018f textpointer ReceivedPromotionalCardText ; 0x0190 textpointer ReceivedLegendaryCardText ; 0x0191 @@ -419,7 +419,7 @@ TextOffsets:: ; 34000 (d:4000) textpointer Text019f ; 0x019f textpointer Text01a0 ; 0x01a0 textpointer Text01a1 ; 0x01a1 - textpointer Text01a2 ; 0x01a2 + textpointer NowPrintingText ; 0x01a2 textpointer DrMasonText ; 0x01a3 textpointer DrawSevenCardsPracticeDuelText ; 0x01a4 textpointer ChooseGoldeenPracticeDuelText ; 0x01a5 diff --git a/src/wram.asm b/src/wram.asm index 9a6dffb..40388ec 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -31,12 +31,22 @@ wDecompressionSecondaryBuffer:: ; c000 wDecompressionSecondaryBufferStart:: ; c0ef ds $11 +NEXTU + +; names of the last players who have done +; Card Pop! with current save file +wCardPopNameList:: ; c000 + ds CARDPOP_NAME_LIST_SIZE + ENDU ds $100 SECTION "WRAM0 Duels 1", WRAM0 +; this union spans from c200 to c3ff +UNION + ; In order to be identified during a duel, the 60 cards of each duelist are given an index between 0 and 59. ; These indexes are assigned following the order of the card list in wPlayerDeck or wOpponentDeck, ; which, in turn, follows the internal order of the cards. @@ -387,6 +397,15 @@ wOpponentArenaCardLastTurnEffect:: ; c3f8 ds $7 +NEXTU + +; buffer used to store the Card Pop! name list +; that is received from the other player +wOtherPlayerCardPopNameList:: ; c200 + ds CARDPOP_NAME_LIST_SIZE + +ENDU + UNION ; temporary list of the cards drawn from a booster pack @@ -403,6 +422,13 @@ NEXTU wPlayerDeck:: ; c400 ds $80 +NEXTU + +; lists all the possible candidates of cards +; that can be received through Card Pop! +wCardPopCardCandidates:: ; c400 + ds $80 + ENDU wOpponentDeck:: ; c480 @@ -423,7 +449,28 @@ wDefaultText:: ; c590 ds $2 wc592:: ; c592 - ds $6e + ds $3 + + ds $55 + +wc5ea:: ; c5ea + ds $1 + +; related with wc5ef for Card Pop! communications +wc5eb:: ; c5eb + ds $4 + +; related with wc5eb for Card Pop! communications +wc5ef:: ; c5ef + ds $4 + +; stores the result from LookUpNameInCardPopNameList +; is $ff if name was found in the Card Pop! list +; is $00 otherwise +wCardPopNameSearchResult:: ; c5f3 + ds $1 + + ds $c SECTION "WRAM0 Text Engine", WRAM0 @@ -1745,7 +1792,7 @@ wce6d:: ; ce6d wce6e:: ; ce6e ds $1 -wce6f:: ; ce6f +wPrinterStatus:: ; ce6f ds $1 wce70:: ; ce70 @@ -1793,7 +1840,39 @@ wce83:: ; ce83 wce84:: ; ce84 ds $1 - ds $1c +; buffer to store data that will be sent/received through IR +wIRDataBuffer:: ; ce85 + ds $8 + +wVBlankFunctionTrampolineBackup:: ; ce8d + ds $2 + +wce8f:: ; ce8f + ds $1 + + ds $9 + +wce99:: ; ce99 + ds $1 + +wce9a:: ; ce9a + ds $1 + +wce9b:: ; ce9b + ds $1 + + ds $2 + +wce9e:: ; ce9e + ds $1 + +wce9f:: ; ce9f + ds $1 + +; which song to play when obtaining the card from Card Pop! +; the card's rarity determines which song to play +wCardPopCardObtainSong:: ; cea0 + ds $1 wcea1:: ; cea1 ds $1 @@ -2404,7 +2483,18 @@ wd3cb:: ; d3cb wd3cc:: ; d3cc ds $1 - ds $3 +; total number of cards the player has collected +wTotalNumCardsCollected:: ; d3cd + ds $1 + +; total number of cards to be collected +; doesn't count the Phantom cards (Venusaur1 and Mew2) +; unless they have already been collected +wTotalNumCardsToCollect:: ; d3ce + ds $1 + +wCardToAddToCollection:: ; d3cf + ds $1 wd3d0:: ; d3d0 ds $1 diff --git a/tools/tcgdisasm.py b/tools/tcgdisasm.py index 95db628..4cf162d 100644 --- a/tools/tcgdisasm.py +++ b/tools/tcgdisasm.py @@ -308,7 +308,7 @@ unconditional_returns = [0xc9, 0xd9, 0xe7] # e7 begins a script, which is not ha absolute_jumps = [0xc3, 0xc2, 0xca, 0xd2, 0xda] call_commands = [0xcd, 0xc4, 0xcc, 0xd4, 0xdc, 0xdf, 0xef] relative_jumps = [0x18, 0x20, 0x28, 0x30, 0x38] -unconditional_jumps = [0xc3, 0x18] +unconditional_jumps = [0xc3, 0x18, 0xe9] # the event macros found in bank 3. They db a byte after calling so need to be treated specially event_macros = [(0xca8f,"set_event_value {}"),(0xcacd,"set_event_false {}"),(0xca84,"set_event_zero {}"), (0xcac2,"max_event_value {}"), (0xca69,"get_event_value {}")] |