diff --git a/config/GMPE01_00/symbols.txt b/config/GMPE01_00/symbols.txt index cfcd0172..d51eb189 100644 --- a/config/GMPE01_00/symbols.txt +++ b/config/GMPE01_00/symbols.txt @@ -952,7 +952,7 @@ THPTestProc = .text:0x8005793C; // type:function size:0x27C scope:local THPViewFunc = .text:0x80057BB8; // type:function size:0xA4 scope:local THPViewSprFunc = .text:0x80057C5C; // type:function size:0x17C scope:local THPDecodeFunc = .text:0x80057DD8; // type:function size:0x4C scope:local -MGGetIndex = .text:0x80057E24; // type:function size:0x5C +omGetMGIndex = .text:0x80057E24; // type:function size:0x5C omGameSysInit = .text:0x80057E80; // type:function size:0xF4 omVibrate = .text:0x80057F74; // type:function size:0x9C _CheckFlag = .text:0x80058010; // type:function size:0xA0 @@ -5437,7 +5437,7 @@ omovlhis = .bss:0x8018FB38; // type:object size:0xC0 scope:local XFB_Geometry = .bss:0x8018FBF8; // type:object size:0x18 scope:local GWPlayerCfg = .bss:0x8018FC10; // type:object size:0x28 GWPlayer = .bss:0x8018FC38; // type:object size:0xC0 data:byte -GWSystem = .bss:0x8018FCF8; // type:object size:0xE0 data:byte +GWSystem = .bss:0x8018FCF8; // type:object size:0xDC data:byte GWGameStat = .bss:0x8018FDD8; // type:object size:0x118 GWGameStatDefault = .bss:0x8018FEF0; // type:object size:0x118 CRot = .bss:0x80190008; // type:object size:0xC data:float diff --git a/configure.py b/configure.py index e7ba6984..7f1297ba 100644 --- a/configure.py +++ b/configure.py @@ -254,7 +254,7 @@ config.libs = [ Object(NonMatching, "game/perf.c"), Object(Matching, "game/objmain.c"), Object(NonMatching, "game/fault.c"), - Object(NonMatching, "game/gamework.c"), + Object(Matching, "game/gamework.c"), Object(NonMatching, "game/objsysobj.c"), Object(NonMatching, "game/objdll.c"), Object(Matching, "game/frand.c"), diff --git a/include/REL/w10Dll.h b/include/REL/w10Dll.h index 2dd77653..7026bc04 100644 --- a/include/REL/w10Dll.h +++ b/include/REL/w10Dll.h @@ -5,6 +5,13 @@ #define ARRAY_COUNT(arr) (s32)(sizeof(arr) / sizeof(arr[0])) +typedef struct w10_state { +/* 0x00 */ s32 unk0; +/* 0x04 */ u16 unk4; +/* 0x06 */ u16 unk6; +/* 0x08 */ s16 unk8; +} W10State; + typedef struct unkw10Dll { Vec unk0; Vec unk0C; @@ -107,7 +114,7 @@ extern Process* lbl_1_bss_18; extern s16 lbl_1_bss_1C; extern s16 lbl_1_bss_1E; extern s32 lbl_1_data_78[2]; -extern BoardStateSubStruct* lbl_1_bss_0; +extern W10State* lbl_1_bss_0; extern s16 lbl_1_bss_10[4]; //could be incorrect size extern void* lbl_1_bss_8; //unknown type extern s16 lbl_1_bss_C; diff --git a/include/common_structs.h b/include/common_structs.h index 38dbec4f..c2ed8f6e 100644 --- a/include/common_structs.h +++ b/include/common_structs.h @@ -18,58 +18,132 @@ typedef struct wipe_state { u8 unk2[20]; } WipeState; -typedef struct BoardStateSubStruct { -/* 0x00 */ s32 unk0; -/* 0x04 */ u16 unk4; -/* 0x06 */ u16 unk6; -/* 0x08 */ s16 unk8; -} BoardStateSubStruct; -typedef struct system_work { -/* 0x00 */ char unk00[0x04]; -/* 0x04 */ s8 curTurnCount; -/* 0x05 */ s8 maxTurnCount; -/* 0x06 */ char unk06[0x02]; -/* 0x08 */ u8 unk08; -/* 0x09 */ s8 doubleCoinsOnSpaceBool; -/* 0x0A */ s8 curPlayerIndex; -/* 0x0C */ char unk0C[4]; -/* 0x10 */ BoardStateSubStruct unk10; -/* 0x1A */ char unk1A[0xC6]; -} SystemState; //8018fcf8, sizeof 0xE0 - -typedef struct { - u8 unk0 : 2; -} PlayerFlags; +typedef struct system_state { +/* 0x00 */ struct { + u16 story : 1; + u16 team : 1; + u8 : 7; + }; +/* 0x02 */ struct { + u16 bonus_star : 1; + u16 explain_mg : 1; + u16 show_com_mg : 1; + u16 mg_type : 2; + u16 mess_speed : 2; + u16 save_mode : 2; + }; +/* 0x04 */ s8 turn; +/* 0x05 */ s8 max_turn; +/* 0x06 */ u8 star_flag; +/* 0x07 */ u8 star_total; +/* 0x08 */ struct { + u8 star_pos : 3; + u8 board : 5; +}; +/* 0x09 */ s8 last5_effect; +/* 0x0A */ s8 player_curr; +/* 0x0B */ char unk0B[3]; +/* 0x0E */ s16 hidden_block_pos; +/* 0x10 */ u8 ATTRIBUTE_ALIGN(4) board_data[32]; +/* 0x30 */ u8 mess_delay; +/* 0x31 */ struct { + u8 field31_bit0 : 4; + }; +/* 0x32 */ char unk_32[0x2]; +/* 0x34 */ u16 mg_next; +/* 0x36 */ s16 mg_next_extra; +/* 0x38 */ u8 flag[3][16]; +/* 0x68 */ u8 unk_68[0x74]; +} SystemState; //8018fcf8, sizeof 0xDC typedef struct player_state { -/* 0x00 */ u8 characterID; -/* 0x01 */ s8 unk01; -/* 0x02 */ s8 unk02; -/* 0x03 */ s8 unk03; -/* 0x04 */ s8 controllerPort; -/* 0x05 */ s8 items[3]; -/* 0x08 */ PlayerFlags flags; //0x02 mini mushroom, 0x04 mega mushroom -/* 0x09 */ s8 placement; //0x80 1st, 0x20 2nd, 0x40 3rd, 0x60 4th -/* 0x0A */ u8 spacesLeftToMove; -/* 0x0B */ char unk_0B[5]; -/* 0x10 */ s16 nextABSSpaceIndex; -/* 0x12 */ char unk_12[2]; -/* 0x14 */ s8 blueSpacesLanded; -/* 0x15 */ s8 redSpacesLanded; -/* 0x16 */ s8 happeningSpacesLanded; -/* 0x17 */ s8 chanceSpacesLanded; -/* 0x18 */ char unk_18; -/* 0x19 */ s8 battleSpacesLanded; -/* 0x1A */ s8 itemSpacesLanded; -/* 0x1B */ s8 springSpacesLanded; -/* 0x1C */ s16 coins; -/* 0x1E */ char unk_1E[2]; -/* 0x20 */ s16 totalCoinsCollected; -/* 0x22 */ s16 coinPeak; -/* 0x24 */ char unk_24[6]; -/* 0x2A */ s16 stars; -/* 0x2C */ char unk_2C[4]; +/* 0x00 */ struct { + u8 diff : 2; + u8 com : 1; + u8 character : 4; + u8 auto_size : 2; + }; +/* 0x02 */ struct { + u8 team : 1; + u8 field02_bit1 : 1; + u8 player_idx : 2; + u8 field02_bit4 : 5; + }; +/* 0x04 */ s8 port; +/* 0x05 */ s8 items[3]; +/* 0x08 */ struct { + u8 color : 2; + u8 moving : 1; + u8 field08_bit3 : 1; + u8 show_next : 1; + u8 size : 2; + u8 field08_bit7 : 2; + u8 rank : 2; + u8 bowser_suit : 1; + }; +/* 0x0A */ s8 roll; +/* 0x0C */ s16 space_curr; +/* 0x0E */ s16 space_prev; +/* 0x10 */ s16 space_next; +/* 0x12 */ s16 unk_12; +/* 0x14 */ u8 blue_count; +/* 0x15 */ u8 red_count; +/* 0x16 */ u8 question_count; +/* 0x17 */ u8 fortune_count; +/* 0x18 */ u8 bowser_count; +/* 0x19 */ u8 battle_count; +/* 0x1A */ u8 mushroom_count; +/* 0x1B */ u8 warp_count; +/* 0x1C */ s16 coins; +/* 0x1E */ s16 coins_mg; +/* 0x20 */ s16 coins_total; +/* 0x22 */ s16 coins_max; +/* 0x24 */ s16 coins_battle; +/* 0x26 */ s16 unk_26; +/* 0x28 */ s16 coins_mg_gain; +/* 0x2A */ s16 stars; +/* 0x2C */ s16 stars_max; +/* 0x2E */ char unk_2E[2]; } PlayerState; //size of 0x30 +typedef struct game_stat { +/* 0x0 */ s16 unk_00; +/* 0x2 */ u8 language; +/* 0x3 */ u8 sound_mode; +/* 0x4 */ s8 rumble; +/* 0x6 */ u16 total_stars; +/* 0x8 */ OSTime create_time; +/* 0x10 */ u32 mg_custom[2]; +/* 0x18 */ u32 mg_avail[2]; +/* 0x20 */ u32 mg_record[15]; +/* 0x5C */ u8 board_win_count[9][8]; +/* 0xA4 */ u8 board_play_count[9]; +/* 0xAE */ u16 board_max_stars[9]; +/* 0xC0 */ u16 board_max_coins[9]; +/* 0xD2 */ u8 present[60]; +/* 0x10E */ struct { + u8 story_continue : 1; + u8 party_continue : 1; + u8 open_w06 : 1; + u8 field10E_bit4 : 1; + u8 field10E_bit5 : 1; + u8 field10E_bit6 : 1; + }; +/* 0x10F */ struct { + u8 field10F_bit0 : 1; + u8 field10F_bit1 : 1; + u8 field10F_bit2 : 2; + u8 field10F_bit4 : 2; + u8 field10F_bit6 : 2; + }; +/* 0x110 */ struct { + u8 field110_bit0 : 1; + u8 field110_bit1 : 1; + u8 field110_bit2 : 2; + u8 field110_bit4 : 2; + u8 field110_bit6 : 2; + }; +} GameStat; + #endif diff --git a/include/functions.h b/include/functions.h index b9decdb0..b4f8958a 100644 --- a/include/functions.h +++ b/include/functions.h @@ -40,7 +40,6 @@ void HuWinMesMaxSizeGet(s32, f32*, ...); s16 HuWinCreate(float x, float y, s16 w, s16 h, s16 frame); void HuPadRumbleAllStop(void); -s16 HuPadStatGet(s16); void HuAudFXListnerKill(void); void HuAudDllSndGrpSet(u16 ovl); diff --git a/include/game/gamework.h b/include/game/gamework.h new file mode 100644 index 00000000..9cdb46b1 --- /dev/null +++ b/include/game/gamework.h @@ -0,0 +1,37 @@ +#ifndef _GAME_GAMEWORK_H +#define _GAME_GAMEWORK_H + +#include "dolphin.h" + +void GWInit(void); +void GWResetGameStat(void); +s16 GWGetMessSpeed(void); +void GWSetMGRecord(int index, s32 value); +s32 GWGetMGRecord(int index); +void GWGetCharColor(int character, GXColor *color); +void GWSetBoardPlayCount(int board, u8 value); +void GWAddBoardPlayCount(int board, u8 value); +u8 GWGetBoardPlayCount(int board); +void GWSetBoardMaxStars(int board, int value); +u16 GWGetBoardMaxStars(int board); +void GWSetBoardMaxCoins(int board, int value); +u16 GWGetBoardMaxCoins(int board); +int GWIncBoardWinCount(int character, int board); +int GWGetBoardWinCount(int character, int board); +void GWSetBoardWinCount(int character, int board, int value); +int GWGetMGAvail(int id); +int GWSetMGAvail(int id); +int GWGetMGCustom(int id); +int GWSetMGCustom(int id); +int GWResetMGCustom(int id); +s16 GWGetCoins(int player); +void GWSetCoins(int player, s16 value); +void GWAddCoins(int player, s16 amount); +void GWSetStars(int player, s16 value); +void GWAddStars(int player, s16 amount); +s16 GWGetStars(int player); +void GWSetTotalStars(s16 value); +void GWAddTotalStars(s16 amount); +u16 GWGetTotalStars(void); + +#endif \ No newline at end of file diff --git a/include/variables.h b/include/variables.h index 055f334e..7484cb70 100644 --- a/include/variables.h +++ b/include/variables.h @@ -19,6 +19,6 @@ extern char fadeStat; extern PlayerState GWPlayer[4]; extern SystemState GWSystem; - +extern GameStat GWGameStat; #endif diff --git a/src/REL/w10Dll/w10Dll.c b/src/REL/w10Dll/w10Dll.c index b3ea6a1f..39364092 100644 --- a/src/REL/w10Dll/w10Dll.c +++ b/src/REL/w10Dll/w10Dll.c @@ -14,7 +14,7 @@ s16 lbl_1_bss_E; s16 lbl_1_bss_C; void* lbl_1_bss_8; s32 lbl_1_bss_4_pad; -BoardStateSubStruct* lbl_1_bss_0; +W10State* lbl_1_bss_0; //DATA unkw10Dll lbl_1_data_0[1] = { @@ -62,7 +62,7 @@ s32 lbl_1_data_6C[2] = { // function is probably global. only inlined in rels? inline s32 get_current_board(void) { - return GWSystem.unk08 & 0x1F; + return GWSystem.board; } void fn_1_E0(void) { @@ -76,7 +76,7 @@ void fn_1_E0(void) { s32 temp2; temp2 = get_current_board(); - lbl_1_bss_0 = &GWSystem.unk10; + lbl_1_bss_0 = (W10State *)&GWSystem.board_data; lbl_1_bss_0->unk0 = 0; lbl_1_bss_0->unk4 = 0; lbl_1_bss_0->unk6 = 0; diff --git a/src/REL/w10Dll/w10Dll3.c b/src/REL/w10Dll/w10Dll3.c index 6c44bc89..21d5cf1b 100644 --- a/src/REL/w10Dll/w10Dll3.c +++ b/src/REL/w10Dll/w10Dll3.c @@ -174,7 +174,7 @@ void fn_1_13A4(void) { fn_1_BA0(0x2E0023); for (i = 0; i < 4; i++) { - GWPlayer[i].flags.unk0 = 1; + GWPlayer[i].color = 1; } fn_800A4C88(); fn_800884F4(0); diff --git a/src/REL/w10Dll/w10Dll4.c b/src/REL/w10Dll/w10Dll4.c index c89293c8..bcd62892 100644 --- a/src/REL/w10Dll/w10Dll4.c +++ b/src/REL/w10Dll/w10Dll4.c @@ -1,6 +1,8 @@ #include "REL/w10Dll.h" #include "game/data.h" +s16 HuPadStatGet(s16 i); //TODO: Move to some other header file since gamework.c relies on an implicit declaration of it + char lbl_1_data_98[] = "@@@@@@@@@@@@@@ Tutorial Exit @@@@@@@@@@@@@@\n\000"; w10DllUnk03 lbl_1_data_C6[11] = { @@ -85,21 +87,21 @@ void fn_1_176C(void) { void fn_1_179C(void) { fn_1_BA0(0x2E0025); - GWPlayer[1].flags.unk0 = 2; - GWPlayer[3].flags.unk0 = 2; + GWPlayer[1].color = 2; + GWPlayer[3].color = 2; } void fn_1_17F4(void) { fn_1_BA0(0x2E0026); - GWPlayer[0].flags.unk0 = 2; + GWPlayer[0].color = 2; } void fn_1_1834(void) { fn_1_BA0(0x2E0027); - GWPlayer[0].flags.unk0 = 1; - GWPlayer[1].flags.unk0 = 1; - GWPlayer[2].flags.unk0 = 1; - GWPlayer[3].flags.unk0 = 2; + GWPlayer[0].color = 1; + GWPlayer[1].color = 1; + GWPlayer[2].color = 1; + GWPlayer[3].color = 2; } void fn_1_18BC(void) { @@ -139,7 +141,7 @@ void fn_1_1984(void) { return; } for (i = 0; i < ARRAY_COUNT(GWPlayer); i++) { - contPortIndex = GWPlayer[i].controllerPort; + contPortIndex = GWPlayer[i].port; if (contPortIndex == -1) { continue; } @@ -168,7 +170,7 @@ int fn_1_1AAC(s16 arg0, s32 arg1) { if (fn_8005B6A8() == 0) { s32 contPortIndex; for (i = 0; i < ARRAY_COUNT(GWPlayer); i++) { - contPortIndex = GWPlayer[i].controllerPort; + contPortIndex = GWPlayer[i].port; if (contPortIndex == -1) { continue; } @@ -190,8 +192,8 @@ int fn_1_1AAC(s16 arg0, s32 arg1) { } if (arg0 != 0x1D) { OSReport(lbl_1_data_258, - (GWPlayer[0].characterID >> 5) & 1, (GWPlayer[1].characterID >> 5) & 1, - (GWPlayer[2].characterID >> 5) & 1, (GWPlayer[3].characterID >> 5) & 1, + GWPlayer[0].com, GWPlayer[1].com, + GWPlayer[2].com, GWPlayer[3].com, lbl_1_bss_0->unk0, arg0, arg1, lbl_1_bss_0->unk4, lbl_1_bss_0->unk6); if (lbl_1_data_108[lbl_1_bss_0->unk0].unk0 != -1) { if (arg0 == 5) { diff --git a/src/game/gamework.c b/src/game/gamework.c new file mode 100644 index 00000000..c44d4a05 --- /dev/null +++ b/src/game/gamework.c @@ -0,0 +1,362 @@ +#include "common.h" +#include "string.h" +#include "game/gamework.h" + +GameStat GWGameStatDefault; +GameStat GWGameStat; +SystemState GWSystem; +PlayerState GWPlayer[4]; +PlayerConfig GWPlayerCfg[4]; + +static inline void GWErase(void) +{ + memset(GWPlayerCfg, 0, sizeof(GWPlayerCfg)); + memset(GWPlayer, 0, sizeof(GWPlayer)); + memset(&GWSystem, 0, sizeof(GWSystem)); +} + +static inline void InitPlayerConfig(void) +{ + PlayerConfig *config; + s32 i; + for(i=0; i<4; i++) { + config = &GWPlayerCfg[i]; + config->character = i; + config->pad_idx = i; + config->diff = 0; + config->group = i; + if(!HuPadStatGet(i)) { + config->iscom = 0; + } else { + config->iscom = 1; + } + } +} + +static inline void ResetBoardSettings(void) +{ + GWGameStat.rumble = 1; + GWSystem.explain_mg = 1; + GWSystem.show_com_mg = 1; + GWSystem.mess_speed = 1; + GWSystem.mess_delay = 32; + GWSystem.save_mode = 0; +} + +void GWInit(void) +{ + GWResetGameStat(); + _InitFlag(); + GWErase(); + InitPlayerConfig(); + GWGameStat.language = 1; + ResetBoardSettings(); +} + +static inline void ResetMGRecord(GameStat *game_stat) +{ + game_stat->mg_record[0] = 18000; + game_stat->mg_record[1] = 80; + game_stat->mg_record[2] = 3600; + game_stat->mg_record[3] = 7200; + game_stat->mg_record[4] = 0; + game_stat->mg_record[5] = 3600; + game_stat->mg_record[6] = 18000; + game_stat->mg_record[7] = 18000; + game_stat->mg_record[8] = 18000; + game_stat->mg_record[9] = 0; + game_stat->mg_record[10] = 300; + game_stat->mg_record[11] = 0; + game_stat->mg_record[12] = 0; + game_stat->mg_record[13] = 0; + game_stat->mg_record[14] = 0; +} + +static inline void ResetBoardRecord(GameStat *game_stat) +{ + s32 i; + s32 j; + + for(i=0; i<9; i++) { + for(j=0; j<8; j++) { + game_stat->board_win_count[i][j] = 0; + } + game_stat->board_play_count[i] = 0; + game_stat->board_max_stars[i] = 0; + game_stat->board_max_coins[i] = 0; + } +} + +static inline void ResetPresent(GameStat *game_stat) +{ + s32 i; + for(i=0; i<60; i++) { + game_stat->present[i] = 0; + } + (void)i; //HACK to match GWResetGameStat +} + +static inline void ResetFlag(GameStat *game_stat) +{ + game_stat->story_continue = 0; + game_stat->party_continue = 0; + game_stat->open_w06 = 0; + game_stat->field10E_bit4 = 0; + game_stat->field10E_bit5 = 0; + game_stat->field10E_bit6 = 0; + game_stat->field10F_bit0 = game_stat->field110_bit0 = 1; + game_stat->field10F_bit1 = game_stat->field110_bit1 = 1; + game_stat->field10F_bit2 = game_stat->field110_bit2 = 0; + game_stat->field10F_bit4 = game_stat->field110_bit4 = 1; + game_stat->field10F_bit6 = game_stat->field110_bit6 = 0; +} + +void GWResetGameStat(void) +{ + GameStat *game_stat = &GWGameStatDefault; + memset(game_stat, 0, sizeof(GameStat)); + game_stat->unk_00 = 0; + game_stat->language = 1; + game_stat->sound_mode = 1; + game_stat->rumble = 1; + game_stat->total_stars = 0; + game_stat->create_time = 0; + game_stat->mg_custom[0] = 0; + game_stat->mg_custom[1] = 0; + game_stat->mg_avail[0] = 0; + game_stat->mg_avail[1] = 0; + ResetMGRecord(game_stat); + ResetBoardRecord(game_stat); + ResetPresent(game_stat); + ResetFlag(game_stat); + memcpy(&GWGameStat, &GWGameStatDefault, sizeof(GameStat)); + ResetBoardSettings(); +} + +s16 GWGetMessSpeed(void) +{ + if(GWSystem.mess_delay > 48) { + GWSystem.mess_speed = 1; + GWSystem.mess_delay = 32; + } + return GWSystem.mess_delay; +} + +void GWSetMGRecord(int index, s32 value) +{ + if(!_CheckFlag(0x1000C)) { + GWGameStat.mg_record[index] = value; + } +} + +s32 GWGetMGRecord(int index) +{ + return GWGameStat.mg_record[index]; +} + +void GWGetCharColor(int character, GXColor *color) +{ + GXColor char_color[] = { + { 227, 67, 67, 255 }, + { 68, 67, 227, 255 }, + { 241, 158, 220, 255 }, + { 67, 228, 68, 255 }, + { 138, 60, 180, 255 }, + { 146, 85, 55, 255 }, + { 227, 228, 68, 255 }, + { 40, 40, 40, 255 } + }; + *color = char_color[character]; +} + +void GWSetBoardPlayCount(int board, u8 value) +{ + if(value > 99) { + value = 99; + } + GWGameStat.board_play_count[board] = value; +} + +void GWAddBoardPlayCount(int board, u8 value) +{ + value += GWGameStat.board_play_count[board]; + if(value > 99) { + value = 99; + } + GWGameStat.board_play_count[board] = value; +} + + +u8 GWGetBoardPlayCount(int board) +{ + return GWGameStat.board_play_count[board]; +} + +void GWSetBoardMaxStars(int board, int value) +{ + GWGameStat.board_max_stars[board] = value; +} + +u16 GWGetBoardMaxStars(int board) +{ + return GWGameStat.board_max_stars[board]; +} + +void GWSetBoardMaxCoins(int board, int value) +{ + GWGameStat.board_max_coins[board] = value; +} + +u16 GWGetBoardMaxCoins(int board) +{ + return GWGameStat.board_max_coins[board]; +} + +int GWIncBoardWinCount(int character, int board) +{ + int win_count = GWGameStat.board_win_count[board][character]+1; + if(win_count > 99) { + win_count = 99; + } + GWGameStat.board_win_count[board][character] = win_count; + return win_count; +} + +int GWGetBoardWinCount(int character, int board) +{ + return GWGameStat.board_win_count[board][character]; +} + +void GWSetBoardWinCount(int character, int board, int value) +{ + GWGameStat.board_win_count[board][character] = value; +} + +int GWGetMGAvail(int id) +{ + int word; + int bit; + id -= 401; + word = id >> 5; + bit = id % 32; + if(GWGameStat.mg_avail[word] & (1 << bit)) { + return 1; + } else { + return 0; + } +} + +int GWSetMGAvail(int id) +{ + int word; + int bit; + id -= 401; + word = id >> 5; + bit = id % 32; + GWGameStat.mg_avail[word] |= (1 << bit); +} + +int GWGetMGCustom(int id) +{ + int word; + int bit; + id -= 401; + word = id >> 5; + bit = id % 32; + if(GWGameStat.mg_custom[word] & (1 << bit)) { + return 1; + } else { + return 0; + } +} + +int GWSetMGCustom(int id) +{ + int word; + int bit; + id -= 401; + word = id >> 5; + bit = id % 32; + GWGameStat.mg_custom[word] |= (1 << bit); +} + +int GWResetMGCustom(int id) +{ + int word; + int bit; + id -= 401; + word = id >> 5; + bit = id % 32; + GWGameStat.mg_custom[word] &= ~(1 << bit); +} + +s16 GWGetCoins(int player) +{ + return GWPlayer[player].coins; +} + +void GWSetCoins(int player, s16 value) +{ + if(!_CheckFlag(0x1000C)) { + if(value < 0) { + value = 0; + } + if(value > 999) { + value = 999; + } + if(value > GWPlayer[player].coins_max) { + GWPlayer[player].coins_max = value; + } + GWPlayer[player].coins = value; + } +} + +void GWAddCoins(int player, s16 amount) +{ + GWSetCoins(player, GWPlayer[player].coins+amount); +} + +void GWSetStars(int player, s16 value) +{ + if(value < 0) { + value = 0; + } + if(value > 999) { + value = 999; + } + if(value > GWPlayer[player].stars_max) { + GWPlayer[player].stars_max = value; + } + GWPlayer[player].stars = value; +} + +void GWAddStars(int player, s16 amount) +{ + GWSetStars(player, GWPlayer[player].stars+amount); +} + +s16 GWGetStars(int player) +{ + return GWPlayer[player].stars; +} + +void GWSetTotalStars(s16 value) +{ + if(value < 0) { + value = 0; + } + if(value > 10000) { + value = 10000; + } + GWGameStat.total_stars = value; +} + +void GWAddTotalStars(s16 amount) +{ + GWSetTotalStars(GWGameStat.total_stars+amount); +} + +u16 GWGetTotalStars(void) +{ + return GWGameStat.total_stars; +} \ No newline at end of file