Merge pull request #1269 from GriffinRichards/bugfix

Use BUGFIX for some inline fixes
This commit is contained in:
GriffinR
2020-12-14 20:00:59 -05:00
committed by GitHub
22 changed files with 158 additions and 47 deletions
+10 -2
View File
@@ -2324,14 +2324,18 @@ AI_CV_SemiInvulnerable:
@ BUG: The scripts for checking type-resistance to weather for semi-invulnerable moves are swapped @ BUG: The scripts for checking type-resistance to weather for semi-invulnerable moves are swapped
@ The result is that the AI is encouraged to stall while taking damage from weather @ The result is that the AI is encouraged to stall while taking damage from weather
@ To fix, swap _CheckSandstormTypes/_CheckIceType in the below script
AI_CV_SemiInvulnerable2: AI_CV_SemiInvulnerable2:
if_status AI_TARGET, STATUS1_TOXIC_POISON, AI_CV_SemiInvulnerable_TryEncourage if_status AI_TARGET, STATUS1_TOXIC_POISON, AI_CV_SemiInvulnerable_TryEncourage
if_status2 AI_TARGET, STATUS2_CURSED, AI_CV_SemiInvulnerable_TryEncourage if_status2 AI_TARGET, STATUS2_CURSED, AI_CV_SemiInvulnerable_TryEncourage
if_status3 AI_TARGET, STATUS3_LEECHSEED, AI_CV_SemiInvulnerable_TryEncourage if_status3 AI_TARGET, STATUS3_LEECHSEED, AI_CV_SemiInvulnerable_TryEncourage
get_weather get_weather
.ifdef BUGFIX
if_equal AI_WEATHER_HAIL, AI_CV_SemiInvulnerable_CheckIceType
if_equal AI_WEATHER_SANDSTORM, AI_CV_SemiInvulnerable_CheckSandstormTypes
.else
if_equal AI_WEATHER_HAIL, AI_CV_SemiInvulnerable_CheckSandstormTypes if_equal AI_WEATHER_HAIL, AI_CV_SemiInvulnerable_CheckSandstormTypes
if_equal AI_WEATHER_SANDSTORM, AI_CV_SemiInvulnerable_CheckIceType if_equal AI_WEATHER_SANDSTORM, AI_CV_SemiInvulnerable_CheckIceType
.endif
goto AI_CV_SemiInvulnerable5 goto AI_CV_SemiInvulnerable5
AI_CV_SemiInvulnerable_CheckSandstormTypes: AI_CV_SemiInvulnerable_CheckSandstormTypes:
@@ -2398,9 +2402,13 @@ AI_CV_Hail_ScoreDown1:
AI_CV_Hail_End: AI_CV_Hail_End:
end end
@ BUG: Facade score is increased if the target is statused, but should be if the user is. Replace AI_TARGET with AI_USER @ BUG: Facade score is increased if the target is statused, but should be if the user is
AI_CV_Facade: AI_CV_Facade:
.ifdef BUGFIX
if_not_status AI_USER, STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON, AI_CV_Facade_End
.else
if_not_status AI_TARGET, STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON, AI_CV_Facade_End if_not_status AI_TARGET, STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON, AI_CV_Facade_End
.endif
score +1 score +1
AI_CV_Facade_End: AI_CV_Facade_End:
end end
@@ -247,7 +247,11 @@ MossdeepCity_SpaceCenter_1F_EventScript_Grunt2:: @ 822321F
copyobjectxytoperm LOCALID_STAIR_GRUNT copyobjectxytoperm LOCALID_STAIR_GRUNT
switch VAR_FACING switch VAR_FACING
case DIR_WEST, MossdeepCity_SpaceCenter_1F_EventScript_MoveGruntFromStairsWest case DIR_WEST, MossdeepCity_SpaceCenter_1F_EventScript_MoveGruntFromStairsWest
case DIR_WEST, MossdeepCity_SpaceCenter_1F_EventScript_MoveGruntFromStairsEast @ BUG: This was meant to be case DIR_EAST #ifdef BUGFIX
case DIR_EAST, MossdeepCity_SpaceCenter_1F_EventScript_MoveGruntFromStairsEast
#else
case DIR_WEST, MossdeepCity_SpaceCenter_1F_EventScript_MoveGruntFromStairsEast
#endif
applymovement LOCALID_STAIR_GRUNT, MossdeepCity_SpaceCenter_1F_Movement_MoveGruntFromStairs applymovement LOCALID_STAIR_GRUNT, MossdeepCity_SpaceCenter_1F_Movement_MoveGruntFromStairs
waitmovement 0 waitmovement 0
setvar VAR_MOSSDEEP_SPACE_CENTER_STAIR_GUARD_STATE, 2 setvar VAR_MOSSDEEP_SPACE_CENTER_STAIR_GUARD_STATE, 2
+4 -4
View File
@@ -15,9 +15,6 @@
// printing system. Use NoCashGBAPrint() and NoCashGBAPrintf() like you // printing system. Use NoCashGBAPrint() and NoCashGBAPrintf() like you
// would normally use AGBPrint() and AGBPrintf(). // would normally use AGBPrint() and AGBPrintf().
// NOTE: Don't try to enable assert right now as many pointers
// still exist in defines and WILL likely result in a broken ROM.
#define ENGLISH #define ENGLISH
#ifdef ENGLISH #ifdef ENGLISH
@@ -26,9 +23,12 @@
#define UNITS_METRIC #define UNITS_METRIC
#endif #endif
// Uncomment to fix some identified minor bugs
//#define BUGFIX
// Various undefined behavior bugs may or may not prevent compilation with // Various undefined behavior bugs may or may not prevent compilation with
// newer compilers. So always fix them when using a modern compiler. // newer compilers. So always fix them when using a modern compiler.
#if MODERN #if MODERN || defined(BUGFIX)
#ifndef UBFIX #ifndef UBFIX
#define UBFIX #define UBFIX
#endif #endif
+4 -2
View File
@@ -1613,8 +1613,10 @@ static void Cmd_if_status_not_in_party(void)
if (species != SPECIES_NONE && species != SPECIES_EGG && hp != 0 && status == statusToCompareTo) if (species != SPECIES_NONE && species != SPECIES_EGG && hp != 0 && status == statusToCompareTo)
{ {
gAIScriptPtr += 10; // UB: Still bugged in Emerald. Uncomment the return statement to fix. gAIScriptPtr += 10;
// return; #ifdef UBFIX
return;
#endif
} }
} }
+12 -2
View File
@@ -863,7 +863,9 @@ static const struct WindowTemplate sInfoCardWindowTemplates[] =
.paletteNum = 15, .paletteNum = 15,
.baseBlock = 372, .baseBlock = 372,
}, },
// UB: No DUMMY_WIN_TEMPLATE at the array's end. #ifdef UBFIX
DUMMY_WIN_TEMPLATE,
#endif
}; };
static const struct ScanlineEffectParams sTourneyTreeScanlineEffectParams = static const struct ScanlineEffectParams sTourneyTreeScanlineEffectParams =
@@ -2526,7 +2528,11 @@ static void CreateDomeOpponentMon(u8 monPartyId, u16 tournamentTrainerId, u8 tou
{ {
int i; int i;
u8 friendship = MAX_FRIENDSHIP; u8 friendship = MAX_FRIENDSHIP;
u8 fixedIv = GetDomeTrainerMonIvs(tournamentTrainerId); // BUG: Should be using (DOME_TRAINERS[tournamentTrainerId].trainerId) instead of (tournamentTrainerId). As a result, all Pokemon have ivs of 3. #ifdef BUGFIX
u8 fixedIv = GetDomeTrainerMonIvs(DOME_TRAINERS[tournamentTrainerId].trainerId);
#else
u8 fixedIv = GetDomeTrainerMonIvs(tournamentTrainerId); // BUG: Using the wrong ID. As a result, all Pokemon have ivs of 3.
#endif
u8 level = SetFacilityPtrsGetLevel(); u8 level = SetFacilityPtrsGetLevel();
CreateMonWithEVSpreadNatureOTID(&gEnemyParty[monPartyId], CreateMonWithEVSpreadNatureOTID(&gEnemyParty[monPartyId],
gFacilityTrainerMons[DOME_MONS[tournamentTrainerId][tournamentMonId]].species, gFacilityTrainerMons[DOME_MONS[tournamentTrainerId][tournamentMonId]].species,
@@ -5964,6 +5970,10 @@ static void DecideRoundWinners(u8 roundId)
else if (tournamentId2 != 0xFF) else if (tournamentId2 != 0xFF)
{ {
// BUG: points1 and points2 are not cleared at the beginning of the loop resulting in not fair results. // BUG: points1 and points2 are not cleared at the beginning of the loop resulting in not fair results.
#ifdef BUGFIX
points1 = 0;
points2 = 0;
#endif
// Calculate points for both trainers. // Calculate points for both trainers.
for (monId1 = 0; monId1 < FRONTIER_PARTY_SIZE; monId1++) for (monId1 = 0; monId1 < FRONTIER_PARTY_SIZE; monId1++)
+5 -1
View File
@@ -3905,7 +3905,11 @@ static void Swap_ShowSummaryMonSprite(void)
personality = GetMonData(mon, MON_DATA_PERSONALITY, NULL); personality = GetMonData(mon, MON_DATA_PERSONALITY, NULL);
otId = GetMonData(mon, MON_DATA_OT_ID, NULL); otId = GetMonData(mon, MON_DATA_OT_ID, NULL);
sFactorySwapScreen->unk2C.field0 = CreateMonPicSprite_HandleDeoxys(species, personality, otId, TRUE, 88, 32, 15, 0xFFFF); // BUG: otId and personality should be switched. #ifdef BUGFIX
sFactorySwapScreen->unk2C.field0 = CreateMonPicSprite_HandleDeoxys(species, otId, personality, TRUE, 88, 32, 15, 0xFFFF);
#else
sFactorySwapScreen->unk2C.field0 = CreateMonPicSprite_HandleDeoxys(species, personality, otId, TRUE, 88, 32, 15, 0xFFFF);
#endif
gSprites[sFactorySwapScreen->unk2C.field0].centerToCornerVecX = 0; gSprites[sFactorySwapScreen->unk2C.field0].centerToCornerVecX = 0;
gSprites[sFactorySwapScreen->unk2C.field0].centerToCornerVecY = 0; gSprites[sFactorySwapScreen->unk2C.field0].centerToCornerVecY = 0;
+6 -2
View File
@@ -1757,7 +1757,9 @@ static bool8 SetPyramidObjectPositionsInAndNearSquare(u8 objType, u8 squareId)
r7 &= 1; r7 &= 1;
} }
// free(floorLayoutOffsets); BUG: floorLayoutOffsets memory not freed #ifdef BUGFIX
free(floorLayoutOffsets);
#endif
return (numObjects / 2) > numPlacedObjects; return (numObjects / 2) > numPlacedObjects;
} }
@@ -1809,7 +1811,9 @@ static bool8 SetPyramidObjectPositionsNearSquare(u8 objType, u8 squareId)
if (r8 == 4) if (r8 == 4)
break; break;
} }
// free(floorLayoutOffsets); BUG: floorLayoutOffsets memory not freed #ifdef BUGFIX
free(floorLayoutOffsets);
#endif
return (numObjects / 2) > numPlacedObjects; return (numObjects / 2) > numPlacedObjects;
} }
+22 -6
View File
@@ -1336,10 +1336,15 @@ void PutNewBattleTowerRecord(struct EmeraldBattleTowerRecord *newRecordEm)
{ {
for (k = 0; k < PLAYER_NAME_LENGTH; k++) for (k = 0; k < PLAYER_NAME_LENGTH; k++)
{ {
// BUG: Wrong variable used, 'j' instead of 'k'. #ifdef BUGFIX
if (gSaveBlock2Ptr->frontier.towerRecords[i].name[k] != newRecord->name[k])
break;
if (newRecord->name[k] == EOS)
#else
if (gSaveBlock2Ptr->frontier.towerRecords[i].name[j] != newRecord->name[j]) if (gSaveBlock2Ptr->frontier.towerRecords[i].name[j] != newRecord->name[j])
break; break;
if (newRecord->name[j] == EOS) if (newRecord->name[j] == EOS)
#endif
{ {
k = PLAYER_NAME_LENGTH; k = PLAYER_NAME_LENGTH;
break; break;
@@ -2956,7 +2961,12 @@ static void FillPartnerParty(u16 trainerId)
sStevenMons[i].species, sStevenMons[i].species,
sStevenMons[i].level, sStevenMons[i].level,
sStevenMons[i].fixedIV, sStevenMons[i].fixedIV,
TRUE, i, // BUG: personality was stored in the 'j' variable. As a result, Steven's pokemon do not have the intended natures. TRUE,
#ifdef BUGFIX
j,
#else
i, // BUG: personality was stored in the 'j' variable. As a result, Steven's pokemon do not have the intended natures.
#endif
OT_ID_PRESET, STEVEN_OTID); OT_ID_PRESET, STEVEN_OTID);
for (j = 0; j < PARTY_SIZE; j++) for (j = 0; j < PARTY_SIZE; j++)
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_HP_EV + j, &sStevenMons[i].evs[j]); SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_HP_EV + j, &sStevenMons[i].evs[j]);
@@ -3062,9 +3072,12 @@ bool32 RubyBattleTowerRecordToEmerald(struct RSBattleTowerRecord *src, struct Em
{ {
dst->lvlMode = src->lvlMode; dst->lvlMode = src->lvlMode;
dst->winStreak = src->winStreak; dst->winStreak = src->winStreak;
// BUG: Reading outside the array. sRubyFacilityClassToEmerald has less than FACILITY_CLASSES_COUNT entries. // UB: Reading outside the array. sRubyFacilityClassToEmerald has less than FACILITY_CLASSES_COUNT entries.
// Fix by using ARRAY_COUNT(sRubyFacilityClassToEmerald) #ifdef UBFIX
for (i = 0; i < ARRAY_COUNT(sRubyFacilityClassToEmerald); i++)
#else
for (i = 0; i < FACILITY_CLASSES_COUNT; i++) for (i = 0; i < FACILITY_CLASSES_COUNT; i++)
#endif
{ {
if (sRubyFacilityClassToEmerald[i][0] == src->facilityClass) if (sRubyFacilityClassToEmerald[i][0] == src->facilityClass)
break; break;
@@ -3112,9 +3125,12 @@ bool32 EmeraldBattleTowerRecordToRuby(struct EmeraldBattleTowerRecord *src, stru
{ {
dst->lvlMode = src->lvlMode; dst->lvlMode = src->lvlMode;
dst->winStreak = src->winStreak; dst->winStreak = src->winStreak;
// BUG: Reading outside the array. sRubyFacilityClassToEmerald has less than FACILITY_CLASSES_COUNT entries. // UB: Reading outside the array. sRubyFacilityClassToEmerald has less than FACILITY_CLASSES_COUNT entries.
// Fix by using ARRAY_COUNT(sRubyFacilityClassToEmerald) instead #ifdef UBFIX
for (i = 0; i < ARRAY_COUNT(sRubyFacilityClassToEmerald); i++)
#else
for (i = 0; i < FACILITY_CLASSES_COUNT; i++) for (i = 0; i < FACILITY_CLASSES_COUNT; i++)
#endif
{ {
if (sRubyFacilityClassToEmerald[i][1] == src->facilityClass) if (sRubyFacilityClassToEmerald[i][1] == src->facilityClass)
break; break;
+5 -2
View File
@@ -536,9 +536,12 @@ void HandleAction_ThrowPokeblock(void)
gBattleStruct->safariPkblThrowCounter++; gBattleStruct->safariPkblThrowCounter++;
if (gBattleStruct->safariEscapeFactor > 1) if (gBattleStruct->safariEscapeFactor > 1)
{ {
// BUG: The safariEscapeFactor is unintetionally able to become 0 (but it can not become negative!). This causes the pokeblock throw glitch. // BUG: safariEscapeFactor can become 0 below. This causes the pokeblock throw glitch.
// To fix that change the < in the if statement below to <=. #ifdef BUGFIX
if (gBattleStruct->safariEscapeFactor <= sPkblToEscapeFactor[gBattleStruct->safariPkblThrowCounter][gBattleCommunication[MULTISTRING_CHOOSER]])
#else
if (gBattleStruct->safariEscapeFactor < sPkblToEscapeFactor[gBattleStruct->safariPkblThrowCounter][gBattleCommunication[MULTISTRING_CHOOSER]]) if (gBattleStruct->safariEscapeFactor < sPkblToEscapeFactor[gBattleStruct->safariPkblThrowCounter][gBattleCommunication[MULTISTRING_CHOOSER]])
#endif
gBattleStruct->safariEscapeFactor = 1; gBattleStruct->safariEscapeFactor = 1;
else else
gBattleStruct->safariEscapeFactor -= sPkblToEscapeFactor[gBattleStruct->safariPkblThrowCounter][gBattleCommunication[MULTISTRING_CHOOSER]]; gBattleStruct->safariEscapeFactor -= sPkblToEscapeFactor[gBattleStruct->safariPkblThrowCounter][gBattleCommunication[MULTISTRING_CHOOSER]];
+9 -1
View File
@@ -1852,7 +1852,9 @@ static void Task_HandleOpponent1(u8 taskId)
gRecvCmds[1][BLENDER_COMM_SCORE] = LINKCMD_BLENDER_SCORE_GOOD; gRecvCmds[1][BLENDER_COMM_SCORE] = LINKCMD_BLENDER_SCORE_GOOD;
// BUG: Overrwrote above assignment. Opponent 1 can't get Best at low speed // BUG: Overrwrote above assignment. Opponent 1 can't get Best at low speed
#ifndef BUGFIX
gRecvCmds[1][BLENDER_COMM_SCORE] = LINKCMD_BLENDER_SCORE_GOOD; gRecvCmds[1][BLENDER_COMM_SCORE] = LINKCMD_BLENDER_SCORE_GOOD;
#endif
} }
else if (sBerryBlender->speed < 1500) else if (sBerryBlender->speed < 1500)
{ {
@@ -2131,11 +2133,17 @@ static void UpdateOpponentScores(void)
sBerryBlender->scores[i][SCORE_MISS]++; sBerryBlender->scores[i][SCORE_MISS]++;
} }
// BUG: Should [i][BLENDER_COMM_SCORE] below, not [BLENDER_COMM_SCORE][i] // BUG: Should be [i][BLENDER_COMM_SCORE] below, not [BLENDER_COMM_SCORE][i]
// As a result the music tempo updates if any player misses, but only if 1 specific player hits // As a result the music tempo updates if any player misses, but only if 1 specific player hits
#ifdef BUGFIX
if (gRecvCmds[i][BLENDER_COMM_SCORE] == LINKCMD_BLENDER_SCORE_MISS
|| gRecvCmds[i][BLENDER_COMM_SCORE] == LINKCMD_BLENDER_SCORE_BEST
|| gRecvCmds[i][BLENDER_COMM_SCORE] == LINKCMD_BLENDER_SCORE_GOOD)
#else
if (gRecvCmds[i][BLENDER_COMM_SCORE] == LINKCMD_BLENDER_SCORE_MISS if (gRecvCmds[i][BLENDER_COMM_SCORE] == LINKCMD_BLENDER_SCORE_MISS
|| gRecvCmds[BLENDER_COMM_SCORE][i] == LINKCMD_BLENDER_SCORE_BEST || gRecvCmds[BLENDER_COMM_SCORE][i] == LINKCMD_BLENDER_SCORE_BEST
|| gRecvCmds[BLENDER_COMM_SCORE][i] == LINKCMD_BLENDER_SCORE_GOOD) || gRecvCmds[BLENDER_COMM_SCORE][i] == LINKCMD_BLENDER_SCORE_GOOD)
#endif
{ {
if (sBerryBlender->speed > 1500) if (sBerryBlender->speed > 1500)
m4aMPlayTempoControl(&gMPlayInfo_BGM, ((sBerryBlender->speed - 750) / 20) + 256); m4aMPlayTempoControl(&gMPlayInfo_BGM, ((sBerryBlender->speed - 750) / 20) + 256);
+8 -2
View File
@@ -1734,8 +1734,9 @@ static void ContestAICmd_if_user_doesnt_have_exciting_move(void)
// they're checking for an effect. Checking for a specific effect would make more sense, // they're checking for an effect. Checking for a specific effect would make more sense,
// but given that effects are normally read as a single byte and this reads 2 bytes, it // but given that effects are normally read as a single byte and this reads 2 bytes, it
// seems reading a move was intended and the AI script is using it incorrectly. // seems reading a move was intended and the AI script is using it incorrectly.
// In any case, to fix it to correctly check for effects replace the u16 move assignment with // The fix below aligns the function with how it's used by the script, rather than the apparent
// u16 move = gContestMoves[gContestMons[eContestAI.contestantId].moves[i]].effect; // intention of its usage
static void ContestAICmd_check_user_has_move(void) static void ContestAICmd_check_user_has_move(void)
{ {
int hasMove = FALSE; int hasMove = FALSE;
@@ -1744,7 +1745,12 @@ static void ContestAICmd_check_user_has_move(void)
for (i = 0; i < MAX_MON_MOVES; i++) for (i = 0; i < MAX_MON_MOVES; i++)
{ {
#ifdef BUGFIX
u16 move = gContestMoves[gContestMons[eContestAI.contestantId].moves[i]].effect;
#else
u16 move = gContestMons[eContestAI.contestantId].moves[i]; u16 move = gContestMons[eContestAI.contestantId].moves[i];
#endif
if (move == targetMove) if (move == targetMove)
{ {
hasMove = TRUE; hasMove = TRUE;
+7 -5
View File
@@ -551,13 +551,15 @@ static void InheritIVs(struct Pokemon *egg, struct DayCare *daycare)
// removes position 0 (HP) then position 1 (DEF), then position 2. This is why HP and DEF // removes position 0 (HP) then position 1 (DEF), then position 2. This is why HP and DEF
// have a lower chance to be inherited in Emerald and why the IV picked for inheritance can // have a lower chance to be inherited in Emerald and why the IV picked for inheritance can
// be repeated. Amusingly, FRLG and RS also got this wrong. They remove selectedIvs[i], which // be repeated. Amusingly, FRLG and RS also got this wrong. They remove selectedIvs[i], which
// is not an index! This means that it can sometimes remove the wrong stat. To fix, delete // is not an index! This means that it can sometimes remove the wrong stat.
// the following two lines and uncomment the rest of the block. #ifndef BUGFIX
selectedIvs[i] = availableIVs[Random() % (NUM_STATS - i)]; selectedIvs[i] = availableIVs[Random() % (NUM_STATS - i)];
RemoveIVIndexFromList(availableIVs, i); RemoveIVIndexFromList(availableIVs, i);
// u8 index = Random() % (NUM_STATS - i); #else
// selectedIvs[i] = availableIVs[index]; u8 index = Random() % (NUM_STATS - i);
// RemoveIVIndexFromList(availableIVs, index); selectedIvs[i] = availableIVs[index];
RemoveIVIndexFromList(availableIVs, index);
#endif
} }
// Determine which parent each of the selected IVs should inherit from. // Determine which parent each of the selected IVs should inherit from.
+10 -3
View File
@@ -3846,7 +3846,6 @@ bool8 FldEff_MoveDeoxysRock(struct Sprite* sprite)
static void Task_MoveDeoxysRock(u8 taskId) static void Task_MoveDeoxysRock(u8 taskId)
{ {
// BUG: Possible divide by zero
s16 *data = gTasks[taskId].data; s16 *data = gTasks[taskId].data;
struct Sprite *sprite = &gSprites[data[1]]; struct Sprite *sprite = &gSprites[data[1]];
switch (data[0]) switch (data[0])
@@ -3854,8 +3853,16 @@ static void Task_MoveDeoxysRock(u8 taskId)
case 0: case 0:
data[4] = sprite->pos1.x << 4; data[4] = sprite->pos1.x << 4;
data[5] = sprite->pos1.y << 4; data[5] = sprite->pos1.y << 4;
data[6] = (data[2] * 16 - data[4]) / data[8];
data[7] = (data[3] * 16 - data[5]) / data[8]; // UB: Possible divide by zero
#ifdef UBFIX
#define DIVISOR (data[8] ? data[8] : 1);
#else
#define DIVISOR (data[8])
#endif
data[6] = (data[2] * 16 - data[4]) / DIVISOR;
data[7] = (data[3] * 16 - data[5]) / DIVISOR;
data[0]++; data[0]++;
case 1: case 1:
if (data[8] != 0) if (data[8] != 0)
+3
View File
@@ -983,6 +983,9 @@ static void Task_HandleFrontierPassInput(u8 taskId)
SetMainCallback2(CB2_HideFrontierPass); SetMainCallback2(CB2_HideFrontierPass);
DestroyTask(taskId); DestroyTask(taskId);
// BUG. The function should return here. Otherwise, it can play the same sound twice and destroy the same task twice. // BUG. The function should return here. Otherwise, it can play the same sound twice and destroy the same task twice.
#ifdef BUGFIX
return;
#endif
} }
} }
+11 -3
View File
@@ -2383,13 +2383,21 @@ void ClearRankingHallRecords(void)
{ {
s32 i, j, k; s32 i, j, k;
// BUG: Passing 0 as a pointer instead of a pointer holding a value of 0.
#ifdef BUGFIX
u8 zero = 0;
#define ZERO (&zero)
#else
#define ZERO 0
#endif
for (i = 0; i < HALL_FACILITIES_COUNT; i++) for (i = 0; i < HALL_FACILITIES_COUNT; i++)
{ {
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
{ {
for (k = 0; k < 3; k++) for (k = 0; k < 3; k++)
{ {
CopyTrainerId(gSaveBlock2Ptr->hallRecords1P[i][j][k].id, 0); // BUG: Passing 0 as a pointer instead of a pointer holding a value of 0. CopyTrainerId(gSaveBlock2Ptr->hallRecords1P[i][j][k].id, ZERO);
gSaveBlock2Ptr->hallRecords1P[i][j][k].name[0] = EOS; gSaveBlock2Ptr->hallRecords1P[i][j][k].name[0] = EOS;
gSaveBlock2Ptr->hallRecords1P[i][j][k].winStreak = 0; gSaveBlock2Ptr->hallRecords1P[i][j][k].winStreak = 0;
} }
@@ -2400,8 +2408,8 @@ void ClearRankingHallRecords(void)
{ {
for (k = 0; k < 3; k++) for (k = 0; k < 3; k++)
{ {
CopyTrainerId(gSaveBlock2Ptr->hallRecords2P[j][k].id1, 0); // BUG: Passing 0 as a pointer instead of a pointer holding a value of 0. CopyTrainerId(gSaveBlock2Ptr->hallRecords2P[j][k].id1, ZERO);
CopyTrainerId(gSaveBlock2Ptr->hallRecords2P[j][k].id2, 0); // BUG: Passing 0 as a pointer instead of a pointer holding a value of 0. CopyTrainerId(gSaveBlock2Ptr->hallRecords2P[j][k].id2, ZERO);
gSaveBlock2Ptr->hallRecords2P[j][k].name1[0] = EOS; gSaveBlock2Ptr->hallRecords2P[j][k].name1[0] = EOS;
gSaveBlock2Ptr->hallRecords2P[j][k].name2[0] = EOS; gSaveBlock2Ptr->hallRecords2P[j][k].name2[0] = EOS;
gSaveBlock2Ptr->hallRecords2P[j][k].winStreak = 0; gSaveBlock2Ptr->hallRecords2P[j][k].winStreak = 0;
+8 -2
View File
@@ -1817,10 +1817,13 @@ static u16 GetFrontierStreakInfo(u16 facilityId, u32 *topicTextId)
} }
*topicTextId = 3; *topicTextId = 3;
break; break;
#ifdef BUGFIX
case FRONTIER_FACILITY_PIKE:
#else
case FRONTIER_FACILITY_FACTORY: case FRONTIER_FACILITY_FACTORY:
#endif
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{ {
// BUG: should be looking at battle factory records.
if (streak < gSaveBlock2Ptr->frontier.pikeRecordStreaks[i]) if (streak < gSaveBlock2Ptr->frontier.pikeRecordStreaks[i])
streak = gSaveBlock2Ptr->frontier.pikeRecordStreaks[i]; streak = gSaveBlock2Ptr->frontier.pikeRecordStreaks[i];
} }
@@ -1848,12 +1851,15 @@ static u16 GetFrontierStreakInfo(u16 facilityId, u32 *topicTextId)
} }
*topicTextId = 2; *topicTextId = 2;
break; break;
#ifdef BUGFIX
case FRONTIER_FACILITY_FACTORY:
#else
case FRONTIER_FACILITY_PIKE: case FRONTIER_FACILITY_PIKE:
#endif
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{ {
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
{ {
// BUG: should be looking at battle pike records.
if (streak < gSaveBlock2Ptr->frontier.factoryRecordWinStreaks[i][j]) if (streak < gSaveBlock2Ptr->frontier.factoryRecordWinStreaks[i][j])
streak = gSaveBlock2Ptr->frontier.factoryRecordWinStreaks[i][j]; streak = gSaveBlock2Ptr->frontier.factoryRecordWinStreaks[i][j];
} }
+6 -3
View File
@@ -970,10 +970,13 @@ bool8 MetatileBehavior_IsUnableToEmerge(u8 metatileBehavior)
{ {
// BUG: The player is unintentionally able to emerge on water doors. // BUG: The player is unintentionally able to emerge on water doors.
// Also the narrower underwater door in the underwater tileset has the wrong metatile behavior. This causes the dive glitch. // Also the narrower underwater door in the underwater tileset has the wrong metatile behavior. This causes the dive glitch.
// To fix that add || metatileBehavior == MB_WATER_DOOR to the if statement below and // To fix change the metatile behavior of the narrower water door with porymap's tileset editor.
// change the metatile behavior of the narrower water door with porymaps tileset editor.
if (metatileBehavior == MB_NO_SURFACING if (metatileBehavior == MB_NO_SURFACING
|| metatileBehavior == MB_SEAWEED_NO_SURFACING) || metatileBehavior == MB_SEAWEED_NO_SURFACING
#ifdef BUGFIX
|| metatileBehavior == MB_WATER_DOOR
#endif
)
return TRUE; return TRUE;
else else
return FALSE; return FALSE;
+4 -1
View File
@@ -2861,8 +2861,11 @@ void CalculateMonStats(struct Pokemon *mon)
currentHP = newMaxHP; currentHP = newMaxHP;
else if (currentHP != 0) else if (currentHP != 0)
// BUG: currentHP is unintentionally able to become <= 0 after the instruction below. This causes the pomeg berry glitch. // BUG: currentHP is unintentionally able to become <= 0 after the instruction below. This causes the pomeg berry glitch.
// To fix that set currentHP = 1 if currentHP <= 0.
currentHP += newMaxHP - oldMaxHP; currentHP += newMaxHP - oldMaxHP;
#ifdef BUGFIX
if (currentHP <= 0)
currentHP = 1;
#endif
else else
return; return;
} }
+3 -2
View File
@@ -9329,10 +9329,11 @@ u32 GetBoxMonLevelAt(u8 boxId, u8 boxPosition)
{ {
u32 lvl; u32 lvl;
// BUG: Missed 'else' statement.
if (boxId < TOTAL_BOXES_COUNT && boxPosition < IN_BOX_COUNT && GetBoxMonData(&gPokemonStoragePtr->boxes[boxId][boxPosition], MON_DATA_SANITY_HAS_SPECIES)) if (boxId < TOTAL_BOXES_COUNT && boxPosition < IN_BOX_COUNT && GetBoxMonData(&gPokemonStoragePtr->boxes[boxId][boxPosition], MON_DATA_SANITY_HAS_SPECIES))
lvl = GetLevelFromBoxMonExp(&gPokemonStoragePtr->boxes[boxId][boxPosition]); lvl = GetLevelFromBoxMonExp(&gPokemonStoragePtr->boxes[boxId][boxPosition]);
// else #ifdef BUGFIX
else
#endif
lvl = 0; lvl = 0;
return lvl; return lvl;
+4
View File
@@ -131,7 +131,11 @@ static const u16 sRegionMap_SpecialPlaceLocations[][2] =
{ {
{MAPSEC_UNDERWATER_105, MAPSEC_ROUTE_105}, {MAPSEC_UNDERWATER_105, MAPSEC_ROUTE_105},
{MAPSEC_UNDERWATER_124, MAPSEC_ROUTE_124}, {MAPSEC_UNDERWATER_124, MAPSEC_ROUTE_124},
#ifdef BUGFIX
{MAPSEC_UNDERWATER_125, MAPSEC_ROUTE_125},
#else
{MAPSEC_UNDERWATER_125, MAPSEC_ROUTE_129}, // BUG: Map will incorrectly display the name of Route 129 when diving on Route 125 (for Marine Cave only) {MAPSEC_UNDERWATER_125, MAPSEC_ROUTE_129}, // BUG: Map will incorrectly display the name of Route 129 when diving on Route 125 (for Marine Cave only)
#endif
{MAPSEC_UNDERWATER_126, MAPSEC_ROUTE_126}, {MAPSEC_UNDERWATER_126, MAPSEC_ROUTE_126},
{MAPSEC_UNDERWATER_127, MAPSEC_ROUTE_127}, {MAPSEC_UNDERWATER_127, MAPSEC_ROUTE_127},
{MAPSEC_UNDERWATER_128, MAPSEC_ROUTE_128}, {MAPSEC_UNDERWATER_128, MAPSEC_ROUTE_128},
+3 -2
View File
@@ -463,8 +463,9 @@ static const struct WindowTemplate sWindowTemplates[] =
.paletteNum = 15, .paletteNum = 15,
.baseBlock = 0xC5 .baseBlock = 0xC5
}, },
// BUG: Array not terminated properly #ifdef UBFIX
//DUMMY_WIN_TEMPLATE DUMMY_WIN_TEMPLATE,
#endif
}; };
static const struct GridSelection sGridSelections[NUM_GRID_SELECTIONS + 1] = static const struct GridSelection sGridSelections[NUM_GRID_SELECTIONS + 1] =
+9 -1
View File
@@ -478,7 +478,11 @@ static void Task_TryBecomeLinkLeader(u8 taskId)
// BUG: sPlayerActivityGroupSize was meant below, not gPlayerCurrActivity // BUG: sPlayerActivityGroupSize was meant below, not gPlayerCurrActivity
// This will be false for all but ACTIVITY_BATTLE_DOUBLE and ACTIVITY_DECLINE // This will be false for all but ACTIVITY_BATTLE_DOUBLE and ACTIVITY_DECLINE
// All this changes is which of two texts gets printed // All this changes is which of two texts gets printed
#ifdef BUGFIX
id = (GROUP_MAX(sPlayerActivityGroupSize) == 2) ? 0 : 1;
#else
id = (GROUP_MAX(gPlayerCurrActivity) == 2) ? 1 : 0; id = (GROUP_MAX(gPlayerCurrActivity) == 2) ? 1 : 0;
#endif
if (PrintOnTextbox(&data->textState, sPlayerUnavailableTexts[id])) if (PrintOnTextbox(&data->textState, sPlayerUnavailableTexts[id]))
{ {
data->playerCount = sub_8013398(data->field_0); data->playerCount = sub_8013398(data->field_0);
@@ -1320,7 +1324,11 @@ static bool32 IsPartnerActivityAcceptable(u32 activity, u32 linkGroup)
if (linkGroup == 0xFF) if (linkGroup == 0xFF)
return TRUE; return TRUE;
if (linkGroup <= ARRAY_COUNT(sAcceptedActivityIds)) // UB: <= may access data outside the array #ifdef UBFIX
if (linkGroup < ARRAY_COUNT(sAcceptedActivityIds))
#else
if (linkGroup <= ARRAY_COUNT(sAcceptedActivityIds))
#endif
{ {
const u8 *bytes = sAcceptedActivityIds[linkGroup]; const u8 *bytes = sAcceptedActivityIds[linkGroup];