This commit is contained in:
Adrienn Tindall 2025-09-01 20:01:00 -04:00
commit 75c0962388
38 changed files with 83 additions and 72 deletions

View File

@ -62,7 +62,7 @@ sub: ; @$(MAKE) -C sub
ROMSPEC := rom.rsf
MAKEROM_FLAGS := $(DEFINES)
$(ALL_OBJS): files_for_compile
$(ALL_GAME_OBJS): files_for_compile
$(ELF): files_for_compile libsyscall
libsyscall: files_for_compile
@ -90,7 +90,9 @@ FX_CONST_H := $(WORK_DIR)/lib/include/nitro/fx/fx_const.h
PROJECT_CLEAN_TARGETS += $(FX_CONST_H)
$(FX_CONST_H): $(MKFXCONST) $(TOOLSDIR)/gen_fx_consts/fx_const.csv
$(MKFXCONST) $@
sdk: $(FX_CONST_H)
$(ALL_LIB_OBJS): $(FX_CONST_H)
sdk9: $(ALL_LIB_OBJS)
$(WORK_DIR)/include/global.h: $(FX_CONST_H) ;
# Convenience targets

View File

@ -44,7 +44,7 @@
.public Save_PlayerData_GetProfile
.public Save_PlayerData_GetCoinsAddr
.public PlayerProfile_GetMoney
.public CheckCoins
.public Coins_GetValue
.public FrontierData_BattlePointAction
.public Save_FrontierData_Get
.public SaveData_GetPhoneCallPersistentState

View File

@ -2354,7 +2354,7 @@ _021EECBA:
add r4, r0, #0
ldr r0, [r5, #0xc]
bl Save_PlayerData_GetCoinsAddr
bl CheckCoins
bl Coins_GetValue
add r2, r0, #0
b _021EED04
_021EECD2:

View File

@ -15,7 +15,7 @@ gTrainerPoke_{{ i }}:
.byte {{ poke.difficulty }}
.byte {{ poke.genderOverride }} | ({{ poke.abilityOverride }} << 4)
.short {{ poke.level }}
.short {{ poke.species }}{% if existsIn(poke, "item") %}
.short {{ poke.species }}{% if existsIn(poke, "form") %} | ({{ poke.form }} << 10){% endif %}{% if existsIn(poke, "item") %}
.short {{ poke.item }}{% endif %}{% if existsIn(poke, "moves") %}{% for move in poke.moves %}
.short {{ move }}{% endfor %}{% for k in range(4 - length(poke.moves)) %}
.short MOVE_NONE{% endfor %}{% endif %}

View File

@ -258,7 +258,7 @@ typedef struct BattleMon {
u8 unk78;
u8 msgFlag;
u8 gender : 4;
u8 metGender : 4;
u8 otGender : 4;
u8 ball;
u32 moveEffectFlags;
u32 moveEffectFlagsTemp;

View File

@ -6,44 +6,52 @@
#define MAX_COINS 50000
/*
* void InitCoins(u16 *coins)
*
* Initialize the player's coin case
*
* @param coins: Pointer to coin case amount
* @param coins: Pointer to coin case amount
*/
void InitCoins(u16 *coins);
void Coins_Init(u16 *coins);
/*
* u16 CheckCoins(u16* coins)
*
* Gets the amount of coins owned
*
* @param coins: Pointer to coin case amount
* @param coins: Pointer to coin case amount
*
* @returns: The amount of coins owned
*/
u16 CheckCoins(u16 *coins);
u16 Coins_GetValue(u16 *coins);
/*
* BOOL GiveCoins(u16* coins, u16 amount)
* BOOL CanGiveCoins(u16* coins, u16 amount)
* BOOL TakeCoins(u16* coins, u16 amount)
* Adds an amount of coins. It will fail if the
* coin case would overflow.
*
* GiveCoins adds an amount of coins. It will fail if the
* coin case would overflow.
* CanGiveCoins follows the same logic but does not modify
* the coin case, instead only reports success or failure.
* TakeCoins deducts the amount of coins. It will fail if
* the coin case would underflow.
*
* @param coins: Pointer to coin case amount
* @param amount: Number of coins to adjust by
* @param coins: Pointer to coin case amount
* @param amount: Number of coins to add
*
* @returns: TRUE if success, otherwise FALSE
*/
BOOL GiveCoins(u16 *coins, u16 amount);
BOOL CanGiveCoins(u16 *coins, u16 amount);
BOOL TakeCoins(u16 *coins, u16 amount);
BOOL Coins_Add(u16 *coins, u16 amount);
/*
* Checks if a certain amount of coins can be
* added to the coin case without making it overflow.
*
* @param coins: Pointer to coin case amount
* @param amount: Number of coins to add
*
* @returns: TRUE if success, otherwise FALSE
*/
BOOL Coins_CanAdd(u16 *coins, u16 amount);
/*
* Subtracts an amount of coins. It will fail if the
* coin case would overflow.
*
* @param coins: Pointer to coin case amount
* @param amount: Number of coins to subtract
*
* @returns: TRUE if success, otherwise FALSE
*/
BOOL Coins_Subtract(u16 *coins, u16 amount);
#endif // POKEHEARTGOLD_COINS_H

View File

@ -315,7 +315,7 @@
#define MON_DATA_POKERUS 154
#define MON_DATA_POKEBALL 155
#define MON_DATA_MET_LEVEL 156
#define MON_DATA_MET_GENDER 157
#define MON_DATA_OT_GENDER 157
#define MON_DATA_ENCOUNTER_TYPE 158 // HGSS
#define MON_DATA_RESERVED_159 159
#define MON_DATA_STATUS 160

View File

@ -104,7 +104,7 @@ typedef struct {
/* 0x1A */ u8 pokerus;
/* 0x1B */ u8 pokeball;
/* 0x1C */ u8 metLevel : 7;
u8 metGender : 1;
u8 otGender : 1;
/* 0x1D */ u8 encounterType;
/* 0x1E */ u8 HGSS_Pokeball;
/* 0x1F */ s8 mood;

View File

@ -90,7 +90,7 @@ u8 sub_0207791C(BagView *bagView) {
}
static u16 GetCoinCount(SaveData *saveData) {
return CheckCoins(Save_PlayerData_GetCoinsAddr(saveData));
return Coins_GetValue(Save_PlayerData_GetCoinsAddr(saveData));
}
static u32 GetSealCount(SaveData *saveData) {

View File

@ -119,7 +119,7 @@ void BattleSystem_GetBattleMon(BattleSystem *battleSystem, BattleContext *ctx, i
ctx->battleMons[battlerId].exp = GetMonData(mon, MON_DATA_EXPERIENCE, NULL);
ctx->battleMons[battlerId].personality = GetMonData(mon, MON_DATA_PERSONALITY, NULL);
ctx->battleMons[battlerId].otid = GetMonData(mon, MON_DATA_OTID, NULL);
ctx->battleMons[battlerId].metGender = GetMonData(mon, MON_DATA_MET_GENDER, NULL);
ctx->battleMons[battlerId].otGender = GetMonData(mon, MON_DATA_OT_GENDER, NULL);
ctx->battleMons[battlerId].ball = BattleSystem_GetMonBall(battleSystem, mon);
@ -395,7 +395,7 @@ int GetBattlerVar(BattleContext *ctx, int battlerId, u32 id, void *data) {
case BMON_DATA_MSG_FLAG:
return mon->msgFlag;
case BMON_DATA_OT_GENDER:
return mon->metGender;
return mon->otGender;
case BMON_DATA_MOVE_EFFECT:
return mon->moveEffectFlags;
case BMON_DATA_MOVE_EFFECT_TEMP:
@ -639,7 +639,7 @@ void SetBattlerVar(BattleContext *ctx, int battlerId, u32 id, void *data) {
mon->msgFlag = *data8;
break;
case BMON_DATA_OT_GENDER:
mon->metGender = *data8;
mon->otGender = *data8;
break;
case BMON_DATA_MOVE_EFFECT:
mon->moveEffectFlags = *data32;
@ -5254,7 +5254,7 @@ BOOL ov12_02256854(BattleSystem *battleSystem, BattleContext *ctx) {
u32 gender = PlayerProfile_GetTrainerGender(profile);
const u16 *name = PlayerProfile_GetNamePtr(profile);
if (trainerId == ctx->battleMons[ctx->battlerIdAttacker].otid && gender == ctx->battleMons[ctx->battlerIdAttacker].metGender && !StringNotEqualN(name, &ctx->battleMons[ctx->battlerIdAttacker].otName[0], PLAYER_NAME_LENGTH)) {
if (trainerId == ctx->battleMons[ctx->battlerIdAttacker].otid && gender == ctx->battleMons[ctx->battlerIdAttacker].otGender && !StringNotEqualN(name, &ctx->battleMons[ctx->battlerIdAttacker].otName[0], PLAYER_NAME_LENGTH)) {
return TRUE;
}
@ -5270,7 +5270,7 @@ BOOL ov12_022568B0(BattleSystem *battleSystem, Pokemon *mon) {
GetMonData(mon, MON_DATA_OT_NAME, otName);
if (trainerId == GetMonData(mon, MON_DATA_OTID, NULL) && gender == GetMonData(mon, MON_DATA_MET_GENDER, NULL) && !StringNotEqualN(name, otName, PLAYER_NAME_LENGTH)) {
if (trainerId == GetMonData(mon, MON_DATA_OTID, NULL) && gender == GetMonData(mon, MON_DATA_OT_GENDER, NULL) && !StringNotEqualN(name, otName, PLAYER_NAME_LENGTH)) {
return TRUE;
}

View File

@ -2,20 +2,21 @@
#include "global.h"
void InitCoins(u16 *coins) {
void Coins_Init(u16 *coins) {
*coins = 0;
}
u16 CheckCoins(u16 *coins) {
u16 Coins_GetValue(u16 *coins) {
return *coins;
}
BOOL GiveCoins(u16 *coins, u16 amount) {
BOOL Coins_Add(u16 *coins, u16 amount) {
if (*coins >= MAX_COINS) {
return FALSE;
}
*coins += amount;
if (*coins > MAX_COINS) {
*coins = MAX_COINS;
}
@ -23,11 +24,11 @@ BOOL GiveCoins(u16 *coins, u16 amount) {
return TRUE;
}
BOOL CanGiveCoins(u16 *coins, u16 amount) {
BOOL Coins_CanAdd(u16 *coins, u16 amount) {
return (u32)(amount + *coins) <= MAX_COINS;
}
BOOL TakeCoins(u16 *coins, u16 amount) {
BOOL Coins_Subtract(u16 *coins, u16 amount) {
if (*coins < amount) {
return FALSE;
}

View File

@ -657,7 +657,7 @@ void SetEggStats(Pokemon *mon, int species, u8 metLocation, PlayerProfile *profi
name = PlayerProfile_GetPlayerName_NewString(profile, HEAP_ID_32);
SetMonData(mon, MON_DATA_OT_NAME_2, name);
SetMonData(mon, MON_DATA_OTID, &otId);
SetMonData(mon, MON_DATA_MET_GENDER, &gender);
SetMonData(mon, MON_DATA_OT_GENDER, &gender);
String_Delete(name);
}
MonSetTrainerMemo(mon, profile, trainerMemoStrat, eggLocation, HEAP_ID_DEFAULT);
@ -1045,7 +1045,7 @@ static void sub_0206D038(Pokemon *mon, HeapID heapId) {
pokerus = GetMonData(mon, MON_DATA_POKERUS, NULL);
fateful = GetMonData(mon, MON_DATA_FATEFUL_ENCOUNTER, NULL);
GetMonData(mon, MON_DATA_OT_NAME_2, string);
otGender = GetMonData(mon, MON_DATA_MET_GENDER, NULL);
otGender = GetMonData(mon, MON_DATA_OT_GENDER, NULL);
otId = GetMonData(mon, MON_DATA_OTID, NULL);
form = GetMonData(mon, MON_DATA_FORM, NULL);
if (species == SPECIES_MANAPHY && GetMonData(mon, MON_DATA_EGG_MET_LOCATION, NULL) == sub_02017FE4(MAPSECTYPE_EXTERNAL, 1)) {
@ -1071,7 +1071,7 @@ static void sub_0206D038(Pokemon *mon, HeapID heapId) {
SetMonData(tmpMon, MON_DATA_POKERUS, &pokerus);
SetMonData(tmpMon, MON_DATA_FATEFUL_ENCOUNTER, &fateful);
SetMonData(tmpMon, MON_DATA_OT_NAME_2, string);
SetMonData(tmpMon, MON_DATA_MET_GENDER, &otGender);
SetMonData(tmpMon, MON_DATA_OT_GENDER, &otGender);
SetMonData(tmpMon, MON_DATA_OTID, &otId);
SetMonData(tmpMon, MON_DATA_FORM, &form);
metLoc = GetMonData(mon, MON_DATA_EGG_MET_LOCATION, NULL);

View File

@ -223,7 +223,7 @@ static void _CreateTradeMon(Pokemon *mon, NPCTrade *trade_dat, u32 level, NpcTra
SetMonData(mon, MON_DATA_OT_NAME_2, name);
String_Delete(name);
SetMonData(mon, MON_DATA_MET_GENDER, &trade_dat->gender);
SetMonData(mon, MON_DATA_OT_GENDER, &trade_dat->gender);
SetMonData(mon, MON_DATA_GAME_LANGUAGE, &trade_dat->language);
mapsec = MapHeader_GetMapSec(mapno);

View File

@ -33,28 +33,28 @@ BOOL ScrCmd_118(ScriptContext *ctx) {
BOOL ScrCmd_GetCoinAmount(ScriptContext *ctx) {
u16 *ptr = ScriptGetVarPointer(ctx);
*ptr = CheckCoins(Save_PlayerData_GetCoinsAddr(ctx->fieldSystem->saveData));
*ptr = Coins_GetValue(Save_PlayerData_GetCoinsAddr(ctx->fieldSystem->saveData));
return FALSE;
}
BOOL ScrCmd_GiveCoins(ScriptContext *ctx) {
FieldSystem *fieldSystem = ctx->fieldSystem;
u16 amount = ScriptGetVar(ctx);
GiveCoins(Save_PlayerData_GetCoinsAddr(fieldSystem->saveData), amount);
Coins_Add(Save_PlayerData_GetCoinsAddr(fieldSystem->saveData), amount);
return FALSE;
}
BOOL ScrCmd_TakeCoins(ScriptContext *ctx) {
FieldSystem *fieldSystem = ctx->fieldSystem;
u16 amount = ScriptGetVar(ctx);
TakeCoins(Save_PlayerData_GetCoinsAddr(fieldSystem->saveData), amount);
Coins_Subtract(Save_PlayerData_GetCoinsAddr(fieldSystem->saveData), amount);
return FALSE;
}
BOOL ScrCmd_569(ScriptContext *ctx) {
FieldSystem *fieldSystem = ctx->fieldSystem;
u16 *ptr = ScriptGetVarPointer(ctx);
TakeCoins(Save_PlayerData_GetCoinsAddr(fieldSystem->saveData), *ptr);
Coins_Subtract(Save_PlayerData_GetCoinsAddr(fieldSystem->saveData), *ptr);
return FALSE;
}
@ -62,7 +62,7 @@ BOOL ScrCmd_CheckCoinsImmediate(ScriptContext *ctx) {
FieldSystem *fieldSystem = ctx->fieldSystem;
u16 *ptr = ScriptGetVarPointer(ctx);
u32 amount = ScriptReadWord(ctx);
u16 coins = CheckCoins(Save_PlayerData_GetCoinsAddr(fieldSystem->saveData));
u16 coins = Coins_GetValue(Save_PlayerData_GetCoinsAddr(fieldSystem->saveData));
if (coins < amount) {
*ptr = FALSE;
} else {
@ -75,7 +75,7 @@ BOOL ScrCmd_CheckCoinsVar(ScriptContext *ctx) {
FieldSystem *fieldSystem = ctx->fieldSystem;
u16 *resultPtr = ScriptGetVarPointer(ctx);
u16 *amountPtr = ScriptGetVarPointer(ctx);
u16 coins = CheckCoins(Save_PlayerData_GetCoinsAddr(fieldSystem->saveData));
u16 coins = Coins_GetValue(Save_PlayerData_GetCoinsAddr(fieldSystem->saveData));
if (coins < *amountPtr) {
*resultPtr = FALSE;
} else {
@ -88,7 +88,7 @@ BOOL ScrCmd_CheckGiveCoins(ScriptContext *ctx) {
FieldSystem *fieldSystem = ctx->fieldSystem;
u16 *ptr = ScriptGetVarPointer(ctx);
u16 amount = ScriptGetVar(ctx);
*ptr = CanGiveCoins(Save_PlayerData_GetCoinsAddr(fieldSystem->saveData), amount);
*ptr = Coins_CanAdd(Save_PlayerData_GetCoinsAddr(fieldSystem->saveData), amount);
return FALSE;
}

View File

@ -11,7 +11,7 @@ void Save_PlayerData_Init(PLAYERDATA *player) {
Options_Init(&player->options);
PlayerProfile_Init(&player->profile);
InitCoins(&player->coins);
Coins_Init(&player->coins);
InitIGT(&player->igt);
}

View File

@ -840,8 +840,8 @@ static u32 GetBoxMonDataInternal(BoxPokemon *boxMon, int attr, void *dest) {
case MON_DATA_MET_LEVEL:
ret = blockD->metLevel;
break;
case MON_DATA_MET_GENDER:
ret = blockD->metGender;
case MON_DATA_OT_GENDER:
ret = blockD->otGender;
break;
case MON_DATA_ENCOUNTER_TYPE:
ret = blockD->encounterType;
@ -1308,8 +1308,8 @@ static void SetBoxMonDataInternal(BoxPokemon *boxMon, int attr, const void *valu
case MON_DATA_MET_LEVEL:
blockD->metLevel = VALUE(u8);
break;
case MON_DATA_MET_GENDER:
blockD->metGender = VALUE(u8);
case MON_DATA_OT_GENDER:
blockD->otGender = VALUE(u8);
break;
case MON_DATA_ENCOUNTER_TYPE:
blockD->encounterType = VALUE(u8);
@ -1676,7 +1676,7 @@ static void AddBoxMonDataInternal(BoxPokemon *boxMon, int attr, int value) {
case MON_DATA_POKERUS:
case MON_DATA_POKEBALL:
case MON_DATA_MET_LEVEL:
case MON_DATA_MET_GENDER:
case MON_DATA_OT_GENDER:
case MON_DATA_ENCOUNTER_TYPE:
case MON_DATA_RESERVED_159:
case MON_DATA_STATUS:
@ -4115,7 +4115,7 @@ BOOL BoxmonBelongsToPlayer(BoxPokemon *boxMon, PlayerProfile *profile, HeapID he
u32 myId = PlayerProfile_GetTrainerID(profile);
u32 otId = GetBoxMonData(boxMon, MON_DATA_OTID, NULL);
u32 myGender = PlayerProfile_GetTrainerGender(profile);
u32 otGender = GetBoxMonData(boxMon, MON_DATA_MET_GENDER, NULL);
u32 otGender = GetBoxMonData(boxMon, MON_DATA_OT_GENDER, NULL);
String *r7 = PlayerProfile_GetPlayerName_NewString(profile, heapId);
String *r6 = String_New(PLAYER_NAME_LENGTH + 1, heapId);
BOOL ret = FALSE;

View File

@ -292,7 +292,7 @@ static void MGGive_Mon(FieldSystem *fieldSys, MysteryGiftData *unused) {
CopyPokemonToPokemon(pokemon, tmpPokemon);
SetMonData(tmpPokemon, MON_DATA_OT_NAME_2, playerName);
SetMonData(tmpPokemon, MON_DATA_OTID, &trainerId);
SetMonData(tmpPokemon, MON_DATA_MET_GENDER, &gender);
SetMonData(tmpPokemon, MON_DATA_OT_GENDER, &gender);
pokemon = tmpPokemon;
String_Delete(playerName);
}

View File

@ -799,7 +799,7 @@ static void BoxMon_SetOriginalTrainerData(BoxPokemon *boxMon, PlayerProfile *pro
String *name = PlayerProfile_GetPlayerName_NewString(profile, heapId);
SetBoxMonData(boxMon, MON_DATA_OTID, &otId);
SetBoxMonData(boxMon, MON_DATA_MET_GENDER, &gender);
SetBoxMonData(boxMon, MON_DATA_OT_GENDER, &gender);
SetBoxMonData(boxMon, MON_DATA_OT_NAME_2, name);
String_Delete(name);

View File

@ -293,7 +293,7 @@ BOOL MonIsFromTogepiEgg(Pokemon *mon, SaveData *saveData) {
if (word != PlayerProfile_GetTrainerID(profile)) {
return FALSE;
}
u8 byte = GetMonData(mon, MON_DATA_MET_GENDER, NULL);
u8 byte = GetMonData(mon, MON_DATA_OT_GENDER, NULL);
if (byte != PlayerProfile_GetTrainerGender(profile)) {
return FALSE;
}
@ -337,7 +337,7 @@ static BOOL MonIsInGameTradePokeInternal(Pokemon *mon, NPCTrade *trade, NpcTrade
if (pid != trade->pid) {
return FALSE;
}
u8 gender = GetMonData(mon, MON_DATA_MET_GENDER, NULL);
u8 gender = GetMonData(mon, MON_DATA_OT_GENDER, NULL);
if (gender != trade->gender) {
return FALSE;
}

View File

@ -160,7 +160,7 @@ static void RenderCoinPayoutScreen(VoltorbFlipAppWork *work) {
GfGfxLoader_LoadScrnDataFromOpenNarc(work->narc, NARC_voltorb_flip_voltorb_flip_00000006_bin, work->bgConfig, GF_BG_LYR_SUB_0, 0, 0, 1, work->heapId);
int payout = GamePayout(work->game);
u16 coins = (u32)CheckCoins(work->coins);
u16 coins = (u32)Coins_GetValue(work->coins);
PrintCoins(work, COIN_DISPLAY_PAYOUT, payout);
PrintCoins(work, COIN_DISPLAY_TOTAL, coins);
@ -271,7 +271,7 @@ static BOOL ov122_021E5B5C(WorkflowEngine *workflow, VoltorbFlipAppWork *work) {
}
BOOL ov122_021E5BA8(WorkflowEngine *workflow, VoltorbFlipAppWork *work) {
u32 coins = CheckCoins(work->coins);
u32 coins = Coins_GetValue(work->coins);
if (coins >= 50000) {
// "Youve gathered 50,000 Coins. You cannot gather..."
PrintTextWindow(work, msg_0039_00014, 1);
@ -778,7 +778,7 @@ BOOL ov122_021E6594(WorkflowEngine *workflow, VoltorbFlipAppWork *work) {
ov122_021E8E40(work->unk240);
int payout = GamePayout(work->game);
u16 coins = (u32)CheckCoins(work->coins);
u16 coins = (u32)Coins_GetValue(work->coins);
PrintCoins(work, COIN_DISPLAY_PAYOUT, payout);
PrintCoins(work, COIN_DISPLAY_TOTAL, coins);
@ -1026,12 +1026,12 @@ static BOOL AddCoinsToPayout(VoltorbFlipAppWork *work) {
static BOOL AwardPayoutToPlayer(VoltorbFlipAppWork *work) {
BOOL payoutDeducted; // only TRUE for incremental deduction
u16 coins = (u32)CheckCoins(work->coins);
u16 coins = (u32)Coins_GetValue(work->coins);
u16 payout = GamePayout(work->game);
if (System_GetTouchNew() || gSystem.newKeys != 0 || coins >= 50000) {
DeductFromPayout(work->game, (u8)payout);
GiveCoins(work->coins, payout);
Coins_Add(work->coins, payout);
int newTotal = coins + payout;
if (newTotal > 50000) {
@ -1046,7 +1046,7 @@ static BOOL AwardPayoutToPlayer(VoltorbFlipAppWork *work) {
}
if (payoutDeducted) {
GiveCoins(work->coins, 1);
Coins_Add(work->coins, 1);
PrintCoins(work, COIN_DISPLAY_PAYOUT, (u16)(payout - 1));
PrintCoins(work, COIN_DISPLAY_TOTAL, (u16)(coins + 1));
if (payout % 4 == 0) {
@ -1981,7 +1981,7 @@ static void ov122_021E8094(OverlayManager *man) {
ov122_021E73FC(work);
ov122_021E6B38(work);
u16 coins = (u32)CheckCoins(work->coins);
u16 coins = (u32)Coins_GetValue(work->coins);
PrintCoins(work, COIN_DISPLAY_TOTAL, coins);
ov122_021E7AEC(work);
ov122_021E7BD4(work);

View File

@ -17,7 +17,7 @@ all: $(prog)
clean: ; $(RM) -r $(DEPDIR) $(OBJS) $(prog) $(prog).exe
$(prog): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^
$(CC) $(LDFLAGS) -lm -o $@ $^
$(OBJS): %.o: %.c
$(OBJS): %.o: %.c $(DEPDIR)/%.d | $(DEPDIR)