#include "global.h" #include "constants/game_stat.h" #include "overworld.h" #include "berry_blender.h" #include "bg.h" #include "window.h" #include "task.h" #include "sprite.h" #include "sound.h" #include "constants/songs.h" #include "m4a.h" #include "bg.h" #include "palette.h" #include "decompress.h" #include "malloc.h" #include "gpu_regs.h" #include "text.h" #include "text_window.h" #include "event_data.h" #include "main.h" #include "link.h" #include "item_menu_icons.h" #include "berry.h" #include "item.h" #include "constants/items.h" #include "string_util.h" #include "international_string_util.h" #include "random.h" #include "menu.h" #include "pokeblock.h" #include "trig.h" #include "tv.h" #include "item_menu.h" #include "battle_records.h" #define BLENDER_SCORE_BEST 0 #define BLENDER_SCORE_GOOD 1 #define BLENDER_SCORE_MISS 2 #define BLENDER_MAX_PLAYERS 4 #define BLENDER_SCORES_NO 3 enum { PLAY_AGAIN_OK, DONT_PLAY_AGAIN, CANT_PLAY_NO_BERRIES, CANT_PLAY_NO_PKBLCK_SPACE }; struct BlenderBerry { u16 itemId; u8 name[BERRY_NAME_LENGTH + 1]; u8 flavors[FLAVOR_COUNT]; u8 smoothness; }; struct TimeAndRPM { u32 time; u16 max_RPM; }; struct BlenderGameBlock { struct TimeAndRPM timeRPM; u16 scores[BLENDER_MAX_PLAYERS][BLENDER_SCORES_NO]; }; struct TvBlenderStruct { u8 name[11]; u8 pokeblockFlavor; u8 pokeblockColor; u8 pokeblockSheen; }; struct BerryBlenderData { u8 mainState; u8 loadGfxState; u8 unused_02[0x42]; u16 field_44; u8 scoreIconIds[BLENDER_SCORES_NO]; u16 arrowPos; s16 field_4C; u16 max_RPM; u8 syncArrowSpriteIds[BLENDER_MAX_PLAYERS]; u8 syncArrowSprite2Ids[BLENDER_MAX_PLAYERS]; u8 unused_57[0xB]; u8 gameEndState; u16 field_64[BLENDER_MAX_PLAYERS]; u16 field_6C; u16 field_6E; u16 playAgainState; u8 field_72; u16 chosenItemId[BLENDER_MAX_PLAYERS]; u8 playersNo; u8 unused_7D[0x10]; u16 field_8E[BLENDER_MAX_PLAYERS]; u16 field_96[BLENDER_MAX_PLAYERS]; u8 yesNoAnswer; u8 stringVar[100]; u32 gameFrameTime; s32 framesToWait; u32 field_10C; u8 unused_110[4]; u8 field_114; u16 field_116; u16 field_118; u16 field_11A; u16 bg_X; u16 bg_Y; u8 field_120[3]; u8 field_123; u16 scores[BLENDER_MAX_PLAYERS][BLENDER_SCORES_NO]; u8 playerPlaces[BLENDER_MAX_PLAYERS]; struct BgAffineSrcData bgAffineSrc; u16 field_154; struct BlenderBerry blendedBerries[BLENDER_MAX_PLAYERS]; struct TimeAndRPM smallBlock; u32 field_1A0; u8 field_1A4; struct TvBlenderStruct tvBlender; u8 tilemapBuffers[2][0x800]; s16 textState; void *tilesBuffer; struct BlenderGameBlock gameBlock; }; extern struct MusicPlayerInfo gMPlayInfo_SE2; extern struct MusicPlayerInfo gMPlayInfo_BGM; extern u8 gInGameOpponentsNo; extern u8 gUnknown_020322D5; // graphics extern const u8 gBerryBlenderArrowTiles[]; extern const u8 gBerryBlenderStartTiles[]; extern const u8 gBerryBlenderMarubatsuTiles[]; extern const u8 gBerryBlenderParticlesTiles[]; extern const u8 gBerryBlenderCountdownNumbersTiles[]; extern const u16 gBerryBlenderMiscPalette[]; extern const u16 gBerryBlenderArrowPalette[]; extern const u8 sBlenderCenterGfx[]; extern const u8 gUnknown_08D91DB8[]; extern const u8 gUnknown_08D927EC[]; // text extern const u8 gText_SavingDontTurnOff2[]; extern const u8 gText_Space[]; extern const u8 gText_BlenderMaxSpeedRecord[]; extern const u8 gText_234Players[]; extern void sub_800A418(void); extern u8 sub_800A9D8(void); extern void sub_81AABF0(void (*callback)(void)); extern void sub_800B4C0(void); extern void ClearLinkCallback(void); extern void sub_8009F8C(void); extern void sub_8153430(void); extern bool8 sub_8153474(void); extern void sub_80EECEC(void); // this file's functions static void BerryBlender_SetBackgroundsPos(void); static void sub_8080EA4(u8 taskId); static void sub_8080FD0(u8 taskId); static void sub_80810F8(u8 taskId); static void sub_8081224(u8 taskId); static void sub_8083F3C(u8 taskId); static void sub_80833F8(struct Sprite *sprite); static void sub_8082F68(struct Sprite *sprite); static void sub_8083010(struct Sprite *sprite); static void sub_80830C0(struct Sprite *sprite); static void sub_8082F9C(struct Sprite *sprite); static void Blender_SetPlayerNamesLocal(u8 opponentsNum); static void sub_807FAC8(void); static void sub_8082D28(void); static bool32 Blender_PrintText(s16 *textState, const u8 *string, s32 textSpeed); static void sub_807FFA4(void); static void sub_8080018(void); static void sub_80808D4(void); static void Blender_DummiedOutFunc(s16 a0, s16 a1); static void sub_8081898(void); static void sub_8082CB4(struct BgAffineSrcData *bgAffineSrc); static bool8 sub_8083380(void); static void sub_808074C(void); static void Blender_PrintPlayerNames(void); static void sub_8080588(void); static void Blender_SetParticipantBerryData(u8 participantId, u16 itemId); static void Blender_AddTextPrinter(u8 windowId, const u8 *string, u8 x, u8 y, s32 speed, s32 caseId); static void sub_8080DF8(void); static void sub_8082E84(void); static void sub_80832BC(s16* a0, u16 a1); static void sub_8083140(u16 a0, u16 a2); static void sub_8083230(u16 a0); static void sub_808330C(void); static void sub_8082AD4(void); static void CB2_HandleBlenderEndGame(void); static bool8 Blender_PrintBlendingRanking(void); static bool8 Blender_PrintBlendingResults(void); static void CB2_HandlePlayerPlayAgainChoice(void); static void CB2_HandlePlayerLinkPlayAgainChoice(void); static void sub_8083170(u16 a0, u16 a1); static void Blender_PrintMadePokeblockString(struct Pokeblock *pokeblock, u8 *dst); static bool32 TryAddContestLinkTvShow(struct Pokeblock *pokeblock, struct TvBlenderStruct *a1); // ewram EWRAM_DATA static struct BerryBlenderData *sBerryBlenderData = NULL; EWRAM_DATA static s32 sUnknown_020322A8[5] = {0}; EWRAM_DATA static s32 sUnknown_020322BC[5] = {0}; EWRAM_DATA static u32 sUnknown_020322D0 = 0; // iwram IWRAM_DATA static s16 sUnknown_03000DE8[8]; IWRAM_DATA static s16 sUnknown_03000DF8[6]; IWRAM_DATA static s16 sUnknown_03000E04; IWRAM_DATA static s16 sUnknown_03000E06; // rom static const u16 sBlenderCenterPal[] = INCBIN_U16("graphics/berry_blender/center.gbapal"); static const u8 sBlenderCenterMap[] = INCBIN_U8("graphics/berry_blender/center_map.bin"); static const u16 sBlenderOuterPal[] = INCBIN_U16("graphics/berry_blender/outer.gbapal"); // unreferenced pals? static const u16 sUnknownPal_0[] = INCBIN_U16("graphics/unknown/unknown_339514.gbapal"); static const u16 sUnknownArray_1[224] = {0}; // unused text? static const u8 sUnusedText_YesNo[] = _("YES\nNO"); static const u8 sUnusedText_2[] = _("▶"); static const u8 sUnusedText_Space[] = _(" "); static const u8 sUnusedText_Terminating[] = _("Terminating."); static const u8 sUnusedText_LinkPartnerNotFound[] = _("Link partner(s) not found.\nPlease try again.\p"); static const u8 sText_BerryBlenderStart[] = _("Starting up the BERRY BLENDER.\pPlease select a BERRY from your BAG\nto put in the BERRY BLENDER.\p"); static const u8 sText_NewParagraph[] = _("\p"); static const u8 sText_WasMade[] = _(" was made!"); static const u8 sText_Mister[] = _("MISTER"); static const u8 sText_Laddie[] = _("LADDIE"); static const u8 sText_Lassie[] = _("LASSIE"); static const u8 sText_Master[] = _("MASTER"); static const u8 sText_Dude[] = _("DUDE"); static const u8 sText_Miss[] = _("MISS"); static const u8* const sBlenderOpponentsNames[] = { sText_Mister, sText_Laddie, sText_Lassie, sText_Master, sText_Dude, sText_Miss }; enum { BLENDER_MISTER, BLENDER_LADDIE, BLENDER_LASSIE, BLENDER_MASTER, BLENDER_DUDE, BLENDER_MISS }; static const u8 sText_PressAToStart[] = _("Press the A Button to start."); static const u8 sText_PleaseWaitAWhile[] = _("Please wait a while."); static const u8 sText_CommunicationStandby[] = _("Communication standby…"); static const u8 sText_WouldLikeToBlendAnotherBerry[] = _("Would you like to blend another BERRY?"); static const u8 sText_RunOutOfBerriesForBlending[] = _("You’ve run out of BERRIES for\nblending in the BERRY BLENDER.\p"); static const u8 sText_YourPokeblockCaseIsFull[] = _("Your {POKEBLOCK} CASE is full.\p"); static const u8 sText_HasNoBerriesToPut[] = _(" has no BERRIES to put in\nthe BERRY BLENDER."); static const u8 sText_ApostropheSPokeblockCaseIsFull[] = _("’s {POKEBLOCK} CASE is full.\p"); static const u8 sText_BlendingResults[] = _("RESULTS OF BLENDING"); static const u8 sText_BerryUsed[] = _("BERRY USED"); static const u8 sText_SpaceBerry[] = _(" BERRY"); static const u8 sText_Time[] = _("Time:"); static const u8 sText_Min[] = _(" min. "); static const u8 sText_Sec[] = _(" sec."); static const u8 sText_MaximumSpeed[] = _("MAXIMUM SPEED"); static const u8 sText_RPM[] = _(" RPM"); static const u8 sText_Dot[] = _("."); static const u8 sText_NewLine[] = _("\n"); static const u8 sText_Space[] = _(" "); static const u8 sText_Ranking[] = _("RANKING"); static const u8 sText_TheLevelIs[] = _("The level is "); static const u8 sText_TheFeelIs[] = _(", and the feel is "); static const u8 sText_Dot2[] = _("."); static const struct BgTemplate sBerryBlenderBgTemplates[3] = { { .bg = 0, .charBaseIndex = 3, .mapBaseIndex = 31, .screenSize = 0, .paletteMode = 0, .priority = 0, .baseTile = 0, }, { .bg = 1, .charBaseIndex = 2, .mapBaseIndex = 12, .screenSize = 0, .paletteMode = 0, .priority = 1, .baseTile = 0, }, { .bg = 2, .charBaseIndex = 0, .mapBaseIndex = 8, .screenSize = 1, .paletteMode = 1, .priority = 0, .baseTile = 0, } }; static const struct WindowTemplate sBerryBlender_WindowTemplates[] = { { .priority = 0, .tilemapLeft = 1, .tilemapTop = 6, .width = 7, .height = 2, .paletteNum = 14, .baseBlock = 0x28, }, { .priority = 0, .tilemapLeft = 22, .tilemapTop = 6, .width = 7, .height = 2, .paletteNum = 14, .baseBlock = 0x36, }, { .priority = 0, .tilemapLeft = 1, .tilemapTop = 12, .width = 7, .height = 2, .paletteNum = 14, .baseBlock = 0x44, }, { .priority = 0, .tilemapLeft = 22, .tilemapTop = 12, .width = 7, .height = 2, .paletteNum = 14, .baseBlock = 0x52, }, { .priority = 0, .tilemapLeft = 2, .tilemapTop = 15, .width = 27, .height = 4, .paletteNum = 14, .baseBlock = 0x60, }, { .priority = 0, .tilemapLeft = 5, .tilemapTop = 3, .width = 21, .height = 14, .paletteNum = 14, .baseBlock = 0x60, }, DUMMY_WIN_TEMPLATE }; static const struct WindowTemplate sBlender_YesNoWindowTemplate = { .priority = 0, .tilemapLeft = 21, .tilemapTop = 9, .width = 5, .height = 4, .paletteNum = 14, .baseBlock = 0xCC }; static const s8 sUnknown_083399C0[][2] = { {-1, -1}, {1, -1}, {-1, 1}, {1, 1} }; static const u8 sBlenderSyncArrowsPos[BLENDER_MAX_PLAYERS][2] = { {72, 32}, {168, 32}, {72, 128}, {168, 128} }; static const u8 sUnknown_083399D0[3][4] = { {-1, 0, 1, -1}, {-1, 0, 1, 2}, {0, 1, 2, 3} }; static const u16 sUnknown_083399DC[] = {0, 0xC000, 0x4000, 0x8000}; static const u8 sUnknown_083399E4[] = {1, 1, 0}; static const u8 sUnknown_083399E7[] = {32, 224, 96, 160, 0}; static const TaskFunc sUnknown_083399EC[] = { sub_8080EA4, sub_8080FD0, sub_80810F8 }; static const struct OamData sOamData_8216314 = { .y = 0, .affineMode = 0, .objMode = 0, .mosaic = 0, .bpp = 0, .shape = 0, .x = 0, .matrixNum = 0, .size = 2, .tileNum = 0, .priority = 1, .paletteNum = 0, .affineParam = 0, }; static const union AnimCmd sSpriteAnim_821631C[] = { ANIMCMD_FRAME(16, 5, 1, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_8216324[] = { ANIMCMD_FRAME(16, 5, .vFlip = TRUE), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_821632C[] = { ANIMCMD_FRAME(16, 5, .hFlip = TRUE), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_8216334[] = { ANIMCMD_FRAME(16, 5, 0, 0), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_821633C[] = { ANIMCMD_FRAME(48, 2, 1, 1), ANIMCMD_FRAME(32, 5, 1, 1), ANIMCMD_FRAME(48, 3, 1, 1), ANIMCMD_FRAME(16, 5, 1, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_8216350[] = { ANIMCMD_FRAME(48, 2, .vFlip = TRUE), ANIMCMD_FRAME(32, 5, .vFlip = TRUE), ANIMCMD_FRAME(48, 3, .vFlip = TRUE), ANIMCMD_FRAME(16, 5, .vFlip = TRUE), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_8216364[] = { ANIMCMD_FRAME(48, 2, .hFlip = TRUE), ANIMCMD_FRAME(32, 5, .hFlip = TRUE), ANIMCMD_FRAME(48, 3, .hFlip = TRUE), ANIMCMD_FRAME(16, 5, .hFlip = TRUE), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_8216378[] = { ANIMCMD_FRAME(48, 2, 0, 0), ANIMCMD_FRAME(32, 5, 0, 0), ANIMCMD_FRAME(48, 3, 0, 0), ANIMCMD_FRAME(16, 5, 0, 0), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_821638C[] = { ANIMCMD_FRAME(0, 5, 1, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_8216394[] = { ANIMCMD_FRAME(0, 5, .vFlip = TRUE), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_821639C[] = { ANIMCMD_FRAME(0, 5, .hFlip = TRUE), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_82163A4[] = { ANIMCMD_FRAME(0, 5, 0, 0), ANIMCMD_END }; static const union AnimCmd *const sSpriteAnimTable_82163AC[] = { sSpriteAnim_821631C, sSpriteAnim_8216324, sSpriteAnim_821632C, sSpriteAnim_8216334, sSpriteAnim_821633C, sSpriteAnim_8216350, sSpriteAnim_8216364, sSpriteAnim_8216378, sSpriteAnim_821638C, sSpriteAnim_8216394, sSpriteAnim_821639C, sSpriteAnim_82163A4 }; static const struct SpriteSheet sSpriteSheet_BlenderArrow = { gBerryBlenderArrowTiles, 0x800, 46545 }; static const struct SpritePalette sSpritePal_BlenderMisc = { gBerryBlenderMiscPalette, 46546 }; static const struct SpritePalette sSpritePal_BlenderArrow = { gBerryBlenderArrowPalette, 12312 }; static const struct SpriteTemplate sBlenderSyncArrow_SpriteTemplate = { .tileTag = 46545, .paletteTag = 12312, .oam = &sOamData_8216314, .anims = sSpriteAnimTable_82163AC, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = sub_80833F8 }; static const struct OamData sOamData_821640C = { .y = 0, .affineMode = 0, .objMode = 0, .mosaic = 0, .bpp = 0, .shape = 0, .x = 0, .matrixNum = 0, .size = 1, .tileNum = 0, .priority = 0, .paletteNum = 0, .affineParam = 0, }; static const union AnimCmd sSpriteAnim_8216414[] = { ANIMCMD_FRAME(0, 20), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_821641C[] = { ANIMCMD_FRAME(4, 20, 1, 0), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_8216424[] = { ANIMCMD_FRAME(8, 4), ANIMCMD_FRAME(12, 4), ANIMCMD_FRAME(8, 4), ANIMCMD_FRAME(12, 4), ANIMCMD_FRAME(8, 4), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_821643C[] = { ANIMCMD_FRAME(8, 4), ANIMCMD_END }; static const union AnimCmd *const sSpriteAnimTable_8216444[] = { sSpriteAnim_8216414, sSpriteAnim_821641C, sSpriteAnim_8216424, sSpriteAnim_821643C, }; static const struct SpriteSheet sUnknown_08339B38 = { gBerryBlenderMarubatsuTiles, 0x200, 48888 }; static const struct SpriteTemplate sUnknown_08339B40 = { .tileTag = 48888, .paletteTag = 46546, .oam = &sOamData_821640C, .anims = sSpriteAnimTable_8216444, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = sub_8082F68 }; static const struct OamData sOamData_8216474 = { .y = 0, .affineMode = 0, .objMode = 0, .mosaic = 0, .bpp = 0, .shape = 0, .x = 0, .matrixNum = 0, .size = 0, .tileNum = 0, .priority = 1, .paletteNum = 0, .affineParam = 0, }; static const union AnimCmd sSpriteAnim_821647C[] = { ANIMCMD_FRAME(0, 3), ANIMCMD_FRAME(1, 4), ANIMCMD_FRAME(3, 5), ANIMCMD_FRAME(1, 4), ANIMCMD_FRAME(0, 3), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_8216494[] = { ANIMCMD_FRAME(0, 3), ANIMCMD_FRAME(2, 4), ANIMCMD_FRAME(4, 5), ANIMCMD_FRAME(2, 4), ANIMCMD_FRAME(0, 3), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_82164AC[] = { ANIMCMD_FRAME(0, 2), ANIMCMD_FRAME(1, 2), ANIMCMD_FRAME(2, 2), ANIMCMD_FRAME(4, 4), ANIMCMD_FRAME(3, 3), ANIMCMD_FRAME(2, 2), ANIMCMD_FRAME(1, 2), ANIMCMD_FRAME(0, 2), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_82164D0[] = { ANIMCMD_FRAME(5, 5, 1, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_82164D8[] = { ANIMCMD_FRAME(6, 5, 1, 1), ANIMCMD_END }; static const union AnimCmd *const sSpriteAnimTable_82164E0[] = { sSpriteAnim_821647C, sSpriteAnim_8216494, sSpriteAnim_82164AC, sSpriteAnim_82164D0, sSpriteAnim_82164D8, }; static const struct SpriteSheet sUnknown_08339BD8 = { gBerryBlenderParticlesTiles, 0xE0, 23456 }; static const struct SpriteTemplate sUnknown_08339BE0 = { .tileTag = 23456, .paletteTag = 46546, .oam = &sOamData_8216474, .anims = sSpriteAnimTable_82164E0, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy }; static const struct OamData sOamData_8216514 = { .y = 0, .affineMode = 0, .objMode = 0, .mosaic = 0, .bpp = 0, .shape = 0, .x = 0, .matrixNum = 0, .size = 2, .tileNum = 0, .priority = 1, .paletteNum = 0, .affineParam = 0, }; static const union AnimCmd sSpriteAnim_821651C[] = { ANIMCMD_FRAME(32, 30), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_8216524[] = { ANIMCMD_FRAME(16, 30), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_821652C[] = { ANIMCMD_FRAME(0, 30), ANIMCMD_END }; static const union AnimCmd *const sSpriteAnimTable_8216534[] = { sSpriteAnim_821651C, sSpriteAnim_8216524, sSpriteAnim_821652C, }; static const struct SpriteSheet sUnknown_08339C24 = { gBerryBlenderCountdownNumbersTiles, 0x600, 12345 }; static const struct SpriteTemplate sUnknown_08339C2C = { .tileTag = 12345, .paletteTag = 46546, .oam = &sOamData_8216514, .anims = sSpriteAnimTable_8216534, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = sub_8083010 }; static const struct OamData sOamData_8216560 = { .y = 0, .affineMode = 0, .objMode = 0, .mosaic = 0, .bpp = 0, .shape = 1, .x = 0, .matrixNum = 0, .size = 3, .tileNum = 0, .priority = 1, .paletteNum = 0, .affineParam = 0, }; static const union AnimCmd sSpriteAnim_8216568[] = { ANIMCMD_FRAME(0, 30), ANIMCMD_END }; static const union AnimCmd *const sSpriteAnimTable_8216570[] = { sSpriteAnim_8216568, }; static const struct SpriteSheet sUnknown_08339C58 = { gBerryBlenderStartTiles, 0x400, 12346 }; static const struct SpriteTemplate sUnknown_08339C60 = { .tileTag = 12346, .paletteTag = 46546, .oam = &sOamData_8216560, .anims = sSpriteAnimTable_8216570, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = sub_80830C0 }; static const s16 sUnknown_08339C78[][5] = { {-10, 20, 10, 2, 1}, {250, 20, 10, -2, 1}, {-10, 140, 10, 2, -1}, {250, 140, 10, -2, -1}, }; static const u8 sOpponentBerrySets[][3] = { {4, 3, 2}, {0, 4, 3}, {1, 0, 4}, {2, 1, 0}, {3, 2, 1}, {0, 2, 3}, {1, 3, 4}, {2, 4, 0}, {3, 0, 1}, {4, 1, 2}, }; static const u8 sSpecialOpponentBerrySets[] = {30, 31, 32, 33, 34}; static const u8 sUnknown_08339CC3[] = {1, 1, 2, 3, 4}; static const u8 sUnknown_08339CC8[] = {0x1C, 0x16, 0x13, 0x1A, 0x19, 0x0E, 0x0D, 0x0B, 0x07, 0x15}; static const u8 sUnknown_08339CD2[] = { 0xfe, 0x02, 0x02, 0xce, 0xd0, 0x37, 0x44, 0x07, 0x1f, 0x0c, 0x10, 0x00, 0xff, 0xfe, 0x91, 0x72, 0xce, 0xd0, 0x37, 0x44, 0x07, 0x1f, 0x0c, 0x10, 0x00, 0xff, 0x06, 0x27, 0x02, 0xff, 0x00, 0x0c, 0x48, 0x02, 0xff, 0x00, 0x01, 0x1f, 0x02, 0xff, 0x00, 0x16, 0x37, 0x02, 0xff, 0x00, 0x0d, 0x50, 0x4b, 0x02, 0xff, 0x06, 0x06, 0x06, 0x06, 0x05, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02 }; static const struct WindowTemplate sBlenderRecordWindowTemplate = { .priority = 0, .tilemapLeft = 6, .tilemapTop = 4, .width = 18, .height = 11, .paletteNum = 15, .baseBlock = 8 }; // code static void Blender_ControlHitPitch(void) { m4aMPlayPitchControl(&gMPlayInfo_SE2, 0xFFFF, 2 * (sBerryBlenderData->field_4C - 128)); } static void VBlankCB0_BerryBlender(void) { BerryBlender_SetBackgroundsPos(); SetBgAffine(2, sBerryBlenderData->bgAffineSrc.texX, sBerryBlenderData->bgAffineSrc.texY, sBerryBlenderData->bgAffineSrc.scrX, sBerryBlenderData->bgAffineSrc.scrY, sBerryBlenderData->bgAffineSrc.sx, sBerryBlenderData->bgAffineSrc.sy, sBerryBlenderData->bgAffineSrc.alpha); LoadOam(); ProcessSpriteCopyRequests(); TransferPlttBuffer(); } static bool8 LoadBerryBlenderGfx(void) { switch (sBerryBlenderData->loadGfxState) { case 0: sBerryBlenderData->tilesBuffer = AllocZeroed(GetDecompressedDataSize(sBlenderCenterGfx) + 100); LZDecompressWram(sBlenderCenterGfx, sBerryBlenderData->tilesBuffer); sBerryBlenderData->loadGfxState++; break; case 1: CopyToBgTilemapBuffer(2, sBlenderCenterMap, 0x400, 0); CopyBgTilemapBufferToVram(2); LoadPalette(sBlenderCenterPal, 0, 0x100); sBerryBlenderData->loadGfxState++; break; case 2: LoadBgTiles(2, sBerryBlenderData->tilesBuffer, GetDecompressedDataSize(sBlenderCenterGfx), 0); sBerryBlenderData->loadGfxState++; break; case 3: LZDecompressWram(gUnknown_08D91DB8, sBerryBlenderData->tilesBuffer); sBerryBlenderData->loadGfxState++; break; case 4: LoadBgTiles(1, sBerryBlenderData->tilesBuffer, GetDecompressedDataSize(gUnknown_08D91DB8), 0); sBerryBlenderData->loadGfxState++; break; case 5: LZDecompressWram(gUnknown_08D927EC, sBerryBlenderData->tilesBuffer); sBerryBlenderData->loadGfxState++; break; case 6: CopyToBgTilemapBuffer(1, sBerryBlenderData->tilesBuffer, GetDecompressedDataSize(gUnknown_08D927EC), 0); CopyBgTilemapBufferToVram(1); sBerryBlenderData->loadGfxState++; break; case 7: LoadPalette(sBlenderOuterPal, 0x80, 0x20); sBerryBlenderData->loadGfxState++; break; case 8: LoadSpriteSheet(&sSpriteSheet_BlenderArrow); LoadSpriteSheet(&sUnknown_08339BD8); LoadSpriteSheet(&sUnknown_08339B38); sBerryBlenderData->loadGfxState++; break; case 9: LoadSpriteSheet(&sUnknown_08339C24); LoadSpriteSheet(&sUnknown_08339C58); LoadSpritePalette(&sSpritePal_BlenderArrow); LoadSpritePalette(&sSpritePal_BlenderMisc); Free(sBerryBlenderData->tilesBuffer); sBerryBlenderData->loadGfxState = 0; return TRUE; } return FALSE; } static void sub_807F9D0(void) { FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 0x1E, 0x14); CopyBgTilemapBufferToVram(0); ShowBg(0); ShowBg(1); SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); ChangeBgX(0, 0, 0); ChangeBgY(0, 0, 0); ChangeBgX(1, 0, 0); ChangeBgY(1, 0, 0); } static void InitBerryBlenderWindows(void) { if (InitWindows(sBerryBlender_WindowTemplates)) { s32 i; DeactivateAllTextPrinters(); for (i = 0; i < 5; i++) FillWindowPixelBuffer(i, 0); FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 0x1E, 0x14); sub_81978B0(0xE0); } } void DoBerryBlending(void) { if (sBerryBlenderData == NULL) sBerryBlenderData = AllocZeroed(sizeof(*sBerryBlenderData)); sBerryBlenderData->gameEndState = 0; sBerryBlenderData->mainState = 0; sBerryBlenderData->gameEndState = 0; Blender_SetPlayerNamesLocal(gSpecialVar_0x8004); SetMainCallback2(sub_807FAC8); } static void sub_807FAC8(void) { s32 i; switch (sBerryBlenderData->mainState) { case 0: SetGpuReg(REG_OFFSET_DISPCNT, 0); ResetSpriteData(); FreeAllSpritePalettes(); SetVBlankCallback(NULL); ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(1, sBerryBlenderBgTemplates, ARRAY_COUNT(sBerryBlenderBgTemplates)); SetBgTilemapBuffer(1, sBerryBlenderData->tilemapBuffers[0]); SetBgTilemapBuffer(2, sBerryBlenderData->tilemapBuffers[1]); LoadUserWindowBorderGfx(0, 1, 0xD0); LoadMessageBoxGfx(0, 0x14, 0xF0); InitBerryBlenderWindows(); sBerryBlenderData->mainState++; sBerryBlenderData->field_118 = 0; sBerryBlenderData->field_116 = 0; sBerryBlenderData->field_11A = 0x50; sBerryBlenderData->bg_X = 0; sBerryBlenderData->bg_Y = 0; sBerryBlenderData->loadGfxState = 0; sub_8082D28(); break; case 1: if (LoadBerryBlenderGfx()) { for (i = 0; i < BLENDER_MAX_PLAYERS; i++) { sBerryBlenderData->syncArrowSpriteIds[i] = CreateSprite(&sBlenderSyncArrow_SpriteTemplate, sBlenderSyncArrowsPos[i][0], sBlenderSyncArrowsPos[i][1], 1); StartSpriteAnim(&gSprites[sBerryBlenderData->syncArrowSpriteIds[i]], i + 8); } if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { sub_800E0E8(); CreateWirelessStatusIndicatorSprite(0, 0); } SetVBlankCallback(VBlankCB0_BerryBlender); sBerryBlenderData->mainState++; } break; case 2: BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, 0); sub_8082D28(); sBerryBlenderData->mainState++; break; case 3: sub_807F9D0(); if (!gPaletteFade.active) sBerryBlenderData->mainState++; break; case 4: if (Blender_PrintText(&sBerryBlenderData->textState, sText_BerryBlenderStart, GetPlayerTextSpeed())) sBerryBlenderData->mainState++; break; case 5: BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, 0); sBerryBlenderData->mainState++; break; case 6: if (!gPaletteFade.active) { FreeAllWindowBuffers(); UnsetBgTilemapBuffer(2); UnsetBgTilemapBuffer(1); SetVBlankCallback(NULL); sub_81AABF0(sub_807FFA4); sBerryBlenderData->mainState = 0; } break; } AnimateSprites(); BuildOamBuffer(); RunTextPrinters(); UpdatePaletteFade(); } static void sub_807FD08(struct Sprite* sprite) { sprite->data[1] += sprite->data[6]; sprite->data[2] -= sprite->data[4]; sprite->data[2] += sprite->data[7]; sprite->data[0] += sprite->data[7]; sprite->data[4]--; if (sprite->data[0] < sprite->data[2]) { sprite->data[3] = sprite->data[4] = sprite->data[3] - 1; if (++sprite->data[5] > 3) DestroySprite(sprite); else PlaySE(SE_TB_KARA); } sprite->pos1.x = sprite->data[1]; sprite->pos1.y = sprite->data[2]; } static void sub_807FD64(struct Sprite* sprite, s16 a2, s16 a3, s16 a4, s16 a5, s16 a6) { sprite->data[0] = a3; sprite->data[1] = a2; sprite->data[2] = a3; sprite->data[3] = a4; sprite->data[4] = 10; sprite->data[5] = 0; sprite->data[6] = a5; sprite->data[7] = a6; sprite->callback = sub_807FD08; } static void sub_807FD90(u16 a0, u8 a1) { u8 spriteId = sub_80D511C(a0 + 123, 0, 80, a1 & 1); sub_807FD64(&gSprites[spriteId], sUnknown_08339C78[a1][0], sUnknown_08339C78[a1][1], sUnknown_08339C78[a1][2], sUnknown_08339C78[a1][3], sUnknown_08339C78[a1][4]); } static void Blender_CopyBerryData(struct BlenderBerry* berry, u16 itemId) { const struct Berry *berryInfo = GetBerryInfo(ITEM_TO_BERRY(itemId)); berry->itemId = itemId; StringCopy(berry->name, berryInfo->name); berry->flavors[FLAVOR_SPICY] = berryInfo->spicy; berry->flavors[FLAVOR_DRY] = berryInfo->dry; berry->flavors[FLAVOR_SWEET] = berryInfo->sweet; berry->flavors[FLAVOR_BITTER] = berryInfo->bitter; berry->flavors[FLAVOR_SOUR] = berryInfo->sour; berry->smoothness = berryInfo->smoothness; } static void Blender_SetPlayerNamesLocal(u8 opponentsNum) { switch (opponentsNum) { case 0: gInGameOpponentsNo = 0; break; case 1: gInGameOpponentsNo = 1; sBerryBlenderData->playersNo = 2; StringCopy(gLinkPlayers[0].name, gSaveBlock2Ptr->playerName); if (!FlagGet(FLAG_0x340)) StringCopy(gLinkPlayers[1].name, sBlenderOpponentsNames[BLENDER_MASTER]); else StringCopy(gLinkPlayers[1].name, sBlenderOpponentsNames[BLENDER_MISTER]); gLinkPlayers[0].language = GAME_LANGUAGE; gLinkPlayers[1].language = GAME_LANGUAGE; break; case 2: gInGameOpponentsNo = 2; sBerryBlenderData->playersNo = 3; StringCopy(gLinkPlayers[0].name, gSaveBlock2Ptr->playerName); StringCopy(gLinkPlayers[1].name, sBlenderOpponentsNames[BLENDER_DUDE]); StringCopy(gLinkPlayers[2].name, sBlenderOpponentsNames[BLENDER_LASSIE]); gLinkPlayers[0].language = GAME_LANGUAGE; gLinkPlayers[1].language = GAME_LANGUAGE; gLinkPlayers[2].language = GAME_LANGUAGE; break; case 3: gInGameOpponentsNo = 3; sBerryBlenderData->playersNo = 4; StringCopy(gLinkPlayers[0].name, gSaveBlock2Ptr->playerName); StringCopy(gLinkPlayers[1].name, sBlenderOpponentsNames[BLENDER_MISS]); StringCopy(gLinkPlayers[2].name, sBlenderOpponentsNames[BLENDER_LADDIE]); StringCopy(gLinkPlayers[3].name, sBlenderOpponentsNames[BLENDER_LASSIE]); gLinkPlayers[0].language = GAME_LANGUAGE; gLinkPlayers[1].language = GAME_LANGUAGE; gLinkPlayers[2].language = GAME_LANGUAGE; gLinkPlayers[3].language = GAME_LANGUAGE; break; } } static void sub_807FFA4(void) { s32 i; SetGpuReg(REG_OFFSET_DISPCNT, 0); if (sBerryBlenderData == NULL) sBerryBlenderData = AllocZeroed(sizeof(*sBerryBlenderData)); sBerryBlenderData->mainState = 0; sBerryBlenderData->field_10C = 0; for (i = 0; i < BLENDER_MAX_PLAYERS; i++) sBerryBlenderData->chosenItemId[i] = ITEM_NONE; Blender_SetPlayerNamesLocal(gSpecialVar_0x8004); if (gSpecialVar_0x8004 == 0) SetMainCallback2(sub_8080018); else SetMainCallback2(sub_80808D4); } static void sub_8080018(void) { s32 i, j; switch (sBerryBlenderData->mainState) { case 0: sub_8080588(); gLinkType = 0x4422; sBerryBlenderData->field_72 = 0; for (i = 0; i < BLENDER_MAX_PLAYERS; i++) { sBerryBlenderData->field_64[i] = 0; for (j = 0; j < 3; j++) { sBerryBlenderData->scores[i][j] = 0; } } sBerryBlenderData->playAgainState = 0; sBerryBlenderData->max_RPM = 0; sBerryBlenderData->loadGfxState = 0; sBerryBlenderData->mainState++; break; case 1: if (LoadBerryBlenderGfx()) { sBerryBlenderData->mainState++; sub_8082D28(); } break; case 2: for (i = 0; i < BLENDER_MAX_PLAYERS; i++) { sBerryBlenderData->syncArrowSprite2Ids[i] = CreateSprite(&sBlenderSyncArrow_SpriteTemplate, sBlenderSyncArrowsPos[i][0], sBlenderSyncArrowsPos[i][1], 1); StartSpriteAnim(&gSprites[sBerryBlenderData->syncArrowSprite2Ids[i]], i + 8); } if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { sub_800E0E8(); CreateWirelessStatusIndicatorSprite(0, 0); } sBerryBlenderData->mainState++; break; case 3: BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, 0); sBerryBlenderData->mainState++; break; case 4: sub_807F9D0(); if (!gPaletteFade.active) { sBerryBlenderData->mainState++; } break; case 5: Blender_PrintText(&sBerryBlenderData->textState, sText_CommunicationStandby, 0); sBerryBlenderData->mainState = 8; sBerryBlenderData->framesToWait = 0; break; case 8: sBerryBlenderData->mainState++; sBerryBlenderData->field_114 = 0; Blender_CopyBerryData(&sBerryBlenderData->blendedBerries[0], gSpecialVar_ItemId); memcpy(gBlockSendBuffer, &sBerryBlenderData->blendedBerries[0], sizeof(struct BlenderBerry)); sub_800ADF8(); sBerryBlenderData->framesToWait = 0; break; case 9: if (sub_800A520()) { ResetBlockReceivedFlags(); if (GetMultiplayerId() == 0) sub_800A4D8(4); sBerryBlenderData->mainState++; } break; case 10: if (++sBerryBlenderData->framesToWait > 20) { sub_8197DF8(4, TRUE); if (GetBlockReceivedStatus() == sub_800A9D8()) { for (i = 0; i < GetLinkPlayerCount(); i++) { memcpy(&sBerryBlenderData->blendedBerries[i], &gBlockRecvBuffer[i][0], sizeof(struct BlenderBerry)); sBerryBlenderData->chosenItemId[i] = sBerryBlenderData->blendedBerries[i].itemId; } ResetBlockReceivedFlags(); sBerryBlenderData->mainState++; } } break; case 11: sBerryBlenderData->playersNo = GetLinkPlayerCount(); for (i = 0; i < BLENDER_MAX_PLAYERS; i++) { if (sBerryBlenderData->field_114 == sUnknown_083399D0[sBerryBlenderData->playersNo - 2][i]) { sub_807FD90(sBerryBlenderData->chosenItemId[sBerryBlenderData->field_114], i); break; } } sBerryBlenderData->framesToWait = 0; sBerryBlenderData->mainState++; sBerryBlenderData->field_114++; break; case 12: if (++sBerryBlenderData->framesToWait > 60) { if (sBerryBlenderData->field_114 >= sBerryBlenderData->playersNo) { sBerryBlenderData->mainState++; sBerryBlenderData->arrowPos = sUnknown_083399DC[sUnknown_083399E4[sBerryBlenderData->playersNo - 2]] - 22528; } else { sBerryBlenderData->mainState--; } sBerryBlenderData->framesToWait = 0; } break; case 13: if (sub_800A520()) { sBerryBlenderData->mainState++; sub_8082CB4(&sBerryBlenderData->bgAffineSrc); PlaySE(SE_RU_HYUU); ShowBg(2); } break; case 14: SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON); sBerryBlenderData->arrowPos += 0x200; sBerryBlenderData->field_11A += 4; if (sBerryBlenderData->field_11A > 0xFF) { SetGpuRegBits(REG_OFFSET_BG2CNT, 2); sBerryBlenderData->mainState++; sBerryBlenderData->field_11A = 0x100; sBerryBlenderData->arrowPos = sUnknown_083399DC[sUnknown_083399E4[sBerryBlenderData->playersNo - 2]]; sBerryBlenderData->framesToWait = 0; PlaySE(SE_TRACK_DOOR); sub_808074C(); Blender_PrintPlayerNames(); } sub_8082CB4(&sBerryBlenderData->bgAffineSrc); break; case 15: if (sub_8083380()) { sBerryBlenderData->framesToWait = 0; sBerryBlenderData->mainState++; } sub_8082CB4(&sBerryBlenderData->bgAffineSrc); break; case 16: CreateSprite(&sUnknown_08339C2C, 120, -16, 3); sBerryBlenderData->mainState++; break; case 18: sBerryBlenderData->mainState++; break; case 19: sub_800ADF8(); sBerryBlenderData->mainState++; break; case 20: if (sub_800A520()) { sub_800A418(); sBerryBlenderData->mainState++; } break; case 21: sBerryBlenderData->field_4C = 128; sBerryBlenderData->gameFrameTime = 0; SetMainCallback2(sub_8081898); if (GetCurrentMapMusic() != MUS_CYCLING) { sBerryBlenderData->field_154 = GetCurrentMapMusic(); } PlayBGM(MUS_CYCLING); break; } Blender_DummiedOutFunc(sBerryBlenderData->bg_X, sBerryBlenderData->bg_Y); RunTasks(); AnimateSprites(); BuildOamBuffer(); RunTextPrinters(); UpdatePaletteFade(); } static void sub_8080588(void) { SetGpuReg(REG_OFFSET_DISPCNT, 0); ResetSpriteData(); FreeAllSpritePalettes(); ResetTasks(); SetVBlankCallback(VBlankCB0_BerryBlender); ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(1, sBerryBlenderBgTemplates, ARRAY_COUNT(sBerryBlenderBgTemplates)); SetBgTilemapBuffer(1, sBerryBlenderData->tilemapBuffers[0]); SetBgTilemapBuffer(2, sBerryBlenderData->tilemapBuffers[1]); LoadUserWindowBorderGfx(0, 1, 0xD0); LoadMessageBoxGfx(0, 0x14, 0xF0); InitBerryBlenderWindows(); sBerryBlenderData->field_44 = 0; sBerryBlenderData->field_4C = 0; sBerryBlenderData->arrowPos = 0; sBerryBlenderData->max_RPM = 0; sBerryBlenderData->bg_X = 0; sBerryBlenderData->bg_Y = 0; } static u8 sub_8080624(u16 arrowPos, u8 playerId) { u32 var1 = (arrowPos / 0x100) + 0x18; u8 arrID = sBerryBlenderData->field_96[playerId]; u32 var2 = sUnknown_083399E7[arrID]; if (var1 >= var2 && var1 < var2 + 0x30) { if (var1 >= var2 + 20 && var1 < var2 + 28) return 2; else return 1; } return 0; } static void Blender_SetOpponentsBerryData(u16 playerBerryItemId, u8 playersNum, struct BlenderBerry* playerBerry) { u16 opponentSetId = 0; u16 opponentBerryId; u16 var; u16 i; if (playerBerryItemId == ITEM_ENIGMA_BERRY) { for (i = 0; i < FLAVOR_COUNT; i++) { if (playerBerry->flavors[opponentSetId] > playerBerry->flavors[i]) opponentSetId = i; } opponentSetId += 5; } else { opponentSetId = playerBerryItemId - FIRST_BERRY_INDEX; if (opponentSetId >= 5) opponentSetId = (opponentSetId % 5) + 5; } for (i = 0; i < playersNum - 1; i++) { opponentBerryId = sOpponentBerrySets[opponentSetId][i]; var = playerBerryItemId - 163; if (!FlagGet(0x340) && gSpecialVar_0x8004 == 1) { opponentSetId %= 5; opponentBerryId = sSpecialOpponentBerrySets[opponentSetId]; if (var <= 4) opponentBerryId -= 5; } Blender_SetParticipantBerryData(i + 1, opponentBerryId + FIRST_BERRY_INDEX); } } static void sub_808074C(void) { s32 i, j; for (i = 0; i < BLENDER_MAX_PLAYERS; i++) { sBerryBlenderData->field_96[i] = 0xFF; sBerryBlenderData->field_8E[i] = sUnknown_083399D0[sBerryBlenderData->playersNo - 2][i]; } for (j = 0; j < BLENDER_MAX_PLAYERS; j++) { for (i = 0; i < BLENDER_MAX_PLAYERS; i++) { if (sBerryBlenderData->field_8E[i] == j) sBerryBlenderData->field_96[j] = i; } } } static void Blender_PrintPlayerNames(void) { s32 i, xPos; u32 multiplayerId = 0; u8 text[20]; if (gReceivedRemoteLinkPlayers) multiplayerId = GetMultiplayerId(); for (i = 0; i < BLENDER_MAX_PLAYERS; i++) { if (sBerryBlenderData->field_8E[i] != 0xFF) { sBerryBlenderData->syncArrowSpriteIds[sBerryBlenderData->field_8E[i]] = sBerryBlenderData->syncArrowSprite2Ids[i]; StartSpriteAnim(&gSprites[sBerryBlenderData->syncArrowSpriteIds[sBerryBlenderData->field_8E[i]]], i); text[0] = EOS; StringCopy(text, gLinkPlayers[sBerryBlenderData->field_8E[i]].name); xPos = GetStringCenterAlignXOffset(1, text, 0x38); if (multiplayerId == sBerryBlenderData->field_8E[i]) Blender_AddTextPrinter(i, text, xPos, 1, 0, 2); else Blender_AddTextPrinter(i, text, xPos, 1, 0, 1); PutWindowTilemap(i); CopyWindowToVram(i, 3); } } } static void sub_80808D4(void) { s32 i, j; switch (sBerryBlenderData->mainState) { case 0: sub_800B4C0(); sub_8080588(); Blender_SetParticipantBerryData(0, gSpecialVar_ItemId); Blender_CopyBerryData(&sBerryBlenderData->blendedBerries[0], gSpecialVar_ItemId); Blender_SetOpponentsBerryData(gSpecialVar_ItemId, sBerryBlenderData->playersNo, &sBerryBlenderData->blendedBerries[0]); for (i = 0; i < BLENDER_MAX_PLAYERS; i++) { sBerryBlenderData->field_64[i] = 0; for (j = 0; j < 3; j++) { sBerryBlenderData->scores[i][j] = 0; } } sBerryBlenderData->playAgainState = 0; sBerryBlenderData->loadGfxState = 0; gLinkType = 0x4422; sBerryBlenderData->mainState++; break; case 1: if (LoadBerryBlenderGfx()) { sBerryBlenderData->mainState++; sub_8082D28(); } break; case 2: for (i = 0; i < BLENDER_MAX_PLAYERS; i++) { sBerryBlenderData->syncArrowSprite2Ids[i] = CreateSprite(&sBlenderSyncArrow_SpriteTemplate, sBlenderSyncArrowsPos[i][0], sBlenderSyncArrowsPos[i][1], 1); StartSpriteAnim(&gSprites[sBerryBlenderData->syncArrowSprite2Ids[i]], i + 8); } sBerryBlenderData->mainState++; break; case 3: BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, 0); sBerryBlenderData->mainState++; sBerryBlenderData->framesToWait = 0; break; case 4: if (++sBerryBlenderData->framesToWait == 2) sub_807F9D0(); if (!gPaletteFade.active) sBerryBlenderData->mainState = 8; break; case 8: sBerryBlenderData->mainState = 11; sBerryBlenderData->field_114 = 0; break; case 11: for (i = 0; i < BLENDER_MAX_PLAYERS; i++) { u32 var = sUnknown_083399D0[sBerryBlenderData->playersNo - 2][i]; if (sBerryBlenderData->field_114 == var) { sub_807FD90(sBerryBlenderData->chosenItemId[sBerryBlenderData->field_114], i); break; } } sBerryBlenderData->framesToWait = 0; sBerryBlenderData->mainState++; sBerryBlenderData->field_114++; break; case 12: if (++sBerryBlenderData->framesToWait > 60) { if (sBerryBlenderData->field_114 >= sBerryBlenderData->playersNo) { sBerryBlenderData->arrowPos = sUnknown_083399DC[sUnknown_083399E4[sBerryBlenderData->playersNo - 2]] - 22528; sBerryBlenderData->mainState++; } else { sBerryBlenderData->mainState--; } sBerryBlenderData->framesToWait = 0; } break; case 13: sBerryBlenderData->mainState++; sub_808074C(); PlaySE(SE_RU_HYUU); sub_8082CB4(&sBerryBlenderData->bgAffineSrc); ShowBg(2); break; case 14: SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON); sBerryBlenderData->arrowPos += 0x200; sBerryBlenderData->field_11A += 4; if (sBerryBlenderData->field_11A > 0xFF) { sBerryBlenderData->mainState++; sBerryBlenderData->field_11A = 0x100; sBerryBlenderData->arrowPos = sUnknown_083399DC[sUnknown_083399E4[sBerryBlenderData->playersNo - 2]]; SetGpuRegBits(REG_OFFSET_BG2CNT, 2); sBerryBlenderData->framesToWait = 0; PlaySE(SE_TRACK_DOOR); Blender_PrintPlayerNames(); } sub_8082CB4(&sBerryBlenderData->bgAffineSrc); break; case 15: if (sub_8083380()) { sBerryBlenderData->mainState++; } sub_8082CB4(&sBerryBlenderData->bgAffineSrc); break; case 16: CreateSprite(&sUnknown_08339C2C, 120, -16, 3); sBerryBlenderData->mainState++; break; case 18: sBerryBlenderData->mainState++; break; case 19: sBerryBlenderData->mainState++; break; case 20: sBerryBlenderData->mainState++; break; case 21: sub_8080DF8(); sBerryBlenderData->field_4C = 0x80; sBerryBlenderData->gameFrameTime = 0; sBerryBlenderData->field_123 = 0; sBerryBlenderData->field_72 = 0; SetMainCallback2(sub_8081898); if (gSpecialVar_0x8004 == 1) { if (!FlagGet(FLAG_0x340)) sBerryBlenderData->field_120[0] = CreateTask(sub_8081224, 10); else sBerryBlenderData->field_120[0] = CreateTask(sUnknown_083399EC[0], 10); } if (gSpecialVar_0x8004 > 1) { for (i = 0; i < gSpecialVar_0x8004; i++) sBerryBlenderData->field_120[i] = CreateTask(sUnknown_083399EC[i], 10 + i); } if (GetCurrentMapMusic() != MUS_CYCLING) sBerryBlenderData->field_154 = GetCurrentMapMusic(); PlayBGM(MUS_CYCLING); PlaySE(SE_MOTER); Blender_ControlHitPitch(); break; } Blender_DummiedOutFunc(sBerryBlenderData->bg_X, sBerryBlenderData->bg_Y); RunTasks(); AnimateSprites(); BuildOamBuffer(); RunTextPrinters(); UpdatePaletteFade(); } static void sub_8080DF8(void) { s32 i; for (i = 0; i < 4; i++) { gSendCmd[0] = 0; gSendCmd[2] = 0; gRecvCmds[i][0] = 0; gRecvCmds[i][2] = 0; } } static void sub_8080E20(u8 taskId) { if(++gTasks[taskId].data[0] > gTasks[taskId].data[1]) { gRecvCmds[gTasks[taskId].data[2]][2] = 0x2345; DestroyTask(taskId); } } static void sub_8080E6C(u8 a0, u8 a1) { u8 taskId = CreateTask(sub_8080E20, 80); gTasks[taskId].data[1] = a1; gTasks[taskId].data[2] = a0; } static void sub_8080EA4(u8 taskId) { if (sub_8080624(sBerryBlenderData->arrowPos, 1) == 2) { if (gTasks[taskId].data[0] == 0) { if (sBerryBlenderData->field_123 == 0) { u8 rand = Random() / 655; if (sBerryBlenderData->field_4C < 500) { if (rand > 75) gRecvCmds[1][2] = 0x4523; else gRecvCmds[1][2] = 0x5432; gRecvCmds[1][2] = 0x5432; } else if (sBerryBlenderData->field_4C < 1500) { if (rand > 80) { gRecvCmds[1][2] = 0x4523; } else { u8 value = rand - 21; if (value < 60) gRecvCmds[1][2] = 0x5432; else if (rand < 10) sub_8080E6C(1, 5); } } else if (rand <= 90) { u8 value = rand - 71; if (value < 20) gRecvCmds[1][2] = 0x5432; else if (rand < 30) sub_8080E6C(1, 5); } else { gRecvCmds[1][2] = 0x4523; } } else { gRecvCmds[1][2] = 0x4523; } gTasks[taskId].data[0] = 1; } } else { gTasks[taskId].data[0] = 0; } } static void sub_8080FD0(u8 taskId) { u32 var1 = (sBerryBlenderData->arrowPos + 0x1800) & 0xFFFF; u32 var2 = sBerryBlenderData->field_96[2] & 0xFF; if ((var1 >> 8) > sUnknown_083399E7[var2] + 20 && (var1 >> 8) < sUnknown_083399E7[var2] + 40) { if (gTasks[taskId].data[0] == 0) { if (sBerryBlenderData->field_123 == 0) { u8 rand = Random() / 655; if (sBerryBlenderData->field_4C < 500) { if (rand > 66) gRecvCmds[2][2] = 0x4523; else gRecvCmds[2][2] = 0x5432; } else { u8 value; if (rand > 65) gRecvCmds[2][2] = 0x4523; value = rand - 41; if (value < 25) gRecvCmds[2][2] = 0x5432; if (rand < 10) sub_8080E6C(2, 5); } gTasks[taskId].data[0] = 1; } else { gRecvCmds[2][2] = 0x4523; gTasks[taskId].data[0] = 1; } } } else { gTasks[taskId].data[0] = 0; } } static void sub_80810F8(u8 taskId) { u32 var1, var2; var1 = (sBerryBlenderData->arrowPos + 0x1800) & 0xFFFF; var2 = sBerryBlenderData->field_96[3] & 0xFF; if ((var1 >> 8) > sUnknown_083399E7[var2] + 20 && (var1 >> 8) < sUnknown_083399E7[var2] + 40) { if (gTasks[taskId].data[0] == 0) { if (sBerryBlenderData->field_123 == 0) { u8 rand = (Random() / 655); if (sBerryBlenderData->field_4C < 500) { if (rand > 88) gRecvCmds[3][2] = 0x4523; else gRecvCmds[3][2] = 0x5432; } else { if (rand > 60) { gRecvCmds[3][2] = 0x4523; } else { s8 value = rand - 56; // makes me wonder what the original code was u8 value2 = value; if (value2 < 5) gRecvCmds[3][2] = 0x5432; } if (rand < 5) sub_8080E6C(3, 5); } gTasks[taskId].data[0] = 1; } else { gRecvCmds[3][2] = 0x4523; gTasks[taskId].data[0] = 1; } } } else { gTasks[taskId].data[0] = 0; } } static void sub_8081224(u8 taskId) { if (sub_8080624(sBerryBlenderData->arrowPos, 1) == 2) { if (gTasks[taskId].data[0] == 0) { gRecvCmds[1][2] = 0x4523; gTasks[taskId].data[0] = 1; } } else { gTasks[taskId].data[0] = 0; } } static void sub_8081288(u16 a0, u8 a1) { u8 spriteId; spriteId = CreateSprite(&sUnknown_08339B40, sBlenderSyncArrowsPos[a1][0] - (10 * sUnknown_083399C0[a1][0]), sBlenderSyncArrowsPos[a1][1] - (10 * sUnknown_083399C0[a1][1]), 1); if (a0 == 0x4523) { StartSpriteAnim(&gSprites[spriteId], 2); gSprites[spriteId].callback = sub_8082F9C; PlaySE(SE_RU_GASHIN); } else if (a0 == 0x5432) { StartSpriteAnim(&gSprites[spriteId], 0); PlaySE(SE_SEIKAI); } else if (a0 == 0x2345) { StartSpriteAnim(&gSprites[spriteId], 1); PlaySE(SE_HAZURE); } sub_8082E84(); } static void sub_8081370(u16 a0) { Blender_ControlHitPitch(); switch (a0) { case 0x4523: if (sBerryBlenderData->field_4C < 1500) sBerryBlenderData->field_4C += (0x180 / sUnknown_08339CC3[sBerryBlenderData->playersNo]); else { sBerryBlenderData->field_4C += (128 / sUnknown_08339CC3[sBerryBlenderData->playersNo]); sub_80832BC(&sBerryBlenderData->bg_X, (sBerryBlenderData->field_4C / 100) - 10); sub_80832BC(&sBerryBlenderData->bg_Y, (sBerryBlenderData->field_4C / 100) - 10); } break; case 0x5432: if (sBerryBlenderData->field_4C < 1500) sBerryBlenderData->field_4C += (0x100 / sUnknown_08339CC3[sBerryBlenderData->playersNo]); break; case 0x2345: sBerryBlenderData->field_4C -= (0x100 / sUnknown_08339CC3[sBerryBlenderData->playersNo]); if (sBerryBlenderData->field_4C < 0x80) sBerryBlenderData->field_4C = 0x80; break; } } static bool32 sub_80814B0(u16 arg0, u16 arg1, u16 arg2) { if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { if ((arg0 & 0xFF00) == arg2) return TRUE; } else { if (arg0 == arg1) return TRUE; } return FALSE; } static void sub_80814F4(void) { s32 i; if (gSpecialVar_0x8004 != 0) { if (gSendCmd[2] != 0) { gRecvCmds[0][2] = gSendCmd[2]; gRecvCmds[0][0] = 0x4444; gSendCmd[2] = 0; } for (i = 1; i < 4; i++) { if (gRecvCmds[i][2] != 0) gRecvCmds[i][0] = 0x4444; } } for (i = 0; i < sBerryBlenderData->playersNo; i++) { if (sub_80814B0(gRecvCmds[i][0], 0x4444, 0x4400)) { u32 var = sBerryBlenderData->field_96[i]; if (gRecvCmds[i][2] == 0x4523) { sub_8081370(0x4523); sBerryBlenderData->field_116 += (sBerryBlenderData->field_4C / 55); if (sBerryBlenderData->field_116 >= 1000) sBerryBlenderData->field_116 = 1000; sub_8081288(0x4523, var); sBerryBlenderData->scores[i][BLENDER_SCORE_BEST]++; } else if (gRecvCmds[i][2] == 0x5432) { sub_8081370(0x5432); sBerryBlenderData->field_116 += (sBerryBlenderData->field_4C / 70); sub_8081288(0x5432, var); sBerryBlenderData->scores[i][BLENDER_SCORE_GOOD]++; } else if (gRecvCmds[i][2] == 0x2345) { sub_8081288(0x2345, var); sub_8081370(0x2345); if (sBerryBlenderData->scores[i][BLENDER_SCORE_MISS] < 999) sBerryBlenderData->scores[i][BLENDER_SCORE_MISS]++; } if (gRecvCmds[i][2] == 0x2345 || gRecvCmds[2][i] == 0x4523 || gRecvCmds[2][i] == 0x5432) // could be a bug, 2 and i are reversed { if (sBerryBlenderData->field_4C > 1500) m4aMPlayTempoControl(&gMPlayInfo_BGM, ((sBerryBlenderData->field_4C - 750) / 20) + 256); else m4aMPlayTempoControl(&gMPlayInfo_BGM, 0x100); } } } if (gSpecialVar_0x8004 != 0) { for (i = 0; i < sBerryBlenderData->playersNo; i++) { gRecvCmds[i][0] = 0; gRecvCmds[i][2] = 0; } } } static void sub_8081744(void) { u8 var2; bool8 A_pressed = FALSE; u8 playerId = 0; if (gReceivedRemoteLinkPlayers != 0) playerId = GetMultiplayerId(); var2 = sBerryBlenderData->field_96[playerId]; if (sBerryBlenderData->gameEndState == 0) { if (gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A && gMain.newKeys & A_BUTTON) { if ((gMain.heldKeysRaw & (A_BUTTON | L_BUTTON)) != (A_BUTTON | L_BUTTON)) A_pressed = TRUE; } else if (gMain.newKeys & A_BUTTON) { A_pressed = TRUE; } if (A_pressed) { u8 var3; StartSpriteAnim(&gSprites[sBerryBlenderData->syncArrowSpriteIds[sBerryBlenderData->field_8E[var2]]], var2 + 4); var3 = sub_8080624(sBerryBlenderData->arrowPos, playerId); if (var3 == 2) gSendCmd[2] = 0x4523; else if (var3 == 1) gSendCmd[2] = 0x5432; else gSendCmd[2] = 0x2345; } } if (++sBerryBlenderData->field_72 > 5) { if (sBerryBlenderData->field_4C > 128) sBerryBlenderData->field_4C--; sBerryBlenderData->field_72 = 0; } if (gUnknown_020322D5 && gMain.newKeys & L_BUTTON) sBerryBlenderData->field_123 ^= 1; } static void sub_8081898(void) { sub_8082D28(); if (sBerryBlenderData->gameFrameTime < (99 * 60 * 60) + (59 * 60)) // game time can't be longer than 99 minutes and 59 seconds, can't print 3 digits sBerryBlenderData->gameFrameTime++; sub_8081744(); SetLinkDebugValues((u16)(sBerryBlenderData->field_4C), sBerryBlenderData->field_116); sub_80814F4(); sub_8083140(sBerryBlenderData->field_116, 1000); sub_8083230(sBerryBlenderData->field_4C); sub_808330C(); sub_8082AD4(); if (sBerryBlenderData->gameEndState == 0 && sBerryBlenderData->field_118 >= 1000) { sBerryBlenderData->field_116 = 1000; sBerryBlenderData->gameEndState = 1; SetMainCallback2(CB2_HandleBlenderEndGame); } Blender_DummiedOutFunc(sBerryBlenderData->bg_X, sBerryBlenderData->bg_Y); RunTasks(); AnimateSprites(); BuildOamBuffer(); RunTextPrinters(); UpdatePaletteFade(); } static void Blender_DummiedOutFunc(s16 a0, s16 a1) { } static bool8 sub_8081964(struct BlenderBerry* berries, u8 index1, u8 index2) { if (berries[index1].itemId != berries[index2].itemId || (StringCompare(berries[index1].name, berries[index2].name) == 0 && (berries[index1].flavors[FLAVOR_SPICY] == berries[index2].flavors[FLAVOR_SPICY] && berries[index1].flavors[FLAVOR_DRY] == berries[index2].flavors[FLAVOR_DRY] && berries[index1].flavors[FLAVOR_SWEET] == berries[index2].flavors[FLAVOR_SWEET] && berries[index1].flavors[FLAVOR_BITTER] == berries[index2].flavors[FLAVOR_BITTER] && berries[index1].flavors[FLAVOR_SOUR] == berries[index2].flavors[FLAVOR_SOUR] && berries[index1].smoothness == berries[index2].smoothness))) return TRUE; else return FALSE; } static u32 Blender_GetPokeblockColor(struct BlenderBerry* berries, s16* a1, u8 playersNo, u8 a3) { s16 vars[6]; s32 i; s32 r6; u8 r2; for (i = 0; i < 6; i++) vars[i] = a1[i]; r6 = 0; for (i = 0; i < 5; i++) { if (vars[i] == 0) r6++; } if (r6 == 5 || a3 > 3) return 12; for (i = 0; i < playersNo; i++) { for (r6 = 0; r6 < playersNo; r6++) { if (berries[i].itemId == berries[r6].itemId && i != r6 && (berries[i].itemId != ITEM_ENIGMA_BERRY || sub_8081964(berries, i, r6))) return 12; } } r2 = 0; for (r2 = 0, i = 0; i < 5; i++) { if (vars[i] > 0) r2++; } if (r2 > 3) return 13; if (r2 == 3) return 11; for (i = 0; i < 5; i++) { if (vars[i] > 50) return 14; } if (r2 == 1 && vars[0] > 0) return 1; if (r2 == 1 && vars[1] > 0) return 2; if (r2 == 1 && vars[2] > 0) return 3; if (r2 == 1 && vars[3] > 0) return 4; if (r2 == 1 && vars[4] > 0) return 5; if (r2 == 2) { s32 var = 0; for (i = 0; i < 5; i++) { if (vars[i] > 0) sUnknown_03000DF8[var++] = i; } if (vars[sUnknown_03000DF8[0]] >= vars[sUnknown_03000DF8[1]]) { if (sUnknown_03000DF8[0] == 0) return (sUnknown_03000DF8[1] << 16) | 6; if (sUnknown_03000DF8[0] == 1) return (sUnknown_03000DF8[1] << 16) | 7; if (sUnknown_03000DF8[0] == 2) return (sUnknown_03000DF8[1] << 16) | 8; if (sUnknown_03000DF8[0] == 3) return (sUnknown_03000DF8[1] << 16) | 9; if (sUnknown_03000DF8[0] == 4) return (sUnknown_03000DF8[1] << 16) | 10; } else { if (sUnknown_03000DF8[1] == 0) return (sUnknown_03000DF8[0] << 16) | 6; if (sUnknown_03000DF8[1] == 1) return (sUnknown_03000DF8[0] << 16) | 7; if (sUnknown_03000DF8[1] == 2) return (sUnknown_03000DF8[0] << 16) | 8; if (sUnknown_03000DF8[1] == 3) return (sUnknown_03000DF8[0] << 16) | 9; if (sUnknown_03000DF8[1] == 4) return (sUnknown_03000DF8[0] << 16) | 10; } } return 0; } static void sub_8081BB0(s16 value) { sUnknown_03000E04 = value; } static s16 sub_8081BBC(void) { return sUnknown_03000E04; } static void sub_8081BC8(s16 value) { sUnknown_03000E06 = value; } static s16 sub_8081BD4(void) { return sUnknown_03000E06; } static void Blender_CalculatePokeblock(struct BlenderBerry *berries, struct Pokeblock *pokeblock, u8 playersNo, u8 *flavors, u16 maxRPM) { s32 i, j; s32 multiuseVar, var2; u8 var3; for (i = 0; i < 6; i++) sUnknown_03000DE8[i] = 0; for (i = 0; i < playersNo; i++) { for (j = 0; j < 6; j++) sUnknown_03000DE8[j] += berries[i].flavors[j]; } multiuseVar = sUnknown_03000DE8[0]; sUnknown_03000DE8[0] -= sUnknown_03000DE8[1]; sUnknown_03000DE8[1] -= sUnknown_03000DE8[2]; sUnknown_03000DE8[2] -= sUnknown_03000DE8[3]; sUnknown_03000DE8[3] -= sUnknown_03000DE8[4]; sUnknown_03000DE8[4] -= multiuseVar; multiuseVar = 0; for (i = 0; i < 5; i++) { if (sUnknown_03000DE8[i] < 0) { sUnknown_03000DE8[i] = 0; multiuseVar++; } } var3 = multiuseVar; for (i = 0; i < 5; i++) { if (sUnknown_03000DE8[i] > 0) { if (sUnknown_03000DE8[i] < multiuseVar) sUnknown_03000DE8[i] = 0; else sUnknown_03000DE8[i] -= multiuseVar; } } for (i = 0; i < 5; i++) { sUnknown_020322A8[i] = sUnknown_03000DE8[i]; } multiuseVar = maxRPM / 333 + 100; sUnknown_020322D0 = multiuseVar; for (i = 0; i < 5; i++) { s32 r4; s32 r5 = sUnknown_03000DE8[i]; r5 = (r5 * multiuseVar) / 10; r4 = r5 % 10; r5 /= 10; if (r4 > 4) r5++; sUnknown_03000DE8[i] = r5; } for (i = 0; i < 5; i++) { sUnknown_020322BC[i] = sUnknown_03000DE8[i]; } pokeblock->color = Blender_GetPokeblockColor(berries, &sUnknown_03000DE8[0], playersNo, var3); sUnknown_03000DE8[5] = (sUnknown_03000DE8[5] / playersNo) - playersNo; if (sUnknown_03000DE8[5] < 0) sUnknown_03000DE8[5] = 0; if (pokeblock->color == 12) { multiuseVar = Random() % 10; for (i = 0; i < 5; i++) { if ((sUnknown_08339CC8[multiuseVar] >> i) & 1) sUnknown_03000DE8[i] = 2; else sUnknown_03000DE8[i] = 0; } } for (i = 0; i < 6; i++) { if (sUnknown_03000DE8[i] > 255) sUnknown_03000DE8[i] = 255; } pokeblock->spicy = sUnknown_03000DE8[0]; pokeblock->dry = sUnknown_03000DE8[1]; pokeblock->sweet = sUnknown_03000DE8[2]; pokeblock->bitter = sUnknown_03000DE8[3]; pokeblock->sour = sUnknown_03000DE8[4]; pokeblock->feel = sUnknown_03000DE8[5]; for (i = 0; i < 6; i++) { flavors[i] = sUnknown_03000DE8[i]; } } static void BlenderDebug_CalculatePokeblock(struct BlenderBerry* berries, struct Pokeblock* pokeblock, u8 playersNo, u8* flavors, u16 a4) { Blender_CalculatePokeblock(berries, pokeblock, playersNo, flavors, a4); } static void sub_8081E20(void) { u32 frames = (u16)(sBerryBlenderData->gameFrameTime); u16 max_RPM = sBerryBlenderData->max_RPM; s16 var = 0; if (frames < 900) var = 5; else if ((u16)(frames - 900) < 600) var = 4; else if ((u16)(frames - 1500) < 600) var = 3; else if ((u16)(frames - 2100) < 900) var = 2; else if ((u16)(frames - 3300) < 300) var = 1; sub_8081BC8(var); var = 0; if (max_RPM <= 64) { if (max_RPM >= 50 && max_RPM < 100) var = -1; else if (max_RPM >= 100 && max_RPM < 150) var = -2; else if (max_RPM >= 150 && max_RPM < 200) var = -3; else if (max_RPM >= 200 && max_RPM < 250) var = -4; else if (max_RPM >= 250 && max_RPM < 300) var = -5; else if (max_RPM >= 350 && max_RPM < 400) var = -6; else if (max_RPM >= 400 && max_RPM < 450) var = -7; else if (max_RPM >= 500 && max_RPM < 550) var = -8; else if (max_RPM >= 550 && max_RPM < 600) var = -9; else if (max_RPM >= 600) var = -10; } sub_8081BB0(var); } static void sub_8081F94(u16 *a0) { if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) *a0 = 0x2F00; else *a0 = 0x2FFF; } static void CB2_HandleBlenderEndGame(void) { u8 i, j; if (sBerryBlenderData->gameEndState < 3) sub_8082D28(); GetMultiplayerId(); // unused return value switch (sBerryBlenderData->gameEndState) { case 1: m4aMPlayTempoControl(&gMPlayInfo_BGM, 256); for (i = 0; i < gSpecialVar_0x8004; i++) { DestroyTask(sBerryBlenderData->field_120[i]); } sBerryBlenderData->gameEndState++; break; case 2: sBerryBlenderData->field_4C -= 32; if (sBerryBlenderData->field_4C <= 0) { ClearLinkCallback(); sBerryBlenderData->field_4C = 0; if (gReceivedRemoteLinkPlayers != 0) sBerryBlenderData->gameEndState++; else sBerryBlenderData->gameEndState = 5; sBerryBlenderData->mainState = 0; m4aMPlayStop(&gMPlayInfo_SE2); } Blender_ControlHitPitch(); break; case 3: if (GetMultiplayerId() != 0) { sBerryBlenderData->gameEndState++; } else if (sub_800A520()) { if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { sBerryBlenderData->gameBlock.timeRPM.time = sBerryBlenderData->gameFrameTime; sBerryBlenderData->gameBlock.timeRPM.max_RPM = sBerryBlenderData->max_RPM; for (i = 0; i < BLENDER_MAX_PLAYERS; i++) { for (j = 0; j < BLENDER_SCORES_NO; j++) sBerryBlenderData->gameBlock.scores[i][j] = sBerryBlenderData->scores[i][j]; } if (SendBlock(0, &sBerryBlenderData->gameBlock, sizeof(sBerryBlenderData->gameBlock))) sBerryBlenderData->gameEndState++; } else { sBerryBlenderData->smallBlock.time = sBerryBlenderData->gameFrameTime; sBerryBlenderData->smallBlock.max_RPM = sBerryBlenderData->max_RPM; if (SendBlock(0, &sBerryBlenderData->smallBlock, sizeof(sBerryBlenderData->smallBlock) + 32)) sBerryBlenderData->gameEndState++; } } break; case 4: if (GetBlockReceivedStatus()) { ResetBlockReceivedFlags(); sBerryBlenderData->gameEndState++; if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { struct BlenderGameBlock *receivedBlock = (struct BlenderGameBlock*)(&gBlockRecvBuffer); sBerryBlenderData->max_RPM = receivedBlock->timeRPM.max_RPM; sBerryBlenderData->gameFrameTime = receivedBlock->timeRPM.time; for (i = 0; i < BLENDER_MAX_PLAYERS; i++) { for (j = 0; j < BLENDER_SCORES_NO; j++) sBerryBlenderData->scores[i][j] = receivedBlock->scores[i][j]; } } else { struct TimeAndRPM *receivedBlock = (struct TimeAndRPM*)(&gBlockRecvBuffer); sBerryBlenderData->max_RPM = receivedBlock->max_RPM; sBerryBlenderData->gameFrameTime = receivedBlock->time; } } break; case 5: if (Blender_PrintBlendingRanking()) sBerryBlenderData->gameEndState++; break; case 6: if (Blender_PrintBlendingResults()) { if (gInGameOpponentsNo == 0) IncrementGameStat(GAME_STAT_POKEBLOCKS_WITH_FRIENDS); else IncrementGameStat(GAME_STAT_POKEBLOCKS); sBerryBlenderData->gameEndState++; } break; case 7: if (Blender_PrintText(&sBerryBlenderData->textState, sText_WouldLikeToBlendAnotherBerry, GetPlayerTextSpeed())) sBerryBlenderData->gameEndState++; break; case 9: sBerryBlenderData->yesNoAnswer = 0; CreateYesNoMenu(&sBlender_YesNoWindowTemplate, 1, 0xD, 0); sBerryBlenderData->gameEndState++; break; case 10: switch (Menu_ProcessInputNoWrap_()) { case 1: case -1: sBerryBlenderData->yesNoAnswer = 1; sBerryBlenderData->gameEndState++; for (i = 0; i field_8E[i] != 0xFF) { PutWindowTilemap(i); CopyWindowToVram(i, 3); } } break; case 0: sBerryBlenderData->yesNoAnswer = 0; sBerryBlenderData->gameEndState++; for (i = 0; i field_8E[i] != 0xFF) { PutWindowTilemap(i); CopyWindowToVram(i, 3); } } break; } break; case 11: sub_8081F94(&gSendCmd[0]); if (sBerryBlenderData->yesNoAnswer == 0) { if (IsBagPocketNonEmpty(POCKET_BERRIES) == FALSE) // no berries { sBerryBlenderData->playAgainState = CANT_PLAY_NO_BERRIES; gSendCmd[1] = 0x9999; } else if (GetFirstFreePokeblockSlot() == -1) // no space for pokeblocks { sBerryBlenderData->playAgainState = CANT_PLAY_NO_PKBLCK_SPACE; gSendCmd[1] = 0xAAAA; } else { sBerryBlenderData->playAgainState = PLAY_AGAIN_OK; gSendCmd[1] = 0x7779; } sBerryBlenderData->gameEndState++; } else { sBerryBlenderData->playAgainState = DONT_PLAY_AGAIN; gSendCmd[1] = 0x8888; sBerryBlenderData->gameEndState++; } break; case 12: if (gInGameOpponentsNo) { SetMainCallback2(CB2_HandlePlayerPlayAgainChoice); sBerryBlenderData->gameEndState = 0; sBerryBlenderData->mainState = 0; } else { sBerryBlenderData->gameEndState++; } break; case 8: sBerryBlenderData->gameEndState++; break; case 13: if (Blender_PrintText(&sBerryBlenderData->textState, sText_CommunicationStandby, GetPlayerTextSpeed())) { SetMainCallback2(CB2_HandlePlayerLinkPlayAgainChoice); sBerryBlenderData->gameEndState = 0; sBerryBlenderData->mainState = 0; } break; } sub_808330C(); sub_8083230(sBerryBlenderData->field_4C); sub_8082AD4(); Blender_DummiedOutFunc(sBerryBlenderData->bg_X, sBerryBlenderData->bg_Y); RunTasks(); AnimateSprites(); BuildOamBuffer(); RunTextPrinters(); UpdatePaletteFade(); } static bool8 LinkPlayAgainHandleSaving(void) { switch (sBerryBlenderData->field_1A0) { case 0: sub_800ADF8(); sBerryBlenderData->field_1A0 = 1; sBerryBlenderData->framesToWait = 0; break; case 1: if (sub_800A520()) { sBerryBlenderData->field_1A0++; gSoftResetDisabled = TRUE; } break; case 2: sub_8153430(); sBerryBlenderData->field_1A0++; sBerryBlenderData->framesToWait = 0; break; case 3: if (++sBerryBlenderData->framesToWait == 10) { sub_800ADF8(); sBerryBlenderData->field_1A0++; } break; case 4: if (sub_800A520()) { if (sub_8153474()) { sBerryBlenderData->field_1A0 = 5; } else { sBerryBlenderData->framesToWait = 0; sBerryBlenderData->field_1A0 = 3; } } break; case 5: sBerryBlenderData->field_1A0++; sBerryBlenderData->framesToWait = 0; break; case 6: if (++sBerryBlenderData->framesToWait > 5) { gSoftResetDisabled = FALSE; return TRUE; } break; } return FALSE; } static void CB2_HandlePlayerLinkPlayAgainChoice(void) { switch (sBerryBlenderData->gameEndState) { case 0: if (sBerryBlenderData->field_64[0] == 0x2222) { sBerryBlenderData->gameEndState = 5; } else if (sBerryBlenderData->field_64[0] == 0x1111) { if (sBerryBlenderData->field_6C == 0x9999) sBerryBlenderData->gameEndState = 2; else if (sBerryBlenderData->field_6C == 0xAAAA) sBerryBlenderData->gameEndState = 1; else sBerryBlenderData->gameEndState = 5; } break; case 1: sBerryBlenderData->gameEndState = 3; StringCopy(gStringVar4, gLinkPlayers[sBerryBlenderData->field_6E].name); StringAppend(gStringVar4, sText_ApostropheSPokeblockCaseIsFull); break; case 2: sBerryBlenderData->gameEndState++; StringCopy(gStringVar4, gLinkPlayers[sBerryBlenderData->field_6E].name); StringAppend(gStringVar4, sText_HasNoBerriesToPut); break; case 3: if (Blender_PrintText(&sBerryBlenderData->textState, gStringVar4, GetPlayerTextSpeed())) { sBerryBlenderData->framesToWait = 0; sBerryBlenderData->gameEndState++; } break; case 4: if (++sBerryBlenderData->framesToWait > 60) sBerryBlenderData->gameEndState = 5; break; case 5: Blender_PrintText(&sBerryBlenderData->textState, gText_SavingDontTurnOff2, 0); sub_800ADF8(); sBerryBlenderData->gameEndState++; break; case 6: if (sub_800A520()) { sBerryBlenderData->framesToWait = 0; sBerryBlenderData->gameEndState++; sBerryBlenderData->field_1A0 = 0; } break; case 7: if (LinkPlayAgainHandleSaving()) { PlaySE(SE_SAVE); sBerryBlenderData->gameEndState++; } break; case 8: sBerryBlenderData->gameEndState++; sub_800ADF8(); break; case 9: if (sub_800A520()) { BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, 0); sBerryBlenderData->gameEndState++; } break; case 10: if (!gPaletteFade.active) { if (sBerryBlenderData->field_64[0] == 0x2222) { FreeAllWindowBuffers(); UnsetBgTilemapBuffer(2); UnsetBgTilemapBuffer(1); FREE_AND_SET_NULL(sBerryBlenderData); SetMainCallback2(DoBerryBlending); } else { sBerryBlenderData->framesToWait = 0; sBerryBlenderData->gameEndState++; } } break; case 11: if (++sBerryBlenderData->framesToWait > 30) { sub_800AC34(); sBerryBlenderData->gameEndState++; } break; case 12: if (gReceivedRemoteLinkPlayers == 0) { FREE_AND_SET_NULL(sBerryBlenderData); SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); } break; } sub_8082AD4(); Blender_DummiedOutFunc(sBerryBlenderData->bg_X, sBerryBlenderData->bg_Y); RunTasks(); AnimateSprites(); BuildOamBuffer(); RunTextPrinters(); UpdatePaletteFade(); } static void CB2_HandlePlayerPlayAgainChoice(void) { switch (sBerryBlenderData->gameEndState) { case 0: if (sBerryBlenderData->playAgainState == PLAY_AGAIN_OK || sBerryBlenderData->playAgainState == DONT_PLAY_AGAIN) sBerryBlenderData->gameEndState = 9; if (sBerryBlenderData->playAgainState == CANT_PLAY_NO_BERRIES) sBerryBlenderData->gameEndState = 2; if (sBerryBlenderData->playAgainState == CANT_PLAY_NO_PKBLCK_SPACE) sBerryBlenderData->gameEndState = 1; break; case 1: sBerryBlenderData->gameEndState = 3; sBerryBlenderData->textState = 0; StringCopy(gStringVar4, sText_YourPokeblockCaseIsFull); break; case 2: sBerryBlenderData->gameEndState++; sBerryBlenderData->textState = 0; StringCopy(gStringVar4, sText_RunOutOfBerriesForBlending); break; case 3: if (Blender_PrintText(&sBerryBlenderData->textState, gStringVar4, GetPlayerTextSpeed())) sBerryBlenderData->gameEndState = 9; break; case 9: BeginFastPaletteFade(3); sBerryBlenderData->gameEndState++; break; case 10: if (!gPaletteFade.active) { if (sBerryBlenderData->playAgainState == PLAY_AGAIN_OK) SetMainCallback2(DoBerryBlending); else SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); FreeAllWindowBuffers(); UnsetBgTilemapBuffer(2); UnsetBgTilemapBuffer(1); FREE_AND_SET_NULL(sBerryBlenderData); } break; } sub_8082AD4(); Blender_DummiedOutFunc(sBerryBlenderData->bg_X, sBerryBlenderData->bg_Y); RunTasks(); AnimateSprites(); BuildOamBuffer(); RunTextPrinters(); UpdatePaletteFade(); } static void sub_8082AD4(void) { if (gReceivedRemoteLinkPlayers) { if (sub_80814B0(gRecvCmds[0][0], 0x2FFF, 0x2F00)) { if (gRecvCmds[0][1] == 0x1111) { switch (gRecvCmds[0][2]) { case 0x8888: sBerryBlenderData->field_6C = 0x8888; sBerryBlenderData->field_6E = gRecvCmds[0][3]; break; case 0x9999: sBerryBlenderData->field_6C = 0x9999; sBerryBlenderData->field_6E = gRecvCmds[0][3]; break; case 0xAAAA: sBerryBlenderData->field_6C = 0xAAAA; sBerryBlenderData->field_6E = gRecvCmds[0][3]; break; } sBerryBlenderData->field_64[0] = 0x1111; } else if (gRecvCmds[0][1] == 0x2222) { sBerryBlenderData->field_64[0] = 0x2222; } } if (GetMultiplayerId() == 0 && sBerryBlenderData->field_64[0] != 0x1111 && sBerryBlenderData->field_64[0] != 0x2222) { u8 i; for (i = 0; i < GetLinkPlayerCount(); i++) { if (sub_80814B0(gRecvCmds[i][0], 0x2FFF, 0x2F00)) { switch (gRecvCmds[i][1]) { case 0x8888: sBerryBlenderData->field_64[i] = 0x8888; break; case 0x7779: sBerryBlenderData->field_64[i] = 0x7779; break; case 0x9999: sBerryBlenderData->field_64[i] = 0x9999; break; case 0xAAAA: sBerryBlenderData->field_64[i] = 0xAAAA; break; } } } for (i = 0; i < GetLinkPlayerCount(); i++) { if (sBerryBlenderData->field_64[i] == 0) break; } if (i == GetLinkPlayerCount()) { for (i = 0; i < GetLinkPlayerCount(); i++) { if (sBerryBlenderData->field_64[i] != 0x7779) break; } sub_8081F94(&gSendCmd[0]); if (i == GetLinkPlayerCount()) { gSendCmd[1] = 0x2222; } else { gSendCmd[1] = 0x1111; gSendCmd[2] = sBerryBlenderData->field_64[i]; gSendCmd[3] = i; } } } } } static void sub_8082CB4(struct BgAffineSrcData *dest) { struct BgAffineSrcData affineSrc; affineSrc.texX = 0x7800; affineSrc.texY = 0x5000; affineSrc.scrX = 0x78 - sBerryBlenderData->bg_X; affineSrc.scrY = 0x50 - sBerryBlenderData->bg_Y; affineSrc.sx = sBerryBlenderData->field_11A; affineSrc.sy = sBerryBlenderData->field_11A; affineSrc.alpha = sBerryBlenderData->arrowPos; *dest = affineSrc; } u16 GetBlenderArrowPosition(void) { return sBerryBlenderData->arrowPos; } static void sub_8082D28(void) { u8 playerId = 0; if (gReceivedRemoteLinkPlayers != 0) playerId = GetMultiplayerId(); if (gWirelessCommType && gReceivedRemoteLinkPlayers != 0) { if (playerId == 0) { sBerryBlenderData->arrowPos += sBerryBlenderData->field_4C; gSendCmd[5] = sBerryBlenderData->field_116; gSendCmd[6] = sBerryBlenderData->arrowPos; sub_8082CB4(&sBerryBlenderData->bgAffineSrc); } else { if ((gRecvCmds[0][0] & 0xFF00) == 0x4400) { sBerryBlenderData->field_116 = gRecvCmds[0][5]; sBerryBlenderData->arrowPos = gRecvCmds[0][6]; sub_8082CB4(&sBerryBlenderData->bgAffineSrc); } } } else { sBerryBlenderData->arrowPos += sBerryBlenderData->field_4C; sub_8082CB4(&sBerryBlenderData->bgAffineSrc); } } static void BerryBlender_SetBackgroundsPos(void) { SetGpuReg(REG_OFFSET_BG1HOFS, sBerryBlenderData->bg_X); SetGpuReg(REG_OFFSET_BG1VOFS, sBerryBlenderData->bg_Y); SetGpuReg(REG_OFFSET_BG0HOFS, sBerryBlenderData->bg_X); SetGpuReg(REG_OFFSET_BG0VOFS, sBerryBlenderData->bg_Y); } static void sub_8082E3C(struct Sprite* sprite) { sprite->data[2] += sprite->data[0]; sprite->data[3] += sprite->data[1]; sprite->pos2.x = sprite->data[2] / 8; sprite->pos2.y = sprite->data[3] / 8; if (sprite->animEnded) DestroySprite(sprite); } static void sub_8082E84(void) { s32 limit = (Random() % 2) + 1; s32 i; for (i = 0; i < limit; i++) { u16 rand; s32 x, y; u8 spriteId; rand = sBerryBlenderData->arrowPos + (Random() % 20); x = gSineTable[(rand & 0xFF) + 64] / 4; y = gSineTable[(rand & 0xFF)] / 4; spriteId = CreateSprite(&sUnknown_08339BE0, x + 120, y + 80, 1); gSprites[spriteId].data[0] = 16 - (Random() % 32); gSprites[spriteId].data[1] = 16 - (Random() % 32); gSprites[spriteId].callback = sub_8082E3C; } } static void sub_8082F68(struct Sprite* sprite) { sprite->data[0]++; sprite->pos2.y = -(sprite->data[0] / 3); if (sprite->animEnded) DestroySprite(sprite); } static void sub_8082F9C(struct Sprite* sprite) { sprite->data[0]++; sprite->pos2.y = -(sprite->data[0] * 2); if (sprite->pos2.y < -12) sprite->pos2.y = -12; if (sprite->animEnded) DestroySprite(sprite); } static void Blender_SetParticipantBerryData(u8 participantId, u16 itemId) { sBerryBlenderData->chosenItemId[participantId] = itemId; Blender_CopyBerryData(&sBerryBlenderData->blendedBerries[participantId], itemId); } static void sub_8083010(struct Sprite* sprite) { switch (sprite->data[0]) { case 0: sprite->data[1] += 8; if (sprite->data[1] > 88) { sprite->data[1] = 88; sprite->data[0]++; PlaySE(SE_KON); } break; case 1: sprite->data[2] += 1; if (sprite->data[2] > 20) { sprite->data[0]++; sprite->data[2] = 0; } break; case 2: sprite->data[1] += 4; if (sprite->data[1] > 176) { if (++sprite->data[3] == 3) { DestroySprite(sprite); CreateSprite(&sUnknown_08339C60, 120, -20, 2); } else { sprite->data[0] = 0; sprite->data[1] = -16; StartSpriteAnim(sprite, sprite->data[3]); } } break; } sprite->pos2.y = sprite->data[1]; } static void sub_80830C0(struct Sprite* sprite) { switch (sprite->data[0]) { case 0: sprite->data[1] += 8; if (sprite->data[1] > 92) { sprite->data[1] = 92; sprite->data[0]++; PlaySE(SE_PIN); } break; case 1: sprite->data[2] += 1; if (sprite->data[2] > 20) sprite->data[0]++; break; case 2: sprite->data[1] += 4; if (sprite->data[1] > 176) { sBerryBlenderData->mainState++; DestroySprite(sprite); } break; } sprite->pos2.y = sprite->data[1]; } static void sub_8083140(u16 a0, u16 a1) { if (sBerryBlenderData->field_118 < a0) { sBerryBlenderData->field_118 += 2; sub_8083170(sBerryBlenderData->field_118, a1); } } static void sub_8083170(u16 a0, u16 a1) { s32 var1, var2, var3, var4; u16 *vram; vram = (u16*)(VRAM + 0x6000); var1 = (a0 * 64) / a1; var2 = var1 / 8; for (var4 = 0; var4 < var2; var4++) { vram[11 + var4] = 0x80E9; vram[43 + var4] = 0x80F9; } var3 = var1 % 8; if (var3 != 0) { vram[11 + var4] = var3 + 0x80E1; vram[43 + var4] = var3 + 0x80F1; var4++; } for (; var4 < 8; var4++) { vram[11 + var4] = 0x80E1; vram[43 + var4] = 0x80F1; } } static u32 sub_8083210(u16 a0) { return 0x57E40 * a0 / 0x10000; } static void sub_8083230(u16 a0) { u8 i; u8 palAdders[5]; u32 var = sub_8083210(a0); if (sBerryBlenderData->max_RPM < var) sBerryBlenderData->max_RPM = var; for (i = 0; i < 5; i++) { palAdders[i] = var % 10; var /= 10; } *((u16*)(VRAM + 0x6458)) = palAdders[4] + 0x8072; *((u16*)(VRAM + 0x645A)) = palAdders[3] + 0x8072; *((u16*)(VRAM + 0x645C)) = palAdders[2] + 0x8072; *((u16*)(VRAM + 0x6460)) = palAdders[1] + 0x8072; *((u16*)(VRAM + 0x6462)) = palAdders[0] + 0x8072; } static void sub_80832BC(s16* a0, u16 a1) { if (*a0 == 0) *a0 = (Random() % a1) - (a1 / 2); } static void sub_80832E8(s16* a0) { if (*a0 < 0) (*a0)++; if (*a0 > 0) (*a0)--; } static void sub_808330C(void) { sub_80832E8(&sBerryBlenderData->bg_X); sub_80832E8(&sBerryBlenderData->bg_Y); } static void sub_8083334(s16* a0, u16 a1) { s32 var; if (a1 < 10) var = 16; else var = 8; if (*a0 == 0) { *a0 = (Random() % var) - (var / 2); } else { if (*a0 < 0) (*a0)++; if (*a0 > 0) (*a0)--; } } static bool8 sub_8083380(void) { if (sBerryBlenderData->framesToWait == 0) { sBerryBlenderData->bg_X = 0; sBerryBlenderData->bg_Y = 0; } sBerryBlenderData->framesToWait++; sub_8083334(&sBerryBlenderData->bg_X, sBerryBlenderData->framesToWait); sub_8083334(&sBerryBlenderData->bg_Y, sBerryBlenderData->framesToWait); if (sBerryBlenderData->framesToWait == 20) { sBerryBlenderData->bg_X = 0; sBerryBlenderData->bg_Y = 0; return TRUE; } return FALSE; } static void sub_80833F8(struct Sprite* sprite) { sprite->pos2.x = -(sBerryBlenderData->bg_X); sprite->pos2.y = -(sBerryBlenderData->bg_Y); } static void TryUpdateBerryBlenderRecord(void) { if (gSaveBlock1Ptr->berryBlenderRecords[sBerryBlenderData->playersNo - 2] < sBerryBlenderData->max_RPM) gSaveBlock1Ptr->berryBlenderRecords[sBerryBlenderData->playersNo - 2] = sBerryBlenderData->max_RPM; } static bool8 Blender_PrintBlendingResults(void) { u16 i; s32 xPos, yPos; struct Pokeblock pokeblock; u8 flavors[6]; u8 text[40]; u16 berryIds[4]; // unused switch (sBerryBlenderData->mainState) { case 0: sBerryBlenderData->mainState++; sBerryBlenderData->framesToWait = 17; break; case 1: sBerryBlenderData->framesToWait -= 10; if (sBerryBlenderData->framesToWait < 0) { sBerryBlenderData->framesToWait = 0; sBerryBlenderData->mainState++; } break; case 2: if (++sBerryBlenderData->framesToWait > 20) { for (i = 0; i < BLENDER_SCORES_NO; i++) DestroySprite(&gSprites[sBerryBlenderData->scoreIconIds[i]]); sBerryBlenderData->framesToWait = 0; sBerryBlenderData->mainState++; } break; case 3: { u16 minutes, seconds; u8 *txtPtr; xPos = GetStringCenterAlignXOffset(1, sText_BlendingResults, 0xA8); Blender_AddTextPrinter(5, sText_BlendingResults, xPos, 1, TEXT_SPEED_FF, 0); if (sBerryBlenderData->playersNo == 4) yPos = 17; else yPos = 21; for (i = 0; i < sBerryBlenderData->playersNo; yPos += 16, i++) { u8 place = sBerryBlenderData->playerPlaces[i]; ConvertIntToDecimalStringN(sBerryBlenderData->stringVar, i + 1, STR_CONV_MODE_LEFT_ALIGN, 1); StringAppend(sBerryBlenderData->stringVar, sText_Dot); StringAppend(sBerryBlenderData->stringVar, gText_Space); StringAppend(sBerryBlenderData->stringVar, gLinkPlayers[place].name); Blender_AddTextPrinter(5, sBerryBlenderData->stringVar, 8, yPos, TEXT_SPEED_FF, 3); StringCopy(sBerryBlenderData->stringVar, sBerryBlenderData->blendedBerries[place].name); ConvertInternationalString(sBerryBlenderData->stringVar, gLinkPlayers[place].language); StringAppend(sBerryBlenderData->stringVar, sText_SpaceBerry); Blender_AddTextPrinter(5, sBerryBlenderData->stringVar, 0x54, yPos, TEXT_SPEED_FF, 3); } Blender_AddTextPrinter(5, sText_MaximumSpeed, 0, 0x51, TEXT_SPEED_FF, 3); ConvertIntToDecimalStringN(sBerryBlenderData->stringVar, sBerryBlenderData->max_RPM / 100, STR_CONV_MODE_RIGHT_ALIGN, 3); StringAppend(sBerryBlenderData->stringVar, sText_Dot); ConvertIntToDecimalStringN(text, sBerryBlenderData->max_RPM % 100, STR_CONV_MODE_LEADING_ZEROS, 2); StringAppend(sBerryBlenderData->stringVar, text); StringAppend(sBerryBlenderData->stringVar, sText_RPM); xPos = GetStringRightAlignXOffset(1, sBerryBlenderData->stringVar, 0xA8); Blender_AddTextPrinter(5, sBerryBlenderData->stringVar, xPos, 0x51, TEXT_SPEED_FF, 3); Blender_AddTextPrinter(5, sText_Time, 0, 0x61, TEXT_SPEED_FF, 3); seconds = (sBerryBlenderData->gameFrameTime / 60) % 60; minutes = (sBerryBlenderData->gameFrameTime / (60 * 60)); ConvertIntToDecimalStringN(sBerryBlenderData->stringVar, minutes, STR_CONV_MODE_LEADING_ZEROS, 2); txtPtr = StringAppend(sBerryBlenderData->stringVar, sText_Min); ConvertIntToDecimalStringN(txtPtr, seconds, STR_CONV_MODE_LEADING_ZEROS, 2); StringAppend(sBerryBlenderData->stringVar, sText_Sec); xPos = GetStringRightAlignXOffset(1, sBerryBlenderData->stringVar, 0xA8); Blender_AddTextPrinter(5, sBerryBlenderData->stringVar, xPos, 0x61, TEXT_SPEED_FF, 3); sBerryBlenderData->framesToWait = 0; sBerryBlenderData->mainState++; CopyWindowToVram(5, 2); } break; case 4: if (gMain.newKeys & A_BUTTON) sBerryBlenderData->mainState++; break; case 5: sub_8198070(5, 1); for (i = 0; i < BLENDER_MAX_PLAYERS; i++) { if (sBerryBlenderData->chosenItemId[i] != 0) berryIds[i] = sBerryBlenderData->chosenItemId[i] - FIRST_BERRY_INDEX; if (sBerryBlenderData->field_8E[i] != 0xFF) { PutWindowTilemap(i); CopyWindowToVram(i, 3); } } sub_8081E20(); Blender_CalculatePokeblock(sBerryBlenderData->blendedBerries, &pokeblock, sBerryBlenderData->playersNo, flavors, sBerryBlenderData->max_RPM); Blender_PrintMadePokeblockString(&pokeblock, sBerryBlenderData->stringVar); TryAddContestLinkTvShow(&pokeblock, &sBerryBlenderData->tvBlender); CreateTask(sub_8083F3C, 6); sub_80EECEC(); RemoveBagItem(gSpecialVar_ItemId, 1); AddPokeblock(&pokeblock); sBerryBlenderData->textState = 0; sBerryBlenderData->mainState++; break; case 6: if (Blender_PrintText(&sBerryBlenderData->textState, sBerryBlenderData->stringVar, GetPlayerTextSpeed())) { TryUpdateBerryBlenderRecord(); return TRUE; } break; } return FALSE; } static void Blender_PrintMadePokeblockString(struct Pokeblock *pokeblock, u8 *dst) { u8 text[12]; u8 flavorLvl, feel; dst[0] = EOS; StringCopy(dst, gPokeblockNames[pokeblock->color]); StringAppend(dst, sText_WasMade); StringAppend(dst, sText_NewLine); flavorLvl = GetHighestPokeblocksFlavorLevel(pokeblock); feel = GetPokeblocksFeel(pokeblock); StringAppend(dst, sText_TheLevelIs); ConvertIntToDecimalStringN(text, flavorLvl, STR_CONV_MODE_LEFT_ALIGN, 3); StringAppend(dst, text); StringAppend(dst, sText_TheFeelIs); ConvertIntToDecimalStringN(text, feel, STR_CONV_MODE_LEFT_ALIGN, 3); StringAppend(dst, text); StringAppend(dst, sText_Dot2); StringAppend(dst, sText_NewParagraph); } static void Blender_SortBasedOnPoints(u8 *places, u8 playersNum, u32 *scores) { s32 i, j; for (i = 0; i < playersNum; i++) { for (j = 0; j < playersNum; j++) { if (scores[places[i]] > scores[places[j]]) { u8 temp = places[i]; places[i] = places[j]; places[j] = temp; } } } } static void Blender_SortScores(void) { u8 playerId; u8 i; u8 places[BLENDER_MAX_PLAYERS]; u32 points[BLENDER_MAX_PLAYERS]; for (i = 0; i < sBerryBlenderData->playersNo; i++) places[i] = i; for (i = 0; i < sBerryBlenderData->playersNo; i++) { points[i] = 1000000 * sBerryBlenderData->scores[i][BLENDER_SCORE_BEST]; points[i] += 1000 * sBerryBlenderData->scores[i][BLENDER_SCORE_GOOD]; points[i] += 1000 - sBerryBlenderData->scores[i][BLENDER_SCORE_MISS]; } Blender_SortBasedOnPoints(places, sBerryBlenderData->playersNo, points); for (i = 0; i < sBerryBlenderData->playersNo; i++) sBerryBlenderData->playerPlaces[i] = places[i]; if (gReceivedRemoteLinkPlayers == 0) playerId = 0; else playerId = GetMultiplayerId(); for (i = 0; i < sBerryBlenderData->playersNo; i++) { if (sBerryBlenderData->playerPlaces[i] == playerId) sBerryBlenderData->field_1A4 = i; } } static bool8 Blender_PrintBlendingRanking(void) { u16 i; s32 xPos, yPos; switch (sBerryBlenderData->mainState) { case 0: sBerryBlenderData->mainState++; sBerryBlenderData->framesToWait = 255; break; case 1: sBerryBlenderData->framesToWait -= 10; if (sBerryBlenderData->framesToWait < 0) { sBerryBlenderData->framesToWait = 0; sBerryBlenderData->mainState++; } break; case 2: if (++sBerryBlenderData->framesToWait > 20) { sBerryBlenderData->framesToWait = 0; sBerryBlenderData->mainState++; } break; case 3: SetWindowBorderStyle(5, 0, 1, 0xD); xPos = GetStringCenterAlignXOffset(1, sText_Ranking, 0xA8); Blender_AddTextPrinter(5, sText_Ranking, xPos, 1, TEXT_SPEED_FF, 0); sBerryBlenderData->scoreIconIds[BLENDER_SCORE_BEST] = CreateSprite(&sUnknown_08339B40, 128, 52, 0); StartSpriteAnim(&gSprites[sBerryBlenderData->scoreIconIds[BLENDER_SCORE_BEST]], 3); gSprites[sBerryBlenderData->scoreIconIds[BLENDER_SCORE_BEST]].callback = SpriteCallbackDummy; sBerryBlenderData->scoreIconIds[BLENDER_SCORE_GOOD] = CreateSprite(&sUnknown_08339B40, 160, 52, 0); gSprites[sBerryBlenderData->scoreIconIds[BLENDER_SCORE_GOOD]].callback = SpriteCallbackDummy; sBerryBlenderData->scoreIconIds[BLENDER_SCORE_MISS] = CreateSprite(&sUnknown_08339B40, 192, 52, 0); StartSpriteAnim(&gSprites[sBerryBlenderData->scoreIconIds[BLENDER_SCORE_MISS]], 1); gSprites[sBerryBlenderData->scoreIconIds[BLENDER_SCORE_MISS]].callback = SpriteCallbackDummy; Blender_SortScores(); for (yPos = 0x29, i = 0; i < sBerryBlenderData->playersNo; yPos += 0x10, i++) { u8 place = sBerryBlenderData->playerPlaces[i]; ConvertIntToDecimalStringN(sBerryBlenderData->stringVar, i + 1, STR_CONV_MODE_LEFT_ALIGN, 1); StringAppend(sBerryBlenderData->stringVar, sText_Dot); StringAppend(sBerryBlenderData->stringVar, gText_Space); StringAppend(sBerryBlenderData->stringVar, gLinkPlayers[place].name); Blender_AddTextPrinter(5, sBerryBlenderData->stringVar, 0, yPos, TEXT_SPEED_FF, 3); ConvertIntToDecimalStringN(sBerryBlenderData->stringVar, sBerryBlenderData->scores[place][BLENDER_SCORE_BEST], STR_CONV_MODE_RIGHT_ALIGN, 3); Blender_AddTextPrinter(5, sBerryBlenderData->stringVar, 0x4E, yPos, TEXT_SPEED_FF, 3); ConvertIntToDecimalStringN(sBerryBlenderData->stringVar, sBerryBlenderData->scores[place][BLENDER_SCORE_GOOD], STR_CONV_MODE_RIGHT_ALIGN, 3); Blender_AddTextPrinter(5, sBerryBlenderData->stringVar, 0x6E, yPos, TEXT_SPEED_FF, 3); ConvertIntToDecimalStringN(sBerryBlenderData->stringVar, sBerryBlenderData->scores[place][BLENDER_SCORE_MISS], STR_CONV_MODE_RIGHT_ALIGN, 3); Blender_AddTextPrinter(5, sBerryBlenderData->stringVar, 0x8E, yPos, TEXT_SPEED_FF, 3); } PutWindowTilemap(5); CopyWindowToVram(5, 3); sBerryBlenderData->framesToWait = 0; sBerryBlenderData->mainState++; break; case 4: if (++sBerryBlenderData->framesToWait > 20) sBerryBlenderData->mainState++; break; case 5: if (gMain.newKeys & A_BUTTON) { PlaySE(SE_SELECT); sBerryBlenderData->mainState++; } break; case 6: sBerryBlenderData->mainState = 0; return TRUE; } return FALSE; } void ShowBerryBlenderRecordWindow(void) { s32 i; s32 xPos, yPos; struct WindowTemplate winTemplate; u8 text[32]; winTemplate = sBlenderRecordWindowTemplate; gRecordsWindowId = AddWindow(&winTemplate); NewMenuHelpers_DrawStdWindowFrame(gRecordsWindowId, 0); FillWindowPixelBuffer(gRecordsWindowId, 0x11); xPos = GetStringCenterAlignXOffset(1, gText_BlenderMaxSpeedRecord, 0x90); AddTextPrinterParameterized(gRecordsWindowId, 1, gText_BlenderMaxSpeedRecord, xPos, 1, 0, NULL); AddTextPrinterParameterized(gRecordsWindowId, 1, gText_234Players, 4, 0x29, 0, NULL); for (i = 0, yPos = 0x29; i < BLENDER_SCORES_NO; i++) { u8 *txtPtr; u32 record; record = gSaveBlock1Ptr->berryBlenderRecords[i]; txtPtr = ConvertIntToDecimalStringN(text, record / 100, STR_CONV_MODE_RIGHT_ALIGN, 3); txtPtr = StringAppend(txtPtr, sText_Dot); txtPtr = ConvertIntToDecimalStringN(txtPtr, record % 100, STR_CONV_MODE_LEADING_ZEROS, 2); txtPtr = StringAppend(txtPtr, sText_RPM); xPos = GetStringRightAlignXOffset(1, text, 0x8C); AddTextPrinterParameterized(gRecordsWindowId, 1, text, xPos, yPos + (i * 16), 0, NULL); } PutWindowTilemap(gRecordsWindowId); CopyWindowToVram(gRecordsWindowId, 3); } static void sub_8083F3C(u8 taskId) { if (gTasks[taskId].data[0] == 0) { PlayFanfare(MUS_FANFA1); gTasks[taskId].data[0]++; } if (IsFanfareTaskInactive()) { PlayBGM(sBerryBlenderData->field_154); DestroyTask(taskId); } } static bool32 TryAddContestLinkTvShow(struct Pokeblock *pokeblock, struct TvBlenderStruct *tvBlender) { u8 flavorLevel = GetHighestPokeblocksFlavorLevel(pokeblock); u16 sheen = (flavorLevel * 10) / GetPokeblocksFeel(pokeblock); tvBlender->pokeblockSheen = sheen; tvBlender->pokeblockColor = pokeblock->color; tvBlender->name[0] = EOS; if (gReceivedRemoteLinkPlayers != 0) { if (sBerryBlenderData->field_1A4 == 0 && sheen > 20) { StringCopy(tvBlender->name, gLinkPlayers[sBerryBlenderData->playerPlaces[sBerryBlenderData->playersNo - 1]].name); tvBlender->pokeblockFlavor = GetPokeblocksFlavor(pokeblock); if (Put3CheersForPokeblocksOnTheAir(tvBlender->name, tvBlender->pokeblockFlavor, tvBlender->pokeblockColor, tvBlender->pokeblockSheen, gLinkPlayers[sBerryBlenderData->playerPlaces[sBerryBlenderData->playersNo - 1]].language)) { return TRUE; } return FALSE; } else if (sBerryBlenderData->field_1A4 == sBerryBlenderData->playersNo - 1 && sheen <= 20) { StringCopy(tvBlender->name, gLinkPlayers[sBerryBlenderData->playerPlaces[0]].name); tvBlender->pokeblockFlavor = GetPokeblocksFlavor(pokeblock); if (Put3CheersForPokeblocksOnTheAir(tvBlender->name, tvBlender->pokeblockFlavor, tvBlender->pokeblockColor, tvBlender->pokeblockSheen, gLinkPlayers[sBerryBlenderData->playerPlaces[0]].language)) { return TRUE; } return FALSE; } } return FALSE; } static void Blender_AddTextPrinter(u8 windowId, const u8 *string, u8 x, u8 y, s32 speed, s32 caseId) { u8 txtColor[3]; u32 letterSpacing = 0; switch (caseId) { case 0: case 3: txtColor[0] = 1; txtColor[1] = 2; txtColor[2] = 3; break; case 1: txtColor[0] = 0; txtColor[1] = 2; txtColor[2] = 3; break; case 2: txtColor[0] = 0; txtColor[1] = 4; txtColor[2] = 5; break; } if (caseId != 3) { FillWindowPixelBuffer(windowId, txtColor[0] | (txtColor[0] << 4)); } AddTextPrinterParameterized4(windowId, 1, x, y, letterSpacing, 1, txtColor, speed, string); } static bool32 Blender_PrintText(s16 *textState, const u8 *string, s32 textSpeed) { switch (*textState) { case 0: sub_8197B1C(4, FALSE, 0x14, 0xF); Blender_AddTextPrinter(4, string, 0, 1, textSpeed, 0); PutWindowTilemap(4); CopyWindowToVram(4, 3); (*textState)++; break; case 1: if (!IsTextPrinterActive(4)) { *textState = 0; return TRUE; } break; } return FALSE; }