Fix a symbol/data mismatch in wLinkPlayer* and mailmsg (#198)
Some checks failed
CI / build (push) Has been cancelled
CI / build-macos (push) Has been cancelled

This commit is contained in:
Alieneer
2026-08-18 16:06:51 -04:00
committed by GitHub
parent 6ec32bffb6
commit 2e413fafb1
3 changed files with 232 additions and 87 deletions

View File

@@ -42,7 +42,10 @@ DEF SERIAL_RN_PREAMBLE_LENGTH EQU 7
DEF SERIAL_PATCH_PREAMBLE_LENGTH EQU 3
DEF SERIAL_RNS_LENGTH EQU 10
DEF SERIAL_PADDING_LENGTH EQU 3
DEF SERIAL_MAIL_PREAMBLE_BYTE EQU $20
DEF SERIAL_MAIL_PREAMBLE_LENGTH EQU 5
DEF SERIAL_MAIL_DATA_END EQU $21
; used to replace SERIAL_NO_DATA_BYTE
DEF SERIAL_MAIL_REPLACEMENT_BYTE EQU $21
DEF SERIAL_MAIL_REPLACEMENT_BYTE EQU $22

View File

@@ -68,15 +68,15 @@ Gen2ToGen1LinkComms:
ld a, IE_SERIAL
ldh [rIE], a
ld hl, wLinkBattleRNPreamble
ld de, wEnemyMon
ld de, wOTLinkBattleRNData
ld bc, SERIAL_RN_PREAMBLE_LENGTH + SERIAL_RNS_LENGTH
call Serial_ExchangeBytes
ld a, SERIAL_NO_DATA_BYTE
ld [de], a
ld hl, wLinkData
ld de, wOTPlayerName
ld bc, PLAYER_NAME_LENGTH + (1 + PARTY_LENGTH + 1) + (REDMON_STRUCT_LENGTH + PLAYER_NAME_LENGTH * 2) * PARTY_LENGTH + 3
ld hl, wLinkSendTimeCapsuleParty
ld de, wLinkReceivedPartyData
ld bc, wLinkSendTimeCapsulePartyEnd - wLinkSendTimeCapsuleParty
call Serial_ExchangeBytes
ld a, SERIAL_NO_DATA_BYTE
ld [de], a
@@ -91,16 +91,16 @@ Gen2ToGen1LinkComms:
ld de, MUSIC_NONE
call PlayMusic
call Link_CopyRandomNumbers
ld hl, wOTPlayerName
ld hl, wLinkReceivedPartyData
call Link_FindFirstNonControlCharacter_SkipZero
ld de, wLinkData
ld bc, PLAYER_NAME_LENGTH + (1 + PARTY_LENGTH + 1) + (REDMON_STRUCT_LENGTH + PLAYER_NAME_LENGTH * 2) * PARTY_LENGTH + 3
ld de, wLinkTimeCapsulePartyData
ld bc, wLinkTimeCapsulePartyDataEnd - wLinkTimeCapsulePartyData
call Link_CopyOTData
ld de, wPlayerTrademon
ld hl, wLinkPlayerData
ld c, $02
ld de, wOTPatchLists
ld hl, wTimeCapsulePatchedData
ld c, 2 ; number of patch lists
.loop
ld a, [de]
@@ -112,7 +112,7 @@ Gen2ToGen1LinkComms:
cp SERIAL_NO_DATA_BYTE
jr z, .loop
cp SERIAL_PATCH_LIST_PART_TERMINATOR
jr z, .next
jr z, .next_patch_list
push hl
push bc
ld b, 0
@@ -125,12 +125,12 @@ Gen2ToGen1LinkComms:
pop hl
jr .loop
.next
.next_patch_list
ld hl, wLinkPlayerData + SERIAL_PATCH_DATA_SIZE
dec c
jr nz, .loop
ld hl, wLinkData
ld hl, wLinkTimeCapsulePlayerName
ld de, wOTPlayerName
ld bc, PLAYER_NAME_LENGTH
call CopyBytes
@@ -140,10 +140,10 @@ Gen2ToGen1LinkComms:
ld [de], a
inc de
.party_loop
.species_loop
ld a, [hli]
cp -1
jr z, .done_party
jr z, .convert_party_struct
ld [wTempByteValue], a
push hl
push de
@@ -153,9 +153,9 @@ Gen2ToGen1LinkComms:
ld a, [wTempByteValue]
ld [de], a
inc de
jr .party_loop
jr .species_loop
.done_party:
.convert_party_struct:
ld [de], a
ld hl, wLinkPlayerData
call Link_ConvertPartyStruct1to2
@@ -221,15 +221,15 @@ Gen2ToGen2LinkComms:
ldh [rIE], a
ld hl, wLinkBattleRNPreamble
ld de, wEnemyMon
ld de, wOTLinkBattleRNData
ld bc, SERIAL_RN_PREAMBLE_LENGTH + SERIAL_RNS_LENGTH
call Serial_ExchangeBytes
ld a, SERIAL_NO_DATA_BYTE
ld [de], a
ld hl, wLinkData
ld hl, wLinkSendParty
ld de, wOTPlayerName
ld bc, SERIAL_PREAMBLE_LENGTH + PLAYER_NAME_LENGTH + (1 + PARTY_LENGTH + 1) + (PARTYMON_STRUCT_LENGTH + PLAYER_NAME_LENGTH * 2) * PARTY_LENGTH + 7
ld bc, wLinkSendPartyEnd - wLinkSendParty
call Serial_ExchangeBytes
ld a, SERIAL_NO_DATA_BYTE
ld [de], a
@@ -242,9 +242,9 @@ Gen2ToGen2LinkComms:
ld a, [wLinkMode]
cp LINK_TRADECENTER
jr nz, .not_trading
ld hl, wLinkPlayerMail
ld de, wBattle
ld bc, wLinkPlayerMailEnd - wLinkPlayerMail
ld hl, wLinkSendMail
ld de, wLinkReceivedMail
ld bc, wLinkSendMailEnd - wLinkSendMail
call ExchangeBytes
.not_trading
ld a, IE_JOYPAD | IE_SERIAL | IE_TIMER | IE_VBLANK
@@ -255,22 +255,22 @@ Gen2ToGen2LinkComms:
ld hl, wOTPlayerName
call Link_FindFirstNonControlCharacter_SkipZero
ld de, wLinkData
ld bc, PLAYER_NAME_LENGTH + (1 + PARTY_LENGTH + 1) + (PARTYMON_STRUCT_LENGTH + PLAYER_NAME_LENGTH * 2) * PARTY_LENGTH
ld de, wLinkPlayerPartyData
ld bc, wLinkPlayerPartyDataEnd - wLinkPlayerPartyData
call Link_CopyOTData
ld de, wPlayerTrademon
ld hl, wLinkPlayerData
ld c, 2
.loop1:
.party_patch_loop:
ld a, [de]
inc de
and a
jr z, .loop1
jr z, .party_patch_loop
cp SERIAL_PREAMBLE_BYTE
jr z, .loop1
jr z, .party_patch_loop
cp SERIAL_NO_DATA_BYTE
jr z, .loop1
jr z, .party_patch_loop
cp SERIAL_PATCH_LIST_PART_TERMINATOR
jr z, .next1
push hl
@@ -283,58 +283,58 @@ Gen2ToGen2LinkComms:
ld [hl], a
pop bc
pop hl
jr .loop1
jr .party_patch_loop
.next1:
ld hl, wPicrossLayoutBuffer + 1
ld hl, wLinkPlayerData + SERIAL_PATCH_DATA_SIZE
dec c
jr nz, .loop1
jr nz, .party_patch_loop
ld a, [wLinkMode]
cp LINK_TRADECENTER
jr nz, .skip_mail
ld hl, wBattle
.loop2
.find_mail_preamble
ld a, [hli]
cp SERIAL_MAIL_PREAMBLE_BYTE
jr nz, .loop2
.loop3
jr nz, .find_mail_preamble
.skip_mail_preamble
ld a, [hli]
cp SERIAL_NO_DATA_BYTE
jr z, .loop3
jr z, .skip_mail_preamble
cp SERIAL_MAIL_PREAMBLE_BYTE
jr z, .loop3
jr z, .skip_mail_preamble
dec hl
ld de, wLinkPlayerMail
.loop4
ld de, wLinkSendMail
.mail_body_patch_loop
ld a, [hli]
cp SERIAL_NO_DATA_BYTE
jr z, .loop4
jr z, .mail_body_patch_loop
ld [de], a
inc de
cp SERIAL_MAIL_REPLACEMENT_BYTE
jr nz, .loop4
ld de, wLinkPlayerMail
.loop5:
cp SERIAL_MAIL_DATA_END
jr nz, .mail_body_patch_loop
ld de, wLinkSendMail
.mail_metadata_patch_loop:
ld a, [de]
inc de
cp SERIAL_MAIL_REPLACEMENT_BYTE
cp SERIAL_MAIL_DATA_END
jr z, .okay
cp $22
jr nz, .loop5
cp SERIAL_MAIL_REPLACEMENT_BYTE
jr nz, .mail_metadata_patch_loop
dec de
ld a, SERIAL_NO_DATA_BYTE
ld [de], a
inc de
jr .loop5
jr .mail_metadata_patch_loop
.okay:
dec de
xor a
ld [de], a
.skip_mail:
ld hl, wLinkData
ld hl, wLinkPlayerName
ld de, wOTPlayerName
ld bc, PLAYER_NAME_LENGTH
call CopyBytes
@@ -456,20 +456,20 @@ endr
dec b
jr nz, .clear_loop
ld hl, wLinkData + SERIAL_PREAMBLE_LENGTH + PLAYER_NAME_LENGTH + (1 + PARTY_LENGTH + 1) - 1
ld hl, wLinkSendPartyPartyEnd
ld de, wPlayerPatchLists + SERIAL_RNS_LENGTH
lb bc, 0, 0
.patch_loop:
; Check if we've gone over the entire area
; If we're processing the first patch area, check if we've reached the end
inc c
ld a, c
cp SERIAL_PATCH_DATA_SIZE + 1
jr z, .data1_done
; If we're processing the second patch area, check if we've reached the end
ld a, b
dec a
jr nz, .process
; If we're processing the second patch area, check if we've reached the end
push bc
ld a, [wLinkMode]
cp LINK_TIMECAPSULE
@@ -507,14 +507,14 @@ endr
ret
Link_PrepPartyData_Gen1:
ld de, wLinkData
ld de, wLinkSendTimeCapsuleParty
ld a, SERIAL_PREAMBLE_BYTE
ld b, SERIAL_PREAMBLE_LENGTH
.loop1
.preamble_loop
ld [de], a
inc de
dec b
jr nz, .loop1
jr nz, .preamble_loop
ld hl, wPlayerName
ld bc, PLAYER_NAME_LENGTH
@@ -525,10 +525,10 @@ Link_PrepPartyData_Gen1:
ld a, [hli]
ld [de], a
inc de
.loop2
.species_loop
ld a, [hli]
cp -1
jr z, .done_party
jr z, .convert_party_struct
ld [wTempByteValue], a
push hl
push de
@@ -538,9 +538,9 @@ Link_PrepPartyData_Gen1:
ld a, [wTempByteValue]
ld [de], a
inc de
jr .loop2
jr .species_loop
.done_party
.convert_party_struct
ld [de], a
pop de
ld hl, 1 + PARTY_LENGTH + 1
@@ -661,7 +661,7 @@ Link_PrepPartyData_Gen1:
ret
Link_PrepPartyData_Gen2:
ld de, wLinkData
ld de, wLinkSendParty
ld a, SERIAL_PREAMBLE_BYTE
ld b, SERIAL_PREAMBLE_LENGTH
.preamble_loop:
@@ -695,8 +695,8 @@ Link_PrepPartyData_Gen2:
cp LINK_TRADECENTER
ret nz
; Fill 5 bytes at wLinkPlayerMailPreamble with $20
ld de, wLinkPlayerMail
; Fill 5 bytes at wLinkSendMailPreamble with $20
ld de, wLinkSendMail
ld a, SERIAL_MAIL_PREAMBLE_BYTE
call Link_CopyMailPreamble
@@ -707,17 +707,17 @@ Link_PrepPartyData_Gen2:
call CopyBytes
call CloseSRAM
ld a, MAIL_MSG_LENGTH + 1
ld a, SERIAL_MAIL_DATA_END
ld [de], a
ld hl, wLinkPlayerMailMessages
ld hl, wLinkSendMailMessages
.loop:
ld a, [hli]
cp SERIAL_MAIL_REPLACEMENT_BYTE
cp SERIAL_MAIL_DATA_END
jr z, .end
cp SERIAL_NO_DATA_BYTE
jr nz, .loop
dec hl
ld [hl], $22
ld [hl], SERIAL_MAIL_REPLACEMENT_BYTE
inc hl
jr .loop
@@ -866,7 +866,7 @@ Link_ConvertPartyStruct1to2:
ld a, BASE_HAPPINESS
ld [hli], a
xor a
ld [hli], a
ld [hli], a ; wOTPartyMon*PokerusStatus
ld [hli], a
ld [hl], a
pop hl
@@ -891,7 +891,7 @@ Link_CopyRandomNumbers:
ldh a, [hSerialConnectionStatus]
cp USING_INTERNAL_CLOCK
ret z
ld hl, wEnemyMon
ld hl, wOTLinkBattleRNData
call Link_FindFirstNonControlCharacter_AllowZero
ld de, wLinkBattleRNs
ld c, SERIAL_RNS_LENGTH
@@ -1514,7 +1514,7 @@ LinkTrade:
ld bc, MAIL_STRUCT_LENGTH
call AddNTimes
push hl
ld hl, wLinkPlayerMail
ld hl, wLinkSendMail
ld a, [wCurOTTradePartyMon]
ld bc, MAIL_STRUCT_LENGTH
call AddNTimes

View File

@@ -324,30 +324,96 @@ wMapBufferEnd::
UNION
wLinkData::
wOverworldMapBlocks:: ds 1300
wLinkDataEnd::
wOverworldMapBlocksEnd::
NEXTU
ds 700
wLinkPlayerMail::
wLinkPlayerMailPreamble:: ds SERIAL_MAIL_PREAMBLE_LENGTH
wLinkPlayerMailMessages:: ds MAIL_STRUCT_LENGTH * PARTY_LENGTH
wLinkPlayerMailPatchSet:: ds 35
wLinkPlayerMailEnd::
ds 10
; This section union is 1300 bytes, the largest of all link data unions inside "Overworld Map"
wLinkData::
; player's party data, formatted for link transfer (Gen 2 link session)
wLinkSendParty::
wLinkSendPartyPreamble:: ds SERIAL_PREAMBLE_LENGTH
wLinkSendPartyPlayerName:: ds PLAYER_NAME_LENGTH
wLinkSendPartyPartyCount:: db
wLinkSendPartyPartySpecies:: ds PARTY_LENGTH
wLinkSendPartyPartyEnd:: db ; older code doesn't check PartyCount
wLinkSendPartyPlayerID:: dw
; wLinkSendPartyPlayerPartyMon1 - wLinkSendPartyPlayerPartyMon6
for n, 1, PARTY_LENGTH + 1
wLinkSendPartyPlayerPartyMon{d:n}:: party_struct wLinkSendPartyPlayerPartyMon{d:n}
endr
; wLinkSendPartyPlayerPartyMon1OT - wLinkSendPartyPlayerPartyMon6OT
for n, 1, PARTY_LENGTH + 1
wLinkSendPartyPlayerPartyMon{d:n}OT:: ds PLAYER_NAME_LENGTH
endr
; wLinkSendPartyPlayerPartyMon1Nickname - wLinkSendPartyPlayerPartyMon6Nickname
for n, 1, PARTY_LENGTH + 1
wLinkSendPartyPlayerPartyMon{d:n}Nickname:: ds MON_NAME_LENGTH
endr
wLinkSendPartyPadding:: ds 5
wLinkSendPartyEnd::
ds 313
; player's party mail, formatted for link transfer, during a link session
wLinkSendMail::
wLinkSendMailPreamble:: ds SERIAL_MAIL_PREAMBLE_LENGTH
wLinkSendMailMessages:: ds (MAIL_MSG_LENGTH + 2) * PARTY_LENGTH
wLinkSendMailMetadata:: ds (MAIL_STRUCT_LENGTH - (MAIL_MSG_LENGTH + 2)) * PARTY_LENGTH
wLinkSendMailPatchSet:: ds (MAIL_STRUCT_LENGTH - (MAIL_MSG_LENGTH + 2)) * PARTY_LENGTH - 1
wLinkSendMailEnd::
ds 20
UNION
wLinkReceivedMail::
; during a link session, the other player's raw mail data is initially stored here
ds SERIAL_MAIL_PREAMBLE_LENGTH
ds MAIL_STRUCT_LENGTH * PARTY_LENGTH
ds (MAIL_STRUCT_LENGTH - (MAIL_MSG_LENGTH + 2)) * PARTY_LENGTH -1
wLinkReceivedMailEnd::
NEXTU
; it's then processed on location to align data start with wLinkReceivedMailMessages,
; before applying the mail patch
wLinkReceivedMailMessages:: ds (MAIL_MSG_LENGTH + 2) * PARTY_LENGTH
wLinkReceivedMailMetadata:: ds (MAIL_STRUCT_LENGTH - (MAIL_MSG_LENGTH + 2)) * PARTY_LENGTH
wLinkReceivedMailPatchSet:: ds (MAIL_STRUCT_LENGTH - (MAIL_MSG_LENGTH + 2)) * PARTY_LENGTH -1
ENDU
ds 20
wLinkDataEnd::
NEXTU
wLYOverrides:: ds SCREEN_HEIGHT_PX
wLYOverridesEnd:: db
ds 15
wLYOverrides2:: ds SCREEN_HEIGHT_PX
wLYOverrides2End::
; player's party data, formatted for link transfer (Time Capsule link session)
wLinkSendTimeCapsuleParty::
wLinkSendTimeCapsulePartyPlayerName:: ds PLAYER_NAME_LENGTH
wLinkSendTimeCapsulePartyPartyCount:: db
wLinkSendTimeCapsulePartyPartySpecies:: ds PARTY_LENGTH
wLinkSendTimeCapsulePartyPartyEnd:: db ; older code doesn't check PartyCount
; wLinkSendTimeCapsulePartyMon1 - wLinkSendTimeCapsulePartyMon6
for n, 1, PARTY_LENGTH + 1
wLinkSendTimeCapsulePartyMon{d:n}:: red_party_struct wLinkSendTimeCapsulePartyMon{d:n}
endr
wLinkSendTimeCapsulePartyMonOTs::
; wLinkSendTimeCapsulePartyMon1OT - wLinkSendTimeCapsulePartyMon6OT
for n, 1, PARTY_LENGTH + 1
wLinkSendTimeCapsulePartyMon{d:n}OT:: ds PLAYER_NAME_LENGTH
endr
wLinkSendTimeCapsulePartyMonNicknames::
; wLinkSendTimeCapsulePartyMon1Nickname - wLinkSendTimeCapsulePartyMon6Nickname
for n, 1, PARTY_LENGTH + 1
wLinkSendTimeCapsulePartyMon{d:n}Nickname:: ds MON_NAME_LENGTH
endr
wLinkSendTimeCapsulePartyPadding:: ds SERIAL_PADDING_LENGTH
wLinkSendTimeCapsulePartyEnd::
NEXTU
; after the initial link session (Gen 2), the other player's party data
; is temporarily stored here before applying patch data
wLinkPlayerPartyData::
; link data members
wLinkPlayerName:: ds PLAYER_NAME_LENGTH
wLinkPartyCount:: db
@@ -364,17 +430,65 @@ endr
wLinkPlayerPartyMonOTs::
; wLinkPlayerPartyMon1OT - wLinkPlayerPartyMon6OT
for n, 1, PARTY_LENGTH + 1
wLinkPlayerPartyMon{d:n}OT:: ds NAME_LENGTH
wLinkPlayerPartyMon{d:n}OT:: ds PLAYER_NAME_LENGTH
endr
wLinkPlayerPartyMonNicknames::
; wLinkPlayerPartyMon1Nickname - wLinkPlayerPartyMon6Nickname
for n, 1, PARTY_LENGTH + 1
wLinkPlayerPartyMon{d:n}Nickname:: ds NAME_LENGTH
wLinkPlayerPartyMon{d:n}Nickname:: ds MON_NAME_LENGTH
endr
wLinkPlayerPartyDataEnd::
NEXTU
UNION
; after the initial link session (Gen 1), the other player's party data
; is temporarily stored here before applying patch data
wLinkTimeCapsulePartyData::
; link player's name and party species are not patched,
; as they normally don't contain SERIAL_NO_DATA_BYTE
wLinkTimeCapsulePlayerName:: ds PLAYER_NAME_LENGTH
wLinkTimeCapsulePartyCount:: db
wLinkTimeCapsulePartySpecies:: ds PARTY_LENGTH
wLinkTimeCapsulePartyEnd:: db ; older code doesn't check PartyCount
wTimeCapsulePatchedData::
; wTimeCapsulePartyMon1 - wTimeCapsulePartyMon6
for n, 1, PARTY_LENGTH + 1
wTimeCapsulePartyMon{d:n}:: red_party_struct wTimeCapsulePartyMon{d:n}
endr
wTimeCapsulePartyMonOTs::
; wTimeCapsulePartyMon1OT - wTimeCapsulePartyMon6OT
for n, 1, PARTY_LENGTH + 1
wTimeCapsulePartyMon{d:n}OT:: ds PLAYER_NAME_LENGTH
endr
wTimeCapsulePartyMonNicknames::
; wTimeCapsulePartyMon1Nickname - wTimeCapsulePartyMon6Nickname
for n, 1, PARTY_LENGTH + 1
wTimeCapsulePartyMon{d:n}Nickname:: ds MON_NAME_LENGTH
endr
ENDU
wLinkTimeCapsulePartyPadding:: ds SERIAL_PADDING_LENGTH
wLinkTimeCapsulePartyDataEnd::
; link player's name and party species are not patched,
; as they normally don't contain SERIAL_NO_DATA_BYTE
NEXTU
wLYOverrides:: ds SCREEN_HEIGHT_PX
wLYOverridesEnd:: db
ds 15
wLYOverrides2:: ds SCREEN_HEIGHT_PX
wLYOverrides2End::
NEXTU
; Pikachu minigame
wPikachuMinigamePikachuObjectPointer:: dw
@@ -1336,11 +1450,15 @@ wLinkBattleRNs:: ds 10
wTempEnemyMonSpecies:: db
wTempBattleMonSpecies:: db
UNION
wOTLinkBattleRNData:: ds SERIAL_RN_PREAMBLE_LENGTH + SERIAL_RNS_LENGTH
NEXTU
wEnemyMon:: battle_struct wEnemyMon
wEnemyMonBaseStats:: ds NUM_EXP_STATS
wEnemyMonCatchRate:: db
wEnemyMonBaseExp:: db
wEnemyMonEnd::
ENDU
wBattleMode:: db
wTempWildMonSpecies:: db
@@ -1843,8 +1961,30 @@ wBreedMon2:: box_struct wBreedMon2
; Uses the last two bits to keep track of your breeder mons' genders.
; Bit clear = male, bit set = female
wBreedMonGenders:: db
wOTPlayerName:: ds PLAYER_NAME_LENGTH
; This union spans 353 bytes.
UNION
; During a link session, other player's raw party data is initially stored here.
; The actual data is contained between SERIAL_PREAMBLE_LENGTH and SERIAL_PADDING_LENGTH,
; allowing possible data shift due to hardware behavior.
wLinkReceivedPartyData::
; Gen 2 link format
ds PLAYER_NAME_LENGTH
ds 1 + PARTY_LENGTH + 1
ds (PARTYMON_STRUCT_LENGTH + PLAYER_NAME_LENGTH * 2) * PARTY_LENGTH
ds SERIAL_PADDING_LENGTH
NEXTU
; Gen 1 link format
ds PLAYER_NAME_LENGTH
ds 1 + PARTY_LENGTH + 1
ds (REDMON_STRUCT_LENGTH + PLAYER_NAME_LENGTH * 2) * PARTY_LENGTH
ds SERIAL_PADDING_LENGTH
wLinkReceivedPartyEnd:: db
NEXTU
wOTPlayerName:: ds PLAYER_NAME_LENGTH
ds 15
wOTPartyData::
@@ -1889,6 +2029,8 @@ wPokemonDataEnd::
wBox:: box wBox
ENDU
SECTION "Stack Bottom", WRAM0