Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 35 additions & 11 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,6 @@ jobs:
- name: Checkout
if: ${{ github.event_name == 'push' }}
uses: actions/checkout@master

- name: Checkout gh-pages
if: ${{ github.event_name == 'push' }}
uses: actions/checkout@master
with:
path: gh-pages
ref: gh-pages

- name: Checkout agbcc
uses: actions/checkout@master
Expand All @@ -58,8 +51,11 @@ jobs:

- name: Install tools
run: |
sudo apt update && sudo apt install gcc-arm-none-eabi binutils-arm-none-eabi
sudo apt update && sudo apt install gcc-arm-none-eabi binutils-arm-none-eabi xorg-dev
python3 -m pip install gitpython
# build-essential, git, and libpng-dev are already installed
# gcc-arm-none-eabi is only needed for the modern build
# as an alternative to dkP

- name: Install agbcc
run: |
Expand All @@ -78,7 +74,6 @@ jobs:
python3 scripts/progress.py text

- name: Generate reports
if: ${{ github.event_name == 'push' }}
run: |
mkdir -p gh-pages/reports
mkdir -p gh-pages/maps
Expand All @@ -88,8 +83,37 @@ jobs:
python3 scripts/progress.py shield-json -m > gh-pages/reports/progress-sa1-shield-matching.json
echo "REPORTS_COMMIT_MSG=$( git log --format=%s ${GITHUB_SHA} )" >> $GITHUB_ENV
cp sa1.map gh-pages/maps/${GITHUB_SHA}.map

- name: Update reports

- name: Upload progress
if: ${{ github.event_name == 'push' || github.event_name == 'pull_request' }}
uses: actions/upload-artifact@v7
with:
path: |
gh-pages

publish-progress:
name: Publish progress
runs-on: ubuntu-24.04
needs: [build-gba]
# Only able to run from repo pull requests (by maintainers, or on the main branch via push)
if: ${{ github.event_name == 'push' || github.event_name == 'pull_request' }}
permissions:
contents: write
steps:
- name: Checkout gh-pages
uses: actions/checkout@master
with:
path: gh-pages
ref: gh-pages
- name: Download progress
uses: actions/download-artifact@v7
with:
path: |
gh-pages
- run: |
cd gh-pages
git status
- name: Publish reports
if: ${{ github.event_name == 'push' }}
uses: EndBug/add-and-commit@v7
with:
Expand Down
6 changes: 3 additions & 3 deletions include/constants/zones.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@
#define IS_EXTRA_STAGE(lvl) ((lvl) == LEVEL_INDEX(ZONE_FINAL, ACT_THE_MOON))
#define IS_FINAL_OR_EXTRA_STAGE(lvl) ((IS_FINAL_STAGE(lvl)) || (IS_EXTRA_STAGE(lvl)))

#define ZONE_TIME_TO_INT(minutes, seconds) (int)(((minutes * 60.) + seconds) * GBA_FRAMES_PER_SECOND)
#define TIMER_WARNING_BEGIN (ZONE_TIME_TO_INT(0, 20))
#define MAX_COURSE_TIME (ZONE_TIME_TO_INT(10, 0))
#define TIME(minutes, seconds) (int)(((minutes * 60.) + seconds) * GBA_FRAMES_PER_SECOND)
#define TIMER_WARNING_BEGIN (TIME(0, 20))
#define MAX_COURSE_TIME (TIME(10, 0))

#define SPECIAL_STAGE_REQUIRED_SP_RING_COUNT 7

Expand Down
10 changes: 5 additions & 5 deletions include/game/parameters/characters.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
#define PLAYER_MAX_FLOATING_SPEED (2.25)

// NOTE: Equal in SA1 and SA2!
#define PLAYER_INVULNERABLE_DURATION ZONE_TIME_TO_INT(0, 2)
#define PLAYER_INVINCIBLE_DURATION ZONE_TIME_TO_INT(0, 20)
#define PLAYER_SPEED_UP_DURATION ZONE_TIME_TO_INT(0, 20)
#define PLAYER_INVULNERABLE_DURATION TIME(0, 2)
#define PLAYER_INVINCIBLE_DURATION TIME(0, 20)
#define PLAYER_SPEED_UP_DURATION TIME(0, 20)
#define PLAYER_SPEED_UP_MUSIC_TEMPO Q(2.0)

#define PLAYER_AIR_SPEED_MAX 15.0
Expand All @@ -39,13 +39,13 @@
#define TRICK__STOP_N_SLAM__DROP_SPEED Q(0.21875)

/*** Cream ***/
#define CREAM_FLYING_DURATION ZONE_TIME_TO_INT(0, 4)
#define CREAM_FLYING_DURATION TIME(0, 4)

/*** Tails ***/
// NOTE: Unlike Cream, Tails does fly for 8 seconds, but his initial value gets set to 4.
// For some reason they lower his timer only every 2nd frame (in PlayerCB_8012C2C),
// instead of using a bigger value from the get-go, even though they gave him a
// 4-byte timer.
#define TAILS_FLYING_DURATION (ZONE_TIME_TO_INT(0, 8) / 2)
#define TAILS_FLYING_DURATION (TIME(0, 8) / 2)

#endif // GUARD_PARAMETERS_CHARACTERS_H
10 changes: 5 additions & 5 deletions src/game/egg_rocket_transitions.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ NONMATCH("asm/non_matching/game/egg_rocket_trans__Task_80294A8.inc", void Task_8

if (gGameMode == GAME_MODE_SINGLE_PLAYER) {
gStageFlags |= FLAGS_EXECUTE_HBLANK_COPY;
gCourseTime = ZONE_TIME_TO_INT(5, 0);
gCourseTime = TIME(5, 0);
}
}

Expand All @@ -368,7 +368,7 @@ NONMATCH("asm/non_matching/game/egg_rocket_trans__Task_80294A8.inc", void Task_8

if (gGameMode == GAME_MODE_SINGLE_PLAYER) {
gStageFlags |= FLAGS_EXECUTE_HBLANK_COPY;
gCourseTime = ZONE_TIME_TO_INT(5, 0);
gCourseTime = TIME(5, 0);
}
}

Expand Down Expand Up @@ -399,7 +399,7 @@ void Task_80297E8(void)
if (--shake->unkC == 0) {
if (gGameMode == GAME_MODE_SINGLE_PLAYER) {
gStageFlags |= STAGE_FLAG__TIMER_REVERSED;
gCourseTime = ZONE_TIME_TO_INT(5, 0);
gCourseTime = TIME(5, 0);
}

gPlayer.moveState &= ~MOVESTATE_IGNORE_INPUT;
Expand All @@ -415,7 +415,7 @@ void CreateEggRocketLaunchScreenShakeEffect()
struct Task *t = TaskCreate(Task_80298C0, sizeof(EggRocketScreenShake), 0x4000, 0, NULL);
EggRocketScreenShake *shake = TASK_DATA(t);

shake->unkC = ZONE_TIME_TO_INT(0, 1);
shake->unkC = TIME(0, 1);

CreateScreenShake(0x800, 8, 16, 10, SCREENSHAKE_VERTICAL);

Expand All @@ -429,7 +429,7 @@ void Task_80298C0()
EggRocketScreenShake *shake = TASK_DATA(gCurTask);

if (--shake->unkC == 0) {
shake->unkC = ZONE_TIME_TO_INT(0, 5);
shake->unkC = TIME(0, 5);
CreateScreenShake(0x800, 8, 16, 300, (SCREENSHAKE_VERTICAL | SCREENSHAKE_RANDOM_VALUE));
gCurTask->main = Task_80297E8;
}
Expand Down
2 changes: 1 addition & 1 deletion src/game/enemies/boss_3_egg_ball.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ void CreateEntity_EggBall(MapEntity *me, u16 regionX, u16 regionY, u8 id)
t = TaskCreate(Task_PipeInitialDelay, sizeof(EggBall_Pipe), 0x2200U, 0U, TaskDestructor_8030754);
strc = TASK_DATA(t);
strc->unk44 = i;
strc->delay = ZONE_TIME_TO_INT(0, 1.5);
strc->delay = TIME(0, 1.5);
strc->unk3C = unk3C = gUnknown_084ACDD2[i][0][0];
strc->unk3E = unk3E = gUnknown_084ACDD2[i][0][1];
strc->base.regionX = boss->base.regionX;
Expand Down
2 changes: 1 addition & 1 deletion src/game/enemies/bosses_egg_mobile.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ void Task_EggMobileAscent()
UpdateSpriteAnimation(s2);
DisplaySprite(s2);

if (eggMobile->stunDelay > ZONE_TIME_TO_INT(0, 0.75)) {
if (eggMobile->stunDelay > TIME(0, 0.75)) {
eggMobile->offsetY -= Q(1);

if (eggMobile->offsetY <= -Q(80)) {
Expand Down
2 changes: 1 addition & 1 deletion src/game/enemies/bosses_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ void Task_801623C()

if ((Coll_Player_Entity_Intersection(s, capsule->worldX, capsule->worldY, p) & 0x80000)
|| (Coll_Player_Entity_Intersection(s2, capsule->worldX, capsule->worldY, p) & 0x80000)) {
p->timerInvulnerability = ZONE_TIME_TO_INT(0, 2);
p->timerInvulnerability = TIME(0, 2);
if (I(p->qWorldX) < gCamera.x + (DISPLAY_WIDTH / 2)) {
p->qSpeedAirX = -Q(2);
sideX = (capsule->worldX + s->hitboxes[0].b.left) - p->spriteOffsetX;
Expand Down
2 changes: 1 addition & 1 deletion src/game/enemies/fireball.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include "constants/zones.h"

#define NUM_SPARKS 2
#define FIREBALL_SPAWN_RATE ZONE_TIME_TO_INT(0, 4)
#define FIREBALL_SPAWN_RATE TIME(0, 4)

typedef struct {
/* 0x00 */ MapEntity *me;
Expand Down
2 changes: 1 addition & 1 deletion src/game/enemies/mirror.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ void Task_MirrorShoot(void)
}
}

if (mirror->frames == ZONE_TIME_TO_INT(0, 1)) {
if (mirror->frames == TIME(0, 1)) {
s->variant = 0;
gCurTask->main = Task_Mirror;
}
Expand Down
4 changes: 2 additions & 2 deletions src/game/enemies/mole.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ void Task_Mole(void)
return;
}

if (++mole->frames >= ZONE_TIME_TO_INT(0, 1)) {
if (++mole->frames >= TIME(0, 1)) {
mole->frames = 0;
s->variant = 1;

Expand Down Expand Up @@ -118,7 +118,7 @@ void Task_Mole_8071640(void)
return;
}

if (++mole->frames >= ZONE_TIME_TO_INT(0, 1)) {
if (++mole->frames >= TIME(0, 1)) {
mole->frames = 0;
s->variant = 0;
gCurTask->main = Task_Mole;
Expand Down
8 changes: 4 additions & 4 deletions src/game/game_over.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ void Task_GameOverScreenInit(void)

screen->frames = ++frames;

if (frames >= ZONE_TIME_TO_INT(0, 1)) {
if (frames >= TIME(0, 1)) {
screen->s.frameFlags = 0;
screen->s2.frameFlags = 0;
gCurTask->main = Task_8056100;
Expand Down Expand Up @@ -297,7 +297,7 @@ void Task_8056100(void)

screen->frames = ++frames;

if (frames >= ZONE_TIME_TO_INT(0, 1.5)) {
if (frames >= TIME(0, 1.5)) {
gCurTask->main = Task_805618C;
}

Expand All @@ -324,7 +324,7 @@ void Task_805618C(void)

screen->frames = ++frames;

if (frames >= ZONE_TIME_TO_INT(0, 2)) {
if (frames >= TIME(0, 2)) {
s->frameFlags = SPRITE_OAM_ORDER(2);
s2->frameFlags = SPRITE_OAM_ORDER(2);

Expand Down Expand Up @@ -678,7 +678,7 @@ NONMATCH("asm/non_matching/game/game_over__Task_805676C.inc", void Task_805676C(
}
}

if (unk24 >= ZONE_TIME_TO_INT(0, 20)) {
if (unk24 >= TIME(0, 20)) {
gCurTask->main = Task_DestroyGameOverD;
}

Expand Down
2 changes: 1 addition & 1 deletion src/game/interactables/boulder_spawner.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "constants/vram_hardcoded.h"
#include "constants/zones.h"

#define BOULDER_SPAWN_RATE ZONE_TIME_TO_INT(0, 2)
#define BOULDER_SPAWN_RATE TIME(0, 2)

typedef struct {
/* 0x00 */ SpriteBase base;
Expand Down
4 changes: 2 additions & 2 deletions src/game/interactables/stage_goal.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ void Task_StageGoal2(void)

if (count == 0) {
gStageFlags |= STAGE_FLAG__TIMER_REVERSED;
gCourseTime = ZONE_TIME_TO_INT(1, 0);
gCourseTime = TIME(1, 0);
}

gPlayer.moveState |= MOVESTATE_IGNORE_INPUT;
Expand Down Expand Up @@ -371,7 +371,7 @@ void Task_StageGoal2(void)
}

gStageFlags |= STAGE_FLAG__TIMER_REVERSED;
gCourseTime = ZONE_TIME_TO_INT(1, 0);
gCourseTime = TIME(1, 0);

gPlayer.moveState |= MOVESTATE_IGNORE_INPUT;
gPlayer.heldInput = DPAD_RIGHT;
Expand Down
2 changes: 1 addition & 1 deletion src/game/interactables/underwater_lava_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include "constants/songs.h"
#include "constants/zones.h"

#define LAVA_SPURT_RATE ZONE_TIME_TO_INT(0, 1.7)
#define LAVA_SPURT_RATE TIME(0, 1.7)

typedef struct {
/* 0x00 */ SpriteBase base;
Expand Down
4 changes: 2 additions & 2 deletions src/game/multiplayer/hud.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,12 @@ NONMATCH("asm/non_matching/game/multiplayer/results_2__Task_ChaoHuntHUD.inc", vo
hud = TASK_DATA(gCurTask);

// Show the red timer every 2 frames, lasting 2 frames
if (((u32)gCourseTime < ZONE_TIME_TO_INT(1, 0)) && (gCourseTime & 2)) {
if (((u32)gCourseTime < TIME(1, 0)) && (gCourseTime & 2)) {
timerSprites = hud->spritesB;
} else {
timerSprites = hud->spritesA;
}
if (!(1 & gStageFlags) && (gCourseTime < ZONE_TIME_TO_INT(1, 0)) && (Mod(gCourseTime, 60) == 0)) {
if (!(1 & gStageFlags) && (gCourseTime < TIME(1, 0)) && (Mod(gCourseTime, 60) == 0)) {
m4aSongNumStart(SE_TIMER);
}
s = &timerSprites[10];
Expand Down
2 changes: 1 addition & 1 deletion src/game/multiplayer/mp_player.c
Original file line number Diff line number Diff line change
Expand Up @@ -1948,7 +1948,7 @@ bool32 SA2_LABEL(sub_8018300)(void)
if (gMultiplayerCharacters[mpp->unk56] == 3) {
if (s->graphics.anim == SA1_ANIM_CHAR(AMY, BOOSTLESS_ATTACK) || s->graphics.anim == SA1_ANIM_CHAR(AMY, 56)) {
gPlayer.itemEffect |= PLAYER_ITEM_EFFECT__MP_SLOW_DOWN;
gPlayer.timerSpeedup = ZONE_TIME_TO_INT(0, 10);
gPlayer.timerSpeedup = TIME(0, 10);
gPlayer.itemEffect &= ~PLAYER_ITEM_EFFECT__SPEED_UP;
CreateItemTask_Confusion(gPlayer.character);
m4aMPlayTempoControl(&gMPlayInfo_BGM, Q(0.5));
Expand Down
8 changes: 4 additions & 4 deletions src/game/multiplayer/multiplayer_event_mgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ void ReceiveRoomEvent_ItemEffect(union MultiSioData *recv, u8 i)
|| ((gMultiplayerConnections & (0x10 << (i))) >> ((i + 4))
!= (gMultiplayerConnections & (0x10 << (SIO_MULTI_CNT->id))) >> (SIO_MULTI_CNT->id + 4))) {
gPlayer.itemEffect |= PLAYER_ITEM_EFFECT__CONFUSION;
gPlayer.timerConfusion = ZONE_TIME_TO_INT(0, 10);
gPlayer.timerConfusion = TIME(0, 10);
CreateItemTask_Confusion(gPlayer.character);
#if (GAME == GAME_SA2)
m4aSongNumStart(SE_ITEM_CONFUSION);
Expand Down Expand Up @@ -177,7 +177,7 @@ void ReceiveRoomEvent_ItemEffect(union MultiSioData *recv, u8 i)
gPlayer.layer = (mpp->unk54 >> 7) & 1;
gPlayer.moveState |= MOVESTATE_IN_AIR;
mpp->unk60 = 30;
gPlayer.timerInvulnerability = ZONE_TIME_TO_INT(0, 2);
gPlayer.timerInvulnerability = TIME(0, 2);
gCamera.x = (I(gPlayer.qWorldX) + gCamera.shiftX) - (DISPLAY_WIDTH / 2);
gCamera.y = (I(gPlayer.qWorldY) + gCamera.shiftY) - (DISPLAY_HEIGHT / 2);
#if (GAME == GAME_SA2)
Expand All @@ -192,7 +192,7 @@ void ReceiveRoomEvent_ItemEffect(union MultiSioData *recv, u8 i)
|| ((gMultiplayerConnections & (0x10 << (i))) >> ((i + 4))
!= (gMultiplayerConnections & (0x10 << (SIO_MULTI_CNT->id))) >> (SIO_MULTI_CNT->id + 4))) {
gPlayer.itemEffect |= PLAYER_ITEM_EFFECT__MP_SLOW_DOWN;
gPlayer.timerSpeedup = ZONE_TIME_TO_INT(0, 10);
gPlayer.timerSpeedup = TIME(0, 10);
gPlayer.itemEffect &= ~PLAYER_ITEM_EFFECT__SPEED_UP;
CreateItemTask_Confusion(gPlayer.character);
m4aMPlayTempoControl(&gMPlayInfo_BGM, Q(0.5));
Expand Down Expand Up @@ -304,7 +304,7 @@ NONMATCH("asm/non_matching/game/multiplayer/evt_mgr__ReceiveRoomEvent_ReachedSta

if (count2 == 0 && !(gStageFlags & 1)) {
gStageFlags |= 4;
gCourseTime = ZONE_TIME_TO_INT(1, 0);
gCourseTime = TIME(1, 0);
};

if ((count3 + 1) >= (u32)(count - 1) || gGameMode == GAME_MODE_MULTI_PLAYER || gGameMode == GAME_MODE_TEAM_PLAY) {
Expand Down
4 changes: 2 additions & 2 deletions src/game/sa1_sa2_shared/demo_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
#if (GAME == GAME_SA1)
#define DEMO_SPRITE_PRIO 1
#define DEMO_OAM_ORDER 15
#define DEMO_PLAYBACK_TIME ZONE_TIME_TO_INT(0, 30)
#define DEMO_PLAYBACK_TIME TIME(0, 30)
#elif (GAME == GAME_SA2)
#define DEMO_SPRITE_PRIO 0
#define DEMO_OAM_ORDER 1
#define DEMO_PLAYBACK_TIME ZONE_TIME_TO_INT(0, 24.5)
#define DEMO_PLAYBACK_TIME TIME(0, 24.5)
#endif

typedef struct {
Expand Down
4 changes: 2 additions & 2 deletions src/game/sa1_sa2_shared/itembox.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
#include "constants/songs.h"
#include "constants/zones.h"

#define ITEM_DURATION_INVINCIBILITY ZONE_TIME_TO_INT(0, 20)
#define ITEM_DURATION_SPEED_UP ZONE_TIME_TO_INT(0, 20)
#define ITEM_DURATION_INVINCIBILITY TIME(0, 20)
#define ITEM_DURATION_SPEED_UP TIME(0, 20)

typedef struct {
/* 0x00|0x00 */ SpriteBase base;
Expand Down
Loading
Loading