summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Adding-Support-for-Connectivity-with-Other-Hacks-Whilst-Maintaining-Connectivity-with-Vanilla.md88
1 files changed, 39 insertions, 49 deletions
diff --git a/Adding-Support-for-Connectivity-with-Other-Hacks-Whilst-Maintaining-Connectivity-with-Vanilla.md b/Adding-Support-for-Connectivity-with-Other-Hacks-Whilst-Maintaining-Connectivity-with-Vanilla.md
index 31a77e9..c6aa27f 100644
--- a/Adding-Support-for-Connectivity-with-Other-Hacks-Whilst-Maintaining-Connectivity-with-Vanilla.md
+++ b/Adding-Support-for-Connectivity-with-Other-Hacks-Whilst-Maintaining-Connectivity-with-Vanilla.md
@@ -38,24 +38,21 @@ struct LinkPlayer
/* 0x1A */ u16 language;
};
```
-And in `include/link_rfu.h`, we need to find `struct __attribute__((packed, aligned(2))) GFtgtGname` and make the following change:
+And in `include/link_rfu.h`, we need to find `struct __attribute__((packed, aligned(2))) RfuGameData` and make the following change:
```diff
-struct __attribute__((packed, aligned(2))) GFtgtGname
+struct __attribute__((packed, aligned(2))) RfuGameData
{
- struct GFtgtGnameSub unk_00;
- u8 child_sprite_gender[RFU_CHILD_MAX]; // u8 sprite_idx:3;
- // u8 gender:1;
- // u8 unk_4:3
- // u8 active:1
- u16 species:10;
- u16 type:6;
+ struct RfuGameCompatibilityData compatibility;
+ u8 partnerInfo[RFU_CHILD_MAX];
+ u16 tradeSpecies:10;
+ u16 tradeType:6;
u8 activity:7;
- u8 started:1;
+ u8 startedActivity:1;
u8 playerGender:1;
- u8 level:7;
+ u8 tradeLevel:7;
- u8 padding;
+ u8 versionModifier;
-}; // size: RFU_GNAME_SIZE
+};
```
If you notice, we now have a `versionModifier` in both structs which we will be using to signal hacks that the game is in fact an unofficial game.
@@ -87,46 +84,35 @@ if ((linkPlayer->version & 0xFF) == VERSION_RUBY || (linkPlayer->version & 0xFF)
- linkPlayer->neverRead = 0;
linkPlayer->progressFlags = 0;
}
-ConvertLinkPlayerName(linkPlayer);
-if (strcmp(block->magic1, sASCIIGameFreakInc) != 0
- || strcmp(block->magic2, sASCIIGameFreakInc) != 0)
-{
- SetMainCallback2(CB2_LinkError);
-}
-else
-{
- HandleReceiveRemoteLinkPlayer(i);
-}
```
This removes the reference to `linkPlayer->neverRead`, which was changed to our new `versionModifier` label. Don't worry, that byte is written to but never read hence it being named `neverRead`.
Now, we need to open [src/link_rfu_3](https://github.com/pret/pokeemerald/blob/master/src/link_rfu_3.c) and find the function named `InitHostRFUtgtGname`and make changes as follows:
```diff
-void InitHostRFUtgtGname(struct GFtgtGname *data, u8 activity, bool32 started, s32 child_sprite_genders)
+void InitHostRfuGameData(struct RfuGameData *data, u8 activity, bool32 startedActivity, s32 partnerInfo)
{
s32 i;
- for (i = 0; i < 2; i++)
- {
- data->unk_00.playerTrainerId[i] = gSaveBlock2Ptr->playerTrainerId[i];
- }
+ for (i = 0; i < (s32)ARRAY_COUNT(data->compatibility.playerTrainerId); i++)
+ data->compatibility.playerTrainerId[i] = gSaveBlock2Ptr->playerTrainerId[i];
+
for (i = 0; i < RFU_CHILD_MAX; i++)
{
- data->child_sprite_gender[i] = child_sprite_genders;
- child_sprite_genders >>= 8;
+ data->partnerInfo[i] = partnerInfo;
+ partnerInfo >>= 8; // Each element is 1 byte
}
data->playerGender = gSaveBlock2Ptr->playerGender;
data->activity = activity;
data->started = started;
+ data->versionModifier = VERSION_MODIFIER;
- data->unk_00.language = GAME_LANGUAGE;
- data->unk_00.version = GAME_VERSION;
- data->unk_00.hasNews = FALSE;
- data->unk_00.hasCard = FALSE;
-- data->unk_00.unknown = FALSE;
- data->unk_00.isChampion = FlagGet(FLAG_IS_CHAMPION);
- data->unk_00.hasNationalDex = IsNationalPokedexEnabled();
- data->unk_00.gameClear = FlagGet(FLAG_SYS_GAME_CLEAR);
+ data->compatibility.language = GAME_LANGUAGE;
+ data->compatibility.version = GAME_VERSION;
+ data->compatibility.hasNews = FALSE;
+ data->compatibility.hasCard = FALSE;
+ data->compatibility.unknown = FALSE;
+ data->compatibility.isChampion = FlagGet(FLAG_IS_CHAMPION);
+ data->compatibility.hasNationalDex = IsNationalPokedexEnabled();
+ data->compatibility.gameClear = FlagGet(FLAG_SYS_GAME_CLEAR);
}
```
Now, our game will send our `versionModifier` ID through both wireless and cable link. Now, we need to make a few edits to the trainer card. This is probably the most difficult step in this tutorial so follow carefully.
@@ -158,8 +144,11 @@ struct TrainerCard
/*0x28*/ u16 easyChatProfile[TRAINER_CARD_PROFILE_LENGTH];
/*0x30*/ u8 playerName[PLAYER_NAME_LENGTH + 1];
/*0x38*/ u8 version;
- /*0x3A*/ bool16 hasAllFrontierSymbols;
- /*0x3C*/ u32 berryCrushPoints;
+ /*0x3A*/ bool16 linkHasAllFrontierSymbols;
+ /*0x3C*/ union {
+ u32 berryCrush;
+ u32 frontier;
+ } linkPoints; // This field is used differently by FRLG vs Emerald
/*0x40*/ u32 unionRoomNum;
/*0x44*/ u8 filler[8];
/*0x4C*/ bool8 shouldDrawStickers; // FRLG only
@@ -167,10 +156,12 @@ struct TrainerCard
/*0x4E*/ u8 monIconTint; // FRLG only
/*0x4F*/ u8 facilityClass;
/*0x50*/ u8 stickers[TRAINER_CARD_STICKER_TYPES]; // FRLG only
++ /*0x53*/ u8 versionModifier;
/*0x54*/ u16 monSpecies[PARTY_SIZE]; // FRLG only
- /*0x60*/ bool16 hasAllSymbols;
+ // Note: Link players use linkHasAllFrontierSymbols, not the field below,
+ // which they use for a Wonder Card flag id instead (see CreateTrainerCardInBuffer)
+ /*0x60*/ bool16 hasAllFrontierSymbols;
/*0x62*/ u16 frontierBP;
-+ /*0x64*/ u8 versionModifier;
};
```
This is so the game can use the `versionModifier` value when loading the trainer card.
@@ -181,8 +172,8 @@ void CopyTrainerCardData(struct TrainerCard *dst, u16 *src, u8 gameVersion, u8 v
Okay, now we actually need to use that new byte! Open [src/trainer_card.c](https://github.com/pret/pokeemerald/blob/master/src/trainer_card.c) and find the functions `CopyTrainerCardData`, `TrainerCard_GenerateCardForLinkPlayer` and `TrainerCard_GenerateCardForPlayer`.
In `CopyTrainerCardData`, make the following changes:
```diff
-- void CopyTrainerCardData(struct TrainerCard *dst, u16 *src, u8 gameVersion)
-+ void CopyTrainerCardData(struct TrainerCard *dst, u16 *src, u8 gameVersion, u8 versionModifier)
+- void CopyTrainerCardData(struct TrainerCard *dst, struct TrainerCard *src, u8 gameVersion)
++ void CopyTrainerCardData(struct TrainerCard *dst, struct TrainerCard *src, u8 gameVersion, u8 versionModifier)
{
memset(dst, 0, sizeof(struct TrainerCard));
dst->version = gameVersion;
@@ -198,9 +189,9 @@ In `CopyTrainerCardData`, make the following changes:
break;
case CARD_TYPE_EMERALD:
memcpy(dst, src, 0x60);
- dst->berryCrushPoints = 0;
- dst->hasAllSymbols = src[29];
- dst->frontierBP = src[30];
+ dst->linkPoints.frontier = 0;
+ dst->hasAllFrontierSymbols = src->linkHasAllFrontierSymbols;
+ dst->frontierBP = *((u16*)&src->linkPoints.frontier);
break;
}
}
@@ -229,14 +220,13 @@ In `TrainerCard_GenerateCardForPlayer`, make the following changes:
```diff
void TrainerCard_GenerateCardForPlayer(struct TrainerCard *trainerCard)
{
-- memset(trainerCard, 0, 0x60);
-+ memset(trainerCard, 0, sizeof(struct TrainerCard));
+ memset(trainerCard, 0, sizeof(struct TrainerCard));
trainerCard->version = GAME_VERSION;
+ trainerCard->versionModifier = VERSION_MODIFIER;
- SetPlayerCardData(trainerCard, CARD_TYPE_EMERALD);
+ SetPlayerCardData(trainerCard, VersionToCardType(GAME_VERSION, VERSION_MODIFIER));
trainerCard->hasAllFrontierSymbols = HasAllFrontierSymbols();
- *((u16*)&trainerCard->berryCrushPoints) = gSaveBlock2Ptr->frontier.cardBattlePoints;
+ trainerCard->frontierBP = gSaveBlock2Ptr->frontier.cardBattlePoints;
if (trainerCard->hasAllFrontierSymbols)
trainerCard->stars++;