File merge/slice/naming (#212)
Some checks failed
CI / build (push) Has been cancelled

* kickback naming, catch state enum

* sound renaming through 98

* initial block

* pre split comments

* launcher clarity, board designations

* split out save_and_restore file

* board indicator file split, board setup named

* rename debug, split off center_capture_hole

* checkpoint

* pointer carving
This commit is contained in:
Retnuhytnuob 2026-03-21 17:38:10 -05:00 committed by GitHub
parent 77c628e0ee
commit e78163d87a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
67 changed files with 14311 additions and 12233 deletions

File diff suppressed because it is too large Load Diff

View File

@ -4206,7 +4206,7 @@ gHatchPieceMatrixNums:: @ 0x086AE318
gOneUpSpritePalette:: @ 0x086AE324
.incbin "baserom.gba", 0x6AE324, 0x20
gSapphirePondAnimFramesets:: @ 0x086AE344
gSpoinkAnimFrameset:: @ 0x086AE344
.incbin "baserom.gba", 0x6AE344, 0x50
gTravelEventAnimData:: @ 0x086AE394
@ -4535,112 +4535,436 @@ gRubySlingshotAnimIndices:: @ 0x086B08CA
.incbin "baserom.gba", 0x6B08CA, 0xA
gRubySlingshotTilePointers:: @ 0x086B08D4
.incbin "baserom.gba", 0x6B08D4, 0x78
@ Arranged into 2(sides) sets of 3 sets of 5.
@ Third set of 5 is the destination address.
.4byte gUnknown_082647F0, gUnknown_08264BF0, gUnknown_08264FF0, gUnknown_082653F0, gUnknown_08265810
.4byte gUnknown_08264850, gUnknown_08264C50, gUnknown_08265050, gUnknown_08265450, gUnknown_08265870
.4byte 0x0600DA00, 0x0600DA20, 0x0600DA60, 0x0600DAC0, 0x0600DB20
.4byte gUnknown_082648F0, gUnknown_08264CD0, gUnknown_082650B0, gUnknown_082654B0, gUnknown_082658B0
.4byte gUnknown_08264950, gUnknown_08264D30, gUnknown_08265110, gUnknown_08265510, gUnknown_08265910
.4byte 0x0600DB60, 0x0600DB80, 0x0600DBC0, 0x0600DC20, 0x0600DC80
gShopItemTilePointers:: @ 0x086B094C
.incbin "baserom.gba", 0x6B094C, 0x24
@ Arranged into 3 sets of 3.
@ Third set is the destination address.
.4byte gUnknown_08262BB0, gUnknown_08262FB0, gUnknown_08263430
.4byte gUnknown_08262C70, gUnknown_08263070, gUnknown_082634F0
.4byte 0x0600D860, 0x0600D920, 0x0600D9E0
gRubyProgressDigitTilePointers:: @ 0x086B0970
.incbin "baserom.gba", 0x6B0970, 0x58
@ 11 sets of 2.
@ Eleventh has the destination address.
.4byte gUnknown_08262790, gUnknown_082628D0
.4byte gUnknown_082627B0, gUnknown_082628F0
.4byte gUnknown_082627D0, gUnknown_08262910
.4byte gUnknown_082627F0, gUnknown_08262930
.4byte gUnknown_08262810, gUnknown_08262950
.4byte gUnknown_08262830, gUnknown_08262970
.4byte gUnknown_08262850, gUnknown_08262990
.4byte gUnknown_08262870, gUnknown_082629B0
.4byte gUnknown_08262890, gUnknown_082629D0
.4byte gUnknown_082628B0, gUnknown_082629F0
.4byte 0x0600D820, 0x0600D840
gRubyTrapIndicatorTilePointers:: @ 0x086B09C8
.incbin "baserom.gba", 0x6B09C8, 0x20
@ 4 sets of 2
@ fourth set has destination address
.4byte gUnknown_0825FF30, gUnknown_08260330
.4byte gUnknown_0825FF70, gUnknown_08260370
.4byte gUnknown_0825FFB0, gUnknown_082603B0
.4byte 0x060081C0, 0x060085C0
gRubyCatchLightTilePointers:: @ 0x086B09E8
.incbin "baserom.gba", 0x6B09E8, 0xA8
@ 3 sets of 7 sets of 2
@ seventh set has destination address
.4byte gUnknown_0825FAB0, gUnknown_0825FEB0
.4byte gUnknown_0825FAF0, gUnknown_0825FEF0
.4byte gUnknown_0825FFF0, gUnknown_082603F0
.4byte gUnknown_08260030, gUnknown_08260430
.4byte gUnknown_08260170, gUnknown_08260570
.4byte gUnknown_082601B0, gUnknown_082605B0
.4byte 0x0600A180, 0x0600A580
.4byte gUnknown_0825FAB0, gUnknown_0825FEB0
.4byte gUnknown_0825FAF0, gUnknown_0825FEF0
.4byte gUnknown_08260070, gUnknown_08260470
.4byte gUnknown_082600B0, gUnknown_082604B0
.4byte gUnknown_082601F0, gUnknown_082605F0
.4byte gUnknown_08260230, gUnknown_08260630
.4byte 0x0600A1C0, 0x0600A5C0
.4byte gUnknown_0825FAB0, gUnknown_0825FEB0
.4byte gUnknown_0825FAF0, gUnknown_0825FEF0
.4byte gUnknown_082600F0, gUnknown_082604F0
.4byte gUnknown_08260130, gUnknown_08260530
.4byte gUnknown_08260270, gUnknown_08260670
.4byte gUnknown_082602B0, gUnknown_082606B0
.4byte 0x0600A200, 0x0600A600
gRubyModeTimerTilePointers:: @ 0x086B0A90
.incbin "baserom.gba", 0x6B0A90, 0x30
@ 3 sets of 4
@ third set has destination address
.4byte gUnknown_08260770, gUnknown_08260B70, gUnknown_08260F90, gUnknown_082613F0
.4byte gUnknown_08260870, gUnknown_08260C70, gUnknown_08261090, gUnknown_082614F0
.4byte 0x0600AD80, 0x0600B180, 0x0600B5A0, 0x0600BA00
gRubyCatchArrowTilePointers:: @ 0x086B0AC0
.incbin "baserom.gba", 0x6B0AC0, 0x30
@ 3 sets of 4
@ third set has destination address
.4byte gUnknown_08261770, gUnknown_08261B70, gUnknown_08261F70, gUnknown_08262370
.4byte gUnknown_082617F0, gUnknown_08261BF0, gUnknown_08261FF0, gUnknown_082623F0
.4byte 0x0600B960, 0x0600BD60, 0x0600C160, 0x0600C560
gRubyEvoArrowTilePointers:: @ 0x086B0AF0
.incbin "baserom.gba", 0x6B0AF0, 0x30
@ 3 sets of 4
@ third set has destination address
.4byte gUnknown_082619B0, gUnknown_08261D70, gUnknown_08262170, gUnknown_08262570
.4byte gUnknown_08261A30, gUnknown_08261DF0, gUnknown_082621F0, gUnknown_082625F0
.4byte 0x0600B620, 0x0600B9E0, 0x0600BDE0, 0x0600C1E0
gRubyRouletteSlotTilePointers:: @ 0x086B0B20
.incbin "baserom.gba", 0x6B0B20, 0x50
@ 5 sets of 4
@ fifth set has the destination address
.4byte gUnknown_08263910, gUnknown_08263D10, gUnknown_08264110, gUnknown_08264510
.4byte gUnknown_082639B0, gUnknown_08263DB0, gUnknown_082641B0, gUnknown_082645B0
.4byte gUnknown_082637D0, gUnknown_08263BD0, gUnknown_08263FD0, gUnknown_082643D0
.4byte gUnknown_08263870, gUnknown_08263C70, gUnknown_08264070, gUnknown_08264470
.4byte 0x0600C620, 0x0600CA20, 0x0600CE20, 0x0600D220
gRubyBallPowerUpLightTilePointers:: @ 0x086B0B70
.incbin "baserom.gba", 0x6B0B70, 0x24
@ 3 sets of 3
@ third value has the destination address
.4byte gUnknown_0825F730, gUnknown_0825F770, 0x060085C0
.4byte gUnknown_0825F7B0, gUnknown_0825F7F0, 0x06008600
.4byte gUnknown_0825F830, gUnknown_0825F870, 0x06008660
gRubyCatchProgressArrowTilePointers:: @ 0x086B0B94
.incbin "baserom.gba", 0x6B0B94, 0x30
@ 3 sets of 4
@ third set has the destination address
.4byte gUnknown_082618B0, gUnknown_08261C70, gUnknown_08262070, gUnknown_08262470
.4byte gUnknown_08261930, gUnknown_08261CF0, gUnknown_082620F0, gUnknown_082624F0
.4byte 0x0600D2A0, 0x0600D660, 0x06008260, 0x06008660
gRubyHoleIndicatorTilePointers:: @ 0x086B0BC4
.incbin "baserom.gba", 0x6B0BC4, 0x40
@ 4 sets of 4
@ third value has the destination; fouth value blank.
.4byte gUnknown_0825F8B0, gUnknown_0825F8F0, 0x0600A460, 0
.4byte gUnknown_0825F930, gUnknown_0825F970, 0x0600A4C0, 0
.4byte gUnknown_0825F9B0, gUnknown_0825F9F0, 0x0600A6C0, 0
.4byte gUnknown_0825FA30, gUnknown_0825FA70, 0x0600A720, 0
gSapphireEvoArrowTilePtrs:: @ 0x086B0C04
.incbin "baserom.gba", 0x6B0C04, 0xB4
gRubyEvoArrowTilePtrs:: @ 0x086B0C04
@ 3 sets of 5 sets of 3
@ fifth set has the destination address
.4byte gUnknown_0825D310, gUnknown_0825D710, gUnknown_0825DB10
.4byte gUnknown_0825D310, gUnknown_0825D710, gUnknown_0825DB10
.4byte gUnknown_0825D370, gUnknown_0825D770, gUnknown_0825DB70
.4byte gUnknown_0825D3D0, gUnknown_0825D7D0, gUnknown_0825DBD0
.4byte 0x0600D080, 0x0600D480, 0x06008080
gSapphireCoinRewardTilePtrs:: @ 0x086B0CB8
.incbin "baserom.gba", 0x6B0CB8, 0xB4
.4byte gUnknown_0825D430, gUnknown_0825D830, gUnknown_0825DC30
.4byte gUnknown_0825D490, gUnknown_0825D890, gUnknown_0825DC90
.4byte gUnknown_0825D4F0, gUnknown_0825D8F0, gUnknown_0825DCF0
.4byte gUnknown_0825D550, gUnknown_0825D950, gUnknown_0825DD50
.4byte 0x060080A0, 0x060084A0, 0x060088A0
gSapphireCatchArrowTilePtrs:: @ 0x086B0D6C
.incbin "baserom.gba", 0x6B0D6C, 0xB4
.4byte gUnknown_0825D5B0, gUnknown_0825D9B0, gUnknown_0825DDB0
.4byte gUnknown_0825D5B0, gUnknown_0825D9B0, gUnknown_0825DDB0
.4byte gUnknown_0825D610, gUnknown_0825DA10, gUnknown_0825DE10
.4byte gUnknown_0825D670, gUnknown_0825DA70, gUnknown_0825DE70
.4byte 0x060088C0, 0x06008CC0, 0x060090C0
gRubyCoinRewardTilePtrs:: @ 0x086B0CB8
@ 3 sets of 5 sets of 3
@ fifth set has the destination address
.4byte gUnknown_0825DF10, gUnknown_0825E310, gUnknown_0825E710
.4byte gUnknown_0825DF10, gUnknown_0825E310, gUnknown_0825E710
.4byte gUnknown_0825DF70, gUnknown_0825E370, gUnknown_0825E770
.4byte gUnknown_0825DFD0, gUnknown_0825E3D0, gUnknown_0825E7D0
.4byte 0x0600B4E0, 0x0600B8E0, 0x0600BCE0
.4byte gUnknown_0825E030, gUnknown_0825E430, gUnknown_0825E830
.4byte gUnknown_0825E090, gUnknown_0825E490, gUnknown_0825E890
.4byte gUnknown_0825E0F0, gUnknown_0825E4F0, gUnknown_0825E8F0
.4byte gUnknown_0825E150, gUnknown_0825E550, gUnknown_0825E950
.4byte 0x0600BCE0, 0x0600C0E0, 0x0600C4E0
.4byte gUnknown_0825E1B0, gUnknown_0825E5B0, gUnknown_0825E9B0
.4byte gUnknown_0825E1B0, gUnknown_0825E5B0, gUnknown_0825E9B0
.4byte gUnknown_0825E210, gUnknown_0825E610, gUnknown_0825EA10
.4byte gUnknown_0825E270, gUnknown_0825E670, gUnknown_0825EA70
.4byte 0x0600C500, 0x0600C900, 0x0600CD00
gRubyCatchArrowTilePtrs:: @ 0x086B0D6C
@ 3 sets of 5 sets of 3
@ fifth set has the destination address
.4byte gUnknown_0825EB10, gUnknown_0825EF10, gUnknown_0825F310
.4byte gUnknown_0825EB10, gUnknown_0825EF10, gUnknown_0825F310
.4byte gUnknown_0825EB70, gUnknown_0825EF70, gUnknown_0825F370
.4byte gUnknown_0825EBD0, gUnknown_0825EFD0, gUnknown_0825F3D0
.4byte 0x0600D2E0, 0x0600D6E0, 0x060082E0
.4byte gUnknown_0825EC50, gUnknown_0825F050, gUnknown_0825F430
.4byte gUnknown_0825ECB0, gUnknown_0825F0B0, gUnknown_0825F490
.4byte gUnknown_0825ED10, gUnknown_0825F110, gUnknown_0825F4F0
.4byte gUnknown_0825ED70, gUnknown_0825F170, gUnknown_0825F550
.4byte 0x060082E0, 0x060086E0, 0x06008AC0
.4byte gUnknown_0825EDD0, gUnknown_0825F1B0, gUnknown_0825F5B0
.4byte gUnknown_0825EDD0, gUnknown_0825F1B0, gUnknown_0825F5B0
.4byte gUnknown_0825EE30, gUnknown_0825F210, gUnknown_0825F610
.4byte gUnknown_0825EE90, gUnknown_0825F270, gUnknown_0825F670
.4byte 0x06008AC0, 0x06008EA0, 0x060092A0
gBallShadowTileIndices:: @ 0x086B0E20
.incbin "baserom.gba", 0x6B0E20, 0x40
@ 31 values (ix 0 - 30) used, then padding
.2byte 0,0,0,0,1,1,1,1,2,2
.2byte 2,2,3,3,3,3,4,4,4,4
.2byte 4,5,5,5,5,5,5,5,5,5
.2byte 5
.align 2, 0
gSlingshotHitFrameIndices:: @ 0x086B0E60
.incbin "baserom.gba", 0x6B0E60, 0xC
.2byte 0,1,1,1,1,0
gBumperHitCounterTilePtrs:: @ 0x086B0E6C
.incbin "baserom.gba", 0x6B0E6C, 0x30
@ 6 sets of 2
@ sixth set has destination address
.4byte gUnknown_082DEEE0, gUnknown_082DF2E0
.4byte gUnknown_082DEF20, gUnknown_082DF320
.4byte gUnknown_082DEF60, gUnknown_082DF360
.4byte gUnknown_082DEFA0, gUnknown_082DF3A0
.4byte gUnknown_082DEFE0, gUnknown_082DF3E0
.4byte 0x0600A640, 0x0600AA40
gSapphireProgressDigitTilePtrs:: @ 0x086B0E9C
.incbin "baserom.gba", 0x6B0E9C, 0xB0
@ 11 sets of 4
@ eleventh set has destination address
.4byte gUnknown_082DCE00, gUnknown_082DD200, gUnknown_082DCF40, gUnknown_082DD340
.4byte gUnknown_082DCE20, gUnknown_082DD220, gUnknown_082DCF60, gUnknown_082DD360
.4byte gUnknown_082DCE40, gUnknown_082DD240, gUnknown_082DCF80, gUnknown_082DD380
.4byte gUnknown_082DCE60, gUnknown_082DD260, gUnknown_082DCFA0, gUnknown_082DD3A0
.4byte gUnknown_082DCE80, gUnknown_082DD280, gUnknown_082DCFC0, gUnknown_082DD3C0
.4byte gUnknown_082DCEA0, gUnknown_082DD2A0, gUnknown_082DCFE0, gUnknown_082DD3E0
.4byte gUnknown_082DCEC0, gUnknown_082DD2C0, gUnknown_082DD000, gUnknown_082DD400
.4byte gUnknown_082DCEE0, gUnknown_082DD2E0, gUnknown_082DD020, gUnknown_082DD420
.4byte gUnknown_082DCF00, gUnknown_082DD300, gUnknown_082DD040, gUnknown_082DD440
.4byte gUnknown_082DCF20, gUnknown_082DD320, gUnknown_082DD060, gUnknown_082DD460
.4byte 0x0600B220, 0x0600B620, 0x0600B240, 0x0600B640
gRotatingBackgroundTilePtrs:: @ 0x086B0F4C
.incbin "baserom.gba", 0x6B0F4C, 0x50
@ 5 sets of 4
@ fifth set has destination address
.4byte gUnknown_082E3EC0, gUnknown_082E42C0, gUnknown_082E46C0, gUnknown_082E4AC0
.4byte gUnknown_082E3F40, gUnknown_082E4340, gUnknown_082E4740, gUnknown_082E4B40
.4byte gUnknown_082E3FC0, gUnknown_082E43C0, gUnknown_082E47C0, gUnknown_082E4BC0
.4byte gUnknown_082E3F40, gUnknown_082E4340, gUnknown_082E4740, gUnknown_082E4B40
.4byte 0x0600AEA0, 0x0600B2A0, 0x0600B6A0, 0x0600BAA0
gBonusModeIndicatorTilePtrs:: @ 0x086B0F9C
.incbin "baserom.gba", 0x6B0F9C, 0x10
gHatchMachineDrawSegment:: @ 0x086B0F9C
@ 10 sets of 3 sets of 2
@ third set has destination address
.4byte gUnknown_082DE1E0, gUnknown_082DE5E0
.4byte gUnknown_082DE620, gUnknown_082DEA20
.4byte 0x0600DD40, 0x0600DD80
gUnknown_086B0FAC:: @ 0x086B0FAC
.incbin "baserom.gba", 0x6B0FAC, 0xE0
.4byte gUnknown_082DE660, gUnknown_082DEA60
.4byte gUnknown_082DE6A0, gUnknown_082DEAA0
.4byte 0x0600DDC0, 0x0600DE00
.4byte gUnknown_082DE6E0, gUnknown_082DEAE0
.4byte gUnknown_082DE720, gUnknown_082DEB20
.4byte 0x0600D9C0, 0x0600DAC0
.4byte gUnknown_082DEB60, gUnknown_082DEB60
.4byte gUnknown_082DEBA0, gUnknown_082DEBA0
.4byte 0x0600DE40, 0x0600DE40
.4byte gUnknown_082DE7E0, gUnknown_082DEBE0
.4byte gUnknown_082DE820, gUnknown_082DEC20
.4byte 0x0600D900, 0x0600DA00
.4byte gUnknown_082DE860, gUnknown_082DEC60
.4byte gUnknown_082DE8A0, gUnknown_082DECA0
.4byte 0x0600DE80, 0x0600DEC0
.4byte gUnknown_082DE8E0, gUnknown_082DECE0
.4byte gUnknown_082DE920, gUnknown_082DED20
.4byte 0x0600DF00, 0x0600DF40
.4byte gUnknown_082DE960, gUnknown_082DED60
.4byte gUnknown_082DE9A0, gUnknown_082DEDA0
.4byte 0x0600DF80, 0x0600DFC0
.4byte gUnknown_082DE9E0, gUnknown_082DEDE0
.4byte gUnknown_082DEE20, gUnknown_082DF220
.4byte 0x0600E000, 0x0600E040
.4byte gUnknown_082DEE60, gUnknown_082DF260
.4byte gUnknown_082DEEA0, gUnknown_082DF2A0
.4byte 0x0600E080, 0x0600E0C0
gSapphireSlingshotTilePtrs:: @ 0x086B108C
.incbin "baserom.gba", 0x6B108C, 0x78
@ 2 sets (sides) of 3 sets of 5
@ third set has destination address
.4byte gUnknown_082E2AA0, gUnknown_082E2EA0, gUnknown_082E32A0, gUnknown_082E36A0, gUnknown_082E3AC0
.4byte gUnknown_082E2B00, gUnknown_082E2F00, gUnknown_082E3300, gUnknown_082E3700, gUnknown_082E3B20
.4byte 0x0600E100, 0x0600E120, 0x0600E160, 0x0600E1C0, 0x0600E220
.4byte gUnknown_082E2BA0, gUnknown_082E2F80, gUnknown_082E3360, gUnknown_082E3760, gUnknown_082E3B60
.4byte gUnknown_082E2C00, gUnknown_082E2FE0, gUnknown_082E33C0, gUnknown_082E37C0, gUnknown_082E3BC0
.4byte 0x0600E260, 0x0600E280, 0x0600E2C0, 0x0600E320, 0x0600E380
gSapphireTrapIndicatorTilePtrs:: @ 0x086B1104
.incbin "baserom.gba", 0x6B1104, 0x20
@ 4 sets of 2
@ fourth set has destination address
.4byte gUnknown_082DDE20, gUnknown_082DE220
.4byte gUnknown_082DDE60, gUnknown_082DE260
.4byte gUnknown_082DDEA0, gUnknown_082DE2A0
.4byte 0x060081C0, 0x060085C0
gSapphireCatchLightTilePtrs:: @ 0x086B1124
.incbin "baserom.gba", 0x6B1124, 0xA8
@ 3 sets of 7 sets of 2
@ seventh set has destination address
.4byte gUnknown_082DD9A0, gUnknown_082DDDA0
.4byte gUnknown_082DD9E0, gUnknown_082DDDE0
.4byte gUnknown_082DDEE0, gUnknown_082DE2E0
.4byte gUnknown_082DDF20, gUnknown_082DE320
.4byte gUnknown_082DE060, gUnknown_082DE460
.4byte gUnknown_082DE0A0, gUnknown_082DE4A0
.4byte 0x0600A180, 0x0600A580
.4byte gUnknown_082DD9A0, gUnknown_082DDDA0
.4byte gUnknown_082DD9E0, gUnknown_082DDDE0
.4byte gUnknown_082DDF60, gUnknown_082DE360
.4byte gUnknown_082DDFA0, gUnknown_082DE3A0
.4byte gUnknown_082DE0E0, gUnknown_082DE4E0
.4byte gUnknown_082DE120, gUnknown_082DE520
.4byte 0x0600A1C0, 0x0600A5C0
.4byte gUnknown_082DD9A0, gUnknown_082DDDA0
.4byte gUnknown_082DD9E0, gUnknown_082DDDE0
.4byte gUnknown_082DDFE0, gUnknown_082DE3E0
.4byte gUnknown_082DE020, gUnknown_082DE420
.4byte gUnknown_082DE160, gUnknown_082DE560
.4byte gUnknown_082DE1A0, gUnknown_082DE5A0
.4byte 0x0600A200, 0x0600A600
gSapphireModeTimerDisplayTilePtrs:: @ 0x086B11CC
.incbin "baserom.gba", 0x6B11CC, 0x30
@ 3 sets of 4
@ third set has destination address
.4byte gUnknown_082DF660, gUnknown_082DFA60, gUnknown_082DFE80, gUnknown_082E02E0
.4byte gUnknown_082DF760, gUnknown_082DFB60, gUnknown_082DFF80, gUnknown_082E03E0
.4byte 0x0600AD80, 0x0600B180, 0x0600B5A0, 0x0600BA00
gSapphireCatchArrowPaletteTilePtrs:: @ 0x086B11FC
.incbin "baserom.gba", 0x6B11FC, 0x30
@ 3 sets of 4
@ third set has destination address
.4byte gUnknown_082E06A0, gUnknown_082E0A60, gUnknown_082E0E60, gUnknown_082E1260
.4byte gUnknown_082E0720, gUnknown_082E0AE0, gUnknown_082E0EE0, gUnknown_082E12E0
.4byte 0x0600CEA0, 0x0600D260, 0x0600D660, 0x06008260
gSapphireEvoArrowPaletteTilePtrs:: @ 0x086B122C
.incbin "baserom.gba", 0x6B122C, 0x30
@ 3 sets of 4
@ third set has destination address
.4byte gUnknown_082E0860, gUnknown_082E0C60, gUnknown_082E1060, gUnknown_082E1460
.4byte gUnknown_082E08E0, gUnknown_082E0CE0, gUnknown_082E10E0, gUnknown_082E14E0
.4byte 0x0600A9A0, 0x0600ADA0, 0x0600B1A0, 0x0600B5A0
gSapphireRouletteSlotTilePtrs:: @ 0x086B125C
.incbin "baserom.gba", 0x6B125C, 0x50
@ 5 sets of 4
@ fifth set has destination address
.4byte gUnknown_082E1680, gUnknown_082E1A80, gUnknown_082E1E80, gUnknown_082E2280
.4byte gUnknown_082E1700, gUnknown_082E1B00, gUnknown_082E1F00, gUnknown_082E2300
.4byte gUnknown_082E1780, gUnknown_082E1B80, gUnknown_082E1F80, gUnknown_082E2380
.4byte gUnknown_082E1800, gUnknown_082E1C00, gUnknown_082E2000, gUnknown_082E2400
.4byte 0x0600BD20, 0x0600C120, 0x0600C520, 0x0600C920
gSapphireBallPowerUpLightTilePtrs:: @ 0x086B12AC
.incbin "baserom.gba", 0x6B12AC, 0x24
@ 3 sets of 3
@ third value has destination address
.4byte gUnknown_082DD620, gUnknown_082DD660, 0x06008540
.4byte gUnknown_082DD6A0, gUnknown_082DD6E0, 0x060085A0
.4byte gUnknown_082DD720, gUnknown_082DD760, 0x060085E0
gSapphireCatchFlashTilePtrs:: @ 0x086B12D0
.incbin "baserom.gba", 0x6B12D0, 0x30
@ 3 sets of 4
@ third set has destination address
.4byte gUnknown_082E0780, gUnknown_082E0B60, gUnknown_082E0F60, gUnknown_082E1360
.4byte gUnknown_082E0800, gUnknown_082E0BE0, gUnknown_082E0FE0, gUnknown_082E13E0
.4byte 0x0600C260, 0x0600C640, 0x0600CA40, 0x0600CE40
gSapphireHoleIndicatorTilePtrs:: @ 0x086B1300
.incbin "baserom.gba", 0x6B1300, 0x40
@ 4 sets of 4
@ third value has the destination; fouth value blank.
.4byte gUnknown_082DD7A0, gUnknown_082DD7E0, 0x0600A460, 0
.4byte gUnknown_082DD820, gUnknown_082DD860, 0x0600A4C0, 0
.4byte gUnknown_082DD8A0, gUnknown_082DD8E0, 0x0600A6C0, 0
.4byte gUnknown_082DD920, gUnknown_082DD960, 0x0600A720, 0
gSapphireEvoArrowBonusTilePtrs:: @ 0x086B1340
.incbin "baserom.gba", 0x6B1340, 0xB4
gSapphireEvoArrowTilePtrs:: @ 0x086B1340
@ 3 sets of 5 sets of 3
@ fifth set has destination address
.4byte gUnknown_082DA9E0, gUnknown_082DADE0, gUnknown_082DB1E0
.4byte gUnknown_082DA9E0, gUnknown_082DADE0, gUnknown_082DB1E0
.4byte gUnknown_082DAA40, gUnknown_082DAE40, gUnknown_082DB240
.4byte gUnknown_082DAAA0, gUnknown_082DAEA0, gUnknown_082DB2A0
.4byte 0x0600D080, 0x0600D480, 0x06008080
gSapphireCoinRewardAltTilePtrs:: @ 0x086B13F4
.incbin "baserom.gba", 0x6B13F4, 0x78
.4byte gUnknown_082DAB00, gUnknown_082DAF00, gUnknown_082DB300
.4byte gUnknown_082DAB60, gUnknown_082DAF60, gUnknown_082DB360
.4byte gUnknown_082DABC0, gUnknown_082DAFC0, gUnknown_082DB3C0
.4byte gUnknown_082DAC20, gUnknown_082DB020, gUnknown_082DB420
.4byte 0x060080A0, 0x060084A0, 0x060088A0
gUnknown_086B146C:: @ 0x086B146C
.incbin "baserom.gba", 0x6B146C, 0x3C
.4byte gUnknown_082DAC80, gUnknown_082DB080, gUnknown_082DB4A0
.4byte gUnknown_082DAC80, gUnknown_082DB080, gUnknown_082DB4A0
.4byte gUnknown_082DACE0, gUnknown_082DB0E0, gUnknown_082DB500
.4byte gUnknown_082DAD40, gUnknown_082DB140, gUnknown_082DB560
.4byte 0x060088C0, 0x06008CC0, 0x060090E0
gSapphireCatchArrowBonusTilePtrs:: @ 0x086B14A8
.incbin "baserom.gba", 0x6B14A8, 0xB4
gSapphireCoinRewardTilePtrs:: @ 0x086B13F4
@ 3 sets of 5 sets of 3
@ fourth set has destination address; fifth has spacers
.4byte gUnknown_082DB5E0, gUnknown_082DB9E0, gUnknown_082DBDE0
.4byte gUnknown_082DB640, gUnknown_082DBA40, gUnknown_082DBE40
.4byte gUnknown_082DB6A0, gUnknown_082DBAA0, gUnknown_082DBEA0
.4byte 0x0600C4A0, 0x0600C8A0, 0x0600CCA0
.4byte 0,0,0
.4byte gUnknown_082DB720, gUnknown_082DBB20, gUnknown_082DBF20
.4byte gUnknown_082DB780, gUnknown_082DBB80, gUnknown_082DBF80
.4byte gUnknown_082DB7E0, gUnknown_082DBBE0, gUnknown_082DBFE0
.4byte 0x0600CCE0, 0x0600D0E0, 0x0600D4C0
.4byte 0,0,0
.4byte gUnknown_082DB820, gUnknown_082DBC20, gUnknown_082DC020
.4byte gUnknown_082DB880, gUnknown_082DBC80, gUnknown_082DC080
.4byte gUnknown_082DB8E0, gUnknown_082DBCE0, gUnknown_082DC0E0
.4byte 0x0600D0E0, 0x0600D4E0, 0x060080E0
.4byte 0,0,0
gSapphireCatchArrowTilePtrs:: @ 0x086B14A8
@ 3 sets of 5 sets of 3
@ fifth set has destination address
.4byte gUnknown_082DC1E0, gUnknown_082DC5E0, gUnknown_082DC9E0
.4byte gUnknown_082DC1E0, gUnknown_082DC5E0, gUnknown_082DC9E0
.4byte gUnknown_082DC240, gUnknown_082DC640, gUnknown_082DCA40
.4byte gUnknown_082DC2A0, gUnknown_082DC6A0, gUnknown_082DCAA0
.4byte 0x0600D2E0, 0x0600D6E0, 0x060082E0
.4byte gUnknown_082DC320, gUnknown_082DC720, gUnknown_082DCB00
.4byte gUnknown_082DC380, gUnknown_082DC780, gUnknown_082DCB60
.4byte gUnknown_082DC3E0, gUnknown_082DC7E0, gUnknown_082DCBC0
.4byte gUnknown_082DC440, gUnknown_082DC840, gUnknown_082DCC20
.4byte 0x060082E0, 0x060086E0, 0x06008AC0
.4byte gUnknown_082DC4A0, gUnknown_082DC880, gUnknown_082DCC80
.4byte gUnknown_082DC4A0, gUnknown_082DC880, gUnknown_082DCC80
.4byte gUnknown_082DC500, gUnknown_082DC8E0, gUnknown_082DCCE0
.4byte gUnknown_082DC560, gUnknown_082DC940, gUnknown_082DCD40
.4byte 0x06008AC0, 0x06008EA0, 0x060092A0
gFieldSpriteSets:: @ 0x086B155C
.4byte gUnknown_086B2390

View File

Before

Width:  |  Height:  |  Size: 186 B

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 B

View File

@ -435,7 +435,7 @@ extern void DispatchRubyCatchModeInit();
extern void UpdateRubyCatchModeAnimation(void);
//extern ? InitSharpedoCatchMode();
extern void AnimateSharpedoCatchSequence();
extern void InitEggHatchMode(void);
extern void InitRubyEggHatchMode(void);
//extern ? AnimateEggHatchSequence();
//extern ? InitRubyEvolutionShopMode();
//extern ? AnimateRubyEvolutionShopSequence();
@ -483,9 +483,9 @@ extern void UpdatePokemonNamePosition();
extern void HidePokemonNameDisplay();
extern void InitEvolutionSuccessDisplay(void);
extern void AnimateEvolutionSuccessScreen(void);
extern void InitEggModeAnimation(void);
extern void InitRubyEggModeAnimation(void);
//extern ? UpdateEggModeAnimation();
//extern ? UpdateEggHatchDisplay();
//extern ? UpdateHatchCave();
extern void CleanupEggModeState(void);
//extern ? InitEggMode();
//extern ? UpdateEggMode();
@ -534,22 +534,22 @@ extern void DrawSpoinkSprite();
extern void RunEvolutionCutscene(void);
//extern ? sub_2DE54();
extern void RunTravelEventCutscene(void);
extern void DecrementFieldTimer();
extern void DecrementPelipperTimer();
extern void UpdatePelipperPondEntity();
extern void AnimateWailmerEntity();
extern void UpdateZigzagoonEntity();
extern void DrawZigzagoonAndShockWall();
extern void DrawZigzagoonAndRouletteStopPrompt();
extern void UpdateSapphireBumperLogic();
extern void DrawSapphireBumperSprites();
extern void CalculateRubyBumperBounce();
extern void HandleRubyBumperHit();
extern void InitSapphireEggCaveState();
extern void UpdateSapphireEggCaveAnimation();
extern void InitSapphireEggHatchState();
extern void UpdateSapphireEggHatchAnimation();
extern void UpdateSapphireSeedotCollection();
extern void DrawSapphireSeedotAndBasketSprites();
extern void UpdateSapphireShopSignAnimation();
extern void DrawSapphireShopSignSprite(void);
extern void UpdateSapphireHoleLetterSystem();
extern void UpdateSapphireEggMachine();
extern void DrawBoardEdgeBanner(void);
extern void RestoreBoardObjPalettes(s16);
extern void RegisterCaptureOrEvolution(s16);
@ -620,7 +620,7 @@ extern void SphealBoard_PelipperDeliversBall(void);
extern void UpdateSealeoKnockdownPhysics(void);
extern void AnimateSphealBackground(void);
extern void UpdateSphealResultsScreen(void);
extern void loadIntroduction(void);
extern void loadFieldBoardGraphics(void);
extern void SetBoardCollisionConfig(s16);
extern void UpdateScrollingBackgroundTiles(void);
//extern ? AllBoardProcess_1A_47100();
@ -654,23 +654,23 @@ extern void ProcessMainBoardBallDrainAndLaunch(void);
extern void ProcessBonusBoardBallDrain(void);
extern void ResetBoardStateOnDeath(void);
extern void UpdateRubyBoardAnimations(void);
extern void AnimateRubySlingshotTimer(void);
extern void AnimateRubySlingshotHit(void);
extern void LoadShopItemGraphics(s16);
extern void DrawRubyProgressDigits(void);
extern void AnimateRubyTrapIndicator(void);
extern void AnimateRubyCatchLightBlink(void);
extern void AnimateRubyHoleIndicators(void);
extern void DrawRubyModeTimerDisplay(void);
extern void AnimateRubyCatchArrow(void);
extern void AnimateRubyEvoArrow(void);
extern void AnimateRubyCatchArrowPalette(void);
extern void AnimateRubyEvoArrowPalette(void);
extern void AnimateRubyRouletteSlot(void);
extern void AnimateRubyCatchProgressArrow(void);
extern void AnimateRubyBallPowerUpSequence(void);
extern void DrawRubyBallPowerUpLights(void);
extern void UpdateCoinRewardTimer(void);
extern void DrawCoinRewardMeter(void);
extern void DrawEvoArrowProgress(void);
extern void DrawCatchArrowProgress(void);
extern void DrawRubyCoinRewardMeter(void);
extern void DrawRubyEvoArrowProgress(void);
extern void DrawRubyCatchArrowProgress(void);
extern void UpdateSapphireBoardAnimations(void);
extern void DrawSapphireProgressDigits(void);
extern void AnimateSapphireSlingshotHit(void);
@ -679,16 +679,16 @@ extern void AnimateRotatingBackground(void);
extern void AnimateSapphireCatchLightBlink(void);
extern void AnimateSapphireHoleIndicators(void);
extern void DrawSapphireModeTimerDisplay(void);
extern void DrawCoinRewardMeterAlt(void);
extern void DrawSapphireCoinRewardMeter(void);
extern void AnimateSapphireCatchArrowPalette(void);
extern void AnimateSapphireEvoArrowPalette(void);
extern void DrawEvoArrowBonusField(void);
extern void DrawCatchArrowBonusField(void);
extern void AnimateCatchArrowPaletteFlash(void);
extern void DrawSapphireEvoArrowProgress(void);
extern void DrawSapphireCatchArrowProgress(void);
extern void AnimateSapphireCatchArrowPaletteFlash(void);
extern void AnimateSapphireRouletteSlot(void);
extern void DrawBallPowerUpLights(void);
extern void AnimateBonusModeIndicators(void);
extern void AnimateBumperHitCounter(void);
extern void DrawSapphireBallPowerUpLights(void);
extern void AnimateHatchMachineSpinner(void);
extern void AnimatePelliperBumper(void);
extern void RubyBoardProcess_0A_50848(void);
//extern ? RubyBoardProcess_0B_50918();
extern void SapphireBoardProcess_0A_50AD4(void);

View File

@ -0,0 +1,15 @@
#ifndef GUARD_FUNCTIONS_MAIN_BOARD_H
#define GUARD_FUNCTIONS_MAIN_BOARD_H
extern void SelectRubyShopDoorState(void);
extern void AnimateRubyShopDoor(void);
extern void UpdateEggModeAnimation(void);
extern void UpdateHatchCave(void);
extern void DrawPikachuSpinner(void);
extern void UpdateEvolutionShopSprite(void);
extern void InitRubyEggModeAnimation(void);
extern void LoadShopItemGraphics(s16);
#endif //GUARD_FUNCTIONS_MAIN_BOARD_H

23
include/functions_ruby.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef GUARD_FUNCTIONS_RUBY_H
#define GUARD_FUNCTIONS_RUBY_H
#include "functions_main_boards.h"
extern void UpdateNuzleafEntity(void);
extern void DrawRubyNuzleafPlatformSprite(void);
extern void RubyPondTriBumperHandleHitAndDraw(void);
extern void DrawWhiscash(void);
extern void AnimateSharpedoEntity(void);
extern void UpdateChikoritaAttackAnimation(void);
extern void AnimateChikoritaSprite(void);
extern void UpdateGulpinBossState(void);
extern void UpdateRubyRampPrizeGate(void);
extern void DrawRubySideBumperSprites(void);
extern void UpdateRubySideBumperAnimation(void);
extern void UpdateRubyBoardEntityRendering(void);
extern void UpdateRubyBoardEntityLogic(void);
extern void HandleRubyFlipperButtonInput(void);
extern void RubyPond_EntityLogic(void);
#endif //GUARD_FUNCTIONS_RUBY_H

View File

@ -248,11 +248,11 @@ struct PinballGame
/*0x12E*/ s16 totalWeight; // Added weight of all possible mons in area
/*0x130*/ s16 speciesWeights[25]; // Weight of each species
/*0x162*/ s8 forcePondToWhiscash;
/*0x163*/ s8 sapphirePondFlag;
/*0x164*/ s8 pondAnimFrameIndex;
/*0x165*/ s8 sapphireEntityCollisionFlag;
/*0x166*/ u16 sapphireSpriteTimer;
/*0x168*/ u16 pondAnimSubTimer;
/*0x163*/ s8 spoinkEntityState;
/*0x164*/ s8 spoinkAnimFrameIx;
/*0x165*/ s8 ballTouchingSpoink;
/*0x166*/ u16 spoinkPullbackYDistance;
/*0x168*/ u16 spoinkAnimFrameTimer;
/*0x16A*/ s16 bannerSlideX;
/*0x16C*/ s8 rubyPondState;
/*0x16D*/ u8 filler16D[0x1];
@ -408,7 +408,7 @@ struct PinballGame
/*0x2CA*/ s16 eggDeliveryY;
/*0x2CC*/ s16 eggDeliveryVelX;
/*0x2CE*/ s16 eggDeliveryVelY;
/*0x2D0*/ s8 eggDeliveryState;
/*0x2D0*/ s8 rubyEggDeliveryState;
/*0x2D1*/ u8 filler2D1[3];
/*0x2D4*/ u16 cyndaquilCaveSpriteX;
/*0x2D6*/ u16 cyndaquilCaveSpriteY;
@ -470,11 +470,11 @@ struct PinballGame
/*0x335*/ u8 filler335[0x1];
/*0x336*/ u16 seedotAnimTimer[3];
/*0x33C*/ u16 seedotYOffset[3];
/*0x342*/ s8 sapphireDiverterActive;
/*0x343*/ s8 holeCaptureReady;
/*0x344*/ s8 holeLetterNewHit;
/*0x345*/ s8 holeLetterCount;
/*0x346*/ s8 holeLetterSystemState;
/*0x342*/ s8 hatchMachineActive; // Turns off while launching, Reenabled when ball touches ramp
/*0x343*/ s8 sapphirerubyEggDeliveryState;
/*0x344*/ s8 hatchMachineNewHit;
/*0x345*/ s8 sapphireHatchMachineFrameIx;
/*0x346*/ s8 sapphireHatchMachineState; // 0-6
/*0x347*/ u8 filler347[0x1];
/*0x348*/ u16 holeAnimFrameCounter;
/*0x34A*/ s8 targetBumperHitCounter;

View File

@ -30,55 +30,74 @@ SECTIONS
{
src/crt0.o(.text);
src/util.o(.text);
src/rom_850.o(.text);
src/main.o(.text);
src/gbplayer.o(.text);
src/link.o(.text);
src/rom_2414.o(.text);
src/bonus_field_select.o(.text);
src/ereader.o(.text);
src/pokedex.o(.text);
src/field_select.o(.text);
src/intro.o(.text);
src/high_scores.o(.text);
src/rom_1068C.o(.text);
src/display.o(.text);
src/titlescreen.o(.text);
src/board_process5.o(.text);
src/board_process7.o(.text);
src/board_process6.o(.text);
src/collision_checks.o(.text);
src/board_process6_collision.o(.text);
src/collision_ruby.o(.text);
src/collision_sapphire.o(.text);
src/collision_dusclops.o(.text);
src/collision_kecleon.o(.text);
src/collision_kyogre.o(.text);
src/collision_groudon.o(.text);
src/collision_rayquaza.o(.text);
src/collision_spheal.o(.text);
src/game_idle.o(.text);
src/board_process4.o(.text);
src/board_process3_ruby.o(.text);
src/rom_1A0F4.o(.text);
src/rom_1A98C.o(.text);
src/rom_201B8.o(.text);
src/board_state_transitions_and_idle.o(.text);
src/board_process3_ruby_entities.o(.text);
src/banners.o(.text);
src/ruby_catch_holes.o(.text);
src/main_board_catch_holes.o(.text);
src/main_portrait_display.o(.text);
src/board_process3_ruby_entities_2.o(.text);
src/board_process_3_charge_spinner.o(.text);
src/ruby_trigger_targets.o(.text);
src/pichu_entity.o(.text);
src/rom_27E08.o(.text);
src/rom_27F94.o(.text);
src/rom_2C538.o(.text);
src/rom_2E67C.o(.text);
src/rom_30480.o(.text);
src/rom_31BE8.o(.text);
src/rom_31CF8.o(.text);
src/catch_tile_logic.o(.text);
src/travel_mode.o(.text);
src/evolution_mode.o(.text);
src/catch_and_hatch_modes.o(.text);
src/catch_tile_particles.o(.text);
src/center_capture_hole.o(.text);
src/ruby_ramp.o(.text);
src/launcher_and_cutscenes.o(.text);
src/sapphire_pond_and_zigzagoon.o(.text);
src/board_bumpers.o(.text);
src/sapphire_seedot_egg_shop.o(.text);
src/board_edge.o(.text);
src/catch_hatch_picker.o(.text);
src/board_process3_sapphire.o(.text);
src/board_process3_dusclops.o(.text);
src/rom_356A0.o(.text);
src/bonus_complete_scoring_transition.o(.text);
src/board_process3_kecleon.o(.text);
src/board_process3_kyogre.o(.text);
src/board_process3_groudon.o(.text);
src/board_process3_rayquaza.o(.text);
src/board_process3_spheal.o(.text);
src/rom_467F4.o(.text);
src/board_setup.o(.text);
src/board_process1.o(.text);
src/debug_menu.o(.text);
src/mode_change_and_debug_menu.o(.text);
src/pause_game.o(.text);
src/pinball_game_main.o(.text);
src/save_and_restore_game.o(.text);
src/board_process8.o(.text);
src/board_process2.o(.text);
src/rom_4F258.o(.text);
src/rom_50AD4.o(.text);
src/board_process0.o(.text);
src/ruby_board_indicators.o(.text);
src/sapphire_board_indicators.o(.text);
src/board_process0_sprite_init.o(.text);
src/options.o(.text);
src/pokemon_cry.o(.text);
src/save.o(.text);

View File

@ -6,7 +6,6 @@
extern void RenderBannerSlideAnimation(void);
void ProcessBannerCameraTransition(void)
{
if ((gMain.modeChangeFlags & MODE_CHANGE_BANNER) != 0)

415
src/board_bumpers.c Normal file
View File

@ -0,0 +1,415 @@
#include "global.h"
#include "m4a.h"
#include "main.h"
#include "constants/bg_music.h"
#include "constants/main_board.h"
extern const u8 gSapphireBoardShopShockWall_Gfx[][0x80];
extern const s16 gSapphireBumperAnimFrames[][2];
extern const s16 gBumperMosaicValues[];
extern const u8 gSapphireBumperLeft_Gfx[][0x300];
extern const u8 gSapphireBumperLeftHit_Gfx[][0x200];
extern const u8 gSapphireBumperRight_Gfx[][0x300];
extern const u8 gSapphireBumperRightHit_Gfx[][0x200];
extern const u8 gPondBumper_Gfx[][0x200];
void UpdateSapphireBumperLogic(void)
{
s16 i;
u32 mosaicVal;
for (i = 0; i < 2; i++)
{
switch (gCurrentPinballGame->sapphireBumperState[i])
{
case 0:
if (gSapphireBumperAnimFrames[gCurrentPinballGame->sapphireBumperAnimKeyframe[i]][1] > gCurrentPinballGame->sapphireBumperAnimSubTimer[i])
{
gCurrentPinballGame->sapphireBumperAnimSubTimer[i]++;
}
else
{
gCurrentPinballGame->sapphireBumperAnimKeyframe[i]++;
gCurrentPinballGame->sapphireBumperAnimSubTimer[i] = 0;
if (gCurrentPinballGame->sapphireBumperAnimKeyframe[i] > 3)
gCurrentPinballGame->sapphireBumperAnimKeyframe[i] = 0;
}
if (gCurrentPinballGame->sapphireBumperHitFxTimer[i] < 152)
gCurrentPinballGame->sapphireBumperHitFxTimer[i]++;
else
gCurrentPinballGame->sapphireBumperHitFxTimer[i] = 0;
break;
case 1:
if (gSapphireBumperAnimFrames[gCurrentPinballGame->sapphireBumperAnimKeyframe[i]][1] > gCurrentPinballGame->sapphireBumperAnimSubTimer[i])
{
gCurrentPinballGame->sapphireBumperAnimSubTimer[i]++;
}
else
{
gCurrentPinballGame->sapphireBumperAnimKeyframe[i]++;
gCurrentPinballGame->sapphireBumperAnimSubTimer[i] = 0;
if (gCurrentPinballGame->sapphireBumperAnimKeyframe[i] == 5)
{
m4aSongNumStart(SE_UNKNOWN_0xE6);
gCurrentPinballGame->scoreAddedInFrame = 2000;
}
}
if (gCurrentPinballGame->sapphireBumperAnimKeyframe[i] == 6)
{
if (gCurrentPinballGame->sapphireBumperLitCountdown)
{
if (gCurrentPinballGame->sapphireBumperLitCountdown == 1)
{
gCurrentPinballGame->sapphireBumperAnimKeyframe[i] = 7;
gCurrentPinballGame->sapphireBumperState[i] = 2;
}
}
gCurrentPinballGame->sapphireBumperAnimSubTimer[i] = 0;
}
gCurrentPinballGame->sapphireBumperHitFxTimer[i] = 20;
break;
case 2:
if (gSapphireBumperAnimFrames[gCurrentPinballGame->sapphireBumperAnimKeyframe[i]][1] > gCurrentPinballGame->sapphireBumperAnimSubTimer[i])
{
gCurrentPinballGame->sapphireBumperAnimSubTimer[i]++;
}
else
{
gCurrentPinballGame->sapphireBumperAnimKeyframe[i]++;
gCurrentPinballGame->sapphireBumperAnimSubTimer[i] = 0;
if (gCurrentPinballGame->sapphireBumperAnimKeyframe[i] == 8)
m4aSongNumStart(SE_UNKNOWN_0xE7);
if (gCurrentPinballGame->sapphireBumperAnimKeyframe[i] > 8)
{
gCurrentPinballGame->sapphireBumperAnimKeyframe[i] = 0;
gCurrentPinballGame->sapphireBumperState[i] = 0;
}
}
gCurrentPinballGame->sapphireBumperHitFxTimer[i] = 20;
break;
case 3:
gCurrentPinballGame->sapphireBumperAnimKeyframe[i] = 9;
gCurrentPinballGame->sapphireBumperAnimSubTimer[i] = 0;
gCurrentPinballGame->sapphireBumperState[i] = 4;
gCurrentPinballGame->sapphireBumperHitFxTimer[i] = 20;
break;
case 4:
if (gSapphireBumperAnimFrames[gCurrentPinballGame->sapphireBumperAnimKeyframe[i]][1] > gCurrentPinballGame->sapphireBumperAnimSubTimer[i])
{
gCurrentPinballGame->sapphireBumperAnimSubTimer[i]++;
}
else
{
gCurrentPinballGame->sapphireBumperAnimKeyframe[i]++;
gCurrentPinballGame->sapphireBumperAnimSubTimer[i] = 0;
if (gCurrentPinballGame->sapphireBumperAnimKeyframe[i] > 17)
{
if (gCurrentPinballGame->boardState == 6)
{
gCurrentPinballGame->sapphireBumperAnimKeyframe[i] = 0;
gCurrentPinballGame->sapphireBumperState[i] = 0;
}
else
{
gCurrentPinballGame->sapphireBumperAnimKeyframe[i] = 9;
}
}
}
gCurrentPinballGame->sapphireBumperHitFxTimer[i] = 20;
break;
case 5:
if (gSapphireBumperAnimFrames[gCurrentPinballGame->sapphireBumperAnimKeyframe[i]][1] > gCurrentPinballGame->sapphireBumperAnimSubTimer[i])
{
gCurrentPinballGame->sapphireBumperAnimSubTimer[i]++;
}
else
{
gCurrentPinballGame->sapphireBumperAnimKeyframe[i]++;
gCurrentPinballGame->sapphireBumperAnimSubTimer[i] = 0;
if (gCurrentPinballGame->sapphireBumperAnimKeyframe[i] > 17)
{
gCurrentPinballGame->sapphireBumperState[i] = 0;
gCurrentPinballGame->sapphireBumperAnimKeyframe[i] = 0;
}
}
gCurrentPinballGame->sapphireBumperHitFxTimer[i] = 20;
break;
}
}
if (gCurrentPinballGame->ballCatchState != TRAP_EVO_SHOP_HOLE)
{
if (gCurrentPinballGame->sapphireBumperLitCountdown)
gCurrentPinballGame->sapphireBumperLitCountdown--;
}
if (gCurrentPinballGame->ballLaunchTimer)
{
gCurrentPinballGame->ballLaunchTimer--;
if (gCurrentPinballGame->ballLaunchTimer == 0)
gCurrentPinballGame->secondaryBall = gCurrentPinballGame->ballStates;
}
if (gCurrentPinballGame->shopBumperHitTimer)
{
if (gCurrentPinballGame->shopBumperHitTimer == 17)
{
m4aSongNumStart(SE_UNKNOWN_0xE8);
gCurrentPinballGame->scoreAddedInFrame = 10;
PlayRumble(13);
}
mosaicVal = gBumperMosaicValues[gCurrentPinballGame->shopBumperHitTimer / 3];
REG_MOSAIC = (mosaicVal << 12) | (mosaicVal << 8) | (mosaicVal << 4) | (mosaicVal << 0);
gCurrentPinballGame->shopBumperHitTimer--;
}
if (gCurrentPinballGame->boardState > 2)
{
if (gCurrentPinballGame->boardState != 6)
{
for (i = 0; i < 2; i++)
{
if (gCurrentPinballGame->sapphireBumperState[i])
{
gCurrentPinballGame->sapphireBumperState[i] = 0;
gCurrentPinballGame->sapphireBumperAnimKeyframe[i] = 0;
gCurrentPinballGame->sapphireBumperAnimSubTimer[i] = 0;
}
}
}
}
else if (gCurrentPinballGame->evoArrowProgress > 2)
{
if (gCurrentPinballGame->evolvablePartySize > 0)
{
if (gCurrentPinballGame->sapphireBumperState[0] < 3)
{
gCurrentPinballGame->sapphireBumperState[0] = 3;
gCurrentPinballGame->sapphireBumperState[1] = 3;
}
}
}
else
{
if (gCurrentPinballGame->sapphireBumperState[0] > 2)
{
gCurrentPinballGame->sapphireBumperState[0] = 0;
gCurrentPinballGame->sapphireBumperAnimKeyframe[0] = 0;
gCurrentPinballGame->sapphireBumperState[1] = 0;
gCurrentPinballGame->sapphireBumperAnimKeyframe[1] = 0;
}
}
}
void DrawSapphireBumperSprites(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 index;
group = &gMain.spriteGroups[61];
if (!group->available)
return;
group->baseX = 68 - gCurrentPinballGame->cameraXOffset;
group->baseY = 144 - gCurrentPinballGame->cameraYOffset;
index = gSapphireBumperAnimFrames[gCurrentPinballGame->sapphireBumperAnimKeyframe[0]][0];
DmaCopy16(3, &gSapphireBumperLeft_Gfx[index], (void *)0x06012DA0, 0x280);
for (i = 0; i < 2; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
group = &gMain.spriteGroups[58];
group->baseX = 68 - gCurrentPinballGame->cameraXOffset;
if (gCurrentPinballGame->sapphireBumperHitFxTimer[0] < 14)
{
group->baseY = 144 - gCurrentPinballGame->cameraYOffset;
index = gCurrentPinballGame->sapphireBumperHitFxTimer[0] / 2;
DmaCopy16(3, &gSapphireBumperLeftHit_Gfx[index], (void *)0x06014720, 0x180);
}
else
{
group->baseY = 200;
}
oamSimple = &group->oam[0];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
group = &gMain.spriteGroups[62];
group->baseX = 36 - gCurrentPinballGame->cameraXOffset;
group->baseY = 163 - gCurrentPinballGame->cameraYOffset;
index = gSapphireBumperAnimFrames[gCurrentPinballGame->sapphireBumperAnimKeyframe[1]][0];
DmaCopy16(3, &gSapphireBumperRight_Gfx[index], (void *)0x060130A0, 0x280);
for (i = 0; i < 2; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
group = &gMain.spriteGroups[59];
group->baseX = 36 - gCurrentPinballGame->cameraXOffset;
if (gCurrentPinballGame->sapphireBumperHitFxTimer[1] < 14)
{
group->baseY = 163 - gCurrentPinballGame->cameraYOffset;
index = gCurrentPinballGame->sapphireBumperHitFxTimer[1] / 2;
DmaCopy16(3, &gSapphireBumperRightHit_Gfx[index], (void *)0x06014920, 0x180);
}
else
{
group->baseY = 200;
}
oamSimple = &group->oam[0];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
group = &gMain.spriteGroups[76];
group->baseX = 61 - gCurrentPinballGame->cameraXOffset;
group->baseY = 186 - gCurrentPinballGame->cameraYOffset;
if (gCurrentPinballGame->eggHatchShockWallOverride)
{
gCurrentPinballGame->shopShockWallAnimState = 3;
}
else if (gCurrentPinballGame->sapphireBumperState[0])
{
if (gCurrentPinballGame->sapphireBumperState[1])
gCurrentPinballGame->shopShockWallAnimState = 3;
else
gCurrentPinballGame->shopShockWallAnimState = 2;
}
else if (gCurrentPinballGame->sapphireBumperState[1])
{
gCurrentPinballGame->shopShockWallAnimState = 1;
}
else
{
gCurrentPinballGame->shopShockWallAnimState = 0;
}
if (gCurrentPinballGame->shopShockWallAnimState < 3)
index = gCurrentPinballGame->shopShockWallAnimState * 3 + (gCurrentPinballGame->globalAnimFrameCounter % 30) / 10;
else
index = 9;
DmaCopy16(3, &gSapphireBoardShopShockWall_Gfx[index], (void *)0x060146A0, 0x80);
oamSimple = &group->oam[0];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
void CalculateRubyBumperBounce(void)
{
gCurrentPinballGame->rubyBumperLogicPosition[0].x = 920;
gCurrentPinballGame->rubyBumperLogicPosition[0].y = (133 - (gCurrentPinballGame->globalAnimFrameCounter % 60) / 30) * 10;
gCurrentPinballGame->rubyBumperLogicPosition[1].x = 1260;
gCurrentPinballGame->rubyBumperLogicPosition[1].y = (131 - ((gCurrentPinballGame->globalAnimFrameCounter + 10) % 60) / 30) * 10;
gCurrentPinballGame->rubyBumperLogicPosition[2].x = 1080;
gCurrentPinballGame->rubyBumperLogicPosition[2].y = (161 - ((gCurrentPinballGame->globalAnimFrameCounter + 20) % 60) / 30) * 10;
}
void HandleRubyBumperHit(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 index;
group = &gMain.spriteGroups[63];
if (gCurrentPinballGame->bumperHitCountdown > 0)
{
if (gCurrentPinballGame->bumperHitCountdown == 2)
{
gCurrentPinballGame->scoreAddedInFrame = 500;
m4aSongNumStart(SE_RUBY_BUMPER_HIT);
PlayRumble(7);
if (gCurrentPinballGame->boardState == 4 && gCurrentPinballGame->boardSubState == 5)
{
if (gCurrentPinballGame->hatchTilesBumperAcknowledged < 6)
{
if (gCurrentPinballGame->hatchTilesBumperAcknowledged == 0)
gCurrentPinballGame->hatchTilesBumperAcknowledged = 1;
else if (gCurrentPinballGame->hatchTilesBumperAcknowledged == 1)
gCurrentPinballGame->hatchTilesBumperAcknowledged = 3;
else
gCurrentPinballGame->hatchTilesBumperAcknowledged = 6;
if (gCurrentPinballGame->hatchTilesBumperAcknowledged == 6)
{
if (gCurrentPinballGame->hatchTilesBoardAcknowledged == 0)
{
gMain.modeChangeFlags |= MODE_CHANGE_BANNER;
gCurrentPinballGame->bannerDelayTimer = 50;
gCurrentPinballGame->bannerDisplayTimer = 600;
gCurrentPinballGame->cameraYScrollTarget = 0xEC;
gCurrentPinballGame->cameraYAdjust = 0;
gCurrentPinballGame->cameraYScrollSpeed = 4;
gCurrentPinballGame->bannerGfxIndex = 7;
gCurrentPinballGame->bannerActive = 1;
gCurrentPinballGame->bannerPreserveBallState = 0;
gCurrentPinballGame->bannerDisplayDuration = 80;
gCurrentPinballGame->bannerSlidePosition = -2500;
gCurrentPinballGame->bannerSlideTimer = 50;
gCurrentPinballGame->bannerSlideVelocity = 0;
DmaCopy16(3, gModeBannerTilemaps[7], (void *)0x06015800, 0x2400);
DmaCopy16(3, gModeBannerPalettes[7], (void *)0x050003C0, 0x20);
gMain.blendControl = 0xCE;
}
}
}
}
gCurrentPinballGame->pondEntitySpriteFlag++;
gCurrentPinballGame->bumperHitsSinceReset++;
if (gCurrentPinballGame->bumperHitsSinceReset == 100)
gCurrentPinballGame->scoreAddedInFrame = 50000;
}
gCurrentPinballGame->bumperHitCountdown--;
}
if (group->available)
{
for (i = 0; i < 3; i++)
{
if (gCurrentPinballGame->pondBumperStates[i] > 0)
{
if (gCurrentPinballGame->pondBumperStates[i] < 0)
gCurrentPinballGame->pondBumperStates[i] += 3;
index = gCurrentPinballGame->pondBumperStates[i] / 4 + 2;
gCurrentPinballGame->pondBumperStates[i]--;
}
else
{
index = ((gCurrentPinballGame->globalAnimFrameCounter + (i * 10)) % 30) / 15;
}
DmaCopy16(3, &gPondBumper_Gfx[index], (void *)0x060133A0 + i * 0x200, 0x200);
group->baseX = gCurrentPinballGame->rubyBumperLogicPosition[i].x / 10 - gCurrentPinballGame->cameraXOffset - 8;
group->baseY = gCurrentPinballGame->rubyBumperLogicPosition[i].y / 10 - gCurrentPinballGame->cameraYOffset - 10;
gCurrentPinballGame->rubyBumperCollisionPosition[i].x = (-(gCurrentPinballGame->rubyBumperLogicPosition[i].x / 10) + 8) * 2;
gCurrentPinballGame->rubyBumperCollisionPosition[i].y = (-(gCurrentPinballGame->rubyBumperLogicPosition[i].y / 10) + 3) * 2;
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
}

76
src/board_edge.c Normal file
View File

@ -0,0 +1,76 @@
#include "global.h"
#include "main.h"
#include "gba/gba.h"
#include "m4a.h"
#include "constants/fields.h"
#include "constants/bg_music.h"
extern const u8 gRubyStageCyndaquil_Gfx[][0x280];
void DrawBoardEdgeBanner(void)
{
s16 i;
struct SpriteGroup *group;
if (gMain.selectedField == FIELD_RUBY)
group = &gMain.spriteGroups[81];
else
group = &gMain.spriteGroups[85];
if (group->available)
{
if (gCurrentPinballGame->cameraBaseX < 8)
{
group->baseX = gCurrentPinballGame->cameraXOffset;
group->baseX = -8 - group->baseX;
}
else
{
group->baseX = gCurrentPinballGame->cameraXOffset;
group->baseX = 256 - group->baseX;
}
group->baseY = 0;
for (i = 0; i < 5; i++)
{
struct OamDataSimple *oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY + i * 0x20;
}
}
}
/**
* Executed when saving or loading from a main field
* arg0
* 0 when saving and loading normally
* 2 when loading into the evo or mart menu
*/
void RestoreBoardObjPalettes(s16 arg0)
{
if (gCurrentPinballGame->paletteSwapActive == 1)
{
DmaCopy16(3, gBoardConfig.fieldLayout.objPaletteSets[arg0], (void*)OBJ_PLTT, 0x20);
}
if (gMain.selectedField == FIELD_SAPPHIRE)
{
DmaCopy16(3, gBoardConfig.fieldLayout.objPaletteSets[arg0] + 0x40, (void*)OBJ_PLTT + 0x40, 0xC0);
}
else
{
DmaCopy16(3, gBoardConfig.fieldLayout.objPaletteSets[arg0] + 0x40, (void*)OBJ_PLTT + 0x40, 0xE0);
}
DmaCopy16(3, gBoardConfig.fieldLayout.objPaletteSets[arg0] + 0x140, (void *)OBJ_PLTT + 0x140, 0x20);
// related to Y position of camera on the field
if (gCurrentPinballGame->cameraYViewport < 170)
{
DmaCopy16(3, gFieldPaletteVariants[gMain.selectedField][arg0 * 2], (void *)OBJ_PLTT + 0x160, 0x20);
}
else
{
DmaCopy16(3, gFieldPaletteVariants[gMain.selectedField][arg0 * 2 + 1], (void *)OBJ_PLTT + 0x160, 0x20);
}
}

View File

@ -421,12 +421,12 @@ void ProcessMainBoardBallDrainAndLaunch(void)
if (gCurrentPinballGame->boardState && gCurrentPinballGame->newButtonActions[1] && gCurrentPinballGame->ballInLaunchChute)
{
gCurrentPinballGame->launcherCharging = 1;
gCurrentPinballGame->sapphirePondFlag = 1;
gCurrentPinballGame->spoinkEntityState = 1;
}
if (gCurrentPinballGame->launcherCharging && gCurrentPinballGame->releasedButtonActions[1])
{
gCurrentPinballGame->sapphirePondFlag = 3;
gCurrentPinballGame->spoinkEntityState = 3;
if (gCurrentPinballGame->ballInLaunchChute)
{
PlayRumble(7);

View File

@ -1,51 +1,24 @@
#include "global.h"
#include "functions.h"
#include "functions_ruby.h"
#include "main.h"
#include "m4a.h"
#include "constants/bg_music.h"
#include "constants/ruby_states.h"
extern const void (*gBoardStateInitFuncs[])(void);
extern const void (*gBoardStateUpdateFuncs[])(void);
extern void HandleBoardStateTransitionTeardown(void);
extern void UpdateRubyBoardEntityRendering(void);
extern void UpdateRubyBoardEntityLogic(void);
extern void HandleRubyFlipperButtonInput(void);
extern void UpdateNuzleafEntity(void);
extern void SelectShopDoorState(void);
extern void AnimateShopDoor(void);
extern void DrawWhiscash(void);
extern void RubyPond_EntityLogic(void);
extern void RubyPondTriBumperHandleHitAndDraw(void);
extern void AnimateSharpedoEntity(void);
extern void DrawPikachuSpinner(void);
extern void UpdateChikoritaAttackAnimation(void);
extern void AnimateChikoritaSprite(void);
extern void UpdateGulpinBossState(void);
extern void UpdateSideBumperAnimation(void);
extern void DrawSideBumperSprites(void);
extern void UpdateEvolutionShopSprite(void);
extern void InitEggModeAnimation(void);
extern void UpdateEggModeAnimation(void);
extern void UpdateEggHatchDisplay(void);
extern void UpdateRubyRampPrizeGate(void);
extern void DrawRubyNuzleafPlatformSprite(void);
extern void LoadShopItemGraphics(s16);
void RubyBoardProcess_3A_19A20(void)
{
gCurrentPinballGame->catchModeArrows = 2;
UpdateNuzleafEntity();
LoadShopItemGraphics(0);
AnimateShopDoor();
InitEggModeAnimation();
AnimateRubyShopDoor();
InitRubyEggModeAnimation();
UpdateEggModeAnimation();
gCurrentPinballGame->cyndaquilCaveSpriteX = 73;
gCurrentPinballGame->cyndaquilCaveSpriteY = 154;
gCurrentPinballGame->eggCaveState = 0;
UpdateEggHatchDisplay();
UpdateHatchCave();
RubyPond_EntityLogic();
gCurrentPinballGame->pondBumperStates[0] = 10;
@ -91,271 +64,3 @@ void RubyBoardProcess_3B_19B10(void)
}
}
}
void RequestBoardStateTransition(u8 arg0)
{
gCurrentPinballGame->boardTransitionPhase = 2;
gCurrentPinballGame->nextBoardState = arg0;
if (gCurrentPinballGame->boardState == 2)
gMain.fieldSpriteGroups[13]->available = 0;
}
void BoardStateDispatcher(void)
{
switch (gCurrentPinballGame->boardTransitionPhase)
{
case 0:
gBoardStateInitFuncs[gCurrentPinballGame->boardState]();
gCurrentPinballGame->boardTransitionPhase++;
break;
case 1:
gBoardStateUpdateFuncs[gCurrentPinballGame->boardState]();
break;
case 2:
HandleBoardStateTransitionTeardown();
gCurrentPinballGame->prevBoardState = gCurrentPinballGame->boardState;
gCurrentPinballGame->boardState = gCurrentPinballGame->nextBoardState;
gCurrentPinballGame->boardTransitionPhase = 0;
break;
}
}
void InitFieldIdle(void)
{
s16 num1;
u8 num2;
if (gCurrentPinballGame->prevBoardState > 0)
{
if (gMain.selectedField == FIELD_RUBY)
{
num1 = gCurrentPinballGame->numCompletedBonusStages / 5;
if ((num1 & 1) == 0)
{
m4aSongNumStart(MUS_FIELD_RUBY);
}
else
{
m4aSongNumStart(MUS_FIELD_RUBY2);
}
}
else
{
num1 = gCurrentPinballGame->numCompletedBonusStages / 5;
if ((num1 & 1) == 0)
{
m4aSongNumStart(MUS_FIELD_SAPPHIRE);
}
else
{
m4aSongNumStart(MUS_FIELD_SAPPHIRE2);
}
}
}
num2 = gCurrentPinballGame->prevBoardState - 1;
if (num2 > 1)
{
gCurrentPinballGame->evoArrowProgress = gCurrentPinballGame->arrowProgressPreserved;
gCurrentPinballGame->catchArrowProgress = gCurrentPinballGame->catchModeArrows;
gCurrentPinballGame->arrowProgressPreserved = 0;
gCurrentPinballGame->catchModeArrows = 0;
}
}
void UpdateFieldIdle(void)
{
if (gCurrentPinballGame->allHolesLit != 0)
{
if (gCurrentPinballGame->allHolesLitDelayTimer != 0)
{
gCurrentPinballGame->allHolesLitDelayTimer--;
}
else
{
RequestBoardStateTransition(2);
}
}
}
void HandleBoardStateTransitionTeardown(void)
{
if (gCurrentPinballGame->boardState == 2 && gCurrentPinballGame->nextBoardState > 2)
ResetCatchState(0);
if (gCurrentPinballGame->boardState > 2)
return;
if (gCurrentPinballGame->nextBoardState == 3)
{
gCurrentPinballGame->arrowProgressPreserved = gCurrentPinballGame->evoArrowProgress;
gCurrentPinballGame->catchModeArrows = gCurrentPinballGame->catchArrowProgress;
gCurrentPinballGame->evoArrowProgress = 0;
gCurrentPinballGame->catchArrowProgress = 0;
}
if (gCurrentPinballGame->nextBoardState == 4)
{
gCurrentPinballGame->arrowProgressPreserved = gCurrentPinballGame->evoArrowProgress;
gCurrentPinballGame->catchModeArrows = gCurrentPinballGame->catchArrowProgress;
gCurrentPinballGame->evoArrowProgress = 0;
gCurrentPinballGame->catchArrowProgress = 0;
}
else if (gCurrentPinballGame->nextBoardState == 6)
{
gCurrentPinballGame->catchModeArrows = gCurrentPinballGame->catchArrowProgress;
gCurrentPinballGame->arrowProgressPreserved = 0;
gCurrentPinballGame->evoArrowProgress = 0;
gCurrentPinballGame->catchArrowProgress = 0;
}
else if (gCurrentPinballGame->nextBoardState > 3)
{
gCurrentPinballGame->arrowProgressPreserved = gCurrentPinballGame->evoArrowProgress;
gCurrentPinballGame->catchModeArrows = gCurrentPinballGame->catchArrowProgress;
gCurrentPinballGame->evoArrowProgress = 0;
gCurrentPinballGame->catchArrowProgress = 0;
}
}
void UpdateRubyBoardEntityRendering(void)
{
int randNum;
ProcessBannerCameraTransition();
SelectShopDoorState();
if (gCurrentPinballGame->rampPrizeRespawnTimer != 0)
{
gCurrentPinballGame->rampPrizeRespawnTimer--;
if (gCurrentPinballGame->rampPrizeRespawnTimer == 0)
{
randNum = Random();
gCurrentPinballGame->rampPrizeType = ((randNum + gMain.systemFrameCount) % 100) + 1;
}
}
if (gCurrentPinballGame->cameraYViewport < 110)
{
UpdateNuzleafEntity();
AnimateShopDoor();
DrawRubyNuzleafPlatformSprite();
}
AnimateOneUpSprite();
if (gCurrentPinballGame->cameraYViewport < 168)
{
UpdateEggModeAnimation();
}
if (gCurrentPinballGame->cameraYViewport < 220)
{
UpdateEggHatchDisplay();
if (gCurrentPinballGame->shouldProcessWhiscash)
{
DrawWhiscash();
}
else
{
RubyPondTriBumperHandleHitAndDraw();
}
AnimateSharpedoEntity();
DrawPikachuSpinner();
}
UpdateChikoritaAttackAnimation();
if (gCurrentPinballGame->cameraYViewport > 63)
{
AnimateChikoritaSprite();
UpdateGulpinBossState();
}
if (gCurrentPinballGame->cameraYViewport > 115)
{
UpdateRubyRampPrizeGate();
}
if (gCurrentPinballGame->cameraYViewport > 130)
{
DrawSideBumperSprites();
}
UpdateSpoinkAnimation();
if (gCurrentPinballGame->cameraYViewport > 168)
{
DrawSpoinkSprite();
}
UpdateKickbackLogic();
ProcessChargeIndicator();
UpdateRubyBoardAnimations();
UpdatePortraitSpritePositions();
UpdateEvolutionShopSprite();
DrawBoardEdgeBanner();
if (gCurrentPinballGame->coinRewardAmount != 0)
{
AnimateCoinReward();
}
BonusStage_HandleModeChangeFlags();
if (gCurrentPinballGame->ballLaunchTimer != 0)
{
gCurrentPinballGame->ballLaunchTimer--;
if (gCurrentPinballGame->ballLaunchTimer == 0)
{
gCurrentPinballGame->secondaryBall = gCurrentPinballGame->ballStates;
}
}
}
void UpdateRubyBoardEntityLogic(void)
{
RubyPond_EntityLogic();
UpdateRubyCatchModeAnimation();
UpdatePikachuChargeCounter();
UpdateSideBumperAnimation();
if (gCurrentPinballGame->mainBoardCountdownTimer != 0)
{
gCurrentPinballGame->mainBoardCountdownTimer--;
}
}
//Duplicate of HandleSapphireFlipperButtonInput, with "gCurrentPinballGame->rampGateHitFlag = 1;" added in the final if statement
void HandleRubyFlipperButtonInput(void)
{
int tmp;
if (gCurrentPinballGame->newButtonActions[0])
{
if (gCurrentPinballGame->pikaKickbackTimer == 0 && gCurrentPinballGame->outLanePikaPosition != 2 &&
gCurrentPinballGame->pichuEntranceTimer == 0 && gCurrentPinballGame->kickbackFiring == 0)
{
gCurrentPinballGame->outLanePikaPosition = 0;
}
tmp = gCurrentPinballGame->holeIndicators[0];
gCurrentPinballGame->holeIndicators[0] = gCurrentPinballGame->holeIndicators[1];
gCurrentPinballGame->holeIndicators[1] = gCurrentPinballGame->holeIndicators[2];
gCurrentPinballGame->holeIndicators[2] = gCurrentPinballGame->holeIndicators[3];
gCurrentPinballGame->holeIndicators[3] = tmp;
tmp = gCurrentPinballGame->ballPowerUpLight[0];
gCurrentPinballGame->ballPowerUpLight[0] = gCurrentPinballGame->ballPowerUpLight[1];
gCurrentPinballGame->ballPowerUpLight[1] = gCurrentPinballGame->ballPowerUpLight[2];
gCurrentPinballGame->ballPowerUpLight[2] = tmp;
}
if (gCurrentPinballGame->newButtonActions[1])
{
if (gCurrentPinballGame->pikaKickbackTimer == 0 && gCurrentPinballGame->outLanePikaPosition != 2 &&
gCurrentPinballGame->pichuEntranceTimer == 0 && gCurrentPinballGame->kickbackFiring == 0)
{
gCurrentPinballGame->outLanePikaPosition = 1;
}
tmp = gCurrentPinballGame->holeIndicators[3];
gCurrentPinballGame->holeIndicators[3] = gCurrentPinballGame->holeIndicators[2];
gCurrentPinballGame->holeIndicators[2] = gCurrentPinballGame->holeIndicators[1];
gCurrentPinballGame->holeIndicators[1] = gCurrentPinballGame->holeIndicators[0];
gCurrentPinballGame->holeIndicators[0] = tmp;
tmp = gCurrentPinballGame->ballPowerUpLight[2];
gCurrentPinballGame->ballPowerUpLight[2] = gCurrentPinballGame->ballPowerUpLight[1];
gCurrentPinballGame->ballPowerUpLight[1] = gCurrentPinballGame->ballPowerUpLight[0];
gCurrentPinballGame->ballPowerUpLight[0] = tmp;
gCurrentPinballGame->rampGateHitFlag = 1;
}
}

View File

@ -0,0 +1,148 @@
#include "global.h"
#include "functions.h"
#include "functions_ruby.h"
#include "main.h"
void UpdateRubyBoardEntityRendering(void)
{
int randNum;
ProcessBannerCameraTransition();
SelectRubyShopDoorState();
if (gCurrentPinballGame->rampPrizeRespawnTimer != 0)
{
gCurrentPinballGame->rampPrizeRespawnTimer--;
if (gCurrentPinballGame->rampPrizeRespawnTimer == 0)
{
randNum = Random();
gCurrentPinballGame->rampPrizeType = ((randNum + gMain.systemFrameCount) % 100) + 1;
}
}
if (gCurrentPinballGame->cameraYViewport < 110)
{
UpdateNuzleafEntity();
AnimateRubyShopDoor();
DrawRubyNuzleafPlatformSprite();
}
AnimateOneUpSprite();
if (gCurrentPinballGame->cameraYViewport < 168)
{
UpdateEggModeAnimation();
}
if (gCurrentPinballGame->cameraYViewport < 220)
{
UpdateHatchCave();
if (gCurrentPinballGame->shouldProcessWhiscash)
{
DrawWhiscash();
}
else
{
RubyPondTriBumperHandleHitAndDraw();
}
AnimateSharpedoEntity();
DrawPikachuSpinner();
}
UpdateChikoritaAttackAnimation();
if (gCurrentPinballGame->cameraYViewport > 63)
{
AnimateChikoritaSprite();
UpdateGulpinBossState();
}
if (gCurrentPinballGame->cameraYViewport > 115)
{
UpdateRubyRampPrizeGate();
}
if (gCurrentPinballGame->cameraYViewport > 130)
{
DrawRubySideBumperSprites();
}
UpdateSpoinkAnimation();
if (gCurrentPinballGame->cameraYViewport > 168)
{
DrawSpoinkSprite();
}
UpdateKickbackLogic();
ProcessChargeIndicator();
UpdateRubyBoardAnimations();
UpdatePortraitSpritePositions();
UpdateEvolutionShopSprite();
DrawBoardEdgeBanner();
if (gCurrentPinballGame->coinRewardAmount != 0)
{
AnimateCoinReward();
}
BonusStage_HandleModeChangeFlags();
if (gCurrentPinballGame->ballLaunchTimer != 0)
{
gCurrentPinballGame->ballLaunchTimer--;
if (gCurrentPinballGame->ballLaunchTimer == 0)
{
gCurrentPinballGame->secondaryBall = gCurrentPinballGame->ballStates;
}
}
}
void UpdateRubyBoardEntityLogic(void)
{
RubyPond_EntityLogic();
UpdateRubyCatchModeAnimation();
UpdatePikachuChargeCounter();
UpdateRubySideBumperAnimation();
if (gCurrentPinballGame->mainBoardCountdownTimer != 0)
{
gCurrentPinballGame->mainBoardCountdownTimer--;
}
}
//Duplicate of HandleSapphireFlipperButtonInput, with "gCurrentPinballGame->rampGateHitFlag = 1;" added in the final if statement
void HandleRubyFlipperButtonInput(void)
{
int tmp;
if (gCurrentPinballGame->newButtonActions[0])
{
if (gCurrentPinballGame->pikaKickbackTimer == 0 && gCurrentPinballGame->outLanePikaPosition != 2 &&
gCurrentPinballGame->pichuEntranceTimer == 0 && gCurrentPinballGame->kickbackFiring == 0)
{
gCurrentPinballGame->outLanePikaPosition = 0;
}
tmp = gCurrentPinballGame->holeIndicators[0];
gCurrentPinballGame->holeIndicators[0] = gCurrentPinballGame->holeIndicators[1];
gCurrentPinballGame->holeIndicators[1] = gCurrentPinballGame->holeIndicators[2];
gCurrentPinballGame->holeIndicators[2] = gCurrentPinballGame->holeIndicators[3];
gCurrentPinballGame->holeIndicators[3] = tmp;
tmp = gCurrentPinballGame->ballPowerUpLight[0];
gCurrentPinballGame->ballPowerUpLight[0] = gCurrentPinballGame->ballPowerUpLight[1];
gCurrentPinballGame->ballPowerUpLight[1] = gCurrentPinballGame->ballPowerUpLight[2];
gCurrentPinballGame->ballPowerUpLight[2] = tmp;
}
if (gCurrentPinballGame->newButtonActions[1])
{
if (gCurrentPinballGame->pikaKickbackTimer == 0 && gCurrentPinballGame->outLanePikaPosition != 2 &&
gCurrentPinballGame->pichuEntranceTimer == 0 && gCurrentPinballGame->kickbackFiring == 0)
{
gCurrentPinballGame->outLanePikaPosition = 1;
}
tmp = gCurrentPinballGame->holeIndicators[3];
gCurrentPinballGame->holeIndicators[3] = gCurrentPinballGame->holeIndicators[2];
gCurrentPinballGame->holeIndicators[2] = gCurrentPinballGame->holeIndicators[1];
gCurrentPinballGame->holeIndicators[1] = gCurrentPinballGame->holeIndicators[0];
gCurrentPinballGame->holeIndicators[0] = tmp;
tmp = gCurrentPinballGame->ballPowerUpLight[2];
gCurrentPinballGame->ballPowerUpLight[2] = gCurrentPinballGame->ballPowerUpLight[1];
gCurrentPinballGame->ballPowerUpLight[1] = gCurrentPinballGame->ballPowerUpLight[0];
gCurrentPinballGame->ballPowerUpLight[0] = tmp;
gCurrentPinballGame->rampGateHitFlag = 1;
}
}

View File

@ -0,0 +1,907 @@
#include "global.h"
#include "m4a.h"
#include "main.h"
#include "constants/bg_music.h"
#include "constants/ruby_states.h"
extern struct SongHeader se_whiscash_splashdown;
extern const u8 gRubyBoardSharpedo_Gfx[][0x260];
extern const s16 gSharpedoAnimFrameData[][2];
extern const u16 gSharpedoSpritesheetOam[42][3][3];
extern const u8 gRubyFlashingTiles_Secondary[][0x100];
extern const u8 gChinchouBumperPalettes[];
extern const struct Vector16 gChinchouWaypointPositions[];
extern const s16 gPondBumperTransitionFrames[];
extern const u8 gLotadBumperTiles[][0x100];
extern const u8 gLotadBumperPalettes[];
extern const s16 gLotadBobOffsets[];
extern const s16 gWhiscashFramesetData[][4];
extern const s16 gWhiscashShakeOffsets[];
extern const u8 gWhiscashPalettes[];
extern const u8 gWhiscash_Gfx[][0x480];
extern const u8 gRubyBoardShopDoor_Gfx[][0x180];
extern const s16 gNuzleafAnimFrameData[50][3];
extern const s16 gNuzleafPositions[][2];
extern const u8 gRubyStageNuzleaf_Gfx[][0x280];
extern const u16 gNuzleafOamData[58][6];
#define MIN_POND_SWITCHES_BEFORE_WHISCASH_AVAILABLE 3
void UpdateNuzleafEntity(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 * dst;
s16 var0;
s16 var1;
group = &gMain.spriteGroups[71];
var0 = 0;
var1 = 0;
switch (gCurrentPinballGame->nuzleafAnimState)
{
case 0:
var0 = (gMain.systemFrameCount % 36) / 18;
var1 = var0;
break;
case 1:
gCurrentPinballGame->nuzleafFrameTimer = 0;
gCurrentPinballGame->nuzleafFrameIndex = 0;
gCurrentPinballGame->nuzleafAnimState = 2;
var1 = gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][0];
var0 = gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][2];
m4aSongNumStart(SE_UNKNOWN_0xCF);
PlayRumble(7);
gCurrentPinballGame->scoreAddedInFrame = 50000;
break;
case 2:
if (gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][1] > gCurrentPinballGame->nuzleafFrameTimer)
{
gCurrentPinballGame->nuzleafFrameTimer++;
}
else
{
gCurrentPinballGame->nuzleafFrameTimer = 0;
gCurrentPinballGame->nuzleafFrameIndex++;
if (gCurrentPinballGame->nuzleafFrameIndex == 7)
{
gCurrentPinballGame->nuzleafAnimState = 0;
gCurrentPinballGame->nuzleafFrameIndex = 0;
gCurrentPinballGame->nuzleafPositionIndex = 1;
}
}
var1 = gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][0];
var0 = gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][2];
break;
case 3:
gCurrentPinballGame->nuzleafFrameTimer = 0;
gCurrentPinballGame->nuzleafFrameIndex = 7;
gCurrentPinballGame->nuzleafAnimState = 4;
var1 = gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][0];
var0 = gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][2];
m4aSongNumStart(SE_UNKNOWN_0xCF);
PlayRumble(7);
gCurrentPinballGame->scoreAddedInFrame = 100000;
break;
case 4:
if (gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][1] > gCurrentPinballGame->nuzleafFrameTimer)
{
gCurrentPinballGame->nuzleafFrameTimer++;
}
else
{
gCurrentPinballGame->nuzleafFrameTimer = 0;
gCurrentPinballGame->nuzleafFrameIndex++;
if (gCurrentPinballGame->nuzleafFrameIndex == 18)
{
gCurrentPinballGame->nuzleafAnimState = 5;
m4aSongNumStart(SE_UNKNOWN_0xD1);
}
}
if (gCurrentPinballGame->nuzleafFrameTimer == 6)
m4aSongNumStart(SE_UNKNOWN_0xD0);
var1 = gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][0];
var0 = gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][2];
break;
case 5:
case 6:
if (gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][1] > gCurrentPinballGame->nuzleafFrameTimer)
{
gCurrentPinballGame->nuzleafFrameTimer++;
}
else
{
gCurrentPinballGame->nuzleafFrameTimer = 0;
gCurrentPinballGame->nuzleafFrameIndex++;
if (gCurrentPinballGame->nuzleafFrameIndex == 24)
gCurrentPinballGame->nuzleafFrameIndex = 18;
}
var1 = gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][0];
var0 = gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][2];
break;
case 7:
gCurrentPinballGame->nuzleafHitFlag = 0;
gCurrentPinballGame->nuzleafPositionIndex = 0;
gCurrentPinballGame->nuzleafFrameTimer = 0;
gCurrentPinballGame->nuzleafFrameIndex = 0;
gCurrentPinballGame->nuzleafAnimState = 0;
gCurrentPinballGame->nuzleafFrameIndex = 24;
var1 = gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][0];
var0 = gNuzleafAnimFrameData[gCurrentPinballGame->nuzleafFrameIndex][2];
break;
}
if (group->available)
{
group->baseX = gNuzleafPositions[gCurrentPinballGame->nuzleafPositionIndex][0] - gCurrentPinballGame->cameraXOffset;
group->baseY = gNuzleafPositions[gCurrentPinballGame->nuzleafPositionIndex][1] - gCurrentPinballGame->cameraYOffset;
DmaCopy16(3, gRubyStageNuzleaf_Gfx[gCurrentPinballGame->nuzleafGfxTileIndex], (void *)0x06014380, 0x260);
for (i = 0; i < 2; i++)
{
oamSimple = &group->oam[i];
dst = (u16 *)&gOamBuffer[oamSimple->oamId];
*dst++ = gNuzleafOamData[var1][i * 3 + 0];
*dst++ = gNuzleafOamData[var1][i * 3 + 1];
*dst++ = gNuzleafOamData[var1][i * 3 + 2];
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
}
gCurrentPinballGame->nuzleafGfxTileIndex = var0;
}
void SelectRubyShopDoorState(void)
{
if (gCurrentPinballGame->ballCatchState != 3)
{
if (gCurrentPinballGame->boardState < 3)
{
if (gCurrentPinballGame->evolutionShopActive == 0)
gCurrentPinballGame->shopDoorTargetFrame = gCurrentPinballGame->shopDoorOpenLevel & 0xF;
else
gCurrentPinballGame->shopDoorTargetFrame = 3;
}
else if (gCurrentPinballGame->boardState != 6)
{
gCurrentPinballGame->shopDoorTargetFrame = 0;
}
}
}
void AnimateRubyShopDoor(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 priority;
group = &gMain.spriteGroups[65];
if ((gCurrentPinballGame->shopDoorTargetFrame & 0xF) != gCurrentPinballGame->shopDoorCurrentFrame)
{
if (gCurrentPinballGame->shopDoorAnimDelay)
{
if (gCurrentPinballGame->shopDoorAnimDelay == 5)
{
gMain.modeChangeFlags |= MODE_CHANGE_BANNER;
gCurrentPinballGame->bannerDelayTimer = 0;
gCurrentPinballGame->bannerDisplayTimer = 3;
gCurrentPinballGame->cameraYScrollTarget = 0;
gCurrentPinballGame->cameraYAdjust = 0;
gCurrentPinballGame->cameraYScrollSpeed = 0;
gCurrentPinballGame->bannerGfxIndex = 0;
gCurrentPinballGame->bannerActive = 1;
gCurrentPinballGame->bannerPreserveBallState = 0;
m4aSongNumStart(SE_UNKNOWN_0xBD);
}
gCurrentPinballGame->shopDoorAnimDelay--;
}
else
{
if (gCurrentPinballGame->shopDoorCurrentFrame > (gCurrentPinballGame->shopDoorTargetFrame & 0xF))
{
gCurrentPinballGame->shopDoorCurrentFrame--;
gCurrentPinballGame->shopDoorAnimDelay = 4;
}
else
{
gCurrentPinballGame->shopDoorCurrentFrame++;
gCurrentPinballGame->shopDoorAnimDelay = 4;
}
DmaCopy16(3, gRubyBoardShopDoor_Gfx[gCurrentPinballGame->shopDoorCurrentFrame], (void *)0x06013180, 0x180);
}
}
if (gCurrentPinballGame->shopDoorCurrentFrame < 3)
priority = 3;
else
priority = 2;
group->baseX = 208 - gCurrentPinballGame->cameraXOffset;
group->baseY = 80 - gCurrentPinballGame->cameraYOffset;
for (i = 0; i < 2; i++)
{
oamSimple = &gMain.spriteGroups[65].oam[i];
gOamBuffer[oamSimple->oamId].priority = priority;
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
void DrawWhiscash(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 var0;
const s16 *var1;
group = &gMain.spriteGroups[63];
var1 = gWhiscashFramesetData[gCurrentPinballGame->whiscashFrameIx];
if (group->available)
{
var0 = var1[0];
DmaCopy16(3, gWhiscashPalettes + gCurrentPinballGame->activePaletteIndex * 0x60, (void *)0x05000320, 0x20);
DmaCopy16(3, gWhiscash_Gfx[var0], (void *)0x06014680, 0x460);
gCurrentPinballGame->rubyBumperCollisionPosition[0].x = -248;
gCurrentPinballGame->rubyBumperCollisionPosition[0].y = -316;
group->baseX = var1[2] + 124u - gCurrentPinballGame->cameraXOffset;
group->baseY = var1[3] + 150u - gCurrentPinballGame->cameraYOffset;
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
if (var0 == 4 || var0 == 10)
gCurrentPinballGame->whiscashInvulnerable = 0;
else
gCurrentPinballGame->whiscashInvulnerable = 1;
}
}
//Ruby Pond
void RubyPond_EntityLogic(void)
{
s16 i;
u16 angle;
u16 angle2;
s16 var1;
s16 frameDecidedNextPondState;
struct Vector32 tempVec;
struct Vector32 tempVec2;
int squaredMagnitude;
if (gCurrentPinballGame->shouldProcessWhiscash)
{
// If board is currently in one of the modes (catch/etc) force reset to the 3 chinchou
if (gCurrentPinballGame->boardState > 2)
gCurrentPinballGame->rubyPondContentsChanging = TRUE;
// Don't immediately force change state if Wishcash is actively doing something
if (gCurrentPinballGame->rubyPondContentsChanging)
{
if (gCurrentPinballGame->whiscashState < WHISCASH_STATE_ABSORB_ZONE_HIT)
{
gCurrentPinballGame->whiscashState = WHISCASH_STATE_LEAVING;
gCurrentPinballGame->whiscashFrameIx = WHISCASH_FRAME_LEAVING-1;
gCurrentPinballGame->whiscashStateTimer = 0;
}
gCurrentPinballGame->rubyPondContentsChanging = FALSE;
}
switch (gCurrentPinballGame->whiscashState)
{
case WHISCASH_STATE_ARRIVAL:
if (gWhiscashFramesetData[gCurrentPinballGame->whiscashFrameIx][1] > gCurrentPinballGame->whiscashStateTimer)
{
gCurrentPinballGame->whiscashStateTimer++;
}
else
{
gCurrentPinballGame->whiscashStateTimer = 0;
gCurrentPinballGame->whiscashFrameIx++;
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_SITTING)
gCurrentPinballGame->whiscashState = WHISCASH_STATE_SITTING;
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_SPLASH)
m4aSongNumStart(SE_WHISCASH_EMERGE_SPLASH);
}
break;
case WHISCASH_STATE_SITTING:
// Alternates between frame 4 and 5
gCurrentPinballGame->whiscashFrameIx = (gCurrentPinballGame->whiscashStateTimer % 44) / 22 + 4;
gCurrentPinballGame->whiscashStateTimer++;
break;
case WHISCASH_STATE_ABSORB_ZONE_HIT:
gCurrentPinballGame->whiscashFrameIx = WHISCASH_FRAME_ABSORB_BALL_START;
gCurrentPinballGame->whiscashStateTimer = 0;
gCurrentPinballGame->whiscashState = WHISCASH_STATE_ABSORBING;
gCurrentPinballGame->ball->oamPriority = 0;
gCurrentPinballGame->scoreAddedInFrame = 5000;
m4aSongNumStart(SE_WHISCASH_CATCH_BALL);
PlayRumble(7);
break;
case WHISCASH_STATE_ABSORBING:
if (gWhiscashFramesetData[gCurrentPinballGame->whiscashFrameIx][1] > gCurrentPinballGame->whiscashStateTimer)
{
gCurrentPinballGame->whiscashStateTimer++;
}
else
{
gCurrentPinballGame->whiscashStateTimer = 0;
gCurrentPinballGame->whiscashFrameIx++;
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_BALL_HELD_SUNK+1)
{
gCurrentPinballGame->whiscashFrameIx = WHISCASH_FRAME_BALL_HELD_SUNK;
gCurrentPinballGame->whiscashStateTimer = 65;
gCurrentPinballGame->whiscashState = WHISCASH_STATE_TO_SPHEAL_BOARD;
}
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_LEAVING)
m4aSongNumStart(SE_WHISCASH_LEAVE_BURBLE);
}
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_ABSORB_BALL_START)
{
gCurrentPinballGame->ball->spinAngle += 64;
gCurrentPinballGame->ball->positionQ8.x = 0x8900;
gCurrentPinballGame->ball->positionQ8.y = 0xBD00;
gCurrentPinballGame->ball->velocity.x = 0;
gCurrentPinballGame->ball->velocity.y = 0;
}
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_ABSORB_BALL_START+1)
{
gCurrentPinballGame->ball->spinAngle += 64;
gCurrentPinballGame->ball->positionQ8.x = 0x8C00;
gCurrentPinballGame->ball->positionQ8.y = 0xB700;
gCurrentPinballGame->ball->velocity.x = 0;
gCurrentPinballGame->ball->velocity.y = 0;
}
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_ABSORB_BALL_START+2)
gCurrentPinballGame->ball->ballHidden = 1;
break;
case WHISCASH_STATE_TO_SPHEAL_BOARD:
gCurrentPinballGame->startButtonDisabled = 1;
if (gCurrentPinballGame->whiscashStateTimer == 65)
{
m4aSongNumStart(SE_WARP);
gMain.blendControl = 0x9E;
}
if (gCurrentPinballGame->whiscashStateTimer)
{
gCurrentPinballGame->whiscashStateTimer--;
gMain.blendBrightness = 16 - gCurrentPinballGame->whiscashStateTimer / 4;
if (gCurrentPinballGame->whiscashStateTimer == 0)
{
gCurrentPinballGame->nextBonusField = FIELD_SPHEAL;
gCurrentPinballGame->bonusReturnState = 1;
gCurrentPinballGame->arrowProgressPreserved = gCurrentPinballGame->evoArrowProgress;
gCurrentPinballGame->catchModeArrows = gCurrentPinballGame->catchArrowProgress;
TransitionToBonusField();
}
}
break;
case WHISCASH_STATE_INIT_RETURN_FROM_BONUS: //from board initialization
gCurrentPinballGame->whiscashFrameIx = WHISCASH_FRAME_DELIVER_BALL_START;
gCurrentPinballGame->whiscashStateTimer = 0;
gCurrentPinballGame->whiscashState = WHISCASH_STATE_RISE_SPIT_LEAVE;
gCurrentPinballGame->ball->oamPriority = 0;
break;
case WHISCASH_STATE_RISE_SPIT_LEAVE:
if (gWhiscashFramesetData[gCurrentPinballGame->whiscashFrameIx][1] > gCurrentPinballGame->whiscashStateTimer)
{
gCurrentPinballGame->whiscashStateTimer++;
}
else
{
gCurrentPinballGame->whiscashStateTimer = 0;
gCurrentPinballGame->whiscashFrameIx++;
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_DELIVER_BALL_END+1)
{
gCurrentPinballGame->whiscashFrameIx = WHISCASH_FRAME_SUBMERGED;
gCurrentPinballGame->whiscashState = WHISCASH_STATE_CLEANUP;
}
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_SPITBALL + 1)
{
gCurrentPinballGame->ball->spinAngle -= 64;
gCurrentPinballGame->ball->positionQ8.x = 0x8300;
gCurrentPinballGame->ball->positionQ8.y = 0xC700;
gCurrentPinballGame->ball->velocity.x = -120;
gCurrentPinballGame->ball->velocity.y = 210;
gCurrentPinballGame->ball->oamPriority = 3;
}
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_EMERGING)
m4aSongNumStart(SE_WHISCASH_EMERGE_SPLASH);
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_SPITBALL + 7) {
m4aSongNumStart(SE_WHISCASH_LEAVE_BURBLE);
}
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_SPITBALL)
{
m4aSongNumStart(SE_WHISCASH_SPIT_BALL);
}
}
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_SPITBALL)
{
gCurrentPinballGame->ball->ballHidden = 0;
gCurrentPinballGame->ball->spinAngle -= 64;
gCurrentPinballGame->ball->positionQ8.x = 0x8500;
gCurrentPinballGame->ball->positionQ8.y = 0xC000;
gCurrentPinballGame->ball->velocity.x = 0;
gCurrentPinballGame->ball->velocity.y = 0;
}
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_SPITBALL+2)
gCurrentPinballGame->ballFrozenState = 0;
break;
case WHISCASH_STATE_HIT:
gCurrentPinballGame->whiscashFrameIx = WHISCASH_FRAME_HIT;
gCurrentPinballGame->whiscashStateTimer = 0;
gCurrentPinballGame->whiscashState = WHISCASH_STATE_ANGRY;
gCurrentPinballGame->scoreAddedInFrame = 10;
m4aSongNumStart(SE_RUBY_BUMPER_HIT);
PlayRumble(7);
if (gCurrentPinballGame->saverTimeRemaining)
gCurrentPinballGame->saverTimeRemaining = 1;
break;
case WHISCASH_STATE_ANGRY:
if (gWhiscashFramesetData[gCurrentPinballGame->whiscashFrameIx][1] > gCurrentPinballGame->whiscashStateTimer)
{
gCurrentPinballGame->whiscashStateTimer++;
}
else
{
gCurrentPinballGame->whiscashStateTimer = 0;
gCurrentPinballGame->whiscashFrameIx++;
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_GONE_AFTER_HIT+1)
{
gCurrentPinballGame->whiscashFrameIx = WHISCASH_FRAME_SUBMERGED;
gCurrentPinballGame->whiscashState = WHISCASH_STATE_CLEANUP;
}
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_LEAVING_AFTER_HIT)
m4aSongNumStart(SE_WHISCASH_LEAVE_BURBLE);
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_HIT+2)
m4aSongNumStart(SE_WHISCASH_EARTHQUAKE);
}
// Heavy shaking starts
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_GONE_AFTER_HIT)
{
gCurrentPinballGame->screenShakeX = gWhiscashShakeOffsets[gCurrentPinballGame->whiscashStateTimer % 8];
if (gCurrentPinballGame->whiscashStateTimer % 4 == 0)
MPlayStart(&gMPlayInfo_SE3, &se_whiscash_splashdown);
if (gCurrentPinballGame->whiscashStateTimer % 10 == 0)
PlayRumble(12);
}
break;
case WHISCASH_STATE_LEAVING: //Early Exit (mode started)
if (gWhiscashFramesetData[gCurrentPinballGame->whiscashFrameIx][1] > gCurrentPinballGame->whiscashStateTimer)
{
gCurrentPinballGame->whiscashStateTimer++;
}
else
{
gCurrentPinballGame->whiscashStateTimer = 0;
gCurrentPinballGame->whiscashFrameIx++;
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_BALL_HELD_SUNK+1)
{
gCurrentPinballGame->whiscashFrameIx = WHISCASH_FRAME_SUBMERGED;
gCurrentPinballGame->whiscashState = WHISCASH_STATE_CLEANUP;
}
if (gCurrentPinballGame->whiscashFrameIx == WHISCASH_FRAME_LEAVING)
m4aSongNumStart(SE_WHISCASH_LEAVE_BURBLE);
}
break;
case WHISCASH_STATE_CLEANUP:
gCurrentPinballGame->shouldProcessWhiscash = FALSE;
gCurrentPinballGame->whiscashFrameIx = WHISCASH_FRAME_SUBMERGED;
gCurrentPinballGame->whiscashStateTimer = 0;
gCurrentPinballGame->rubyPondContentsChanging = TRUE;
gCurrentPinballGame->rubyPondChangeTimer = 64;
gCurrentPinballGame->screenShakeX = 0;
break;
}
}
else
{
if (gCurrentPinballGame->rubyPondContentsChanging)
{
if (gCurrentPinballGame->rubyPondChangeTimer < 144)
{
gCurrentPinballGame->pondBumperStates[0] = gPondBumperTransitionFrames[gCurrentPinballGame->rubyPondChangeTimer / 8];
gCurrentPinballGame->pondBumperStates[1] = gCurrentPinballGame->pondBumperStates[0];
gCurrentPinballGame->pondBumperStates[2] = gCurrentPinballGame->pondBumperStates[0];
}
else
{
gCurrentPinballGame->rubyPondContentsChanging = FALSE;
}
if (gCurrentPinballGame->pondBumperStates[0] == 10)
{
if (gCurrentPinballGame->rubyPondChangeTimer % 8 == 0 && gCurrentPinballGame->rubyPondChangeTimer / 8 == 8)
{
// Can't switch to Whiscash if in a catch/hatch/etc state, or if it hasn't yet hit a threshold
// of pond states first.
gCurrentPinballGame->pondSwitchesSinceLastWhiscash++;
if (gCurrentPinballGame->pondSwitchesSinceLastWhiscash < MIN_POND_SWITCHES_BEFORE_WHISCASH_AVAILABLE ||
gCurrentPinballGame->boardState > 2)
{
frameDecidedNextPondState = (gMain.systemFrameCount % 5) + 1;
if (gCurrentPinballGame->rubyPondState == frameDecidedNextPondState)
gCurrentPinballGame->rubyPondState = ((gMain.systemFrameCount + 1) % 5) + 1;
else
gCurrentPinballGame->rubyPondState = frameDecidedNextPondState;
}
else
{
frameDecidedNextPondState = (gMain.systemFrameCount % 6) + 1;
if (gCurrentPinballGame->rubyPondState == frameDecidedNextPondState)
gCurrentPinballGame->rubyPondState = ((gMain.systemFrameCount + 1) % 6) + 1;
else
gCurrentPinballGame->rubyPondState = frameDecidedNextPondState;
}
if (gCurrentPinballGame->forcePondToWhiscash)
{
gCurrentPinballGame->forcePondToWhiscash = FALSE;
gCurrentPinballGame->rubyPondState = RUBY_POND_STATE_WHISCASH;
}
if (gCurrentPinballGame->rubyPondState == RUBY_POND_STATE_WHISCASH)
{
gCurrentPinballGame->shouldProcessWhiscash = TRUE;
gCurrentPinballGame->whiscashState = WHISCASH_STATE_ARRIVAL;
gCurrentPinballGame->whiscashStateTimer = 0;
gCurrentPinballGame->whiscashFrameIx = WHISCASH_FRAME_SUBMERGED;
gCurrentPinballGame->rubyPondContentsChanging = FALSE;
gCurrentPinballGame->pondSwitchesSinceLastWhiscash = 0;
}
if (gCurrentPinballGame->rubyPondState == RUBY_POND_STATE_CHINCHOU_SINGLE_CLOCKWISE)
{
gCurrentPinballGame->rubyBumperLogicPosition[0].x = gChinchouWaypointPositions[0].x * 10;
gCurrentPinballGame->rubyBumperLogicPosition[0].y = gChinchouWaypointPositions[0].y * 10;
}
}
}
gCurrentPinballGame->rubyPondChangeTimer++;
if (gCurrentPinballGame->rubyPondChangeTimer == 32)
m4aSongNumStart(SE_RUBY_BUMPER_LEAVES);
switch (gCurrentPinballGame->rubyPondState)
{
case RUBY_POND_STATE_CHINCHOU_STAGGERED:
case RUBY_POND_STATE_CHINCHOU_CLOCKWISE:
case RUBY_POND_STATE_CHINCHOU_COUNTERCLOCKWISE:
case RUBY_POND_STATE_CHINCHOU_ROWS:
if (gCurrentPinballGame->rubyPondChangeTimer == 102)
m4aSongNumStart(SE_RUBY_BUMPER_EMERGES);
if (gCurrentPinballGame->rubyPondChangeTimer == 116)
m4aSongNumStart(SE_RUBY_BUMPER_EMERGES);
if (gCurrentPinballGame->rubyPondChangeTimer == 130)
m4aSongNumStart(SE_RUBY_BUMPER_EMERGES);
break;
case RUBY_POND_STATE_LOTAD:
if (gCurrentPinballGame->rubyPondChangeTimer == 102)
m4aSongNumStart(SE_RUBY_BUMPER_EMERGES);
if (gCurrentPinballGame->rubyPondChangeTimer == 118)
m4aSongNumStart(SE_RUBY_BUMPER_EMERGES);
if (gCurrentPinballGame->rubyPondChangeTimer == 134)
m4aSongNumStart(SE_RUBY_BUMPER_EMERGES);
break;
case RUBY_POND_STATE_CHINCHOU_SINGLE_CLOCKWISE:
if (gCurrentPinballGame->rubyPondChangeTimer == 104)
m4aSongNumStart(SE_RUBY_BUMPER_EMERGES);
break;
}
}
}
switch (gCurrentPinballGame->rubyPondState)
{
case RUBY_POND_STATE_CHINCHOU_STAGGERED:
gCurrentPinballGame->rubyBumperLogicPosition[0].x = 1250;
gCurrentPinballGame->rubyBumperLogicPosition[0].y = 1270;
gCurrentPinballGame->rubyBumperLogicPosition[2].x = 1600;
gCurrentPinballGame->rubyBumperLogicPosition[2].y = 1360;
gCurrentPinballGame->rubyBumperLogicPosition[1].x = 1370;
gCurrentPinballGame->rubyBumperLogicPosition[1].y = 1610;
break;
case RUBY_POND_STATE_CHINCHOU_CLOCKWISE:
for (i = 0; i < 3; i++)
{
angle = (gCurrentPinballGame->globalAnimFrameCounter & 0x7F) * 0x200 + i * 0x5555;
var1 = (gCurrentPinballGame->globalAnimFrameCounter % 60) - 30;
if (var1 < 0)
var1 = -var1;
gCurrentPinballGame->bumperOrbitRadius = 180;
gCurrentPinballGame->rubyBumperLogicPosition[i].x = (gCurrentPinballGame->bumperOrbitRadius * Cos(angle)) / 20000 + 1380;
gCurrentPinballGame->rubyBumperLogicPosition[i].y = (gCurrentPinballGame->bumperOrbitRadius * Sin(angle)) / 20000 + 1500;
}
break;
case RUBY_POND_STATE_CHINCHOU_COUNTERCLOCKWISE:
for (i = 0; i < 3; i++)
{
angle = 10000 - ((gCurrentPinballGame->globalAnimFrameCounter & 0x7F) * 0x200 + i * 0x5555);
var1 = (gCurrentPinballGame->globalAnimFrameCounter % 60) - 30;
if (var1 < 0)
var1 = -var1;
gCurrentPinballGame->bumperOrbitRadius = 180;
gCurrentPinballGame->rubyBumperLogicPosition[i].x = (gCurrentPinballGame->bumperOrbitRadius * Cos(angle)) / 20000 + 1380;
gCurrentPinballGame->rubyBumperLogicPosition[i].y = (gCurrentPinballGame->bumperOrbitRadius * Sin(angle)) / 20000 + 1500;
}
break;
case RUBY_POND_STATE_CHINCHOU_ROWS:
for (i = 0; i < 2; i++)
{
var1 = 23 - (gCurrentPinballGame->globalAnimFrameCounter % 46);
if (var1 < 0)
var1 = -var1;
gCurrentPinballGame->rubyBumperLogicPosition[i + 1].x = (i * 33 + 121) * 10;
gCurrentPinballGame->rubyBumperLogicPosition[i + 1].y = var1 * 5 + 1340;
}
var1 = 23 - (gCurrentPinballGame->globalAnimFrameCounter + 23) % 46;
if (var1 < 0)
var1 = 0-var1;
gCurrentPinballGame->rubyBumperLogicPosition[0].x = 1370;
gCurrentPinballGame->rubyBumperLogicPosition[0].y = var1 * 5 + 1620;
break;
case RUBY_POND_STATE_LOTAD:
gCurrentPinballGame->rubyBumperLogicPosition[0].x = 1210;
gCurrentPinballGame->rubyBumperLogicPosition[0].y = gLotadBobOffsets[(gCurrentPinballGame->globalAnimFrameCounter % 60) / 10] + 1300;
gCurrentPinballGame->rubyBumperLogicPosition[1].x = 1600;
gCurrentPinballGame->rubyBumperLogicPosition[1].y = gLotadBobOffsets[((gCurrentPinballGame->globalAnimFrameCounter + 20) % 60) / 10] + 1410;
gCurrentPinballGame->rubyBumperLogicPosition[2].x = 1370;
gCurrentPinballGame->rubyBumperLogicPosition[2].y = gLotadBobOffsets[((gCurrentPinballGame->globalAnimFrameCounter + 40) % 60) / 10] + 1660;
break;
case RUBY_POND_STATE_CHINCHOU_SINGLE_CLOCKWISE:
tempVec.x = gChinchouWaypointPositions[gCurrentPinballGame->chinchouWaypointTarget].x * 10 - gCurrentPinballGame->rubyBumperLogicPosition[0].x;
tempVec.y = gChinchouWaypointPositions[gCurrentPinballGame->chinchouWaypointTarget].y * 10 - gCurrentPinballGame->rubyBumperLogicPosition[0].y;
squaredMagnitude = (tempVec.x * tempVec.x) + (tempVec.y * tempVec.y);
angle2 = ArcTan2(tempVec.x, -tempVec.y);
tempVec2.x = (Cos(angle2) * 7) / 20000;
tempVec2.y = (Sin(angle2) * -7) / 20000;
gCurrentPinballGame->rubyBumperLogicPosition[0].x += tempVec2.x;
gCurrentPinballGame->rubyBumperLogicPosition[0].y += tempVec2.y;
if (squaredMagnitude < 2500)
gCurrentPinballGame->chinchouWaypointTarget = Random() % 4;
// moved off screen
gCurrentPinballGame->rubyBumperLogicPosition[1].x = 0;
gCurrentPinballGame->rubyBumperLogicPosition[1].y = -300;
gCurrentPinballGame->rubyBumperLogicPosition[2].x = 0;
gCurrentPinballGame->rubyBumperLogicPosition[2].y = -300;
break;
case RUBY_POND_STATE_WHISCASH:
// moved off screen
gCurrentPinballGame->rubyBumperLogicPosition[0].x = 0;
gCurrentPinballGame->rubyBumperLogicPosition[0].y = -300;
gCurrentPinballGame->rubyBumperLogicPosition[1].x = 0;
gCurrentPinballGame->rubyBumperLogicPosition[1].y = -300;
gCurrentPinballGame->rubyBumperLogicPosition[2].x = 0;
gCurrentPinballGame->rubyBumperLogicPosition[2].y = -300;
break;
}
}
// Ruby pond bumpers Handle Hit and draw
void RubyPondTriBumperHandleHitAndDraw(void)
{
s16 i;
s16 j;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 var0;
if (gCurrentPinballGame->bumperHitCountdown > 0)
{
if (gCurrentPinballGame->bumperHitCountdown == 2)
{
gCurrentPinballGame->scoreAddedInFrame = 500;
m4aSongNumStart(SE_RUBY_BUMPER_HIT);
PlayRumble(7);
if (gCurrentPinballGame->boardState == 4 && gCurrentPinballGame->boardSubState == 5 && gCurrentPinballGame->hatchTilesBumperAcknowledged < 6)
{
if (gCurrentPinballGame->hatchTilesBumperAcknowledged == 0)
gCurrentPinballGame->hatchTilesBumperAcknowledged = 1;
else if (gCurrentPinballGame->hatchTilesBumperAcknowledged == 1)
gCurrentPinballGame->hatchTilesBumperAcknowledged = 3;
else
gCurrentPinballGame->hatchTilesBumperAcknowledged = 6;
if (gCurrentPinballGame->hatchTilesBumperAcknowledged == 6)
{
if (gCurrentPinballGame->hatchTilesBoardAcknowledged == 0)
{
if (gCurrentPinballGame->rubyPondState == RUBY_POND_STATE_LOTAD)
{
gMain.modeChangeFlags |= MODE_CHANGE_BANNER;
gCurrentPinballGame->bannerDelayTimer = 50;
gCurrentPinballGame->bannerDisplayTimer = 600;
gCurrentPinballGame->cameraYScrollTarget = 236;
gCurrentPinballGame->cameraYAdjust = 0;
gCurrentPinballGame->cameraYScrollSpeed = 4;
gCurrentPinballGame->bannerGfxIndex = 6;
gCurrentPinballGame->bannerActive = 1;
gCurrentPinballGame->bannerPreserveBallState = 0;
gCurrentPinballGame->bannerDisplayDuration = 80;
gCurrentPinballGame->bannerSlidePosition = -2500;
gCurrentPinballGame->bannerSlideTimer = 50;
gCurrentPinballGame->bannerSlideVelocity = 0;
DmaCopy16(3, gModeBannerTilemaps[6], (void *)0x06015800, 0x2400);
DmaCopy16(3, gModeBannerPalettes[6], (void *)0x050003C0, 0x20);
}
else
{
gMain.modeChangeFlags |= MODE_CHANGE_BANNER;
gCurrentPinballGame->bannerDelayTimer = 50;
gCurrentPinballGame->bannerDisplayTimer = 600;
gCurrentPinballGame->cameraYScrollTarget = 236;
gCurrentPinballGame->cameraYAdjust = 0;
gCurrentPinballGame->cameraYScrollSpeed = 4;
gCurrentPinballGame->bannerGfxIndex = 1;
gCurrentPinballGame->bannerActive = 1;
gCurrentPinballGame->bannerPreserveBallState = 0;
gCurrentPinballGame->bannerDisplayDuration = 80;
gCurrentPinballGame->bannerSlidePosition = -2500;
gCurrentPinballGame->bannerSlideTimer = 50;
gCurrentPinballGame->bannerSlideVelocity = 0;
DmaCopy16(3, gModeBannerTilemaps[1], (void *)0x06015800, 0x2400);
DmaCopy16(3, gModeBannerPalettes[1], (void *)0x050003C0, 0x20);
}
gMain.blendControl = 0xCE;
}
}
}
gCurrentPinballGame->pondEntitySpriteFlag++;
gCurrentPinballGame->bumperHitsSinceReset++;
}
gCurrentPinballGame->bumperHitCountdown--;
}
group = &gMain.spriteGroups[62];
if (gCurrentPinballGame->rubyPondState == RUBY_POND_STATE_LOTAD)
{
for (i = 0; i < 3; i++)
{
if (gCurrentPinballGame->pondBumperStates[i])
{
if (gCurrentPinballGame->pondBumperStates[i] > 100)
{
gCurrentPinballGame->pondBumperStates[i]--;
if (gCurrentPinballGame->pondBumperStates[i] == 100)
gCurrentPinballGame->pondBumperStates[i] = 0;
var0 = 8;
}
else
{
var0 = gCurrentPinballGame->pondBumperStates[i];
}
}
else
{
var0 = (gCurrentPinballGame->globalAnimFrameCounter % 50) / 25;
}
DmaCopy16(3, gLotadBumperTiles[var0], (void *)0x06012E80 + i * 0x100, 0x100);
}
DmaCopy16(3, gLotadBumperPalettes + gCurrentPinballGame->activePaletteIndex * 0x60, (void *)0x05000320, 0x20);
}
else // chinchou
{
for (i = 0; i < 3; i++)
{
if (gCurrentPinballGame->pondBumperStates[i])
{
if (gCurrentPinballGame->pondBumperStates[i] > 100)
{
var0 = 9 - gCurrentPinballGame->pondBumperStates[i] / 105;
gCurrentPinballGame->pondBumperStates[i]--;
if (gCurrentPinballGame->pondBumperStates[i] == 100)
gCurrentPinballGame->pondBumperStates[i] = 0;
}
else
{
var0 = gCurrentPinballGame->pondBumperStates[i];
}
}
else
{
var0 = (gCurrentPinballGame->globalAnimFrameCounter % 50) / 25;
}
DmaCopy16(3, gRubyFlashingTiles_Secondary[var0], (void *)0x06012E80 + i * 0x100, 0x100);
}
DmaCopy16(3, gChinchouBumperPalettes + gCurrentPinballGame->activePaletteIndex * 0x60, (void *)0x05000320, 0x20);
}
// Draw Bumpers: Lotad/chinchou
for (i = 0; i < 3; i++)
{
group->baseX = gCurrentPinballGame->rubyBumperLogicPosition[i].x / 10 - gCurrentPinballGame->cameraXOffset - 8;
group->baseY = gCurrentPinballGame->rubyBumperLogicPosition[i].y / 10 - gCurrentPinballGame->cameraYOffset - 4;
gCurrentPinballGame->rubyBumperCollisionPosition[i].x = (-(gCurrentPinballGame->rubyBumperLogicPosition[i].x / 10) + 8) * 2;
gCurrentPinballGame->rubyBumperCollisionPosition[i].y = (-(gCurrentPinballGame->rubyBumperLogicPosition[i].y / 10) + 7) * 2;
if (group->baseY < -40)
group->baseY = -40;
//sprites have a left/right half.
for (j = 0; j < 2; j++)
{
oamSimple = &group->oam[j + i * 2];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
}
void AnimateSharpedoEntity(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 * dst;
const u16 * src;
s16 index;
s16 var0;
index = (gMain.systemFrameCount % 55) / 11;
group = &gMain.spriteGroups[61];
DmaCopy16(3, gRubyBoardSharpedo_Gfx[gCurrentPinballGame->catchHoleTileVariant], (void *)0x06012C20, 0x260);
if (gCurrentPinballGame->catchHoleAnimFrame)
index = gCurrentPinballGame->catchHoleAnimFrame;
var0 = gSharpedoAnimFrameData[index][0];
gCurrentPinballGame->catchHoleTileVariant = gSharpedoAnimFrameData[index][1];
group->baseX = 179 - gCurrentPinballGame->cameraXOffset;
group->baseY = 174 - gCurrentPinballGame->cameraYOffset;
for (i = 0; i < 3; i++)
{
oamSimple = &group->oam[i];
dst = (u16*)&gOamBuffer[oamSimple->oamId];
src = gSharpedoSpritesheetOam[var0][i];
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
}

View File

@ -24,8 +24,8 @@ void SapphireBoardProcess_3A_326F4(void)
gCurrentPinballGame->chargeIndicatorScaleX = 0x100;
gCurrentPinballGame->chargeIndicatorScaleY = 0x100;
InitSapphireEggCaveState();
UpdateSapphireEggCaveAnimation();
InitSapphireEggHatchState();
UpdateSapphireEggHatchAnimation();
UpdateSapphireShopSignAnimation();
DrawSapphireShopSignSprite();
UpdatePelipperPondEntity();
@ -60,13 +60,14 @@ void UpdateSapphireBoardEntityRendering(void)
if (gCurrentPinballGame->cameraYViewport < 0x5a)
{
UpdateSapphireEggCaveAnimation();
UpdateSapphireHoleLetterSystem();
UpdateSapphireEggHatchAnimation();
UpdateSapphireEggMachine();
}
if (gCurrentPinballGame->boardState < 3)
{
if (gCurrentPinballGame->holeLetterCount == 3 && gCurrentPinballGame->holeLetterSystemState == 0)
if (gCurrentPinballGame->sapphireHatchMachineFrameIx == 3 &&
gCurrentPinballGame->sapphireHatchMachineState == 0)
{
gCurrentPinballGame->catchArrowPaletteActive = 1;
}
@ -103,7 +104,7 @@ void UpdateSapphireBoardEntityRendering(void)
if (0x76 < gCurrentPinballGame->cameraYViewport)
{
DrawZigzagoonAndShockWall();
DrawZigzagoonAndRouletteStopPrompt();
DrawSapphireSeedotAndBasketSprites();
}
@ -133,7 +134,7 @@ void UpdateSapphireBoardEntityLogic(void)
gCurrentPinballGame->mainBoardCountdownTimer--;
UpdateZigzagoonEntity();
DecrementFieldTimer();
DecrementPelipperTimer();
UpdateSapphireShopSignAnimation();
if (!(gMain.modeChangeFlags & MODE_CHANGE_END_OF_GAME))

View File

@ -338,7 +338,6 @@ void ComputeFlipperBounce(struct Vector16* arg0, struct Vector16* arg1, s16 arg2
}
}
void ComputeWallReflection(u16 arg0, struct Vector16 *arg1, struct Vector16 *arg2)
{
u16 angleOfFlippedArg1;
@ -742,7 +741,6 @@ u16 CheckFlipperCollision(struct Vector16* arg0, u16* arg1)
return res;
}
u16 CheckCatchTargetCollision(struct Vector16 *arg0, u16 *arg1)
{
struct Vector16 vec1;
@ -832,7 +830,6 @@ u16 CheckCatchTargetCollision(struct Vector16 *arg0, u16 *arg1)
return res;
}
void ProcessBonusTrapPhysics(void)
{
struct Vector16 vec1;
@ -991,4 +988,4 @@ void ComputeFlipperLaunchVelocity(s32 arg0, s16 arg1, struct Vector16* arg2, u16
arg2->x = scale * Cos(angle2) / 20000;
arg2->y = -scale * Sin(angle2) / 20000;
}
}
}

View File

@ -58,7 +58,7 @@ void MainBoardProcess_7B_12524(void)
SetMatrixScale(currentBallState->scale, currentBallState->scale, 0);
spriteGroup->baseX = -(gCurrentPinballGame->cameraBaseX + 7) + currentBallState->positionQ0.x - gCurrentPinballGame->screenShakeX;
spriteGroup->baseY = -(gCurrentPinballGame->cameraBaseY + 7) + currentBallState->positionQ0.y - gCurrentPinballGame->cameraScrollOffset - gCurrentPinballGame->cameraYAdjust + gCurrentPinballGame->sapphireSpriteTimer;
spriteGroup->baseY = -(gCurrentPinballGame->cameraBaseY + 7) + currentBallState->positionQ0.y - gCurrentPinballGame->cameraScrollOffset - gCurrentPinballGame->cameraYAdjust + gCurrentPinballGame->spoinkPullbackYDistance;
currentBallState->screenPosition.x = spriteGroup->baseX;
currentBallState->screenPosition.y = spriteGroup->baseY;
@ -100,7 +100,7 @@ void MainBoardProcess_7B_12524(void)
SetMatrixScale(currentBallState->scale, currentBallState->scale, 0);
spriteGroup->baseX = -(gCurrentPinballGame->cameraBaseX + 7) + currentBallState->positionQ0.x - gCurrentPinballGame->screenShakeX;
spriteGroup->baseY = -(gCurrentPinballGame->cameraBaseY + 7) + currentBallState->positionQ0.y - gCurrentPinballGame->cameraScrollOffset - gCurrentPinballGame->cameraYAdjust + gCurrentPinballGame->sapphireSpriteTimer;
spriteGroup->baseY = -(gCurrentPinballGame->cameraBaseY + 7) + currentBallState->positionQ0.y - gCurrentPinballGame->cameraScrollOffset - gCurrentPinballGame->cameraYAdjust + gCurrentPinballGame->spoinkPullbackYDistance;
currentBallState->screenPosition.x = spriteGroup->baseX;
currentBallState->screenPosition.y = spriteGroup->baseY;

View File

@ -0,0 +1,148 @@
#include "global.h"
#include "m4a.h"
#include "main.h"
#include "constants/bg_music.h"
extern struct SongHeader se_pika_full_charge_1_up;
extern struct SongHeader se_pika_spinner_clack;
void UpdatePikachuChargeCounter(void)
{
if (gCurrentPinballGame->pikaChargeTarget != gCurrentPinballGame->pikaChargeProgress)
{
gCurrentPinballGame->pikaChargeProgress += 2;
gCurrentPinballGame->chargeFillValue = gCurrentPinballGame->pikaChargeProgress / 14;
gCurrentPinballGame->fullChargeSlideAnimTimer = 80;
gCurrentPinballGame->chargeIndicatorScaleX = 256;
gCurrentPinballGame->chargeIndicatorScaleY = 256;
if (gCurrentPinballGame->chargeFillValue == 11)
gCurrentPinballGame->chargeFillAnimTimer = 120;
if (gCurrentPinballGame->chargeFillValue > 11)
{
gCurrentPinballGame->chargeFillValue = 12;
gCurrentPinballGame->fullChargeSlideAnimTimer = 120;
gCurrentPinballGame->chargeIndicatorScaleX = 256;
gCurrentPinballGame->chargeIndicatorScaleY = 256;
}
if (gCurrentPinballGame->pikaChargeProgress < 168 && gCurrentPinballGame->pikaChargeProgress % 8 == 0)
{
s8 offset = gCurrentPinballGame->pikaChargeProgress / 21;
m4aSongNumStart(SE_PIKA_CHARGE_DO + offset);
}
if (gCurrentPinballGame->pikaChargeTarget <= gCurrentPinballGame->pikaChargeProgress)
{
gCurrentPinballGame->pikaChargeProgress = gCurrentPinballGame->pikaChargeTarget;
if (gCurrentPinballGame->pikaChargeProgress >= 168)
{
MPlayStart(&gMPlayInfo_SE1, &se_pika_full_charge_1_up);
gCurrentPinballGame->scoreAddedInFrame = 3000;
}
}
}
if (gCurrentPinballGame->pikaSpinCooldownTimer)
gCurrentPinballGame->pikaSpinCooldownTimer--;
if (gCurrentPinballGame->pikaSpinMomentum > 0)
{
gCurrentPinballGame->pikaSpinMomentum -= 3;
if (gCurrentPinballGame->pikaSpinMomentum < 0)
gCurrentPinballGame->pikaSpinMomentum = 0;
if (gCurrentPinballGame->pikaSpinFrameCounter < gCurrentPinballGame->pikaSpinPeriod - 1)
{
gCurrentPinballGame->pikaSpinFrameCounter++;
}
else
{
gCurrentPinballGame->pikaSpinFrameCounter = 0;
MPlayStart(&gMPlayInfo_SE3, &se_pika_spinner_clack);
gCurrentPinballGame->scoreAddedInFrame = 100;
if (gCurrentPinballGame->chargeFillValue < 12 && gCurrentPinballGame->kickbackFiring == 0)
{
gCurrentPinballGame->fullChargeSlideAnimTimer = 80;
gCurrentPinballGame->chargeIndicatorScaleX = 256;
gCurrentPinballGame->chargeIndicatorScaleY = 256;
}
}
gCurrentPinballGame->pikaSpinPeriod = (450 - gCurrentPinballGame->pikaSpinMomentum) / 10;
if (gCurrentPinballGame->pikaSpinPeriod < 5)
gCurrentPinballGame->pikaSpinPeriod = 5;
gCurrentPinballGame->pikachuSpinFrame = (gCurrentPinballGame->pikaSpinFrameCounter * 16) / gCurrentPinballGame->pikaSpinPeriod;
}
else
{
if (gCurrentPinballGame->pikaSpinMomentum < 0)
{
gCurrentPinballGame->pikaSpinMomentum += 3;
if (gCurrentPinballGame->pikaSpinMomentum > 0)
gCurrentPinballGame->pikaSpinMomentum = 0;
if (gCurrentPinballGame->pikaSpinFrameCounter < gCurrentPinballGame->pikaSpinPeriod - 1)
{
gCurrentPinballGame->pikaSpinFrameCounter++;
}
else
{
gCurrentPinballGame->pikaSpinFrameCounter = 0;
MPlayStart(&gMPlayInfo_SE3, &se_pika_spinner_clack);
gCurrentPinballGame->scoreAddedInFrame = 100;
if (gCurrentPinballGame->chargeFillValue < 12 && gCurrentPinballGame->kickbackFiring == 0)
{
gCurrentPinballGame->fullChargeSlideAnimTimer = 80;
gCurrentPinballGame->chargeIndicatorScaleX = 256;
gCurrentPinballGame->chargeIndicatorScaleY = 256;
}
}
gCurrentPinballGame->pikaSpinPeriod = (450 + gCurrentPinballGame->pikaSpinMomentum) / 10;
if (gCurrentPinballGame->pikaSpinPeriod < 5)
gCurrentPinballGame->pikaSpinPeriod = 5;
gCurrentPinballGame->pikachuSpinFrame = (gCurrentPinballGame->pikaSpinFrameCounter * 16) / gCurrentPinballGame->pikaSpinPeriod;
}
else
{
if (gCurrentPinballGame->pikachuSpinFrame > 0)
{
gCurrentPinballGame->pikaSpinFrameCounter++;
gCurrentPinballGame->pikaSpinFrameCounter %= 40;
gCurrentPinballGame->pikachuSpinFrame = (gCurrentPinballGame->pikaSpinFrameCounter * 16) / 40;
}
}
}
}
void DrawPikachuSpinner(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 index;
index = gCurrentPinballGame->pikachuSpinFrame;
group = gMain.fieldSpriteGroups[31];
group->baseX = 206 - gCurrentPinballGame->cameraXOffset;
if (gMain.selectedField == FIELD_RUBY)
group->baseY = 174 - gCurrentPinballGame->cameraYOffset;
else
group->baseY = 154 - gCurrentPinballGame->cameraYOffset;
if (gCurrentPinballGame->pikachuSpinFrame != gCurrentPinballGame->pikachuSpinPrevFrame)
{
gCurrentPinballGame->pikachuSpinPrevFrame = gCurrentPinballGame->pikachuSpinFrame;
DmaCopy16(3, gMainBoardPikaSpinner_Gfx[index], (void *)0x06010780, 0x120);
}
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}

View File

@ -78,7 +78,7 @@ extern const u8 gSphealIntroSprites_Gfx[];
extern const struct FieldBoardLayout gFieldBoardConfigs[];
void loadIntroduction(void)
void loadFieldBoardGraphics(void)
{
struct BoardConfig *dest = &gBoardConfig;
const struct FieldBoardLayout *src = gFieldBoardConfigs;

View File

@ -0,0 +1,134 @@
#include "global.h"
#include "main.h"
#include "m4a.h"
#include "constants/bg_music.h"
extern const void (*gBoardStateInitFuncs[])(void);
extern const void (*gBoardStateUpdateFuncs[])(void);
extern void HandleBoardStateTransitionTeardown(void);
void RequestBoardStateTransition(u8 arg0)
{
gCurrentPinballGame->boardTransitionPhase = 2;
gCurrentPinballGame->nextBoardState = arg0;
if (gCurrentPinballGame->boardState == 2)
gMain.fieldSpriteGroups[13]->available = 0;
}
void BoardStateDispatcher(void)
{
switch (gCurrentPinballGame->boardTransitionPhase)
{
case 0:
gBoardStateInitFuncs[gCurrentPinballGame->boardState]();
gCurrentPinballGame->boardTransitionPhase++;
break;
case 1:
gBoardStateUpdateFuncs[gCurrentPinballGame->boardState]();
break;
case 2:
HandleBoardStateTransitionTeardown();
gCurrentPinballGame->prevBoardState = gCurrentPinballGame->boardState;
gCurrentPinballGame->boardState = gCurrentPinballGame->nextBoardState;
gCurrentPinballGame->boardTransitionPhase = 0;
break;
}
}
void InitFieldIdle(void)
{
s16 num1;
u8 num2;
if (gCurrentPinballGame->prevBoardState > 0)
{
if (gMain.selectedField == FIELD_RUBY)
{
num1 = gCurrentPinballGame->numCompletedBonusStages / 5;
if ((num1 & 1) == 0)
{
m4aSongNumStart(MUS_FIELD_RUBY);
}
else
{
m4aSongNumStart(MUS_FIELD_RUBY2);
}
}
else
{
num1 = gCurrentPinballGame->numCompletedBonusStages / 5;
if ((num1 & 1) == 0)
{
m4aSongNumStart(MUS_FIELD_SAPPHIRE);
}
else
{
m4aSongNumStart(MUS_FIELD_SAPPHIRE2);
}
}
}
num2 = gCurrentPinballGame->prevBoardState - 1;
if (num2 > 1)
{
gCurrentPinballGame->evoArrowProgress = gCurrentPinballGame->arrowProgressPreserved;
gCurrentPinballGame->catchArrowProgress = gCurrentPinballGame->catchModeArrows;
gCurrentPinballGame->arrowProgressPreserved = 0;
gCurrentPinballGame->catchModeArrows = 0;
}
}
void UpdateFieldIdle(void)
{
if (gCurrentPinballGame->allHolesLit != 0)
{
if (gCurrentPinballGame->allHolesLitDelayTimer != 0)
{
gCurrentPinballGame->allHolesLitDelayTimer--;
}
else
{
RequestBoardStateTransition(2);
}
}
}
void HandleBoardStateTransitionTeardown(void)
{
if (gCurrentPinballGame->boardState == 2 && gCurrentPinballGame->nextBoardState > 2)
ResetCatchState(0);
if (gCurrentPinballGame->boardState > 2)
return;
if (gCurrentPinballGame->nextBoardState == 3)
{
gCurrentPinballGame->arrowProgressPreserved = gCurrentPinballGame->evoArrowProgress;
gCurrentPinballGame->catchModeArrows = gCurrentPinballGame->catchArrowProgress;
gCurrentPinballGame->evoArrowProgress = 0;
gCurrentPinballGame->catchArrowProgress = 0;
}
if (gCurrentPinballGame->nextBoardState == 4)
{
gCurrentPinballGame->arrowProgressPreserved = gCurrentPinballGame->evoArrowProgress;
gCurrentPinballGame->catchModeArrows = gCurrentPinballGame->catchArrowProgress;
gCurrentPinballGame->evoArrowProgress = 0;
gCurrentPinballGame->catchArrowProgress = 0;
}
else if (gCurrentPinballGame->nextBoardState == 6)
{
gCurrentPinballGame->catchModeArrows = gCurrentPinballGame->catchArrowProgress;
gCurrentPinballGame->arrowProgressPreserved = 0;
gCurrentPinballGame->evoArrowProgress = 0;
gCurrentPinballGame->catchArrowProgress = 0;
}
else if (gCurrentPinballGame->nextBoardState > 3)
{
gCurrentPinballGame->arrowProgressPreserved = gCurrentPinballGame->evoArrowProgress;
gCurrentPinballGame->catchModeArrows = gCurrentPinballGame->catchArrowProgress;
gCurrentPinballGame->evoArrowProgress = 0;
gCurrentPinballGame->catchArrowProgress = 0;
}
}

914
src/catch_and_hatch_modes.c Normal file
View File

@ -0,0 +1,914 @@
#include "global.h"
#include "m4a.h"
#include "main.h"
#include "constants/bg_music.h"
extern u8 gCatchSpriteFrameBuffer[];
extern struct BoardConfig gBoardConfig;
extern u8 gCatchSpritePaletteBuffer[];
extern u8 gCatchSpritePalettes[];
extern const u8 gSapphireCatchTilesGfx[];
extern const u8 gSapphireCatchPalette[];
extern const u8 gDefaultBallPalette[];
extern const u8 gBasketAnimationTilesGfx[][0x480];
extern const u8 gCapturePalette[];
extern const s16 gHatchSequentialFrameData[8][2];
extern const struct Vector16 gJirachiWaypoints[];
extern const u16 gJirachiStarFrameIndices[][10];
extern const u8 (*gMonIconPalettes[])[0x20];
extern const u16 gSapphireFloatOamFramesets[68][3][3];
extern const u16 gSapphireHatchOamFramesets[14][18];
extern const u8 (*gCatchSpriteGfxPtrs[])[0x480];
extern struct SongHeader se_evo_item_appear;
enum HatchTileRevealStates {
HATCH_TILE_REVEAL_NONE = 0,
HATCH_TILE_REVEAL_ONE_AT_A_TIME = 1,
HATCH_TILE_REVEAL_ALL_AT_ONCE = 2
};
#define BONUS_CATCH_TIME 7200 //2 minutes, 60FPS
void CleanupCatchEmState(void)
{
s16 i;
gCurrentPinballGame->creatureHitCount = 0;
gCurrentPinballGame->captureFlashTimer = 0;
gMain.fieldSpriteGroups[18]->available = 0;
gMain.fieldSpriteGroups[12]->available = 0;
gCurrentPinballGame->jirachiCollisionEnabled = 0;
LoadPortraitGraphics(0, 0);
gCurrentPinballGame->portraitDisplayState = 0;
ResetEventState();
for (i = 0; i < 6; i++)
gCurrentPinballGame->hatchTilePalette[i] = 13;
for (i = 0; i < 3; i++)
{
if (i < gCurrentPinballGame->evoItemCount)
gCurrentPinballGame->catchLights[i] = 1;
else
gCurrentPinballGame->catchLights[i] = 0;
}
}
void InitCatchEmMode(void)
{
s16 i, j;
gCurrentPinballGame->boardSubState = 0;
gCurrentPinballGame->stageTimer = 0;
gCurrentPinballGame->boardModeType = 1;
gCurrentPinballGame->eventTimer = gCurrentPinballGame->timerBonus + BONUS_CATCH_TIME;
gCurrentPinballGame->timerBonus = 0;
gCurrentPinballGame->creatureHitCount = 0;
gCurrentPinballGame->creatureHitCooldown = 0;
gCurrentPinballGame->captureFlashTimer = 0;
gCurrentPinballGame->hatchTilesBoardAcknowledged = 0;
gCurrentPinballGame->hatchSequentialTilesRevealed = 0;
gCurrentPinballGame->hatchTilesBumperAcknowledged = 0;
gCurrentPinballGame->hatchSequentialTileRevealFrameAnimTimer = 0;
gCurrentPinballGame->hatchFrameId = 0;
gCurrentPinballGame->catchArrowProgress = 0;
gCurrentPinballGame->catchProgressFlashing = 0;
if (gCurrentPinballGame->catchEmModeStartCount == 0)
{
gCurrentPinballGame->saverTimeRemaining = 6000;
}
else
{
gCurrentPinballGame->saverTimeRemaining = 4200;
}
gCurrentPinballGame->catchEmModeStartCount++;
DmaCopy16(3, gDefaultBallPalette, (void *)PLTT + 0x180, 0x20);
for (i = 0; i < 6; i++)
{
gCurrentPinballGame->hatchTileShufflePool[i] = i;
}
gCurrentPinballGame->hatchGridCellIndex = gMain.systemFrameCount % 6;
gCurrentPinballGame->hatchTilesRemaining = 5;
for (j = gCurrentPinballGame->hatchGridCellIndex; j < gCurrentPinballGame->hatchTilesRemaining; j++)
{
gCurrentPinballGame->hatchTileShufflePool[j] = gCurrentPinballGame->hatchTileShufflePool[j+1];
}
}
void UpdateCatchEmMode(void)
{
s16 i;
if (gCurrentPinballGame->boardModeType && gCurrentPinballGame->eventTimer < 2 && gCurrentPinballGame->boardSubState < 10)
{
m4aMPlayAllStop();
m4aSongNumStart(MUS_END_OF_BALL2);
gCurrentPinballGame->stageTimer = 200;
gCurrentPinballGame->boardSubState = 10;
}
switch (gCurrentPinballGame->boardSubState)
{
case 0:
BuildSpeciesWeightsForCatchEmMode();
gCurrentPinballGame->boardSubState++;
break;
case 1:
PickSpeciesForCatchEmMode();
if (gMain.mainState != STATE_GAME_IDLE)
SaveFile_SetPokedexFlags(gCurrentPinballGame->currentSpecies, 1);
gCurrentPinballGame->boardSubState++;
break;
case 2:
LoadCatchSpriteGraphics();
gCurrentPinballGame->catchModeArrows = 0;
gCurrentPinballGame->boardSubState++;
break;
case 3:
LoadPortraitGraphics(3, 0);
gCurrentPinballGame->hatchTileRevealState = HATCH_TILE_REVEAL_NONE;
gCurrentPinballGame->hatchRevealPhase = 0;
gCurrentPinballGame->boardSubState++;
for (i = 0; i < 6; i++)
gCurrentPinballGame->hatchTilePalette[i] = 15;
break;
case 4: // init hatch mode
if (gMain.modeChangeFlags == MODE_CHANGE_NONE)
{
if (gMain.selectedField == FIELD_RUBY)
{
if (gCurrentPinballGame->modeAnimTimer == 94)
{
m4aMPlayAllStop();
}
else if (gCurrentPinballGame->modeAnimTimer == 93)
{
gMain.modeChangeFlags |= MODE_CHANGE_BANNER;
gCurrentPinballGame->bannerDelayTimer = 0;
gCurrentPinballGame->bannerDisplayTimer = 120;
gCurrentPinballGame->cameraYScrollTarget = 0;
gCurrentPinballGame->cameraYAdjust = 0;
gCurrentPinballGame->cameraYScrollSpeed = 0;
gCurrentPinballGame->bannerGfxIndex = 2;
gCurrentPinballGame->bannerActive = 1;
gCurrentPinballGame->bannerPreserveBallState = 1;
gCurrentPinballGame->bannerDisplayDuration = 80;
gCurrentPinballGame->bannerSlidePosition = -2500;
gCurrentPinballGame->bannerSlideTimer = 50;
gCurrentPinballGame->bannerSlideVelocity = 0;
DmaCopy16(3, gModeBannerTilemaps[2], (void *)0x06015800, 0x2400);
DmaCopy16(3, gModeBannerPalettes[2], (void *)0x050003C0, 0x20);
gMain.blendControl = 0xCE;
}
else if (gCurrentPinballGame->modeAnimTimer == 73)
{
m4aSongNumStart(MUS_CATCH_EM_MODE);
}
else if (gCurrentPinballGame->modeAnimTimer < 17)
{
gCurrentPinballGame->boardModeType = 2;
gCurrentPinballGame->boardSubState++;
}
}
else // Sapphire board
{
if (gCurrentPinballGame->modeAnimTimer == 68)
{
m4aMPlayAllStop();
}
else if (gCurrentPinballGame->modeAnimTimer == 67)
{
gMain.modeChangeFlags |= MODE_CHANGE_BANNER;
gCurrentPinballGame->bannerDelayTimer = 0;
gCurrentPinballGame->bannerDisplayTimer = 120;
gCurrentPinballGame->cameraYScrollTarget = 0;
gCurrentPinballGame->cameraYAdjust = 0;
gCurrentPinballGame->cameraYScrollSpeed = 0;
gCurrentPinballGame->bannerGfxIndex = 2;
gCurrentPinballGame->bannerActive = 1;
gCurrentPinballGame->bannerPreserveBallState = 1;
gCurrentPinballGame->bannerDisplayDuration = 80;
gCurrentPinballGame->bannerSlidePosition = -2500;
gCurrentPinballGame->bannerSlideTimer = 50;
gCurrentPinballGame->bannerSlideVelocity = 0;
DmaCopy16(3, gModeBannerTilemaps[2], (void *)0x06015800, 0x2400);
DmaCopy16(3, gModeBannerPalettes[2], (void *)0x050003C0, 0x20);
gMain.blendControl = 0xCE;
}
else if (gCurrentPinballGame->modeAnimTimer == 47)
{
m4aSongNumStart(MUS_CATCH_EM_MODE2);
}
else if (gCurrentPinballGame->modeAnimTimer == 0)
{
gCurrentPinballGame->boardModeType = 2;
gCurrentPinballGame->boardSubState++;
}
}
}
CheckHatchTileRevealState();
return;
case 5: // hatch mode running
gCurrentPinballGame->evoArrowPaletteActive = 1;
CheckHatchTileRevealState();
gCurrentPinballGame->stageTimer = 0;
return;
case 6:
gCurrentPinballGame->evoArrowPaletteActive = 0;
if (gCurrentPinballGame->stageTimer == 0)
{
gCurrentPinballGame->stageTimer++;
}
else
{
gCurrentPinballGame->activePortraitType = 10;
DmaCopy16(3, gSapphireCatchTilesGfx, (void *)0x06015800, 0x1400);
DmaCopy16(3, gSapphireCatchPalette, (void *)0x050003C0, 0x20);
m4aSongNumStart(SE_UNKNOWN_0xA7);
gCurrentPinballGame->boardSubState++;
gCurrentPinballGame->stageTimer = 0;
}
break;
case 7:
PlayEggCrackAnimation();
return;
case 8:
ResetHatchFrameState();
DmaCopy16(3, gCapturePalette, (void *)0x050003E0, 0x20);
DmaCopy16(3, gCatchSpritePalettes, (void *)0x050003A0, 0x20);
gCurrentPinballGame->catchTargetX = 118;
gCurrentPinballGame->catchTargetY = 264;
gCurrentPinballGame->evoBlinkTimer = 0;
gCurrentPinballGame->catchLights[0] = 2;
gCurrentPinballGame->catchLights[1] = 2;
gCurrentPinballGame->catchLights[2] = 2;
DrawCaughtPokemonSprite();
gCurrentPinballGame->jirachiCollisionEnabled = 1;
gCurrentPinballGame->boardSubState++;
gCurrentPinballGame->bgmFadeTimer = 140;
PlayCry_Normal(gSpeciesInfo[gCurrentPinballGame->currentSpecies].speciesIdRS, 0);
gCurrentPinballGame->stageTimer = 0;
return;
case 9:
if (gCurrentPinballGame->stageTimer == 0)
{
gCurrentPinballGame->bannerDisplayTimer = 0;
gCurrentPinballGame->stageTimer++;
}
DrawCaughtPokemonSprite();
if (gCurrentPinballGame->creatureHitCooldown)
gCurrentPinballGame->creatureHitCooldown--;
break;
case 10:
CleanupCaughtPokemonSprite();
DisableHatchTileDisplay();
gCurrentPinballGame->boardSubState++;
break;
case 11:
CleanupCatchEmState();
gCurrentPinballGame->boardSubState++;
break;
case 12:
gCurrentPinballGame->evoArrowPaletteActive = 0;
if (gCurrentPinballGame->stageTimer)
{
gCurrentPinballGame->stageTimer--;
}
else
{
if (gCurrentPinballGame->catchLights[2] == 1)
RequestBoardStateTransition(3);
else
RequestBoardStateTransition(1);
gCurrentPinballGame->boardSubState = 0;
}
break;
}
}
//jirachi.c starts here
void InitJirachiBonus(void)
{
gCurrentPinballGame->boardSubState = 0;
gCurrentPinballGame->stageTimer = 0;
gCurrentPinballGame->boardModeType = 1;
gCurrentPinballGame->eventTimer = gCurrentPinballGame->timerBonus + 1800;
gCurrentPinballGame->timerBonus = 0;
gCurrentPinballGame->creatureHitCount = 0;
gCurrentPinballGame->creatureHitCooldown = 0;
gCurrentPinballGame->captureFlashTimer = 0;
gCurrentPinballGame->jirachiWaypointTimer = 0;
gCurrentPinballGame->jirachiLogicX = 900;
gCurrentPinballGame->jirachiLogicY = -1400;
gCurrentPinballGame->jirachiWaypoint = 0;
gCurrentPinballGame->jirachiTargetX = 0;
gCurrentPinballGame->jirachiTargetY = 0;
gCurrentPinballGame->jirachiDisplayX = 0;
gCurrentPinballGame->jirachiDisplayY = 0;
gCurrentPinballGame->jirachiCenterX = 0;
gCurrentPinballGame->jirachiCenterY = 0;
gCurrentPinballGame->catchArrowProgress = 0;
gCurrentPinballGame->catchProgressFlashing = 0;
gCurrentPinballGame->jirachiTagTimer[0] = 0;
gCurrentPinballGame->jirachiTagTimer[1] = 10;
gCurrentPinballGame->jirachiTagTimer[2] = 20;
gCurrentPinballGame->jirachiTagTimer[3] = 30;
gCurrentPinballGame->saverTimeRemaining = 3240;
gCurrentPinballGame->allHolesLit = 0;
gCurrentPinballGame->holeIndicators[0] = 0;
gCurrentPinballGame->holeIndicators[1] = gCurrentPinballGame->holeIndicators[0];
gCurrentPinballGame->holeIndicators[2] = gCurrentPinballGame->holeIndicators[0];
gCurrentPinballGame->holeIndicators[3] = gCurrentPinballGame->holeIndicators[0];
DmaCopy16(3, gDefaultBallPalette, (void *)0x05000180, 0x20);
}
void UpdateJirachiBonus(void)
{
struct Vector32 tempVec;
struct Vector32 deltaVec;
u16 angle;
int xx, yy;
int deltaMagSquared;
u16 var0;
switch (gCurrentPinballGame->boardSubState)
{
case 0:
gCurrentPinballGame->currentSpecies = SPECIES_JIRACHI;
LoadCatchSpriteGraphics();
gCurrentPinballGame->boardSubState++;
return;
case 1:
if (gMain.modeChangeFlags == MODE_CHANGE_NONE)
{
if (gMain.selectedField == FIELD_RUBY)
{
if (gCurrentPinballGame->modeAnimTimer == 94)
{
m4aMPlayAllStop();
}
else if (gCurrentPinballGame->modeAnimTimer == 93)
{
gMain.modeChangeFlags |= MODE_CHANGE_BANNER;
gCurrentPinballGame->bannerDelayTimer = 0;
gCurrentPinballGame->bannerDisplayTimer = 120;
gCurrentPinballGame->cameraYScrollTarget = 0;
gCurrentPinballGame->cameraYAdjust = 0;
gCurrentPinballGame->cameraYScrollSpeed = 0;
gCurrentPinballGame->bannerGfxIndex = 5;
gCurrentPinballGame->bannerActive = 1;
gCurrentPinballGame->bannerPreserveBallState = 1;
gCurrentPinballGame->bannerDisplayDuration = 80;
gCurrentPinballGame->bannerSlidePosition = -2500;
gCurrentPinballGame->bannerSlideTimer = 50;
gCurrentPinballGame->bannerSlideVelocity = 0;
DmaCopy16(3, gModeBannerTilemaps[5], (void *)0x06015800, 0x2400);
DmaCopy16(3, gModeBannerPalettes[5], (void *)0x050003C0, 0x20);
gMain.blendControl = 0xCE;
}
else if (gCurrentPinballGame->modeAnimTimer == 73)
{
m4aSongNumStart(MUS_JIRACHI);
}
else if (gCurrentPinballGame->modeAnimTimer == 40)
{
gCurrentPinballGame->boardSubState++;
}
}
else
{
if (gCurrentPinballGame->modeAnimTimer == 68)
{
m4aMPlayAllStop();
}
else if (gCurrentPinballGame->modeAnimTimer == 67)
{
gMain.modeChangeFlags |= MODE_CHANGE_BANNER;
gCurrentPinballGame->bannerDelayTimer = 0;
gCurrentPinballGame->bannerDisplayTimer = 120;
gCurrentPinballGame->cameraYScrollTarget = 0;
gCurrentPinballGame->cameraYAdjust = 0;
gCurrentPinballGame->cameraYScrollSpeed = 0;
gCurrentPinballGame->bannerGfxIndex = 5;
gCurrentPinballGame->bannerActive = 1;
gCurrentPinballGame->bannerPreserveBallState = 1;
gCurrentPinballGame->bannerDisplayDuration = 80;
gCurrentPinballGame->bannerSlidePosition = -2500;
gCurrentPinballGame->bannerSlideTimer = 50;
gCurrentPinballGame->bannerSlideVelocity = 0;
DmaCopy16(3, gModeBannerTilemaps[5], (void *)0x06015800, 0x2400);
DmaCopy16(3, gModeBannerPalettes[5], (void *)0x050003C0, 0x20);
gMain.blendControl = 0xCE;
return;
}
else if (gCurrentPinballGame->modeAnimTimer == 47)
{
m4aSongNumStart(MUS_JIRACHI);
return;
}
else if (gCurrentPinballGame->modeAnimTimer == 40)
{
gCurrentPinballGame->boardSubState++;
}
}
}
else if ((gMain.modeChangeFlags & MODE_CHANGE_BANNER) && gCurrentPinballGame->bannerSlideTimer == 1)
{
gCurrentPinballGame->portraitDisplayState = 3;
return;
}
break;
case 2:
DmaCopy16(3, gCapturePalette, (void *)0x050003E0, 0x20);
DmaCopy16(3, gCatchSpritePalettes, (void *)0x050003A0, 0x20);
gCurrentPinballGame->evoBlinkTimer = 0;
gCurrentPinballGame->catchLights[0] = 2;
gCurrentPinballGame->catchLights[1] = 2;
gCurrentPinballGame->catchLights[2] = 2;
gCurrentPinballGame->jirachiCollisionEnabled = 1;
gMain.fieldSpriteGroups[33]->available = 1;
DmaCopy16(3, gCatchSpriteGfxBuffer, (void *)0x06010CA0, 0x480);
gCurrentPinballGame->modeAnimTimer = 40;
gCurrentPinballGame->jirachiLogicX = 900;
gCurrentPinballGame->jirachiLogicY = -1400;
gCurrentPinballGame->jirachiWaypoint = 0;
gCurrentPinballGame->jirachiTargetX = gJirachiWaypoints[gCurrentPinballGame->jirachiWaypoint].x;
gCurrentPinballGame->jirachiTargetY = gJirachiWaypoints[gCurrentPinballGame->jirachiWaypoint].y;
gCurrentPinballGame->stageTimer = 0;
m4aSongNumStart(SE_JIRACHI_MOVE);
gCurrentPinballGame->boardSubState++;
gCurrentPinballGame->jirachiDisplayX = gCurrentPinballGame->jirachiLogicX;
gCurrentPinballGame->jirachiDisplayY = gCurrentPinballGame->jirachiLogicY;
return;
case 3:
if (gCurrentPinballGame->captureState == 2)
{
gCurrentPinballGame->catchTargetX = gCurrentPinballGame->jirachiDisplayX / 10 + 118;
gCurrentPinballGame->catchTargetY = gCurrentPinballGame->jirachiDisplayY / 10 + 272;
}
else
{
deltaVec.x = gCurrentPinballGame->jirachiTargetX - gCurrentPinballGame->jirachiLogicX;
deltaVec.y = gCurrentPinballGame->jirachiTargetY - gCurrentPinballGame->jirachiLogicY;
xx = deltaVec.x * deltaVec.x;
yy = deltaVec.y * deltaVec.y;
deltaMagSquared = xx + yy;
angle = ArcTan2(deltaVec.x, -deltaVec.y);
if (deltaMagSquared < 2500)
{
tempVec.x = 0;
tempVec.y = 0;
if (gCurrentPinballGame->jirachiWaypointTimer < 200)
{
gCurrentPinballGame->jirachiWaypointTimer++;
}
else
{
gCurrentPinballGame->jirachiWaypointTimer = 0;
if (gCurrentPinballGame->jirachiWaypoint < 11)
gCurrentPinballGame->jirachiWaypoint++;
else
gCurrentPinballGame->jirachiWaypoint = 0;
m4aSongNumStart(SE_JIRACHI_MOVE);
gCurrentPinballGame->jirachiTargetX = gJirachiWaypoints[gCurrentPinballGame->jirachiWaypoint].x;
gCurrentPinballGame->jirachiTargetY = gJirachiWaypoints[gCurrentPinballGame->jirachiWaypoint].y;
}
}
else
{
tempVec.x = (Cos(angle) * 7) / 20000;
tempVec.y = (Sin(angle) * -7) / 20000;
}
gCurrentPinballGame->jirachiLogicX += tempVec.x;
gCurrentPinballGame->jirachiLogicY += tempVec.y;
var0 = ((gCurrentPinballGame->stageTimer % 80) << 0x10) / 80;
gCurrentPinballGame->jirachiDisplayX = gCurrentPinballGame->jirachiLogicX;
gCurrentPinballGame->jirachiDisplayY = gCurrentPinballGame->jirachiLogicY + (Sin(var0) * 60) / 20000;
}
if (gCurrentPinballGame->stageTimer < 500)
{
gCurrentPinballGame->modeAnimTimer = 40;
if (gCurrentPinballGame->stageTimer == 499)
gCurrentPinballGame->boardModeType = 2;
}
gCurrentPinballGame->stageTimer++;
DrawJirachiSprites();
if (gCurrentPinballGame->creatureHitCooldown)
gCurrentPinballGame->creatureHitCooldown--;
if (gCurrentPinballGame->boardModeType && gCurrentPinballGame->eventTimer < 2 && gCurrentPinballGame->boardSubState < 5)
{
m4aMPlayAllStop();
m4aSongNumStart(MUS_END_OF_BALL2);
gCurrentPinballGame->boardSubState = 4;
gCurrentPinballGame->stageTimer = 150;
gCurrentPinballGame->jirachiCollisionEnabled = 0;
MPlayStart(&gMPlayInfo_SE1, &se_evo_item_appear);
}
return;
case 4:
if (gCurrentPinballGame->stageTimer)
gCurrentPinballGame->stageTimer--;
else
gCurrentPinballGame->boardSubState = 5;
DrawJirachiSprites();
if (gCurrentPinballGame->creatureHitCooldown)
gCurrentPinballGame->creatureHitCooldown--;
break;
case 5:
DrawJirachiSprites();
CleanupJirachiSprites();
CleanupCatchEmState();
gCurrentPinballGame->jirachiActivationFlags = 240;
gCurrentPinballGame->boardSubState = 6;
gCurrentPinballGame->stageTimer = 0;
return;
case 6:
gCurrentPinballGame->evoArrowPaletteActive = 0;
if (gCurrentPinballGame->stageTimer)
{
gCurrentPinballGame->stageTimer--;
}
else
{
if (gCurrentPinballGame->catchLights[2] == 1)
RequestBoardStateTransition(3);
else
RequestBoardStateTransition(1);
gCurrentPinballGame->boardSubState = 0;
}
}
}
//sprite graphics starts here
void LoadCatchSpriteGraphics(void)
{
s16 i;
s16 catchIndex;
const u8 *sp0[3];
const u8 *spC[3];
catchIndex = gSpeciesInfo[gCurrentPinballGame->currentSpecies].catchIndex;
for (i = 0; i < 3; i++)
{
sp0[i] = gCatchSpriteGfxPtrs[catchIndex / 5][(i + (catchIndex % 5) * 3)];
spC[i] = gMonIconPalettes[catchIndex / 5][i * 5 + catchIndex % 5];
}
for (i = 0; i < 3; i++)
{
DmaCopy16(3, sp0[i], &gCatchSpriteGfxBuffer[i * 0x480], 0x480);
DmaCopy16(3, spC[i], &gCatchSpritePalettes[i * 0x20], 0x20);
}
DmaCopy16(3, gMonIconPalettes[0][15], &gCatchSpritePalettes[0x60], 0x20);
}
void LoadEggSpriteGraphics(void)
{
s16 eggIndex;
const u8 *src0;
const u8 *src1;
eggIndex= gSpeciesInfo[gCurrentPinballGame->currentSpecies].eggIndex;
src0 = gMonHatchSpriteGroupGfx[eggIndex / 6][eggIndex % 6];
src1 = gMonHatchSpriteGroupPals[eggIndex / 6][eggIndex % 6];
DmaCopy16(3, src0, gCatchSpriteFrameBuffer, 0x10E0);
DmaCopy16(3, src1, gCatchSpritePaletteBuffer, 0x20);
}
void DrawCaughtPokemonSprite(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 priority;
s16 index;
index = (gMain.fieldFrameCount % 50) / 25;
group = gMain.fieldSpriteGroups[33];
if (!group->available)
return;
gCurrentPinballGame->jirachiCenterX = 96;
gCurrentPinballGame->jirachiCenterY = 288;
group->baseX = 96 - gCurrentPinballGame->cameraXOffset;
group->baseY = 288 - gCurrentPinballGame->cameraYOffset;
if (gCurrentPinballGame->captureFlashTimer > 4)
{
if (gCurrentPinballGame->captureFlashTimer == 20 || gCurrentPinballGame->captureFlashTimer == 200)
{
DmaCopy16(3, gCatchSpriteFlashGfx, (void *)0x06010CA0, 0x480);
}
if (gCurrentPinballGame->captureFlashTimer == 24)
{
DmaCopy16(3, gCatchSpriteGfxBuffer, (void *)0x06010CA0, 0x480);
}
gCurrentPinballGame->captureFlashTimer--;;
}
else if (gCurrentPinballGame->randomSpriteVariantSeed == 5)
{
DmaCopy16(3, &gCatchSpriteGfxBuffer[index * 0x480], (void *)0x06010CA0, 0x480);
}
if (gCurrentPinballGame->captureSequenceTimer < 13)
priority = 2;
else
priority = 1;
if (group->baseY >= 200)
group->baseY = 200;
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
gOamBuffer[oamSimple->oamId].priority = priority;
}
}
void CleanupCaughtPokemonSprite(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
group = gMain.fieldSpriteGroups[33];
if (group->available)
{
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = 200;
gOamBuffer[oamSimple->oamId].y = 180;
}
}
gMain.fieldSpriteGroups[33]->available = 0;
}
void DrawJirachiSprites(void)
{
s16 i, j;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 *dst;
const u16 *src;
s16 index;
s16 priority;
s16 var1;
index = (gMain.fieldFrameCount % 50) / 25;
group = gMain.fieldSpriteGroups[33];
if (group->available)
{
gCurrentPinballGame->jirachiCenterX = gCurrentPinballGame->jirachiDisplayX / 10 + 96;
gCurrentPinballGame->jirachiCenterY = gCurrentPinballGame->jirachiDisplayY / 10 + 288;
group->baseX = gCurrentPinballGame->jirachiDisplayX / 10 + 96u - gCurrentPinballGame->cameraXOffset;
group->baseY = gCurrentPinballGame->jirachiDisplayY / 10 + 288u - gCurrentPinballGame->cameraYOffset;
if (gCurrentPinballGame->boardSubState > 3)
{
if (gCurrentPinballGame->stageTimer >= 90)
{
index = (150 - gCurrentPinballGame->stageTimer) / 4;
DmaCopy16(3, &gBasketAnimationTilesGfx[index], (void *)0x06010CA0, 0x480);
}
else
{
group->baseY = 190;
}
}
else if (gCurrentPinballGame->captureFlashTimer > 4)
{
if (gCurrentPinballGame->captureFlashTimer == 20 || gCurrentPinballGame->captureFlashTimer == 200)
{
DmaCopy16(3, gCatchSpriteFlashGfx, (void *)0x06010CA0, 0x480);
}
if (gCurrentPinballGame->captureFlashTimer == 24)
{
DmaCopy16(3, gCatchSpriteGfxBuffer, (void *)0x06010CA0, 0x480);
}
gCurrentPinballGame->captureFlashTimer--;
}
else if (gCurrentPinballGame->randomSpriteVariantSeed == 5)
{
DmaCopy16(3, &gCatchSpriteGfxBuffer[index * 0x480], (void *)0x06010CA0, 0x480);
}
if (gCurrentPinballGame->captureState != 2)
{
priority = 1;
}
else
{
if (gCurrentPinballGame->captureSequenceTimer < 13)
priority = 2;
else
priority = 1;
}
if (group->baseY >= 200)
group->baseY = 200;
else if (group->baseY < -60)
group->baseY = -60;
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
gOamBuffer[oamSimple->oamId].priority = priority;
}
}
for (j = 0; j < 4; j++)
{
group = gMain.fieldSpriteGroups[45 + j];
if (group->available)
{
group->baseX = gCurrentPinballGame->jirachiStarTagPos[j].x - gCurrentPinballGame->cameraXOffset;
group->baseY = gCurrentPinballGame->jirachiStarTagPos[j].y - gCurrentPinballGame->cameraYOffset;
var1 = gJirachiStarFrameIndices[j][9 - gCurrentPinballGame->jirachiTagTimer[j] / 4];
if (group->baseY >= 200)
group->baseY = 200;
else if (group->baseY < -60)
group->baseY = -60;
for (i = 0; i < 3; i++)
{
oamSimple = &group->oam[i];
dst = (u16*)&gOamBuffer[oamSimple->oamId];
src = gSapphireFloatOamFramesets[var1][i];
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
}
if (gCurrentPinballGame->captureState != 2 && gCurrentPinballGame->boardSubState < 4)
{
if (gCurrentPinballGame->jirachiTagTimer[j] == 0)
{
gCurrentPinballGame->jirachiTagTimer[j] = 40;
gCurrentPinballGame->jirachiStarTagPos[j].x = gCurrentPinballGame->jirachiCenterX;
gCurrentPinballGame->jirachiStarTagPos[j].y = gCurrentPinballGame->jirachiCenterY + 16;
gMain.fieldSpriteGroups[45 + j]->available = 1;
}
}
if (gCurrentPinballGame->jirachiTagTimer[j])
{
gCurrentPinballGame->jirachiTagTimer[j]--;
if (gCurrentPinballGame->jirachiTagTimer[j] == 0)
gMain.fieldSpriteGroups[45 + j]->available = 0;
}
}
}
void CleanupJirachiSprites(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
group = gMain.fieldSpriteGroups[33];
if (group->available)
{
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = 200;
gOamBuffer[oamSimple->oamId].y = 180;
}
}
gMain.fieldSpriteGroups[33]->available = 0;
for (i = 0; i < 4; i++)
gMain.fieldSpriteGroups[45 + i]->available = 0;
}
//draw_catch_tiles
void CheckHatchTileRevealState(void)
{
// Cross vertical threshold, check completion
if (gCurrentPinballGame->cameraYViewport > 138)
{
if (gCurrentPinballGame->hatchTileRevealState == HATCH_TILE_REVEAL_NONE && gCurrentPinballGame->hatchTilesBumperAcknowledged > 0)
{
// Reveal all at once, if the bumpers have been hit enough in one trip up to reveal all tiles
// This will be in 'banner' mode at this point, scrolling down, and records points mid sequence
if (gCurrentPinballGame->hatchTilesBoardAcknowledged + 6 == gCurrentPinballGame->hatchTilesBumperAcknowledged)
{
gCurrentPinballGame->hatchTileRevealState = HATCH_TILE_REVEAL_ALL_AT_ONCE;
gCurrentPinballGame->scoreAddedInFrame = 300000;
}
else
{
gCurrentPinballGame->hatchTileRevealState = HATCH_TILE_REVEAL_ONE_AT_A_TIME;
}
}
gCurrentPinballGame->hatchTilesBoardAcknowledged = gCurrentPinballGame->hatchTilesBumperAcknowledged;
}
if (gCurrentPinballGame->hatchTileRevealState == HATCH_TILE_REVEAL_ALL_AT_ONCE)
RevealAllHatchTilesAtOnce();
else if (gCurrentPinballGame->hatchTileRevealState == HATCH_TILE_REVEAL_ONE_AT_A_TIME)
RevealSequentialHatchTiles();
}
void PlayEggCrackAnimation(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 *dst;
if (gHatchSequentialFrameData[gCurrentPinballGame->hatchFrameId][1] > gCurrentPinballGame->hatchSequentialTileRevealFrameAnimTimer)
{
gCurrentPinballGame->hatchSequentialTileRevealFrameAnimTimer++;
}
else
{
gCurrentPinballGame->hatchSequentialTileRevealFrameAnimTimer = 0;
gCurrentPinballGame->hatchFrameId++;
}
if (gCurrentPinballGame->hatchFrameId == 2 && gCurrentPinballGame->hatchSequentialTileRevealFrameAnimTimer > 3)
{
gCurrentPinballGame->portraitDisplayState = 3;
gMain.fieldSpriteGroups[33]->available = 1;
}
if (gCurrentPinballGame->hatchFrameId > 2)
{
DmaCopy16(3, gCatchSpritePalettes, (void *)0x050003A0, 0x20);
DmaCopy16(3, gCatchSpriteGfxBuffer, (void *)0x06010CA0, 0x480);
DrawCaughtPokemonSprite();
}
group = gMain.fieldSpriteGroups[18];
if (group->available)
{
group->baseX = 96 - gCurrentPinballGame->cameraXOffset;
group->baseY = 296 - gCurrentPinballGame->cameraYOffset;
if (group->baseY >= 200)
group->baseY = 200;
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
dst = (u16*)&gOamBuffer[oamSimple->oamId];
*dst++ = gSapphireHatchOamFramesets[gHatchSequentialFrameData[gCurrentPinballGame->hatchFrameId][0]][i*3+0];
*dst++ = gSapphireHatchOamFramesets[gHatchSequentialFrameData[gCurrentPinballGame->hatchFrameId][0]][i*3+1];
*dst++ = gSapphireHatchOamFramesets[gHatchSequentialFrameData[gCurrentPinballGame->hatchFrameId][0]][i*3+2];
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
}
gMain.fieldSpriteGroups[18]->available = 1;
if (gCurrentPinballGame->hatchFrameId > 6)
{
gCurrentPinballGame->boardSubState++;
gMain.fieldSpriteGroups[18]->available = 0;
gCurrentPinballGame->activePortraitType = 0;
}
}
void ResetHatchFrameState(void)
{
s16 i;
gCurrentPinballGame->hatchFrameId = 0;
for (i = 0; i < 6; i++)
gCurrentPinballGame->hatchTilePalette[i] = 13;
}

View File

@ -9,6 +9,127 @@
extern const u16 gWildMonLocations[AREA_COUNT][2][WILD_MON_LOCATION_COUNT];
extern const u16 gEggLocations[MAIN_FIELD_COUNT][26];
/**
* 0 if captured via ball
* 1 if evolved
*/
void RegisterCaptureOrEvolution(s16 evolved)
{
s16 i;
if (!evolved)
{
if (gMain.mainState != STATE_GAME_IDLE)
SaveFile_SetPokedexFlags(gCurrentPinballGame->currentSpecies, SPECIES_CAUGHT);
if (gSpeciesInfo[gCurrentPinballGame->currentSpecies].evolutionMethod != 0)
{
if (gSpeciesInfo[gCurrentPinballGame->currentSpecies].evolutionTarget < SPECIES_NONE)
{
if (gCurrentPinballGame->evolvablePartySize < MAX_EVOLVABLE_PARTY_SIZE)
{
gCurrentPinballGame->evolvablePartySpecies[gCurrentPinballGame->evolvablePartySize] =
gCurrentPinballGame->currentSpecies;
gCurrentPinballGame->evolvablePartySize++;
}
else
{
for (i = 0; i < MAX_EVOLVABLE_PARTY_SIZE; i++)
gCurrentPinballGame->evolvablePartySpecies[i] = gCurrentPinballGame->evolvablePartySpecies[i + 1];
gCurrentPinballGame->evolvablePartySpecies[MAX_EVOLVABLE_PARTY_SIZE - 1] = gCurrentPinballGame->currentSpecies;
}
}
}
}
else
{
gCurrentPinballGame->evolvablePartySize--;
for (i = gCurrentPinballGame->evolvingPartyIndex; i < gCurrentPinballGame->evolvablePartySize; i++)
gCurrentPinballGame->evolvablePartySpecies[i] = gCurrentPinballGame->evolvablePartySpecies[i + 1];
if (gCurrentPinballGame->currentSpecies == SPECIES_WURMPLE)
{
if ((gMain.systemFrameCount & 1) == 0)
{
if (gMain_saveData.pokedexFlags[SPECIES_SILCOON] < SPECIES_CAUGHT)
gCurrentPinballGame->currentSpecies = SPECIES_SILCOON;
else
gCurrentPinballGame->currentSpecies = SPECIES_CASCOON;
}
else
{
if (gMain_saveData.pokedexFlags[SPECIES_CASCOON] < SPECIES_CAUGHT)
gCurrentPinballGame->currentSpecies = SPECIES_CASCOON;
else
gCurrentPinballGame->currentSpecies = SPECIES_SILCOON;
}
}
else if (gCurrentPinballGame->currentSpecies == SPECIES_GLOOM)
{
if (gMain.selectedField == FIELD_RUBY)
gCurrentPinballGame->currentSpecies = SPECIES_VILEPLUME;
else
gCurrentPinballGame->currentSpecies = SPECIES_BELLOSSOM;
}
else if (gCurrentPinballGame->currentSpecies == SPECIES_CLAMPERL)
{
if ((gMain.systemFrameCount & 1) == 0)
{
if (gMain_saveData.pokedexFlags[SPECIES_HUNTAIL] < SPECIES_CAUGHT)
gCurrentPinballGame->currentSpecies = SPECIES_HUNTAIL;
else
gCurrentPinballGame->currentSpecies = SPECIES_GOREBYSS;
}
else
{
if (gMain_saveData.pokedexFlags[SPECIES_GOREBYSS] < SPECIES_CAUGHT)
gCurrentPinballGame->currentSpecies = SPECIES_GOREBYSS;
else
gCurrentPinballGame->currentSpecies = SPECIES_HUNTAIL;
}
}
else if (gCurrentPinballGame->currentSpecies == SPECIES_NINCADA)
{
gCurrentPinballGame->currentSpecies = SPECIES_SHEDINJA;
if (gMain.mainState != STATE_GAME_IDLE)
SaveFile_SetPokedexFlags(SPECIES_SHEDINJA, SPECIES_CAUGHT);
gCurrentPinballGame->currentSpecies = SPECIES_NINJASK;
}
else
{
gCurrentPinballGame->currentSpecies =
gSpeciesInfo[gCurrentPinballGame->currentSpecies].evolutionTarget;
}
if (gMain.mainState != STATE_GAME_IDLE)
SaveFile_SetPokedexFlags(gCurrentPinballGame->currentSpecies, SPECIES_CAUGHT);
if (gSpeciesInfo[gCurrentPinballGame->currentSpecies].evolutionMethod != 0)
{
if (gSpeciesInfo[gCurrentPinballGame->currentSpecies].evolutionTarget < SPECIES_NONE)
{
if (gCurrentPinballGame->evolvablePartySize < MAX_EVOLVABLE_PARTY_SIZE)
{
gCurrentPinballGame->evolvablePartySpecies[gCurrentPinballGame->evolvablePartySize] =
gCurrentPinballGame->currentSpecies;
gCurrentPinballGame->evolvablePartySize++;
}
else
{
for (i = 0; i < MAX_EVOLVABLE_PARTY_SIZE; i++)
gCurrentPinballGame->evolvablePartySpecies[i] = gCurrentPinballGame->evolvablePartySpecies[i + 1];
gCurrentPinballGame->evolvablePartySpecies[MAX_EVOLVABLE_PARTY_SIZE - 1] = gCurrentPinballGame->currentSpecies;
}
}
}
}
}
static inline u32 GetTimeAdjustedRandom()
{
return Random() + (gMain.systemFrameCount + gMain.fieldFrameCount);

380
src/catch_tile_logic.c Normal file
View File

@ -0,0 +1,380 @@
#include "global.h"
#include "m4a.h"
#include "main.h"
#include "constants/bg_music.h"
extern const s16 gHatchSequentialTileFramesetData[][2];
extern const u16 gHatchSequentialTileBreakSpritesheetOam[28][18];
extern const s16 gHatchRevealSparkleTimings[];
extern const u16 gHatchRevealOamFramesets[16][18];
extern const u8 gHatchRevealPalette[];
extern const u16 gHatchFullRevealOamFramesets[18][18];
extern const u8 gHatchRevealTilesGfx[];
extern const s16 gHatchRevealFinalTimings[];
extern const u8 gHatchFinalTilesGfx[];
extern const u8 gHatchFinalPalette[];
extern const u16 gHatchSequentialOamFramesets[22][12];
extern const u8 gHatchStartTilesGfx[];
extern const u8 gHatchStartPalette[];
extern const u8 gHatchStage2TilesGfx[];
extern const u8 gHatchStage2Palette[];
extern const u8 gHatchStage3TilesGfx[];
extern const u8 gHatchStage3Palette[];
void DisableHatchTileDisplay(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
group = gMain.fieldSpriteGroups[18];
if (group->available)
{
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = 200;
gOamBuffer[oamSimple->oamId].y = 180;
}
}
gMain.fieldSpriteGroups[18]->available = 0;
group = gMain.fieldSpriteGroups[12];
if (group->available)
{
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = 200;
gOamBuffer[oamSimple->oamId].y = 180;
}
}
gMain.fieldSpriteGroups[12]->available = 0;
gCurrentPinballGame->activePortraitType = 0;
}
void RevealSequentialHatchTiles(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 *dst;
s16 var0;
int var1;
var1 = 1;
gMain.fieldSpriteGroups[18]->available = 1;
if (gCurrentPinballGame->hatchFrameId > 0)
UpdateSequentialTileParticles();
if (gCurrentPinballGame->hatchSequentialTilesRevealed < gCurrentPinballGame->hatchTilesBoardAcknowledged)
{
if (gCurrentPinballGame->hatchFrameId == 0 && gCurrentPinballGame->hatchSequentialTileRevealFrameAnimTimer == 0)
{
gCurrentPinballGame->activePortraitType = 11;
DmaCopy16(3, gHatchRevealPalette, (void *)0x050003C0, 0x20);
DmaCopy16(3, gHatchRevealTilesGfx, (void *)0x06015800, 0x2800);
}
if (gHatchSequentialTileFramesetData[gCurrentPinballGame->hatchFrameId][1] > gCurrentPinballGame->hatchSequentialTileRevealFrameAnimTimer)
{
gCurrentPinballGame->hatchSequentialTileRevealFrameAnimTimer++;
}
else
{
gCurrentPinballGame->hatchSequentialTileRevealFrameAnimTimer = 0;
gCurrentPinballGame->hatchFrameId++;
if (gCurrentPinballGame->hatchFrameId > 12)
{
gCurrentPinballGame->hatchSequentialTilesRevealed++;
gCurrentPinballGame->hatchFrameId = 0;
var1 = 0;
gCurrentPinballGame->hatchTilesRemaining--;
if (gCurrentPinballGame->hatchSequentialTilesRevealed == gCurrentPinballGame->hatchTilesBoardAcknowledged)
{
if (gCurrentPinballGame->hatchTilesRemaining >= 0)
gCurrentPinballGame->activePortraitType = 0;
}
if (gCurrentPinballGame->hatchTilesRemaining < 0)
{
gCurrentPinballGame->hatchTilesBoardAcknowledged = 0;
gCurrentPinballGame->hatchSequentialTilesRevealed = 0;
gCurrentPinballGame->hatchTilesBumperAcknowledged = 0;
for (i = 0; i < 6; i++)
gCurrentPinballGame->hatchTileShufflePool[i] = i;
var0 = gMain.systemFrameCount % 6;
gCurrentPinballGame->hatchTilesRemaining = 5;
gCurrentPinballGame->boardSubState++;
gMain.fieldSpriteGroups[18]->available = 0;
}
else if (gCurrentPinballGame->hatchTilesRemaining == 0)
{
var0 = 0;
}
else
{
var0 = gMain.systemFrameCount % gCurrentPinballGame->hatchTilesRemaining;
}
gCurrentPinballGame->hatchGridCellIndex = gCurrentPinballGame->hatchTileShufflePool[var0];
for (i = var0; i < gCurrentPinballGame->hatchTilesRemaining; i++)
gCurrentPinballGame->hatchTileShufflePool[i] = gCurrentPinballGame->hatchTileShufflePool[i + 1];
}
else
{
if (gCurrentPinballGame->hatchFrameId == 1)
gCurrentPinballGame->hatchTilePalette[gCurrentPinballGame->hatchGridCellIndex] = 13;
}
}
}
else
{
var1 = 0;
}
if (gCurrentPinballGame->hatchFrameId == 1)
{
m4aSongNumStart(SE_CATCH_TILE_REVEAL);
InitSequentialTileParticles();
}
if (gCurrentPinballGame->hatchFrameId == 12)
var1 = 0;
group = gMain.fieldSpriteGroups[18];
if (var1)
{
group->baseX = (gCurrentPinballGame->hatchGridCellIndex % 3) * 16 - (gCurrentPinballGame->cameraXOffset - 96);
group->baseY = (gCurrentPinballGame->hatchGridCellIndex / 3) * 16 - (gCurrentPinballGame->cameraYOffset - 300);
}
else
{
group->baseY = 200;
}
if (group->baseY >= 200)
group->baseY = 200;
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
dst = (u16 *)&gOamBuffer[oamSimple->oamId];
*dst++ = gHatchSequentialTileBreakSpritesheetOam[gHatchSequentialTileFramesetData[gCurrentPinballGame->hatchFrameId][0]][i * 3 + 0];
*dst++ = gHatchSequentialTileBreakSpritesheetOam[gHatchSequentialTileFramesetData[gCurrentPinballGame->hatchFrameId][0]][i * 3 + 1];
*dst++ = gHatchSequentialTileBreakSpritesheetOam[gHatchSequentialTileFramesetData[gCurrentPinballGame->hatchFrameId][0]][i * 3 + 2];
gOamBuffer[oamSimple->oamId].priority = 3;
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
}
void RevealAllHatchTilesAtOnce(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 *dst;
s16 var0;
switch (gCurrentPinballGame->hatchRevealPhase)
{
case 0:
if (gCurrentPinballGame->revealAnimFrameCounter < 60)
{
gCurrentPinballGame->revealAnimFrameCounter++;
}
else
{
gCurrentPinballGame->hatchRevealPhase++;
gCurrentPinballGame->revealAnimFrameCounter = 0;
}
gMain.blendControl = 0xCE;
break;
case 1:
gCurrentPinballGame->activePortraitType = 5;
DmaCopy16(3, gHatchStartTilesGfx, (void *)0x06015800, 0x2000);
DmaCopy16(3, gHatchStartPalette, (void *)0x050003C0, 0x20);
gMain.fieldSpriteGroups[35]->available = 1;
m4aSongNumStart(SE_CATCH_ALL_REVEAL_LIGHTNING);
gCurrentPinballGame->hatchRevealPhase++;
gCurrentPinballGame->revealAnimFrameCounter = 0;
gCurrentPinballGame->revealFramesetIndex = 0;
break;
case 2:
if (gHatchRevealSparkleTimings[gCurrentPinballGame->revealFramesetIndex] > gCurrentPinballGame->revealAnimFrameCounter)
{
gCurrentPinballGame->revealAnimFrameCounter++;
}
else
{
gCurrentPinballGame->revealAnimFrameCounter = 0;
gCurrentPinballGame->revealFramesetIndex++;
if (gCurrentPinballGame->revealFramesetIndex > 7)
{
gCurrentPinballGame->revealFramesetIndex = 7;
gCurrentPinballGame->hatchRevealPhase++;
gMain.fieldSpriteGroups[35]->available = 0;
}
}
var0 = gCurrentPinballGame->revealFramesetIndex;
group = gMain.fieldSpriteGroups[35];
group->baseX = 124 - gCurrentPinballGame->cameraXOffset;
group->baseY = 244 - gCurrentPinballGame->cameraYOffset;
if (group->baseY >= 200)
group->baseY = 200;
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
dst = (u16 *)&gOamBuffer[oamSimple->oamId];
*dst++ = gHatchRevealOamFramesets[var0][i * 3 + 0];
*dst++ = gHatchRevealOamFramesets[var0][i * 3 + 1];
*dst++ = gHatchRevealOamFramesets[var0][i * 3 + 2];
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
break;
case 3:
gCurrentPinballGame->activePortraitType = 6;
DmaCopy16(3, gHatchStage2TilesGfx, (void *)0x06015800, 0x800);
DmaCopy16(3, gHatchStage2Palette, (void *)0x050003C0, 0x20);
gMain.fieldSpriteGroups[36]->available = 1;
gCurrentPinballGame->hatchRevealPhase++;
gCurrentPinballGame->revealAnimFrameCounter = 0;
gCurrentPinballGame->startButtonDisabled = 1;
break;
case 4:
var0 = gCurrentPinballGame->revealAnimFrameCounter / 2;
if (gCurrentPinballGame->revealAnimFrameCounter < 15)
{
gCurrentPinballGame->revealAnimFrameCounter++;
}
else
{
gMain.fieldSpriteGroups[36]->available = 0;
gCurrentPinballGame->hatchRevealPhase++;
gCurrentPinballGame->revealAnimFrameCounter = 0;
gCurrentPinballGame->revealFramesetIndex = 0;
}
group = gMain.fieldSpriteGroups[36];
group->baseX = 96 - gCurrentPinballGame->cameraXOffset;
group->baseY = 300 - gCurrentPinballGame->cameraYOffset;
if (group->baseY >= 200)
group->baseY = 200;
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
dst = (u16 *)&gOamBuffer[oamSimple->oamId];
*dst++ = gHatchFullRevealOamFramesets[var0][i * 3 + 0];
*dst++ = gHatchFullRevealOamFramesets[var0][i * 3 + 1];
*dst++ = gHatchFullRevealOamFramesets[var0][i * 3 + 2];
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
break;
case 5:
gCurrentPinballGame->activePortraitType = 7;
DmaCopy16(3, gHatchStage3TilesGfx, (void *)0x06015800, 0x2000);
DmaCopy16(3, gHatchStage3Palette, (void *)0x050003C0, 0x20);
gCurrentPinballGame->hatchRevealPhase++;
InitBurstTileParticles();
m4aSongNumStart(SE_CATCH_ALL_REVEAL_SHATTER);
break;
case 6:
gMain.blendBrightness = 0;
gMain.blendControl = ((REG_DISPCNT & (DISPCNT_OBJ_ON | DISPCNT_BG_ALL_ON)) >> 8) | 0xA0;
if (gCurrentPinballGame->revealAnimFrameCounter < 73)
{
s16 var1;
if (gCurrentPinballGame->revealAnimFrameCounter < 8)
{
gMain.blendBrightness = 16;
}
else
{
for (i = 0; i < 6; i++)
gCurrentPinballGame->hatchTilePalette[i] = 13;
gMain.blendBrightness = ((8 - gCurrentPinballGame->revealAnimFrameCounter) / 4) + 16;
}
}
if (gCurrentPinballGame->revealAnimFrameCounter < 72)
{
gCurrentPinballGame->revealAnimFrameCounter++;
}
else
{
gCurrentPinballGame->hatchRevealPhase++;
gCurrentPinballGame->revealAnimFrameCounter = 0;
gCurrentPinballGame->revealFramesetIndex = 0;
}
if (gCurrentPinballGame->revealAnimFrameCounter > 8U)
{
if (gCurrentPinballGame->hatchSequentialTileRevealFrameAnimTimer < 0x7000)
UpdateBurstTileParticles();
}
break;
case 7:
gCurrentPinballGame->activePortraitType = 8;
DmaCopy16(3, gHatchFinalTilesGfx, (void *)0x06015800, 0x1800);
DmaCopy16(3, gHatchFinalPalette, (void *)0x050003C0, 0x20);
gMain.fieldSpriteGroups[37]->available = 1;
gCurrentPinballGame->hatchRevealPhase++;
gCurrentPinballGame->startButtonDisabled = 0;
break;
case 8:
if (gHatchRevealFinalTimings[gCurrentPinballGame->revealFramesetIndex] > gCurrentPinballGame->revealAnimFrameCounter)
{
gCurrentPinballGame->revealAnimFrameCounter++;
}
else
{
gCurrentPinballGame->revealAnimFrameCounter = 0;
gCurrentPinballGame->revealFramesetIndex++;
if (gCurrentPinballGame->revealFramesetIndex > 10)
{
gCurrentPinballGame->boardSubState++;
gMain.fieldSpriteGroups[37]->available = 0;
gCurrentPinballGame->hatchTilesBoardAcknowledged = 0;
gCurrentPinballGame->hatchSequentialTilesRevealed = 0;
gCurrentPinballGame->hatchTilesBumperAcknowledged = 0;
gMain.blendControl = 0xCE;
gMain.blendBrightness = 0;
gMain.fieldSpriteGroups[37]->available = 0;
gCurrentPinballGame->revealFramesetIndex = 10;
gCurrentPinballGame->activePortraitType = 0;
}
}
var0 = gCurrentPinballGame->revealFramesetIndex;
group = gMain.fieldSpriteGroups[37];
group->baseX = 96 - gCurrentPinballGame->cameraXOffset;
group->baseY = 300 - gCurrentPinballGame->cameraYOffset;
if (group->baseY >= 200)
group->baseY = 200;
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
dst = (u16 *)&gOamBuffer[oamSimple->oamId];
*dst++ = gHatchSequentialOamFramesets[var0][i * 3 + 0];
*dst++ = gHatchSequentialOamFramesets[var0][i * 3 + 1];
*dst++ = gHatchSequentialOamFramesets[var0][i * 3 + 2];
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
break;
}
}

178
src/catch_tile_particles.c Normal file
View File

@ -0,0 +1,178 @@
#include "global.h"
#include "main.h"
extern const s16 gHatchRevealPieceIndices[][16];
extern const s16 gHatchPieceVelocities[][2];
extern const s16 gHatchPieceAffineModes[];
extern const s16 gHatchPieceMatrixNums[6];
extern const s16 gHatchPieceAnimIndices[][12];
extern const u16 gHatchParticleOamAttributes[][3];
extern const u16 gHatchAnimOamAttributes[][3];
void InitSequentialTileParticles(void)
{
s16 i;
for (i = 0; i < 6; i++)
{
gCurrentPinballGame->tileParticlePos[i].x = 0;
gCurrentPinballGame->tileParticlePos[i].y = 0;
gCurrentPinballGame->tileParticleVel[i].x = 200 - (Random() % 400);
gCurrentPinballGame->tileParticleVel[i].y = 80 - (Random() % 550);
gCurrentPinballGame->tileParticleGravity[i] = 10 + (Random() % 15);
}
gCurrentPinballGame->particleAnimTimer = 0;
gMain.fieldSpriteGroups[12]->available = 1;
}
void UpdateSequentialTileParticles(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 *dst;
const u16 *src;
s16 var0;
struct Vector16 tempVector;
group = gMain.fieldSpriteGroups[12];
if (group->available)
{
for (i = 0; i < 6; i++)
{
var0 = gHatchPieceAnimIndices[i][gCurrentPinballGame->particleAnimTimer / 4];
gCurrentPinballGame->tileParticleVel[i].y += gCurrentPinballGame->tileParticleGravity[i];
if (gCurrentPinballGame->tileParticlePos[i].y < 14000)
{
gCurrentPinballGame->tileParticlePos[i].x += gCurrentPinballGame->tileParticleVel[i].x;
gCurrentPinballGame->tileParticlePos[i].y += gCurrentPinballGame->tileParticleVel[i].y;
}
tempVector.x = ((gCurrentPinballGame->hatchGridCellIndex % 3) * 16 + 96u - gCurrentPinballGame->cameraXOffset) + (gCurrentPinballGame->tileParticlePos[i].x / 100);
tempVector.y = ((gCurrentPinballGame->hatchGridCellIndex / 3) * 16 + 300u - gCurrentPinballGame->cameraYOffset) + (gCurrentPinballGame->tileParticlePos[i].y / 100);
if (tempVector.y >= 200)
tempVector.y = 200;
oamSimple = &group->oam[i];
dst = (u16*)&gOamBuffer[oamSimple->oamId];
*dst++ = gHatchAnimOamAttributes[var0][0];
*dst++ = gHatchAnimOamAttributes[var0][1];
*dst++ = gHatchAnimOamAttributes[var0][2];
gOamBuffer[oamSimple->oamId].x += tempVector.x;
gOamBuffer[oamSimple->oamId].y += tempVector.y;
}
}
if (gCurrentPinballGame->particleAnimTimer < 48)
{
gCurrentPinballGame->particleAnimTimer++;
}
else
{
gCurrentPinballGame->hatchSequentialTileRevealFrameAnimTimer = 0x7100;
gMain.fieldSpriteGroups[12]->available = 0;
}
}
void InitBurstTileParticles(void)
{
s16 i;
const struct Vector16 *var0;
for (i = 0; i < 6; i++)
{
gCurrentPinballGame->tileParticlePos[i].x = ((i % 3) * 16 - 24) * 100;
gCurrentPinballGame->tileParticlePos[i].y = ((i / 3) * 16 - 28) * 100;
gCurrentPinballGame->tileParticleVel[i].x = gHatchPieceVelocities[i][0] - ((Random() % 200) - 60);
gCurrentPinballGame->tileParticleVel[i].y = gHatchPieceVelocities[i][1] - ((Random() % 200) - 60);
gCurrentPinballGame->tileParticleGravity[i] = (Random() % 4) + 1;
}
gCurrentPinballGame->tileParticlePos[0].x = -5600;
gCurrentPinballGame->tileParticlePos[0].y = -6000;
gCurrentPinballGame->tileParticleGravity[0] = 3;
gCurrentPinballGame->tileParticlePos[4].x = -4000;
gCurrentPinballGame->tileParticlePos[4].y = -4400;
gCurrentPinballGame->tileParticleGravity[4] = 3;
gCurrentPinballGame->particleAnimTimer = 0;
gMain.fieldSpriteGroups[12]->available = 1;
}
void UpdateBurstTileParticles(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 *dst;
s16 index;
struct Vector16 tempVector;
s16 sp0[6];
s16 scale;
group = gMain.fieldSpriteGroups[12];
if (group->available)
{
for (i = 0; i < 6; i++)
{
index = gCurrentPinballGame->particleAnimTimer / 5;
sp0[i] = gHatchRevealPieceIndices[i][index];
if (gCurrentPinballGame->particleAnimTimer > 4)
{
gCurrentPinballGame->tileParticleVel[i].y += gCurrentPinballGame->tileParticleGravity[i];
if (i == 4)
gCurrentPinballGame->tileParticleVel[i].x += gCurrentPinballGame->tileParticleGravity[4] * 4;
gCurrentPinballGame->tileParticlePos[i].x += gCurrentPinballGame->tileParticleVel[i].x;
gCurrentPinballGame->tileParticlePos[i].y += gCurrentPinballGame->tileParticleVel[i].y;
}
tempVector.x = (gCurrentPinballGame->tileParticlePos[i].x / 100) + 96u - gCurrentPinballGame->cameraXOffset;
tempVector.y = (gCurrentPinballGame->tileParticlePos[i].y / 100) + 304u - gCurrentPinballGame->cameraYOffset;
if (tempVector.y >= 160)
tempVector.y = 160;
oamSimple = &group->oam[i];
dst = (u16*)&gOamBuffer[oamSimple->oamId];
*dst++ = gHatchParticleOamAttributes[sp0[i]][0];
*dst++ = gHatchParticleOamAttributes[sp0[i]][1];
*dst++ = gHatchParticleOamAttributes[sp0[i]][2];
gOamBuffer[oamSimple->oamId].x += tempVector.x;
gOamBuffer[oamSimple->oamId].y += tempVector.y;
gOamBuffer[oamSimple->oamId].affineMode = gHatchPieceAffineModes[i];
gOamBuffer[oamSimple->oamId].matrixNum = gHatchPieceMatrixNums[i];
}
}
scale = ((gCurrentPinballGame->particleAnimTimer * gCurrentPinballGame->particleAnimTimer * 0xD0) / 0x510) + 0x80;
if (sp0[0] == 4)
scale = -scale;
SetMatrixScale(scale, scale, 2);
scale = 0x80;
if (sp0[1] == 4)
scale = -scale;
SetMatrixScale(scale, scale, 3);
scale = ((gCurrentPinballGame->particleAnimTimer * gCurrentPinballGame->particleAnimTimer * 0x100) / 0x510) + 0x80;
if (sp0[3] == 4)
scale = -scale;
SetMatrixScale(scale, scale, 4);
scale = ((gCurrentPinballGame->particleAnimTimer * gCurrentPinballGame->particleAnimTimer * 0x1C0) / 0x510) + 0x40;
if (sp0[4]== 4)
scale = -scale;
SetMatrixScale(scale, scale, 5);
if (gCurrentPinballGame->particleAnimTimer < 47)
{
gCurrentPinballGame->particleAnimTimer++;
}
else
{
gCurrentPinballGame->hatchSequentialTileRevealFrameAnimTimer = 0x7100;
gMain.fieldSpriteGroups[12]->available = 0;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

228
src/collision_dusclops.c Normal file
View File

@ -0,0 +1,228 @@
#include "global.h"
#include "main.h"
#include "constants/dusclops_states.h"
s16 CollisionCheck_Dusclops(struct Vector16* arg0, u16* arg1) {
struct Vector16 vec1;
struct Vector16 vec2;
u16 sp00;
u8 sp02;
u16 return_val;
s16 collisionTileIndex;
s32 tileMapPage;
s32 boardLayer;
u32 some_enum;
u32 switch_enum;
return_val = 0;
gCurrentPinballGame->ball->spinAcceleration = 0;
vec1.x = arg0->x / 8;
vec1.y = arg0->y / 8;
vec2.x = arg0->x % 8;
vec2.y = arg0->y % 8;
tileMapPage = vec1.y / 64;
boardLayer = gCurrentPinballGame->boardLayerDepth;
vec1.y %= 64;
collisionTileIndex = gBoardConfig.fieldLayout.collisionTileMap[boardLayer + tileMapPage][vec1.y * 64 + vec1.x];
sp00 = gBoardConfig.fieldLayout.collisionAngleMap[boardLayer + tileMapPage][collisionTileIndex * 64 + vec2.y * 8 + vec2.x];
sp02 = gBoardConfig.fieldLayout.collisionTypeMap[boardLayer + tileMapPage][collisionTileIndex * 64 + vec2.y * 8 + vec2.x];
CheckDusclopsEntitiesCollision(arg0, &sp00, &sp02);
switch_enum = sp02 & 0xF;
some_enum = sp02 >> 4;
switch (switch_enum)
{
case 1:
case 4:
case 6:
gCurrentPinballGame->collisionSurfaceType = switch_enum - 1;
gCurrentPinballGame->collisionResponseType = 1;
*arg1 = sp00;
if (*arg1 >= 0x3FF0 && *arg1 <= 0x4010)
{
if (gCurrentPinballGame->ball->positionQ0.x < gBoardConfig.fieldLayout.ballSpawnX - 8 ||
gCurrentPinballGame->ball->positionQ0.y < gBoardConfig.fieldLayout.ballSpawnY - 8)
{
if (gCurrentPinballGame->ball->spinSpeed > 0)
{
*arg1 = 0x3E00;
}
else if (gCurrentPinballGame->ball->spinSpeed != 0)
{
*arg1 = 0x4100;
}
else
{
if (gMain.systemFrameCount & 1)
{
gCurrentPinballGame->ball->spinAcceleration = 0x28;
gCurrentPinballGame->ball->spinSpeed = 1;
*arg1 = 0x3E00;
}
else
{
gCurrentPinballGame->ball->spinAcceleration = 0xFFD8;
gCurrentPinballGame->ball->spinSpeed = 0xFFFF;
*arg1 = 0x4100;
}
}
}
}
return_val = 1;
break;
case 2:
case 3:
gCurrentPinballGame->collisionSurfaceType = switch_enum - 1;
gCurrentPinballGame->collisionResponseType = 2;
*arg1 = sp00 & 0x0000FFF0;
return_val = 1;
break;
case 5:
some_enum = 4;
break;
}
CheckDusclopsAbsorbZoneHit(some_enum, &return_val, arg1);
return return_val;
}
void CheckDusclopsEntitiesCollision(struct Vector16 *arg0, s16* arg1, u8* arg2) {
s16 deltaX;
s16 deltaY;
u16 maskedResult;
u8 lowerNibble;
u8 temp;
maskedResult = 0;
lowerNibble = 0;
if(gCurrentPinballGame->boardEntityCollisionMode == DUSCLOPS_ENTITY_COLLISION_MODE_DUSCLOPS)
{
if (*arg2 != 0)
return;
deltaX = arg0->x -gCurrentPinballGame->bossCollisionX;
deltaY = arg0->y -gCurrentPinballGame->bossCollisionY;
if (deltaX > 95U || deltaY > 119U)
return;
maskedResult = 0xFFF0 & gDusclopsBodyCollisionMap[(deltaY * 96 ) + deltaX];
lowerNibble = 0xF & gDusclopsBodyCollisionMap[(deltaY * 96 ) + deltaX];
if (lowerNibble == 0)
return;
//Can be hit when ready to absorb (2) or when walking (3)
temp = gCurrentPinballGame->bossEntityState -3;
if (temp <= 1U)
*arg2 = 1;
else
*arg2 = lowerNibble;
gCurrentPinballGame->bossEntityState = DUSCLOPS_ENTITY_STATE_HIT;
*arg1 = maskedResult;
return;
}
if(gCurrentPinballGame->boardEntityCollisionMode == DUSCLOPS_ENTITY_COLLISION_MODE_DUSKULL)
{
if (*arg2 != 0)
return;
if (gCurrentPinballGame->minionCanCollide[0] )
{
deltaX = arg0->x - gCurrentPinballGame->minionCollisionPosition[0].x;
deltaY = arg0->y - gCurrentPinballGame->minionCollisionPosition[0].y;
if (deltaX < 64U && deltaY < 64U)
{
maskedResult = 0xFFF0 & gSharedBumperCollisionMap[deltaY * 64 + deltaX];
lowerNibble = 0xF & gSharedBumperCollisionMap[deltaY * 64 + deltaX];
if (lowerNibble != 0)
gCurrentPinballGame->minionState[0] = DUSKULL_ENTITY_STATE_HIT;
}
}
if (lowerNibble == 0)
{
if (gCurrentPinballGame->minionCanCollide[1] )
{
deltaX = arg0->x - gCurrentPinballGame->minionCollisionPosition[1].x;
deltaY = arg0->y - gCurrentPinballGame->minionCollisionPosition[1].y;
if (deltaX < 64U && deltaY < 64U)
{
maskedResult = 0xFFF0 & gSharedBumperCollisionMap[deltaY * 64 + deltaX];
lowerNibble = 0xF & gSharedBumperCollisionMap[deltaY * 64 + deltaX];
if (lowerNibble != 0)
gCurrentPinballGame->minionState[1] = DUSKULL_ENTITY_STATE_HIT;
}
}
}
if (lowerNibble == 0)
{
if ( gCurrentPinballGame->minionCanCollide[2] )
{
deltaX = arg0->x - gCurrentPinballGame->minionCollisionPosition[2].x;
deltaY = arg0->y - gCurrentPinballGame->minionCollisionPosition[2].y;
if (deltaX < 64U && deltaY < 64U)
{
maskedResult = 0xFFF0 & gSharedBumperCollisionMap[deltaY * 64 + deltaX];
lowerNibble = 0xF & gSharedBumperCollisionMap[deltaY * 64 + deltaX];
if (lowerNibble != 0)
{
gCurrentPinballGame->minionState[2] = DUSKULL_ENTITY_STATE_HIT;
}
}
}
}
if (lowerNibble != 0)
{
*arg1 = maskedResult;
*arg2 = 6;
}
return;
}
}
void CheckDusclopsAbsorbZoneHit(u8 arg0, u16 *arg1, u16 *arg2)
{
switch (arg0)
{
case 1:
case 2:
case 3:
break;
case 4:
gCurrentPinballGame->bossEntityState = DUSCLOPS_ENTITY_STATE_HIT_ABSORB_ZONE;
gCurrentPinballGame->ballFrozenState = 1;
gCurrentPinballGame->boardEntityCollisionMode = DUSCLOPS_ENTITY_COLLISION_MODE_NONE;
break;
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
break;
}
}

203
src/collision_groudon.c Normal file
View File

@ -0,0 +1,203 @@
#include "global.h"
#include "main.h"
s16 CollisionCheck_Groudon(struct Vector16 *arg0, u16 *arg1)
{
struct Vector16 vec1;
struct Vector16 vec2;
u16 sp00;
u8 sp02;
u16 return_val;
u32 some_enum;
u32 switch_enum;
return_val = 0;
gCurrentPinballGame->ball->spinAcceleration = 0;
if (arg0->y < 0x200)
{
s16 r2;
s32 tileMapPage;
s32 boardLayer;
vec1.x = arg0->x / 8;
vec1.y = arg0->y / 8;
vec2.x = arg0->x % 8;
vec2.y = arg0->y % 8;
tileMapPage = vec1.y / 64;
boardLayer = gCurrentPinballGame->boardLayerDepth;
vec1.y %= 64;
r2 = gBoardConfig.fieldLayout.collisionTileMap[boardLayer + tileMapPage][vec1.y * 64 + vec1.x];
sp00 = gBoardConfig.fieldLayout.collisionAngleMap[boardLayer + tileMapPage][r2 * 64 + vec2.y * 8 + vec2.x];
sp02 = gBoardConfig.fieldLayout.collisionTypeMap[boardLayer + tileMapPage][r2 * 64 + vec2.y * 8 + vec2.x];
}
else
{
sp00 = 0;
sp02 = 0;
}
CheckGroudonEntityCollision(arg0, &sp00, &sp02);
switch_enum = sp02 & 0xF;
some_enum = sp02 >> 4;
switch (switch_enum)
{
case 1:
case 4:
case 6:
gCurrentPinballGame->collisionSurfaceType = switch_enum - 1;
gCurrentPinballGame->collisionResponseType = 1;
*arg1 = sp00;
if (*arg1 >= 0x3FF0 && *arg1 <= 0x4010)
{
if (gCurrentPinballGame->ball->positionQ0.x < (gBoardConfig.fieldLayout.ballSpawnX - 8) || gCurrentPinballGame->ball->positionQ0.y < gBoardConfig.fieldLayout.ballSpawnY - 8)
{
if (gCurrentPinballGame->ball->spinSpeed > 0)
{
*arg1 = 0x3E00;
}
else if (gCurrentPinballGame->ball->spinSpeed != 0)
{
*arg1 = 0x4100;
}
else
{
if (gMain.systemFrameCount & 1)
{
gCurrentPinballGame->ball->spinAcceleration = 40;
gCurrentPinballGame->ball->spinSpeed = 1;
*arg1 = 0x3E00;
}
else
{
gCurrentPinballGame->ball->spinAcceleration = -40;
gCurrentPinballGame->ball->spinSpeed = -1;
*arg1 = 0x4100;
}
}
}
}
return_val = 1;
break;
case 2:
case 3:
gCurrentPinballGame->collisionSurfaceType = switch_enum - 1;
gCurrentPinballGame->collisionResponseType = 2;
*arg1 = sp00 & 0xFFF0;
return_val = 1;
break;
case 5:
some_enum = 4;
break;
}
ProcessGroudonCollisionEvent(some_enum, &return_val, arg1);
return return_val;
}
void CheckGroudonEntityCollision(struct Vector16 *arg0, u16 *arg1, u8 *arg2)
{
s16 deltaX;
s16 deltaY;
u16 resultFromArray;
u16 maskedResult;
u16 lowerNibble;
s16 i;
if (gCurrentPinballGame->boardEntityCollisionMode == 1)
{
if ((*arg2 & 0xF) == 0)
{
deltaX = arg0->x - gCurrentPinballGame->bossCollisionX;
deltaY = arg0->y - gCurrentPinballGame->bossCollisionY;
if ((deltaX >= 0 && deltaX < 0x70) && (deltaY >= 0 && deltaY < 0x80))
{
resultFromArray = gGroudonBodyCollisionMap[(deltaY * 0x70) + deltaX];
maskedResult = resultFromArray & 0xFFF0;
lowerNibble = resultFromArray & 0xF;
if (lowerNibble != 0)
{
if (gCurrentPinballGame->bossHitFlashTimer == 0)
gCurrentPinballGame->bossHitFlashTimer = 0x27;
*arg1 = maskedResult;
*arg2 = lowerNibble;
}
}
}
}
for (i = 0; i < 3; i++)
{
if (gCurrentPinballGame->boulderCollisionPos[i].x <= 0)
continue;
if ((*arg2 & 0xF) != 0)
continue;
deltaX = arg0->x - gCurrentPinballGame->boulderCollisionPos[i].x;
deltaY = arg0->y - gCurrentPinballGame->boulderCollisionPos[i].y;
if ((deltaX < 0 || deltaX >= 0x50) || (deltaY < 0 || deltaY >= 0x50))
continue;
maskedResult = gGroudonProjectileCollisionMap[(deltaY * 0x50) + deltaX] & 0xFFF0;
lowerNibble = gGroudonProjectileCollisionMap[(deltaY * 0x50) + deltaX] & 0xF;
if (lowerNibble == 0)
continue;
*arg1 = maskedResult;
*arg2 = 6;
gCurrentPinballGame->boulderHitFlag[i] = 1;
}
for (i = 0; i < 4; i++)
{
if (gCurrentPinballGame->firePillarCollisionPos[i].x <= 0)
continue;
if ((*arg2 & 0xF) != 0)
continue;
deltaX = arg0->x - gCurrentPinballGame->firePillarCollisionPos[i].x;
deltaY = arg0->y - gCurrentPinballGame->firePillarCollisionPos[i].y;
if ((deltaX < 0 || deltaX >= 0x50) || (deltaY < 0 || deltaY >= 0x50))
continue;
maskedResult = gGroudonProjectileCollisionMap[(deltaY * 0x50) + deltaX] & 0xFFF0;
lowerNibble = gGroudonProjectileCollisionMap[(deltaY * 0x50) + deltaX] & 0xF;
if (lowerNibble == 0)
continue;
*arg1 = maskedResult;
*arg2 = 6;
gCurrentPinballGame->firePillarHitTimer[i] = 8;
}
}
void ProcessGroudonCollisionEvent(u8 arg0, u16 *arg1, u16 *arg2)
{
switch (arg0)
{
case 1:
case 2:
case 3:
break;
case 4:
gCurrentPinballGame->bossEntityState = 6;
gCurrentPinballGame->ballFrozenState = 1;
break;
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
break;
}
}

412
src/collision_kecleon.c Normal file
View File

@ -0,0 +1,412 @@
#include "global.h"
s16 CollisionCheck_Kecleon(struct Vector16 *arg0, u16 *arg1)
{
struct Vector16 vec1;
struct Vector16 vec2;
u16 sp00;
u8 sp02;
u16 return_val;
s16 collisionTileIndex;
s32 tileMapPage;
s32 boardLayer;
u32 some_enum;
u32 switch_enum;
return_val = 0;
gCurrentPinballGame->ball->spinAcceleration = 0;
vec1.x = arg0->x / 8;
vec1.y = arg0->y / 8;
vec2.x = arg0->x % 8;
vec2.y = arg0->y % 8;
tileMapPage = vec1.y / 64;
boardLayer = gCurrentPinballGame->boardLayerDepth;
vec1.y %= 64;
collisionTileIndex = gBoardConfig.fieldLayout.collisionTileMap[boardLayer + tileMapPage][vec1.y * 64 + vec1.x];
sp00 = gBoardConfig.fieldLayout.collisionAngleMap[boardLayer + tileMapPage][collisionTileIndex * 64 + vec2.y * 8 + vec2.x];
sp02 = gBoardConfig.fieldLayout.collisionTypeMap[boardLayer + tileMapPage][collisionTileIndex * 64 + vec2.y * 8 + vec2.x];
CheckKecleonEntityCollision(arg0, &sp00, &sp02);
switch_enum = sp02 & 0xF;
some_enum = sp02 >> 4;
switch (switch_enum)
{
case 1:
case 4:
case 6:
gCurrentPinballGame->collisionSurfaceType = switch_enum - 1;
gCurrentPinballGame->collisionResponseType = 1;
*arg1 = sp00;
return_val = 1;
break;
case 2:
case 3:
gCurrentPinballGame->collisionSurfaceType = 0;
gCurrentPinballGame->collisionResponseType = 1;
*arg1 = sp00 & 0x0000FFF0;
return_val = 1;
if (gCurrentPinballGame->kecleonBoardHitState == 0)
{
s32 kecleonActive = gCurrentPinballGame->kecleonTargetActive;
if (kecleonActive == 0)
{
gCurrentPinballGame->kecleonBoardHitState = 1;
gCurrentPinballGame->kecleonCollisionX = kecleonActive;
}
}
gCurrentPinballGame->kecleonCollisionY = 40;
break;
case 5:
some_enum = 4;
break;
}
ProcessKecleonCollisionEvent(some_enum, &return_val, arg1);
return return_val;
}
void CheckKecleonEntityCollision(struct Vector16 *arg0, u16 *arg1, u8 *arg2)
{
s16 deltaX;
s16 deltaY;
u16 arrayValue;
if (gCurrentPinballGame->boardEntityCollisionMode == 1)
{
if (*arg2 & 0xF)
return;
deltaX = arg0->x - gCurrentPinballGame->bossCollisionX;
deltaY = arg0->y - gCurrentPinballGame->bossCollisionY;
if ((deltaX < 0 || deltaX > 0x3F) || (deltaY < 0 || deltaY > 0x57))
return;
arrayValue = (u8)(gKecleonTongueCollisionMap[(deltaY * 0x40) + deltaX]) & 0xF;
if (arrayValue == 0)
return;
if (gCurrentPinballGame->ball->ballHidden != 0)
return;
if (gCurrentPinballGame->bossEntityState > 8)
return;
gCurrentPinballGame->bossEntityState = 9;
}
else if (gCurrentPinballGame->boardEntityCollisionMode == 2)
{
u16 maskedResult;
if (*arg2 & 0xF)
return;
deltaX = arg0->x - gCurrentPinballGame->bossCollisionX;
deltaY = arg0->y - gCurrentPinballGame->bossCollisionY;
if ((deltaX < 0 || deltaX > 0x57) || (deltaY < 0 || deltaY > 0x3F))
return;
maskedResult = gKecleonBodyCollisionMap[(deltaY * 0x58) + deltaX] & 0xFFF0;
arrayValue = gKecleonBodyCollisionMap[(deltaY * 0x58) + deltaX] & 0xF;
if (arrayValue == 0)
return;
if (gCurrentPinballGame->ball->ballHidden != 0)
return;
if (gCurrentPinballGame->bossEntityState == 12)
return;
gCurrentPinballGame->bossEntityState = 11;
*arg1 = maskedResult;
*arg2 = 6;
}
}
void ProcessKecleonCollisionEvent(u8 arg0, u16 *arg1, u16 *arg2)
{
s16 x, y;
x = gCurrentPinballGame->ball->positionQ0.x;
y = gCurrentPinballGame->ball->positionQ0.y;
switch (arg0)
{
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 13:
case 14:
case 15:
return;
case 8:
if (x <= 0x72)
{
if (y <= 0x38)
{
if (gCurrentPinballGame->kecleonBerryLargeFlashTimer[0] <= 0)
gCurrentPinballGame->kecleonBerryLargeFlashTimer[0] = 0x18;
}
else
{
if (gCurrentPinballGame->kecleonBerryLargeFlashTimer[1] <= 0)
gCurrentPinballGame->kecleonBerryLargeFlashTimer[1] = 0x18;
}
}
else if (y <= 0x63)
{
if (gCurrentPinballGame->kecleonBerryLargeFlashTimer[3] <= 0)
gCurrentPinballGame->kecleonBerryLargeFlashTimer[3] = 0x18;
}
else
{
if (gCurrentPinballGame->kecleonBerryLargeFlashTimer[2] <= 0)
gCurrentPinballGame->kecleonBerryLargeFlashTimer[2] = 0x18;
}
break;
case 9:
if (x <= 0x72)
{
if (y <= 0x45)
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[7] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[7] = 0x18;
}
else
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[5] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[5] = 0x18;
}
}
else if (y <= 0x45)
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[8] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[8] = 0x18;
}
else
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[0] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[0] = 0x18;
}
break;
case 10:
if (gCurrentPinballGame->kecleonHitboxX == 0)
{
gCurrentPinballGame->kecleonHitSparkTimer[0] = 0xB;
gCurrentPinballGame->ballTrailPosition[0].x = gCurrentPinballGame->ball->positionQ0.x - 7;
gCurrentPinballGame->ballTrailPosition[0].y = gCurrentPinballGame->ball->positionQ0.y - 7;
}
else if (gCurrentPinballGame->kecleonHitboxX == 3)
{
gCurrentPinballGame->kecleonHitSparkTimer[1] = 0xB;
gCurrentPinballGame->ballTrailPosition[1].x = gCurrentPinballGame->ball->positionQ0.x - 7;
gCurrentPinballGame->ballTrailPosition[1].y = gCurrentPinballGame->ball->positionQ0.y - 7;
}
else if (gCurrentPinballGame->kecleonHitboxX == 6)
{
gCurrentPinballGame->kecleonHitSparkTimer[2] = 0xB;
gCurrentPinballGame->ballTrailPosition[2].x = gCurrentPinballGame->ball->positionQ0.x - 7;
gCurrentPinballGame->ballTrailPosition[2].y = gCurrentPinballGame->ball->positionQ0.y - 7;
}
else if (gCurrentPinballGame->kecleonHitboxX == 9)
{
gCurrentPinballGame->kecleonHitSparkTimer[3] = 0xB;
gCurrentPinballGame->ballTrailPosition[3].x = gCurrentPinballGame->ball->positionQ0.x - 7;
gCurrentPinballGame->ballTrailPosition[3].y = gCurrentPinballGame->ball->positionQ0.y - 7;
}
break;
case 11:
if (x <= 0x72)
{
if (y <= 0x45)
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[9] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[9] = 0x18;
}
else
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[2] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[2] = 0x18;
}
}
else if (y <= 0x45)
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[6] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[6] = 0x18;
}
else
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[1] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[1] = 0x18;
}
break;
case 12:
if (x <= 0x72)
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[4] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[4] = 0x18;
}
else
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[3] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[3] = 0x18;
}
break;
}
}
void CheckKecleonProjectileCollision(struct Vector16 *arg0)
{
struct Vector16 vec1;
struct Vector16 vec2;
s16 x, y;
u16 sp00;
u8 sp02;
s16 collisionTileIndex;
s32 tileMapPage;
s32 boardLayer;
u32 some_enum;
gCurrentPinballGame->kecleonCollisionEnabled = 1;
vec1.x = arg0->x / 8;
vec1.y = arg0->y / 8;
vec2.x = arg0->x % 8;
vec2.y = arg0->y % 8;
tileMapPage = vec1.y / 64;
boardLayer = gCurrentPinballGame->boardLayerDepth;
vec1.y %= 64;
collisionTileIndex = gBoardConfig.fieldLayout.collisionTileMap[boardLayer + tileMapPage][vec1.y * 64 + vec1.x];
sp00 = gBoardConfig.fieldLayout.collisionAngleMap[boardLayer + tileMapPage][collisionTileIndex * 64 + vec2.y * 8 + vec2.x];
sp02 = gBoardConfig.fieldLayout.collisionTypeMap[boardLayer + tileMapPage][collisionTileIndex * 64 + vec2.y * 8 + vec2.x];
some_enum = (sp02 >> 2) >> 2;
x = gCurrentPinballGame->kecleonCollisionPos.x;
y = gCurrentPinballGame->kecleonCollisionPos.y;
switch (some_enum)
{
case 8:
if (x <= 0x72)
{
if (y <= 0x38)
{
if (gCurrentPinballGame->kecleonBerryLargeFlashTimer[0] <= 0)
gCurrentPinballGame->kecleonBerryLargeFlashTimer[0] = 0x18;
}
else
{
if (gCurrentPinballGame->kecleonBerryLargeFlashTimer[1] <= 0)
gCurrentPinballGame->kecleonBerryLargeFlashTimer[1] = 0x18;
}
}
else if (y <= 0x63)
{
if (gCurrentPinballGame->kecleonBerryLargeFlashTimer[3] <= 0)
gCurrentPinballGame->kecleonBerryLargeFlashTimer[3] = 0x18;
}
else
{
if (gCurrentPinballGame->kecleonBerryLargeFlashTimer[2] <= 0)
gCurrentPinballGame->kecleonBerryLargeFlashTimer[2] = 0x18;
}
break;
case 9:
if (x <= 0x72)
{
if (y <= 0x45)
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[7] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[7] = 0x18;
}
else
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[5] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[5] = 0x18;
}
}
else if (y <= 0x45)
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[8] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[8] = 0x18;
}
else
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[0] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[0] = 0x18;
}
break;
case 10:
gCurrentPinballGame->kecleonCollisionEnabled = 0;
if (gCurrentPinballGame->kecleonHitboxY == 0)
{
if (gCurrentPinballGame->kecleonCollisionPos.x != gCurrentPinballGame->kecleonBerryHitPosition[0].x || gCurrentPinballGame->kecleonCollisionPos.y != gCurrentPinballGame->kecleonBerryHitPosition[0].y)
{
gCurrentPinballGame->kecleonHitSparkTimer[4] = 0x11;
gCurrentPinballGame->kecleonBerryHitPosition[0].x = gCurrentPinballGame->kecleonCollisionPos.x;
gCurrentPinballGame->kecleonBerryHitPosition[0].y = gCurrentPinballGame->kecleonCollisionPos.y;
}
}
else if (gCurrentPinballGame->kecleonHitboxY == 8)
{
if (gCurrentPinballGame->kecleonCollisionPos.x != gCurrentPinballGame->kecleonBerryHitPosition[1].x || gCurrentPinballGame->kecleonCollisionPos.y != gCurrentPinballGame->kecleonBerryHitPosition[1].y)
{
gCurrentPinballGame->kecleonHitSparkTimer[5] = 0x11;
gCurrentPinballGame->kecleonBerryHitPosition[1].x = gCurrentPinballGame->kecleonCollisionPos.x;
gCurrentPinballGame->kecleonBerryHitPosition[1].y = gCurrentPinballGame->kecleonCollisionPos.y;
}
}
else if (gCurrentPinballGame->kecleonHitboxY == 16)
{
if (gCurrentPinballGame->kecleonCollisionPos.x != gCurrentPinballGame->kecleonBerryHitPosition[2].x || gCurrentPinballGame->kecleonCollisionPos.y != gCurrentPinballGame->kecleonBerryHitPosition[2].y)
{
gCurrentPinballGame->kecleonHitSparkTimer[6] = 0x11;
gCurrentPinballGame->kecleonBerryHitPosition[2].x = gCurrentPinballGame->kecleonCollisionPos.x;
gCurrentPinballGame->kecleonBerryHitPosition[2].y = gCurrentPinballGame->kecleonCollisionPos.y;
}
}
break;
case 11:
if (x <= 0x72)
{
if (y <= 0x45)
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[9] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[9] = 0x18;
}
else
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[2] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[2] = 0x18;
}
}
else if (y <= 0x45)
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[6] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[6] = 0x18;
}
else
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[1] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[1] = 0x18;
}
break;
case 12:
if (x <= 0x72)
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[4] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[4] = 0x18;
}
else
{
if (gCurrentPinballGame->kecleonBerrySmallFlashTimer[3] <= 0)
gCurrentPinballGame->kecleonBerrySmallFlashTimer[3] = 0x18;
}
break;
}
}

198
src/collision_kyogre.c Normal file
View File

@ -0,0 +1,198 @@
#include "global.h"
#include "main.h"
s16 CollisionCheck_Kyogre(struct Vector16 *arg0, u16 *arg1)
{
struct Vector16 vec1;
struct Vector16 vec2;
u16 sp00;
u8 sp02;
u16 return_val;
s16 collisionTileIndex;
s32 tileMapPage;
s32 boardLayer;
u32 some_enum;
u32 switch_enum;
return_val = 0;
gCurrentPinballGame->ball->spinAcceleration = 0;
if (arg0->y < 0x200)
{
vec1.x = arg0->x / 8;
vec1.y = arg0->y / 8;
vec2.x = arg0->x % 8;
vec2.y = arg0->y % 8;
tileMapPage = vec1.y / 64;
boardLayer = gCurrentPinballGame->boardLayerDepth;
vec1.y %= 64;
collisionTileIndex = gBoardConfig.fieldLayout.collisionTileMap[boardLayer + tileMapPage][vec1.y * 64 + vec1.x];
sp00 = gBoardConfig.fieldLayout.collisionAngleMap[boardLayer + tileMapPage][collisionTileIndex * 64 + vec2.y * 8 + vec2.x];
sp02 = gBoardConfig.fieldLayout.collisionTypeMap[boardLayer + tileMapPage][collisionTileIndex * 64 + vec2.y * 8 + vec2.x];
}
else
{
sp00 = 0;
sp02 = 0;
}
CheckKyogreEntityCollision(arg0, &sp00, &sp02);
switch_enum = sp02 & 0xF;
some_enum = sp02 >> 4;
switch (switch_enum)
{
case 1:
case 4:
case 6:
gCurrentPinballGame->collisionSurfaceType = switch_enum - 1;
gCurrentPinballGame->collisionResponseType = 1;
*arg1 = sp00;
if (*arg1 >= 0x3FF0 && *arg1 <= 0x4010)
{
if (gCurrentPinballGame->ball->positionQ0.x < gBoardConfig.fieldLayout.ballSpawnX - 8 ||
gCurrentPinballGame->ball->positionQ0.y < gBoardConfig.fieldLayout.ballSpawnY - 8)
{
if (gCurrentPinballGame->ball->spinSpeed > 0)
{
*arg1 = 0x3E00;
}
else if (gCurrentPinballGame->ball->spinSpeed != 0)
{
*arg1 = 0x4100;
}
else
{
if (gMain.systemFrameCount & 1)
{
gCurrentPinballGame->ball->spinAcceleration = 0x28;
gCurrentPinballGame->ball->spinSpeed = 1;
*arg1 = 0x3E00;
}
else
{
gCurrentPinballGame->ball->spinAcceleration = 0xFFD8;
gCurrentPinballGame->ball->spinSpeed = 0xFFFF;
*arg1 = 0x4100;
}
}
}
}
return_val = 1;
break;
case 2:
case 3:
gCurrentPinballGame->collisionSurfaceType = switch_enum - 1;
gCurrentPinballGame->collisionResponseType = 2;
*arg1 = sp00 & 0x0000FFF0;
return_val = 1;
break;
case 5:
some_enum = 4;
break;
}
ProcessKyogreCollisionEvent(some_enum, &return_val, arg1);
return return_val;
}
void CheckKyogreEntityCollision(struct Vector16 *arg0, u16 *arg1, u8 *arg2)
{
s16 deltaX;
s16 deltaY;
u16 arrayValue;
u16 maskedResult;
if (gCurrentPinballGame->boardEntityCollisionMode == 1)
{
if (*arg2 & 0xF)
return;
deltaX = arg0->x - gCurrentPinballGame->bossCollisionX;
deltaY = arg0->y - gCurrentPinballGame->bossCollisionY;
if ((deltaX < 0 || deltaX >= 0x78) || (deltaY < 0 || deltaY >= 0x98))
return;
maskedResult = gKyogreForm1CollisionMap[(deltaY * 0x78) + deltaX] & 0xFFF0;
arrayValue = gKyogreForm1CollisionMap[(deltaY * 0x78) + deltaX] & 0xF;
if (arrayValue == 0)
return;
gCurrentPinballGame->bossHitFlashTimer = 8;
*arg1 = maskedResult;
*arg2 = 6;
}
else if (gCurrentPinballGame->boardEntityCollisionMode == 2)
{
if (*arg2 & 0xF)
return;
deltaX = arg0->x - gCurrentPinballGame->bossCollisionX;
deltaY = arg0->y - gCurrentPinballGame->bossCollisionY;
if ((deltaX < 0 || deltaX >= 0x60) || (deltaY < 0 || deltaY >= 0x58))
return;
maskedResult = gKyogreForm2CollisionMap[(deltaY * 0x60) + deltaX] & 0xFFF0;
arrayValue = gKyogreForm2CollisionMap[(deltaY * 0x60) + deltaX] & 0xF;
if (arrayValue == 0)
return;
gCurrentPinballGame->bossHitFlashTimer = 8;
*arg1 = maskedResult;
*arg2 = 6;
}
else if (gCurrentPinballGame->boardEntityCollisionMode == 3)
{
if (*arg2 & 0xF)
return;
deltaX = arg0->x - gCurrentPinballGame->bossCollisionX;
deltaY = arg0->y - gCurrentPinballGame->bossCollisionY;
if ((deltaX < 0 || deltaX >= 0x60) || (deltaY < 0 || deltaY >= 0x68))
return;
maskedResult = gKyogreForm3CollisionMap[(deltaY * 0x60) + deltaX] & 0xFFF0;
arrayValue = gKyogreForm3CollisionMap[(deltaY * 0x60) + deltaX] & 0xF;
if (arrayValue == 0)
return;
gCurrentPinballGame->bossHitFlashTimer = 8;
*arg1 = maskedResult;
*arg2 = 6;
}
}
void ProcessKyogreCollisionEvent(u8 arg0, u16 *arg1, u16 *arg2)
{
switch (arg0)
{
case 1:
case 2:
case 3:
break;
case 4:
gCurrentPinballGame->bossEntityState = 6;
gCurrentPinballGame->ballFrozenState = 1;
break;
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
break;
}
}

153
src/collision_rayquaza.c Normal file
View File

@ -0,0 +1,153 @@
#include "global.h"
#include "main.h"
//One known callsite is 080145D2 during the rayquaza bonus stage
s16 CollisionCheck_Rayquaza(struct Vector16 *arg0, u16 *arg1)
{
struct Vector16 vec1;
struct Vector16 vec2;
u16 sp00;
u8 sp02;
u16 return_val;
u32 some_enum;
u32 switch_enum;
return_val = 0;
gCurrentPinballGame->ball->spinAcceleration = 0;
if (arg0->y < 0x200)
{
s16 r2;
s32 tileMapPage;
s32 boardLayer;
vec1.x = arg0->x / 8;
vec1.y = arg0->y / 8;
vec2.x = arg0->x % 8;
vec2.y = arg0->y % 8;
tileMapPage = vec1.y / 64;
boardLayer = gCurrentPinballGame->boardLayerDepth;
vec1.y %= 64;
r2 = gBoardConfig.fieldLayout.collisionTileMap[boardLayer + tileMapPage][vec1.y * 64 + vec1.x];
sp00 = gBoardConfig.fieldLayout.collisionAngleMap[boardLayer + tileMapPage][r2 * 64 + vec2.y * 8 + vec2.x];
sp02 = gBoardConfig.fieldLayout.collisionTypeMap[boardLayer + tileMapPage][r2 * 64 + vec2.y * 8 + vec2.x];
}
else
{
sp00 = 0;
sp02 = 0;
}
CheckRayquazaEntityCollision(arg0, &sp00, &sp02);
switch_enum = sp02 & 0xF;
some_enum = sp02 >> 4;
switch (switch_enum)
{
case 1:
case 4:
case 6:
gCurrentPinballGame->collisionSurfaceType = switch_enum - 1;
gCurrentPinballGame->collisionResponseType = 1;
*arg1 = sp00;
if (*arg1 >= 0x3FF0 && *arg1 <= 0x4010)
{
if (gCurrentPinballGame->ball->positionQ0.x < (gBoardConfig.fieldLayout.ballSpawnX - 8) || gCurrentPinballGame->ball->positionQ0.y < gBoardConfig.fieldLayout.ballSpawnY - 8)
{
if (gCurrentPinballGame->ball->spinSpeed > 0)
{
*arg1 = 0x3E00;
}
else if (gCurrentPinballGame->ball->spinSpeed != 0)
{
*arg1 = 0x4100;
}
else
{
if (gMain.systemFrameCount & 1)
{
gCurrentPinballGame->ball->spinAcceleration = 40;
gCurrentPinballGame->ball->spinSpeed = 1;
*arg1 = 0x3E00;
}
else
{
gCurrentPinballGame->ball->spinAcceleration = -40;
gCurrentPinballGame->ball->spinSpeed = -1;
*arg1 = 0x4100;
}
}
}
}
return_val = 1;
break;
case 2:
case 3:
gCurrentPinballGame->collisionSurfaceType = switch_enum - 1;
gCurrentPinballGame->collisionResponseType = 2;
*arg1 = sp00 & 0xFFF0;
return_val = 1;
break;
case 5:
some_enum = 4;
break;
}
ProcessRayquazaCollisionEvent(some_enum, &return_val, arg1);
return return_val;
}
void CheckRayquazaEntityCollision(struct Vector16 *arg0, u16 *arg1, u8 *arg2)
{
s16 deltaX;
s16 deltaY;
u16 maskedResult;
u16 lowerNibble;
if (gCurrentPinballGame->boardEntityCollisionMode != 1)
return;
if (*arg2 & 0xF)
return;
deltaX = arg0->x - gCurrentPinballGame->bossCollisionX;
deltaY = arg0->y - gCurrentPinballGame->bossCollisionY;
if ((deltaX < 0 || deltaX >= 0x80) || (deltaY < 0 || deltaY >= 0x80))
return;
maskedResult = gRayquazaBodyCollisionMap[(deltaY * 0x80) + deltaX] & 0xFFF0;
lowerNibble = gRayquazaBodyCollisionMap[(deltaY * 0x80) + deltaX] & 0xF;
if (lowerNibble == 0)
return;
gCurrentPinballGame->bossHitFlashTimer = 9;
*arg1 = maskedResult;
*arg2 = lowerNibble;
}
void ProcessRayquazaCollisionEvent(u8 arg0, u16 *arg1, u16 *arg2)
{
switch (arg0)
{
case 1:
case 2:
case 3:
break;
case 4:
gCurrentPinballGame->bossEntityState = 6;
gCurrentPinballGame->ballFrozenState = 1;
break;
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
break;
}
}

842
src/collision_ruby.c Normal file
View File

@ -0,0 +1,842 @@
#include "global.h"
#include "main.h"
#include "m4a.h"
#include "constants/bg_music.h"
#include "constants/ruby_states.h"
extern const u16 gRubyAltEntity0CollisionMap[];
extern const u16 gRubyAltEntity1CollisionMap[];
extern const u16 gWhiscashCollisionMap[];
extern struct SongHeader se_unk_99;
s16 CollisionCheck_Ruby(struct Vector16 *arg0, u16* arg1) {
struct Vector16 vec1;
struct Vector16 vec2;
u16 sp00;
u8 sp02;
u16 return_val;
s16 collisionTileIndex;
s32 tileMapPage;
s32 boardLayer;
u32 some_enum;
u32 switch_enum;
return_val = 0;
gCurrentPinballGame->ball->spinAcceleration = 0;
vec1.x = arg0->x / 8;
vec1.y = arg0->y / 8;
vec2.x = arg0->x % 8;
vec2.y = arg0->y % 8;
tileMapPage = vec1.y / 64;
boardLayer = gCurrentPinballGame->boardLayerDepth;
vec1.y %= 64;
collisionTileIndex = gBoardConfig.fieldLayout.collisionTileMap[boardLayer + tileMapPage][vec1.y * 64 + vec1.x];
sp00 = gBoardConfig.fieldLayout.collisionAngleMap[boardLayer + tileMapPage][collisionTileIndex * 64 + vec2.y * 8 + vec2.x];
sp02 = gBoardConfig.fieldLayout.collisionTypeMap[boardLayer + tileMapPage][collisionTileIndex * 64 + vec2.y * 8 + vec2.x];
CheckRubyPondBumperCollision(arg0, &sp00, &sp02);
switch_enum = sp02 & 0xF;
some_enum = sp02 >> 4;
switch (switch_enum-1) {
case 0:
case 3:
case 5:
gCurrentPinballGame->collisionSurfaceType = (switch_enum - 1);
gCurrentPinballGame->collisionResponseType = 1;
*arg1 = sp00;
if (*arg1 >= 0x3FF0 && *arg1 <= 0x4010)
{
if (gCurrentPinballGame->ball->positionQ0.x < gBoardConfig.fieldLayout.ballSpawnX - 8 ||
gCurrentPinballGame->ball->positionQ0.y < gBoardConfig.fieldLayout.ballSpawnY - 8)
{
if (gCurrentPinballGame->ball->spinSpeed > 0)
{
*arg1 = 0x3E00;
}
else if (gCurrentPinballGame->ball->spinSpeed != 0)
{
*arg1 = 0x4100;
}
else
{
if (gMain.systemFrameCount & 1)
{
gCurrentPinballGame->ball->spinAcceleration = 0x28;
gCurrentPinballGame->ball->spinSpeed = 1;
*arg1 = 0x3E00;
}
else
{
gCurrentPinballGame->ball->spinAcceleration = 0xFFD8;
gCurrentPinballGame->ball->spinSpeed = 0xFFFF;
*arg1 = 0x4100;
}
}
}
}
return_val = 1;
break;
case 1:
case 2:
gCurrentPinballGame->collisionSurfaceType = switch_enum - 1;
gCurrentPinballGame->collisionResponseType = 2;
*arg1 = sp00 & 0x0000FFF0;
return_val = 1;
break;
case 4:
gCurrentPinballGame->whiscashState = WHISCASH_STATE_ABSORB_ZONE_HIT;
gCurrentPinballGame->ballFrozenState = 1;
some_enum = 0;
break;
}
ProcessRubyCollisionEvent((s32) some_enum, &return_val, arg1);
return return_val;
}
void CheckRubyPondBumperCollision(struct Vector16* arg0, u16* arg1, u8* arg2)
{
s16 deltaX;
s16 deltaY;
u16 maskedResult;
u8 lowerNibble;
s32 ix;
maskedResult = 0;
lowerNibble = 0;
ix = 0;
if (gCurrentPinballGame->ballInLowerHalf == 0)
{
if (gCurrentPinballGame->boardLayerDepth != 0)
return;
if (gCurrentPinballGame->shouldProcessWhiscash)
{
if (gCurrentPinballGame->whiscashInvulnerable == 0)
return;
deltaX = arg0->x + gCurrentPinballGame->rubyBumperCollisionPosition[0].x;
deltaY = arg0->y + gCurrentPinballGame->rubyBumperCollisionPosition[0].y;
if (deltaX > 79U)
return;
if (deltaY > 87U)
return;
maskedResult = 0xFFF0 & gWhiscashCollisionMap[(deltaY * 80) + deltaX];
lowerNibble = 0xF & gWhiscashCollisionMap[(deltaY * 80) + deltaX];
if (lowerNibble == 0)
return;
*arg1 = maskedResult;
// if hit, while in its base mode, processes as a hit.
// A Ball in the area being sucked in, or already hitting it won't affect it.
if (gCurrentPinballGame->whiscashState <= WHISCASH_STATE_SITTING)
{
*arg2 = lowerNibble;
gCurrentPinballGame->whiscashState = WHISCASH_STATE_HIT;
return;
}
*arg2 = 1;
return;
}
if (0xF & *arg2)
return;
deltaX = arg0->x + (u16) gCurrentPinballGame->rubyBumperCollisionPosition[0].x;
deltaY = arg0->y + (u16) gCurrentPinballGame->rubyBumperCollisionPosition[0].y;
if (deltaX <= 63U && deltaY <= 63U)
{
maskedResult = 0xFFF0 & gSharedBumperCollisionMap[(deltaY * 64) + deltaX];
lowerNibble = 0xF & gSharedBumperCollisionMap[(deltaY * 64) + deltaX];
if (lowerNibble != 0)
ix = 0;
}
if (lowerNibble == 0)
{
deltaX = gCurrentPinballGame->rubyBumperCollisionPosition[1].x + arg0->x;
deltaY = gCurrentPinballGame->rubyBumperCollisionPosition[1].y + arg0->y;
if (deltaX <= 63U && deltaY <= 63U)
{
maskedResult = 0xFFF0 & gSharedBumperCollisionMap[(deltaY * 64) + deltaX];
lowerNibble = 0xF & gSharedBumperCollisionMap[(deltaY * 64) + deltaX];
if (lowerNibble != 0)
ix = 1;
}
if (lowerNibble == 0)
{
deltaX = gCurrentPinballGame->rubyBumperCollisionPosition[2].x + arg0->x;
deltaY = gCurrentPinballGame->rubyBumperCollisionPosition[2].y + arg0->y;
if (deltaX <= 63U && deltaY <= 63U)
{
maskedResult = 0xFFF0 & gSharedBumperCollisionMap[(deltaY * 64) + deltaX];
lowerNibble = 0xF & gSharedBumperCollisionMap[(deltaY * 64) + deltaX];
if (lowerNibble == 0)
return;
ix = 2;
}
if (lowerNibble == 0)
return;
}
}
if (!gCurrentPinballGame->rubyPondContentsChanging)
gCurrentPinballGame->pondBumperStates[ix] = 107;
*arg1 = maskedResult;
*arg2 = lowerNibble;
if (gCurrentPinballGame->bumperHitCountdown > 0)
return;
gCurrentPinballGame->bumperHitCountdown = 2;
}
else
{
if ((*arg2 & 0xF) == 0)
{
if (gCurrentPinballGame->sideBumperAnimPhase[0] > 0)
{
s16 deltaY_alt;
deltaX = 2 * (-24 -gCurrentPinballGame->sideBumperShakeOffset[0]) + arg0->x;
deltaY_alt = arg0->y -580;
if (deltaX <= 71U && deltaY_alt <= 71U)
{
*arg1 = 0xFFF0 & gRubyAltEntity0CollisionMap[(deltaY_alt * 72) + deltaX];
*arg2 = 0xF & gRubyAltEntity0CollisionMap[(deltaY_alt * 72) + deltaX];
if (*arg2 & 1)
{
gCurrentPinballGame->sideBumperHitFlag = 1;
*arg2 = 6;
}
}
}
if (gCurrentPinballGame->sideBumperAnimPhase[1] > 0)
{
deltaX = ((gCurrentPinballGame->sideBumperShakeOffset[1] - 180) * 2) + arg0->x;
deltaY = arg0->y -580;
if (deltaX <= 71U && deltaY <= 71U)
{
*arg1 = 0xFFF0 & gRubyAltEntity1CollisionMap[(deltaY * 72) + deltaX];
*arg2 = 0xF & gRubyAltEntity1CollisionMap[(deltaY * 72) + deltaX];
if (*arg2 & 1)
{
gCurrentPinballGame->sideBumperHitFlag = 2;
*arg2 = 6;
return;
}
}
}
}
}
}
void ProcessRubyCollisionEvent(s32 arg0, s16* arg1, u16* arg2)
{
s16 absVelY;
switch ((u8)arg0 - 1)
{
case 0:
if (gCurrentPinballGame->collisionCooldownTimer == 0)
{
if (gCurrentPinballGame->ball->positionQ1.x > 359)
{
if (gCurrentPinballGame->ball->positionQ1.y > 199)
gCurrentPinballGame->ballCatchState = 1;
else
gCurrentPinballGame->ballCatchState = 3;
}
else
gCurrentPinballGame->ballCatchState= 2;
DispatchRubyCatchModeInit();
gCurrentPinballGame->collisionResponseType = 7;
*arg1 = 1;
return;
}
default:
return;
case 1:
if (gCurrentPinballGame->boardLayerDepth == 0)
{
gCurrentPinballGame->ball->oamPriority = 2;
gCurrentPinballGame->boardLayerDepth = 2;
break;
}
if (gCurrentPinballGame->boardLayerDepth == 2)
{
gCurrentPinballGame->ball->oamPriority = 2;
gCurrentPinballGame->boardLayerDepth = 3;
}
break;
case 2:
if (gCurrentPinballGame->boardLayerDepth == 2)
{
gCurrentPinballGame->ball->oamPriority = 3;
gCurrentPinballGame->boardLayerDepth = 0;
}
else if (gCurrentPinballGame->boardLayerDepth == 3)
{
gCurrentPinballGame->ball->oamPriority = 2;
gCurrentPinballGame->boardLayerDepth = 2;
}
if (gCurrentPinballGame->nuzleafAnimState == 6)
gCurrentPinballGame->nuzleafAnimState = 7;
if (gCurrentPinballGame->shopDoorTargetFrame & 0xF0 )
gCurrentPinballGame->shopDoorTargetFrame = 0;
if (gCurrentPinballGame->shopDoorOpenLevel & 0xF0)
gCurrentPinballGame->shopDoorOpenLevel = 0;
break;
case 3:
if (gCurrentPinballGame->mainBoardCountdownTimer == 0)
{
if (gCurrentPinballGame->ball->positionQ0.x > 131)
{
gCurrentPinballGame->scoreAddedInFrame = 1000;
if (gCurrentPinballGame->progressLevel <= 98)
gCurrentPinballGame->progressLevel++;
}
else if (gCurrentPinballGame->ball->positionQ0.x > 91)
{
gCurrentPinballGame->scoreAddedInFrame = 2000;
gCurrentPinballGame->rubyPondChangeTimer = 0;
gCurrentPinballGame->rubyPondContentsChanging = TRUE;
}
else
{
gCurrentPinballGame->scoreAddedInFrame = 1000;
if (gCurrentPinballGame->chikoritaFlashActive == 0)
{
gCurrentPinballGame->chikoritaFlashActive = 1;
gCurrentPinballGame->chikoritaFlashTimer = 0;
}
}
gCurrentPinballGame->mainBoardCountdownTimer = 45;
m4aSongNumStart(SE_TRIGGER_BUTTON_HIT);
}
break;
case 4:
gCurrentPinballGame->ballInLaunchChute = 1;
gCurrentPinballGame->ballTouchingSpoink = 1;
gCurrentPinballGame->ballCollisionZone = 0;
return;
case 5:
if (gCurrentPinballGame->ballInLowerHalf == 0)
{
SetBoardCollisionConfig(1);
gCurrentPinballGame->boardCollisionConfigChanged = 1;
}
break;
case 6:
if (gCurrentPinballGame->ball->positionQ0.x < 50)
{
if (gCurrentPinballGame->nuzleafHitFlag == 0)
{
gCurrentPinballGame->nuzleafHitFlag = 1;
gCurrentPinballGame->nuzleafAnimState = 1;
gCurrentPinballGame->collisionSurfaceType = 0;
gCurrentPinballGame->collisionResponseType = 2;
*arg2 = 0xB000;
*arg1 = 1;
}
}
else if (gCurrentPinballGame->nuzleafHitFlag == 1)
{
gCurrentPinballGame->nuzleafHitFlag = 2;
gCurrentPinballGame->nuzleafAnimState = 3;
gCurrentPinballGame->collisionSurfaceType = 0;
gCurrentPinballGame->collisionResponseType = 2;
*arg2 = 0xA000;
*arg1 = 1;
gCurrentPinballGame->ball->velocity.x = 0;
gCurrentPinballGame->ball->velocity.y = 0;
memcpy(&gCurrentPinballGame->ballStates[1], gCurrentPinballGame->ballStates, 0x44U);
gCurrentPinballGame->secondaryBall = &gCurrentPinballGame->ballStates[1];
gCurrentPinballGame->ballLaunchTimer = 120;
}
gCurrentPinballGame->ballCollisionZone = 14;
return;
case 7:
if (gCurrentPinballGame->ball->positionQ0.x <= 50)
{
if (gCurrentPinballGame->ballCollisionZone == 8)
{
if (gCurrentPinballGame->boardState <= 2 && gCurrentPinballGame->evoArrowProgress <= 2)
{
if (gCurrentPinballGame->evoArrowProgress == 0)
gCurrentPinballGame->scoreAddedInFrame = 2000;
else if (gCurrentPinballGame->evoArrowProgress == 1)
gCurrentPinballGame->scoreAddedInFrame = 5000;
else
gCurrentPinballGame->scoreAddedInFrame = 10000;
gCurrentPinballGame->evoArrowProgress++;
m4aSongNumStart(SE_UNKNOWN_0x99);
}
gCurrentPinballGame->travelRouletteSlotHitType = 1;
}
gCurrentPinballGame->ballCollisionZone = 2;
return;
}
if (gCurrentPinballGame->ball->positionQ0.x <= 100)
{
if (gCurrentPinballGame->ballCollisionZone == 7)
{
gCurrentPinballGame->coinRewardAmount = 10;
if(gCurrentPinballGame->coinRewardLevel <= 2)
{
if(gCurrentPinballGame->coinRewardLevel == 0)
{
gCurrentPinballGame->scoreAddedInFrame = 2000;
gCurrentPinballGame->coinRewardAmount = 1;
}
else if(gCurrentPinballGame->coinRewardLevel == 1)
{
gCurrentPinballGame->scoreAddedInFrame = 5000;
gCurrentPinballGame->coinRewardAmount = 5;
}
else
{
gCurrentPinballGame->scoreAddedInFrame = 10000;
gCurrentPinballGame->coinRewardAmount = 10;
}
gCurrentPinballGame->coinRewardLevel++;
}
gCurrentPinballGame->coinRewardTimer = 0;
gCurrentPinballGame->coinRewardLevelTimer = 0;
}
gCurrentPinballGame->ballCollisionZone = 1;
return;
}
if (gCurrentPinballGame->ball->positionQ0.x <= 126)
{
if (gCurrentPinballGame->ballPowerUpLight[0] == 0)
gCurrentPinballGame->scoreAddedInFrame = 1000;
gCurrentPinballGame->ballPowerUpLight[0] = 1;
gCurrentPinballGame->ballCollisionZone = 3;
if (gCurrentPinballGame->ballPowerUpAnimActive == 0)
{
if (!(gCurrentPinballGame->ballPowerUpLight[1] &
gCurrentPinballGame->ballPowerUpLight[2]))
return;
gCurrentPinballGame->ballPowerUpAnimActive = 1;
gCurrentPinballGame->ballShadowTimer = 60;
gCurrentPinballGame->scoreAddedInFrame = 4000;
return;
}
}
else
{
if (gCurrentPinballGame->ball->positionQ0.x <= 148)
{
if (gCurrentPinballGame->ballPowerUpLight[1] == 0)
gCurrentPinballGame->scoreAddedInFrame = 1000;
gCurrentPinballGame->ballPowerUpLight[1] = 1;
gCurrentPinballGame->ballCollisionZone = 4;
if (gCurrentPinballGame->ballPowerUpAnimActive != 0)
return;
if (!(gCurrentPinballGame->ballPowerUpLight[0] &
gCurrentPinballGame->ballPowerUpLight[2]))
return;
gCurrentPinballGame->ballPowerUpAnimActive = 1;
gCurrentPinballGame->ballShadowTimer = 60;
gCurrentPinballGame->scoreAddedInFrame = 4000;
return;
}
if (gCurrentPinballGame->ball->positionQ0.x <= 172)
{
if (gCurrentPinballGame->ballPowerUpLight[2] == 0)
gCurrentPinballGame->scoreAddedInFrame = 1000;
gCurrentPinballGame->ballPowerUpLight[2] = 1;
gCurrentPinballGame->ballCollisionZone = 5;
if (gCurrentPinballGame->ballPowerUpAnimActive != 0)
return;
if (!(gCurrentPinballGame->ballPowerUpLight[0] &
gCurrentPinballGame->ballPowerUpLight[1]))
return;
gCurrentPinballGame->ballPowerUpAnimActive = 1;
gCurrentPinballGame->ballShadowTimer = 60;
gCurrentPinballGame->scoreAddedInFrame = 4000;
return;
}
if (gCurrentPinballGame->ballCollisionZone == 9)
{
if (gCurrentPinballGame->boardState <= 2 && gCurrentPinballGame->catchArrowProgress <= 2)
{
if (gCurrentPinballGame->catchArrowProgress == 0)
gCurrentPinballGame->scoreAddedInFrame = 2000;
else if (gCurrentPinballGame->catchArrowProgress == 1)
gCurrentPinballGame->scoreAddedInFrame = 5000;
else
gCurrentPinballGame->scoreAddedInFrame = 10000;
gCurrentPinballGame->catchArrowProgress++;
MPlayStart(&gMPlayInfo_SE1, &se_unk_99);
if (gCurrentPinballGame->catchArrowProgress > 1)
gCurrentPinballGame->catchProgressFlashing = 1;
}
gCurrentPinballGame->travelRouletteSlotHitType = 2;
}
gCurrentPinballGame->ballCollisionZone = 6;
return;
}
break;
case 8:
if (gCurrentPinballGame->ball->positionQ0.x <= 50)
{
gCurrentPinballGame->ballCollisionZone = 8;
return;
}
if (gCurrentPinballGame->ball->positionQ0.x <= 100)
{
gCurrentPinballGame->ballCollisionZone = 7;
return;
}
gCurrentPinballGame->ballCollisionZone = 9;
return;
case 9:
if (gCurrentPinballGame->ball->positionQ0.x <= 46)
{
gCurrentPinballGame->ballCollisionZone = 10;
if (gCurrentPinballGame->holeIndicators[0] != 0)
return;
gCurrentPinballGame->scoreAddedInFrame = 1000;
gCurrentPinballGame->holeIndicators[0] = 1;
if (gCurrentPinballGame->allHolesLit != 0)
return;
if (!(gCurrentPinballGame->holeIndicators[1] &
gCurrentPinballGame->holeIndicators[2] &
gCurrentPinballGame->holeIndicators[3]))
return;
gCurrentPinballGame->allHolesLit = 1;
gCurrentPinballGame->allHolesLitBlinkTimer = 126;
gCurrentPinballGame->scoreAddedInFrame = 4000;
return;
}
if (gCurrentPinballGame->ball->positionQ0.x <= 120)
{
gCurrentPinballGame->ballCollisionZone = 11;
if (gCurrentPinballGame->holeIndicators[1] != 0)
return;
gCurrentPinballGame->scoreAddedInFrame = 1000;
gCurrentPinballGame->holeIndicators[1] = 1;
if (gCurrentPinballGame->allHolesLit != 0)
return;
if (!(gCurrentPinballGame->holeIndicators[0] &
gCurrentPinballGame->holeIndicators[2] &
gCurrentPinballGame->holeIndicators[3]))
return;
gCurrentPinballGame->allHolesLit = 1;
gCurrentPinballGame->allHolesLitBlinkTimer = 126;
gCurrentPinballGame->scoreAddedInFrame = 4000;
return;
}
if (gCurrentPinballGame->ball->positionQ0.x <= 193)
{
gCurrentPinballGame->ballCollisionZone = 12;
if (gCurrentPinballGame->holeIndicators[2] != 0)
return;
gCurrentPinballGame->scoreAddedInFrame = 1000;
gCurrentPinballGame->holeIndicators[2] = 1;
if (gCurrentPinballGame->allHolesLit != 0)
return;
if (!(gCurrentPinballGame->holeIndicators[0] &
gCurrentPinballGame->holeIndicators[1] &
gCurrentPinballGame->holeIndicators[3]))
return;
gCurrentPinballGame->allHolesLit = 1;
gCurrentPinballGame->allHolesLitBlinkTimer = 126;
gCurrentPinballGame->scoreAddedInFrame = 4000;
return;
}
gCurrentPinballGame->ballCollisionZone = 13;
if (gCurrentPinballGame->holeIndicators[3] != 0)
return;
gCurrentPinballGame->scoreAddedInFrame = 1000;
gCurrentPinballGame->holeIndicators[3] = 1;
if (gCurrentPinballGame->allHolesLit != 0)
return;
if (!(gCurrentPinballGame->holeIndicators[0] &
gCurrentPinballGame->holeIndicators[1] &
gCurrentPinballGame->holeIndicators[2]))
return;
gCurrentPinballGame->allHolesLit = 1;
gCurrentPinballGame->allHolesLitBlinkTimer = 126;
gCurrentPinballGame->scoreAddedInFrame = 4000;
return;
case 10:
if (gCurrentPinballGame->ballInLowerHalf == 0)
{
if (gCurrentPinballGame->ball->positionQ0.x > 170)
{
if (gCurrentPinballGame->shopDoorTargetFrame > 2U)
return;
gCurrentPinballGame->collisionSurfaceType = 0;
gCurrentPinballGame->collisionResponseType = 2;
*arg2 = 0xB000;
*arg1 = 1;
if (gCurrentPinballGame->boardState <= 2 && gCurrentPinballGame->shopDoorOpenLevel <= 2)
{
gCurrentPinballGame->shopDoorOpenLevel = 3;
gCurrentPinballGame->shopDoorAnimDelay = 5;
}
gCurrentPinballGame->scoreAddedInFrame = 50000;
return;
}
if (gCurrentPinballGame->nuzleafAnimState <= 4)
{
gCurrentPinballGame->collisionSurfaceType = 0;
gCurrentPinballGame->collisionResponseType = 2;
*arg2 = 0xF800;
*arg1 = 1;
}
if (gCurrentPinballGame->nuzleafAnimState == 5)
gCurrentPinballGame->nuzleafAnimState = 6;
if (gCurrentPinballGame->rampPrizeType == 0)
return;
if (gCurrentPinballGame->rampPrizeType == 1)
gCurrentPinballGame->oneUpAnimTimer = 90;
else
{
gCurrentPinballGame->ballPowerUpOverride = 1;
gCurrentPinballGame->ballPowerUpAnimActive = 1;
gCurrentPinballGame->ballShadowTimer = 60;
m4aSongNumStart(SE_UNKNOWN_0xD8);
}
gCurrentPinballGame->rampPrizeType = 0;
gCurrentPinballGame->rampPrizeRespawnTimer = 600;
return;
}
if (gCurrentPinballGame->pikaKickbackTimer != 0)
return;
if (gCurrentPinballGame->ball->positionQ0.x <= 120)
gCurrentPinballGame->outLaneSide = 1;
else
gCurrentPinballGame->outLaneSide = 2;
if (gCurrentPinballGame->outLanePikaPosition <= 1)
{
if (gCurrentPinballGame->outLanePikaPosition != gCurrentPinballGame->outLaneSide - 1)
return;
else
gCurrentPinballGame->pikaKickbackTimer = 120;
return;
}
gCurrentPinballGame->pikaKickbackTimer = 120;
return;
case 11:
if (gCurrentPinballGame->pikaSpinCooldownTimer != 0)
return;
absVelY = gCurrentPinballGame->ball->velocity.y;
gCurrentPinballGame->pikaSpinMomentum = gCurrentPinballGame->ball->velocity.y;
if (absVelY < 0) {
absVelY = -absVelY;
}
gCurrentPinballGame->pikaChargeTarget += (absVelY) / 3;
if (gCurrentPinballGame->pikaChargeTarget > 168)
gCurrentPinballGame->pikaChargeTarget = 168;
gCurrentPinballGame->pikaSpinCooldownTimer = 20;
return;
case 12:
if (gCurrentPinballGame->cyndaquilCollisionEnabled == 0)
return;
if (gCurrentPinballGame->collisionCooldownTimer != 0)
return;
if (gCurrentPinballGame->eggCaveState != 0)
return;
gCurrentPinballGame->eggCaveState++;
gCurrentPinballGame->cyndaquilCollisionEnabled = 0;
gCurrentPinballGame->collisionSurfaceType = 0;
gCurrentPinballGame->collisionResponseType = 2;
*arg2 = 0xD000;
*arg1 = 1;
gCurrentPinballGame->scoreAddedInFrame = 5000;
m4aSongNumStart(SE_UNKNOWN_0xB7);
PlayRumble(7);
return;
case 13:
if (gCurrentPinballGame->cyndaquilCollisionEnabled == 0)
return;
if (gCurrentPinballGame->collisionCooldownTimer != 0)
return;
if (gCurrentPinballGame->eggCaveState != 1)
return;
gCurrentPinballGame->eggCaveState++;
gCurrentPinballGame->cyndaquilCollisionEnabled = 0;
gCurrentPinballGame->collisionSurfaceType = 0;
gCurrentPinballGame->collisionResponseType = 2;
*arg2 = 0xCC00;
*arg1 = 1;
m4aSongNumStart(SE_UNKNOWN_0xB7);
gCurrentPinballGame->scoreAddedInFrame = 5000;
PlayRumble(7);
return;
case 14:
if ((gCurrentPinballGame->boardState > 2) && (gCurrentPinballGame->boardState != 5))
{
if (gCurrentPinballGame->eggCaveExitDelayTimer == 0)
{
if (gCurrentPinballGame->eggCaveState == 2)
{
gCurrentPinballGame->collisionSurfaceType = 0;
gCurrentPinballGame->collisionResponseType = 2;
*arg2 = 0xC800;
*arg1 = 1;
gCurrentPinballGame->eggCaveState++;
m4aSongNumStart(SE_UNKNOWN_0xB7);
gCurrentPinballGame->scoreAddedInFrame = 5000;
PlayRumble(7);
return;
}
else if (gCurrentPinballGame->eggCaveState == 3)
{
gCurrentPinballGame->collisionSurfaceType = 0;
gCurrentPinballGame->collisionResponseType = 2;
*arg2 = 0xC800;
*arg1 = 1;
m4aSongNumStart(SE_UNKNOWN_0xB7);
gCurrentPinballGame->eggCaveReEntryFlag = 1;
PlayRumble(7);
return;
}
}
}
else if (gCurrentPinballGame->cyndaquilCollisionEnabled != 0 && gCurrentPinballGame->eggCaveState == 2)
{
gCurrentPinballGame->eggCaveState++;
gCurrentPinballGame->cyndaquilCollisionEnabled = 0;
gCurrentPinballGame->collisionSurfaceType = 0;
gCurrentPinballGame->collisionResponseType = 2;
*arg2 = 0xC800;
*arg1 = 1;
m4aSongNumStart(SE_UNKNOWN_0xB7);
gCurrentPinballGame->scoreAddedInFrame = 5000;
PlayRumble(7);
}
break;
}
}

645
src/collision_sapphire.c Normal file
View File

@ -0,0 +1,645 @@
#include "global.h"
#include "main.h"
#include "m4a.h"
#include "constants/bg_music.h"
extern u16 gSapphireTargetBumperIndexMap[];
s16 CollisionCheck_Sapphire(struct Vector16 *arg0, u16* arg1) {
struct Vector16 vec1;
struct Vector16 vec2;
u16 sp00;
u8 sp02;
u16 return_val;
s16 collisionTileIndex;
s32 tileMapPage;
s32 boardLayer;
u32 some_enum;
u8 switch_enum;
return_val = 0;
gCurrentPinballGame->ball->spinAcceleration = 0;
vec1.x = arg0->x / 8;
vec1.y = arg0->y / 8;
vec2.x = arg0->x % 8;
vec2.y = arg0->y % 8;
tileMapPage = vec1.y / 64;
boardLayer = gCurrentPinballGame->boardLayerDepth;
vec1.y %= 64;
collisionTileIndex = gBoardConfig.fieldLayout.collisionTileMap[boardLayer + tileMapPage][vec1.y * 64 + vec1.x];
sp00 = gBoardConfig.fieldLayout.collisionAngleMap[boardLayer + tileMapPage][collisionTileIndex * 64 + vec2.y * 8 + vec2.x];
sp02 = gBoardConfig.fieldLayout.collisionTypeMap[boardLayer + tileMapPage][collisionTileIndex * 64 + vec2.y * 8 + vec2.x];
CheckSapphireBumperCollision(arg0, &sp00, &sp02);
switch_enum = sp02 & 0xF;
some_enum = sp02 >> 4;
switch (switch_enum)
{
case 1:
case 4:
gCurrentPinballGame->collisionSurfaceType = switch_enum - 1;
gCurrentPinballGame->collisionResponseType = 1;
*arg1 = sp00;
if (*arg1 >= 0x3FF0 && *arg1 <= 0x4010)
{
if (gCurrentPinballGame->ball->positionQ0.x < gBoardConfig.fieldLayout.ballSpawnX - 8 ||
gCurrentPinballGame->ball->positionQ0.y < gBoardConfig.fieldLayout.ballSpawnY - 8)
{
if (gCurrentPinballGame->ball->spinSpeed > 0)
{
*arg1 = 0x3E00;
}
else if (gCurrentPinballGame->ball->spinSpeed != 0)
{
*arg1 = 0x4100;
}
else
{
if (gMain.systemFrameCount & 1)
{
gCurrentPinballGame->ball->spinAcceleration = 0x28;
gCurrentPinballGame->ball->spinSpeed = 1;
*arg1 = 0x3E00;
}
else
{
gCurrentPinballGame->ball->spinAcceleration = 0xFFD8;
gCurrentPinballGame->ball->spinSpeed = 0xFFFF;
*arg1 = 0x4100;
}
}
}
}
return_val = 1;
break;
case 3:
case 2:
gCurrentPinballGame->collisionSurfaceType = switch_enum - 1;
gCurrentPinballGame->collisionResponseType = 2;
*arg1 = sp00 & 0x0000FFF0;
return_val = 1;
break;
}
ProcessSapphireCollisionEvent((s32) some_enum, &return_val, arg1);
return return_val;
}
void CheckSapphireBumperCollision(struct Vector16 *arg0, s16 *arg1, u8 *arg2) {
s16 deltaX;
s16 deltaY;
u16 maskedResult = 0;
u8 lowerNibble = 0;
s32 ix = 0;
if (gCurrentPinballGame->ballInLowerHalf == 0)
{
if (gCurrentPinballGame->boardLayerDepth != 0)
return;
deltaX = arg0->x + gCurrentPinballGame->rubyBumperCollisionPosition[0].x;
deltaY = arg0->y + gCurrentPinballGame->rubyBumperCollisionPosition[0].y;
if (deltaX <= 63U && deltaY <= 63U)
{
maskedResult = 0xFFF0 & gSharedBumperCollisionMap[(deltaY * 64) + deltaX];
lowerNibble = 0xF & gSharedBumperCollisionMap[(deltaY * 64) + deltaX];
ix = 0;
}
if (lowerNibble == 0)
{
deltaX = gCurrentPinballGame->rubyBumperCollisionPosition[1].x + arg0->x;
deltaY = gCurrentPinballGame->rubyBumperCollisionPosition[1].y + arg0->y;
if (deltaX <= 63U && deltaY <= 63U)
{
maskedResult = 0xFFF0 & gSharedBumperCollisionMap[(deltaY * 64) + deltaX];
lowerNibble = 0xF & gSharedBumperCollisionMap[(deltaY * 64) + deltaX];
ix = 1;
}
if (lowerNibble == 0)
{
deltaX = gCurrentPinballGame->rubyBumperCollisionPosition[2].x + arg0->x;
deltaY = gCurrentPinballGame->rubyBumperCollisionPosition[2].y + arg0->y;
if (deltaX <= 63U && deltaY <= 63U)
{
maskedResult = 0xFFF0 & gSharedBumperCollisionMap[(deltaY * 64) + deltaX];
lowerNibble = 0xF & gSharedBumperCollisionMap[(deltaY * 64) + deltaX];
ix = 2;
}
if (lowerNibble == 0)
return;
}
}
gCurrentPinballGame->pondBumperStates[ix] = 6;
*arg1 = maskedResult;
*arg2 = lowerNibble;
if (gCurrentPinballGame->bumperHitCountdown <= 0)
gCurrentPinballGame->bumperHitCountdown = 2;
}
}
void ProcessSapphireCollisionEvent(u8 arg0, u16* arg1, u16* arg2)
{
s16 absVelY;
s16 x0Position;
s16 modRes;
s16 index;
u16 angle;
int squaredMagnitude;
switch (arg0)
{
case 1:
if (gCurrentPinballGame->collisionCooldownTimer == 0)
{
if (gCurrentPinballGame->ball->positionQ1.x >= 200)
gCurrentPinballGame->ballCatchState = 1;
else
gCurrentPinballGame->ballCatchState = 3;
DispatchSapphireCatchModeInit();
gCurrentPinballGame->collisionResponseType = 7;
*arg1 = 1;
}
break;
case 2:
if (gCurrentPinballGame->boardLayerDepth == 0)
{
gCurrentPinballGame->ball->oamPriority = 2;
gCurrentPinballGame->boardLayerDepth = 2;
}
else if (gCurrentPinballGame->boardLayerDepth == 2)
{
gCurrentPinballGame->ball->oamPriority = 2;
gCurrentPinballGame->boardLayerDepth = 3;
}
else if (gCurrentPinballGame->boardLayerDepth == 3)
{
gCurrentPinballGame->ball->oamPriority = 1;
}
break;
case 3:
if (gCurrentPinballGame->boardLayerDepth == 2)
{
gCurrentPinballGame->ball->oamPriority = 3;
gCurrentPinballGame->boardLayerDepth = 0;
}
else if (gCurrentPinballGame->boardLayerDepth == 3)
{
gCurrentPinballGame->ball->oamPriority = 2;
gCurrentPinballGame->boardLayerDepth = 2;
}
break;
case 4:
if (gCurrentPinballGame->mainBoardCountdownTimer == 0)
{
if (gCurrentPinballGame->ball->positionQ0.y < 260)
{
if (gCurrentPinballGame->ball->positionQ0.x < 74)
{
if (gCurrentPinballGame->boardState < 3 && gCurrentPinballGame->sapphireBumperState[1] < 3)
{
if (gCurrentPinballGame->sapphireBumperState[1] == 1)
gCurrentPinballGame->sapphireBumperAnimKeyframe[1] = 6;
else
gCurrentPinballGame->sapphireBumperAnimKeyframe[1] = 4;
gCurrentPinballGame->sapphireBumperAnimSubTimer[1] = 0;
gCurrentPinballGame->sapphireBumperState[1] = 1;
PlayRumble(7);
gCurrentPinballGame->ball->velocity.x /= 2;
gCurrentPinballGame->ball->velocity.y /= 2;
memcpy(&gCurrentPinballGame->ballStates[1], &gCurrentPinballGame->ballStates[0], sizeof(*gCurrentPinballGame->ballStates));
gCurrentPinballGame->secondaryBall = &gCurrentPinballGame->ballStates[1];
gCurrentPinballGame->ballLaunchTimer = 25;
}
}
else if (gCurrentPinballGame->ball->positionQ0.x < 116)
{
if (gCurrentPinballGame->boardState < 3 && gCurrentPinballGame->sapphireBumperState[0] < 3)
{
if (gCurrentPinballGame->sapphireBumperState[0] == 1)
gCurrentPinballGame->sapphireBumperAnimKeyframe[0] = 6;
else
gCurrentPinballGame->sapphireBumperAnimKeyframe[0] = 4;
gCurrentPinballGame->sapphireBumperAnimSubTimer[0] = 0;
gCurrentPinballGame->sapphireBumperState[0] = 1;
PlayRumble(7);
gCurrentPinballGame->ball->velocity.x /= 2;
gCurrentPinballGame->ball->velocity.y /= 2;
memcpy(&gCurrentPinballGame->ballStates[1], &gCurrentPinballGame->ballStates[0], sizeof(*gCurrentPinballGame->ballStates));
gCurrentPinballGame->secondaryBall = &gCurrentPinballGame->ballStates[1];
gCurrentPinballGame->ballLaunchTimer = 25;
}
}
else
{
gCurrentPinballGame->pelipperFrameTimer = 1800;
gCurrentPinballGame->pelipperState = 1;
if (gCurrentPinballGame->progressLevel < 99)
gCurrentPinballGame->progressLevel++;
gCurrentPinballGame->scoreAddedInFrame = 5000;
}
}
else
{
if (gCurrentPinballGame->ball->positionQ0.x < 110)
{
gCurrentPinballGame->seedotCollisionTrigger = 1;
gCurrentPinballGame->ball->velocity.y /= 2;
}
else
{
if (gCurrentPinballGame->zigzagoonState == 0)
gCurrentPinballGame->zigzagoonState = 1;
else
gCurrentPinballGame->zigzagoonState = 0;
gCurrentPinballGame->ball->velocity.y /=2;
gCurrentPinballGame->scoreAddedInFrame = 3000;
}
}
gCurrentPinballGame->mainBoardCountdownTimer = 45;
m4aSongNumStart(SE_TRIGGER_BUTTON_HIT);
}
break;
case 5:
gCurrentPinballGame->ballTouchingSpoink = 1;
gCurrentPinballGame->ballInLaunchChute = 1;
gCurrentPinballGame->ballCollisionZone = 0;
gCurrentPinballGame->hatchMachineActive = 0;
break;
case 6:
if (gCurrentPinballGame->ball->positionQ0.x < 120)
{
if (gCurrentPinballGame->ball->velocity.y > 0)
{
angle = 0xDA00;
squaredMagnitude =
gCurrentPinballGame->ball->velocity.x * gCurrentPinballGame->ball->velocity.x +
gCurrentPinballGame->ball->velocity.y * gCurrentPinballGame->ball->velocity.y;
squaredMagnitude = Sqrt(squaredMagnitude * 4) / 2;
gCurrentPinballGame->ball->velocity.x = squaredMagnitude * Cos(angle) / 20000;
gCurrentPinballGame->ball->velocity.y = -squaredMagnitude * Sin(angle) / 20000;
}
}
else
gCurrentPinballGame->hatchMachineActive = 1;
break;
case 7:
if (gCurrentPinballGame->shopShockWallAnimState != 3)
{
gCurrentPinballGame->shopBumperHitTimer = 17;
gCurrentPinballGame->collisionSurfaceType = 0;
gCurrentPinballGame->collisionResponseType = 2;
*arg2 = 0xD800;
*arg1 = 1;
}
break;
case 8:
x0Position = gCurrentPinballGame->ball->positionQ0.x;
if (gCurrentPinballGame->boardLayerDepth > 0)
{
if (gCurrentPinballGame->ballCollisionZone == 7)
{
gCurrentPinballGame->coinRewardAmount = 10;
if (gCurrentPinballGame->coinRewardLevel < 3)
{
if (gCurrentPinballGame->coinRewardLevel == 0)
{
gCurrentPinballGame->scoreAddedInFrame = 2000;
gCurrentPinballGame->coinRewardAmount = 1;
}
else if (gCurrentPinballGame->coinRewardLevel == 1)
{
gCurrentPinballGame->scoreAddedInFrame = 5000;
gCurrentPinballGame->coinRewardAmount = 5;
}
else
{
gCurrentPinballGame->scoreAddedInFrame = 10000;
gCurrentPinballGame->coinRewardAmount = 10;
}
gCurrentPinballGame->coinRewardLevel++;
}
gCurrentPinballGame->coinRewardTimer = 0;
gCurrentPinballGame->coinRewardLevelTimer = 0;
}
gCurrentPinballGame->ballCollisionZone = 1;
}
else
{
if (x0Position <= 72)
{
if (gCurrentPinballGame->ballCollisionZone == 8)
{
if (gCurrentPinballGame->boardState < 3 && gCurrentPinballGame->evoArrowProgress < 3)
{
if (gCurrentPinballGame->evoArrowProgress == 0)
gCurrentPinballGame->scoreAddedInFrame = 2000;
else if (gCurrentPinballGame->evoArrowProgress == 1)
gCurrentPinballGame->scoreAddedInFrame = 5000;
else
gCurrentPinballGame->scoreAddedInFrame = 10000;
gCurrentPinballGame->evoArrowProgress++;
m4aSongNumStart(SE_UNKNOWN_0x99);
}
gCurrentPinballGame->travelRouletteSlotHitType = 1;
}
gCurrentPinballGame->ballCollisionZone = 2;
}
else if (x0Position <= 98)
{
if (gCurrentPinballGame->ballPowerUpLight[0] == 0)
gCurrentPinballGame->scoreAddedInFrame = 1000;
gCurrentPinballGame->ballPowerUpLight[0] = 1;
gCurrentPinballGame->ballCollisionZone = 3;
if (gCurrentPinballGame->ballPowerUpAnimActive == 0 && (gCurrentPinballGame->ballPowerUpLight[1] & gCurrentPinballGame->ballPowerUpLight[2]))
{
gCurrentPinballGame->ballPowerUpAnimActive = 1;
gCurrentPinballGame->ballShadowTimer = 60;
gCurrentPinballGame->scoreAddedInFrame = 4000;
}
}
else if (x0Position <= 118)
{
if (gCurrentPinballGame->ballPowerUpLight[1] == 0)
gCurrentPinballGame->scoreAddedInFrame = 1000;
gCurrentPinballGame->ballPowerUpLight[1] = 1;
gCurrentPinballGame->ballCollisionZone = 4;
if (gCurrentPinballGame->ballPowerUpAnimActive == 0 && (gCurrentPinballGame->ballPowerUpLight[0] & gCurrentPinballGame->ballPowerUpLight[2]))
{
gCurrentPinballGame->ballPowerUpAnimActive = 1;
gCurrentPinballGame->ballShadowTimer = 60;
gCurrentPinballGame->scoreAddedInFrame = 4000;
}
}
else if (x0Position <= 146)
{
if (gCurrentPinballGame->ballPowerUpLight[2] == 0)
gCurrentPinballGame->scoreAddedInFrame = 1000;
gCurrentPinballGame->ballPowerUpLight[2] = 1;
gCurrentPinballGame->ballCollisionZone = 5;
if (gCurrentPinballGame->ballPowerUpAnimActive == 0 && (gCurrentPinballGame->ballPowerUpLight[0] & gCurrentPinballGame->ballPowerUpLight[1]))
{
gCurrentPinballGame->ballPowerUpAnimActive = 1;
gCurrentPinballGame->ballShadowTimer = 60;
gCurrentPinballGame->scoreAddedInFrame = 4000;
}
}
else
{
if (gCurrentPinballGame->ballCollisionZone == 9)
{
if (gCurrentPinballGame->boardState <= 2 && gCurrentPinballGame->catchArrowProgress < 3)
{
if (gCurrentPinballGame->catchArrowProgress == 0)
gCurrentPinballGame->scoreAddedInFrame = 2000;
else if (gCurrentPinballGame->catchArrowProgress == 1)
gCurrentPinballGame->scoreAddedInFrame = 5000;
else
gCurrentPinballGame->scoreAddedInFrame = 10000;
gCurrentPinballGame->catchArrowProgress++;
if (gCurrentPinballGame->chargeFillValue == 13)
m4aSongNumStart(SE_UNKNOWN_0x99);
if (gCurrentPinballGame->catchArrowProgress > 1)
gCurrentPinballGame->catchProgressFlashing = 1;
}
gCurrentPinballGame->travelRouletteSlotHitType = 2;
}
gCurrentPinballGame->ballCollisionZone = 6;
}
}
break;
case 9:
x0Position = gCurrentPinballGame->ball->positionQ0.x;
if (gCurrentPinballGame->boardLayerDepth > 0)
gCurrentPinballGame->ballCollisionZone = 7;
else if (x0Position <= 50)
gCurrentPinballGame->ballCollisionZone = 8;
else
gCurrentPinballGame->ballCollisionZone = 9;
break;
case 10:
if (gCurrentPinballGame->ball->positionQ0.x <= 46)
{
gCurrentPinballGame->ballCollisionZone = 10;
if (gCurrentPinballGame->holeIndicators[0] == 0)
{
gCurrentPinballGame->scoreAddedInFrame = 1000;
gCurrentPinballGame->holeIndicators[0] = 1;
if (gCurrentPinballGame->allHolesLit == 0 && (
gCurrentPinballGame->holeIndicators[1] &
gCurrentPinballGame->holeIndicators[2] &
gCurrentPinballGame->holeIndicators[3]))
{
gCurrentPinballGame->allHolesLit = 1;
gCurrentPinballGame->allHolesLitBlinkTimer = 126;
gCurrentPinballGame->scoreAddedInFrame = 4000;
}
}
}
else if (gCurrentPinballGame->ball->positionQ0.x <= 120)
{
gCurrentPinballGame->ballCollisionZone = 11;
if (gCurrentPinballGame->holeIndicators[1] == 0)
{
gCurrentPinballGame->scoreAddedInFrame = 1000;
gCurrentPinballGame->holeIndicators[1] = 1;
if (gCurrentPinballGame->allHolesLit == 0 && (
gCurrentPinballGame->holeIndicators[0] &
gCurrentPinballGame->holeIndicators[2] &
gCurrentPinballGame->holeIndicators[3]))
{
gCurrentPinballGame->allHolesLit = 1;
gCurrentPinballGame->allHolesLitBlinkTimer = 126;
gCurrentPinballGame->scoreAddedInFrame = 4000;
}
}
}
else if (gCurrentPinballGame->ball->positionQ0.x <= 193)
{
gCurrentPinballGame->ballCollisionZone = 12;
if (gCurrentPinballGame->holeIndicators[2] == 0)
{
gCurrentPinballGame->scoreAddedInFrame = 1000;
gCurrentPinballGame->holeIndicators[2] = 1;
if (gCurrentPinballGame->allHolesLit == 0 && (
gCurrentPinballGame->holeIndicators[0] &
gCurrentPinballGame->holeIndicators[1] &
gCurrentPinballGame->holeIndicators[3]))
{
gCurrentPinballGame->allHolesLit = 1;
gCurrentPinballGame->allHolesLitBlinkTimer = 126;
gCurrentPinballGame->scoreAddedInFrame = 4000;
}
}
}
else
{
gCurrentPinballGame->ballCollisionZone = 13;
if (gCurrentPinballGame->holeIndicators[3] == 0)
{
gCurrentPinballGame->scoreAddedInFrame = 1000;
gCurrentPinballGame->holeIndicators[3] = 1;
if (gCurrentPinballGame->allHolesLit == 0 && (
gCurrentPinballGame->holeIndicators[0] &
gCurrentPinballGame->holeIndicators[1] &
gCurrentPinballGame->holeIndicators[2]))
{
gCurrentPinballGame->allHolesLit = 1;
gCurrentPinballGame->allHolesLitBlinkTimer = 126;
gCurrentPinballGame->scoreAddedInFrame = 4000;
}
}
}
break;
case 11:
if (gCurrentPinballGame->pikaKickbackTimer == 0)
{
if (gCurrentPinballGame->ball->positionQ0.x <= 120)
gCurrentPinballGame->outLaneSide = 1;
else
gCurrentPinballGame->outLaneSide = 2;
if (gCurrentPinballGame->outLanePikaPosition < 2)
{
if (gCurrentPinballGame->outLanePikaPosition == gCurrentPinballGame->outLaneSide - 1)
gCurrentPinballGame->pikaKickbackTimer = 120;
}
else
{
gCurrentPinballGame->pikaKickbackTimer = 120;
}
}
break;
case 12:
if (gCurrentPinballGame->pikaSpinCooldownTimer == 0)
{
absVelY = gCurrentPinballGame->ball->velocity.y;
gCurrentPinballGame->pikaSpinMomentum = absVelY;
if (absVelY < 0)
absVelY = -absVelY;
gCurrentPinballGame->pikaChargeTarget = gCurrentPinballGame->pikaChargeTarget + (absVelY / 3);
if (gCurrentPinballGame->pikaChargeTarget > 168)
gCurrentPinballGame->pikaChargeTarget = 168;
gCurrentPinballGame->pikaSpinCooldownTimer = 20;
}
break;
case 13:
if (gCurrentPinballGame->ballCollisionZone != 14)
{
gCurrentPinballGame->ballCollisionZone = 14;
index = gSapphireTargetBumperIndexMap[gCurrentPinballGame->targetBumperHitCounter];
gCurrentPinballGame->targetBumperAnimTimers[index] = 10;
gCurrentPinballGame->targetBumperHitCounter++;
if (gCurrentPinballGame->targetBumperHitCounter == 3)
{
memcpy(&gCurrentPinballGame->ballStates[1], &gCurrentPinballGame->ballStates[0], sizeof(*gCurrentPinballGame->ballStates));
gCurrentPinballGame->secondaryBall = &gCurrentPinballGame->ballStates[1];
if (gCurrentPinballGame->hatchMachineActive)
gCurrentPinballGame->hatchMachineNewHit = 1;
}
if (gCurrentPinballGame->targetBumperHitCounter == 11)
gCurrentPinballGame->secondaryBall = gCurrentPinballGame->ballStates;
modRes = (gCurrentPinballGame->targetBumperHitCounter - 1) % 4;
gMain.spriteGroups[modRes + 47].available = 1;
gCurrentPinballGame->splashEffectFrameIndex[modRes] = 0;
gCurrentPinballGame->splashEffectFrameTimer[modRes] = 0;
gCurrentPinballGame->splashEffectPositionIndex[modRes] = gCurrentPinballGame->targetBumperHitCounter - 1;
if (gCurrentPinballGame->targetBumperHitCounter > 12)
gCurrentPinballGame->targetBumperHitCounter = 0;
if (index == 0 && gCurrentPinballGame->ball->velocity.y > -120)
gCurrentPinballGame->ball->velocity.y = -120;
if (index == 2 && gCurrentPinballGame->ball->velocity.y > -180)
gCurrentPinballGame->ball->velocity.y = -180;
}
break;
case 14:
if (gCurrentPinballGame->ballCollisionZone != 15)
{
gCurrentPinballGame->ballCollisionZone = 15;
index = gSapphireTargetBumperIndexMap[gCurrentPinballGame->targetBumperHitCounter];
gCurrentPinballGame->targetBumperAnimTimers[index] = 10;
gCurrentPinballGame->targetBumperHitCounter++;
modRes = (gCurrentPinballGame->targetBumperHitCounter -1) % 4;
gMain.spriteGroups[modRes + 47].available = 1;
gCurrentPinballGame->splashEffectFrameIndex[modRes] = 0;
gCurrentPinballGame->splashEffectFrameTimer[modRes] = 0;
gCurrentPinballGame->splashEffectPositionIndex[modRes] = gCurrentPinballGame->targetBumperHitCounter - 1;
if (index == 1 && gCurrentPinballGame->ball->velocity.y > -150)
gCurrentPinballGame->ball->velocity.y = -150;
}
break;
case 15:
if (gCurrentPinballGame->ball->positionQ0.y < 80)
{
if (gCurrentPinballGame->pelipperState == 1)
gCurrentPinballGame->pelipperState = 2;
}
else
{
if (gCurrentPinballGame->pelipperState == 2)
{
gCurrentPinballGame->pelipperState = 3;
gCurrentPinballGame->pelipperFrameTimer = 0;
}
}
break;
}
}

195
src/collision_spheal.c Normal file
View File

@ -0,0 +1,195 @@
#include "global.h"
#include "main.h"
s16 CollisionCheck_Spheal(struct Vector16 *arg0, u16 *arg1)
{
u16 sp0;
u8 sp2;
u16 sp4_return;
struct Vector16 div_result;
struct Vector16 div_remainder;
s32 tileMapPage;
s32 boardLayer;
s16 collisionTileIndex;
u8 enum1, enum2;
sp4_return = 0;
gCurrentPinballGame->ball->spinAcceleration = 0;
div_result.x = arg0->x / 8;
div_result.y = arg0->y / 8;
div_remainder.x = arg0->x % 8;
div_remainder.y = arg0->y % 8;
tileMapPage = div_result.y / 64;
boardLayer = gCurrentPinballGame->boardLayerDepth;
div_result.y %= 64;
collisionTileIndex = gBoardConfig.fieldLayout.collisionTileMap[boardLayer + tileMapPage][div_result.y * 64 + div_result.x];
sp0 = gBoardConfig.fieldLayout.collisionAngleMap[boardLayer + tileMapPage][collisionTileIndex * 64 + div_remainder.y * 8 + div_remainder.x];
sp2 = gBoardConfig.fieldLayout.collisionTypeMap[boardLayer + tileMapPage][collisionTileIndex * 64 + div_remainder.y * 8 + div_remainder.x];
CheckSphealEntityCollision(arg0, &sp0, &sp2);
enum1 = sp2 & 0xF;
enum2 = sp2 >> 4;
switch (enum1)
{
case 1:
case 4:
case 6:
gCurrentPinballGame->collisionSurfaceType = enum1 - 1;
gCurrentPinballGame->collisionResponseType = 1;
*arg1 = sp0;
if (*arg1 >= 0x3FF0 && *arg1 <= 0x4010)
{
if (gCurrentPinballGame->ball->positionQ0.x < (gBoardConfig.fieldLayout.ballSpawnX - 8) ||
gCurrentPinballGame->ball->positionQ0.y < (gBoardConfig.fieldLayout.ballSpawnY - 8))
{
if (gCurrentPinballGame->ball->spinSpeed > 0)
{
*arg1 = 0x3E00;
}
else if (gCurrentPinballGame->ball->spinSpeed != 0)
{
*arg1 = 0x4100;
}
else
{
if (gMain.systemFrameCount & 1)
{
gCurrentPinballGame->ball->spinAcceleration = 40;
gCurrentPinballGame->ball->spinSpeed = 1;
*arg1 = 0x3E00;
}
else
{
gCurrentPinballGame->ball->spinAcceleration = -40;
gCurrentPinballGame->ball->spinSpeed = -1;
*arg1 = 0x4100;
}
}
}
}
sp4_return = 1;
break;
case 2:
case 3:
gCurrentPinballGame->collisionSurfaceType = 0;
gCurrentPinballGame->collisionResponseType = 1;
*arg1 = sp0 & 0x0000FFF0;
if (gCurrentPinballGame->ball->positionQ0.x < 120)
gCurrentPinballGame->minionHitFlashTimer[0] = 24;
else
gCurrentPinballGame->minionHitFlashTimer[1] = 24;
sp4_return = 1;
break;
case 5:
enum2 = 4;
break;
}
ProcessSphealCollisionEvent(enum2, &sp4_return, arg1);
return sp4_return;
}
void CheckSphealEntityCollision(struct Vector16 *arg0, u16 *arg1, u8 *arg2)
{
s16 i;
s16 deltaX, deltaY;
u16 lowerReadFromRom;
u16 upperReadFromRom;
for (i = 0; i < 2; i++)
{
if (gCurrentPinballGame->flyingEnemyCollisionType[i] == 1)
{
if ((arg2[0] & 0xf) != 0)
continue;
deltaX = arg0->x - gCurrentPinballGame->flyingEnemyCollisionPos[i].x;
deltaY = arg0->y - gCurrentPinballGame->flyingEnemyCollisionPos[i].y;
if ((deltaX >= 64 || deltaX < 0) || (deltaY >= 64 || deltaY < 0))
continue;
upperReadFromRom = gSphealFrozenIceCollisionMap[(deltaY * 64) + deltaX] & 0xFFF0;
lowerReadFromRom = gSphealFrozenIceCollisionMap[(deltaY * 64) + deltaX] & 0xF;
if (lowerReadFromRom == 0)
continue;
if (gCurrentPinballGame->ballRespawnState != 0)
continue;
arg1[0] = upperReadFromRom;
arg2[0] = lowerReadFromRom;
arg2[0] = 6;
gCurrentPinballGame->flyingEnemyState[i] = 4;
}
else if (gCurrentPinballGame->flyingEnemyCollisionType[i] != 0)
{
if ((arg2[0] & 0xf) != 0)
continue;
deltaX = arg0->x - gCurrentPinballGame->flyingEnemyCollisionPos[i].x;
deltaY = arg0->y - gCurrentPinballGame->flyingEnemyCollisionPos[i].y;
if ((deltaX >= 64 || deltaX < 0) || (deltaY >= 64 || deltaY < 0))
continue;
upperReadFromRom = gSphealCrackedIceCollisionMap[(deltaY * 64) + deltaX] & 0xFFF0;
lowerReadFromRom = gSphealCrackedIceCollisionMap[(deltaY * 64) + deltaX] & 0xF;
if (lowerReadFromRom == 0)
continue;
arg1[0] = upperReadFromRom;
arg2[0] = lowerReadFromRom;
arg2[0] = 6;
if (gCurrentPinballGame->flyingEnemyCollisionType[i] == 2)
{
gCurrentPinballGame->flyingEnemyState[i] = 4;
}
else
{
gCurrentPinballGame->flyingEnemyHitCooldown[i] = 24;
}
}
}
}
void ProcessSphealCollisionEvent(u8 arg0_enum, u16 *arg1, u16 *arg2)
{
switch (arg0_enum)
{
case 2:
gCurrentPinballGame->knockdownTargetIndex[2] = 0;
gCurrentPinballGame->knockdownPhase[2] = 2;
break;
case 3:
gCurrentPinballGame->knockdownTargetIndex[2] = 1;
gCurrentPinballGame->knockdownPhase[2] = 2;
break;
case 8:
gCurrentPinballGame->knockdownTargetIndex[2] = 0;
gCurrentPinballGame->knockdownPhase[2] = 1;
gCurrentPinballGame->knockdownStunTimer[2] = 100;
break;
case 9:
gCurrentPinballGame->knockdownTargetIndex[2] = 1;
gCurrentPinballGame->knockdownPhase[2] = 1;
gCurrentPinballGame->knockdownStunTimer[2] = 100;
break;
case 1:
case 4:
case 5:
case 6:
case 7:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
break;
}
}

416
src/display.c Normal file
View File

@ -0,0 +1,416 @@
#include "global.h"
#include "main.h"
void FadeInFromWhite(void (*func)(void))
{
u16 i;
DmaCopy16(3, (void*)PLTT, gPaletteFadeBuffers[1], PLTT_SIZE);
DmaFill16(3, 0x7FFF, gPaletteFadeBuffers[0], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[0], gPaletteFadeBuffers[2], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[2], (void*)PLTT, PLTT_SIZE);
UnblankLCD();
for (i = 0; i < 32; i++)
{
if (func != NULL)
func();
InterpolatePaletteStep(i);
MainLoopIter();
if (i == 31)
{
DmaCopy16(3, gPaletteFadeBuffers[1], (void *)PLTT, 0x400);
}
else
{
DmaCopy16(3, gPaletteFadeBuffers[2], (void *)PLTT, 0x400);
}
}
}
void FadeOutToWhite(void (*func)(void))
{
u16 i;
DmaCopy16(3, (void*)PLTT, gPaletteFadeBuffers[0], PLTT_SIZE);
DmaFill16(3, 0x7FFF, gPaletteFadeBuffers[1], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[0], gPaletteFadeBuffers[2], PLTT_SIZE);
for (i = 0; i < 32; i++)
{
if (func != NULL)
func();
InterpolatePaletteStep(i);
MainLoopIter();
if (i == 31)
{
DmaCopy16(3, gPaletteFadeBuffers[1], (void *)PLTT, 0x400);
}
else
{
DmaCopy16(3, gPaletteFadeBuffers[2], (void *)PLTT, 0x400);
}
}
ForceBlankLCD();
MainLoopIter();
ClearGraphicsMemory();
}
void FadeInWithCustomPalettes(u8 * arg0, u8 * arg1, void (*func)(void))
{
u16 i;
DmaCopy16(3, arg0, gPaletteFadeBuffers[1], 0x200);
DmaCopy16(3, arg1, gPaletteFadeBuffers[2], 0x200);
DmaFill16(3, 0, gPaletteFadeBuffers[0], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[0], gPaletteFadeBuffers[2], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[2], (void*)PLTT, PLTT_SIZE);
UnblankLCD();
gMain.dispcntBackup = REG_DISPCNT;
for (i = 0; i < 32; i++)
{
if (func != NULL)
func();
InterpolatePaletteStep(i);
MainLoopIter();
if (i == 31)
{
DmaCopy16(3, gPaletteFadeBuffers[1], (void *)PLTT, 0x400);
}
else
{
DmaCopy16(3, gPaletteFadeBuffers[2], (void *)PLTT, 0x400);
}
}
}
void FadeOutToBlack(void (*func)(void))
{
u16 i;
DmaCopy16(3, (void*)PLTT, gPaletteFadeBuffers[0], PLTT_SIZE);
DmaFill16(3, 0, gPaletteFadeBuffers[1], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[0], gPaletteFadeBuffers[2], PLTT_SIZE);
for (i = 0; i < 32; i++)
{
if (func != NULL)
func();
InterpolatePaletteStep(i);
MainLoopIter();
if (i == 31)
{
DmaCopy16(3, gPaletteFadeBuffers[1], (void *)PLTT, 0x400);
}
else
{
DmaCopy16(3, gPaletteFadeBuffers[2], (void *)PLTT, 0x400);
}
}
MainLoopIter();
}
void InterpolatePaletteStep(u16 arg0)
{
u16 var0;
u16 var1;
u16 b[2];
u16 g[2];
u16 r[2];
u16 spC[4];
spC[0] = 0;
spC[1] = 2;
spC[2] = 1;
spC[3] = 3;
var0 = spC[arg0 & 3] * 128;
var1 = var0 + 128;
arg0 &= ~3;
arg0 += 4;
while(var0 < var1)
{
r[0] = gPaletteFadeBuffers[0][var0] & 0x1F;
g[0] = (gPaletteFadeBuffers[0][var0] & 0x3E0) >> 5;
b[0] = (gPaletteFadeBuffers[0][var0] & 0x7C00) >> 10;
r[1] = gPaletteFadeBuffers[1][var0] & 0x1F;
g[1] = (gPaletteFadeBuffers[1][var0] & 0x3E0) >> 5;
b[1] = (gPaletteFadeBuffers[1][var0] & 0x7C00) >> 10;
if(b[0] < b[1])
b[0] += ((b[1] - b[0]) * arg0) >> 5;
else
b[0] -= ((b[0] - b[1]) * arg0) >> 5;
if(g[0] < g[1])
g[0] += ((g[1] - g[0]) * arg0) >> 5;
else
g[0] -= ((g[0] - g[1]) * arg0) >> 5;
if(r[0] < r[1])
r[0] += ((r[1] - r[0]) * arg0) >> 5;
else
r[0] -= ((r[0] - r[1]) * arg0) >> 5;
gPaletteFadeBuffers[2][var0] = (b[0] << 10) | (g[0] << 5) | r[0];
var0++;
}
}
void DarkenPalette(u8 * pal, u8 * dest, u16 arg2, u16 arg3)
{
u16 i;
u16 b[2];
u16 g[2];
u16 r[2];
DmaCopy16(3, pal, gPaletteFadeBuffers[0], arg2);
DmaFill16(3, 0, gPaletteFadeBuffers[1], arg2);
for(i = 0; i < arg2; i++)
{
r[0] = gPaletteFadeBuffers[0][i] & 0x1F;
g[0] = (gPaletteFadeBuffers[0][i] & 0x3E0) >> 5;
b[0] = (gPaletteFadeBuffers[0][i] & 0x7C00) >> 10;
r[1] = gPaletteFadeBuffers[1][i] & 0x1F;
g[1] = (gPaletteFadeBuffers[1][i] & 0x3E0) >> 5;
b[1] = (gPaletteFadeBuffers[1][i] & 0x7C00) >> 10;
if(b[0] > b[1])
b[0] -= (b[0] * arg3) >> 5;
else
b[0] = b[1];
if(g[0] > g[1])
g[0] -= (g[0] * arg3) >> 5;
else
g[0] = g[1];
if(r[0] > r[1])
r[0] -= (r[0] * arg3) >> 5;
else
r[0] = r[1];
gPaletteFadeBuffers[2][i] = (b[0] << 10) | (g[0] << 5) | r[0];
}
DmaCopy16(3, gPaletteFadeBuffers[2], dest, arg2);
}
void BrightenPalette(u8 * pal, u8 * dest, u16 arg2, u16 arg3)
{
u16 i;
u16 b[2];
u16 g[2];
u16 r[2];
DmaCopy16(3, pal, gPaletteFadeBuffers[0], arg2);
DmaFill16(3, 0x7FFF, gPaletteFadeBuffers[1], arg2);
for(i = 0; i < arg2; i++)
{
r[0] = gPaletteFadeBuffers[0][i] & 0x1F;
g[0] = (gPaletteFadeBuffers[0][i] & 0x3E0) >> 5;
b[0] = (gPaletteFadeBuffers[0][i] & 0x7C00) >> 10;
r[1] = gPaletteFadeBuffers[1][i] & 0x1F;
g[1] = (gPaletteFadeBuffers[1][i] & 0x3E0) >> 5;
b[1] = (gPaletteFadeBuffers[1][i] & 0x7C00) >> 10;
if(b[0] < b[1])
b[0] += ((b[1] - b[0]) * arg3) >> 5;
else
b[0] -= ((b[0] - b[1]) * arg3) >> 5;
if(g[0] < g[1])
g[0] += ((g[1] - g[0]) * arg3) >> 5;
else
g[0] -= ((g[0] - g[1]) * arg3) >> 5;
if(r[0] < r[1])
r[0] += ((r[1] - r[0]) * arg3) >> 5;
else
r[0] -= ((r[0] - r[1]) * arg3) >> 5;
gPaletteFadeBuffers[2][i] = (b[0] << 10) | (g[0] << 5) | r[0];
}
DmaCopy16(3, gPaletteFadeBuffers[2], dest, arg2);
}
void FlashWhiteTransitionIn(void)
{
REG_BLDY = 0x10;
REG_BLDCNT = ((REG_DISPCNT & (DISPCNT_BG_ALL_ON | DISPCNT_OBJ_ON)) >> 8) | BLDCNT_EFFECT_LIGHTEN | BLDCNT_TGT1_BD;
REG_DISPCNT &= ~DISPCNT_FORCED_BLANK;
gMain.dispcntBackup = REG_DISPCNT;
REG_BLDY = 0x10;
MainLoopIter();
REG_BLDY = 0x8;
MainLoopIter();
REG_BLDY = 0;
MainLoopIter();
REG_BLDCNT = 0;
}
void FlashWhiteTransitionOut(void)
{
REG_BLDY = 0;
REG_BLDCNT = ((REG_DISPCNT & (DISPCNT_BG_ALL_ON | DISPCNT_OBJ_ON)) >> 8) | BLDCNT_EFFECT_LIGHTEN | BLDCNT_TGT1_BD;
REG_BLDY = 0;
MainLoopIter();
REG_BLDY = 0x8;
MainLoopIter();
REG_BLDY = 0x10;
MainLoopIter();
DmaFill16(3, 0, (void*)VRAM, VRAM_SIZE);
REG_BG0HOFS = 0;
REG_BG0VOFS = 0;
REG_BG1HOFS = 0;
REG_BG1VOFS = 0;
REG_BG2HOFS = 0;
REG_BG2VOFS = 0;
REG_BG3HOFS = 0;
REG_BG3VOFS = 0;
MainLoopIter();
}
void UnblankLCD(void)
{
REG_DISPCNT &= ~DISPCNT_FORCED_BLANK;
gMain.dispcntBackup = REG_DISPCNT;
}
void ForceBlankLCD(void)
{
gMain.dispcntBackup |= DISPCNT_FORCED_BLANK;
REG_DISPCNT |= DISPCNT_FORCED_BLANK;
}
void DisableDisplayInterrupts(void)
{
REG_DISPSTAT &= ~DISPSTAT_VBLANK_INTR;
REG_DISPSTAT &= ~DISPSTAT_VCOUNT_INTR;
REG_IE &= 0x3FFF;
REG_IE &= 0x3FFE;
if(REG_IE == 0)
REG_IME = 0;
REG_IF |= 1;
}
void PrintString(u16 glyph, u16 palette, int x, int y, int width, int height)
{
u16 i, j;
for (j = 0; j < height; j++)
for (i = 0; i < width; i++)
gBG0TilemapBuffer[y * 0x20 + x + j * 0x20 + i] = (glyph + j * 0x20 + i) | (palette << 12);
}
void CopyString(int srcX, int srcY, int destX, int destY, int width, int height)
{
u16 i, j;
for (j = 0; j < height; j++)
for (i = 0; i < width; i++)
gBG0TilemapBuffer[destY * 0x20 + destX + j * 0x20 + i] = gBG0TilemapBuffer[srcY * 0x20 + srcX + j * 0x20 + i];
}
void SetStringPalette(int x, int y, int width, int height, u16 palette)
{
u16 i, j;
u16 index;
for (j = 0; j < height; j++)
{
for (i = 0; i < width; i++)
{
index = y * 0x20 + x + j * 0x20 + i;
gBG0TilemapBuffer[index] = (gBG0TilemapBuffer[index] & 0xFFF) | (palette << 12);
}
}
}
// This requires volatile parameters to match. There is no reason, *ever*, to do this.
void CopyBgTilesRect(void *volatile src, void *volatile dest, s16 width, s16 height)
{
int j;
for (j = 0; j < height; j++)
{
DmaCopy16(3, (u8 *)src + 0x400 * j, (u8 *)dest + 0x400 * j, width * 0x20);
}
}
// This function is unused. It appears to operates on a pixel canvas where each "tile" is represented by
// 2 bytes.
void CopyPixelCanvasRect(void *volatile src, void *volatile dest, s16 width, s16 height)
{
int j;
for (j = 0; j < height; j++)
{
DmaCopy16(3, (u8 *)src + 0x40 * j, (u8 *)dest + 0x40 * j, width * 2);
}
}
// This function is unused.
void Unused_FadeInWithCustomPalettes(void *src1, void *src2, void (*func)(void))
{
u16 i;
DmaCopy16(3, src1, gPaletteFadeBuffers[1], BG_PLTT_SIZE);
DmaCopy16(3, src2, gPaletteFadeBuffers[2], BG_PLTT_SIZE);
DmaFill16(3, RGB_WHITE, gPaletteFadeBuffers, PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[0], gPaletteFadeBuffers[2], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[2], (void *)PLTT, PLTT_SIZE);
UnblankLCD();
gMain.dispcntBackup = REG_DISPCNT;
for (i = 0; i <= 0x20; i += 0x10)
{
if (func != NULL)
func();
InterpolatePaletteStep(i);
MainLoopIter();
if (i == 0x20)
{
DmaCopy16(3, gPaletteFadeBuffers[1], (void *)PLTT, PLTT_SIZE);
}
else
{
DmaCopy16(3, gPaletteFadeBuffers[2], (void *)PLTT, PLTT_SIZE);
}
}
}
// This function is unused.
void Unused_FadeOutToWhite(void (*func)(void))
{
u16 i;
DmaCopy16(3, (void *)PLTT, gPaletteFadeBuffers[0], PLTT_SIZE);
DmaFill16(3, RGB_WHITE, gPaletteFadeBuffers[1], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[0], gPaletteFadeBuffers[2], PLTT_SIZE);
for (i = 0; i <= 0x20; i += 0x10)
{
if (func != NULL)
func();
InterpolatePaletteStep(i);
MainLoopIter();
if (i == 0x20)
{
DmaCopy16(3, gPaletteFadeBuffers[1], (void *)PLTT, PLTT_SIZE);
}
else
{
DmaCopy16(3, gPaletteFadeBuffers[2], (void *)PLTT, PLTT_SIZE);
}
}
MainLoopIter();
}

473
src/evolution_mode.c Normal file
View File

@ -0,0 +1,473 @@
#include "global.h"
#include "m4a.h"
#include "main.h"
#include "constants/bg_music.h"
extern struct SongHeader se_evo_item_appear;
extern struct SongHeader se_evo_item_finish_appear;
extern struct SongHeader se_evo_item_collected;
extern const u8 gDefaultBallPalette[];
extern const u8 *gEvoItemAppear_GfxList[];
extern const u8 gEvoItemPalettes[][0x20];
extern const s16 gEvoItemAppearFrameThresholds[];
extern const u16 gEvoItemAnimOamFramesets[58][15];
extern const struct Vector16 gEvoItemPositions[][8];
void CleanupEvolutionModeState(void)
{
s16 i;
LoadPortraitGraphics(0, 0);
gCurrentPinballGame->portraitDisplayState = 0;
for (i = 0; i < 3; i++)
{
if (i < gCurrentPinballGame->evoItemCount)
gCurrentPinballGame->catchLights[i] = 1;
else
gCurrentPinballGame->catchLights[i] = 0;
}
gMain.fieldSpriteGroups[13]->available = 0;
gCurrentPinballGame->trapAnimState = 0;
gCurrentPinballGame->bonusTrapEnabled = 0;
ResetEventState();
}
void InitEvolutionMode(void)
{
gCurrentPinballGame->boardSubState = 0;
gCurrentPinballGame->stageTimer = 0;
gCurrentPinballGame->boardModeType = 2;
gCurrentPinballGame->eventTimer = gCurrentPinballGame->timerBonus + 7200;
gCurrentPinballGame->timerBonus = 0;
gCurrentPinballGame->saverTimeRemaining = 3600;
if (gCurrentPinballGame->currentSpecies == SPECIES_WURMPLE)
{
gCurrentPinballGame->evoItemGfxIndex = 0;
}
else if (gCurrentPinballGame->currentSpecies == SPECIES_GLOOM)
{
if (gMain.selectedField == FIELD_RUBY)
gCurrentPinballGame->evoItemGfxIndex = 1;
else
gCurrentPinballGame->evoItemGfxIndex = 7;
}
else if (gCurrentPinballGame->currentSpecies == SPECIES_CLAMPERL)
{
gCurrentPinballGame->evoItemGfxIndex = 3;
}
else
{
gCurrentPinballGame->evoItemGfxIndex = gSpeciesInfo[gCurrentPinballGame->currentSpecies].evolutionMethod - 1;
if (gCurrentPinballGame->evoItemGfxIndex < 0)
gCurrentPinballGame->evoItemGfxIndex = 0;
}
DmaCopy16(3, gDefaultBallPalette, (void *)0x05000180, 0x20);
gCurrentPinballGame->evoArrowProgress = 0;
gCurrentPinballGame->rouletteSlotActive = 0;
gCurrentPinballGame->catchModeEventTimer = 0;
gCurrentPinballGame->evoItemSlotIndex = 0;
gCurrentPinballGame->evoItemsCaught = 0;
gCurrentPinballGame->evoModeResetFlag = 0;
gCurrentPinballGame->evoItemAppearTimer = 0;
LoadPortraitGraphics(3, 0);
}
void UpdateEvolutionMode(void)
{
s16 i, j;
s16 var0;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 index;
if (gCurrentPinballGame->boardModeType && gCurrentPinballGame->eventTimer < 2 && gCurrentPinballGame->boardSubState < 8)
{
m4aMPlayAllStop();
m4aSongNumStart(MUS_END_OF_BALL2);
gCurrentPinballGame->stageTimer = 200;
gCurrentPinballGame->boardSubState = 8;
}
switch (gCurrentPinballGame->boardSubState)
{
case 0:
if (gCurrentPinballGame->evoModeShuffleRound < 2)
{
for (i = 0; i < 8; i++)
gCurrentPinballGame->evoItemShufflePool[i] = i;
index = (Random() + gMain.systemFrameCount) % 5;
gCurrentPinballGame->evoShuffledSlots[0] = gCurrentPinballGame->evoItemShufflePool[index];
for (i = index; i < 7; i++)
gCurrentPinballGame->evoItemShufflePool[i] = gCurrentPinballGame->evoItemShufflePool[i + 1];
index = (Random() + gMain.systemFrameCount) % 4;
gCurrentPinballGame->evoShuffledSlots[1] = gCurrentPinballGame->evoItemShufflePool[index];
for (i = index; i < 6; i++)
gCurrentPinballGame->evoItemShufflePool[i] = gCurrentPinballGame->evoItemShufflePool[i + 1];
index = (Random() + gMain.systemFrameCount) % 3;
gCurrentPinballGame->evoShuffledSlots[2] = gCurrentPinballGame->evoItemShufflePool[index];
}
else
{
for (i = 0; i < 8; i++)
gCurrentPinballGame->evoItemShufflePool[i] = i;
index = (Random() + gMain.systemFrameCount) % 6;
gCurrentPinballGame->evoShuffledSlots[0] = gCurrentPinballGame->evoItemShufflePool[index];
for (i = index; i < 7; i++)
gCurrentPinballGame->evoItemShufflePool[i] = gCurrentPinballGame->evoItemShufflePool[i + 1];
index = (Random() + gMain.systemFrameCount) % 7;
gCurrentPinballGame->evoShuffledSlots[1] = gCurrentPinballGame->evoItemShufflePool[index];
for (i = index; i < 6; i++)
gCurrentPinballGame->evoItemShufflePool[i] = gCurrentPinballGame->evoItemShufflePool[i + 1];
index = (Random() + gMain.systemFrameCount) % 6;
gCurrentPinballGame->evoShuffledSlots[2] = gCurrentPinballGame->evoItemShufflePool[index];
for (i = index; i < 5; i++)
gCurrentPinballGame->evoItemShufflePool[i] = gCurrentPinballGame->evoItemShufflePool[i + 1];
if (gMain.selectedField == FIELD_SAPPHIRE && gCurrentPinballGame->numCompletedBonusStages < 5)
{
for (i = 0; i < 3; i++)
{
if (gCurrentPinballGame->evoShuffledSlots[i] == 5)
{
index = (Random() + gMain.systemFrameCount) % 5;
gCurrentPinballGame->evoShuffledSlots[i] = gCurrentPinballGame->evoItemShufflePool[index];
}
}
}
}
gCurrentPinballGame->evoModeShuffleRound++;
gCurrentPinballGame->boardSubState++;
break;
case 1:
gCurrentPinballGame->evoItemSlotIndex = gCurrentPinballGame->evoShuffledSlots[gCurrentPinballGame->evoItemsCaught];
gCurrentPinballGame->evoItemPosX = gEvoItemPositions[gMain.selectedField][gCurrentPinballGame->evoItemSlotIndex].x;
gCurrentPinballGame->evoItemPosY = gEvoItemPositions[gMain.selectedField][gCurrentPinballGame->evoItemSlotIndex].y;
gCurrentPinballGame->evoItemAppearTimer = 80;
gMain.fieldSpriteGroups[40]->available = 1;
gCurrentPinballGame->boardSubState++;
break;
case 2:
UpdateEvolutionItemAnimation();
gCurrentPinballGame->stageTimer = 0;
break;
case 3:
gCurrentPinballGame->trapAnimState = 1;
if (gCurrentPinballGame->stageTimer < 8)
{
gCurrentPinballGame->stageTimer++;
}
else
{
ShowBonusTrapSprite();
gCurrentPinballGame->trapAnimState = 2;
gCurrentPinballGame->boardSubState++;
}
break;
case 4:
AnimateBonusTrapSprite();
if (gCurrentPinballGame->ballCatchState == 4)
gCurrentPinballGame->boardSubState++;
break;
case 5:
gCurrentPinballGame->boardModeType = 3;
gCurrentPinballGame->preEvoSpecies = gCurrentPinballGame->currentSpecies;
RegisterCaptureOrEvolution(1);
gCurrentPinballGame->postEvoSpecies = gCurrentPinballGame->currentSpecies;
gCurrentPinballGame->stageTimer = 0;
gCurrentPinballGame->boardSubState++;
break;
case 6:
if (gCurrentPinballGame->modeAnimTimer == 148)
{
gCurrentPinballGame->modeAnimTimer++;
if (gMain.spriteGroups[13].available)
{
if (gCurrentPinballGame->chikoritaProjectileTimer >= 80)
{
RunEvolutionCutscene();
if (gCurrentPinballGame->boardSubState == 6)
gCurrentPinballGame->stageTimer++;
}
}
else
{
RunEvolutionCutscene();
if (gCurrentPinballGame->boardSubState == 6)
gCurrentPinballGame->stageTimer++;
}
}
break;
case 7:
if (gCurrentPinballGame->modeAnimTimer == 148)
{
gCurrentPinballGame->modeAnimTimer++;
if (gCurrentPinballGame->stageTimer < 280)
{
if (gCurrentPinballGame->stageTimer == 0)
{
InitEvolutionSuccessDisplay();
m4aSongNumStart(MUS_SUCCESS2);
}
else
{
AnimateEvolutionSuccessScreen();
if (gCurrentPinballGame->stageTimer < 230)
{
if (gCurrentPinballGame->nameRevealAnimFrame == 150)
gCurrentPinballGame->nameRevealAnimFrame--;
}
if (gCurrentPinballGame->stageTimer == 270)
{
LoadPortraitGraphics(0, 0);
gCurrentPinballGame->portraitDisplayState = 0;
}
if (gCurrentPinballGame->scoreCounterAnimationEnabled)
gCurrentPinballGame->stageTimer = 181;
if (gCurrentPinballGame->stageTimer == 180) {
gCurrentPinballGame->scoreCounterAnimationEnabled = TRUE;
gCurrentPinballGame->scoreAddedInFrame = 5000000;
}
}
if (gCurrentPinballGame->stageTimer < 30)
{
gMain.scoreOverlayActive = 1;
var0 = gCurrentPinballGame->stageTimer;
gCurrentPinballGame->cutsceneTilemapColumn = gCurrentPinballGame->stageTimer;
for (i = 0; i <= var0; i++)
{
for (j = 2; j < 12; j++)
gBG0TilemapBuffer[((j + 15) * 0x20) + i] = 0xC100;
}
DmaCopy16(3, gBG0TilemapBuffer, (void *)0x06002000, 0x800);
}
if (gCurrentPinballGame->stageTimer >= 240 && gCurrentPinballGame->stageTimer < 270)
{
var0 = gCurrentPinballGame->stageTimer - 240;
for (i = 0; i <= var0; i ++)
{
for (j = 2; j < 12; j++)
gBG0TilemapBuffer[((j + 15) << 5) + i] = 0x1FF;
}
DmaCopy16(3, gBG0TilemapBuffer, (void *)0x06002000, 0x800);
if (gCurrentPinballGame->stageTimer == 269)
{
gMain.scoreOverlayActive = 0;
gMain.blendControl = 0;
gMain.blendBrightness = 0;
gMain.blendAlpha = 0;
}
}
gCurrentPinballGame->stageTimer++;
}
else
{
gCurrentPinballGame->modeAnimTimer = 40;
}
}
else if (gCurrentPinballGame->modeAnimTimer == 24)
{
if (gCurrentPinballGame->evoItemCount < 3)
{
gCurrentPinballGame->evoCatchLightSlot1 = gCurrentPinballGame->evoItemCount;
gCurrentPinballGame->evoCatchLightSlot2 = gCurrentPinballGame->evoItemCount;
gCurrentPinballGame->catchLights[gCurrentPinballGame->evoCatchLightSlot1] = 1;
gCurrentPinballGame->evoBlinkTimer = 120;
gCurrentPinballGame->evoItemCount++;
if (gCurrentPinballGame->evoItemCount < 3)
{
gCurrentPinballGame->evoCatchLightSlot2 = gCurrentPinballGame->evoItemCount;
gCurrentPinballGame->catchLights[gCurrentPinballGame->evoCatchLightSlot2] = 1;
gCurrentPinballGame->evoBlinkTimer = 120;
gCurrentPinballGame->evoItemCount++;
}
}
if (gCurrentPinballGame->currentSpecies == SPECIES_NINJASK)
{
gCurrentPinballGame->caughtMonCount++;
if (gCurrentPinballGame->bonusMonCatchCount < 99)
gCurrentPinballGame->bonusMonCatchCount++;
if (gCurrentPinballGame->caughtMonCount == 15)
gCurrentPinballGame->oneUpAnimTimer = 92;
}
gCurrentPinballGame->caughtMonCount++;
if (gCurrentPinballGame->caughtMonCount == 15)
gCurrentPinballGame->oneUpAnimTimer = 92;
if (gCurrentPinballGame->bonusMonCatchCount < 99)
gCurrentPinballGame->bonusMonCatchCount++;
gCurrentPinballGame->boardSubState++;
gCurrentPinballGame->stageTimer = 0;
}
break;
case 8:
group = gMain.fieldSpriteGroups[32];
oamSimple = &group->oam[0];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset - 56;
gMain.fieldSpriteGroups[32]->available = 0;
UpdateEvolutionItemAnimation();
gMain.fieldSpriteGroups[40]->available = 0;
gCurrentPinballGame->activePortraitType = 0;
AnimateBonusTrapSprite();
gMain.fieldSpriteGroups[13]->available = 0;
gCurrentPinballGame->shopTransitionActive = 1;
gCurrentPinballGame->shopAnimTimer = 0;
gCurrentPinballGame->evolutionShopActive = 0;
gCurrentPinballGame->boardSubState++;
if (gCurrentPinballGame->allHolesLit)
gCurrentPinballGame->allHolesLitDelayTimer = 120;
break;
case 9:
CleanupEvolutionModeState();
gCurrentPinballGame->boardSubState++;
break;
case 10:
if (gCurrentPinballGame->stageTimer)
{
gCurrentPinballGame->stageTimer--;
}
else
{
if (gCurrentPinballGame->catchLights[2] == 1)
RequestBoardStateTransition(3);
else
RequestBoardStateTransition(1);
gCurrentPinballGame->boardSubState = 0;
}
break;
}
}
void UpdateEvolutionItemAnimation(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 *dst;
const u16 *src;
struct Vector32 tempVector;
int xx, yy;
int squaredMagnitude;
s16 index;
index = (gMain.systemFrameCount % 75) / 3;
group = gMain.fieldSpriteGroups[32];
if (gCurrentPinballGame->evoItemAppearTimer)
{
group = gMain.fieldSpriteGroups[40];
if (gCurrentPinballGame->evoItemAppearTimer == 80)
{
gCurrentPinballGame->activePortraitType = 15;
DmaCopy16(3, gEvoItemAppear_GfxList[gCurrentPinballGame->evoItemGfxIndex], (void *)0x06015800, 0x1C00);
DmaCopy16(3, &gEvoItemPalettes[gCurrentPinballGame->evoItemGfxIndex], (void *)0x050003E0, 0x20);
gCurrentPinballGame->evoItemAnimFrame = 0;
gCurrentPinballGame->evoItemAnimFrameTimer = 0;
}
if (gCurrentPinballGame->evoItemAppearTimer == 60)
MPlayStart(&gMPlayInfo_SE1, &se_evo_item_appear);
if (gEvoItemAppearFrameThresholds[gCurrentPinballGame->evoItemAnimFrame] > gCurrentPinballGame->evoItemAnimFrameTimer)
{
gCurrentPinballGame->evoItemAnimFrameTimer++;
}
else
{
gCurrentPinballGame->evoItemAnimFrameTimer = 1;
gCurrentPinballGame->evoItemAnimFrame++;
if (gCurrentPinballGame->evoItemAnimFrame == 29)
{
gCurrentPinballGame->evoItemAnimFrame = 28;
gCurrentPinballGame->evoItemAppearTimer = 1;
gMain.fieldSpriteGroups[40]->available = 0;
gMain.fieldSpriteGroups[32]->available = 1;
MPlayStart(&gMPlayInfo_SE1, &se_evo_item_finish_appear);
gCurrentPinballGame->activePortraitType = 0;
}
}
group->baseX = gCurrentPinballGame->evoItemPosX - gCurrentPinballGame->cameraXOffset + 8;
group->baseY = gCurrentPinballGame->evoItemPosY - gCurrentPinballGame->cameraYOffset + 8;
if (group->baseY < -30)
group->baseY = -30;
if (group->baseY > 200)
group->baseY = 200;
for (i = 0; i < 5; i++)
{
oamSimple = &group->oam[i];
dst = (u16 *)&gOamBuffer[oamSimple->oamId];
*dst++ = gEvoItemAnimOamFramesets[gCurrentPinballGame->evoItemAnimFrame][i * 3 + 0];
*dst++ = gEvoItemAnimOamFramesets[gCurrentPinballGame->evoItemAnimFrame][i * 3 + 1];
*dst++ = gEvoItemAnimOamFramesets[gCurrentPinballGame->evoItemAnimFrame][i * 3 + 2];
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
gCurrentPinballGame->evoItemAppearTimer--;
}
else
{
tempVector.x = gCurrentPinballGame->ball->positionQ0.x - (gCurrentPinballGame->evoItemPosX + 8);
tempVector.y = gCurrentPinballGame->ball->positionQ0.y - (gCurrentPinballGame->evoItemPosY + 8);
xx = tempVector.x * tempVector.x;
yy = tempVector.y * tempVector.y;
squaredMagnitude = xx + yy;
if (squaredMagnitude < 82 &&
((gCurrentPinballGame->boardLayerDepth == 0 && gCurrentPinballGame->evoItemSlotIndex <= 5) || (gCurrentPinballGame->boardLayerDepth == 2 && gCurrentPinballGame->evoItemSlotIndex > 5)) &&
gCurrentPinballGame->evoItemsCaught < 3)
{
gCurrentPinballGame->scoreAddedInFrame = 10000;
MPlayStart(&gMPlayInfo_SE1, &se_evo_item_collected);
gCurrentPinballGame->boardSubState = 1;
gCurrentPinballGame->catchLights[gCurrentPinballGame->evoItemsCaught] = 5;
gCurrentPinballGame->evoItemsCaught++;
gMain.fieldSpriteGroups[32]->available = 0;
if (gCurrentPinballGame->evoItemsCaught == 3)
{
gCurrentPinballGame->evoItemsCaught = 0;
gCurrentPinballGame->boardSubState = 3;
}
}
group->baseX = gCurrentPinballGame->evoItemPosX - gCurrentPinballGame->cameraXOffset - 8;
group->baseY = gCurrentPinballGame->evoItemPosY - gCurrentPinballGame->cameraYOffset - 8;
if (group->baseY < -30)
group->baseY = -30;
if (group->baseY > 200)
group->baseY = 200;
if (index > 14)
index = 14;
DmaCopy16(3, gEvoItemTilesGfxPtrs[gCurrentPinballGame->evoItemGfxIndex] + index * 0x200, (void *)0x060116C0, 0x200);
oamSimple = &group->oam[0];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}

View File

@ -2389,301 +2389,3 @@ s8 CheckAllPokemonCaught(void)
return 1;
}
void FadeInFromWhite(void (*func)(void))
{
u16 i;
DmaCopy16(3, (void*)PLTT, gPaletteFadeBuffers[1], PLTT_SIZE);
DmaFill16(3, 0x7FFF, gPaletteFadeBuffers[0], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[0], gPaletteFadeBuffers[2], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[2], (void*)PLTT, PLTT_SIZE);
UnblankLCD();
for (i = 0; i < 32; i++)
{
if (func != NULL)
func();
InterpolatePaletteStep(i);
MainLoopIter();
if (i == 31)
{
DmaCopy16(3, gPaletteFadeBuffers[1], (void *)PLTT, 0x400);
}
else
{
DmaCopy16(3, gPaletteFadeBuffers[2], (void *)PLTT, 0x400);
}
}
}
void FadeOutToWhite(void (*func)(void))
{
u16 i;
DmaCopy16(3, (void*)PLTT, gPaletteFadeBuffers[0], PLTT_SIZE);
DmaFill16(3, 0x7FFF, gPaletteFadeBuffers[1], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[0], gPaletteFadeBuffers[2], PLTT_SIZE);
for (i = 0; i < 32; i++)
{
if (func != NULL)
func();
InterpolatePaletteStep(i);
MainLoopIter();
if (i == 31)
{
DmaCopy16(3, gPaletteFadeBuffers[1], (void *)PLTT, 0x400);
}
else
{
DmaCopy16(3, gPaletteFadeBuffers[2], (void *)PLTT, 0x400);
}
}
ForceBlankLCD();
MainLoopIter();
ClearGraphicsMemory();
}
void FadeInWithCustomPalettes(u8 * arg0, u8 * arg1, void (*func)(void))
{
u16 i;
DmaCopy16(3, arg0, gPaletteFadeBuffers[1], 0x200);
DmaCopy16(3, arg1, gPaletteFadeBuffers[2], 0x200);
DmaFill16(3, 0, gPaletteFadeBuffers[0], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[0], gPaletteFadeBuffers[2], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[2], (void*)PLTT, PLTT_SIZE);
UnblankLCD();
gMain.dispcntBackup = REG_DISPCNT;
for (i = 0; i < 32; i++)
{
if (func != NULL)
func();
InterpolatePaletteStep(i);
MainLoopIter();
if (i == 31)
{
DmaCopy16(3, gPaletteFadeBuffers[1], (void *)PLTT, 0x400);
}
else
{
DmaCopy16(3, gPaletteFadeBuffers[2], (void *)PLTT, 0x400);
}
}
}
void FadeOutToBlack(void (*func)(void))
{
u16 i;
DmaCopy16(3, (void*)PLTT, gPaletteFadeBuffers[0], PLTT_SIZE);
DmaFill16(3, 0, gPaletteFadeBuffers[1], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[0], gPaletteFadeBuffers[2], PLTT_SIZE);
for (i = 0; i < 32; i++)
{
if (func != NULL)
func();
InterpolatePaletteStep(i);
MainLoopIter();
if (i == 31)
{
DmaCopy16(3, gPaletteFadeBuffers[1], (void *)PLTT, 0x400);
}
else
{
DmaCopy16(3, gPaletteFadeBuffers[2], (void *)PLTT, 0x400);
}
}
MainLoopIter();
}
void InterpolatePaletteStep(u16 arg0)
{
u16 var0;
u16 var1;
u16 b[2];
u16 g[2];
u16 r[2];
u16 spC[4];
spC[0] = 0;
spC[1] = 2;
spC[2] = 1;
spC[3] = 3;
var0 = spC[arg0 & 3] * 128;
var1 = var0 + 128;
arg0 &= ~3;
arg0 += 4;
while(var0 < var1)
{
r[0] = gPaletteFadeBuffers[0][var0] & 0x1F;
g[0] = (gPaletteFadeBuffers[0][var0] & 0x3E0) >> 5;
b[0] = (gPaletteFadeBuffers[0][var0] & 0x7C00) >> 10;
r[1] = gPaletteFadeBuffers[1][var0] & 0x1F;
g[1] = (gPaletteFadeBuffers[1][var0] & 0x3E0) >> 5;
b[1] = (gPaletteFadeBuffers[1][var0] & 0x7C00) >> 10;
if(b[0] < b[1])
b[0] += ((b[1] - b[0]) * arg0) >> 5;
else
b[0] -= ((b[0] - b[1]) * arg0) >> 5;
if(g[0] < g[1])
g[0] += ((g[1] - g[0]) * arg0) >> 5;
else
g[0] -= ((g[0] - g[1]) * arg0) >> 5;
if(r[0] < r[1])
r[0] += ((r[1] - r[0]) * arg0) >> 5;
else
r[0] -= ((r[0] - r[1]) * arg0) >> 5;
gPaletteFadeBuffers[2][var0] = (b[0] << 10) | (g[0] << 5) | r[0];
var0++;
}
}
void DarkenPalette(u8 * pal, u8 * dest, u16 arg2, u16 arg3)
{
u16 i;
u16 b[2];
u16 g[2];
u16 r[2];
DmaCopy16(3, pal, gPaletteFadeBuffers[0], arg2);
DmaFill16(3, 0, gPaletteFadeBuffers[1], arg2);
for(i = 0; i < arg2; i++)
{
r[0] = gPaletteFadeBuffers[0][i] & 0x1F;
g[0] = (gPaletteFadeBuffers[0][i] & 0x3E0) >> 5;
b[0] = (gPaletteFadeBuffers[0][i] & 0x7C00) >> 10;
r[1] = gPaletteFadeBuffers[1][i] & 0x1F;
g[1] = (gPaletteFadeBuffers[1][i] & 0x3E0) >> 5;
b[1] = (gPaletteFadeBuffers[1][i] & 0x7C00) >> 10;
if(b[0] > b[1])
b[0] -= (b[0] * arg3) >> 5;
else
b[0] = b[1];
if(g[0] > g[1])
g[0] -= (g[0] * arg3) >> 5;
else
g[0] = g[1];
if(r[0] > r[1])
r[0] -= (r[0] * arg3) >> 5;
else
r[0] = r[1];
gPaletteFadeBuffers[2][i] = (b[0] << 10) | (g[0] << 5) | r[0];
}
DmaCopy16(3, gPaletteFadeBuffers[2], dest, arg2);
}
void BrightenPalette(u8 * pal, u8 * dest, u16 arg2, u16 arg3)
{
u16 i;
u16 b[2];
u16 g[2];
u16 r[2];
DmaCopy16(3, pal, gPaletteFadeBuffers[0], arg2);
DmaFill16(3, 0x7FFF, gPaletteFadeBuffers[1], arg2);
for(i = 0; i < arg2; i++)
{
r[0] = gPaletteFadeBuffers[0][i] & 0x1F;
g[0] = (gPaletteFadeBuffers[0][i] & 0x3E0) >> 5;
b[0] = (gPaletteFadeBuffers[0][i] & 0x7C00) >> 10;
r[1] = gPaletteFadeBuffers[1][i] & 0x1F;
g[1] = (gPaletteFadeBuffers[1][i] & 0x3E0) >> 5;
b[1] = (gPaletteFadeBuffers[1][i] & 0x7C00) >> 10;
if(b[0] < b[1])
b[0] += ((b[1] - b[0]) * arg3) >> 5;
else
b[0] -= ((b[0] - b[1]) * arg3) >> 5;
if(g[0] < g[1])
g[0] += ((g[1] - g[0]) * arg3) >> 5;
else
g[0] -= ((g[0] - g[1]) * arg3) >> 5;
if(r[0] < r[1])
r[0] += ((r[1] - r[0]) * arg3) >> 5;
else
r[0] -= ((r[0] - r[1]) * arg3) >> 5;
gPaletteFadeBuffers[2][i] = (b[0] << 10) | (g[0] << 5) | r[0];
}
DmaCopy16(3, gPaletteFadeBuffers[2], dest, arg2);
}
void FlashWhiteTransitionIn(void)
{
REG_BLDY = 0x10;
REG_BLDCNT = ((REG_DISPCNT & (DISPCNT_BG_ALL_ON | DISPCNT_OBJ_ON)) >> 8) | BLDCNT_EFFECT_LIGHTEN | BLDCNT_TGT1_BD;
REG_DISPCNT &= ~DISPCNT_FORCED_BLANK;
gMain.dispcntBackup = REG_DISPCNT;
REG_BLDY = 0x10;
MainLoopIter();
REG_BLDY = 0x8;
MainLoopIter();
REG_BLDY = 0;
MainLoopIter();
REG_BLDCNT = 0;
}
void FlashWhiteTransitionOut(void)
{
REG_BLDY = 0;
REG_BLDCNT = ((REG_DISPCNT & (DISPCNT_BG_ALL_ON | DISPCNT_OBJ_ON)) >> 8) | BLDCNT_EFFECT_LIGHTEN | BLDCNT_TGT1_BD;
REG_BLDY = 0;
MainLoopIter();
REG_BLDY = 0x8;
MainLoopIter();
REG_BLDY = 0x10;
MainLoopIter();
DmaFill16(3, 0, (void*)VRAM, VRAM_SIZE);
REG_BG0HOFS = 0;
REG_BG0VOFS = 0;
REG_BG1HOFS = 0;
REG_BG1VOFS = 0;
REG_BG2HOFS = 0;
REG_BG2VOFS = 0;
REG_BG3HOFS = 0;
REG_BG3VOFS = 0;
MainLoopIter();
}
void UnblankLCD(void)
{
REG_DISPCNT &= ~DISPCNT_FORCED_BLANK;
gMain.dispcntBackup = REG_DISPCNT;
}
void ForceBlankLCD(void)
{
gMain.dispcntBackup |= DISPCNT_FORCED_BLANK;
REG_DISPCNT |= DISPCNT_FORCED_BLANK;
}
void DisableDisplayInterrupts(void)
{
REG_DISPSTAT &= ~DISPSTAT_VBLANK_INTR;
REG_DISPSTAT &= ~DISPSTAT_VCOUNT_INTR;
REG_IE &= 0x3FFF;
REG_IE &= 0x3FFE;
if(REG_IE == 0)
REG_IME = 0;
REG_IF |= 1;
}

View File

@ -0,0 +1,862 @@
#include "global.h"
#include "m4a.h"
#include "main.h"
#include "constants/bg_music.h"
extern const u8 gRubyTravelVolbeat_Gfx[][0x480];
extern const u8 gSapphireTravelIllumise_Gfx[][0x480];
extern const u8 gRubyBoardBonusGfx[];
extern const u8 gRubyBoardBonusObjPalette[];
extern const u8 gSapphireBoardBonusGfx[];
extern const u8 gSapphireBoardBonusObjPalette[];
extern const s16 gTravelEventAnimData[][3];
extern const s16 gAreaToSpeciesTable[];
extern const s16 gAreaRouletteTable[][7];
extern u16 gTravelEventSpritesheetOam[][18];
extern const s16 gHatchRevealFinalTimings[];
extern const u16 gHatchSequentialOamFramesets[22][12];
extern const u8 gBoardActionTilesGfx[];
extern const u8 gBoardActionObjPal[];
extern const u16 gEvolutionSparkleSpritesheetOam[20][12];
extern const u8 gHatchFinalTilesGfx[];
extern const u8 gHatchFinalPalette[];
extern const s16 gSpoinkAnimFrameset[][2];
extern const u8 gSpoinkEntity_Gfx[][0x1C0];
extern const u8 gOneUpBannerSprite_Gfx[][0x200];
extern const u8 gLifeCountDigit_Gfx[][0x40];
extern const u8 gOneUpSpritePalette[];
extern struct SongHeader se_unk_fc;
extern struct SongHeader se_pika_full_charge_1_up;
extern u8 gPaletteFadeRGBCache[][3];
void AnimateOneUpSprite(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 var0;
s16 var1;
s16 index;
s16 scale;
var0 = 0;
group = gMain.fieldSpriteGroups[50];
if (group->available)
{
group->baseX = 202;
if (gCurrentPinballGame->oneUpAnimTimer > 48)
{
var1 = gCurrentPinballGame->oneUpAnimTimer - 48;
if (var1 >= 34)
{
group->baseY = 146 - (42 - var1) * 2;
index = 0;
}
else if (var1 >= 24)
{
group->baseY = 130;
index = 1;
var0 = -9;
}
else if (var1 > 7)
{
group->baseY = 130;
index = 2;
var0 = -4;
}
else
{
group->baseY = 146 - var1 * 2;
index = 0;
}
DmaCopy16(3, gOneUpBannerSprite_Gfx[index], (void *)0x060152A0, 0x200);
}
else
{
group->baseY = 180;
}
oamSimple = &group->oam[0];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
if (gCurrentPinballGame->oneUpAnimTimer > 56)
{
scale = 0x100;
}
else
{
var1 = gCurrentPinballGame->oneUpAnimTimer - 36;
if (var1 >= 0)
{
scale = (var1 * 0x80) / 20 + 0x80;
group->baseY = 130;
var0 = -2;
}
else
{
scale = 0x80;
group->baseY = 180;
var0 = 0;
}
}
oamSimple = &group->oam[1];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY + var0;
gOamBuffer[oamSimple->oamId].affineMode = ST_OAM_AFFINE_NORMAL;
gOamBuffer[oamSimple->oamId].matrixNum = 6;
SetMatrixScale(scale, scale, 6);
if (gCurrentPinballGame->oneUpAnimTimer < 58)
{
index = gCurrentPinballGame->numLives - 1 + (((gCurrentPinballGame->oneUpAnimTimer % 16) / 8) * 9);
DmaCopy16(3, gLifeCountDigit_Gfx[index], (void *)0x06015520, 0x40);
oamSimple = &group->oam[2];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + 216;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset - 112;
}
else
{
oamSimple = &group->oam[2];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + 216;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset - 76;
}
}
if (gCurrentPinballGame->oneUpAnimTimer)
{
if (gCurrentPinballGame->oneUpAnimTimer == 90)
{
group->available = 1;
DmaCopy16(3, gOneUpSpritePalette, (void *)0x05000380, 0x20);
}
if (gCurrentPinballGame->oneUpAnimTimer == 85)
MPlayStart(&gMPlayInfo_SE1, &se_unk_fc);
if (gCurrentPinballGame->oneUpAnimTimer == 58)
{
MPlayStart(&gMPlayInfo_SE1, &se_pika_full_charge_1_up);
if (gCurrentPinballGame->numLives < 9)
gCurrentPinballGame->numLives++;
}
gCurrentPinballGame->oneUpAnimTimer--;
if (gCurrentPinballGame->oneUpAnimTimer == 0)
group->available = 0;
}
}
void AnimateBannerSlide(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
group = gMain.fieldSpriteGroups[10];
if (group->available)
{
group->baseX = gCurrentPinballGame->bannerSlideX;
group->baseY = 44;
for (i = 0; i < 7; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
if (gCurrentPinballGame->bannerDisplayDuration > 0)
{
if (gCurrentPinballGame->bannerDisplayDuration == 120)
gMain.fieldSpriteGroups[10]->available = 1;
gCurrentPinballGame->bannerSlideX = 270 - ((120 - gCurrentPinballGame->bannerDisplayDuration) * 3);
if (gCurrentPinballGame->bannerDisplayDuration == 1)
gMain.fieldSpriteGroups[10]->available = 0;
}
}
void UpdateSpoinkAnimation(void)
{
if (gCurrentPinballGame->cameraYViewport < 170)
{
DmaCopy16(3, gFieldPaletteVariants[gMain.selectedField][gCurrentPinballGame->activePaletteIndex * 2], (void *)OBJ_PLTT + 0x160, 0x20);
}
else
{
DmaCopy16(3, gFieldPaletteVariants[gMain.selectedField][gCurrentPinballGame->activePaletteIndex * 2 + 1], (void *)OBJ_PLTT + 0x160, 0x20);
}
switch (gCurrentPinballGame->spoinkEntityState)
{
case 0:
gCurrentPinballGame->spoinkAnimFrameIx = 0;
gCurrentPinballGame->spoinkAnimFrameTimer = 0;
if (gCurrentPinballGame->ballTouchingSpoink)
gCurrentPinballGame->spoinkPullbackYDistance = (gCurrentPinballGame->globalAnimFrameCounter % 30) / 15;
else
gCurrentPinballGame->spoinkPullbackYDistance = 0;
gCurrentPinballGame->ballTouchingSpoink = 0;
break;
case 1:
if (gCurrentPinballGame->spoinkAnimFrameTimer < 5)
{
if (gCurrentPinballGame->spoinkAnimFrameTimer < 2)
{
gCurrentPinballGame->spoinkAnimFrameIx = 2;
gCurrentPinballGame->spoinkPullbackYDistance = 3;
}
else
{
gCurrentPinballGame->spoinkAnimFrameIx = 3;
gCurrentPinballGame->spoinkPullbackYDistance = 5;
}
if (gCurrentPinballGame->spoinkAnimFrameTimer == 0)
m4aSongNumStart(SE_UNKNOWN_0xCC);
gCurrentPinballGame->spoinkAnimFrameTimer++;
}
else
{
gCurrentPinballGame->spoinkEntityState = 2;
gCurrentPinballGame->spoinkAnimFrameIx = 4;
gCurrentPinballGame->spoinkAnimFrameTimer = 0;
}
break;
case 2:
if (gSpoinkAnimFrameset[gCurrentPinballGame->spoinkAnimFrameIx][1] <= gCurrentPinballGame->spoinkAnimFrameTimer)
{
gCurrentPinballGame->spoinkAnimFrameTimer = 0;
gCurrentPinballGame->spoinkAnimFrameIx++;
if (gCurrentPinballGame->spoinkAnimFrameIx > 7)
gCurrentPinballGame->spoinkAnimFrameIx = 4;
}
else
{
gCurrentPinballGame->spoinkAnimFrameTimer++;
}
break;
case 3:
gCurrentPinballGame->spoinkAnimFrameIx = 8;
gCurrentPinballGame->spoinkAnimFrameTimer = 0;
gCurrentPinballGame->spoinkEntityState = 4;
gCurrentPinballGame->spoinkPullbackYDistance = 0;
break;
case 4:
if (gSpoinkAnimFrameset[gCurrentPinballGame->spoinkAnimFrameIx][1] > gCurrentPinballGame->spoinkAnimFrameTimer)
{
gCurrentPinballGame->spoinkAnimFrameTimer++;
}
else
{
gCurrentPinballGame->spoinkAnimFrameTimer = 0;
gCurrentPinballGame->spoinkAnimFrameIx++;
if (gCurrentPinballGame->spoinkAnimFrameIx > 0x13)
{
gCurrentPinballGame->spoinkAnimFrameIx = 0;
gCurrentPinballGame->spoinkEntityState = 0;
}
}
break;
}
}
void DrawSpoinkSprite(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 index;
group = gMain.fieldSpriteGroups[44];
if (group->available)
{
if (gCurrentPinballGame->spoinkAnimFrameIx == 0)
index = (gCurrentPinballGame->globalAnimFrameCounter % 30) / 15;
else
index = gSpoinkAnimFrameset[gCurrentPinballGame->spoinkAnimFrameIx][0];
DmaCopy16(3, gSpoinkEntity_Gfx[index], (void *)0x060120E0, 0x1C0);
group->baseX = 231 - gCurrentPinballGame->cameraXOffset;
group->baseY = 376 - gCurrentPinballGame->cameraYOffset;
for (i = 0; i < 3; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
}
void RunEvolutionCutscene(void)
{
s16 i, j;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 *dst;
s16 var0;
s16 index;
s16 sp0[0xD8];
s16 sp1B0[0x30];
u8 sp210[3];
if (gCurrentPinballGame->stageTimer <= 360)
{
if (gCurrentPinballGame->stageTimer == 0)
{
m4aMPlayAllStop();
DmaCopy16(3, (void *)0x05000200, gCurrentPinballGame->pauseObjPalette, 0x200);
gCurrentPinballGame->creatureOamPriority = 0;
gCurrentPinballGame->boardEntityActive = 0;
}
if (gCurrentPinballGame->stageTimer == 10)
{
gCurrentPinballGame->activePortraitType = 16;
DmaCopy16(3, gBoardActionTilesGfx, (void *)0x06015800, 0x2400);
DmaCopy16(3, gBoardActionObjPal, (void *)0x050003C0, 0x20);
gMain.fieldSpriteGroups[24]->available = 1;
gMain.fieldSpriteGroups[25]->available = 1;
gMain.fieldSpriteGroups[26]->available = 1;
gMain.fieldSpriteGroups[27]->available = 1;
gMain.fieldSpriteGroups[28]->available = 1;
gMain.fieldSpriteGroups[15]->available = 1;
}
if (gCurrentPinballGame->scrollEffectY < 236)
gCurrentPinballGame->cameraYAdjust = gCurrentPinballGame->stageTimer / 2;;
if (gCurrentPinballGame->stageTimer > 35)
{
if (gCurrentPinballGame->stageTimer < 68)
{
var0 = gCurrentPinballGame->stageTimer - 36;
for (j = 0; j <= var0; j++)
{
for (i = 1; i < 11; i++)
gBG0TilemapBuffer[(i + 15) * 0x20 + j] = 0xC100;
}
DmaCopy16(3, gBG0TilemapBuffer, (void *)0x06002000, 0x800);
if (var0 == 30)
m4aSongNumStart(MUS_EVOLUTION);
if (gMain.selectedField == FIELD_SAPPHIRE && gCurrentPinballGame->stageTimer == 67)
gCurrentPinballGame->sapphireBumperTimer = 120;
}
else if (gCurrentPinballGame->stageTimer <= 344)
{
for (j = 0; j <= 30; j++)
{
for (i = 1; i < 11; i++)
gBG0TilemapBuffer[(i + 15) * 32 + j] = 0xC100;
}
DmaCopy16(3, gBG0TilemapBuffer, (void *)0x06002000, 0x800);
}
}
if (gCurrentPinballGame->stageTimer - 270 >= 0 && gCurrentPinballGame->stageTimer - 270 <= 30)
{
var0 = gCurrentPinballGame->stageTimer - 270;
if (var0 == 0)
{
for (i = 0; i < 16; i++)
{
gPaletteFadeRGBCache[i][0] = gCurrentPinballGame->pauseObjPalette[13][i] & 0x1F;
gPaletteFadeRGBCache[i][1] = (gCurrentPinballGame->pauseObjPalette[13][i] & 0x3E0) >> 5;
gPaletteFadeRGBCache[i][2] = (gCurrentPinballGame->pauseObjPalette[13][i] & 0x7C00) >> 10;
}
}
else
{
u16 *destColor;
for (i = 0; i < 16; i++)
{
destColor = sp1B0;
sp210[0] = gPaletteFadeRGBCache[i][0] + ((0x1F - gPaletteFadeRGBCache[i][0]) * var0) / 30;
sp210[1] = gPaletteFadeRGBCache[i][1] + ((0x1F - gPaletteFadeRGBCache[i][1]) * var0) / 30;
sp210[2] = gPaletteFadeRGBCache[i][2] + ((0x1F - gPaletteFadeRGBCache[i][2]) * var0) / 30;
destColor[i] = sp210[0] | (sp210[1] << 5) | (sp210[2] << 0xA);
}
DmaCopy16(3, destColor, (void *)0x050003A0, 0x20);
}
if (var0 == 10)
m4aSongNumStart(SE_UNKNOWN_0xB0);
}
var0 = gCurrentPinballGame->stageTimer - 300;
if (var0 >= 0 && var0 <= 16)
{
gCurrentPinballGame->startButtonDisabled = 1;
var0 = gCurrentPinballGame->stageTimer - 300;
gMain.blendControl = 0x9F;
gMain.blendBrightness = var0;
}
if (gCurrentPinballGame->stageTimer > 10)
{
group = gMain.fieldSpriteGroups[24];
var0 = -120 + gCurrentPinballGame->stageTimer;
if (var0 >= 22)
sp0[0] = ((var0 - 22) % 102) * 3 - 160;
else
sp0[0] = -162;
if (var0 >= 0)
sp0[1] = (var0 % 102) * 3 - 162;
else
sp0[1] = -162;
if (var0 >= 72)
sp0[2] = ((var0 - 72) % 102) * 3 - 162;
else
sp0[2] = -162;
if (var0 >= 51)
sp0[3] = ((var0 - 51) % 102) * 3 - 161;
else
sp0[3] = -161;
group->baseX = 96 - gCurrentPinballGame->cameraXOffset;
group->baseY = 308 - gCurrentPinballGame->cameraYOffset;
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = group->baseX + sp0[i];
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
var0 = -60 + gCurrentPinballGame->stageTimer;
if (var0 >= 22)
sp0[0] = ((var0 - 22) % 102) * 3 - 160;
else
sp0[0] = -162;
if (var0 >= 0)
sp0[1] = (var0 % 102) * 3 - 162;
else
sp0[1] = -162;
if (var0 >= 72)
sp0[2] = ((var0 - 72) % 102) * 3 - 162;
else
sp0[2] = -162;
if (var0 >= 51)
sp0[3] = ((var0 - 51) % 102) * 3 - 161;
else
sp0[3] = -161;
group = gMain.fieldSpriteGroups[25];
group->baseX = 96 - gCurrentPinballGame->cameraXOffset;
group->baseY = 308 - gCurrentPinballGame->cameraYOffset;
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = group->baseX + sp0[i];
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
group = gMain.fieldSpriteGroups[26];
var0 = -100 + gCurrentPinballGame->stageTimer;
if (var0 >= 0)
sp0[0] = (var0 % 152) * 2 - 160;
else
sp0[0] = -160;
if (var0 >= 38)
sp0[1] = ((var0 - 38) % 152) * 2 - 160;
else
sp0[1] = -160;
if (var0 >= 76)
sp0[2] = ((var0 - 76) % 152) * 2 - 160;
else
sp0[2] = -160;
if (var0 >= 114)
sp0[3] = ((var0 - 114) % 152) * 2 - 160;
else
sp0[3] = -160;
group->baseX = 96 - gCurrentPinballGame->cameraXOffset;
group->baseY = 308 - gCurrentPinballGame->cameraYOffset;
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = group->baseX + sp0[i];
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
group = gMain.fieldSpriteGroups[27];
var0 = -80 + gCurrentPinballGame->stageTimer;
if (var0 >= 0)
sp0[0] = (var0 % 152) * 2 - 160;
else
sp0[0] = -160;
if (var0 >= 38)
sp0[1] = ((var0 - 38) % 152) * 2 - 160;
else
sp0[1] = -160;
if (var0 >= 76)
sp0[2] = ((var0 - 76) % 152) * 2 - 160;
else
sp0[2] = -160;
if (var0 >= 114)
sp0[3] = ((var0 - 114) % 152) * 2 - 160;
else
sp0[3] = -160;
group->baseX = 96 - gCurrentPinballGame->cameraXOffset;
group->baseY = 308 - gCurrentPinballGame->cameraYOffset;
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = group->baseX + sp0[i];
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
var0 = -90 + gCurrentPinballGame->stageTimer;
if (var0 >= 236)
sp0[0] = (var0 - 236) % 272 - 128;
else
sp0[0] = -128;
if (var0 >= 204)
sp0[1] = (var0 - 204) % 272 - 128;
else
sp0[1] = -128;
if (var0 >= 168)
sp0[2] = (var0 - 168) % 272 - 128;
else
sp0[2] = -128;
if (var0 >= 136)
sp0[3] = (var0 - 136) % 272 - 128;
else
sp0[3] = -128;
if (var0 >= 100)
sp0[4] = (var0 - 100) % 272 - 128;
else
sp0[4] = -128;
if (var0 >= 68)
sp0[5] = (var0 - 68) % 272 - 128;
else
sp0[5] = -128;
if (var0 >= 32)
sp0[6] = (var0 - 32) % 272 - 128;
else
sp0[6] = -128;
if (var0 >= 0)
sp0[7] = (var0 % 272) - 128;
else
sp0[7] = -128;
group = gMain.fieldSpriteGroups[28];
group->baseX = 96 - gCurrentPinballGame->cameraXOffset;
group->baseY = 308 - gCurrentPinballGame->cameraYOffset;
for (i = 0; i < 8; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = group->baseX + sp0[i];
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
group = gMain.fieldSpriteGroups[15];
group->baseX = 96 - gCurrentPinballGame->cameraXOffset;
group->baseY = 308 - gCurrentPinballGame->cameraYOffset;
var0 = -120 + gCurrentPinballGame->stageTimer;
if (var0 > 0)
{
sp0[0] = 0;
index = (var0 % 70) / 7;
}
else
{
sp0[0] = -160;
index = 0;
}
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
dst = (u16*)&gOamBuffer[oamSimple->oamId];
*dst++ = gEvolutionSparkleSpritesheetOam[index][i * 3 + 0];
*dst++ = gEvolutionSparkleSpritesheetOam[index][i * 3 + 1];
*dst++ = gEvolutionSparkleSpritesheetOam[index][i * 3 + 2];
gOamBuffer[oamSimple->oamId].x += group->baseX + sp0[0];
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
}
if (gCurrentPinballGame->stageTimer == 350)
{
for (i = 0x1E0; i < 0x340; i++)
gBG0TilemapBuffer[i] = 0x1FF;
DmaCopy16(3, gBG0TilemapBuffer, (void *)0x06002000, 0x800);
if (gMain.selectedField == FIELD_SAPPHIRE)
gCurrentPinballGame->sapphireBumperTimer = 0;
}
if (gCurrentPinballGame->stageTimer == 360)
{
gMain.fieldSpriteGroups[24]->available = 0;
gMain.fieldSpriteGroups[25]->available = 0;
gMain.fieldSpriteGroups[26]->available = 0;
gMain.fieldSpriteGroups[27]->available = 0;
gMain.fieldSpriteGroups[28]->available = 0;
gMain.fieldSpriteGroups[15]->available = 0;
gCurrentPinballGame->currentSpecies = gCurrentPinballGame->postEvoSpecies;
LoadPortraitGraphics(3, 0);
gCurrentPinballGame->activePortraitType = 17;
DmaCopy16(3, gHatchFinalTilesGfx, (void *)0x06015800, 0x1800);
DmaCopy16(3, gHatchFinalPalette, (void *)0x050003C0, 0x20);
gCurrentPinballGame->creatureOamPriority = 3;
}
}
else
{
var0 = gCurrentPinballGame->stageTimer - 360;
if (var0 <= 64)
{
if (var0 == 1)
m4aMPlayStop(&gMPlayInfo_BGM);
gMain.blendControl = 0x9F;
gMain.blendBrightness = 16 - (var0 / 4);
if (var0 == 32)
{
gCurrentPinballGame->bgmFadeTimer = 140;
PlayCry_Normal(gSpeciesInfo[gCurrentPinballGame->currentSpecies].speciesIdRS, 0);
}
if (var0 == 64)
{
gCurrentPinballGame->revealAnimFrameCounter = 0;
gCurrentPinballGame->revealFramesetIndex = 0;
gMain.fieldSpriteGroups[37]->available = 1;
}
}
else
{
gCurrentPinballGame->startButtonDisabled = 0;
if (gHatchRevealFinalTimings[gCurrentPinballGame->revealFramesetIndex] > gCurrentPinballGame->revealAnimFrameCounter)
{
gCurrentPinballGame->revealAnimFrameCounter++;
}
else
{
gCurrentPinballGame->revealAnimFrameCounter = 0;
gCurrentPinballGame->revealFramesetIndex++;
if (gCurrentPinballGame->revealFramesetIndex > 10)
{
gMain.fieldSpriteGroups[37]->available = 0;
gCurrentPinballGame->revealFramesetIndex = 10;
gCurrentPinballGame->stageTimer = 0;
gCurrentPinballGame->boardSubState++;
DmaCopy16(3, gCurrentPinballGame->pauseObjPalette, (void *)0x05000200, 0x180);
gCurrentPinballGame->activePortraitType = 0;
}
}
index = gCurrentPinballGame->revealFramesetIndex;
group = gMain.fieldSpriteGroups[37];
group->baseX = 96 - gCurrentPinballGame->cameraXOffset;
group->baseY = 300 - gCurrentPinballGame->cameraYOffset;
if (group->baseY >= 200)
group->baseY = 200;
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
dst = (u16*)&gOamBuffer[oamSimple->oamId];
*dst++ = gHatchSequentialOamFramesets[index][i * 3 + 0];
*dst++ = gHatchSequentialOamFramesets[index][i * 3 + 1];
*dst++ = gHatchSequentialOamFramesets[index][i * 3 + 2];
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
}
}
}
void RunTravelEventCutscene(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 *dst;
s16 index;
s16 var0;
index = 0;
if (gCurrentPinballGame->stageTimer == 0)
{
gMain.fieldSpriteGroups[16]->available = 1;
gCurrentPinballGame->travelPainterPosX = 1400;
gCurrentPinballGame->travelPainterPosY = -600;
gCurrentPinballGame->activePortraitType = 21;
if (gMain.selectedField == FIELD_RUBY)
{
DmaCopy16(3, gRubyBoardBonusGfx, (void *)0x06015800, 0x1800);
DmaCopy16(3, gRubyBoardBonusObjPalette, (void *)0x050003C0, 0x20);
DmaCopy16(3, gRubyTravelVolbeat_Gfx, (void *)0x06015800, 0x480);
}
else
{
DmaCopy16(3, gSapphireBoardBonusGfx, (void *)0x06015800, 0x1800);
DmaCopy16(3, gSapphireBoardBonusObjPalette, (void *)0x050003C0, 0x20);
DmaCopy16(3, gSapphireTravelIllumise_Gfx, (void *)0x06015800, 0x480);
}
}
else
{
if (gCurrentPinballGame->stageTimer < 60)
{
u16 angle = (gCurrentPinballGame->stageTimer * 0x4000) / 60;
gCurrentPinballGame->travelPainterPosX = (Cos(angle) * 900) / 20000 + 487;
gCurrentPinballGame->travelPainterPosY = (Sin(angle) * 600) / 20000 - 629;
gCurrentPinballGame->travelPainterVelX = -17;
gCurrentPinballGame->travelPainterVelY = -30;
index = (gCurrentPinballGame->stageTimer % 4) / 2;
if (gCurrentPinballGame->stageTimer % 10 == 0)
m4aSongNumStart(SE_TRAVEL_PAINTER_FLIGHT);
}
else if (gCurrentPinballGame->stageTimer < 90)
{
var0 = gCurrentPinballGame->stageTimer - 60;
if (var0 < 12)
{
index = (var0 % 12) / 2 + 2;
}
else
{
var0 -= 12;
index = (var0 % 18) / 3 + 2;
}
gCurrentPinballGame->travelPainterVelY += 2;
gCurrentPinballGame->travelPainterPosX += gCurrentPinballGame->travelPainterVelX;
gCurrentPinballGame->travelPainterPosY += gCurrentPinballGame->travelPainterVelY;
gCurrentPinballGame->travelAnimKeyframeIndex = 0;
gCurrentPinballGame->travelAnimSubTimer = 0;
}
else if (gCurrentPinballGame->stageTimer < 190)
{
if (gTravelEventAnimData[gCurrentPinballGame->travelAnimKeyframeIndex][2] > gCurrentPinballGame->travelAnimSubTimer)
{
gCurrentPinballGame->travelAnimSubTimer++;
}
else
{
gCurrentPinballGame->travelAnimSubTimer = 0;
gCurrentPinballGame->travelAnimKeyframeIndex++;
if (gCurrentPinballGame->travelAnimKeyframeIndex == 7)
{
gCurrentPinballGame->area = gAreaRouletteTable[gMain.selectedField][gCurrentPinballGame->areaRouletteSlotIndex];
gCurrentPinballGame->rouletteAreaIndex[0] = gAreaToSpeciesTable[gCurrentPinballGame->area];
LoadPortraitGraphics(0, 0);
}
if (gCurrentPinballGame->travelAnimKeyframeIndex == 11)
gCurrentPinballGame->stageTimer = 189;
}
index = gTravelEventAnimData[gCurrentPinballGame->travelAnimKeyframeIndex][1];
if (gTravelEventAnimData[gCurrentPinballGame->travelAnimKeyframeIndex][2] == 5 && gCurrentPinballGame->travelAnimSubTimer == 1)
m4aSongNumStart(SE_TRAVEL_PAINTER_PAINTS);
if (index == 16)
gCurrentPinballGame->travelPainterPosX = -80;
else
gCurrentPinballGame->travelPainterPosX = 0;
gCurrentPinballGame->travelPainterVelX = -24;
gCurrentPinballGame->travelPainterVelY = 14;
}
else if (gCurrentPinballGame->stageTimer < 430)
{
var0 = gCurrentPinballGame->stageTimer - 190;
if (var0 < 24)
{
gCurrentPinballGame->travelPainterPosX = var0 * -14;
index = (var0 % 24) / 4 + 2;
}
else if (var0 < 30)
{
index = 12;
if (var0 == 24)
m4aSongNumStart(MUS_SUCCESS);
}
else if (var0 < 42)
{
var0 -= 30;
index = (var0 % 12) / 6 + 13;
}
else
{
index = 15;
}
}
else if (gCurrentPinballGame->stageTimer < 490)
{
index = (gCurrentPinballGame->stageTimer % 4) / 2;
gCurrentPinballGame->travelPainterVelY--;
gCurrentPinballGame->travelPainterPosX += gCurrentPinballGame->travelPainterVelX;
gCurrentPinballGame->travelPainterPosY += gCurrentPinballGame->travelPainterVelY;
if (gCurrentPinballGame->stageTimer % 10 == 0)
m4aSongNumStart(SE_TRAVEL_PAINTER_FLIGHT);
}
if (gMain.selectedField == FIELD_RUBY)
{
DmaCopy16(3, gRubyTravelVolbeat_Gfx[index], (void *) 0x06015800, 0x480);
}
else
{
DmaCopy16(3, gSapphireTravelIllumise_Gfx[index], (void *) 0x06015800, 0x480);
}
index = gTravelEventAnimData[gCurrentPinballGame->travelAnimKeyframeIndex][0];
group = gMain.fieldSpriteGroups[16];
group->baseX = gCurrentPinballGame->travelPainterPosX / 10 + 96u - gCurrentPinballGame->cameraXOffset;
group->baseY = gCurrentPinballGame->travelPainterPosY / 10 + 300u - gCurrentPinballGame->cameraYOffset;
for( i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
dst =(u16*) &gOamBuffer[oamSimple->oamId];
*dst++ = gTravelEventSpritesheetOam[index][i * 3 + 0];
*dst++ = gTravelEventSpritesheetOam[index][i * 3 + 1];
*dst++ = gTravelEventSpritesheetOam[index][i * 3 + 2];
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
}
if (gCurrentPinballGame->stageTimer == 489)
{
gMain.fieldSpriteGroups[16]->available = 0;
gCurrentPinballGame->activePortraitType = 0;
}
}

View File

@ -737,3 +737,86 @@ static void ResetRecvBuffer(void)
}
}
}
s16 LoadSpriteSetsWithCpuCopy(const struct SpriteSet *const *spriteSets, u16 numSpriteSets, struct SpriteGroup *spriteGroups)
{
struct SpriteGroup *spriteGroup;
struct OamDataSimple *simple;
u16 *oamData;
u16 i;
u16 j;
u16 pos;
u16 numSpritesInGroup;
oamData = (u16 *)gOamBuffer;
pos = 0;
CpuCopy16(gEmptyOamData, oamData, sizeof(gOamBuffer));
for (i = 0; i < numSpriteSets; i++) {
spriteGroup = &spriteGroups[i];
if (!spriteGroup->available) {
continue;
}
numSpritesInGroup = spriteSets[i]->count;
CpuCopy16(spriteSets[i]->oamData, &gOamBuffer[pos], numSpritesInGroup * sizeof(struct OamData));
for (j = 0; j < numSpritesInGroup; j++) {
oamData = (u16 *)&gOamBuffer[pos];
simple = &spriteGroup->oam[j];
simple->oamId = pos++;
simple->xOffset = oamData[1] & 0x1FF;
simple->yOffset = oamData[0] & 0xFF;
}
}
return pos;
}
void nullsub_16(void)
{
}
void ResetSerialIO(void)
{
REG_RCNT = 0;
REG_SIOCNT = 0;
REG_SIOMLT_SEND = 0;
REG_SIOMULTI0 = 0;
REG_SIOMLT_SEND = 0;
REG_SIOMULTI0 = 0;
REG_SIOMULTI0 = 0;
REG_SIOMULTI1 = 0;
REG_SIOMULTI2 = 0;
REG_SIOMULTI3 = 0;
}
void SetupDefaultInterrupts(void)
{
REG_IME = 0;
REG_IE = INTR_FLAG_GAMEPAK | INTR_FLAG_VBLANK;
REG_DISPSTAT = DISPSTAT_VBLANK_INTR;
REG_IME = 1;
}
void ResetLinkState(void)
{
gLinkStatusResult = 0;
gLinkTimeoutCounter = 0;
gLinkConnectionState = 0;
gLinkPlayerCount = 0;
gLinkNegotiationFlags = 0;
}
void ResetSerialAndInterrupts(void)
{
ResetSerialIO();
REG_IME = 0;
ResetMainCallback();
ResetVBlankIntrFunc();
REG_IE = INTR_FLAG_GAMEPAK | INTR_FLAG_VCOUNT | INTR_FLAG_VBLANK;
REG_DISPSTAT = DISPSTAT_VCOUNT_INTR | DISPSTAT_VBLANK_INTR;
REG_IME = 1;
}

View File

@ -4,408 +4,6 @@
#include "constants/bg_music.h"
#include "constants/ruby_states.h"
void AnimateSharpedoCatchSequence(void);
void InitSharpedoCatchMode(void);
void AnimateEggHatchSequence(void);
void InitRubyEvolutionShopMode(void);
void AnimateRubyEvolutionShopSequence(void);
void InitCenterTrapMode(void);
void AnimateCenterTrapSequence(void);
void RequestBoardStateTransition(u8);
void AnimateTotodileEggDelivery(void);
void InitAerodactylEggDelivery(void);
void AnimateAerodactylEggDelivery(void);
void DispatchRubyCatchModeInit(void)
{
if (gMain.modeChangeFlags != MODE_CHANGE_NONE)
return;
switch (gCurrentPinballGame->ballCatchState)
{
case TRAP_CATCH_HOLE:
InitSharpedoCatchMode();
break;
case TRAP_EGG_HOLE:
InitEggHatchMode();
break;
case TRAP_EVO_SHOP_HOLE:
InitRubyEvolutionShopMode();
break;
case TRAP_CENTER_HOLE:
InitCenterTrapMode();
break;
}
gCurrentPinballGame->collisionCooldownTimer = 60;
}
void UpdateRubyCatchModeAnimation(void)
{
if (gCurrentPinballGame->collisionCooldownTimer > 0)
gCurrentPinballGame->collisionCooldownTimer--;
switch (gCurrentPinballGame->ballCatchState)
{
case TRAP_CATCH_HOLE:
AnimateSharpedoCatchSequence(); // Catch hole
break;
case TRAP_EGG_HOLE:
AnimateEggHatchSequence(); //Hatch hole
break;
case TRAP_EVO_SHOP_HOLE:
AnimateRubyEvolutionShopSequence(); //Mart / Evo hole
break;
case TRAP_CENTER_HOLE:
AnimateCenterTrapSequence(); //Center Hole
break;
}
}
void InitSharpedoCatchMode(void)
{
if (gCurrentPinballGame->catchArrowProgress > 1)
{
RequestBoardStateTransition(4);
}
gCurrentPinballGame->cameraScrollOffset = 0;
gCurrentPinballGame->cameraScrollEnabled = 0;
gCurrentPinballGame->cameraScrollTarget = 0;
gCurrentPinballGame->modeAnimTimer = 113;
m4aSongNumStart(SE_UNKNOWN_0xCE);
gCurrentPinballGame->scoreAddedInFrame = 50000;
PlayRumble(8);
}
/*
* Ruby board Sharpedo; during the initation of the catch mode
* Echoes UpdateSapphireWailmerCatchSequence, which is the equivalent 'catch hole' on the sapphire board.
*
* Note: this *does not* affect the start of the catch mode itself.
* When this function is nulled out at UpdateRubyCatchModeAnimation, the banner *doesn't* show, and
* the ball bounces off the sharpedo. However, the grid still shows a picked mon,
* and the mode otherwise works mostly normally, with the exception of affecting
* the 'tilt' behavior, and the collision with the cyndaquil pushback.
*/
void AnimateSharpedoCatchSequence(void)
{
if (gCurrentPinballGame->modeAnimTimer) //Countdown timer; ball grabbed/held while banner shows
{
gCurrentPinballGame->modeAnimTimer--;
if (gCurrentPinballGame->modeAnimTimer > 100)
{
gCurrentPinballGame->ballUpgradeTimerFrozen = 1;
gCurrentPinballGame->ballFrozenState = 1;
gCurrentPinballGame->ball->velocity.x = 0;
gCurrentPinballGame->ball->velocity.y = 0;
gCurrentPinballGame->ball->spinSpeed = 0;
if (gCurrentPinballGame->modeAnimTimer > 108)
{
gCurrentPinballGame->boardEntityActive = 1;
if (gCurrentPinballGame->modeAnimTimer > 110)
{
gCurrentPinballGame->ball->positionQ0.x = 195;
gCurrentPinballGame->ball->positionQ0.y = 222;
}
else
{
gCurrentPinballGame->ball->positionQ0.x = 196;
gCurrentPinballGame->ball->positionQ0.y = 221;
}
//Presumed controling either the message board 'state'/'tile'
// or the sharpedo animation 'state'/tile.
gCurrentPinballGame->catchHoleAnimFrame =6;
}
else if (gCurrentPinballGame->modeAnimTimer > 104)
{
gCurrentPinballGame->ball->positionQ0.x = 197;
gCurrentPinballGame->ball->positionQ0.y = 219;
gCurrentPinballGame->catchHoleAnimFrame = 7;
}
else
{
gCurrentPinballGame->ball->ballHidden = 1;
gCurrentPinballGame->catchHoleAnimFrame = 8;
}
}
else if (gCurrentPinballGame->modeAnimTimer > 20)
{
if (gCurrentPinballGame->modeAnimTimer > 77)
{
gCurrentPinballGame->catchHoleAnimFrame = 9;
if (gCurrentPinballGame->modeAnimTimer < 80)
{
if (gCurrentPinballGame->catchHolePauseTimer != 0)
{
gCurrentPinballGame->catchHolePauseTimer--;
gCurrentPinballGame->modeAnimTimer++;
}
}
}
else if (gCurrentPinballGame->modeAnimTimer > 72)
{
gCurrentPinballGame->catchHoleAnimFrame = 10;
}
else if (gCurrentPinballGame->modeAnimTimer > 67)
{
gCurrentPinballGame->catchHoleAnimFrame = 11;
}
else if (gCurrentPinballGame->modeAnimTimer > 44)
{
gCurrentPinballGame->catchHoleAnimFrame = 12;
}
else if (gCurrentPinballGame->modeAnimTimer > 38)
{
gCurrentPinballGame->catchHoleAnimFrame = 13;
}
else if (gCurrentPinballGame->modeAnimTimer > 28)
{
gCurrentPinballGame->catchHoleAnimFrame = 14;
}
else if (gCurrentPinballGame->modeAnimTimer > 23)
{
gCurrentPinballGame->catchHoleAnimFrame = 15;
}
else {
gCurrentPinballGame->catchHoleAnimFrame = 16;
}
}
else if (gCurrentPinballGame->modeAnimTimer > 18)
{
gCurrentPinballGame->ball->positionQ0.x = 193;
gCurrentPinballGame->ball->positionQ0.y = 226;
gCurrentPinballGame->ball->ballHidden = 0;
gCurrentPinballGame->catchHoleAnimFrame = 17;
}
else if (gCurrentPinballGame->modeAnimTimer > 16)
{
gCurrentPinballGame->ballFrozenState = 0;
gCurrentPinballGame->cameraScrollTarget = 0;
gCurrentPinballGame->cameraScrollEnabled = 1;
gCurrentPinballGame->boardEntityActive = 0;
gCurrentPinballGame->ball->spinSpeed = 0;
gCurrentPinballGame->ball->velocity.x = 0xFF56;
gCurrentPinballGame->ball->velocity.y = 220;
gCurrentPinballGame->ball->positionQ0.x = 190;
gCurrentPinballGame->ball->positionQ0.y = 232;
gCurrentPinballGame->catchHoleAnimFrame = 18;
if (gCurrentPinballGame->modeAnimTimer == 18)
{
m4aSongNumStart(194);
PlayRumble(7);
}
}
else if (gCurrentPinballGame->modeAnimTimer > 12)
{
gCurrentPinballGame->ball->spinSpeed = 0;
gCurrentPinballGame->catchHoleAnimFrame = 19;
}
else if (gCurrentPinballGame->modeAnimTimer > 8)
{
gCurrentPinballGame->ball->spinSpeed = 0;
gCurrentPinballGame->catchHoleAnimFrame = 20;
}
else if (gCurrentPinballGame->modeAnimTimer > 4)
{
gCurrentPinballGame->ball->spinSpeed = 0;
gCurrentPinballGame->catchHoleAnimFrame = 21;
}
else
{
gCurrentPinballGame->catchHoleAnimFrame = 22;
}
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
gCurrentPinballGame->ball->prevPositionQ1 = gCurrentPinballGame->ball->positionQ1;
gCurrentPinballGame->ball->positionQ8.x= gCurrentPinballGame->ball->positionQ0.x << 8;
gCurrentPinballGame->ball->positionQ8.y = gCurrentPinballGame->ball->positionQ0.y << 8;
}
else
{
gCurrentPinballGame->collisionCooldownTimer = 30;
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
gCurrentPinballGame->ballCatchState = NOT_TRAPPED;
gCurrentPinballGame->ballUpgradeTimerFrozen = 0;
gCurrentPinballGame->catchHoleAnimFrame = 0;
}
}
void InitEggHatchMode(void)
{
gCurrentPinballGame->scoreAddedInFrame = 100000;
if (gCurrentPinballGame->eggCaveState == 3)
{
gCurrentPinballGame->eggCaveState = 4;
m4aSongNumStart(SE_UNKNOWN_0xB7);
PlayRumble(7);
gCurrentPinballGame->modeAnimTimer = 500;
}
else if (gCurrentPinballGame->eggDeliveryState !=0)
{
gCurrentPinballGame->modeAnimTimer = 300;
}
else
{
gCurrentPinballGame->modeAnimTimer = 120;
}
gCurrentPinballGame->ballUpgradeTimerFrozen = 1;
}
void AnimateEggHatchSequence(void)
{
u16 modeAnimTimer = gCurrentPinballGame->modeAnimTimer;
if (modeAnimTimer != 0)
{
gCurrentPinballGame->ball->ballHidden = 1;
gCurrentPinballGame->ballFrozenState = 1;
gCurrentPinballGame->modeAnimTimer--;
gCurrentPinballGame->ball->velocity.x = 0;
gCurrentPinballGame->ball->velocity.y = 0;
gCurrentPinballGame->ball->positionQ0.x = 0x58;
gCurrentPinballGame->ball->positionQ0.y = 0x94;
gCurrentPinballGame->ball->spinSpeed = 0;
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
if (gCurrentPinballGame->eggDeliveryState != 1)
return;
if (gCurrentPinballGame->modeAnimTimer > 0xC8)
return;
if (gCurrentPinballGame->modeAnimTimer == 0xC8)
{
if (gCurrentPinballGame->activePortraitType != 0)
gCurrentPinballGame->modeAnimTimer++;
else
{
if (gCurrentPinballGame->scoreHi != 0 && gCurrentPinballGame->rubyPondState == RUBY_POND_STATE_LOTAD)
InitTotodileEggDelivery();
else
InitAerodactylEggDelivery();
}
}
else
{
if (gCurrentPinballGame->scoreHi != 0 && gCurrentPinballGame->rubyPondState == RUBY_POND_STATE_LOTAD)
AnimateTotodileEggDelivery();
else
AnimateAerodactylEggDelivery();
}
if (gCurrentPinballGame->modeAnimTimer <= 9)
gCurrentPinballGame->modeAnimTimer++;
}
else
{
gCurrentPinballGame->ball->ballHidden = 0;
gCurrentPinballGame->ballCatchState = NOT_TRAPPED;
gCurrentPinballGame->ball->positionQ0.x = 0x58;
gCurrentPinballGame->ball->positionQ0.y = 0xA2;
gCurrentPinballGame->ball->spinSpeed = 0;
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
gCurrentPinballGame->ballUpgradeTimerFrozen = 0;
if (gCurrentPinballGame->eggDeliveryState == 2)
{
gCurrentPinballGame->eggCaveState = 3;
gCurrentPinballGame->eggCaveLiftTimer = 0x30;
gCurrentPinballGame->eggCaveExitDelayTimer = 0x1E;
}
else
{
gCurrentPinballGame->ballFrozenState = 0;
gCurrentPinballGame->collisionCooldownTimer = 0x3C;
gCurrentPinballGame->ball->velocity.x = 0x14;
gCurrentPinballGame->ball->velocity.y = 0xC8;
}
}
}
void InitRubyEvolutionShopMode(void)
{
gCurrentPinballGame->shopAnimSlideTimer = 0;
gCurrentPinballGame->shopUISlideOffset = 0;
gCurrentPinballGame->modeAnimTimer = 0xB4;
gCurrentPinballGame->shopEntryTimer = 0xB4;
gCurrentPinballGame->scoreAddedInFrame = 500000;
gMain.blendControl = 0xCE;
gMain.blendBrightness = 0;
gCurrentPinballGame->ballUpgradeTimerFrozen = 1;
}
void AnimateRubyEvolutionShopSequence(void)
{
if (gCurrentPinballGame->modeAnimTimer > 0x18)
{
gCurrentPinballGame->ball->ballHidden = 1;
gCurrentPinballGame->ballFrozenState = 1;
gCurrentPinballGame->modeAnimTimer--;
gCurrentPinballGame->ball->velocity.x = 0;
gCurrentPinballGame->ball->velocity.y = 0;
gCurrentPinballGame->ball->positionQ0.x = 0xDC;
gCurrentPinballGame->ball->positionQ0.y = 0x62;
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
gCurrentPinballGame->ball->positionQ8.x = gCurrentPinballGame->ball->positionQ0.x * 256;
gCurrentPinballGame->ball->positionQ8.y = gCurrentPinballGame->ball->positionQ0.y * 256;
if (gCurrentPinballGame->modeAnimTimer > 0x9B)
gCurrentPinballGame->shopDoorTargetFrame = (gCurrentPinballGame->modeAnimTimer - 0x9C) / 8;
if (gCurrentPinballGame->modeAnimTimer <= 0x31)
gCurrentPinballGame->modeAnimTimer++;
UpdateShopEntryAnimation(gCurrentPinballGame->evolutionShopActive);
return;
}
if (gCurrentPinballGame->modeAnimTimer > 0)
{
gCurrentPinballGame->modeAnimTimer--;
gCurrentPinballGame->shopDoorTargetFrame = (0x18 - gCurrentPinballGame->modeAnimTimer) / 8;
return;
}
gCurrentPinballGame->ball->ballHidden = 0;
gCurrentPinballGame->ballFrozenState = 0;
gCurrentPinballGame->collisionCooldownTimer = 0x3C;
gCurrentPinballGame->ball->velocity.x = 0x60;
gCurrentPinballGame->ball->velocity.y = 0xC0;
gCurrentPinballGame->ball->positionQ0.x = 0xDF;
gCurrentPinballGame->ball->positionQ0.y = 0x63;
gCurrentPinballGame->ball->spinSpeed = 0;
gCurrentPinballGame->ballUpgradeTimerFrozen = 0;
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
gCurrentPinballGame->ballCatchState = NOT_TRAPPED;
gCurrentPinballGame->shopDoorTargetFrame = 0x13;
m4aSongNumStart(SE_UNKNOWN_0xC3);
if (gCurrentPinballGame->evoArrowProgress > 2 && gCurrentPinballGame->evolvablePartySize > 0)
{
RequestBoardStateTransition(6);
}
}
void UpdateShopEntryAnimation(s16 arg0)
{
int var_r7 = 0;

329
src/main_portrait_display.c Normal file
View File

@ -0,0 +1,329 @@
#include "global.h"
#include "main.h"
extern const u16 gPortraitGenericPalettes[];
extern const u16 gPortraitPaletteSlots[2];
extern const u16 gPortraitIdleCycleData[];
extern const u16 gPortraitAnimPalettes[];
extern const s16 gRouletteOutcomeFrameOffsets[];
/*
File is used for the center screen display on the main board.
Can contain travel location picture, catch mon, roulette wheel
*/
void LoadPortraitGraphics(s16 arg0, s16 arg1)
{
s16 i;
s16 var0;
s16 sp0[16];
s16 rgb[3];
u16 index;
const u16 *ptr;
const u16 *ptr2;
u16 index2;
switch (arg0)
{
case 0:
gCurrentPinballGame->creatureOamPriority = 3;
gCurrentPinballGame->portraitGfxIndex[arg1] = gCurrentPinballGame->rouletteAreaIndex[arg1];
DmaCopy16(3, gPortraitGenericGraphics[gCurrentPinballGame->portraitGfxIndex[arg1]], (void *)0x06010CA0 + arg1 * 0x300, 0x300);
index = gCurrentPinballGame->rouletteAreaIndex[arg1] * 0x10;
DmaCopy16(3, &gPortraitGenericPalettes[index], (void *)0x05000200 + gPortraitPaletteSlots[arg1] * 0x20, 0x20);
break;
case 1:
ptr = gPortraitIdleCycleData;
gCurrentPinballGame->portraitGfxIndex[arg1] = ptr[(gCurrentPinballGame->portraitCycleFrame % 48) / 24];
index = ptr[2] * 0x10;
DmaCopy16(3, gPortraitAnimFrameGraphics[gCurrentPinballGame->portraitGfxIndex[arg1]], (void *)0x06010CA0 + arg1 * 0x300, 0x300);
DmaCopy16(3, &gPortraitAnimPalettes[index], (void *)0x05000200 + gPortraitPaletteSlots[arg1] * 0x20, 0x20);
break;
case 2:
ptr = gShopItemData[gCurrentPinballGame->modeOutcomeValues[arg1]];
gCurrentPinballGame->portraitGfxIndex[arg1] = ptr[0];
index = ptr[2] * 0x10;
DmaCopy16(3, gPortraitAnimFrameGraphics[gCurrentPinballGame->portraitGfxIndex[arg1]], (void *)0x06010CA0 + arg1 * 0x300, 0x300);
DmaCopy16(3, &gPortraitAnimPalettes[index], (void *)0x05000200 + gPortraitPaletteSlots[arg1] * 0x20, 0x20);
break;
case 3:
gCurrentPinballGame->portraitGfxIndex[arg1] = gCurrentPinballGame->currentSpecies;
DmaCopy16(
3,
gMonPortraitGroupGfx[gCurrentPinballGame->portraitGfxIndex[arg1] / 15] + (gCurrentPinballGame->portraitGfxIndex[arg1] % 15) * 0x300,
(void *)0x06010CA0 + arg1 * 24,
0x300);
DmaCopy16(
3,
gMonPortraitGroupPals[gCurrentPinballGame->portraitGfxIndex[arg1] / 15] + (gCurrentPinballGame->portraitGfxIndex[arg1] % 15) * 0x20,
(void *)0x050003A0 ,
0x20);
DmaCopy16(3, gMonPortraitGroupPals[0] + 15 * 0x20, (void *)0x050003E0, 0x20);
break;
case 9:
if (gCurrentPinballGame->evoChainPosition > 0)
{
if (gMain_saveData.pokedexFlags[gCurrentPinballGame->evoTargetSpecies] == SPECIES_UNSEEN)
{
gCurrentPinballGame->portraitGfxIndex[arg1] = SPECIES_NONE;
DmaCopy16(
3,
gMonPortraitGroupPals[gCurrentPinballGame->portraitGfxIndex[arg1] / 15] + (gCurrentPinballGame->portraitGfxIndex[arg1] % 15) * 0x20,
(void *)0x050003A0,
0x20);
}
else if (gMain_saveData.pokedexFlags[gCurrentPinballGame->evoTargetSpecies] < SPECIES_CAUGHT)
{
gCurrentPinballGame->portraitGfxIndex[arg1] = gCurrentPinballGame->evoTargetSpecies;
DmaCopy16(3, gMonPortraitGroupPals[0] + 15 * 0x20, (void *)0x050003A0, 0x20);
}
else
{
gCurrentPinballGame->portraitGfxIndex[arg1] = gCurrentPinballGame->evoTargetSpecies;
DmaCopy16(
3,
gMonPortraitGroupPals[gCurrentPinballGame->portraitGfxIndex[arg1] / 15] + (gCurrentPinballGame->portraitGfxIndex[arg1] % 15) * 0x20,
(void *)0x050003A0,
0x20);
}
}
else
{
gCurrentPinballGame->portraitGfxIndex[arg1] = gCurrentPinballGame->currentSpecies;
DmaCopy16(
3,
gMonPortraitGroupPals[gCurrentPinballGame->portraitGfxIndex[arg1] / 15] + (gCurrentPinballGame->portraitGfxIndex[arg1] % 15) * 0x20,
(void *)0x050003A0,
0x20);
}
DmaCopy16(
3,
gMonPortraitGroupGfx[gCurrentPinballGame->portraitGfxIndex[arg1] / 15] + (gCurrentPinballGame->portraitGfxIndex[arg1] % 15) * 0x300,
(void *)0x06010CA0 + arg1 * 0x18,
0x300);
break;
case 4:
if (gCurrentPinballGame->boardSubState == 2)
{
gCurrentPinballGame->portraitGfxIndex[arg1] = gShopItemData[15][(gCurrentPinballGame->portraitCycleFrame % 48) / 24];
DmaCopy16(3, gPortraitAnimFrameGraphics[gCurrentPinballGame->portraitGfxIndex[arg1]], (void *)0x06010CA0 + arg1 * 0x300, 0x300);
// !!!!! BUG: this should be multiplied by 16 !!
index = gShopItemData[15][2];
}
else
{
gCurrentPinballGame->portraitGfxIndex[arg1] = gShopItemData[16][(gCurrentPinballGame->portraitCycleFrame % 48) / 24];
DmaCopy16(3, gPortraitAnimFrameGraphics[gCurrentPinballGame->portraitGfxIndex[arg1]], (void *)0x06010CA0 + arg1 * 0x300, 0x300);
index = gShopItemData[16][2] * 16;
}
DmaCopy16(3, &gPortraitAnimPalettes[index], (void *)0x05000200 + gPortraitPaletteSlots[arg1] * 0x20, 0x20);
break;
case 6:
ptr = gShopItemData[gCurrentPinballGame->shopSelectedItemId];
gCurrentPinballGame->portraitGfxIndex[arg1] = ptr[0];
index = ptr[2] * 16;
DmaCopy16(3, gPortraitAnimFrameGraphics[gCurrentPinballGame->portraitGfxIndex[arg1]], (void *)0x06010CA0 + arg1 * 0x300, 0x300);
if (gCurrentPinballGame->coins < ptr[3] ||
(
(gShopCursorToItemMap[gCurrentPinballGame->shopItemCursor] == 3 && gCurrentPinballGame->outLanePikaPosition == 2)
||
(gShopCursorToItemMap[gCurrentPinballGame->shopItemCursor] == 4 && gCurrentPinballGame->shopBonusStageAlreadyBought)
))
{
DmaCopy16(3, &gPortraitAnimPalettes[index], sp0, 0x20);
for (i = 0; i < 16; i++)
{
rgb[0] = ((sp0[i] & 0x1F) * 2) / 3;
rgb[1] = ((sp0[i] & 0x3E0) >> 4) / 3;
rgb[2] = ((sp0[i] & 0x7C00) >> 9) / 3;
sp0[i] = rgb[0] | (rgb[1] << 5) | (rgb[2] << 10);
}
DmaCopy16(3, sp0, (void *)0x05000200 + gPortraitPaletteSlots[arg1] * 0x20, 0x20);
}
else
{
DmaCopy16(3, &gPortraitAnimPalettes[index], (void *)0x05000200 + gPortraitPaletteSlots[arg1] * 0x20, 0x20);
}
break;
case 7:
// TODO: fake match
ptr2 = ptr = gShopItemData[gCurrentPinballGame->modeOutcomeValues[arg1]];
gCurrentPinballGame->portraitGfxIndex[arg1] = *(ptr2 += (gCurrentPinballGame->portraitCycleFrame % 48) / 24);
index = ptr[2] * 16;
DmaCopy16(3, gPortraitAnimFrameGraphics[gCurrentPinballGame->portraitGfxIndex[arg1]], (void *)0x06010CA0 + arg1 * 0x300, 0x300);
DmaCopy16(3, &gPortraitAnimPalettes[index], (void *)0x05000200 + gPortraitPaletteSlots[arg1] * 0x20, 0x20);
break;
case 8:
// TODO: fake match
ptr2 = ptr = gShopItemData[gCurrentPinballGame->rouletteOutcomeId];
gCurrentPinballGame->portraitGfxIndex[arg1] = *(ptr2 += gRouletteOutcomeFrameOffsets[gCurrentPinballGame->outcomeFrameCounter / 12]);
index = ptr[2] * 16;
DmaCopy16(3, gPortraitAnimFrameGraphics[gCurrentPinballGame->portraitGfxIndex[arg1]], (void *)0x06010CA0 + arg1 * 0x300, 0x300);
DmaCopy16(3, &gPortraitAnimPalettes[index], (void *)0x05000200 + gPortraitPaletteSlots[arg1] * 0x20, 0x20);
break;
}
gCurrentPinballGame->portraitRenderMode[arg1] = arg0;
gCurrentPinballGame->portraitCycleFrame++;
}
void UpdatePortraitSpritePositions(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 baseX;
s16 var1;
s16 var2;
if (gCurrentPinballGame->portraitDisplayState == 3)
{
baseX = 0;
var1 = 180;
var2 = 180;
}
else if (gCurrentPinballGame->portraitDisplayState == 2)
{
if (gMain.shopPanelSlideOffset < 20)
{
var1 = 180;
var2 = 180;
}
else
{
var1 = 88 + gCurrentPinballGame->rouletteSubOffset;
var2 = 88;
}
baseX = 48;
}
else
{
baseX = 96 - gCurrentPinballGame->cameraXOffset;
var1 = gCurrentPinballGame->rouletteSubOffset + 300u - gCurrentPinballGame->cameraYOffset;
var2 = 300 - gCurrentPinballGame->cameraYOffset;
}
group = gMain.fieldSpriteGroups[22];
group->baseX = baseX;
group->baseY = var1;
gCurrentPinballGame->rouletteBasePos.x = baseX;
gCurrentPinballGame->rouletteBasePos.y = group->baseY;
if (group->baseY >= 200)
group->baseY = 200;
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].paletteNum = gCurrentPinballGame->hatchTilePalette[i];
gOamBuffer[oamSimple->oamId].priority = gCurrentPinballGame->creatureOamPriority;
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
if (gCurrentPinballGame->portraitDisplayState == 1)
{
group = gMain.fieldSpriteGroups[23];
group->baseX = baseX;
group->baseY = var1 - 0x20;
if (group->baseY >= 180)
group->baseY = 180;
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].paletteNum = 12;
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
group = gMain.fieldSpriteGroups[20];
group->baseX = baseX;
group->baseY = 267 - gCurrentPinballGame->cameraYOffset;
if (group->baseY >= 200)
group->baseY = 200;
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
group = gMain.fieldSpriteGroups[21];
group->baseX = baseX;
group->baseY = 333 - gCurrentPinballGame->cameraYOffset;
if (group->baseY >= 200)
group->baseY = 200;
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
group = gMain.fieldSpriteGroups[19];
group->baseX = baseX - 8;
group->baseY = var2 - 8;
if (group->baseY >= 200)
group->baseY = 200;
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].priority = gCurrentPinballGame->creatureOamPriority;
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
void ClampPortraitSpritesToOffscreen(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
if (gCurrentPinballGame->portraitDisplayState == 1)
{
group = gMain.fieldSpriteGroups[22];
group->baseY = 180;
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
group = gMain.fieldSpriteGroups[23];
group->baseY = 300 - gCurrentPinballGame->cameraYOffset;
if (group->baseY >= 180)
group->baseY = 180;
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
group = gMain.fieldSpriteGroups[20];
group->baseY = 180;
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
group = gMain.fieldSpriteGroups[21];
group->baseY = 180;
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
}

421
src/pichu_entity.c Normal file
View File

@ -0,0 +1,421 @@
#include "global.h"
#include "m4a.h"
#include "main.h"
#include "constants/bg_music.h"
extern struct SongHeader se_pika_no_kickback;
extern struct SongHeader se_pichu_kickback;
extern struct SongHeader se_pikachu_kickback;
extern s16 gPikaSaverAnimFrameTable[100];
extern s16 gOutlaneCenterXPositions[3];
extern u16 gCatchOverlayAnimData[][2];
extern s16 gCatchOverlayOamData[28][12];
extern const struct Vector32 gPikaSaverWaypoints[];
extern const u16 gAngleToDirectionTable[];
extern const u8 gPikachuSaverTilesGfx[];
void UpdateKickbackLogic(void)
{
s16 outlaneChuteIx;
s16 j;
s16 r5;
s16 oamIx;
s16 tempY;
struct SpriteGroup *spriteGroup;
struct OamDataSimple *oamSimple;
u16 *dst;
const u16 *src;
PichuArrivalSequence();
if (gCurrentPinballGame->pikaChargeTarget > 167)
{
gCurrentPinballGame->pikaSaverTileIndex[0] = gPikaSaverAnimFrameTable[(gMain.fieldFrameCount % 160) / 5];
if (gCurrentPinballGame->outLanePikaPosition == 2)
gCurrentPinballGame->pikaSaverTileIndex[1] = gCurrentPinballGame->pikaSaverTileIndex[0] + 6;
else
gCurrentPinballGame->pikaSaverTileIndex[1] = gCurrentPinballGame->pikaSaverTileIndex[0];
}
else
{
gCurrentPinballGame->pikaSaverTileIndex[0] = (gMain.fieldFrameCount % 50) / 25;
if (gCurrentPinballGame->outLanePikaPosition == 2)
gCurrentPinballGame->pikaSaverTileIndex[1] = gCurrentPinballGame->pikaSaverTileIndex[0] + 9;
else
gCurrentPinballGame->pikaSaverTileIndex[1] = gCurrentPinballGame->pikaSaverTileIndex[0];
}
if (gCurrentPinballGame->outLanePikaPosition == 2)
{
gCurrentPinballGame->kickbackOccupied[0] = 1;
gCurrentPinballGame->kickbackOccupied[1] = 1;
}
else
{
gCurrentPinballGame->kickbackOccupied[0 + gCurrentPinballGame->outLanePikaPosition] = 1;
gCurrentPinballGame->kickbackOccupied[1 - gCurrentPinballGame->outLanePikaPosition] = 0;
}
if (gCurrentPinballGame->pikaKickbackTimer != 0)
{
if (gCurrentPinballGame->pikaKickbackTimer == 120)
{
// gCurrentPinballGame->outLaneSide + gCurrentPinballGame->outLanePikaPosition
// Note: this can be && chained off of the previous if, once we have this line deciphered.
if (gCurrentPinballGame->kickbackOccupied[gCurrentPinballGame->outLaneSide - 1] != 0)
{
if (gCurrentPinballGame->pikaChargeTarget > 167)
{
gCurrentPinballGame->ballFrozenState = 1;
gCurrentPinballGame->kickbackFiring = 1;
gCurrentPinballGame->kickbackAnimProgress = 120;
gCurrentPinballGame->kickbackAnimDuration = 120;
gCurrentPinballGame->kickbackLaunchTimer = gCurrentPinballGame->kickbackAnimProgress;
gCurrentPinballGame->ballUpgradeTimerFrozen = 1;
gCurrentPinballGame->kickbackAnimFrameTimer = 0;
gCurrentPinballGame->kickbackFrameId = 0;
if (gCurrentPinballGame->outLanePikaPosition != 2)
{
gCurrentPinballGame->pikaChargeTarget = 0;
gCurrentPinballGame->pikaChargeProgress = 0;
gCurrentPinballGame->prevChargeFillValue = 0;
gCurrentPinballGame->chargeFillValue = 0;
gCurrentPinballGame->chargeIndicatorXOffset = 0;
gCurrentPinballGame->chargeIndicatorYOffset = -4;
gCurrentPinballGame->chargeIndicatorScaleX = 256;
gCurrentPinballGame->chargeIndicatorScaleY = 256;
gCurrentPinballGame->chargeFillAnimTimer = 0;
gCurrentPinballGame->fullChargeSlideAnimTimer = 0;
}
gCurrentPinballGame->kickbackBallHoverPos = gCurrentPinballGame->ball->positionQ1;
gCurrentPinballGame->scoreAddedInFrame = 30000;
if (gCurrentPinballGame->bonusPikaSaverCount <= 98)
gCurrentPinballGame->bonusPikaSaverCount++;
}
else
{
gCurrentPinballGame->pikaKickbackTimer = 60;
MPlayStart(&gMPlayInfo_SE1, &se_pika_no_kickback);
}
outlaneChuteIx = gCurrentPinballGame->outLaneSide - 1;
if (gCurrentPinballGame->outLanePikaPosition == 2)
gCurrentPinballGame->pikaSaverTileIndex[outlaneChuteIx] = (outlaneChuteIx) * 7 + 2;
else
gCurrentPinballGame->pikaSaverTileIndex[outlaneChuteIx] = 2;
DmaCopy16(3, gPikaSaverTilesGfx + (gCurrentPinballGame->pikaSaverTileIndex[outlaneChuteIx] * 0x180), 0x06010480 + ((outlaneChuteIx) * 0x180), 0x180);
}
}
if (gCurrentPinballGame->outLanePikaPosition == 2)
gCurrentPinballGame->pikaSaverTileIndex[gCurrentPinballGame->outLaneSide - 1] = (gCurrentPinballGame->outLaneSide - 1) * 7 + 2;
else
gCurrentPinballGame->pikaSaverTileIndex[gCurrentPinballGame->outLaneSide - 1] = 2;
gCurrentPinballGame->pikaKickbackTimer--;
}
if (gCurrentPinballGame->kickbackFiring != 0)
{
if (gCurrentPinballGame->kickbackLaunchTimer > 1)
{
r5 = (gCurrentPinballGame->kickbackAnimProgress * 0x10000) / 10;
gCurrentPinballGame->kickbackLaunchTimer--;
if (gCurrentPinballGame->kickbackAnimProgress != 0)
{
gCurrentPinballGame->kickbackAnimProgress--;
if (gCurrentPinballGame->kickbackAnimProgress == 40 && gCurrentPinballGame->kickbackLaunchTimer > 40)
{
gCurrentPinballGame->kickbackAnimProgress = 60;
}
}
if (gCurrentPinballGame->kickbackLaunchTimer == 116)
{
if (gCurrentPinballGame->activePortraitType)
gCurrentPinballGame->kickbackLaunchTimer = 120;
else
{
gCurrentPinballGame->activePortraitType = 1;
if (gCurrentPinballGame->outLanePikaPosition == 2)
{
if (gCurrentPinballGame->outLaneSide == 1)
MPlayStart(&gMPlayInfo_SE1, &se_pikachu_kickback);
else
MPlayStart(&gMPlayInfo_SE1, &se_pichu_kickback);
m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 0x40);
}
else
{
MPlayStart(&gMPlayInfo_SE1, &se_pikachu_kickback);
m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 0x40);
}
}
}
if (gCurrentPinballGame->kickbackLaunchTimer == 115 && gCurrentPinballGame->activePortraitType == 1)
m4aMPlayVolumeControl(&gMPlayInfo_SE1, 0xFFFF, 0x200);
// used for the horizontal 'floaty' movement when electric builds pre-launch.
gCurrentPinballGame->ball->positionQ1.x =
gCurrentPinballGame->kickbackBallHoverPos.x + ((Sin(r5) * 6) / 20000) +
((gOutlaneCenterXPositions[gCurrentPinballGame->outLaneSide - 1] * 2 - gCurrentPinballGame->kickbackBallHoverPos.x) * (gCurrentPinballGame->kickbackAnimDuration - gCurrentPinballGame->kickbackAnimProgress)) / gCurrentPinballGame->kickbackAnimDuration;
tempY = ((gCurrentPinballGame->kickbackAnimDuration - gCurrentPinballGame->kickbackAnimProgress) * 40) / gCurrentPinballGame->kickbackAnimDuration;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->kickbackBallHoverPos.y - tempY;
gCurrentPinballGame->ball->positionQ8.x = gCurrentPinballGame->ball->positionQ1.x * 128;
gCurrentPinballGame->ball->positionQ8.y = gCurrentPinballGame->ball->positionQ1.y * 128;
}
else if (gCurrentPinballGame->kickbackLaunchTimer == 1)
{
gCurrentPinballGame->ball->positionQ1.x = gOutlaneCenterXPositions[gCurrentPinballGame->outLaneSide - 1] * 2;
gCurrentPinballGame->ball->positionQ1.y = 702;
gCurrentPinballGame->ball->positionQ8.x = gCurrentPinballGame->ball->positionQ1.x * 128;
gCurrentPinballGame->ball->positionQ8.y = gCurrentPinballGame->ball->positionQ1.y * 128;
gCurrentPinballGame->ball->velocity.x = 0;
// fly me to the moon
gCurrentPinballGame->ball->velocity.y = -300;
m4aSongNumStart(SE_KICKBACK_THUNDERWAVE);
gCurrentPinballGame->kickbackLaunchTimer = 0;
gCurrentPinballGame->ballFrozenState = 0;
gCurrentPinballGame->ballUpgradeTimerFrozen = 0;
gCurrentPinballGame->holeIndicators[(gCurrentPinballGame->outLaneSide - 1) * 3] = 1;
if (gCurrentPinballGame->allHolesLit == 0 &&
(gCurrentPinballGame->holeIndicators[0] &
gCurrentPinballGame->holeIndicators[1] &
gCurrentPinballGame->holeIndicators[2] &
gCurrentPinballGame->holeIndicators[3]))
{
gCurrentPinballGame->allHolesLit = 1;
gCurrentPinballGame->allHolesLitBlinkTimer = 126;
gCurrentPinballGame->scoreAddedInFrame = 4000;
}
PlayRumble(11);
}
if (gCurrentPinballGame->kickbackLaunchTimer >= 100)
{
if (gCurrentPinballGame->outLanePikaPosition == 2)
gCurrentPinballGame->pikaSaverTileIndex[gCurrentPinballGame->outLaneSide - 1] = (gCurrentPinballGame->outLaneSide - 1) * 7 + 2;
else
gCurrentPinballGame->pikaSaverTileIndex[gCurrentPinballGame->outLaneSide - 1] = 2;
if (gCurrentPinballGame->kickbackLaunchTimer == 100)
{
gMain.fieldSpriteGroups[38]->available = 1;
if (gCurrentPinballGame->outLanePikaPosition == 2 && gCurrentPinballGame->outLaneSide == 2)
{
DmaCopy16(3, gPikaSaverFullCoverageGfx, 0x06015800, 0x2400);
}
else
{
DmaCopy16(3, gPikaSaverPartialCoverageGfx, 0x06015800, 0x2400);
}
}
}
else
{
if (gCatchOverlayAnimData[gCurrentPinballGame->kickbackFrameId][1] > gCurrentPinballGame->kickbackAnimFrameTimer)
gCurrentPinballGame->kickbackAnimFrameTimer++;
else
{
gCurrentPinballGame->kickbackAnimFrameTimer = 0;
gCurrentPinballGame->kickbackFrameId++;
if (gCurrentPinballGame->kickbackFrameId == 23)
{
m4aSongNumStop(SE_KICKBACK_THUNDERWAVE);
m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 0x100);
}
if (gCurrentPinballGame->kickbackFrameId > 25)
{
gCurrentPinballGame->kickbackFrameId = 25;
gCurrentPinballGame->kickbackFiring = 0;
gMain.fieldSpriteGroups[38]->available = 0;
gCurrentPinballGame->activePortraitType = 0;
outlaneChuteIx = gCurrentPinballGame->outLaneSide - 1;
if (gCurrentPinballGame->outLanePikaPosition == 2)
gCurrentPinballGame->pikaSaverTileIndex[outlaneChuteIx] = outlaneChuteIx * 9;
else
gCurrentPinballGame->pikaSaverTileIndex[outlaneChuteIx] = 0;
DmaCopy16(3, gPikaSaverTilesGfx + (gCurrentPinballGame->pikaSaverTileIndex[outlaneChuteIx] * 0x180), 0x06010480 + (outlaneChuteIx * 0x180), 0x180);
}
}
if (gCurrentPinballGame->kickbackFrameId >= 17 && gCurrentPinballGame->kickbackFrameId <= 23)
{
if ((gMain.systemFrameCount & 3) >> 1)
gCurrentPinballGame->cameraBaseX = -3;
else
gCurrentPinballGame->cameraBaseX = 3;
}
oamIx = gCatchOverlayAnimData[gCurrentPinballGame->kickbackFrameId][0];
outlaneChuteIx = gCurrentPinballGame->outLaneSide - 1;
spriteGroup = gMain.fieldSpriteGroups[38];
spriteGroup->baseX = (outlaneChuteIx * 177) - (gCurrentPinballGame->cameraXOffset - 16);
if (gCurrentPinballGame->kickbackFiring)
{
spriteGroup->baseY = 380 - gCurrentPinballGame->cameraYOffset;
gCurrentPinballGame->kickbackOccupied[outlaneChuteIx] = 0;
}
else
{
spriteGroup->baseY = 180;
gCurrentPinballGame->kickbackOccupied[outlaneChuteIx] = 1;
}
for (j = 0; j < 4; j++)
{
oamSimple = &spriteGroup->oam[j];
dst = (u16 *)&gOamBuffer[oamSimple->oamId];
*dst++ = gCatchOverlayOamData[oamIx][j * 3 + 0];
*dst++ = gCatchOverlayOamData[oamIx][j * 3 + 1];
*dst++ = gCatchOverlayOamData[oamIx][j * 3 + 2];
gOamBuffer[oamSimple->oamId].x += spriteGroup->baseX;
gOamBuffer[oamSimple->oamId].y += spriteGroup->baseY;
}
}
}
spriteGroup = gMain.fieldSpriteGroups[29];
if (spriteGroup->available)
{
for (outlaneChuteIx = 0; outlaneChuteIx <= 1; outlaneChuteIx++)
{
spriteGroup = gMain.fieldSpriteGroups[29 + outlaneChuteIx];
spriteGroup->baseX = (outlaneChuteIx * 177) - (gCurrentPinballGame->cameraXOffset - 16);
if (gCurrentPinballGame->kickbackOccupied[outlaneChuteIx])
{
if ((gMain.fieldFrameCount % 5) == 0)
{
DmaCopy16(3, gPikaSaverTilesGfx + (gCurrentPinballGame->pikaSaverTileIndex[outlaneChuteIx] * 0x180), 0x06010480 + (outlaneChuteIx * 0x180), 0x180);
}
tempY = 380 - gCurrentPinballGame->cameraYOffset;
spriteGroup->baseY = tempY;
}
else
spriteGroup->baseY = 200;
for (j = 0; j <= 1; j++)
{
oamSimple = &spriteGroup->oam[j];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + spriteGroup->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + spriteGroup->baseY;
}
}
}
}
void PichuArrivalSequence(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
struct Vector32 tempVec;
struct Vector32 tempVec2;
u16 angle;
int xx, yy;
int squaredMagnitude;
s16 index;
group = gMain.fieldSpriteGroups[41];
if (gCurrentPinballGame->pichuEntranceTimer == 0)
return;
if (gCurrentPinballGame->pichuEntranceTimer == 800)
{
group->available = 1;
if (gCurrentPinballGame->pichuWalkMode == 1)
{
//Start entrance
gCurrentPinballGame->walkMonXPos = 1090;
gCurrentPinballGame->walkMonYPos = 4680;
gCurrentPinballGame->creatureWaypointIndex = 0;
}
else
{
//Start exit
gCurrentPinballGame->walkMonXPos = 2000;
gCurrentPinballGame->walkMonYPos = 3820;
gCurrentPinballGame->creatureWaypointIndex = 4;
}
}
else
{
if (gCurrentPinballGame->pichuEntranceTimer == 799)
{
if (gCurrentPinballGame->pichuWalkMode != 1)
{
DmaCopy16(3, gPikaSaverTilesGfx, (void *)0x06010600, 0x180);
}
}
tempVec.x = gPikaSaverWaypoints[gCurrentPinballGame->creatureWaypointIndex].x - 120 - gCurrentPinballGame->walkMonXPos;
tempVec.y = gPikaSaverWaypoints[gCurrentPinballGame->creatureWaypointIndex].y - 160 - gCurrentPinballGame->walkMonYPos;
xx = tempVec.x * tempVec.x;
yy = tempVec.y * tempVec.y;
squaredMagnitude = xx + yy;
angle = ArcTan2(tempVec.x, -tempVec.y);
tempVec2.x = (Cos(angle) * 7) / 20000;
tempVec2.y = (Sin(angle) * -7) / 20000;
index = gAngleToDirectionTable[angle / 0x2000] + (gMain.systemFrameCount % 24) / 8;
gCurrentPinballGame->walkMonXPos += tempVec2.x;
gCurrentPinballGame->walkMonYPos += tempVec2.y;
if (group->available)
{
group->baseX = gCurrentPinballGame->walkMonXPos / 10 - gCurrentPinballGame->cameraXOffset;
group->baseY = gCurrentPinballGame->walkMonYPos / 10 - gCurrentPinballGame->cameraYOffset;
if (group->baseY > 180)
group->baseY = 180;
else if (group->baseY < -30)
group->baseY = -30;
DmaCopy16(3, gMonHatchSpriteGroup5_Gfx + (index + 30) * 0x120 , (void *)0x060112A0, 0x120);
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].priority = 1;
gOamBuffer[oamSimple->oamId].paletteNum = 3;
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
if (squaredMagnitude < 2500)
{
gCurrentPinballGame->creatureWaypointIndex++;
if (gCurrentPinballGame->pichuWalkMode == 1)
{
if (gCurrentPinballGame->creatureWaypointIndex == 4)
{
DmaCopy16(3, gPikachuSaverTilesGfx, (void *)0x06010600, 0x180);
gCurrentPinballGame->outLanePikaPosition = 2;
gMain.fieldSpriteGroups[41]->available = 0;
gCurrentPinballGame->pichuEntranceTimer = 1;
m4aSongNumStart(SE_PICHU_IN_POSITION_CHIRP);
}
}
else if (gCurrentPinballGame->creatureWaypointIndex == 7)
{
gMain.fieldSpriteGroups[41]->available = 0;
gCurrentPinballGame->pichuEntranceTimer = 1;
}
}
}
gCurrentPinballGame->pichuEntranceTimer--;
}

View File

@ -1,5 +1,4 @@
#include "global.h"
#include "agb_sram.h"
#include "main.h"
#include "m4a.h"
#include "constants/ereader.h"
@ -17,61 +16,18 @@ struct BoardProcessPair
};
extern struct BoardProcessPair CurrentBoardProcPairs_020028D8[9];
extern u8 gBoardGfxBuffer[];
extern u8 gBoardBGTileBufferAlt[];
extern const struct BoardProcessPair BoardProcPairs_086B077C[];
extern const VoidFunc gFieldInitFuncs[];
extern struct SpriteGroup *gMainFieldSpriteGroups[][60];
extern struct SpriteGroup *gBonusFieldSpriteGroups[][30];
extern const u8 gBoardActionTilesGfx[];
extern const u8 gEggModeTilesGfx[];
extern const u8 gCaptureModeTilesGfx[];
extern const u8 gCaptureScreenTilesGfx[];
extern const u8 gRubyBoardBonusGfx[];
extern const u8 gRubyBoardBonusObjPalette[];
extern const u8 gSapphireBoardBonusGfx[];
extern const u8 gSapphireBoardBonusObjPalette[];
extern const u8 gSapphireCatchTilesGfx[];
extern const u8 gHatchRevealTilesGfx[];
extern const u8 gHatchStartTilesGfx[];
extern const u8 gHatchStage2TilesGfx[];
extern const u8 gHatchStage3TilesGfx[];
extern const u8 gHatchFinalTilesGfx[];
extern const u8 gAlphabetTilesGfx[][0x40];
extern const u8 gSpaceTileGfx[0x40];
extern const u8 gDecimalDigitTilesGfx[][0x40];
extern const u8 gPokemonNameDisplayGfx[];
extern const u8 gEggPortraitTilesGfx[];
extern const u8 gMainBoardBallSave_Gfx[];
extern const u8 gMainBoardEndOfBall_Gfx[];
extern const u8 gSapphireBoardZigzagoonFx_Gfx[];
extern const s16 gCaughtTextChars[];
extern const u16 gShopCursorToItemMap[];
extern const u8 *gEvoItemAppear_GfxList[];
extern const s16 gEvoShopAnimFrames[][7];
extern const u8 gRubyBoardHatchCave_Gfx[][0x480];
extern const u8 gRubyFlashingDecorationTiles[][0x300];
extern const u8 gRubyBoardSharpedo_Gfx[][0x260];
extern const u8 gRubyFlashingTiles_Secondary[][0x100];
extern const u8 gRubyBoardShopDoor_Gfx[][0x180];
extern const u8 gRubyStageCyndaquil_Gfx[][0x280];
extern const u8 gRubyBoardShop_Gfx[][0x500];
extern const u8 gHoleIndicatorTileGfx[][0x440];
extern const s16 gHoleAnimKeyframeData[][2];
extern const u8 gKecleonBonusClear_Gfx[0x2000];
extern const u8 gKyogreBonusClear_Gfx[0x2000];
extern const u8 gGroudonBoardBackgroundGfx[0x2000];
extern const u8 gGroudonBonusClear_Gfx[0x2000];
extern const u8 gRayquazaSkyBackgroundGfx[0x2800];
extern const u8 gRayquazaWindBoardGfx[0x1C00];
extern const u8 gRayquazaBonusClear_Gfx[0x2000];
extern const u8 gRayquazaSpriteSheet[0x860];
extern const u8 gSphealResultsScreenGfx[0x800];
extern const StateFunc gPinballGameStateFuncs[];
extern const u8 gDxModePikachuObjTiles[];
extern void SaveGameToSram(void);
extern void RestoreGameState(u16);
void ClampPortraitSpritesToOffscreen(void);
void SetBallPositionForBonusReturn(void);
void ClearBG0Tilemap(void);
@ -80,21 +36,6 @@ void InitPinballGameState(void);
void ConfigureBoardProcessesForField(void);
void UpdateButtonActionsFromJoy(void);
void ReplayButtonActionsFromRecording(void);
void SaveGameStateSnapshot(s16);
void SaveGameToSram(void);
void RestoreGameState(u16);
void RestoreFieldSpecificGraphics(void);
void RestoreMainFieldDynamicGraphics(void);
void RestoreRubyBoardTileGraphics(void);
void RestoreSapphireBoardTileGraphics(void);
void nullsub_18(void);
void RestoreDusclopsBonusGraphics(void);
void RestoreKecleonBonusGraphics(void);
void RestoreKyogreBonusGraphics(void);
void RestoreGroudonBonusGraphics(void);
void RestoreRayquazaBonusGraphics(void);
void RestoreSphealBonusGraphics(void);
void PinballGameMain(void)
{
@ -129,7 +70,7 @@ void PinballGame_State0_49ED4(void)
case 0:
SetupDisplayRegistersForField();
InitPinballGameState();
loadIntroduction();
loadFieldBoardGraphics();
DmaCopy16(3, gBoardConfig.fieldLayout.objPaletteSets[0], (void *)OBJ_PLTT, OBJ_PLTT_SIZE);
if (gMain.eReaderBonuses[EREADER_DX_MODE_CARD])
DmaCopy16(3, &gBallPalettes[gCurrentPinballGame->ballUpgradeType], (void *)OBJ_PLTT + 0x20, 0x20);
@ -161,7 +102,7 @@ void PinballGame_State0_49ED4(void)
case 1:
SetupDisplayRegistersForField();
InitPinballGameState();
loadIntroduction();
loadFieldBoardGraphics();
DmaCopy16(3, gBoardConfig.fieldLayout.objPaletteSets[0], (void *)OBJ_PLTT, OBJ_PLTT_SIZE);
if (gMain.eReaderBonuses[EREADER_DX_MODE_CARD])
DmaCopy16(3, &gBallPalettes[gCurrentPinballGame->ballUpgradeType], (void *)OBJ_PLTT + 0x20, 0x20);
@ -187,7 +128,7 @@ void PinballGame_State0_49ED4(void)
case 3:
SetupDisplayRegistersForField();
InitPinballGameState();
loadIntroduction();
loadFieldBoardGraphics();
DmaCopy16(3, gBoardConfig.fieldLayout.objPaletteSets[0], (void *)OBJ_PLTT, OBJ_PLTT_SIZE);
ConfigureBoardProcessesForField();
for (i = 0; i < 9; i++)
@ -960,698 +901,4 @@ void ReplayButtonActionsFromRecording(void)
if (gCurrentPinballGame->newButtonActions[1])
gMain.newKeys = A_BUTTON;
}
void SaveGameStateSnapshot(s16 arg0)
{
s16 i;
u16 *var0;
if (gMPlayInfo_BGM.status >= 0)
{
gCurrentPinballGame->savedBgmSongHeader = gMPlayInfo_BGM.songHeader;
m4aMPlayStop(&gMPlayInfo_BGM);
}
else
{
gCurrentPinballGame->savedBgmSongHeader = NULL;
}
for (i = 0; i < 100; i++)
gCurrentPinballGame->savedSpriteAvailability[gMain.isBonusField][i] = gMain.spriteGroups[i].available;
DmaCopy16(3, (void *)OBJ_PLTT, gCurrentPinballGame->savedObjPalette[gMain.isBonusField], OBJ_PLTT_SIZE);
DmaCopy16(3, (void *)BG_PLTT, gCurrentPinballGame->savedBgPalette[gMain.isBonusField], BG_PLTT_SIZE);
if (!arg0)
return;
gCurrentPinballGame->bgOffsets0 = gMain.bgOffsets[0];
gCurrentPinballGame->bgOffsets1 = gMain.bgOffsets[1];
gCurrentPinballGame->bgOffsets2 = gMain.bgOffsets[2];
gCurrentPinballGame->bgOffsets3 = gMain.bgOffsets[3];
gCurrentPinballGame->savedField = gMain.selectedField;
gCurrentPinballGame->savedTempField = gMain.tempField;
gCurrentPinballGame->savedIsBonusField = gMain.isBonusField;
gCurrentPinballGame->savedModeChangeFlags = gMain.modeChangeFlags;
gCurrentPinballGame->savedDebugMenuCursorIndex = gMain.debugMenuCursorIndex;
gCurrentPinballGame->savedPendingModeChangeType = gMain.pendingModeChangeType;
gCurrentPinballGame->savedAnimationTimer = gMain.animationTimer;
gCurrentPinballGame->savedModeChangeDelayTimer = gMain.modeChangeDelayTimer;
gCurrentPinballGame->savedShopPanelActive = gMain.shopPanelActive;
gCurrentPinballGame->savedShopPanelSlideOffset = gMain.shopPanelSlideOffset;
gCurrentPinballGame->savedBlendControl = gCurrentPinballGame->pauseBlendControl;
gCurrentPinballGame->savedBlendAlpha = gCurrentPinballGame->pauseBlendAlpha;
gCurrentPinballGame->savedBlendBrightness = gCurrentPinballGame->pauseBlendBrightness;
gCurrentPinballGame->savedScoreOverlayActive = gCurrentPinballGame->pauseScoreOverlayActive;
gCurrentPinballGame->savedVCount = gCurrentPinballGame->pauseVCount;
gCurrentPinballGame->ballSpeed = gMain_saveData.ballSpeed;
for (i = 0; i < NUM_EREADER_CARDS; i++)
gCurrentPinballGame->eReaderBonuses[i] = gMain.eReaderBonuses[i];
}
void SaveGameToSram(void)
{
gCurrentPinballGame->saveDataValid = 1;
WriteAndVerifySramFast((const u8 *)gCurrentPinballGame, (void *)SRAM + 0x544, sizeof(*gCurrentPinballGame));
}
void RestoreGameState(u16 arg0)
{
s16 i, j;
s16 var0, var1;
int var2;
if (arg0 == 1)
{
ReadSramFast((void *)SRAM + 0x544, (u8 *)gCurrentPinballGame, sizeof(*gCurrentPinballGame));
}
else if (arg0 == 2)
{
DmaCopy16(3, gBoardConfig.pinballGame, gCurrentPinballGame, sizeof(*gCurrentPinballGame));
gCurrentPinballGame->ball = &gCurrentPinballGame->ballStates[0];
gCurrentPinballGame->secondaryBall = &gCurrentPinballGame->ballStates[0];
var2 = gMain.idleDemoVariant;
if ((var2 & 0x3) == 1)
{
gCurrentPinballGame->pikaSpinMomentum = 0;
gCurrentPinballGame->kickbackAnimFrameTimer = 0;
gCurrentPinballGame->kickbackFrameId = 0;
gCurrentPinballGame->pikaChargeTarget = 0;
gCurrentPinballGame->pikaChargeProgress = 0;
gCurrentPinballGame->prevChargeFillValue = 0;
gCurrentPinballGame->chargeFillValue = 0;
gCurrentPinballGame->chargeIndicatorXOffset = 0;
gCurrentPinballGame->chargeIndicatorYOffset = -4;
gCurrentPinballGame->chargeIndicatorScaleX = 256;
gCurrentPinballGame->chargeIndicatorScaleY = 256;
gCurrentPinballGame->chargeFillAnimTimer = 0;
gCurrentPinballGame->fullChargeSlideAnimTimer = 0;
}
}
if (arg0 != 0)
{
gMain.selectedField = gCurrentPinballGame->savedField;
gMain.tempField = gCurrentPinballGame->savedTempField;
gMain.isBonusField = gCurrentPinballGame->savedIsBonusField;
gMain.modeChangeFlags = gCurrentPinballGame->savedModeChangeFlags;
gMain.debugMenuCursorIndex = gCurrentPinballGame->savedDebugMenuCursorIndex;
gMain.pendingModeChangeType = gCurrentPinballGame->savedPendingModeChangeType;
gMain.animationTimer = gCurrentPinballGame->savedAnimationTimer;
gMain.modeChangeDelayTimer = gCurrentPinballGame->savedModeChangeDelayTimer;
gMain.shopPanelActive = gCurrentPinballGame->savedShopPanelActive;
gMain.shopPanelSlideOffset = gCurrentPinballGame->savedShopPanelSlideOffset;
gMain.blendControl = gCurrentPinballGame->savedBlendControl;
gMain.blendAlpha = gCurrentPinballGame->savedBlendAlpha;
gMain.blendBrightness = gCurrentPinballGame->savedBlendBrightness;
gMain.scoreOverlayActive = gCurrentPinballGame->savedScoreOverlayActive;
gMain.vCount = gCurrentPinballGame->savedVCount;
gMain.bgOffsets[0] = gCurrentPinballGame->bgOffsets0;
gMain.bgOffsets[1] = gCurrentPinballGame->bgOffsets1;
gMain.bgOffsets[2] = gCurrentPinballGame->bgOffsets2;
gMain.bgOffsets[3] = gCurrentPinballGame->bgOffsets3;
for (i = 0; i < NUM_EREADER_CARDS; i++)
gMain.eReaderBonuses[i] = gCurrentPinballGame->eReaderBonuses[i];
gCurrentPinballGame->startButtonDisabled = 1;
if (arg0 == 1 && gMain.selectedField < MAIN_FIELD_COUNT)
{
gCurrentPinballGame->cameraYViewport = gCurrentPinballGame->cameraBaseY +
gCurrentPinballGame->tiltYOffset +
gCurrentPinballGame->cameraScrollOffset +
gCurrentPinballGame->cameraYAdjust;
}
}
else
{
gCurrentPinballGame->cameraYViewport = gCurrentPinballGame->hudSpriteBaseY;
}
gCurrentPinballGame->fadeSubState = 0;
gMain.continueFromSave = 0;
loadIntroduction();
if (gMain.selectedField == FIELD_RUBY && gCurrentPinballGame->boardCollisionConfigChanged)
SetBoardCollisionConfig(1);
if (gMain.selectedField < MAIN_FIELD_COUNT)
{
for (i = 0; i < 22; i++)
{
var0 = i + gCurrentPinballGame->ballLaunchSpeed;
var1 = (i + 10 + gCurrentPinballGame->ballLaunchSpeed) % 22;
if (var0 < 32)
{
DmaCopy16(3, &gBoardGfxBuffer[var0 * 0x400], (void *)0x6008000 + var1 * 0x400, 0x400);
}
else
{
var0 -= 32;
DmaCopy16(3, &gBoardBGTileBufferAlt[var0 * 0x400], (void *)0x6008000 + var1 * 0x400, 0x400);
}
}
}
for (i = 0; i < 0x800; i++)
gBG0TilemapBuffer[i] = 0x1FF;
DmaCopy16(3, gBG0TilemapBuffer, (void *)0x6002000, 0x1000);
if (gMain.scoreOverlayActive)
{
if (gCurrentPinballGame->boardState == 6)
{
for (j = 0; j <= gCurrentPinballGame->cutsceneTilemapColumn; j++)
{
for (i = 2; i < 12; i++)
gBG0TilemapBuffer[(i + 15) * 0x20 + j] = 0xC100;
}
}
else
{
for (j = 0; j <= gCurrentPinballGame->cutsceneTilemapColumn; j++)
{
for (i = 1; i < 11; i++)
gBG0TilemapBuffer[(i + 15) * 0x20 + j] = 0xC100;
}
}
DmaCopy16(3, gBG0TilemapBuffer, (void *)0x6002000, 0x800);
}
DmaCopy16(3, gCurrentPinballGame->savedObjPalette[gMain.isBonusField], (void *)OBJ_PLTT, OBJ_PLTT_SIZE);
DmaCopy16(3, gCurrentPinballGame->savedBgPalette[gMain.isBonusField], (void *)BG_PLTT, BG_PLTT_SIZE);
DmaCopy16(3, &gBallPalettes[gCurrentPinballGame->ballUpgradeType], (void *)OBJ_PLTT + 0x20, 0x20);
RestoreFieldSpecificGraphics();
switch (gMain.selectedField)
{
case FIELD_RUBY:
RubyBoardProcess_0A_50848();
LoadShopItemGraphics(gCurrentPinballGame->evolutionShopActive);
break;
case FIELD_SAPPHIRE:
SapphireBoardProcess_0A_50AD4();
break;
case FIELD_DUSCLOPS:
DusclopsBoardProcess_0A_50D48();
break;
case FIELD_KECLEON:
KecleonBoardProcess_0A_50DE0();
break;
case FIELD_KYOGRE:
KyogreBoardProcess_0A_50F04();
break;
case FIELD_GROUDON:
GroudonBoardProcess_0A_50FD4();
break;
case FIELD_RAYQUAZA:
RayquazaBoardProcess_0A_51090();
break;
case FIELD_SPHEAL:
SphealBoardProcess_0A_51150();
break;
}
for (i = 0; i < 100; i++)
gMain.spriteGroups[i].available = gCurrentPinballGame->savedSpriteAvailability[gMain.isBonusField][i];
if (arg0 == 1)
{
gCurrentPinballGame->saveDataValid = 0;
WriteAndVerifySramFast((const u8 *)gCurrentPinballGame, (void *)SRAM + 0x544, sizeof(gCurrentPinballGame->saveDataValid));
}
}
void RestoreFieldSpecificGraphics(void)
{
s16 i;
struct PokemonSpecies *species;
const u16 *var1;
s16 var2, var3;
switch (gMain.selectedField)
{
case FIELD_RUBY:
RestoreMainFieldDynamicGraphics();
RestoreRubyBoardTileGraphics();
break;
case FIELD_SAPPHIRE:
RestoreMainFieldDynamicGraphics();
RestoreSapphireBoardTileGraphics();
break;
case FIELD_DUSCLOPS:
nullsub_18();
RestoreDusclopsBonusGraphics();
break;
case FIELD_KECLEON:
nullsub_18();
RestoreKecleonBonusGraphics();
break;
case FIELD_KYOGRE:
nullsub_18();
RestoreKyogreBonusGraphics();
break;
case FIELD_GROUDON:
nullsub_18();
RestoreGroudonBonusGraphics();
break;
case FIELD_RAYQUAZA:
nullsub_18();
RestoreRayquazaBonusGraphics();
break;
case FIELD_SPHEAL:
nullsub_18();
RestoreSphealBonusGraphics();
break;
}
switch (gCurrentPinballGame->activePortraitType - 1)
{
case 0:
if (gCurrentPinballGame->outLanePikaPosition == 2 && gCurrentPinballGame->outLaneSide == 2)
{
DmaCopy16(3, gPikaSaverFullCoverageGfx, (void *)0x6015800, 0x2400);
}
else
{
DmaCopy16(3, gPikaSaverPartialCoverageGfx, (void *)0x6015800, 0x2400);
}
break;
case 1:
DmaCopy16(3, gEggModeTilesGfx, (void *)0x6015800, 0x1000);
break;
case 2:
DmaCopy16(3, gCaptureModeTilesGfx, (void *)0x6015800, 0xCA0);
break;
case 3:
DmaCopy16(3, gModeBannerTilemaps[gCurrentPinballGame->bannerGfxIndex], (void *)0x6015800, 0x25E0);
break;
case 4:
DmaCopy16(3, gHatchStartTilesGfx, (void *)0x6015800, 0x2000);
break;
case 5:
DmaCopy16(3, gHatchStage2TilesGfx, (void *)0x6015800, 0x800);
break;
case 6:
DmaCopy16(3, gHatchStage3TilesGfx, (void *)0x6015800, 0x2000);
break;
case 7:
DmaCopy16(3, gHatchFinalTilesGfx, (void *)0x6015800, 0x1800);
break;
case 8:
DmaCopy16(3, gCaptureScreenTilesGfx, (void *)0x6015800, 0x1C00);
break;
case 9:
DmaCopy16(3, gSapphireCatchTilesGfx, (void *)0x6015800, 0x1400);
break;
case 10:
DmaCopy16(3, gHatchRevealTilesGfx, (void *)0x6015800, 0x2800);
break;
case 11:
DmaCopy16(3, gEggPortraitTilesGfx, (void *)0x6015800, 0x280);
break;
case 13:
for (i = 0; i < 10; i++)
{
if (gSpeciesInfo[gCurrentPinballGame->currentSpecies].name[i] == ' ')
{
DmaCopy16(3, gSpaceTileGfx, (void *)0x6015800 + i * 0x40, 0x40);
}
else
{
int var0 = gSpeciesInfo[gCurrentPinballGame->currentSpecies].name[i] - 'A';
DmaCopy16(3, gAlphabetTilesGfx[var0], (void *)0x6015800 + i * 0x40, 0x40);
}
}
DmaCopy16(3, gPokemonNameDisplayGfx, (void *)0x6015C00, 0x940);
break;
case 12:
for (i = 0; i < 10; i++)
{
if (gSpeciesInfo[gCurrentPinballGame->currentSpecies].name[i] == ' ')
{
DmaCopy16(3, gSpaceTileGfx, (void *)0x6015800 + i * 0x40, 0x40);
}
else
{
int var0 = gSpeciesInfo[gCurrentPinballGame->currentSpecies].name[i] - 'A';
DmaCopy16(3, gAlphabetTilesGfx[var0], (void *)0x6015800 + i * 0x40, 0x40);
}
}
for (i = 0; i < 10; i++)
{
if (gCaughtTextChars[i] == ' ')
{
DmaCopy16(3, gSpaceTileGfx, (void *)0x6015800 + (i + 10) * 0x40, 0x40);
}
else
{
int var0 = gCaughtTextChars[i] - 'A';
DmaCopy16(3, gAlphabetTilesGfx[var0], (void *)0x6015800 + (i + 10) * 0x40, 0x40);
}
}
break;
case 14:
DmaCopy16(3, gEvoItemAppear_GfxList[gCurrentPinballGame->evoItemGfxIndex], (void *)0x6015800, 0x1C00);
break;
case 15:
DmaCopy16(3, gBoardActionTilesGfx, (void *)0x6015800, 0x2400);
break;
case 16:
DmaCopy16(3, gHatchFinalTilesGfx, (void *)0x6015800, 0x1800);
break;
case 17:
DmaCopy16(3, gPokemonNameDisplayGfx, (void *)0x6015C00, 0x940);
if (gCurrentPinballGame->evolutionShopActive == 0)
{
var1 = gShopItemData[gShopCursorToItemMap[gCurrentPinballGame->shopItemCursor]];
var2 = var1[3] / 10;
DmaCopy16(3, gDecimalDigitTilesGfx[var2], (void *)0x6015DA0, 0x40);
var3 = var1[3] % 10;
DmaCopy16(3, gDecimalDigitTilesGfx[var3], (void *)0x6015E60, 0x40);
}
break;
case 18:
DmaCopy16(3, gMainBoardBallSave_Gfx, (void *)0x6015800, 0x2400);
break;
case 19:
DmaCopy16(3, gMainBoardEndOfBall_Gfx, (void *)0x6015800, 0x2800);
break;
case 20:
if (gMain.selectedField == FIELD_RUBY)
{
DmaCopy16(3, gRubyBoardBonusGfx, (void *)0x6015800, 0x1800);
DmaCopy16(3, gRubyBoardBonusObjPalette, (void *)OBJ_PLTT + 0x1C0, 0x20);
}
else
{
DmaCopy16(3, gSapphireBoardBonusGfx, (void *)0x6015800, 0x1800);
DmaCopy16(3, gSapphireBoardBonusObjPalette, (void *)OBJ_PLTT + 0x1C0, 0x20);
}
break;
case 21:
DmaCopy16(3, gSapphireBoardZigzagoonFx_Gfx, (void *)0x6015800, 0xC00);
break;
}
}
void RestoreMainFieldDynamicGraphics(void)
{
s16 i;
s16 var0;
LoadCatchSpriteGraphics();
LoadEggSpriteGraphics();
for (i = 0; i <= 1; i++)
{
var0 = gCurrentPinballGame->flipper[i].position / 2;
DmaCopy16(3, gFlipperTileGraphics[var0], ((i * 0x200) + 0x06010000), 0x200);
}
var0 = gCurrentPinballGame->ball->spinAngle / 0x1000;
DmaCopy16(3, gBallRotationTileGraphics[var0], 0x06010400, 0x80);
for (i = 0; i <= 1; i++)
{
DmaCopy16(3, gPikaSaverTilesGfx + ((var0 =gCurrentPinballGame->pikaSaverTileIndex[i]) * 0x180), 0x06010480 + (i * 0x180), 0x180);
}
var0 = gCurrentPinballGame->pikachuSpinFrame;
DmaCopy16(3, gMainBoardPikaSpinner_Gfx[var0 = gCurrentPinballGame->pikachuSpinFrame], 0x06010780, 0x120);
var0 = gCurrentPinballGame->chargeFillValue;
DmaCopy16(3, gChargeFillIndicator_Gfx[var0], 0x06010AE0, 0x80);
for (i = 0; i <= 1; i++)
{
switch (gCurrentPinballGame->portraitRenderMode[i])
{
case 0:
DmaCopy16(3, gPortraitGenericGraphics[gCurrentPinballGame->portraitGfxIndex[i]], 0x06010CA0 + (i * 0x300), 0x300);
gCurrentPinballGame->ball += 0; //TODO: Dumb match is still a match...
break;
case 9:
if (gCurrentPinballGame->evoChainPosition > 0)
{
if (gMain_saveData.pokedexFlags[gCurrentPinballGame->evoTargetSpecies] == 0)
{
gCurrentPinballGame->portraitGfxIndex[i] = 205;
DmaCopy16(3, gMonPortraitGroupPals[gCurrentPinballGame->portraitGfxIndex[i] / 15] + (gCurrentPinballGame->portraitGfxIndex[i] % 15) * 0x20, 0x050003A0, 0x20);
}
else if (gMain_saveData.pokedexFlags[gCurrentPinballGame->evoTargetSpecies] <= 3)
{
gCurrentPinballGame->portraitGfxIndex[i] = gCurrentPinballGame->evoTargetSpecies;
DmaCopy16(3, gMonPortraitGroupPals[0] + 15 * 0x20, 0x050003A0, 0x20);
}
else
{
gCurrentPinballGame->portraitGfxIndex[i] = gCurrentPinballGame->evoTargetSpecies;
DmaCopy16(3, gMonPortraitGroupPals[gCurrentPinballGame->portraitGfxIndex[i] / 15] + (gCurrentPinballGame->portraitGfxIndex[i] % 15) * 0x20, 0x050003A0, 0x20);
}
}
else
{
gCurrentPinballGame->portraitGfxIndex[i] = gCurrentPinballGame->currentSpecies;
DmaCopy16(3, gMonPortraitGroupPals[gCurrentPinballGame->portraitGfxIndex[i] / 15] + ((gCurrentPinballGame->portraitGfxIndex[i] % 15) * 0x20), 0x050003A0, 0x20);
}
case 3:
DmaCopy16(3, gMonPortraitGroupGfx[gCurrentPinballGame->portraitGfxIndex[i] / 15] + (gCurrentPinballGame->portraitGfxIndex[i] % 15) * 0x300, 0x06010CA0 + (i * 0x18), 0x300);
break;
case 1:
case 2:
case 4:
case 6:
case 7:
case 8:
DmaCopy16(3, gPortraitAnimFrameGraphics[gCurrentPinballGame->portraitGfxIndex[i]], 0x06010CA0 + (i * 0x300), 0x300);
break;
}
}
if (gCurrentPinballGame->boardState == 4)
{
switch (gCurrentPinballGame->boardSubState)
{
case 7:
case 8:
if ((u32) gCurrentPinballGame->captureFlashTimer > 4)
{
DmaCopy16(3, gCatchSpriteFlashGfx, 0x06010CA0, 0x480);
}
else
{
DmaCopy16(3, gCatchSpriteGfxBuffer, 0x06010CA0, 0x480);
}
break;
case 9:
if (gCurrentPinballGame->captureSequenceTimer <= 31)
{
if (gCurrentPinballGame->captureFlashTimer > 4)
{
DmaCopy16(3, gCatchSpriteFlashGfx, 0x06010CA0, 0x480);
}
else
{
DmaCopy16(3, gCatchSpriteGfxBuffer, 0x06010CA0, 0x480);
}
}
break;
}
}
if (gCurrentPinballGame->boardState == 8)
{
switch (gCurrentPinballGame->boardSubState)
{
case 2:
if (gCurrentPinballGame->captureFlashTimer > 4U)
{
DmaCopy16(3, gCatchSpriteFlashGfx, 0x06010CA0, 0x480);
}
else
{
DmaCopy16(3, gCatchSpriteGfxBuffer, 0x06010CA0, 0x480);
}
break;
case 3:
if (gCurrentPinballGame->captureSequenceTimer <= 31)
{
if (gCurrentPinballGame->captureFlashTimer > 4U)
{
DmaCopy16(3, gCatchSpriteFlashGfx, 0x06010CA0, 0x480);
}
else
{
DmaCopy16(3, gCatchSpriteGfxBuffer, 0x06010CA0, 0x480);
}
}
break;
}
}
DmaCopy16(3, gMainStageBonusTrap_Gfx[gCurrentPinballGame->bonusTrapAnimFrame], 0x060113C0, 0x300);
DmaCopy16(3, gEvoItemTilesGfxPtrs[gCurrentPinballGame->evoItemGfxIndex] + var0 * 0x200, 0x060116C0, 0x200);
DmaCopy16(3, gEggFrameTilesGfx[(s16)gEggAnimationFrameData[gCurrentPinballGame->eggAnimFrameIndex][3]], 0x06011CE0, 0x200);
DmaCopy16(3, gBallShadowTileGraphics[gCurrentPinballGame->ballShadowTileIndex], 0x06011EE0, 0x200);
return;
}
void RestoreRubyBoardTileGraphics(void)
{
s16 i;
s16 var0;
var0 = gEggAnimationFrameData[gCurrentPinballGame->eggAnimFrameIndex][2];
DmaCopy16(3, gRubyBoardHatchCave_Gfx[var0], (void *)0x60122A0, 0x480);
var0 = (gMain.systemFrameCount % 50) / 25;
DmaCopy16(3, gRubyFlashingDecorationTiles[var0], (void *)0x6012720, 0x300);
DmaCopy16(3, gRubyBoardSharpedo_Gfx[gCurrentPinballGame->catchHoleTileVariant], (void *)0x6012C20, 0x260);
for (i = 0; i < 2; i++)
DmaCopy16(3, gRubyFlashingTiles_Secondary[var0], (void *)0x6010000 + (0x174 + i * 8) * 0x20, 0x100);
var0 = gCurrentPinballGame->shopDoorCurrentFrame & 0xF;
DmaCopy16(3, gRubyBoardShopDoor_Gfx[var0], (void *)0x6013180, 0x180);
if (gCurrentPinballGame->eggCaveState < 3)
gCurrentPinballGame->cyndaquilFrame = 0;
else
gCurrentPinballGame->cyndaquilFrame = 1;
DmaCopy16(3, gRubyStageCyndaquil_Gfx[gCurrentPinballGame->cyndaquilFrame], (void *)0x6013300, 0x280);
var0 = gEvoShopAnimFrames[gCurrentPinballGame->evolutionShopActive][(gCurrentPinballGame->shopAnimTimer % 42) / 6];
DmaCopy16(3, gRubyBoardShop_Gfx[var0], (void *)0x6013D00, 0x500);
}
void RestoreSapphireBoardTileGraphics(void)
{
s16 index;
switch (gCurrentPinballGame->holeLetterSystemState)
{
case 0:
case 1:
case 2:
index = gCurrentPinballGame->holeLetterCount;
DmaCopy16(3, gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
break;
case 3:
case 4:
index = 15;
DmaCopy16(3, gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
break;
case 5:
index = gHoleAnimKeyframeData[gCurrentPinballGame->holeLetterCount][0];
DmaCopy16(3, gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
break;
case 6:
break;
}
}
void RestoreDusclopsBonusGraphics(void)
{
DmaCopy16(3, gDusclopsBonusClear_Gfx, (void *)0x6015800, 0x2000);
}
void RestoreKecleonBonusGraphics(void)
{
DmaCopy16(3, gKecleonBonusClear_Gfx, (void *)0x6015800, 0x2000);
}
void RestoreKyogreBonusGraphics(void)
{
DmaCopy16(3, gKyogreBonusClear_Gfx, (void *)0x6015800, 0x2000);
DmaCopy16(
3,
gMonPortraitGroupGfx[gCurrentPinballGame->portraitGfxIndex[0] / 15] + (gCurrentPinballGame->portraitGfxIndex[0] % 15) * 0x300,
(void *)0x6010CA0,
0x300
);
}
void RestoreGroudonBonusGraphics(void)
{
if (gCurrentPinballGame->boardState < 2)
{
DmaCopy16(3, gGroudonBoardBackgroundGfx, (void *)0x6015800, 0x2000);
}
else
{
DmaCopy16(3, gGroudonBonusClear_Gfx, (void *)0x6015800, 0x2000);
}
DmaCopy16(
3,
gMonPortraitGroupGfx[gCurrentPinballGame->portraitGfxIndex[0] / 15] + (gCurrentPinballGame->portraitGfxIndex[0] % 15) * 0x300,
(void *)0x6010CA0,
0x300
);
}
void RestoreRayquazaBonusGraphics(void)
{
u8 var0;
if (gCurrentPinballGame->boardState == 0)
{
DmaCopy16(3, gRayquazaSkyBackgroundGfx, (void *)0x6015800, 0x2800);
}
else if (gCurrentPinballGame->boardState == 1)
{
DmaCopy16(3, gRayquazaWindBoardGfx, (void *)0x6015800, 0x1C00);
}
else
{
DmaCopy16(3, gRayquazaBonusClear_Gfx, (void *)0x6015800, 0x2000);
}
var0 = gCurrentPinballGame->bossEntityState - 2;
if (var0 > 9)
{
DmaCopy16(3, gRayquazaSpriteSheet, (void *)0x6011620, 0x860);
}
DmaCopy16(
3,
gMonPortraitGroupGfx[gCurrentPinballGame->portraitGfxIndex[0] / 15] + (gCurrentPinballGame->portraitGfxIndex[0] % 15) * 0x300,
(void *)0x6010CA0,
0x300
);
}
void RestoreSphealBonusGraphics(void)
{
s16 i;
int var0;
u16 var1;
for (i = 0; i < 0x800; i++)
gBG0TilemapBuffer[0x400 + i] = 0x200;
DmaCopy16(3, &gBG0TilemapBuffer[0x400], (void *)0x6001000, 0x1000);
gMain.blendControl = 0x1C42;
gMain.blendAlpha = 0xC04;
for (i = 0; i < 0x140; i++)
{
var0 = i;
if (i < 0)
var0 += 31;
var0 = (var0 >> 5) << 5;
var1 = i - var0 - 2;
if (var1 < 28)
gBG0TilemapBuffer[0x800 + i] = 0x9000;
}
gMain.bgOffsets[1].xOffset = 8;
gMain.bgOffsets[1].yOffset = 126;
DmaCopy16(3, &gBG0TilemapBuffer[0x800], (void *)0x6001140, 0x280);
for (i = 0; i < 0x800; i++)
gBG0TilemapBuffer[i] = 0x1FF;
DmaCopy16(3, gSphealResultsScreenGfx, (void *)0x6015800, 0x800);
}
void nullsub_18(void)
{
}
}

View File

@ -1,125 +0,0 @@
#include "global.h"
#include "main.h"
void PrintString(u16 glyph, u16 palette, int x, int y, int width, int height)
{
u16 i, j;
for (j = 0; j < height; j++)
for (i = 0; i < width; i++)
gBG0TilemapBuffer[y * 0x20 + x + j * 0x20 + i] = (glyph + j * 0x20 + i) | (palette << 12);
}
void CopyString(int srcX, int srcY, int destX, int destY, int width, int height)
{
u16 i, j;
for (j = 0; j < height; j++)
for (i = 0; i < width; i++)
gBG0TilemapBuffer[destY * 0x20 + destX + j * 0x20 + i] = gBG0TilemapBuffer[srcY * 0x20 + srcX + j * 0x20 + i];
}
void SetStringPalette(int x, int y, int width, int height, u16 palette)
{
u16 i, j;
u16 index;
for (j = 0; j < height; j++)
{
for (i = 0; i < width; i++)
{
index = y * 0x20 + x + j * 0x20 + i;
gBG0TilemapBuffer[index] = (gBG0TilemapBuffer[index] & 0xFFF) | (palette << 12);
}
}
}
// This requires volatile parameters to match. There is no reason, *ever*, to do this.
void CopyBgTilesRect(void *volatile src, void *volatile dest, s16 width, s16 height)
{
int j;
for (j = 0; j < height; j++)
{
DmaCopy16(3, (u8 *)src + 0x400 * j, (u8 *)dest + 0x400 * j, width * 0x20);
}
}
// This function is unused. It appears to operates on a pixel canvas where each "tile" is represented by
// 2 bytes.
void CopyPixelCanvasRect(void *volatile src, void *volatile dest, s16 width, s16 height)
{
int j;
for (j = 0; j < height; j++)
{
DmaCopy16(3, (u8 *)src + 0x40 * j, (u8 *)dest + 0x40 * j, width * 2);
}
}
// This function is unused.
void Unused_FadeInWithCustomPalettes(void *src1, void *src2, void (*func)(void))
{
u16 i;
DmaCopy16(3, src1, gPaletteFadeBuffers[1], BG_PLTT_SIZE);
DmaCopy16(3, src2, gPaletteFadeBuffers[2], BG_PLTT_SIZE);
DmaFill16(3, RGB_WHITE, gPaletteFadeBuffers, PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[0], gPaletteFadeBuffers[2], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[2], (void *)PLTT, PLTT_SIZE);
UnblankLCD();
gMain.dispcntBackup = REG_DISPCNT;
for (i = 0; i <= 0x20; i += 0x10)
{
if (func != NULL)
func();
InterpolatePaletteStep(i);
MainLoopIter();
if (i == 0x20)
{
DmaCopy16(3, gPaletteFadeBuffers[1], (void *)PLTT, PLTT_SIZE);
}
else
{
DmaCopy16(3, gPaletteFadeBuffers[2], (void *)PLTT, PLTT_SIZE);
}
}
}
// This function is unused.
void Unused_FadeOutToWhite(void (*func)(void))
{
u16 i;
DmaCopy16(3, (void *)PLTT, gPaletteFadeBuffers[0], PLTT_SIZE);
DmaFill16(3, RGB_WHITE, gPaletteFadeBuffers[1], PLTT_SIZE);
DmaCopy16(3, gPaletteFadeBuffers[0], gPaletteFadeBuffers[2], PLTT_SIZE);
for (i = 0; i <= 0x20; i += 0x10)
{
if (func != NULL)
func();
InterpolatePaletteStep(i);
MainLoopIter();
if (i == 0x20)
{
DmaCopy16(3, gPaletteFadeBuffers[1], (void *)PLTT, PLTT_SIZE);
}
else
{
DmaCopy16(3, gPaletteFadeBuffers[2], (void *)PLTT, PLTT_SIZE);
}
}
MainLoopIter();
}
void ClearHighScoreNameEntry(void)
{
int i;
for (i = 0; i < HIGH_SCORE_NAME_LENGTH; i++)
gHighScoreNameEntry[i] = 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,92 +0,0 @@
#include "global.h"
#include "functions.h"
#include "main.h"
#include "variables.h"
extern u32 gLinkStatusResult;
extern s16 gLinkTimeoutCounter;
extern u32 gLinkConnectionState;
extern u8 gLinkPlayerCount;
extern u8 gLinkNegotiationFlags;
s16 LoadSpriteSetsWithCpuCopy(const struct SpriteSet *const *spriteSets, u16 numSpriteSets, struct SpriteGroup *spriteGroups)
{
struct SpriteGroup *spriteGroup;
struct OamDataSimple *simple;
u16 *oamData;
u16 i;
u16 j;
u16 pos;
u16 numSpritesInGroup;
oamData = (u16 *)gOamBuffer;
pos = 0;
CpuCopy16(gEmptyOamData, oamData, sizeof(gOamBuffer));
for (i = 0; i < numSpriteSets; i++) {
spriteGroup = &spriteGroups[i];
if (!spriteGroup->available) {
continue;
}
numSpritesInGroup = spriteSets[i]->count;
CpuCopy16(spriteSets[i]->oamData, &gOamBuffer[pos], numSpritesInGroup * sizeof(struct OamData));
for (j = 0; j < numSpritesInGroup; j++) {
oamData = (u16 *)&gOamBuffer[pos];
simple = &spriteGroup->oam[j];
simple->oamId = pos++;
simple->xOffset = oamData[1] & 0x1FF;
simple->yOffset = oamData[0] & 0xFF;
}
}
return pos;
}
void nullsub_16(void)
{
}
void ResetSerialIO(void)
{
REG_RCNT = 0;
REG_SIOCNT = 0;
REG_SIOMLT_SEND = 0;
REG_SIOMULTI0 = 0;
REG_SIOMLT_SEND = 0;
REG_SIOMULTI0 = 0;
REG_SIOMULTI0 = 0;
REG_SIOMULTI1 = 0;
REG_SIOMULTI2 = 0;
REG_SIOMULTI3 = 0;
}
void SetupDefaultInterrupts(void)
{
REG_IME = 0;
REG_IE = INTR_FLAG_GAMEPAK | INTR_FLAG_VBLANK;
REG_DISPSTAT = DISPSTAT_VBLANK_INTR;
REG_IME = 1;
}
void ResetLinkState(void)
{
gLinkStatusResult = 0;
gLinkTimeoutCounter = 0;
gLinkConnectionState = 0;
gLinkPlayerCount = 0;
gLinkNegotiationFlags = 0;
}
void ResetSerialAndInterrupts(void)
{
ResetSerialIO();
REG_IME = 0;
ResetMainCallback();
ResetVBlankIntrFunc();
REG_IE = INTR_FLAG_GAMEPAK | INTR_FLAG_VCOUNT | INTR_FLAG_VBLANK;
REG_DISPSTAT = DISPSTAT_VCOUNT_INTR | DISPSTAT_VBLANK_INTR;
REG_IME = 1;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,305 +0,0 @@
#include "global.h"
#include "main.h"
#include "gba/gba.h"
#include "m4a.h"
#include "constants/fields.h"
#include "constants/bg_music.h"
extern const u8 gSplashEffectTileGfx[][0x100];
extern const s16 gHoleAnimKeyframeData[][2];
extern const s16 gSplashEffectFrameDurations[][2];
extern const s16 gSplashEffectTileIndices[][2];
extern const u8 gHoleIndicatorTileGfx[][0x440];
extern struct Vector16 gSplashEffectPositions[];
extern const u8 gRubyStageCyndaquil_Gfx[][0x280];
extern const u8 gSapphireShopSignPalettes[][0x20];
extern const u8 gSapphireShopSignTileGfx[][0x480];
void DrawSapphireShopSignSprite(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 index;
group = &gMain.spriteGroups[69];
if (group->available)
{
group->baseX = 16 - gCurrentPinballGame->cameraXOffset;
group->baseY = 115 - gCurrentPinballGame->cameraYOffset;
index = gCurrentPinballGame->shopSignPaletteIndex + gCurrentPinballGame->activePaletteIndex * 3;
DmaCopy16(3, gSapphireShopSignPalettes[index], (void *)0x05000300, 0x20);
DmaCopy16(3, gSapphireShopSignTileGfx[gCurrentPinballGame->shopSignFrame], (void *) 0x06014B20, 0x480);
for (i = 0; i < 2; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
}
void UpdateSapphireHoleLetterSystem(void)
{
s16 i, j;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 index;
switch (gCurrentPinballGame->holeLetterSystemState)
{
case 0:
if (gCurrentPinballGame->holeLetterNewHit)
{
if (gCurrentPinballGame->boardState < 3)
{
if (gCurrentPinballGame->holeLetterCount < 3)
{
gCurrentPinballGame->holeLetterCount++;
gCurrentPinballGame->scoreAddedInFrame = 20000;
m4aSongNumStart(SE_UNKNOWN_0xDE);
}
else
{
gMain.modeChangeFlags |= MODE_CHANGE_BANNER;
gCurrentPinballGame->bannerDelayTimer = 0;
gCurrentPinballGame->bannerDisplayTimer = 920;
gCurrentPinballGame->cameraYScrollTarget = 0;
gCurrentPinballGame->cameraYAdjust = 0;
gCurrentPinballGame->cameraYScrollSpeed = 0;
gCurrentPinballGame->bannerGfxIndex = 0;
gCurrentPinballGame->bannerActive = 1;
gCurrentPinballGame->bannerPreserveBallState = 0;
gCurrentPinballGame->holeLetterSystemState = 1;
gCurrentPinballGame->holeAnimFrameCounter = 0;
m4aMPlayStop(&gMPlayInfo_BGM);
gCurrentPinballGame->scoreAddedInFrame = 200000;
m4aSongNumStart(SE_UNKNOWN_0xDF);
}
}
else
{
if (gCurrentPinballGame->holeLetterCount < 3)
{
gCurrentPinballGame->holeLetterCount++;
gCurrentPinballGame->scoreAddedInFrame = 20000;
m4aSongNumStart(SE_UNKNOWN_0xDE);
}
}
index = gCurrentPinballGame->holeLetterCount;
DmaCopy16(3, &gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
gCurrentPinballGame->holeLetterNewHit = 0;
}
break;
case 1:
if (gCurrentPinballGame->holeAnimFrameCounter < 270)
{
index = (gCurrentPinballGame->holeAnimFrameCounter % 60) / 30 + 4;
DmaCopy16(3, &gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
}
else
{
index = 0;
DmaCopy16(3, &gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
gCurrentPinballGame->holeLetterSystemState = 2;
gCurrentPinballGame->holeLetterCount = 0;
}
if (gCurrentPinballGame->holeAnimFrameCounter == 60)
{
m4aSongNumStart(MUS_EGG_MODE_START);
gCurrentPinballGame->catchArrowPaletteActive = 0;
gCurrentPinballGame->eggAnimationPhase = 5;
gCurrentPinballGame->eggAnimFrameIndex = 12;
gCurrentPinballGame->eggFrameTimer = 0;
}
gCurrentPinballGame->holeAnimFrameCounter++;
break;
case 3:
if (gHoleAnimKeyframeData[gCurrentPinballGame->holeLetterCount][1] > gCurrentPinballGame->holeAnimFrameCounter)
{
gCurrentPinballGame->holeAnimFrameCounter++;
}
else
{
gCurrentPinballGame->holeAnimFrameCounter = 0;
gCurrentPinballGame->holeLetterCount++;
if (gCurrentPinballGame->holeLetterCount == 10)
gCurrentPinballGame->holeLetterSystemState = 4;
if (gCurrentPinballGame->holeLetterCount == 6)
m4aSongNumStart(SE_UNKNOWN_0xE0);
index = gHoleAnimKeyframeData[gCurrentPinballGame->holeLetterCount][0];
DmaCopy16(3, &gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
}
if (gCurrentPinballGame->holeLetterCount < 6)
{
gCurrentPinballGame->walkMonYPos = 280;
}
else
{
gCurrentPinballGame->walkMonYPos += 6;
if (gCurrentPinballGame->holeLetterSystemState == 4)
gCurrentPinballGame->walkMonYPos = gCurrentPinballGame->walkMonYPos + 20;
}
break;
case 4:
if (gCurrentPinballGame->holeCaptureReady && gCurrentPinballGame->holeLetterNewHit)
{
gMain.modeChangeFlags |= MODE_CHANGE_BANNER;
gCurrentPinballGame->bannerDelayTimer = 0;
gCurrentPinballGame->bannerDisplayTimer = 160;
gCurrentPinballGame->cameraYScrollTarget = 0;
gCurrentPinballGame->cameraYAdjust = 0;
gCurrentPinballGame->cameraYScrollSpeed = 0;
gCurrentPinballGame->bannerGfxIndex = 0;
gCurrentPinballGame->bannerActive = 1;
gCurrentPinballGame->bannerPreserveBallState = 0;
gCurrentPinballGame->holeLetterSystemState = 5;
gCurrentPinballGame->holeAnimFrameCounter = 0;
gCurrentPinballGame->holeLetterCount = 10;
m4aSongNumStart(SE_UNKNOWN_0xE0);
gCurrentPinballGame->eggAnimationPhase = 1;
gCurrentPinballGame->portraitOffsetX = 2080;
gCurrentPinballGame->portraitOffsetY = 960;
}
gCurrentPinballGame->holeLetterNewHit = 0;
break;
case 5:
if (gHoleAnimKeyframeData[gCurrentPinballGame->holeLetterCount][1] > gCurrentPinballGame->holeAnimFrameCounter)
{
gCurrentPinballGame->holeAnimFrameCounter++;
}
else
{
gCurrentPinballGame->holeAnimFrameCounter = 0;
gCurrentPinballGame->holeLetterCount++;
if (gCurrentPinballGame->holeLetterCount == 15)
gCurrentPinballGame->holeLetterSystemState = 6;
index = gHoleAnimKeyframeData[gCurrentPinballGame->holeLetterCount][0];
DmaCopy16(3, gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
}
if (gCurrentPinballGame->holeLetterCount == 14 && gCurrentPinballGame->holeAnimFrameCounter == 10)
m4aSongNumStart(SE_UNKNOWN_0xE1);
if (gCurrentPinballGame->portraitOffsetY > 700)
gCurrentPinballGame->portraitOffsetY -= 5;
else
gCurrentPinballGame->portraitOffsetY = 700;
break;
case 6:
gCurrentPinballGame->holeLetterCount = 0;
gCurrentPinballGame->holeAnimFrameCounter = 0;
gCurrentPinballGame->holeLetterSystemState = 0;
gCurrentPinballGame->holeCaptureReady = 0;
break;
}
for (i = 0; i < 4; i++)
{
group = &gMain.spriteGroups[47 + i];
if (group->available)
{
if (gSplashEffectFrameDurations[gCurrentPinballGame->splashEffectFrameIndex[i]][0] > gCurrentPinballGame->splashEffectFrameTimer[i])
{
gCurrentPinballGame->splashEffectFrameTimer[i]++;
}
else
{
gCurrentPinballGame->splashEffectFrameTimer[i] = 0;
gCurrentPinballGame->splashEffectFrameIndex[i]++;
if (gCurrentPinballGame->splashEffectFrameIndex[i] == 6)
{
group->available = 0;
gCurrentPinballGame->splashEffectFrameIndex[i] = 5;
}
}
index = gSplashEffectTileIndices[gCurrentPinballGame->splashEffectFrameIndex[i]][0];
DmaCopy16(3, &gSplashEffectTileGfx[index], (void *)0x060140a0 + i * 0x100, 0x100);
group->baseX = gSplashEffectPositions[gCurrentPinballGame->splashEffectPositionIndex[i]].x - gCurrentPinballGame->cameraXOffset;
group->baseY = gSplashEffectPositions[gCurrentPinballGame->splashEffectPositionIndex[i]].y - gCurrentPinballGame->cameraYOffset;
for (j = 0; j < 3; j++)
{
oamSimple = &group->oam[j];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
}
}
void DrawBoardEdgeBanner(void)
{
s16 i;
struct SpriteGroup *group;
if (gMain.selectedField == FIELD_RUBY)
group = &gMain.spriteGroups[81];
else
group = &gMain.spriteGroups[85];
if (group->available)
{
if (gCurrentPinballGame->cameraBaseX < 8)
{
group->baseX = gCurrentPinballGame->cameraXOffset;
group->baseX = -8 - group->baseX;
}
else
{
group->baseX = gCurrentPinballGame->cameraXOffset;
group->baseX = 256 - group->baseX;
}
group->baseY = 0;
for (i = 0; i < 5; i++)
{
struct OamDataSimple *oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY + i * 0x20;
}
}
}
/**
* Executed when saving or loading from a main field
* arg0
* 0 when saving and loading normally
* 2 when loading into the evo or mart menu
*/
void RestoreBoardObjPalettes(s16 arg0)
{
if (gCurrentPinballGame->paletteSwapActive == 1)
{
DmaCopy16(3, gBoardConfig.fieldLayout.objPaletteSets[arg0], (void*)OBJ_PLTT, 0x20);
}
if (gMain.selectedField == FIELD_SAPPHIRE)
{
DmaCopy16(3, gBoardConfig.fieldLayout.objPaletteSets[arg0] + 0x40, (void*)OBJ_PLTT + 0x40, 0xC0);
}
else
{
DmaCopy16(3, gBoardConfig.fieldLayout.objPaletteSets[arg0] + 0x40, (void*)OBJ_PLTT + 0x40, 0xE0);
}
DmaCopy16(3, gBoardConfig.fieldLayout.objPaletteSets[arg0] + 0x140, (void *)OBJ_PLTT + 0x140, 0x20);
// related to Y position of camera on the field
if (gCurrentPinballGame->cameraYViewport < 170)
{
DmaCopy16(3, gFieldPaletteVariants[gMain.selectedField][arg0 * 2], (void *)OBJ_PLTT + 0x160, 0x20);
}
else
{
DmaCopy16(3, gFieldPaletteVariants[gMain.selectedField][arg0 * 2 + 1], (void *)OBJ_PLTT + 0x160, 0x20);
}
}

View File

@ -1,124 +0,0 @@
#include "global.h"
#include "main.h"
#include "constants/species.h"
/**
* 0 if captured via ball
* 1 if evolved
*/
void RegisterCaptureOrEvolution(s16 evolved)
{
s16 i;
if (!evolved)
{
if (gMain.mainState != STATE_GAME_IDLE)
SaveFile_SetPokedexFlags(gCurrentPinballGame->currentSpecies, SPECIES_CAUGHT);
if (gSpeciesInfo[gCurrentPinballGame->currentSpecies].evolutionMethod != 0)
{
if (gSpeciesInfo[gCurrentPinballGame->currentSpecies].evolutionTarget < SPECIES_NONE)
{
if (gCurrentPinballGame->evolvablePartySize < MAX_EVOLVABLE_PARTY_SIZE)
{
gCurrentPinballGame->evolvablePartySpecies[gCurrentPinballGame->evolvablePartySize] =
gCurrentPinballGame->currentSpecies;
gCurrentPinballGame->evolvablePartySize++;
}
else
{
for (i = 0; i < MAX_EVOLVABLE_PARTY_SIZE; i++)
gCurrentPinballGame->evolvablePartySpecies[i] = gCurrentPinballGame->evolvablePartySpecies[i + 1];
gCurrentPinballGame->evolvablePartySpecies[MAX_EVOLVABLE_PARTY_SIZE - 1] = gCurrentPinballGame->currentSpecies;
}
}
}
}
else
{
gCurrentPinballGame->evolvablePartySize--;
for (i = gCurrentPinballGame->evolvingPartyIndex; i < gCurrentPinballGame->evolvablePartySize; i++)
gCurrentPinballGame->evolvablePartySpecies[i] = gCurrentPinballGame->evolvablePartySpecies[i + 1];
if (gCurrentPinballGame->currentSpecies == SPECIES_WURMPLE)
{
if ((gMain.systemFrameCount & 1) == 0)
{
if (gMain_saveData.pokedexFlags[SPECIES_SILCOON] < SPECIES_CAUGHT)
gCurrentPinballGame->currentSpecies = SPECIES_SILCOON;
else
gCurrentPinballGame->currentSpecies = SPECIES_CASCOON;
}
else
{
if (gMain_saveData.pokedexFlags[SPECIES_CASCOON] < SPECIES_CAUGHT)
gCurrentPinballGame->currentSpecies = SPECIES_CASCOON;
else
gCurrentPinballGame->currentSpecies = SPECIES_SILCOON;
}
}
else if (gCurrentPinballGame->currentSpecies == SPECIES_GLOOM)
{
if (gMain.selectedField == FIELD_RUBY)
gCurrentPinballGame->currentSpecies = SPECIES_VILEPLUME;
else
gCurrentPinballGame->currentSpecies = SPECIES_BELLOSSOM;
}
else if (gCurrentPinballGame->currentSpecies == SPECIES_CLAMPERL)
{
if ((gMain.systemFrameCount & 1) == 0)
{
if (gMain_saveData.pokedexFlags[SPECIES_HUNTAIL] < SPECIES_CAUGHT)
gCurrentPinballGame->currentSpecies = SPECIES_HUNTAIL;
else
gCurrentPinballGame->currentSpecies = SPECIES_GOREBYSS;
}
else
{
if (gMain_saveData.pokedexFlags[SPECIES_GOREBYSS] < SPECIES_CAUGHT)
gCurrentPinballGame->currentSpecies = SPECIES_GOREBYSS;
else
gCurrentPinballGame->currentSpecies = SPECIES_HUNTAIL;
}
}
else if (gCurrentPinballGame->currentSpecies == SPECIES_NINCADA)
{
gCurrentPinballGame->currentSpecies = SPECIES_SHEDINJA;
if (gMain.mainState != STATE_GAME_IDLE)
SaveFile_SetPokedexFlags(SPECIES_SHEDINJA, SPECIES_CAUGHT);
gCurrentPinballGame->currentSpecies = SPECIES_NINJASK;
}
else
{
gCurrentPinballGame->currentSpecies =
gSpeciesInfo[gCurrentPinballGame->currentSpecies].evolutionTarget;
}
if (gMain.mainState != STATE_GAME_IDLE)
SaveFile_SetPokedexFlags(gCurrentPinballGame->currentSpecies, SPECIES_CAUGHT);
if (gSpeciesInfo[gCurrentPinballGame->currentSpecies].evolutionMethod != 0)
{
if (gSpeciesInfo[gCurrentPinballGame->currentSpecies].evolutionTarget < SPECIES_NONE)
{
if (gCurrentPinballGame->evolvablePartySize < MAX_EVOLVABLE_PARTY_SIZE)
{
gCurrentPinballGame->evolvablePartySpecies[gCurrentPinballGame->evolvablePartySize] =
gCurrentPinballGame->currentSpecies;
gCurrentPinballGame->evolvablePartySize++;
}
else
{
for (i = 0; i < MAX_EVOLVABLE_PARTY_SIZE; i++)
gCurrentPinballGame->evolvablePartySpecies[i] = gCurrentPinballGame->evolvablePartySpecies[i + 1];
gCurrentPinballGame->evolvablePartySpecies[MAX_EVOLVABLE_PARTY_SIZE - 1] = gCurrentPinballGame->currentSpecies;
}
}
}
}
}

View File

@ -1,53 +0,0 @@
#include "global.h"
#include "main.h"
u16 IsInVblank(void)
{
if ((REG_IME & 1) // Interrupts enabled
&& (REG_DISPSTAT & DISPSTAT_VBLANK_INTR) // In VBLANK
&& (REG_IE & INTR_FLAG_VBLANK) // VBlank interrupt enabled
&& !(REG_DISPCNT & DISPCNT_FORCED_BLANK)) // Ignore VBlank interrupts during forced blank
return TRUE;
else
return FALSE;
}
void SetMainCallback(void (*func)(void))
{
gMainCallbackShadow = func;
if (!IsInVblank())
gMainCallback = func;
}
void ResetMainCallback(void)
{
gMainCallback = DefaultMainCallback;
gMainCallbackShadow = DefaultMainCallback;
}
void SetVBlankIntrFunc(void (*func)(void))
{
gVBlankIntrFuncShadow = func;
if (!IsInVblank())
*gVBlankIntrFuncPtr = func;
}
void ResetVBlankIntrFunc(void)
{
*gVBlankIntrFuncPtr = VBlankIntr;
gVBlankIntrFuncShadow = VBlankIntr;
}
void SetVCountIntrFunc(void (*func)(void))
{
gVCountIntrFuncShadow = func;
if (!IsInVblank())
*gVCountIntrFuncPtr = func;
}
void ResetVCountIntrFunc(void)
{
*gVCountIntrFuncPtr = VCountIntr;
gVCountIntrFuncShadow = VCountIntr;
}

View File

@ -16,7 +16,11 @@ extern const u8 *gRubyTrapIndicatorTilePointers[][2];
extern const u8 *gRubyProgressDigitTilePointers[][2];
extern const u8 *gShopItemTilePointers[][3];
extern const s16 gRubySlingshotAnimIndices[];
extern const u8 *gRubySlingshotTilePointers[][3][5];
extern const u8 *gRubySlingshotTilePointers[2][3][5];
extern const u8 *gRubyCoinRewardTilePtrs[][5][3];
extern const s16 gCoinRewardLevelTimerThresholds[];
extern const u8 *gRubyEvoArrowTilePtrs[][5][3];
extern const u8 *gRubyCatchArrowTilePtrs[][5][3];
extern struct SongHeader se_ball_upgrade;
@ -28,8 +32,8 @@ void UpdateRubyBoardAnimations(void)
DrawRubyProgressDigits();
if (gCurrentPinballGame->hudSpriteBaseY < 232)
{
AnimateRubyCatchArrow();
AnimateRubyEvoArrow();
AnimateRubyCatchArrowPalette();
AnimateRubyEvoArrowPalette();
}
if (gCurrentPinballGame->hudSpriteBaseY >= 81 && gCurrentPinballGame->hudSpriteBaseY < 248)
@ -44,12 +48,12 @@ void UpdateRubyBoardAnimations(void)
if (gCurrentPinballGame->hudSpriteBaseY > 104)
{
DrawEvoArrowProgress();
DrawCatchArrowProgress();
DrawRubyEvoArrowProgress();
DrawRubyCatchArrowProgress();
}
if (gCurrentPinballGame->hudSpriteBaseY < 256)
DrawCoinRewardMeter();
DrawRubyCoinRewardMeter();
UpdateCoinRewardTimer();
if (gCurrentPinballGame->hudSpriteBaseY > 110)
@ -59,7 +63,7 @@ void UpdateRubyBoardAnimations(void)
{
AnimateRubyCatchLightBlink();
AnimateRubyHoleIndicators();
AnimateRubySlingshotTimer();
AnimateRubySlingshotHit();
}
if (gCurrentPinballGame->hudSpriteBaseY > 202)
@ -69,7 +73,7 @@ void UpdateRubyBoardAnimations(void)
gCurrentPinballGame->saverTimeRemaining--;
}
void AnimateRubySlingshotTimer(void)
void AnimateRubySlingshotHit(void)
{
s16 index;
const u8 **src;
@ -225,7 +229,7 @@ void DrawRubyModeTimerDisplay(void)
}
}
void AnimateRubyCatchArrow(void)
void AnimateRubyCatchArrowPalette(void)
{
s16 index;
const u8 **src;
@ -256,7 +260,7 @@ void AnimateRubyCatchArrow(void)
}
}
void AnimateRubyEvoArrow(void)
void AnimateRubyEvoArrowPalette(void)
{
s16 index;
const u8 **src;
@ -407,3 +411,230 @@ void DrawRubyBallPowerUpLights(void)
DmaCopy16(3, *src, *dest, 0x40);
}
}
void UpdateCoinRewardTimer(void)
{
if (gCurrentPinballGame->coinRewardLevel > 0)
{
if (gCurrentPinballGame->coinRewardLevelTimer < gCoinRewardLevelTimerThresholds[gCurrentPinballGame->coinRewardLevel - 1])
{
gCurrentPinballGame->coinRewardLevelTimer++;
}
else
{
gCurrentPinballGame->coinRewardLevelTimer = 0;
gCurrentPinballGame->coinRewardLevel--;
}
}
}
void DrawRubyCoinRewardMeter(void)
{
s16 sp0[3];
const u8 **src;
const u8 **dest;
if (gCurrentPinballGame->coinRewardLevel == 0)
{
sp0[0] = gCurrentPinballGame->hudBlinkPhase * 2;
sp0[1] = gCurrentPinballGame->hudBlinkPhase;
sp0[2] = 0;
}
else if (gCurrentPinballGame->coinRewardLevel == 1)
{
sp0[0] = 3;
sp0[1] = gCurrentPinballGame->hudBlinkPhase + 1;
sp0[2] = gCurrentPinballGame->hudBlinkPhase * 2;
}
else if (gCurrentPinballGame->coinRewardLevel == 2)
{
sp0[0] = 3;
sp0[1] = 3;
sp0[2] = gCurrentPinballGame->hudBlinkPhase + 2;
}
else
{
sp0[0] = 3;
sp0[1] = 3;
sp0[2] = 3;
}
src = gRubyCoinRewardTilePtrs[0][sp0[0]];
dest = gRubyCoinRewardTilePtrs[0][4];
if (gCurrentPinballGame->hudSpriteBaseY >= 42 && gCurrentPinballGame->hudSpriteBaseY < 208)
{
DmaCopy16(3, src[0], dest[0], 0x60);
}
if (gCurrentPinballGame->hudSpriteBaseY >= 50 && gCurrentPinballGame->hudSpriteBaseY < 216)
{
DmaCopy16(3, src[1], dest[1], 0x60);
}
src = gRubyCoinRewardTilePtrs[1][sp0[1]];
dest = gRubyCoinRewardTilePtrs[1][4];
if (gCurrentPinballGame->hudSpriteBaseY >= 58 && gCurrentPinballGame->hudSpriteBaseY < 224)
{
DmaCopy16(3, src[0], dest[0], 0x60);
}
if (gCurrentPinballGame->hudSpriteBaseY >= 66 && gCurrentPinballGame->hudSpriteBaseY < 232)
{
DmaCopy16(3, src[1], dest[1], 0x60);
}
src = gRubyCoinRewardTilePtrs[2][sp0[2]];
dest = gRubyCoinRewardTilePtrs[2][4];
if (gCurrentPinballGame->hudSpriteBaseY >= 74 && gCurrentPinballGame->hudSpriteBaseY < 240)
{
DmaCopy16(3, src[0], dest[0], 0x60);
}
if (gCurrentPinballGame->hudSpriteBaseY >= 82 && gCurrentPinballGame->hudSpriteBaseY < 248)
{
DmaCopy16(3, src[1], dest[1], 0x60);
}
if (gCurrentPinballGame->hudSpriteBaseY >= 90)
{
DmaCopy16(3, src[2], dest[2], 0x60);
}
}
void DrawRubyEvoArrowProgress(void)
{
s16 sp0[3];
const u8 **src;
const u8 **dest;
if (gCurrentPinballGame->boardState < 3)
{
if (gCurrentPinballGame->evoArrowProgress == 0)
{
sp0[0] = gCurrentPinballGame->hudBlinkPhase * 2;
sp0[1] = 0;
sp0[2] = 0;
}
else if (gCurrentPinballGame->evoArrowProgress == 1)
{
sp0[0] = 3;
sp0[1] = gCurrentPinballGame->hudBlinkPhase + 1;
sp0[2] = gCurrentPinballGame->hudBlinkPhase * 2;
}
else if (gCurrentPinballGame->evoArrowProgress == 2)
{
sp0[0] = 3;
sp0[1] = 3;
sp0[2] = gCurrentPinballGame->hudBlinkPhase + 2;
}
else
{
sp0[0] = 3;
sp0[1] = 3;
sp0[2] = 3;
}
}
else
{
sp0[0] = gCurrentPinballGame->prevTravelArrowTiles[0];
sp0[1] = gCurrentPinballGame->prevTravelArrowTiles[1];
sp0[2] = gCurrentPinballGame->prevTravelArrowTiles[2];
}
src = gRubyEvoArrowTilePtrs[0][sp0[0]];
dest = gRubyEvoArrowTilePtrs[0][4];
if (gCurrentPinballGame->hudSpriteBaseY < 264)
{
DmaCopy16(3, src[0], dest[0], 0x60);
}
DmaCopy16(3, src[1], dest[1], 0x60);
DmaCopy16(3, src[2], dest[2], 0x60);
if (gCurrentPinballGame->hudSpriteBaseY > 120)
{
src = gRubyEvoArrowTilePtrs[1][sp0[1]];
dest = gRubyEvoArrowTilePtrs[1][4];
DmaCopy16(3, src[0], dest[0], 0x60);
DmaCopy16(3, src[1], dest[1], 0x60);
DmaCopy16(3, src[2], dest[2], 0x60);
}
if (gCurrentPinballGame->hudSpriteBaseY > 136)
{
src = gRubyEvoArrowTilePtrs[2][sp0[2]];
dest = gRubyEvoArrowTilePtrs[2][4];
DmaCopy16(3, src[0], dest[0], 0x60);
DmaCopy16(3, src[1], dest[1], 0x60);
DmaCopy16(3, src[2], dest[2], 0x60);
}
}
void DrawRubyCatchArrowProgress(void)
{
s16 sp0[3];
const u8 **src;
const u8 **dest;
if (gCurrentPinballGame->boardState < 3)
{
if (gCurrentPinballGame->catchArrowProgress == 0)
{
sp0[0] = gCurrentPinballGame->hudBlinkPhase * 2;
sp0[1] = 0;
sp0[2] = 0;
}
else if (gCurrentPinballGame->catchArrowProgress == 1)
{
sp0[0] = 3;
sp0[1] = gCurrentPinballGame->hudBlinkPhase + 1;
sp0[2] = gCurrentPinballGame->hudBlinkPhase * 2;
}
else if (gCurrentPinballGame->catchArrowProgress == 2)
{
sp0[0] = 3;
sp0[1] = 3;
sp0[2] = (s16) gCurrentPinballGame->hudBlinkPhase + 2;
}
else
{
sp0[0] = 3;
sp0[1] = 3;
sp0[2] = 3;
}
}
else
{
sp0[0] = gCurrentPinballGame->travelArrowTiles[0];
sp0[1] = gCurrentPinballGame->travelArrowTiles[1];
sp0[2] = gCurrentPinballGame->travelArrowTiles[2];
}
src = gRubyCatchArrowTilePtrs[0][sp0[0]];
dest = gRubyCatchArrowTilePtrs[0][4];
if (gCurrentPinballGame->hudSpriteBaseY < 264)
{
DmaCopy16(3, src[0], dest[0], 0x60);
}
DmaCopy16(3, src[1], dest[1], 0x60);
DmaCopy16(3, src[2], dest[2], 0x60);
if (gCurrentPinballGame->hudSpriteBaseY > 120)
{
src = gRubyCatchArrowTilePtrs[1][sp0[1]];
dest = gRubyCatchArrowTilePtrs[1][4];
DmaCopy16(3, src[0], dest[0], 0x40);
DmaCopy16(3, src[1], dest[1], 0x40);
DmaCopy16(3, src[2], dest[2], 0x60);
}
if (gCurrentPinballGame->hudSpriteBaseY > 136)
{
src = gRubyCatchArrowTilePtrs[2][sp0[2]];
dest = gRubyCatchArrowTilePtrs[2][4];
DmaCopy16(3, src[0], dest[0], 0x40);
DmaCopy16(3, src[1], dest[1], 0x60);
DmaCopy16(3, src[2], dest[2], 0x60);
}
}

403
src/ruby_catch_holes.c Normal file
View File

@ -0,0 +1,403 @@
#include "global.h"
#include "main.h"
#include "m4a.h"
#include "constants/bg_music.h"
#include "constants/ruby_states.h"
#include "functions_ruby.h"
void InitSharpedoCatchMode(void);
void AnimateSharpedoCatchSequence(void);
void InitRubyEvolutionShopMode(void);
void AnimateRubyEvolutionShopSequence(void);
void AnimateRubyEggHatchSequence(void);
void AnimateTotodileEggDelivery(void);
void InitAerodactylEggDelivery(void);
void AnimateAerodactylEggDelivery(void);
void DispatchRubyCatchModeInit(void)
{
if (gMain.modeChangeFlags != MODE_CHANGE_NONE)
return;
switch (gCurrentPinballGame->ballCatchState)
{
case TRAP_CATCH_HOLE:
InitSharpedoCatchMode();
break;
case TRAP_EGG_HOLE:
InitRubyEggHatchMode();
break;
case TRAP_EVO_SHOP_HOLE:
InitRubyEvolutionShopMode();
break;
case TRAP_CENTER_HOLE:
InitCenterTrapMode();
break;
}
gCurrentPinballGame->collisionCooldownTimer = 60;
}
void UpdateRubyCatchModeAnimation(void)
{
if (gCurrentPinballGame->collisionCooldownTimer > 0)
gCurrentPinballGame->collisionCooldownTimer--;
switch (gCurrentPinballGame->ballCatchState)
{
case TRAP_CATCH_HOLE:
AnimateSharpedoCatchSequence(); // Catch hole
break;
case TRAP_EGG_HOLE:
AnimateRubyEggHatchSequence(); //Hatch hole
break;
case TRAP_EVO_SHOP_HOLE:
AnimateRubyEvolutionShopSequence(); //Mart / Evo hole
break;
case TRAP_CENTER_HOLE:
AnimateCenterTrapSequence(); //Center Hole
break;
}
}
void InitSharpedoCatchMode(void)
{
if (gCurrentPinballGame->catchArrowProgress > 1)
{
RequestBoardStateTransition(4);
}
gCurrentPinballGame->cameraScrollOffset = 0;
gCurrentPinballGame->cameraScrollEnabled = 0;
gCurrentPinballGame->cameraScrollTarget = 0;
gCurrentPinballGame->modeAnimTimer = 113;
m4aSongNumStart(SE_UNKNOWN_0xCE);
gCurrentPinballGame->scoreAddedInFrame = 50000;
PlayRumble(8);
}
/*
* Ruby board Sharpedo; during the initation of the catch mode
* Echoes UpdateSapphireWailmerCatchSequence, which is the equivalent 'catch hole' on the sapphire board.
*
* Note: this *does not* affect the start of the catch mode itself.
* When this function is nulled out at UpdateRubyCatchModeAnimation, the banner *doesn't* show, and
* the ball bounces off the sharpedo. However, the grid still shows a picked mon,
* and the mode otherwise works mostly normally, with the exception of affecting
* the 'tilt' behavior, and the collision with the cyndaquil pushback.
*/
void AnimateSharpedoCatchSequence(void)
{
if (gCurrentPinballGame->modeAnimTimer) //Countdown timer; ball grabbed/held while banner shows
{
gCurrentPinballGame->modeAnimTimer--;
if (gCurrentPinballGame->modeAnimTimer > 100)
{
gCurrentPinballGame->ballUpgradeTimerFrozen = 1;
gCurrentPinballGame->ballFrozenState = 1;
gCurrentPinballGame->ball->velocity.x = 0;
gCurrentPinballGame->ball->velocity.y = 0;
gCurrentPinballGame->ball->spinSpeed = 0;
if (gCurrentPinballGame->modeAnimTimer > 108)
{
gCurrentPinballGame->boardEntityActive = 1;
if (gCurrentPinballGame->modeAnimTimer > 110)
{
gCurrentPinballGame->ball->positionQ0.x = 195;
gCurrentPinballGame->ball->positionQ0.y = 222;
}
else
{
gCurrentPinballGame->ball->positionQ0.x = 196;
gCurrentPinballGame->ball->positionQ0.y = 221;
}
//Presumed controling either the message board 'state'/'tile'
// or the sharpedo animation 'state'/tile.
gCurrentPinballGame->catchHoleAnimFrame =6;
}
else if (gCurrentPinballGame->modeAnimTimer > 104)
{
gCurrentPinballGame->ball->positionQ0.x = 197;
gCurrentPinballGame->ball->positionQ0.y = 219;
gCurrentPinballGame->catchHoleAnimFrame = 7;
}
else
{
gCurrentPinballGame->ball->ballHidden = 1;
gCurrentPinballGame->catchHoleAnimFrame = 8;
}
}
else if (gCurrentPinballGame->modeAnimTimer > 20)
{
if (gCurrentPinballGame->modeAnimTimer > 77)
{
gCurrentPinballGame->catchHoleAnimFrame = 9;
if (gCurrentPinballGame->modeAnimTimer < 80)
{
if (gCurrentPinballGame->catchHolePauseTimer != 0)
{
gCurrentPinballGame->catchHolePauseTimer--;
gCurrentPinballGame->modeAnimTimer++;
}
}
}
else if (gCurrentPinballGame->modeAnimTimer > 72)
{
gCurrentPinballGame->catchHoleAnimFrame = 10;
}
else if (gCurrentPinballGame->modeAnimTimer > 67)
{
gCurrentPinballGame->catchHoleAnimFrame = 11;
}
else if (gCurrentPinballGame->modeAnimTimer > 44)
{
gCurrentPinballGame->catchHoleAnimFrame = 12;
}
else if (gCurrentPinballGame->modeAnimTimer > 38)
{
gCurrentPinballGame->catchHoleAnimFrame = 13;
}
else if (gCurrentPinballGame->modeAnimTimer > 28)
{
gCurrentPinballGame->catchHoleAnimFrame = 14;
}
else if (gCurrentPinballGame->modeAnimTimer > 23)
{
gCurrentPinballGame->catchHoleAnimFrame = 15;
}
else {
gCurrentPinballGame->catchHoleAnimFrame = 16;
}
}
else if (gCurrentPinballGame->modeAnimTimer > 18)
{
gCurrentPinballGame->ball->positionQ0.x = 193;
gCurrentPinballGame->ball->positionQ0.y = 226;
gCurrentPinballGame->ball->ballHidden = 0;
gCurrentPinballGame->catchHoleAnimFrame = 17;
}
else if (gCurrentPinballGame->modeAnimTimer > 16)
{
gCurrentPinballGame->ballFrozenState = 0;
gCurrentPinballGame->cameraScrollTarget = 0;
gCurrentPinballGame->cameraScrollEnabled = 1;
gCurrentPinballGame->boardEntityActive = 0;
gCurrentPinballGame->ball->spinSpeed = 0;
gCurrentPinballGame->ball->velocity.x = 0xFF56;
gCurrentPinballGame->ball->velocity.y = 220;
gCurrentPinballGame->ball->positionQ0.x = 190;
gCurrentPinballGame->ball->positionQ0.y = 232;
gCurrentPinballGame->catchHoleAnimFrame = 18;
if (gCurrentPinballGame->modeAnimTimer == 18)
{
m4aSongNumStart(194);
PlayRumble(7);
}
}
else if (gCurrentPinballGame->modeAnimTimer > 12)
{
gCurrentPinballGame->ball->spinSpeed = 0;
gCurrentPinballGame->catchHoleAnimFrame = 19;
}
else if (gCurrentPinballGame->modeAnimTimer > 8)
{
gCurrentPinballGame->ball->spinSpeed = 0;
gCurrentPinballGame->catchHoleAnimFrame = 20;
}
else if (gCurrentPinballGame->modeAnimTimer > 4)
{
gCurrentPinballGame->ball->spinSpeed = 0;
gCurrentPinballGame->catchHoleAnimFrame = 21;
}
else
{
gCurrentPinballGame->catchHoleAnimFrame = 22;
}
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
gCurrentPinballGame->ball->prevPositionQ1 = gCurrentPinballGame->ball->positionQ1;
gCurrentPinballGame->ball->positionQ8.x= gCurrentPinballGame->ball->positionQ0.x << 8;
gCurrentPinballGame->ball->positionQ8.y = gCurrentPinballGame->ball->positionQ0.y << 8;
}
else
{
gCurrentPinballGame->collisionCooldownTimer = 30;
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
gCurrentPinballGame->ballCatchState = NOT_TRAPPED;
gCurrentPinballGame->ballUpgradeTimerFrozen = 0;
gCurrentPinballGame->catchHoleAnimFrame = 0;
}
}
void InitRubyEggHatchMode(void)
{
gCurrentPinballGame->scoreAddedInFrame = 100000;
if (gCurrentPinballGame->eggCaveState == 3)
{
gCurrentPinballGame->eggCaveState = 4;
m4aSongNumStart(SE_UNKNOWN_0xB7);
PlayRumble(7);
gCurrentPinballGame->modeAnimTimer = 500;
}
else if (gCurrentPinballGame->rubyEggDeliveryState !=0)
{
gCurrentPinballGame->modeAnimTimer = 300;
}
else
{
gCurrentPinballGame->modeAnimTimer = 120;
}
gCurrentPinballGame->ballUpgradeTimerFrozen = 1;
}
void AnimateRubyEggHatchSequence(void)
{
u16 modeAnimTimer = gCurrentPinballGame->modeAnimTimer;
if (modeAnimTimer != 0)
{
gCurrentPinballGame->ball->ballHidden = 1;
gCurrentPinballGame->ballFrozenState = 1;
gCurrentPinballGame->modeAnimTimer--;
gCurrentPinballGame->ball->velocity.x = 0;
gCurrentPinballGame->ball->velocity.y = 0;
gCurrentPinballGame->ball->positionQ0.x = 0x58;
gCurrentPinballGame->ball->positionQ0.y = 0x94;
gCurrentPinballGame->ball->spinSpeed = 0;
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
if (gCurrentPinballGame->rubyEggDeliveryState != 1)
return;
if (gCurrentPinballGame->modeAnimTimer > 0xC8)
return;
if (gCurrentPinballGame->modeAnimTimer == 0xC8)
{
if (gCurrentPinballGame->activePortraitType != 0)
gCurrentPinballGame->modeAnimTimer++;
else
{
if (gCurrentPinballGame->scoreHi != 0 && gCurrentPinballGame->rubyPondState == RUBY_POND_STATE_LOTAD)
InitTotodileEggDelivery();
else
InitAerodactylEggDelivery();
}
}
else
{
if (gCurrentPinballGame->scoreHi != 0 && gCurrentPinballGame->rubyPondState == RUBY_POND_STATE_LOTAD)
AnimateTotodileEggDelivery();
else
AnimateAerodactylEggDelivery();
}
if (gCurrentPinballGame->modeAnimTimer <= 9)
gCurrentPinballGame->modeAnimTimer++;
}
else
{
gCurrentPinballGame->ball->ballHidden = 0;
gCurrentPinballGame->ballCatchState = NOT_TRAPPED;
gCurrentPinballGame->ball->positionQ0.x = 0x58;
gCurrentPinballGame->ball->positionQ0.y = 0xA2;
gCurrentPinballGame->ball->spinSpeed = 0;
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
gCurrentPinballGame->ballUpgradeTimerFrozen = 0;
if (gCurrentPinballGame->rubyEggDeliveryState == 2)
{
gCurrentPinballGame->eggCaveState = 3;
gCurrentPinballGame->eggCaveLiftTimer = 0x30;
gCurrentPinballGame->eggCaveExitDelayTimer = 0x1E;
}
else
{
gCurrentPinballGame->ballFrozenState = 0;
gCurrentPinballGame->collisionCooldownTimer = 0x3C;
gCurrentPinballGame->ball->velocity.x = 0x14;
gCurrentPinballGame->ball->velocity.y = 0xC8;
}
}
}
void InitRubyEvolutionShopMode(void)
{
gCurrentPinballGame->shopAnimSlideTimer = 0;
gCurrentPinballGame->shopUISlideOffset = 0;
gCurrentPinballGame->modeAnimTimer = 0xB4;
gCurrentPinballGame->shopEntryTimer = 0xB4;
gCurrentPinballGame->scoreAddedInFrame = 500000;
gMain.blendControl = 0xCE;
gMain.blendBrightness = 0;
gCurrentPinballGame->ballUpgradeTimerFrozen = 1;
}
void AnimateRubyEvolutionShopSequence(void)
{
if (gCurrentPinballGame->modeAnimTimer > 0x18)
{
gCurrentPinballGame->ball->ballHidden = 1;
gCurrentPinballGame->ballFrozenState = 1;
gCurrentPinballGame->modeAnimTimer--;
gCurrentPinballGame->ball->velocity.x = 0;
gCurrentPinballGame->ball->velocity.y = 0;
gCurrentPinballGame->ball->positionQ0.x = 0xDC;
gCurrentPinballGame->ball->positionQ0.y = 0x62;
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
gCurrentPinballGame->ball->positionQ8.x = gCurrentPinballGame->ball->positionQ0.x * 256;
gCurrentPinballGame->ball->positionQ8.y = gCurrentPinballGame->ball->positionQ0.y * 256;
if (gCurrentPinballGame->modeAnimTimer > 0x9B)
gCurrentPinballGame->shopDoorTargetFrame = (gCurrentPinballGame->modeAnimTimer - 0x9C) / 8;
if (gCurrentPinballGame->modeAnimTimer <= 0x31)
gCurrentPinballGame->modeAnimTimer++;
UpdateShopEntryAnimation(gCurrentPinballGame->evolutionShopActive);
return;
}
if (gCurrentPinballGame->modeAnimTimer > 0)
{
gCurrentPinballGame->modeAnimTimer--;
gCurrentPinballGame->shopDoorTargetFrame = (0x18 - gCurrentPinballGame->modeAnimTimer) / 8;
return;
}
gCurrentPinballGame->ball->ballHidden = 0;
gCurrentPinballGame->ballFrozenState = 0;
gCurrentPinballGame->collisionCooldownTimer = 0x3C;
gCurrentPinballGame->ball->velocity.x = 0x60;
gCurrentPinballGame->ball->velocity.y = 0xC0;
gCurrentPinballGame->ball->positionQ0.x = 0xDF;
gCurrentPinballGame->ball->positionQ0.y = 0x63;
gCurrentPinballGame->ball->spinSpeed = 0;
gCurrentPinballGame->ballUpgradeTimerFrozen = 0;
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
gCurrentPinballGame->ballCatchState = NOT_TRAPPED;
gCurrentPinballGame->shopDoorTargetFrame = 0x13;
m4aSongNumStart(SE_UNKNOWN_0xC3);
if (gCurrentPinballGame->evoArrowProgress > 2 && gCurrentPinballGame->evolvablePartySize > 0)
{
RequestBoardStateTransition(6);
}
}

491
src/ruby_trigger_targets.c Normal file
View File

@ -0,0 +1,491 @@
#include "global.h"
#include "m4a.h"
#include "main.h"
#include "constants/bg_music.h"
#include "constants/ruby_states.h"
extern const u8 gSideBumperGfx[][0x100];
extern const s16 gSideBumperGfxFrameIndices[][2];
extern const u16 gSideBumperAnimDurations[][2];
extern const s16 gGulpinAnimData[][5];
extern const u16 gGulpinOamData[146][18];
extern const u8 gRubyStageGulpin_Gfx[][0x180];
extern const s16 gChikoritaFlashFrameIndices[];
extern const u8 gChikoritaExplosionTiles[][0x100];
extern const u8 gChikoritaProjectileTiles[][0x80];
extern const u8 gRubyFlashingDecorationTiles[][0x300];
//ruby
void UpdateChikoritaAttackAnimation(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 index;
s16 var0;
index = 0;
group = &gMain.spriteGroups[14];
if (gCurrentPinballGame->chikoritaProjectileTimer < 60)
{
if (gCurrentPinballGame->chikoritaProjectileTimer >= 27 && gCurrentPinballGame->chikoritaProjectileTimer < 47)
{
index = (gCurrentPinballGame->chikoritaProjectileTimer - 27) / 5;
DmaCopy16(3, gChikoritaExplosionTiles[index], (void *)0x06014280, 0x100);
group->baseX = 176 - gCurrentPinballGame->cameraXOffset;
}
else
{
group->available = 0;
group->baseX = 176 - gCurrentPinballGame->cameraXOffset;
}
}
else
{
if (gCurrentPinballGame->chikoritaProjectileTimer >= 100 && gCurrentPinballGame->chikoritaProjectileTimer < 120)
{
index = (gCurrentPinballGame->chikoritaProjectileTimer - 100) / 5;
DmaCopy16(3, gChikoritaExplosionTiles[index], (void *)0x06014280, 0x100);
group->baseX = 32 - gCurrentPinballGame->cameraXOffset;
}
else
{
group->available = 0;
group->baseX = 32 - gCurrentPinballGame->cameraXOffset;
}
}
if (group->available)
{
group->baseY = 296 - gCurrentPinballGame->cameraYOffset;
if (group->baseY > 180)
group->baseY = 180;
for (i = 0; i < 2; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
group = &gMain.spriteGroups[13];
if (group->available)
{
if (gCurrentPinballGame->chikoritaProjectileTimer < 120)
{
if (gCurrentPinballGame->chikoritaProjectileTimer % 8 == 0)
m4aSongNumStart(SE_UNKNOWN_0xC6);
index = (gCurrentPinballGame->chikoritaProjectileTimer % 16) / 4;
DmaCopy16(3, gChikoritaProjectileTiles[index], (void *)0x06014200, 0x80);
var0 = (gCurrentPinballGame->chikoritaProjectileTimer << 0x10) / 90;
gCurrentPinballGame->chikoritaProjectileVelX -= 2;
gCurrentPinballGame->chikoritaProjectileX += gCurrentPinballGame->chikoritaProjectileVelX;
if (gCurrentPinballGame->chikoritaProjectileTimer < 30)
gCurrentPinballGame->chikoritaProjectileY = gCurrentPinballGame->chikoritaProjectileTimer + (Sin(var0) * 24) / 20000;
else
gCurrentPinballGame->chikoritaProjectileY = 30 + (Sin(var0) * 24) / 20000;
gCurrentPinballGame->chikoritaProjectileTimer++;
if (gCurrentPinballGame->chikoritaProjectileTimer == 27)
{
gMain.spriteGroups[14].available = 1;
m4aSongNumStart(SE_UNKNOWN_0xC7);
if (gCurrentPinballGame->sideBumperBounceCount[1] > 0)
{
gCurrentPinballGame->sideBumperBounceCount[1]++;
}
else
{
gCurrentPinballGame->sideBumperBounceCount[1] = 2;
gCurrentPinballGame->sideBumperAnimTimer[1] = 190;
}
}
if (gCurrentPinballGame->chikoritaProjectileTimer == 100)
{
gMain.spriteGroups[14].available = 1;
m4aSongNumStart(SE_UNKNOWN_0xC7);
if (gCurrentPinballGame->sideBumperBounceCount[0] > 0)
{
gCurrentPinballGame->sideBumperBounceCount[0]++;
}
else
{
gCurrentPinballGame->sideBumperBounceCount[0] = 2;
gCurrentPinballGame->sideBumperAnimTimer[0] = 190;
}
}
}
else
{
gCurrentPinballGame->chikoritaProjectileTimer = 0;
gCurrentPinballGame->chikoritaProjectileX = 0;
gCurrentPinballGame->chikoritaProjectileY = 190;
gCurrentPinballGame->chikoritaProjectileVelX = 100;
gCurrentPinballGame->chikoritaProjectileUnused = 0;
group->available = 0;
}
group->baseX = (gCurrentPinballGame->chikoritaProjectileX / 20) + 71u - gCurrentPinballGame->cameraXOffset;
group->baseY = gCurrentPinballGame->chikoritaProjectileY + 248u - gCurrentPinballGame->cameraYOffset;
if (group->baseY > 190)
group->baseY = 190;
oamSimple = &group->oam[0];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
void AnimateChikoritaSprite(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 index;
group = &gMain.spriteGroups[53];
if (gCurrentPinballGame->chikoritaFlashActive)
{
index = gChikoritaFlashFrameIndices[gCurrentPinballGame->chikoritaFlashTimer / 5];
if (gCurrentPinballGame->chikoritaFlashTimer == 40)
{
gCurrentPinballGame->chikoritaProjectileTimer = 0;
gCurrentPinballGame->chikoritaProjectileX = 0;
gCurrentPinballGame->chikoritaProjectileY = 0;
gCurrentPinballGame->chikoritaProjectileVelX = 100;
gCurrentPinballGame->chikoritaProjectileUnused = 0;
gMain.spriteGroups[13].available = 1;
}
if (gCurrentPinballGame->chikoritaFlashTimer < 54)
gCurrentPinballGame->chikoritaFlashTimer++;
else
gCurrentPinballGame->chikoritaFlashActive = 0;
DmaCopy16(3, gRubyFlashingDecorationTiles[index], (void *)0x06012720, 0x300);
}
else
{
index = (gMain.systemFrameCount % 50) / 25;
if (gCurrentPinballGame->randomSpriteVariantSeed == 1)
{
DmaCopy16(3, gRubyFlashingDecorationTiles[index], (void *)0x06012720, 0x300);
}
}
group->baseX = 55 - gCurrentPinballGame->cameraXOffset;
group->baseY = 221 - gCurrentPinballGame->cameraYOffset;
i = 0;
for (i = 0; i < 2; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
void UpdateGulpinBossState(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 *dst;
const s16 *var0;
s16 index;
var0 = gGulpinAnimData[gCurrentPinballGame->gulpinAnimFrameIndex];
group = &gMain.spriteGroups[57];
group->baseX = 9 - gCurrentPinballGame->cameraXOffset;
group->baseY = 288 - gCurrentPinballGame->cameraYOffset;
if (gCurrentPinballGame->gulpinCurrentLevel > gCurrentPinballGame->seedotCount)
{
if (gCurrentPinballGame->seedotExitSequenceActive)
{
if (gCurrentPinballGame->seedotExitSequenceTimer == 0)
{
gCurrentPinballGame->gulpinAnimFrameIndex = 59;
gCurrentPinballGame->gulpinAnimFrameTimer = 0;
gCurrentPinballGame->seedotExitSequenceTimer++;
}
if (var0[1] > gCurrentPinballGame->gulpinAnimFrameTimer)
{
gCurrentPinballGame->gulpinAnimFrameTimer++;
}
else
{
gCurrentPinballGame->gulpinAnimFrameTimer = 1;
gCurrentPinballGame->gulpinAnimFrameIndex++;
if (gCurrentPinballGame->gulpinAnimFrameIndex == 84)
{
gCurrentPinballGame->gulpinAnimFrameIndex = 0;
gCurrentPinballGame->seedotExitSequenceActive = 0;
gCurrentPinballGame->seedotExitSequenceTimer = 0;
gCurrentPinballGame->gulpinCurrentLevel = 0;
}
if (gCurrentPinballGame->gulpinAnimFrameIndex == 60 || gCurrentPinballGame->gulpinAnimFrameIndex == 69 || gCurrentPinballGame->gulpinAnimFrameIndex == 78)
m4aSongNumStart(SE_UNKNOWN_0xD2);
}
}
}
else if (gCurrentPinballGame->gulpinCurrentLevel < gCurrentPinballGame->seedotCount)
{
if (var0[1] <= gCurrentPinballGame->gulpinAnimFrameTimer)
{
gCurrentPinballGame->gulpinAnimFrameTimer = 1;
gCurrentPinballGame->gulpinAnimFrameIndex++;
if (gCurrentPinballGame->seedotCount == 1)
{
if (gCurrentPinballGame->gulpinAnimFrameIndex == 9)
{
gCurrentPinballGame->gulpinCurrentLevel = 1;
gCurrentPinballGame->gulpinAnimFrameIndex = 84;
}
if (gCurrentPinballGame->gulpinAnimFrameIndex == 6)
m4aSongNumStart(SE_UNKNOWN_0xD2);
}
else if (gCurrentPinballGame->seedotCount == 2)
{
if (gCurrentPinballGame->gulpinAnimFrameIndex == 23)
{
gCurrentPinballGame->gulpinCurrentLevel = 2;
gCurrentPinballGame->gulpinAnimFrameIndex = 95;
}
if (gCurrentPinballGame->gulpinAnimFrameIndex == 20)
m4aSongNumStart(SE_UNKNOWN_0xD2);
}
else if (gCurrentPinballGame->seedotCount == 3)
{
if (gCurrentPinballGame->gulpinAnimFrameIndex == 35)
{
gCurrentPinballGame->gulpinCurrentLevel = 3;
gCurrentPinballGame->gulpinAnimFrameIndex = 35;
RequestBoardStateTransition(7);
}
if (gCurrentPinballGame->gulpinAnimFrameIndex == 32)
m4aSongNumStart(SE_UNKNOWN_0xD2);
}
}
else
{
gCurrentPinballGame->gulpinAnimFrameTimer++;
}
}
else if (gCurrentPinballGame->seedotCount)
{
if (var0[1] > gCurrentPinballGame->gulpinAnimFrameTimer)
{
gCurrentPinballGame->gulpinAnimFrameTimer++;
}
else
{
gCurrentPinballGame->gulpinAnimFrameTimer = 1;
gCurrentPinballGame->gulpinAnimFrameIndex++;
if (gCurrentPinballGame->seedotCount == 1)
{
if (gCurrentPinballGame->gulpinAnimFrameIndex == 95)
gCurrentPinballGame->gulpinAnimFrameIndex = 84;
}
else if (gCurrentPinballGame->seedotCount == 2)
{
if (gCurrentPinballGame->gulpinAnimFrameIndex == 109)
gCurrentPinballGame->gulpinAnimFrameIndex = 95;
}
else if (gCurrentPinballGame->seedotCount == 3)
{
if (gCurrentPinballGame->gulpinAnimFrameIndex == 60)
gCurrentPinballGame->gulpinAnimFrameIndex = 35;
}
}
}
index = var0[0];
DmaCopy16(3, gRubyStageGulpin_Gfx[var0[2]], (void *)0x06013B80, 0x180);
DmaCopy16(3, gRubyStageGulpin_Gfx[var0[3]], (void *)0x06013A00, 0x180);
DmaCopy16(3, gRubyStageGulpin_Gfx[var0[4]], (void *)0x06013880, 0x180);
for (i = 0; i < 6; i++)
{
oamSimple = &group->oam[i];
dst = (u16 *)&gOamBuffer[oamSimple->oamId];
*dst++ = gGulpinOamData[index][i * 3 + 0];
*dst++ = gGulpinOamData[index][i * 3 + 1];
*dst++ = gGulpinOamData[index][i * 3 + 2];
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
}
void UpdateRubySideBumperAnimation(void)
{
s16 i;
for (i = 0; i < 2; i++)
{
if (gCurrentPinballGame->sideBumperBounceCount[i] > 0)
{
if (gSideBumperAnimDurations[gCurrentPinballGame->sideBumperAnimPhase[i]][0] > gCurrentPinballGame->sideBumperAnimTimer[i])
{
gCurrentPinballGame->sideBumperAnimTimer[i]++;
}
else
{
gCurrentPinballGame->sideBumperAnimTimer[i] = 0;
gCurrentPinballGame->sideBumperAnimPhase[i]++;
if (gCurrentPinballGame->sideBumperAnimPhase[i] > 11)
{
gCurrentPinballGame->sideBumperAnimPhase[i] = 0;
gCurrentPinballGame->sideBumperBounceCount[i]--;
}
}
if (gCurrentPinballGame->sideBumperAnimPhase[i] == 1)
gCurrentPinballGame->sideBumperShakeOffset[i] = gCurrentPinballGame->sideBumperAnimTimer[i] / 2;
if (gCurrentPinballGame->sideBumperAnimPhase[i] == 11)
gCurrentPinballGame->sideBumperShakeOffset[i] = 14 - gCurrentPinballGame->sideBumperAnimTimer[i] / 2;
if (gCurrentPinballGame->sideBumperShakeOffset[i] < 3)
gCurrentPinballGame->sideBumperShakeOffset[i] = 3;
}
}
if (gCurrentPinballGame->sideBumperHitFlag)
{
if (gCurrentPinballGame->sideBumperHitFlag == 1)
{
if (gCurrentPinballGame->boardState != 7)
{
if (gCurrentPinballGame->boardState < 3) {
if (gCurrentPinballGame->seedotCount < 3)
{
gCurrentPinballGame->seedotCount++;
if (gCurrentPinballGame->seedotCount == 1)
{
gCurrentPinballGame->gulpinAnimFrameIndex = 0;
gCurrentPinballGame->gulpinAnimFrameTimer = 0;
}
else if (gCurrentPinballGame->seedotCount == 2)
{
gCurrentPinballGame->gulpinAnimFrameIndex = 12;
gCurrentPinballGame->gulpinAnimFrameTimer = 0;
}
else if (gCurrentPinballGame->seedotCount == 3)
{
gCurrentPinballGame->gulpinAnimFrameIndex = 24;
gCurrentPinballGame->gulpinAnimFrameTimer = 0;
gCurrentPinballGame->seedotModeStartDelay = 1;
}
}
}
else
{
if (gCurrentPinballGame->seedotCount < 2)
{
gCurrentPinballGame->seedotCount++;
if (gCurrentPinballGame->seedotCount == 1)
{
gCurrentPinballGame->gulpinAnimFrameIndex = 0;
gCurrentPinballGame->gulpinAnimFrameTimer = 0;
}
else if (gCurrentPinballGame->seedotCount == 2)
{
gCurrentPinballGame->gulpinAnimFrameIndex = 12;
gCurrentPinballGame->gulpinAnimFrameTimer = 0;
}
}
}
}
}
else
{
if (gCurrentPinballGame->rampGateState == 0)
gCurrentPinballGame->rampGateState = 1;
else
gCurrentPinballGame->rampGateState = 0;
}
gCurrentPinballGame->sideBumperBounceCount[0] = 0;
gCurrentPinballGame->sideBumperBounceCount[1] = 0;
gCurrentPinballGame->sideBumperHitFlag = 0;
PlayRumble(7);
m4aSongNumStart(SE_UNKNOWN_0xB7);
gCurrentPinballGame->scoreAddedInFrame = 3000;
gCurrentPinballGame->sideBumperAnimPhase[0] = 0;
gCurrentPinballGame->sideBumperAnimPhase[1] = 0;
gCurrentPinballGame->sideBumperAnimTimer[0] = 0;
gCurrentPinballGame->sideBumperAnimTimer[1] = 0;
gCurrentPinballGame->sideBumperShakeOffset[0] = 3;
gCurrentPinballGame->sideBumperShakeOffset[1] = 3;
}
}
void DrawRubySideBumperSprites(void)
{
s16 i, j;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 index;
for (i = 0; i < 2; i++)
{
index = gSideBumperGfxFrameIndices[gCurrentPinballGame->sideBumperAnimPhase[i]][0];
DmaCopy16(3, gSideBumperGfx[index], (void *)0x06012A20 + i * 0x100, 0x100);
group = &gMain.spriteGroups[59 + i];
if (group->available)
{
int var0 = i * 120 - (gCurrentPinballGame->cameraXOffset - 48);
group->baseX = var0 + ((1 - (i * 2)) * (gCurrentPinballGame->sideBumperShakeOffset[i] - 14));
group->baseY = 301 - gCurrentPinballGame->cameraYOffset;
for (j = 0; j < 3; j++)
{
oamSimple = &group->oam[j];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
}
if (gCurrentPinballGame->seedotModeStartDelay)
{
gCurrentPinballGame->seedotModeStartDelay--;
if (gCurrentPinballGame->seedotModeStartDelay == 0)
{
if (gCurrentPinballGame->activePortraitType)
gCurrentPinballGame->seedotModeStartDelay = 1;
else
gCurrentPinballGame->activePortraitType = 4;
if (gCurrentPinballGame->seedotModeStartDelay == 0)
{
gMain.modeChangeFlags |= MODE_CHANGE_BANNER;
gCurrentPinballGame->bannerDelayTimer = 70;
gCurrentPinballGame->bannerDisplayTimer = 160;
gCurrentPinballGame->cameraYScrollTarget = 0;
gCurrentPinballGame->cameraYAdjust = 0;
gCurrentPinballGame->cameraYScrollSpeed = 0;
gCurrentPinballGame->bannerGfxIndex = 4;
gCurrentPinballGame->bannerActive = 1;
gCurrentPinballGame->bannerPreserveBallState = 0;
gCurrentPinballGame->bannerDisplayDuration = 120;
gCurrentPinballGame->bannerSlidePosition = 0;
gCurrentPinballGame->bannerSlideTimer = 50;
gCurrentPinballGame->bannerSlideVelocity = 0;
DmaCopy16(3, gModeBannerTilemaps[4], (void *)0x06015800, 0x2400);
DmaCopy16(3, gModeBannerPalettes[4], (void *)0x050003C0, 0x20);
gMain.blendControl = 0xCE;
}
}
}
}

View File

@ -4,15 +4,15 @@
#include "constants/bg_music.h"
extern const u8 *gBumperHitCounterTilePtrs[][2];
extern const u8 *gBonusModeIndicatorTilePtrs[][3][2];
extern const u8 *gHatchMachineDrawSegment[][3][2];
extern const u8 *gSapphireBallPowerUpLightTilePtrs[][3];
extern const u8 *gSapphireRouletteSlotTilePtrs[][4];
extern const u8 *gSapphireCatchFlashTilePtrs[][4];
extern const u8 *gSapphireCatchArrowBonusTilePtrs[][5][3];
extern const u8 *gSapphireEvoArrowBonusTilePtrs[][5][3];
extern const u8 *gSapphireCatchArrowTilePtrs[][5][3];
extern const u8 *gSapphireEvoArrowTilePtrs[][5][3];
extern const u8 *gSapphireEvoArrowPaletteTilePtrs[][4];
extern const u8 *gSapphireCatchArrowPaletteTilePtrs[][4];
extern const u8 *gSapphireCoinRewardAltTilePtrs[][5][3];
extern const u8 *gSapphireCoinRewardTilePtrs[][5][3];
extern const u8 *gSapphireModeTimerDisplayTilePtrs[][4];
extern const u8 *gSapphireHoleIndicatorTilePtrs[][4];
extern const u8 *gSapphireCatchLightTilePtrs[][7][2];
@ -21,245 +21,14 @@ extern const u8 *gSapphireTrapIndicatorTilePtrs[][2];
extern const u16 gSlingshotHitFrameIndices[];
extern const u8 *gSapphireSlingshotTilePtrs[][3][5];
extern const u8 *gSapphireProgressDigitTilePtrs[][4];
extern const u8 *gSapphireCatchArrowTilePtrs[][5][3];
extern const u8 *gSapphireEvoArrowTilePtrs[][5][3];
extern const u8 *gSapphireCoinRewardTilePtrs[][5][3];
extern const s16 gCoinRewardLevelTimerThresholds[];
void UpdateCoinRewardTimer(void)
{
if (gCurrentPinballGame->coinRewardLevel > 0)
{
if (gCurrentPinballGame->coinRewardLevelTimer < gCoinRewardLevelTimerThresholds[gCurrentPinballGame->coinRewardLevel - 1])
{
gCurrentPinballGame->coinRewardLevelTimer++;
}
else
{
gCurrentPinballGame->coinRewardLevelTimer = 0;
gCurrentPinballGame->coinRewardLevel--;
}
}
}
void DrawCoinRewardMeter(void)
{
s16 sp0[3];
const u8 **src;
const u8 **dest;
if (gCurrentPinballGame->coinRewardLevel == 0)
{
sp0[0] = gCurrentPinballGame->hudBlinkPhase * 2;
sp0[1] = gCurrentPinballGame->hudBlinkPhase;
sp0[2] = 0;
}
else if (gCurrentPinballGame->coinRewardLevel == 1)
{
sp0[0] = 3;
sp0[1] = gCurrentPinballGame->hudBlinkPhase + 1;
sp0[2] = gCurrentPinballGame->hudBlinkPhase * 2;
}
else if (gCurrentPinballGame->coinRewardLevel == 2)
{
sp0[0] = 3;
sp0[1] = 3;
sp0[2] = gCurrentPinballGame->hudBlinkPhase + 2;
}
else
{
sp0[0] = 3;
sp0[1] = 3;
sp0[2] = 3;
}
src = gSapphireCoinRewardTilePtrs[0][sp0[0]];
dest = gSapphireCoinRewardTilePtrs[0][4];
if (gCurrentPinballGame->hudSpriteBaseY >= 42 && gCurrentPinballGame->hudSpriteBaseY < 208)
{
DmaCopy16(3, src[0], dest[0], 0x60);
}
if (gCurrentPinballGame->hudSpriteBaseY >= 50 && gCurrentPinballGame->hudSpriteBaseY < 216)
{
DmaCopy16(3, src[1], dest[1], 0x60);
}
src = gSapphireCoinRewardTilePtrs[1][sp0[1]];
dest = gSapphireCoinRewardTilePtrs[1][4];
if (gCurrentPinballGame->hudSpriteBaseY >= 58 && gCurrentPinballGame->hudSpriteBaseY < 224)
{
DmaCopy16(3, src[0], dest[0], 0x60);
}
if (gCurrentPinballGame->hudSpriteBaseY >= 66 && gCurrentPinballGame->hudSpriteBaseY < 232)
{
DmaCopy16(3, src[1], dest[1], 0x60);
}
src = gSapphireCoinRewardTilePtrs[2][sp0[2]];
dest = gSapphireCoinRewardTilePtrs[2][4];
if (gCurrentPinballGame->hudSpriteBaseY >= 74 && gCurrentPinballGame->hudSpriteBaseY < 240)
{
DmaCopy16(3, src[0], dest[0], 0x60);
}
if (gCurrentPinballGame->hudSpriteBaseY >= 82 && gCurrentPinballGame->hudSpriteBaseY < 248)
{
DmaCopy16(3, src[1], dest[1], 0x60);
}
if (gCurrentPinballGame->hudSpriteBaseY >= 90)
{
DmaCopy16(3, src[2], dest[2], 0x60);
}
}
void DrawEvoArrowProgress(void)
{
s16 sp0[3];
const u8 **src;
const u8 **dest;
if (gCurrentPinballGame->boardState < 3)
{
if (gCurrentPinballGame->evoArrowProgress == 0)
{
sp0[0] = gCurrentPinballGame->hudBlinkPhase * 2;
sp0[1] = 0;
sp0[2] = 0;
}
else if (gCurrentPinballGame->evoArrowProgress == 1)
{
sp0[0] = 3;
sp0[1] = gCurrentPinballGame->hudBlinkPhase + 1;
sp0[2] = gCurrentPinballGame->hudBlinkPhase * 2;
}
else if (gCurrentPinballGame->evoArrowProgress == 2)
{
sp0[0] = 3;
sp0[1] = 3;
sp0[2] = gCurrentPinballGame->hudBlinkPhase + 2;
}
else
{
sp0[0] = 3;
sp0[1] = 3;
sp0[2] = 3;
}
}
else
{
sp0[0] = gCurrentPinballGame->prevTravelArrowTiles[0];
sp0[1] = gCurrentPinballGame->prevTravelArrowTiles[1];
sp0[2] = gCurrentPinballGame->prevTravelArrowTiles[2];
}
src = gSapphireEvoArrowTilePtrs[0][sp0[0]];
dest = gSapphireEvoArrowTilePtrs[0][4];
if (gCurrentPinballGame->hudSpriteBaseY < 264)
{
DmaCopy16(3, src[0], dest[0], 0x60);
}
DmaCopy16(3, src[1], dest[1], 0x60);
DmaCopy16(3, src[2], dest[2], 0x60);
if (gCurrentPinballGame->hudSpriteBaseY > 120)
{
src = gSapphireEvoArrowTilePtrs[1][sp0[1]];
dest = gSapphireEvoArrowTilePtrs[1][4];
DmaCopy16(3, src[0], dest[0], 0x60);
DmaCopy16(3, src[1], dest[1], 0x60);
DmaCopy16(3, src[2], dest[2], 0x60);
}
if (gCurrentPinballGame->hudSpriteBaseY > 136)
{
src = gSapphireEvoArrowTilePtrs[2][sp0[2]];
dest = gSapphireEvoArrowTilePtrs[2][4];
DmaCopy16(3, src[0], dest[0], 0x60);
DmaCopy16(3, src[1], dest[1], 0x60);
DmaCopy16(3, src[2], dest[2], 0x60);
}
}
void DrawCatchArrowProgress(void)
{
s16 sp0[3];
const u8 **src;
const u8 **dest;
if (gCurrentPinballGame->boardState < 3)
{
if (gCurrentPinballGame->catchArrowProgress == 0)
{
sp0[0] = gCurrentPinballGame->hudBlinkPhase * 2;
sp0[1] = 0;
sp0[2] = 0;
}
else if (gCurrentPinballGame->catchArrowProgress == 1)
{
sp0[0] = 3;
sp0[1] = gCurrentPinballGame->hudBlinkPhase + 1;
sp0[2] = gCurrentPinballGame->hudBlinkPhase * 2;
}
else if (gCurrentPinballGame->catchArrowProgress == 2)
{
sp0[0] = 3;
sp0[1] = 3;
sp0[2] = (s16) gCurrentPinballGame->hudBlinkPhase + 2;
}
else
{
sp0[0] = 3;
sp0[1] = 3;
sp0[2] = 3;
}
}
else
{
sp0[0] = gCurrentPinballGame->travelArrowTiles[0];
sp0[1] = gCurrentPinballGame->travelArrowTiles[1];
sp0[2] = gCurrentPinballGame->travelArrowTiles[2];
}
src = gSapphireCatchArrowTilePtrs[0][sp0[0]];
dest = gSapphireCatchArrowTilePtrs[0][4];
if (gCurrentPinballGame->hudSpriteBaseY < 264)
{
DmaCopy16(3, src[0], dest[0], 0x60);
}
DmaCopy16(3, src[1], dest[1], 0x60);
DmaCopy16(3, src[2], dest[2], 0x60);
if (gCurrentPinballGame->hudSpriteBaseY > 120)
{
src = gSapphireCatchArrowTilePtrs[1][sp0[1]];
dest = gSapphireCatchArrowTilePtrs[1][4];
DmaCopy16(3, src[0], dest[0], 0x40);
DmaCopy16(3, src[1], dest[1], 0x40);
DmaCopy16(3, src[2], dest[2], 0x60);
}
if (gCurrentPinballGame->hudSpriteBaseY > 136)
{
src = gSapphireCatchArrowTilePtrs[2][sp0[2]];
dest = gSapphireCatchArrowTilePtrs[2][4];
DmaCopy16(3, src[0], dest[0], 0x40);
DmaCopy16(3, src[1], dest[1], 0x60);
DmaCopy16(3, src[2], dest[2], 0x60);
}
}
void UpdateSapphireBoardAnimations(void)
{
gCurrentPinballGame->hudBlinkPhase = (gCurrentPinballGame->hudAnimFrameCounter % 40) / 20;
gCurrentPinballGame->hudAnimFrameCounter++;
AnimateBonusModeIndicators();
AnimateHatchMachineSpinner();
if (gCurrentPinballGame->hudSpriteBaseY > 83)
AnimateSapphireCatchArrowPalette();
@ -271,10 +40,10 @@ void UpdateSapphireBoardAnimations(void)
AnimateRubyBallPowerUpSequence();
if (gCurrentPinballGame->hudSpriteBaseY < 112)
DrawBallPowerUpLights();
DrawSapphireBallPowerUpLights();
if (gCurrentPinballGame->hudSpriteBaseY >= 64 && gCurrentPinballGame->hudSpriteBaseY < 254)
AnimateCatchArrowPaletteFlash();
AnimateSapphireCatchArrowPaletteFlash();
if (gCurrentPinballGame->hudSpriteBaseY >= 27 && gCurrentPinballGame->hudSpriteBaseY < 211)
{
@ -284,12 +53,12 @@ void UpdateSapphireBoardAnimations(void)
if (gCurrentPinballGame->hudSpriteBaseY > 104)
{
DrawEvoArrowBonusField();
DrawCatchArrowBonusField();
DrawSapphireEvoArrowProgress();
DrawSapphireCatchArrowProgress();
}
if (gCurrentPinballGame->hudSpriteBaseY > 72)
DrawCoinRewardMeterAlt();
DrawSapphireCoinRewardMeter();
UpdateCoinRewardTimer();
if (gCurrentPinballGame->hudSpriteBaseY > 110)
@ -306,7 +75,7 @@ void UpdateSapphireBoardAnimations(void)
DrawSapphireModeTimerDisplay();
if (gCurrentPinballGame->hudSpriteBaseY >= 8 && gCurrentPinballGame->hudSpriteBaseY < 182)
AnimateBumperHitCounter();
AnimatePelliperBumper();
if (gCurrentPinballGame->saverTimeRemaining && gCurrentPinballGame->ballCatchState == 0)
gCurrentPinballGame->saverTimeRemaining--;
@ -483,7 +252,7 @@ void DrawSapphireModeTimerDisplay(void)
}
}
void DrawCoinRewardMeterAlt(void)
void DrawSapphireCoinRewardMeter(void)
{
s16 sp0[3];
const u8 **src;
@ -514,8 +283,8 @@ void DrawCoinRewardMeterAlt(void)
sp0[2] = 2;
}
src = gSapphireCoinRewardAltTilePtrs[0][sp0[0]];
dest = gSapphireCoinRewardAltTilePtrs[0][3];
src = gSapphireCoinRewardTilePtrs[0][sp0[0]];
dest = gSapphireCoinRewardTilePtrs[0][3];
if (gCurrentPinballGame->hudSpriteBaseY < 240)
{
DmaCopy16(3, src[0], dest[0], 0x40);
@ -528,8 +297,8 @@ void DrawCoinRewardMeterAlt(void)
if (gCurrentPinballGame->hudSpriteBaseY > 88)
{
src = gSapphireCoinRewardAltTilePtrs[1][sp0[1]];
dest = gSapphireCoinRewardAltTilePtrs[1][3];
src = gSapphireCoinRewardTilePtrs[1][sp0[1]];
dest = gSapphireCoinRewardTilePtrs[1][3];
if (gCurrentPinballGame->hudSpriteBaseY < 254)
{
DmaCopy16(3, src[0], dest[0], 0x40);
@ -542,8 +311,8 @@ void DrawCoinRewardMeterAlt(void)
if (gCurrentPinballGame->hudSpriteBaseY > 96)
{
src = gSapphireCoinRewardAltTilePtrs[2][sp0[2]];
dest = gSapphireCoinRewardAltTilePtrs[2][3];
src = gSapphireCoinRewardTilePtrs[2][sp0[2]];
dest = gSapphireCoinRewardTilePtrs[2][3];
if (gCurrentPinballGame->hudSpriteBaseY < 264)
{
DmaCopy16(3, src[0], dest[0], 0x40);
@ -614,7 +383,7 @@ void AnimateSapphireEvoArrowPalette(void)
}
}
void DrawEvoArrowBonusField(void)
void DrawSapphireEvoArrowProgress(void)
{
s16 sp0[3];
const u8 **src;
@ -655,8 +424,8 @@ void DrawEvoArrowBonusField(void)
}
src = gSapphireEvoArrowBonusTilePtrs[0][sp0[0]];
dest = gSapphireEvoArrowBonusTilePtrs[0][4];
src = gSapphireEvoArrowTilePtrs[0][sp0[0]];
dest = gSapphireEvoArrowTilePtrs[0][4];
if (gCurrentPinballGame->hudSpriteBaseY < 264)
{
DmaCopy16(3, src[0], dest[0], 0x60);
@ -666,23 +435,23 @@ void DrawEvoArrowBonusField(void)
if (gCurrentPinballGame->hudSpriteBaseY > 120)
{
src = gSapphireEvoArrowBonusTilePtrs[1][sp0[1]];
dest = gSapphireEvoArrowBonusTilePtrs[1][4];
src = gSapphireEvoArrowTilePtrs[1][sp0[1]];
dest = gSapphireEvoArrowTilePtrs[1][4];
DmaCopy16(3, src[0], dest[0], 0x60);
DmaCopy16(3, src[1], dest[1], 0x60);
DmaCopy16(3, src[2], dest[2], 0x60);
}
if (gCurrentPinballGame->hudSpriteBaseY > 136) {
src = gSapphireEvoArrowBonusTilePtrs[2][sp0[2]];
dest = gSapphireEvoArrowBonusTilePtrs[2][4];
src = gSapphireEvoArrowTilePtrs[2][sp0[2]];
dest = gSapphireEvoArrowTilePtrs[2][4];
DmaCopy16(3, src[0], dest[0], 0x60);
DmaCopy16(3, src[1], dest[1], 0x60);
DmaCopy16(3, src[2], dest[2], 0x40);
}
}
void DrawCatchArrowBonusField(void)
void DrawSapphireCatchArrowProgress(void)
{
s16 sp0[3];
const u8 **src;
@ -722,8 +491,8 @@ void DrawCatchArrowBonusField(void)
sp0[2] = gCurrentPinballGame->travelArrowTiles[2];
}
src = gSapphireCatchArrowBonusTilePtrs[0][sp0[0]];
dest = gSapphireCatchArrowBonusTilePtrs[0][4];
src = gSapphireCatchArrowTilePtrs[0][sp0[0]];
dest = gSapphireCatchArrowTilePtrs[0][4];
if (gCurrentPinballGame->hudSpriteBaseY < 264)
{
DmaCopy16(3, src[0], dest[0], 0x60);
@ -734,8 +503,8 @@ void DrawCatchArrowBonusField(void)
if (gCurrentPinballGame->hudSpriteBaseY > 120)
{
src = gSapphireCatchArrowBonusTilePtrs[1][sp0[1]];
dest = gSapphireCatchArrowBonusTilePtrs[1][4];
src = gSapphireCatchArrowTilePtrs[1][sp0[1]];
dest = gSapphireCatchArrowTilePtrs[1][4];
DmaCopy16(3, src[0], dest[0], 0x40);
DmaCopy16(3, src[1], dest[1], 0x40);
DmaCopy16(3, src[2], dest[2], 0x60);
@ -743,15 +512,15 @@ void DrawCatchArrowBonusField(void)
if (gCurrentPinballGame->hudSpriteBaseY > 136)
{
src = gSapphireCatchArrowBonusTilePtrs[2][sp0[2]];
dest = gSapphireCatchArrowBonusTilePtrs[2][4];
src = gSapphireCatchArrowTilePtrs[2][sp0[2]];
dest = gSapphireCatchArrowTilePtrs[2][4];
DmaCopy16(3, src[0], dest[0], 0x40);
DmaCopy16(3, src[1], dest[1], 0x60);
DmaCopy16(3, src[2], dest[2], 0x40);
}
}
void AnimateCatchArrowPaletteFlash(void)
void AnimateSapphireCatchArrowPaletteFlash(void)
{
s16 index;
const u8 **src;
@ -830,7 +599,7 @@ void AnimateSapphireRouletteSlot(void)
}
}
void DrawBallPowerUpLights(void)
void DrawSapphireBallPowerUpLights(void)
{
s16 i;
@ -842,14 +611,14 @@ void DrawBallPowerUpLights(void)
}
}
void AnimateBonusModeIndicators(void)
void AnimateHatchMachineSpinner(void)
{
s16 i;
s16 srcIndex;
const u8 **src;
const u8 **dest;
if (gCurrentPinballGame->holeLetterSystemState != 3)
if (gCurrentPinballGame->sapphireHatchMachineState != 3)
{
for (i = 0; i < 10; i++)
{
@ -866,15 +635,15 @@ void AnimateBonusModeIndicators(void)
srcIndex = 0;
}
src = gBonusModeIndicatorTilePtrs[i][srcIndex];
dest = gBonusModeIndicatorTilePtrs[i][2];
src = gHatchMachineDrawSegment[i][srcIndex];
dest = gHatchMachineDrawSegment[i][2];
DmaCopy16(3, src[0], dest[0], 0x40);
DmaCopy16(3, src[1], dest[1], 0x40);
}
}
}
void AnimateBumperHitCounter(void)
void AnimatePelliperBumper(void)
{
s16 index;
const u8 **src;

View File

@ -0,0 +1,516 @@
#include "global.h"
#include "m4a.h"
#include "main.h"
#include "constants/bg_music.h"
#include "constants/main_board.h"
extern const s16 gPelipperIdleFrameIndices[];
extern const s16 gPelipperSwallowAnimData[][3];
extern const s8 gPelipperFlyAnimTable[][2];
extern const u8 gPelipper_Gfx[][0x480];
extern const u16 gPelipperPondSpritesheetOam[20][4][3];
extern const s16 gWailmerAnimFrameMap[][2];
extern const u8 gSapphireBoardWailmer_Gfx[][0x300];
extern const u16 gWailmerSpritesheetOam[26][2][3];
extern const u8 gSapphireBoardZigzagoonFx_Gfx[];
extern const s16 gZigzagoonAnimKeyframes[][3];
extern const u8 gSapphireBoardZigzagoon_Gfx[][0x380];
extern const u16 gSapphireBoardZigzagoonSpritesheetOam[42][3][3];
extern const u16 gZigzagoonFxSpritesheetOam[14][7][3];
extern const u8 gZigzagoonShockWallIndicator_Gfx[][0x200];
extern struct SongHeader se_unk_e3;
void DecrementPelipperTimer(void)
{
if (gCurrentPinballGame->pelipperState == 1)
{
if (gCurrentPinballGame->pelipperFrameTimer)
gCurrentPinballGame->pelipperFrameTimer--;
else
gCurrentPinballGame->pelipperState = 0;
}
}
void UpdatePelipperPondEntity(void)
{
s16 i;
struct SpriteGroup *group = &gMain.spriteGroups[60];
struct OamDataSimple *oamSimple;
u16 *dst;
const u16 *src;
s16 var_sl;
s16 sp0;
s16 index;
var_sl = 0;
sp0 = 0;
switch (gCurrentPinballGame->pelipperState)
{
case 0:
gCurrentPinballGame->pelipperYBobOffset = 0;
var_sl = (gCurrentPinballGame->globalAnimFrameCounter % 50) / 25;
gCurrentPinballGame->pelipperPosX = 0;
gCurrentPinballGame->pelipperPosY = 0;
break;
case 1:
var_sl = gPelipperIdleFrameIndices[(gCurrentPinballGame->globalAnimFrameCounter % 40) / 10];
gCurrentPinballGame->pelipperPosX = 0;
gCurrentPinballGame->pelipperPosY = 0;
gCurrentPinballGame->pelipperSwallowAnimIndex = 0;
gCurrentPinballGame->pelipperSwallowSubTimer = 0;
if (gCurrentPinballGame->boardState > 2)
{
gCurrentPinballGame->pelipperState = 0;
var_sl = 0;
}
break;
case 2:
var_sl = 4;
break;
case 3:
if (gCurrentPinballGame->pelipperFrameTimer < 3)
{
if (gCurrentPinballGame->pelipperFrameTimer == 0)
{
gCurrentPinballGame->ballUpgradeTimerFrozen = 1;
gCurrentPinballGame->ballFrozenState = 1;
gCurrentPinballGame->ball->velocity.x = 0;
gCurrentPinballGame->ball->velocity.y = 0;
gCurrentPinballGame->ball->spinSpeed = 0;
m4aSongNumStart(SE_UNKNOWN_0xE2);
PlayRumble(7);
gCurrentPinballGame->scoreAddedInFrame = 100000;
}
gCurrentPinballGame->ball->positionQ0.x = 156;
gCurrentPinballGame->ball->positionQ0.y = 121 + gCurrentPinballGame->pelipperFrameTimer * 2;
var_sl = 4;
}
else if (gCurrentPinballGame->pelipperFrameTimer < 23)
{
gCurrentPinballGame->ball->positionQ0.x = 157;
gCurrentPinballGame->ball->positionQ0.y = 134;
gCurrentPinballGame->ball->ballHidden = 1;
var_sl = 5;
}
else
{
gCurrentPinballGame->pelipperState = 4;
gCurrentPinballGame->pelipperFrameTimer = 0;
var_sl = 2;
}
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
gCurrentPinballGame->ball->positionQ8.x = gCurrentPinballGame->ball->positionQ0.x << 8;
gCurrentPinballGame->ball->positionQ8.y = gCurrentPinballGame->ball->positionQ0.y << 8;
gCurrentPinballGame->pelipperFrameTimer++;
gCurrentPinballGame->pelipperSfxTimer = 0;
break;
case 4:
if (gPelipperSwallowAnimData[gCurrentPinballGame->pelipperSwallowAnimIndex][2] > gCurrentPinballGame->pelipperSwallowSubTimer)
{
gCurrentPinballGame->pelipperSwallowSubTimer++;
}
else
{
gCurrentPinballGame->pelipperSwallowSubTimer = 0;
gCurrentPinballGame->pelipperSwallowAnimIndex++;
if (gCurrentPinballGame->pelipperSwallowAnimIndex == 21)
{
gCurrentPinballGame->pelipperSwallowAnimIndex = 20;
gCurrentPinballGame->pelipperState = 5;
gCurrentPinballGame->pelipperFrameTimer = 0;
}
if (gCurrentPinballGame->pelipperSwallowAnimIndex == 1)
m4aSongNumStart(SE_UNKNOWN_0xE3);
}
sp0 = gPelipperSwallowAnimData[gCurrentPinballGame->pelipperSwallowAnimIndex][0];
var_sl = gPelipperSwallowAnimData[gCurrentPinballGame->pelipperSwallowAnimIndex][1];
if (gCurrentPinballGame->pelipperSfxTimer++ % 35 == 34)
m4aSongNumStart(SE_UNKNOWN_0xE3);
break;
case 5:
if (gCurrentPinballGame->pelipperFrameTimer == 0)
{
gCurrentPinballGame->pelipperPosX = -360;
gCurrentPinballGame->pelipperPosY = -200;
}
index = (gCurrentPinballGame->pelipperFrameTimer % 26) / 2;
var_sl = gPelipperFlyAnimTable[index][0];
gCurrentPinballGame->pelipperYBobOffset = gPelipperFlyAnimTable[index][1] * 10;
gCurrentPinballGame->pelipperFlyVelX = -12;
gCurrentPinballGame->pelipperFlyVelY = -10;
gCurrentPinballGame->pelipperPosX += gCurrentPinballGame->pelipperFlyVelX;
gCurrentPinballGame->pelipperPosY += gCurrentPinballGame->pelipperFlyVelY;
gCurrentPinballGame->ball->positionQ0.x = gCurrentPinballGame->pelipperPosX / 10 + 157;
gCurrentPinballGame->ball->positionQ0.y = gCurrentPinballGame->pelipperPosY / 10 + 134;
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
gCurrentPinballGame->ball->positionQ8.x = gCurrentPinballGame->ball->positionQ0.x << 8;
gCurrentPinballGame->ball->positionQ8.y = gCurrentPinballGame->ball->positionQ0.y << 8;
gCurrentPinballGame->pelipperFrameTimer++;
if (gCurrentPinballGame->ball->positionQ0.y < -12)
{
if (gCurrentPinballGame->bumperHitsSinceReset > 99)
{
gCurrentPinballGame->bumperHitsSinceReset = 0;
gCurrentPinballGame->pelipperState = 6;
gCurrentPinballGame->pelipperFrameTimer = 65;
m4aMPlayAllStop();
}
else
{
gCurrentPinballGame->pelipperFrameTimer = 0;
gCurrentPinballGame->pelipperState = 7;
}
}
if (gCurrentPinballGame->pelipperSfxTimer++ % 35 == 34)
m4aSongNumStart(SE_UNKNOWN_0xE3);
break;
case 6:
gCurrentPinballGame->startButtonDisabled = 1;
var_sl = gPelipperFlyAnimTable[0][0];
if (gCurrentPinballGame->pelipperFrameTimer == 65)
{
m4aSongNumStart(SE_WARP);
gMain.blendControl = 0x9E;
}
if (gCurrentPinballGame->pelipperFrameTimer)
{
gCurrentPinballGame->pelipperFrameTimer--;
gMain.blendBrightness = 16 - gCurrentPinballGame->pelipperFrameTimer / 4;
if (gCurrentPinballGame->pelipperFrameTimer == 0)
{
gCurrentPinballGame->nextBonusField = FIELD_SPHEAL;
gCurrentPinballGame->bonusReturnState = 2;
gCurrentPinballGame->arrowProgressPreserved = gCurrentPinballGame->evoArrowProgress;
gCurrentPinballGame->catchModeArrows = gCurrentPinballGame->catchArrowProgress;
TransitionToBonusField();
}
}
break;
case 7:
gCurrentPinballGame->pelipperPosX = -1880;
gCurrentPinballGame->pelipperPosY = -800;
gCurrentPinballGame->pelipperFlyVelX = 82;
gCurrentPinballGame->pelipperFlyVelY = 0;
gCurrentPinballGame->pelipperFrameTimer = 0;
gCurrentPinballGame->pelipperState = 8;
var_sl = 13;
sp0 = 9;
break;
case 8:
var_sl = (gCurrentPinballGame->pelipperFrameTimer % 24) / 6 + 13;
gCurrentPinballGame->pelipperYBobOffset = (Sin(gCurrentPinballGame->pelipperFrameTimer * 0x400) * 240) / 20000;
if (gCurrentPinballGame->pelipperFrameTimer == 0)
m4aSongNumStart(SE_UNKNOWN_0xE4);
if (gCurrentPinballGame->pelipperFrameTimer < 40)
{
gCurrentPinballGame->pelipperPosX += gCurrentPinballGame->pelipperFlyVelX;
gCurrentPinballGame->pelipperPosY += gCurrentPinballGame->pelipperFlyVelY;
}
else if (gCurrentPinballGame->pelipperFrameTimer >= 70)
{
gCurrentPinballGame->pelipperFrameTimer = 0;
gCurrentPinballGame->pelipperState = 9;
gCurrentPinballGame->pelipperPosX = 1200;
gCurrentPinballGame->pelipperPosY = -1000;
m4aSongNumStart(SE_UNKNOWN_0xE3);
gCurrentPinballGame->pelipperSfxTimer = 0;
}
if (gCurrentPinballGame->pelipperFrameTimer == 13)
{
gCurrentPinballGame->ball->ballHidden = 0;
gCurrentPinballGame->pelipperBallDropVelX = 5;
gCurrentPinballGame->pelipperBallDropVelY = -25;
gCurrentPinballGame->pelipperBallDropPosX = (gCurrentPinballGame->pelipperPosX / 10 + 157) * 10;
gCurrentPinballGame->pelipperBallDropPosY = (gCurrentPinballGame->pelipperPosY / 10 + 134) * 10;
gCurrentPinballGame->ball->oamPriority = 1;
}
if (gCurrentPinballGame->ballFrozenState)
{
if (gCurrentPinballGame->pelipperFrameTimer < 13)
{
gCurrentPinballGame->ball->positionQ0.x = gCurrentPinballGame->pelipperPosX / 10 + 157;
gCurrentPinballGame->ball->positionQ0.y = gCurrentPinballGame->pelipperPosY / 10 + 134;
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
gCurrentPinballGame->ball->positionQ8.x = gCurrentPinballGame->ball->positionQ0.x << 8;
gCurrentPinballGame->ball->positionQ8.y = gCurrentPinballGame->ball->positionQ0.y << 8;
}
else
{
gCurrentPinballGame->pelipperBallDropVelY += 2;
gCurrentPinballGame->pelipperBallDropPosX += gCurrentPinballGame->pelipperBallDropVelX;
gCurrentPinballGame->pelipperBallDropPosY += gCurrentPinballGame->pelipperBallDropVelY;
gCurrentPinballGame->ball->positionQ0.x = gCurrentPinballGame->pelipperBallDropPosX / 10;
gCurrentPinballGame->ball->positionQ0.y = gCurrentPinballGame->pelipperBallDropPosY / 10;
if (gCurrentPinballGame->ball->positionQ0.y >= 91)
{
gCurrentPinballGame->ball->positionQ0.y = 91;
gCurrentPinballGame->ballUpgradeTimerFrozen = 0;
gCurrentPinballGame->ballFrozenState = 0;
gCurrentPinballGame->ball->velocity.x = 128;
gCurrentPinballGame->ball->velocity.y = 256;
gCurrentPinballGame->ball->oamPriority = 3;
gCurrentPinballGame->boardLayerDepth = 0;
m4aSongNumStart(SE_UNKNOWN_0xE5);
PlayRumble(7);
}
gCurrentPinballGame->ball->positionQ1.x = gCurrentPinballGame->ball->positionQ0.x * 2;
gCurrentPinballGame->ball->positionQ1.y = gCurrentPinballGame->ball->positionQ0.y * 2;
gCurrentPinballGame->ball->positionQ8.x = gCurrentPinballGame->ball->positionQ0.x << 8;
gCurrentPinballGame->ball->positionQ8.y = gCurrentPinballGame->ball->positionQ0.y << 8;
}
}
sp0 = 9;
gCurrentPinballGame->pelipperFrameTimer++;
break;
case 9:
index = (gCurrentPinballGame->pelipperFrameTimer % 26) / 2;
var_sl = gPelipperFlyAnimTable[index][0] + 4;
gCurrentPinballGame->pelipperYBobOffset = gPelipperFlyAnimTable[index][1];
gCurrentPinballGame->pelipperFlyVelX = -12;
gCurrentPinballGame->pelipperFlyVelY = 10;
if (gCurrentPinballGame->pelipperFrameTimer < 100)
{
gCurrentPinballGame->pelipperPosX += gCurrentPinballGame->pelipperFlyVelX;
gCurrentPinballGame->pelipperPosY += gCurrentPinballGame->pelipperFlyVelY;
}
else
{
gCurrentPinballGame->pelipperFrameTimer = 0;
gCurrentPinballGame->pelipperState = 10;
MPlayStart(&gMPlayInfo_SE1, &se_unk_e3);
}
if (gCurrentPinballGame->pelipperSfxTimer++ % 35 == 34)
MPlayStart(&gMPlayInfo_SE1, &se_unk_e3);
gCurrentPinballGame->pelipperFrameTimer++;
break;
case 10:
gCurrentPinballGame->pelipperYBobOffset = 0;
gCurrentPinballGame->pelipperState = 0;
gCurrentPinballGame->pelipperFrameTimer = 0;
var_sl = 0;
break;
}
if (group->available)
{
DmaCopy16(3, gPelipper_Gfx[var_sl], (void *)0x060122A0, 0x480);
group->baseX = gCurrentPinballGame->pelipperPosX / 10 + 146 - gCurrentPinballGame->cameraXOffset;
group->baseY = gCurrentPinballGame->pelipperPosY / 10 + 110 - gCurrentPinballGame->cameraYOffset + gCurrentPinballGame->pelipperYBobOffset / 10;
for (i = 0; i < 4; i++)
{
oamSimple = &group->oam[i];
dst = (u16*)&gOamBuffer[oamSimple->oamId];
src = gPelipperPondSpritesheetOam[sp0][i];
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
}
}
void AnimateWailmerEntity(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 *dst;
const u16 *src;
s16 index;
s16 var0;
index = (gCurrentPinballGame->globalAnimFrameCounter % 32) / 16;
group = &gMain.spriteGroups[75];
if (gCurrentPinballGame->catchHoleAnimFrame)
index = gCurrentPinballGame->catchHoleAnimFrame;
var0 = gWailmerAnimFrameMap[index][0];
index = gWailmerAnimFrameMap[index][1];
group->baseX = 164 - gCurrentPinballGame->cameraXOffset;
group->baseY = 166 - gCurrentPinballGame->cameraYOffset;
DmaCopy16(3, gSapphireBoardWailmer_Gfx[index], (void *)0x06012720, 0x300);
for (i = 0; i < 2; i++)
{
oamSimple = &group->oam[i];
dst = (u16*)&gOamBuffer[oamSimple->oamId];
src = gWailmerSpritesheetOam[var0][i];
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
}
void UpdateZigzagoonEntity(void)
{
s16 var0;
switch (gCurrentPinballGame->zigzagoonState)
{
case 0:
gCurrentPinballGame->zigzagoonGfxFrame = (gCurrentPinballGame->globalAnimFrameCounter % 50) / 25 + 2;
gCurrentPinballGame->zigzagoonOamFrame = gCurrentPinballGame->zigzagoonGfxFrame + 1;
gCurrentPinballGame->zigzagoonShockWallActive = 0;
break;
case 1:
var0 = gCurrentPinballGame->globalAnimFrameCounter % 33;
if (var0 < 13)
{
gCurrentPinballGame->zigzagoonGfxFrame = 0;
gCurrentPinballGame->zigzagoonOamFrame = 0;
}
else if (var0 < 20)
{
gCurrentPinballGame->zigzagoonGfxFrame = 9;
gCurrentPinballGame->zigzagoonOamFrame = 1;
}
else if (var0 < 26)
{
gCurrentPinballGame->zigzagoonGfxFrame = 1;
gCurrentPinballGame->zigzagoonOamFrame = 2;
}
else
{
gCurrentPinballGame->zigzagoonGfxFrame = 9;
gCurrentPinballGame->zigzagoonOamFrame = 1;
}
if (gCurrentPinballGame->ballCatchState != TRAP_CENTER_HOLE)
gCurrentPinballGame->zigzagoonShockWallActive = 0;
break;
case 2:
gCurrentPinballGame->zigzagoonShockWallActive = 0;
gCurrentPinballGame->zigzagoonAnimKeyframeIndex = 0;
gCurrentPinballGame->sapphireBumperAnimFrame = 0;
gCurrentPinballGame->zigzagoonState = 3;
gCurrentPinballGame->zigzagoonFxFrame = 0;
gMain.spriteGroups[27].available = 1;
gCurrentPinballGame->activePortraitType = 22;
DmaCopy16(3, gSapphireBoardZigzagoonFx_Gfx, (void *)0x06015800, 0xC00);
m4aSongNumStart(SE_UNKNOWN_0xEC);
gCurrentPinballGame->scoreAddedInFrame = 5000;
break;
case 3:
if (gZigzagoonAnimKeyframes[gCurrentPinballGame->zigzagoonAnimKeyframeIndex][1] > gCurrentPinballGame->sapphireBumperAnimFrame)
{
gCurrentPinballGame->sapphireBumperAnimFrame++;
}
else
{
gCurrentPinballGame->zigzagoonAnimKeyframeIndex++;
gCurrentPinballGame->sapphireBumperAnimFrame = 0;
if (gCurrentPinballGame->zigzagoonAnimKeyframeIndex > 16)
{
gCurrentPinballGame->zigzagoonAnimKeyframeIndex = 16;
gCurrentPinballGame->zigzagoonState = 4;
}
}
gCurrentPinballGame->zigzagoonOamFrame = gZigzagoonAnimKeyframes[gCurrentPinballGame->zigzagoonAnimKeyframeIndex][0];
gCurrentPinballGame->zigzagoonGfxFrame = gZigzagoonAnimKeyframes[gCurrentPinballGame->zigzagoonAnimKeyframeIndex][2];
if (gCurrentPinballGame->zigzagoonAnimKeyframeIndex < 6)
gCurrentPinballGame->zigzagoonFxFrame = gCurrentPinballGame->zigzagoonAnimKeyframeIndex + 1;
else
gCurrentPinballGame->zigzagoonFxFrame = 0;
break;
case 4:
gCurrentPinballGame->activePortraitType = 0;
gMain.spriteGroups[27].available = 0;
gCurrentPinballGame->zigzagoonState = 0;
break;
}
}
void DrawZigzagoonAndRouletteStopPrompt(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 *dst;
const u16 *src;
s16 index;
group = &gMain.spriteGroups[26];
if (group->available)
{
group->baseX = 198 - gCurrentPinballGame->cameraXOffset;
group->baseY = gCurrentPinballGame->sapphireBumperTimer + 284 - gCurrentPinballGame->cameraYOffset;
index = gCurrentPinballGame->zigzagoonGfxFrame;
DmaCopy16(3, gSapphireBoardZigzagoon_Gfx[index], (void *)0x06012A20, 0x380);
index = gCurrentPinballGame->zigzagoonOamFrame;
for (i = 0; i < 3; i++)
{
oamSimple = &group->oam[i];
dst = (u16*)&gOamBuffer[oamSimple->oamId];
src = gSapphireBoardZigzagoonSpritesheetOam[index][i];
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
}
group = &gMain.spriteGroups[27];
if (group->available)
{
group->baseX = 198 - gCurrentPinballGame->cameraXOffset;
group->baseY = 284 - gCurrentPinballGame->cameraYOffset;
index = gCurrentPinballGame->zigzagoonFxFrame;
for (i = 0; i < 7; i++)
{
oamSimple = &group->oam[i];
dst = (u16*)&gOamBuffer[oamSimple->oamId];
src = gZigzagoonFxSpritesheetOam[index][i];
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
}
group = &gMain.spriteGroups[70];
if (group->available)
{
group->baseX = 206 - gCurrentPinballGame->cameraXOffset;
if (gCurrentPinballGame->zigzagoonShockWallActive)
{
group->baseY = 260 - gCurrentPinballGame->cameraYOffset;
index = (gCurrentPinballGame->globalAnimFrameCounter % 50) / 25;
DmaCopy16(3, &gZigzagoonShockWallIndicator_Gfx[index], (void *)0x06014FA0, 0x200);
}
else
{
group->baseY = 200;
}
oamSimple = &group->oam[0];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}

View File

@ -13,8 +13,18 @@ extern const u16 gShopSignTransitionFrames[][14];
extern const u16 gShopSignIntroFrames[][4];
extern const u16 gShopSignLoopFrames[][5];
extern const s16 gHoleAnimKeyframeData[][2];
extern const u8 gHoleIndicatorTileGfx[][0x440];
void InitSapphireEggCaveState(void)
extern const u8 gSplashEffectTileGfx[][0x100];
extern struct Vector16 gSplashEffectPositions[];
extern const s16 gSplashEffectFrameDurations[][2];
extern const s16 gSplashEffectTileIndices[][2];
extern const u8 gSapphireShopSignPalettes[][0x20];
extern const u8 gSapphireShopSignTileGfx[][0x480];
void InitSapphireEggHatchState(void)
{
gCurrentPinballGame->eggAnimationPhase = 1;
gCurrentPinballGame->prevEggAnimFrame = 0;
@ -24,7 +34,7 @@ void InitSapphireEggCaveState(void)
gCurrentPinballGame->portraitOffsetY = 700;
}
void UpdateSapphireEggCaveAnimation(void)
void UpdateSapphireEggHatchAnimation(void)
{
s16 i;
struct SpriteGroup *group;
@ -160,7 +170,7 @@ void UpdateSapphireEggCaveAnimation(void)
if (group->available)
{
group->baseX = 192 - gCurrentPinballGame->cameraXOffset;
if (gCurrentPinballGame->holeLetterSystemState > 2 && gMain.modeChangeFlags)
if (gCurrentPinballGame->sapphireHatchMachineState > 2 && gMain.modeChangeFlags)
group->baseY = 56 - gCurrentPinballGame->cameraYOffset;
else
group->baseY = 200;
@ -525,3 +535,224 @@ void UpdateSapphireShopSignAnimation(void)
}
}
}
void DrawSapphireShopSignSprite(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 index;
group = &gMain.spriteGroups[69];
if (group->available)
{
group->baseX = 16 - gCurrentPinballGame->cameraXOffset;
group->baseY = 115 - gCurrentPinballGame->cameraYOffset;
index = gCurrentPinballGame->shopSignPaletteIndex + gCurrentPinballGame->activePaletteIndex * 3;
DmaCopy16(3, gSapphireShopSignPalettes[index], (void *)0x05000300, 0x20);
DmaCopy16(3, gSapphireShopSignTileGfx[gCurrentPinballGame->shopSignFrame], (void *) 0x06014B20, 0x480);
for (i = 0; i < 2; i++)
{
oamSimple = &group->oam[i];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
}
void UpdateSapphireEggMachine(void)
{
s16 i, j;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
s16 index;
switch (gCurrentPinballGame->sapphireHatchMachineState)
{
case 0:
if (gCurrentPinballGame->hatchMachineNewHit)
{
if (gCurrentPinballGame->boardState < 3)
{
if (gCurrentPinballGame->sapphireHatchMachineFrameIx < 3)
{
gCurrentPinballGame->sapphireHatchMachineFrameIx++;
gCurrentPinballGame->scoreAddedInFrame = 20000;
m4aSongNumStart(SE_UNKNOWN_0xDE);
}
else
{
gMain.modeChangeFlags |= MODE_CHANGE_BANNER;
gCurrentPinballGame->bannerDelayTimer = 0;
gCurrentPinballGame->bannerDisplayTimer = 920;
gCurrentPinballGame->cameraYScrollTarget = 0;
gCurrentPinballGame->cameraYAdjust = 0;
gCurrentPinballGame->cameraYScrollSpeed = 0;
gCurrentPinballGame->bannerGfxIndex = 0;
gCurrentPinballGame->bannerActive = 1;
gCurrentPinballGame->bannerPreserveBallState = 0;
gCurrentPinballGame->sapphireHatchMachineState = 1;
gCurrentPinballGame->holeAnimFrameCounter = 0;
m4aMPlayStop(&gMPlayInfo_BGM);
gCurrentPinballGame->scoreAddedInFrame = 200000;
m4aSongNumStart(SE_UNKNOWN_0xDF);
}
}
else
{
if (gCurrentPinballGame->sapphireHatchMachineFrameIx < 3)
{
gCurrentPinballGame->sapphireHatchMachineFrameIx++;
gCurrentPinballGame->scoreAddedInFrame = 20000;
m4aSongNumStart(SE_UNKNOWN_0xDE);
}
}
index = gCurrentPinballGame->sapphireHatchMachineFrameIx;
DmaCopy16(3, &gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
gCurrentPinballGame->hatchMachineNewHit = 0;
}
break;
case 1:
if (gCurrentPinballGame->holeAnimFrameCounter < 270)
{
index = (gCurrentPinballGame->holeAnimFrameCounter % 60) / 30 + 4;
DmaCopy16(3, &gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
}
else
{
index = 0;
DmaCopy16(3, &gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
gCurrentPinballGame->sapphireHatchMachineState = 2;
gCurrentPinballGame->sapphireHatchMachineFrameIx = 0;
}
if (gCurrentPinballGame->holeAnimFrameCounter == 60)
{
m4aSongNumStart(MUS_EGG_MODE_START);
gCurrentPinballGame->catchArrowPaletteActive = 0;
gCurrentPinballGame->eggAnimationPhase = 5;
gCurrentPinballGame->eggAnimFrameIndex = 12;
gCurrentPinballGame->eggFrameTimer = 0;
}
gCurrentPinballGame->holeAnimFrameCounter++;
break;
case 3:
if (gHoleAnimKeyframeData[gCurrentPinballGame->sapphireHatchMachineFrameIx][1] > gCurrentPinballGame->holeAnimFrameCounter)
{
gCurrentPinballGame->holeAnimFrameCounter++;
}
else
{
gCurrentPinballGame->holeAnimFrameCounter = 0;
gCurrentPinballGame->sapphireHatchMachineFrameIx++;
if (gCurrentPinballGame->sapphireHatchMachineFrameIx == 10)
gCurrentPinballGame->sapphireHatchMachineState = 4;
if (gCurrentPinballGame->sapphireHatchMachineFrameIx == 6)
m4aSongNumStart(SE_UNKNOWN_0xE0);
index = gHoleAnimKeyframeData[gCurrentPinballGame->sapphireHatchMachineFrameIx][0];
DmaCopy16(3, &gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
}
if (gCurrentPinballGame->sapphireHatchMachineFrameIx < 6)
{
gCurrentPinballGame->walkMonYPos = 280;
}
else
{
gCurrentPinballGame->walkMonYPos += 6;
if (gCurrentPinballGame->sapphireHatchMachineState == 4)
gCurrentPinballGame->walkMonYPos = gCurrentPinballGame->walkMonYPos + 20;
}
break;
case 4:
if (gCurrentPinballGame->sapphirerubyEggDeliveryState && gCurrentPinballGame->hatchMachineNewHit)
{
gMain.modeChangeFlags |= MODE_CHANGE_BANNER;
gCurrentPinballGame->bannerDelayTimer = 0;
gCurrentPinballGame->bannerDisplayTimer = 160;
gCurrentPinballGame->cameraYScrollTarget = 0;
gCurrentPinballGame->cameraYAdjust = 0;
gCurrentPinballGame->cameraYScrollSpeed = 0;
gCurrentPinballGame->bannerGfxIndex = 0;
gCurrentPinballGame->bannerActive = 1;
gCurrentPinballGame->bannerPreserveBallState = 0;
gCurrentPinballGame->sapphireHatchMachineState = 5;
gCurrentPinballGame->holeAnimFrameCounter = 0;
gCurrentPinballGame->sapphireHatchMachineFrameIx = 10;
m4aSongNumStart(SE_UNKNOWN_0xE0);
gCurrentPinballGame->eggAnimationPhase = 1;
gCurrentPinballGame->portraitOffsetX = 2080;
gCurrentPinballGame->portraitOffsetY = 960;
}
gCurrentPinballGame->hatchMachineNewHit = 0;
break;
case 5:
if (gHoleAnimKeyframeData[gCurrentPinballGame->sapphireHatchMachineFrameIx][1] > gCurrentPinballGame->holeAnimFrameCounter)
{
gCurrentPinballGame->holeAnimFrameCounter++;
}
else
{
gCurrentPinballGame->holeAnimFrameCounter = 0;
gCurrentPinballGame->sapphireHatchMachineFrameIx++;
if (gCurrentPinballGame->sapphireHatchMachineFrameIx == 15)
gCurrentPinballGame->sapphireHatchMachineState = 6;
index = gHoleAnimKeyframeData[gCurrentPinballGame->sapphireHatchMachineFrameIx][0];
DmaCopy16(3, gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
}
if (gCurrentPinballGame->sapphireHatchMachineFrameIx == 14 && gCurrentPinballGame->holeAnimFrameCounter == 10)
m4aSongNumStart(SE_UNKNOWN_0xE1);
if (gCurrentPinballGame->portraitOffsetY > 700)
gCurrentPinballGame->portraitOffsetY -= 5;
else
gCurrentPinballGame->portraitOffsetY = 700;
break;
case 6:
gCurrentPinballGame->sapphireHatchMachineFrameIx = 0;
gCurrentPinballGame->holeAnimFrameCounter = 0;
gCurrentPinballGame->sapphireHatchMachineState = 0;
gCurrentPinballGame->sapphirerubyEggDeliveryState = 0;
break;
}
for (i = 0; i < 4; i++)
{
group = &gMain.spriteGroups[47 + i];
if (group->available)
{
if (gSplashEffectFrameDurations[gCurrentPinballGame->splashEffectFrameIndex[i]][0] > gCurrentPinballGame->splashEffectFrameTimer[i])
{
gCurrentPinballGame->splashEffectFrameTimer[i]++;
}
else
{
gCurrentPinballGame->splashEffectFrameTimer[i] = 0;
gCurrentPinballGame->splashEffectFrameIndex[i]++;
if (gCurrentPinballGame->splashEffectFrameIndex[i] == 6)
{
group->available = 0;
gCurrentPinballGame->splashEffectFrameIndex[i] = 5;
}
}
index = gSplashEffectTileIndices[gCurrentPinballGame->splashEffectFrameIndex[i]][0];
DmaCopy16(3, &gSplashEffectTileGfx[index], (void *)0x060140a0 + i * 0x100, 0x100);
group->baseX = gSplashEffectPositions[gCurrentPinballGame->splashEffectPositionIndex[i]].x - gCurrentPinballGame->cameraXOffset;
group->baseY = gSplashEffectPositions[gCurrentPinballGame->splashEffectPositionIndex[i]].y - gCurrentPinballGame->cameraYOffset;
for (j = 0; j < 3; j++)
{
oamSimple = &group->oam[j];
gOamBuffer[oamSimple->oamId].x = oamSimple->xOffset + group->baseX;
gOamBuffer[oamSimple->oamId].y = oamSimple->yOffset + group->baseY;
}
}
}
}

768
src/save_and_restore_game.c Normal file
View File

@ -0,0 +1,768 @@
#include "global.h"
#include "agb_sram.h"
#include "main.h"
#include "m4a.h"
extern u8 gBoardGfxBuffer[];
extern u8 gBoardBGTileBufferAlt[];
extern const u8 gMainBoardBallSave_Gfx[];
extern const u8 gMainBoardEndOfBall_Gfx[];
extern const u8 gBoardActionTilesGfx[];
extern const u8 gEggModeTilesGfx[];
extern const u8 gAreaRouletteSelectedFx_Gfx[];
extern const u8 gCaptureModeTilesGfx[];
extern const u8 gCaptureScreenTilesGfx[];
extern const u8 gHatchRevealTilesGfx[];
extern const u8 gHatchStartTilesGfx[];
extern const u8 gHatchStage2TilesGfx[];
extern const u8 gHatchStage3TilesGfx[];
extern const u8 gHatchFinalTilesGfx[];
extern const u8 *gEvoItemAppear_GfxList[];
extern const s16 gEvoShopAnimFrames[][7];
extern const u16 gShopCursorToItemMap[];
extern const u8 gRubyBoardBonusGfx[];
extern const u8 gRubyBoardBonusObjPalette[];
extern const u8 gRubyBoardHatchCave_Gfx[][0x480];
extern const u8 gRubyFlashingDecorationTiles[][0x300];
extern const u8 gRubyBoardSharpedo_Gfx[][0x260];
extern const u8 gRubyFlashingTiles_Secondary[][0x100];
extern const u8 gRubyBoardShopDoor_Gfx[][0x180];
extern const u8 gRubyStageCyndaquil_Gfx[][0x280];
extern const u8 gRubyBoardShop_Gfx[][0x500];
extern const u8 gSapphireBoardBonusGfx[];
extern const u8 gSapphireBoardBonusObjPalette[];
extern const u8 gSapphireCatchTilesGfx[];
extern const u8 gSapphireBoardZigzagoonFx_Gfx[];
extern const u8 gAlphabetTilesGfx[][0x40];
extern const u8 gSpaceTileGfx[0x40];
extern const u8 gDecimalDigitTilesGfx[][0x40];
extern const u8 gPokemonNameDisplayGfx[];
extern const s16 gCaughtTextChars[];
extern const u8 gHoleIndicatorTileGfx[][0x440];
extern const s16 gHoleAnimKeyframeData[][2];
extern const u8 gKecleonBonusClear_Gfx[0x2000];
extern const u8 gKyogreBonusClear_Gfx[0x2000];
extern const u8 gGroudonBoardBackgroundGfx[0x2000];
extern const u8 gGroudonBonusClear_Gfx[0x2000];
extern const u8 gRayquazaSkyBackgroundGfx[0x2800];
extern const u8 gRayquazaWindBoardGfx[0x1C00];
extern const u8 gRayquazaBonusClear_Gfx[0x2000];
extern const u8 gRayquazaSpriteSheet[0x860];
extern const u8 gSphealResultsScreenGfx[0x800];
void SaveGameStateSnapshot(s16);
void RestoreFieldSpecificGraphics(void);
void RestoreMainFieldDynamicGraphics(void);
void RestoreRubyBoardTileGraphics(void);
void RestoreSapphireBoardTileGraphics(void);
void nullsub_18(void);
void RestoreDusclopsBonusGraphics(void);
void RestoreKecleonBonusGraphics(void);
void RestoreKyogreBonusGraphics(void);
void RestoreGroudonBonusGraphics(void);
void RestoreRayquazaBonusGraphics(void);
void RestoreSphealBonusGraphics(void);
void SaveGameStateSnapshot(s16 arg0)
{
s16 i;
u16 *var0;
if (gMPlayInfo_BGM.status >= 0)
{
gCurrentPinballGame->savedBgmSongHeader = gMPlayInfo_BGM.songHeader;
m4aMPlayStop(&gMPlayInfo_BGM);
}
else
{
gCurrentPinballGame->savedBgmSongHeader = NULL;
}
for (i = 0; i < 100; i++)
gCurrentPinballGame->savedSpriteAvailability[gMain.isBonusField][i] = gMain.spriteGroups[i].available;
DmaCopy16(3, (void *)OBJ_PLTT, gCurrentPinballGame->savedObjPalette[gMain.isBonusField], OBJ_PLTT_SIZE);
DmaCopy16(3, (void *)BG_PLTT, gCurrentPinballGame->savedBgPalette[gMain.isBonusField], BG_PLTT_SIZE);
if (!arg0)
return;
gCurrentPinballGame->bgOffsets0 = gMain.bgOffsets[0];
gCurrentPinballGame->bgOffsets1 = gMain.bgOffsets[1];
gCurrentPinballGame->bgOffsets2 = gMain.bgOffsets[2];
gCurrentPinballGame->bgOffsets3 = gMain.bgOffsets[3];
gCurrentPinballGame->savedField = gMain.selectedField;
gCurrentPinballGame->savedTempField = gMain.tempField;
gCurrentPinballGame->savedIsBonusField = gMain.isBonusField;
gCurrentPinballGame->savedModeChangeFlags = gMain.modeChangeFlags;
gCurrentPinballGame->savedDebugMenuCursorIndex = gMain.debugMenuCursorIndex;
gCurrentPinballGame->savedPendingModeChangeType = gMain.pendingModeChangeType;
gCurrentPinballGame->savedAnimationTimer = gMain.animationTimer;
gCurrentPinballGame->savedModeChangeDelayTimer = gMain.modeChangeDelayTimer;
gCurrentPinballGame->savedShopPanelActive = gMain.shopPanelActive;
gCurrentPinballGame->savedShopPanelSlideOffset = gMain.shopPanelSlideOffset;
gCurrentPinballGame->savedBlendControl = gCurrentPinballGame->pauseBlendControl;
gCurrentPinballGame->savedBlendAlpha = gCurrentPinballGame->pauseBlendAlpha;
gCurrentPinballGame->savedBlendBrightness = gCurrentPinballGame->pauseBlendBrightness;
gCurrentPinballGame->savedScoreOverlayActive = gCurrentPinballGame->pauseScoreOverlayActive;
gCurrentPinballGame->savedVCount = gCurrentPinballGame->pauseVCount;
gCurrentPinballGame->ballSpeed = gMain_saveData.ballSpeed;
for (i = 0; i < NUM_EREADER_CARDS; i++)
gCurrentPinballGame->eReaderBonuses[i] = gMain.eReaderBonuses[i];
}
void SaveGameToSram(void)
{
gCurrentPinballGame->saveDataValid = 1;
WriteAndVerifySramFast((const u8 *)gCurrentPinballGame, (void *)SRAM + 0x544, sizeof(*gCurrentPinballGame));
}
void RestoreGameState(u16 arg0)
{
s16 i, j;
s16 var0, var1;
int var2;
if (arg0 == 1)
{
ReadSramFast((void *)SRAM + 0x544, (u8 *)gCurrentPinballGame, sizeof(*gCurrentPinballGame));
}
else if (arg0 == 2)
{
DmaCopy16(3, gBoardConfig.pinballGame, gCurrentPinballGame, sizeof(*gCurrentPinballGame));
gCurrentPinballGame->ball = &gCurrentPinballGame->ballStates[0];
gCurrentPinballGame->secondaryBall = &gCurrentPinballGame->ballStates[0];
var2 = gMain.idleDemoVariant;
if ((var2 & 0x3) == 1)
{
gCurrentPinballGame->pikaSpinMomentum = 0;
gCurrentPinballGame->kickbackAnimFrameTimer = 0;
gCurrentPinballGame->kickbackFrameId = 0;
gCurrentPinballGame->pikaChargeTarget = 0;
gCurrentPinballGame->pikaChargeProgress = 0;
gCurrentPinballGame->prevChargeFillValue = 0;
gCurrentPinballGame->chargeFillValue = 0;
gCurrentPinballGame->chargeIndicatorXOffset = 0;
gCurrentPinballGame->chargeIndicatorYOffset = -4;
gCurrentPinballGame->chargeIndicatorScaleX = 256;
gCurrentPinballGame->chargeIndicatorScaleY = 256;
gCurrentPinballGame->chargeFillAnimTimer = 0;
gCurrentPinballGame->fullChargeSlideAnimTimer = 0;
}
}
if (arg0 != 0)
{
gMain.selectedField = gCurrentPinballGame->savedField;
gMain.tempField = gCurrentPinballGame->savedTempField;
gMain.isBonusField = gCurrentPinballGame->savedIsBonusField;
gMain.modeChangeFlags = gCurrentPinballGame->savedModeChangeFlags;
gMain.debugMenuCursorIndex = gCurrentPinballGame->savedDebugMenuCursorIndex;
gMain.pendingModeChangeType = gCurrentPinballGame->savedPendingModeChangeType;
gMain.animationTimer = gCurrentPinballGame->savedAnimationTimer;
gMain.modeChangeDelayTimer = gCurrentPinballGame->savedModeChangeDelayTimer;
gMain.shopPanelActive = gCurrentPinballGame->savedShopPanelActive;
gMain.shopPanelSlideOffset = gCurrentPinballGame->savedShopPanelSlideOffset;
gMain.blendControl = gCurrentPinballGame->savedBlendControl;
gMain.blendAlpha = gCurrentPinballGame->savedBlendAlpha;
gMain.blendBrightness = gCurrentPinballGame->savedBlendBrightness;
gMain.scoreOverlayActive = gCurrentPinballGame->savedScoreOverlayActive;
gMain.vCount = gCurrentPinballGame->savedVCount;
gMain.bgOffsets[0] = gCurrentPinballGame->bgOffsets0;
gMain.bgOffsets[1] = gCurrentPinballGame->bgOffsets1;
gMain.bgOffsets[2] = gCurrentPinballGame->bgOffsets2;
gMain.bgOffsets[3] = gCurrentPinballGame->bgOffsets3;
for (i = 0; i < NUM_EREADER_CARDS; i++)
gMain.eReaderBonuses[i] = gCurrentPinballGame->eReaderBonuses[i];
gCurrentPinballGame->startButtonDisabled = 1;
if (arg0 == 1 && gMain.selectedField < MAIN_FIELD_COUNT)
{
gCurrentPinballGame->cameraYViewport = gCurrentPinballGame->cameraBaseY +
gCurrentPinballGame->tiltYOffset +
gCurrentPinballGame->cameraScrollOffset +
gCurrentPinballGame->cameraYAdjust;
}
}
else
{
gCurrentPinballGame->cameraYViewport = gCurrentPinballGame->hudSpriteBaseY;
}
gCurrentPinballGame->fadeSubState = 0;
gMain.continueFromSave = 0;
loadFieldBoardGraphics();
if (gMain.selectedField == FIELD_RUBY && gCurrentPinballGame->boardCollisionConfigChanged)
SetBoardCollisionConfig(1);
if (gMain.selectedField < MAIN_FIELD_COUNT)
{
for (i = 0; i < 22; i++)
{
var0 = i + gCurrentPinballGame->ballLaunchSpeed;
var1 = (i + 10 + gCurrentPinballGame->ballLaunchSpeed) % 22;
if (var0 < 32)
{
DmaCopy16(3, &gBoardGfxBuffer[var0 * 0x400], (void *)0x6008000 + var1 * 0x400, 0x400);
}
else
{
var0 -= 32;
DmaCopy16(3, &gBoardBGTileBufferAlt[var0 * 0x400], (void *)0x6008000 + var1 * 0x400, 0x400);
}
}
}
for (i = 0; i < 0x800; i++)
gBG0TilemapBuffer[i] = 0x1FF;
DmaCopy16(3, gBG0TilemapBuffer, (void *)0x6002000, 0x1000);
if (gMain.scoreOverlayActive)
{
if (gCurrentPinballGame->boardState == 6)
{
for (j = 0; j <= gCurrentPinballGame->cutsceneTilemapColumn; j++)
{
for (i = 2; i < 12; i++)
gBG0TilemapBuffer[(i + 15) * 0x20 + j] = 0xC100;
}
}
else
{
for (j = 0; j <= gCurrentPinballGame->cutsceneTilemapColumn; j++)
{
for (i = 1; i < 11; i++)
gBG0TilemapBuffer[(i + 15) * 0x20 + j] = 0xC100;
}
}
DmaCopy16(3, gBG0TilemapBuffer, (void *)0x6002000, 0x800);
}
DmaCopy16(3, gCurrentPinballGame->savedObjPalette[gMain.isBonusField], (void *)OBJ_PLTT, OBJ_PLTT_SIZE);
DmaCopy16(3, gCurrentPinballGame->savedBgPalette[gMain.isBonusField], (void *)BG_PLTT, BG_PLTT_SIZE);
DmaCopy16(3, &gBallPalettes[gCurrentPinballGame->ballUpgradeType], (void *)OBJ_PLTT + 0x20, 0x20);
RestoreFieldSpecificGraphics();
switch (gMain.selectedField)
{
case FIELD_RUBY:
RubyBoardProcess_0A_50848();
LoadShopItemGraphics(gCurrentPinballGame->evolutionShopActive);
break;
case FIELD_SAPPHIRE:
SapphireBoardProcess_0A_50AD4();
break;
case FIELD_DUSCLOPS:
DusclopsBoardProcess_0A_50D48();
break;
case FIELD_KECLEON:
KecleonBoardProcess_0A_50DE0();
break;
case FIELD_KYOGRE:
KyogreBoardProcess_0A_50F04();
break;
case FIELD_GROUDON:
GroudonBoardProcess_0A_50FD4();
break;
case FIELD_RAYQUAZA:
RayquazaBoardProcess_0A_51090();
break;
case FIELD_SPHEAL:
SphealBoardProcess_0A_51150();
break;
}
for (i = 0; i < 100; i++)
gMain.spriteGroups[i].available = gCurrentPinballGame->savedSpriteAvailability[gMain.isBonusField][i];
if (arg0 == 1)
{
gCurrentPinballGame->saveDataValid = 0;
WriteAndVerifySramFast((const u8 *)gCurrentPinballGame, (void *)SRAM + 0x544, sizeof(gCurrentPinballGame->saveDataValid));
}
}
void RestoreFieldSpecificGraphics(void)
{
s16 i;
struct PokemonSpecies *species;
const u16 *var1;
s16 var2, var3;
switch (gMain.selectedField)
{
case FIELD_RUBY:
RestoreMainFieldDynamicGraphics();
RestoreRubyBoardTileGraphics();
break;
case FIELD_SAPPHIRE:
RestoreMainFieldDynamicGraphics();
RestoreSapphireBoardTileGraphics();
break;
case FIELD_DUSCLOPS:
nullsub_18();
RestoreDusclopsBonusGraphics();
break;
case FIELD_KECLEON:
nullsub_18();
RestoreKecleonBonusGraphics();
break;
case FIELD_KYOGRE:
nullsub_18();
RestoreKyogreBonusGraphics();
break;
case FIELD_GROUDON:
nullsub_18();
RestoreGroudonBonusGraphics();
break;
case FIELD_RAYQUAZA:
nullsub_18();
RestoreRayquazaBonusGraphics();
break;
case FIELD_SPHEAL:
nullsub_18();
RestoreSphealBonusGraphics();
break;
}
switch (gCurrentPinballGame->activePortraitType - 1)
{
case 0:
if (gCurrentPinballGame->outLanePikaPosition == 2 && gCurrentPinballGame->outLaneSide == 2)
{
DmaCopy16(3, gPikaSaverFullCoverageGfx, (void *)0x6015800, 0x2400);
}
else
{
DmaCopy16(3, gPikaSaverPartialCoverageGfx, (void *)0x6015800, 0x2400);
}
break;
case 1:
DmaCopy16(3, gEggModeTilesGfx, (void *)0x6015800, 0x1000);
break;
case 2:
DmaCopy16(3, gCaptureModeTilesGfx, (void *)0x6015800, 0xCA0);
break;
case 3:
DmaCopy16(3, gModeBannerTilemaps[gCurrentPinballGame->bannerGfxIndex], (void *)0x6015800, 0x25E0);
break;
case 4:
DmaCopy16(3, gHatchStartTilesGfx, (void *)0x6015800, 0x2000);
break;
case 5:
DmaCopy16(3, gHatchStage2TilesGfx, (void *)0x6015800, 0x800);
break;
case 6:
DmaCopy16(3, gHatchStage3TilesGfx, (void *)0x6015800, 0x2000);
break;
case 7:
DmaCopy16(3, gHatchFinalTilesGfx, (void *)0x6015800, 0x1800);
break;
case 8:
DmaCopy16(3, gCaptureScreenTilesGfx, (void *)0x6015800, 0x1C00);
break;
case 9:
DmaCopy16(3, gSapphireCatchTilesGfx, (void *)0x6015800, 0x1400);
break;
case 10:
DmaCopy16(3, gHatchRevealTilesGfx, (void *)0x6015800, 0x2800);
break;
case 11:
DmaCopy16(3, gAreaRouletteSelectedFx_Gfx, (void *)0x6015800, 0x280);
break;
case 13:
for (i = 0; i < 10; i++)
{
if (gSpeciesInfo[gCurrentPinballGame->currentSpecies].name[i] == ' ')
{
DmaCopy16(3, gSpaceTileGfx, (void *)0x6015800 + i * 0x40, 0x40);
}
else
{
int var0 = gSpeciesInfo[gCurrentPinballGame->currentSpecies].name[i] - 'A';
DmaCopy16(3, gAlphabetTilesGfx[var0], (void *)0x6015800 + i * 0x40, 0x40);
}
}
DmaCopy16(3, gPokemonNameDisplayGfx, (void *)0x6015C00, 0x940);
break;
case 12:
for (i = 0; i < 10; i++)
{
if (gSpeciesInfo[gCurrentPinballGame->currentSpecies].name[i] == ' ')
{
DmaCopy16(3, gSpaceTileGfx, (void *)0x6015800 + i * 0x40, 0x40);
}
else
{
int var0 = gSpeciesInfo[gCurrentPinballGame->currentSpecies].name[i] - 'A';
DmaCopy16(3, gAlphabetTilesGfx[var0], (void *)0x6015800 + i * 0x40, 0x40);
}
}
for (i = 0; i < 10; i++)
{
if (gCaughtTextChars[i] == ' ')
{
DmaCopy16(3, gSpaceTileGfx, (void *)0x6015800 + (i + 10) * 0x40, 0x40);
}
else
{
int var0 = gCaughtTextChars[i] - 'A';
DmaCopy16(3, gAlphabetTilesGfx[var0], (void *)0x6015800 + (i + 10) * 0x40, 0x40);
}
}
break;
case 14:
DmaCopy16(3, gEvoItemAppear_GfxList[gCurrentPinballGame->evoItemGfxIndex], (void *)0x6015800, 0x1C00);
break;
case 15:
DmaCopy16(3, gBoardActionTilesGfx, (void *)0x6015800, 0x2400);
break;
case 16:
DmaCopy16(3, gHatchFinalTilesGfx, (void *)0x6015800, 0x1800);
break;
case 17:
DmaCopy16(3, gPokemonNameDisplayGfx, (void *)0x6015C00, 0x940);
if (gCurrentPinballGame->evolutionShopActive == 0)
{
var1 = gShopItemData[gShopCursorToItemMap[gCurrentPinballGame->shopItemCursor]];
var2 = var1[3] / 10;
DmaCopy16(3, gDecimalDigitTilesGfx[var2], (void *)0x6015DA0, 0x40);
var3 = var1[3] % 10;
DmaCopy16(3, gDecimalDigitTilesGfx[var3], (void *)0x6015E60, 0x40);
}
break;
case 18:
DmaCopy16(3, gMainBoardBallSave_Gfx, (void *)0x6015800, 0x2400);
break;
case 19:
DmaCopy16(3, gMainBoardEndOfBall_Gfx, (void *)0x6015800, 0x2800);
break;
case 20:
if (gMain.selectedField == FIELD_RUBY)
{
DmaCopy16(3, gRubyBoardBonusGfx, (void *)0x6015800, 0x1800);
DmaCopy16(3, gRubyBoardBonusObjPalette, (void *)OBJ_PLTT + 0x1C0, 0x20);
}
else
{
DmaCopy16(3, gSapphireBoardBonusGfx, (void *)0x6015800, 0x1800);
DmaCopy16(3, gSapphireBoardBonusObjPalette, (void *)OBJ_PLTT + 0x1C0, 0x20);
}
break;
case 21:
DmaCopy16(3, gSapphireBoardZigzagoonFx_Gfx, (void *)0x6015800, 0xC00);
break;
}
}
void RestoreMainFieldDynamicGraphics(void)
{
s16 i;
s16 var0;
LoadCatchSpriteGraphics();
LoadEggSpriteGraphics();
for (i = 0; i <= 1; i++)
{
var0 = gCurrentPinballGame->flipper[i].position / 2;
DmaCopy16(3, gFlipperTileGraphics[var0], ((i * 0x200) + 0x06010000), 0x200);
}
var0 = gCurrentPinballGame->ball->spinAngle / 0x1000;
DmaCopy16(3, gBallRotationTileGraphics[var0], 0x06010400, 0x80);
for (i = 0; i <= 1; i++)
{
DmaCopy16(3, gPikaSaverTilesGfx + ((var0 =gCurrentPinballGame->pikaSaverTileIndex[i]) * 0x180), 0x06010480 + (i * 0x180), 0x180);
}
var0 = gCurrentPinballGame->pikachuSpinFrame;
DmaCopy16(3, gMainBoardPikaSpinner_Gfx[var0 = gCurrentPinballGame->pikachuSpinFrame], 0x06010780, 0x120);
var0 = gCurrentPinballGame->chargeFillValue;
DmaCopy16(3, gChargeFillIndicator_Gfx[var0], 0x06010AE0, 0x80);
for (i = 0; i <= 1; i++)
{
switch (gCurrentPinballGame->portraitRenderMode[i])
{
case 0:
DmaCopy16(3, gPortraitGenericGraphics[gCurrentPinballGame->portraitGfxIndex[i]], 0x06010CA0 + (i * 0x300), 0x300);
gCurrentPinballGame->ball += 0; //TODO: Dumb match is still a match...
break;
case 9:
if (gCurrentPinballGame->evoChainPosition > 0)
{
if (gMain_saveData.pokedexFlags[gCurrentPinballGame->evoTargetSpecies] == 0)
{
gCurrentPinballGame->portraitGfxIndex[i] = 205;
DmaCopy16(3, gMonPortraitGroupPals[gCurrentPinballGame->portraitGfxIndex[i] / 15] + (gCurrentPinballGame->portraitGfxIndex[i] % 15) * 0x20, 0x050003A0, 0x20);
}
else if (gMain_saveData.pokedexFlags[gCurrentPinballGame->evoTargetSpecies] <= 3)
{
gCurrentPinballGame->portraitGfxIndex[i] = gCurrentPinballGame->evoTargetSpecies;
DmaCopy16(3, gMonPortraitGroupPals[0] + 15 * 0x20, 0x050003A0, 0x20);
}
else
{
gCurrentPinballGame->portraitGfxIndex[i] = gCurrentPinballGame->evoTargetSpecies;
DmaCopy16(3, gMonPortraitGroupPals[gCurrentPinballGame->portraitGfxIndex[i] / 15] + (gCurrentPinballGame->portraitGfxIndex[i] % 15) * 0x20, 0x050003A0, 0x20);
}
}
else
{
gCurrentPinballGame->portraitGfxIndex[i] = gCurrentPinballGame->currentSpecies;
DmaCopy16(3, gMonPortraitGroupPals[gCurrentPinballGame->portraitGfxIndex[i] / 15] + ((gCurrentPinballGame->portraitGfxIndex[i] % 15) * 0x20), 0x050003A0, 0x20);
}
case 3:
DmaCopy16(3, gMonPortraitGroupGfx[gCurrentPinballGame->portraitGfxIndex[i] / 15] + (gCurrentPinballGame->portraitGfxIndex[i] % 15) * 0x300, 0x06010CA0 + (i * 0x18), 0x300);
break;
case 1:
case 2:
case 4:
case 6:
case 7:
case 8:
DmaCopy16(3, gPortraitAnimFrameGraphics[gCurrentPinballGame->portraitGfxIndex[i]], 0x06010CA0 + (i * 0x300), 0x300);
break;
}
}
if (gCurrentPinballGame->boardState == 4)
{
switch (gCurrentPinballGame->boardSubState)
{
case 7:
case 8:
if ((u32) gCurrentPinballGame->captureFlashTimer > 4)
{
DmaCopy16(3, gCatchSpriteFlashGfx, 0x06010CA0, 0x480);
}
else
{
DmaCopy16(3, gCatchSpriteGfxBuffer, 0x06010CA0, 0x480);
}
break;
case 9:
if (gCurrentPinballGame->captureSequenceTimer <= 31)
{
if (gCurrentPinballGame->captureFlashTimer > 4)
{
DmaCopy16(3, gCatchSpriteFlashGfx, 0x06010CA0, 0x480);
}
else
{
DmaCopy16(3, gCatchSpriteGfxBuffer, 0x06010CA0, 0x480);
}
}
break;
}
}
if (gCurrentPinballGame->boardState == 8)
{
switch (gCurrentPinballGame->boardSubState)
{
case 2:
if (gCurrentPinballGame->captureFlashTimer > 4U)
{
DmaCopy16(3, gCatchSpriteFlashGfx, 0x06010CA0, 0x480);
}
else
{
DmaCopy16(3, gCatchSpriteGfxBuffer, 0x06010CA0, 0x480);
}
break;
case 3:
if (gCurrentPinballGame->captureSequenceTimer <= 31)
{
if (gCurrentPinballGame->captureFlashTimer > 4U)
{
DmaCopy16(3, gCatchSpriteFlashGfx, 0x06010CA0, 0x480);
}
else
{
DmaCopy16(3, gCatchSpriteGfxBuffer, 0x06010CA0, 0x480);
}
}
break;
}
}
DmaCopy16(3, gMainStageBonusTrap_Gfx[gCurrentPinballGame->bonusTrapAnimFrame], 0x060113C0, 0x300);
DmaCopy16(3, gEvoItemTilesGfxPtrs[gCurrentPinballGame->evoItemGfxIndex] + var0 * 0x200, 0x060116C0, 0x200);
DmaCopy16(3, gEggFrameTilesGfx[(s16)gEggAnimationFrameData[gCurrentPinballGame->eggAnimFrameIndex][3]], 0x06011CE0, 0x200);
DmaCopy16(3, gBallShadowTileGraphics[gCurrentPinballGame->ballShadowTileIndex], 0x06011EE0, 0x200);
return;
}
void RestoreRubyBoardTileGraphics(void)
{
s16 i;
s16 var0;
var0 = gEggAnimationFrameData[gCurrentPinballGame->eggAnimFrameIndex][2];
DmaCopy16(3, gRubyBoardHatchCave_Gfx[var0], (void *)0x60122A0, 0x480);
var0 = (gMain.systemFrameCount % 50) / 25;
DmaCopy16(3, gRubyFlashingDecorationTiles[var0], (void *)0x6012720, 0x300);
DmaCopy16(3, gRubyBoardSharpedo_Gfx[gCurrentPinballGame->catchHoleTileVariant], (void *)0x6012C20, 0x260);
for (i = 0; i < 2; i++)
DmaCopy16(3, gRubyFlashingTiles_Secondary[var0], (void *)0x6010000 + (0x174 + i * 8) * 0x20, 0x100);
var0 = gCurrentPinballGame->shopDoorCurrentFrame & 0xF;
DmaCopy16(3, gRubyBoardShopDoor_Gfx[var0], (void *)0x6013180, 0x180);
if (gCurrentPinballGame->eggCaveState < 3)
gCurrentPinballGame->cyndaquilFrame = 0;
else
gCurrentPinballGame->cyndaquilFrame = 1;
DmaCopy16(3, gRubyStageCyndaquil_Gfx[gCurrentPinballGame->cyndaquilFrame], (void *)0x6013300, 0x280);
var0 = gEvoShopAnimFrames[gCurrentPinballGame->evolutionShopActive][(gCurrentPinballGame->shopAnimTimer % 42) / 6];
DmaCopy16(3, gRubyBoardShop_Gfx[var0], (void *)0x6013D00, 0x500);
}
void RestoreSapphireBoardTileGraphics(void)
{
s16 index;
switch (gCurrentPinballGame->sapphireHatchMachineState)
{
case 0:
case 1:
case 2:
index = gCurrentPinballGame->sapphireHatchMachineFrameIx;
DmaCopy16(3, gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
break;
case 3:
case 4:
index = 15;
DmaCopy16(3, gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
break;
case 5:
index = gHoleAnimKeyframeData[gCurrentPinballGame->sapphireHatchMachineFrameIx][0];
DmaCopy16(3, gHoleIndicatorTileGfx[index], (void *)0x600D900, 0x440);
break;
case 6:
break;
}
}
void RestoreDusclopsBonusGraphics(void)
{
DmaCopy16(3, gDusclopsBonusClear_Gfx, (void *)0x6015800, 0x2000);
}
void RestoreKecleonBonusGraphics(void)
{
DmaCopy16(3, gKecleonBonusClear_Gfx, (void *)0x6015800, 0x2000);
}
void RestoreKyogreBonusGraphics(void)
{
DmaCopy16(3, gKyogreBonusClear_Gfx, (void *)0x6015800, 0x2000);
DmaCopy16(
3,
gMonPortraitGroupGfx[gCurrentPinballGame->portraitGfxIndex[0] / 15] + (gCurrentPinballGame->portraitGfxIndex[0] % 15) * 0x300,
(void *)0x6010CA0,
0x300
);
}
void RestoreGroudonBonusGraphics(void)
{
if (gCurrentPinballGame->boardState < 2)
{
DmaCopy16(3, gGroudonBoardBackgroundGfx, (void *)0x6015800, 0x2000);
}
else
{
DmaCopy16(3, gGroudonBonusClear_Gfx, (void *)0x6015800, 0x2000);
}
DmaCopy16(
3,
gMonPortraitGroupGfx[gCurrentPinballGame->portraitGfxIndex[0] / 15] + (gCurrentPinballGame->portraitGfxIndex[0] % 15) * 0x300,
(void *)0x6010CA0,
0x300
);
}
void RestoreRayquazaBonusGraphics(void)
{
u8 var0;
if (gCurrentPinballGame->boardState == 0)
{
DmaCopy16(3, gRayquazaSkyBackgroundGfx, (void *)0x6015800, 0x2800);
}
else if (gCurrentPinballGame->boardState == 1)
{
DmaCopy16(3, gRayquazaWindBoardGfx, (void *)0x6015800, 0x1C00);
}
else
{
DmaCopy16(3, gRayquazaBonusClear_Gfx, (void *)0x6015800, 0x2000);
}
var0 = gCurrentPinballGame->bossEntityState - 2;
if (var0 > 9)
{
DmaCopy16(3, gRayquazaSpriteSheet, (void *)0x6011620, 0x860);
}
DmaCopy16(
3,
gMonPortraitGroupGfx[gCurrentPinballGame->portraitGfxIndex[0] / 15] + (gCurrentPinballGame->portraitGfxIndex[0] % 15) * 0x300,
(void *)0x6010CA0,
0x300
);
}
void RestoreSphealBonusGraphics(void)
{
s16 i;
int var0;
u16 var1;
for (i = 0; i < 0x800; i++)
gBG0TilemapBuffer[0x400 + i] = 0x200;
DmaCopy16(3, &gBG0TilemapBuffer[0x400], (void *)0x6001000, 0x1000);
gMain.blendControl = 0x1C42;
gMain.blendAlpha = 0xC04;
for (i = 0; i < 0x140; i++)
{
var0 = i;
if (i < 0)
var0 += 31;
var0 = (var0 >> 5) << 5;
var1 = i - var0 - 2;
if (var1 < 28)
gBG0TilemapBuffer[0x800 + i] = 0x9000;
}
gMain.bgOffsets[1].xOffset = 8;
gMain.bgOffsets[1].yOffset = 126;
DmaCopy16(3, &gBG0TilemapBuffer[0x800], (void *)0x6001140, 0x280);
for (i = 0; i < 0x800; i++)
gBG0TilemapBuffer[i] = 0x1FF;
DmaCopy16(3, gSphealResultsScreenGfx, (void *)0x6015800, 0x800);
}
void nullsub_18(void)
{
}

View File

@ -31,6 +31,14 @@ enum
SUBSTATE_11,
};
void ClearHighScoreNameEntry(void)
{
int i;
for (i = 0; i < HIGH_SCORE_NAME_LENGTH; i++)
gHighScoreNameEntry[i] = 0;
}
void TitlescreenMain(void)
{
gTitlescreenStateFuncs[gMain.subState]();

533
src/travel_mode.c Normal file
View File

@ -0,0 +1,533 @@
#include "global.h"
#include "m4a.h"
#include "main.h"
#include "constants/bg_music.h"
#include "constants/ruby_states.h"
extern const s16 gAreaRouletteTable[][7];
extern const s16 gAreaToSpeciesTable[];
extern const u16 gAreaRouletteOamFramesets[18][27];
extern const u8 gTravelPortraitPalette[];
extern const u8 gAreaRouletteSelectedFx_Gfx[];
extern const u8 gDefaultBallPalette[];
extern const s16 gPondDialAnimFrames[];
extern const s16 gBumperAnimFrames[];
void InitAreaRoulette(void)
{
s16 i;
gCurrentPinballGame->boardSubState = 1;
gCurrentPinballGame->stageTimer = 0;
gCurrentPinballGame->creatureOamPriority = 3;
gCurrentPinballGame->areaVisitCount = 0;
gCurrentPinballGame->areaRouletteSlotIndex = (Random() + gMain.systemFrameCount) % 6;
gCurrentPinballGame->area = gAreaRouletteTable[gMain.selectedField][gCurrentPinballGame->areaRouletteSlotIndex];
gCurrentPinballGame->rouletteAreaIndex[1] = gAreaToSpeciesTable[gCurrentPinballGame->area];
gCurrentPinballGame->area = gAreaRouletteTable[gMain.selectedField][(gCurrentPinballGame->areaRouletteSlotIndex + 1) % 6];
gCurrentPinballGame->rouletteAreaIndex[0] = gAreaToSpeciesTable[gCurrentPinballGame->area];
LoadPortraitGraphics(0, 0);
LoadPortraitGraphics(0, 1);
for (i = 0; i < 6; i++)
gCurrentPinballGame->hatchTilePalette[i] = 13;
DmaCopy16(3, gTravelPortraitPalette, (void *)0x050003C0, 0x20);
DmaCopy16(3, gAreaRouletteSelectedFx_Gfx, (void *)0x06015800, 0x280);
gCurrentPinballGame->activePortraitType = 12;
}
void UpdateAreaRoulette(void)
{
s16 i;
struct SpriteGroup *group;
struct OamDataSimple *oamSimple;
u16 *dst;
s16 var0;
switch (gCurrentPinballGame->boardSubState)
{
case 1:
gMain.blendControl = 0x1C10;
gMain.blendAlpha = BLDALPHA_BLEND(0, 16);
gCurrentPinballGame->boardSubState++;
gCurrentPinballGame->rouletteSubOffset = 0;
gCurrentPinballGame->cameraScrollTarget = 0;
gCurrentPinballGame->cameraScrollEnabled = 1;
gMain.fieldSpriteGroups[20]->available = 1;
gMain.fieldSpriteGroups[21]->available = 1;
gMain.fieldSpriteGroups[23]->available = 1;
gMain.fieldSpriteGroups[22]->available = 1;
gMain.fieldSpriteGroups[19]->available = 1;
gCurrentPinballGame->rouletteFrameIndex = 30;
gCurrentPinballGame->rouletteRotationPeriod = 30;
gCurrentPinballGame->rouletteSpinSpeed = 0;
if (gMain.selectedField == FIELD_RUBY)
{
gCurrentPinballGame->pondBumperStates[0] = 10;
gCurrentPinballGame->pondBumperStates[1] = 10;
gCurrentPinballGame->pondBumperStates[2] = 10;
}
else
{
gCurrentPinballGame->pondBumperStates[0] = 0;
gCurrentPinballGame->pondBumperStates[1] = 0;
gCurrentPinballGame->pondBumperStates[2] = 0;
}
gCurrentPinballGame->rubyPondChangeTimer = 0;
break;
case 2:
if (gCurrentPinballGame->cameraScrollOffset == 0)
{
gCurrentPinballGame->boardSubState++;
gCurrentPinballGame->stageTimer = 0;
}
if (gMain.selectedField == FIELD_RUBY)
{
if (gCurrentPinballGame->rubyPondChangeTimer < 143)
gCurrentPinballGame->pondBumperStates[0] = gPondDialAnimFrames[gCurrentPinballGame->rubyPondChangeTimer / 8];
if (gCurrentPinballGame->rubyPondChangeTimer >= 18 && gCurrentPinballGame->rubyPondChangeTimer < 161)
gCurrentPinballGame->pondBumperStates[2] = gPondDialAnimFrames[(gCurrentPinballGame->rubyPondChangeTimer - 18) / 8];
if (gCurrentPinballGame->rubyPondChangeTimer >= 36 && gCurrentPinballGame->rubyPondChangeTimer < 179)
gCurrentPinballGame->pondBumperStates[1] = gPondDialAnimFrames[(gCurrentPinballGame->rubyPondChangeTimer - 36) / 8];
gCurrentPinballGame->rubyPondChangeTimer++;
}
gCurrentPinballGame->rouletteSubOffset = (gCurrentPinballGame->rouletteFrameIndex * 32) / gCurrentPinballGame->rouletteRotationPeriod;
gCurrentPinballGame->portraitDisplayState = 1;
gCurrentPinballGame->stageTimer++;
UpdateRouletteAnimState();
break;
case 3:
if (gCurrentPinballGame->stageTimer < 15)
{
gCurrentPinballGame->stageTimer++;
if (gCurrentPinballGame->stageTimer == 15)
{
gCurrentPinballGame->boardSubState++;
gCurrentPinballGame->rouletteRotationPeriod = 6;
gCurrentPinballGame->rouletteSpinSpeed = 0;
}
}
SetRouletteActiveState(0);
/* fallthrough */
case 4:
case 5:
if (gCurrentPinballGame->boardSubState == 3)
{
gCurrentPinballGame->rouletteFrameIndex--;
gCurrentPinballGame->rouletteFrameIndex %= gCurrentPinballGame->rouletteRotationPeriod;
}
else if (gCurrentPinballGame->boardSubState == 4)
{
gCurrentPinballGame->rouletteFrameIndex++;
if (gCurrentPinballGame->newButtonActions[1] && gCurrentPinballGame->boardSubState == 4)
{
if (gCurrentPinballGame->rouletteSpinSpeed == 0)
{
if (gMain.eReaderBonuses[EREADER_RUIN_AREA_CARD])
gCurrentPinballGame->rouletteSpinSpeed = 48;
else
gCurrentPinballGame->rouletteSpinSpeed = 1;
gCurrentPinballGame->rouletteInitialSpeed = gCurrentPinballGame->rouletteSpinSpeed;
gCurrentPinballGame->spoinkEntityState = 1;
gCurrentPinballGame->launcherCharging = 1;
gCurrentPinballGame->saverTimeRemaining = 3600;
gCurrentPinballGame->rubyPondState = RUBY_POND_STATE_CHINCHOU_COUNTERCLOCKWISE;
}
}
if (gCurrentPinballGame->rouletteSpinSpeed)
{
gCurrentPinballGame->rouletteSpinSpeed--;
if (gMain.eReaderBonuses[EREADER_RUIN_AREA_CARD])
{
gCurrentPinballGame->numCompletedBonusStages = 4;
if (gCurrentPinballGame->rouletteSpinSpeed < 24)
{
gCurrentPinballGame->rouletteSpinSpeed = 24;
if (gCurrentPinballGame->areaRouletteSlotIndex == 6)
gCurrentPinballGame->rouletteSpinSpeed = 0;
}
}
if (gCurrentPinballGame->rouletteSpinSpeed == 0)
{
gCurrentPinballGame->boardSubState = 5;
}
else
{
if (gCurrentPinballGame->rouletteFrameIndex == gCurrentPinballGame->rouletteRotationPeriod)
{
gCurrentPinballGame->rouletteRotationPeriod = 40 - (gCurrentPinballGame->rouletteSpinSpeed * 30) / gCurrentPinballGame->rouletteInitialSpeed;
gCurrentPinballGame->rouletteFrameIndex = 0;
}
}
}
gCurrentPinballGame->rouletteFrameIndex %= gCurrentPinballGame->rouletteRotationPeriod;
}
else
{
gCurrentPinballGame->rouletteFrameIndex++;
gCurrentPinballGame->rouletteFrameIndex %= gCurrentPinballGame->rouletteRotationPeriod;
if (gCurrentPinballGame->rouletteFrameIndex == 0)
{
gCurrentPinballGame->stageTimer = 0;
gCurrentPinballGame->boardSubState++;
gMain.fieldSpriteGroups[23]->available = 0;
gMain.fieldSpriteGroups[20]->available = 0;
gMain.fieldSpriteGroups[21]->available = 0;
gMain.fieldSpriteGroups[34]->available = 1;
m4aSongNumStart(SE_AREA_ROULETTE_SELECTED);
}
}
gCurrentPinballGame->rouletteSubOffset = (gCurrentPinballGame->rouletteFrameIndex * 32) / gCurrentPinballGame->rouletteRotationPeriod;
if (gCurrentPinballGame->rouletteFrameIndex == 0)
{
gCurrentPinballGame->rouletteAreaIndex[0] = gCurrentPinballGame->rouletteAreaIndex[1];
LoadPortraitGraphics(0, 0);
}
if (gCurrentPinballGame->rouletteFrameIndex == 1)
{
if (gMain.eReaderBonuses[EREADER_RUIN_AREA_CARD])
{
gCurrentPinballGame->areaRouletteSlotIndex = (gCurrentPinballGame->areaRouletteSlotIndex + 1) % 7;
gCurrentPinballGame->areaRouletteNextSlot = 0;
gCurrentPinballGame->areaRouletteFarSlot = 1;
}
else
{
gCurrentPinballGame->areaRouletteSlotIndex = (gCurrentPinballGame->areaRouletteSlotIndex + 1) % 6;
gCurrentPinballGame->areaRouletteNextSlot = (gCurrentPinballGame->areaRouletteSlotIndex + 1) % 6;
gCurrentPinballGame->areaRouletteFarSlot = (gCurrentPinballGame->areaRouletteSlotIndex + 2) % 6;
}
gCurrentPinballGame->area = gAreaRouletteTable[gMain.selectedField][gCurrentPinballGame->areaRouletteSlotIndex];
gCurrentPinballGame->rouletteAreaIndex[1] = gAreaToSpeciesTable[gCurrentPinballGame->area];
LoadPortraitGraphics(0, 1);
m4aSongNumStart(SE_ROULETTE_TICK);
}
break;
case 6:
if (gCurrentPinballGame->stageTimer < 50)
{
gCurrentPinballGame->stageTimer++;
if (gCurrentPinballGame->stageTimer == 50)
{
gCurrentPinballGame->boardSubState = 0;
RequestBoardStateTransition(1);
}
}
if (gCurrentPinballGame->stageTimer < 29)
{
if (gCurrentPinballGame->stageTimer < 8)
var0 = gCurrentPinballGame->stageTimer / 4;
else
var0 = ((gCurrentPinballGame->stageTimer - 8) / 3) + 2;
group = gMain.fieldSpriteGroups[34];
if (group->available)
{
group->baseX = 96u - gCurrentPinballGame->cameraXOffset;
group->baseY = gCurrentPinballGame->rouletteSubOffset + 300u - gCurrentPinballGame->cameraYOffset;
if (group->baseY >= 200)
group->baseY = 200;
for (i = 0; i < 9; i++)
{
oamSimple = &group->oam[i];
dst = (u16 *)&gOamBuffer[oamSimple->oamId];
*dst++ = gAreaRouletteOamFramesets[var0][i * 3 + 0];
*dst++ = gAreaRouletteOamFramesets[var0][i * 3 + 1];
*dst++ = gAreaRouletteOamFramesets[var0][i * 3 + 2];
gOamBuffer[oamSimple->oamId].x += group->baseX;
gOamBuffer[oamSimple->oamId].y += group->baseY;
}
}
if (gCurrentPinballGame->stageTimer == 0x1C) {
gMain.fieldSpriteGroups[34]->available = 0;
gCurrentPinballGame->activePortraitType = 0;
}
}
gCurrentPinballGame->portraitDisplayState = 0;
break;
}
}
void UpdateRouletteAnimState(void)
{
s16 index;
index = (gMain.systemFrameCount % 100) / 10;
gCurrentPinballGame->hudAnimFrameCounter = 0;
gCurrentPinballGame->catchArrowProgress = gBumperAnimFrames[index];
gCurrentPinballGame->evoArrowProgress = gBumperAnimFrames[index];
gCurrentPinballGame->coinRewardLevel = gBumperAnimFrames[index];
if (index == 7 || index == 9)
{
gCurrentPinballGame->catchArrowPaletteActive = 1;
gCurrentPinballGame->rouletteSlotActive = 1;
gCurrentPinballGame->evoArrowPaletteActive = 1;
}
else
{
gCurrentPinballGame->catchArrowPaletteActive = 0;
gCurrentPinballGame->rouletteSlotActive = 0;
gCurrentPinballGame->evoArrowPaletteActive = 0;
}
}
void SetRouletteActiveState(s16 arg0)
{
if (arg0)
{
gCurrentPinballGame->rouletteSlotActive = 1;
gCurrentPinballGame->catchArrowPaletteActive = 1;
gCurrentPinballGame->catchProgressFlashing = 1;
gCurrentPinballGame->evoArrowProgress = 3;
gCurrentPinballGame->coinRewardLevel = 3;
gCurrentPinballGame->catchArrowProgress = 3;
gCurrentPinballGame->evoArrowPaletteActive = 1;
}
else
{
gCurrentPinballGame->evoArrowPaletteActive = 0;
gCurrentPinballGame->rouletteSlotActive = 0;
gCurrentPinballGame->catchArrowPaletteActive = 0;
gCurrentPinballGame->evoArrowProgress = 0;
gCurrentPinballGame->coinRewardLevel = 0;
gCurrentPinballGame->catchArrowProgress = 2;
}
gCurrentPinballGame->progressLevel = 1;
}
void CleanupTravelModeState(void)
{
gCurrentPinballGame->travelRouletteSlotHitType = 0;
gCurrentPinballGame->seedotCount = 0;
if (gMain.selectedField == FIELD_RUBY)
{
gCurrentPinballGame->gulpinCurrentLevel = 0;
gCurrentPinballGame->gulpinAnimFrameIndex = 0;
gCurrentPinballGame->gulpinAnimFrameTimer = 0;
}
gCurrentPinballGame->seedotExitSequenceActive = 1;
gCurrentPinballGame->seedotExitSequenceTimer = 0;
LoadPortraitGraphics(0, 0);
gCurrentPinballGame->portraitDisplayState = 0;
gMain.fieldSpriteGroups[13]->available = 0;
gCurrentPinballGame->trapAnimState = 0;
gCurrentPinballGame->bonusTrapEnabled = 0;
gCurrentPinballGame->prevTravelArrowTiles[0] = gCurrentPinballGame->travelArrowTiles[0] = 0;
gCurrentPinballGame->prevTravelArrowTiles[1] = gCurrentPinballGame->travelArrowTiles[1] = 0;
gCurrentPinballGame->prevTravelArrowTiles[2] = gCurrentPinballGame->travelArrowTiles[2] = 0;
ResetEventState();
}
void InitTravelMode(void)
{
gCurrentPinballGame->boardSubState = 0;
gCurrentPinballGame->stageTimer = 0;
gCurrentPinballGame->boardModeType = 2;
gCurrentPinballGame->eventTimer = gCurrentPinballGame->timerBonus + 3600;
gCurrentPinballGame->timerBonus = 0;
gCurrentPinballGame->saverTimeRemaining = 1800;
DmaCopy16(3, gDefaultBallPalette, (void *)0x05000180, 0x20);
}
void UpdateTravelMode(void)
{
s16 var0;
if (gCurrentPinballGame->boardModeType && gCurrentPinballGame->eventTimer < 2 && gCurrentPinballGame->boardSubState < 6)
{
m4aMPlayAllStop();
m4aSongNumStart(MUS_END_OF_BALL2);
gCurrentPinballGame->stageTimer = 200;
gCurrentPinballGame->boardSubState = 6;
}
switch (gCurrentPinballGame->boardSubState)
{
case 0:
if (gMain.modeChangeFlags == MODE_CHANGE_NONE)
{
gCurrentPinballGame->boardSubState++;
gCurrentPinballGame->portraitCycleFrame = 0;
}
gCurrentPinballGame->travelRouletteSlotHitType = 0;
break;
case 1:
LoadPortraitGraphics(4, 0);
if (gCurrentPinballGame->stageTimer == 35)
m4aSongNumStart(MUS_TRAVEL_MODE);
if (gCurrentPinballGame->travelRouletteSlotHitType)
{
gCurrentPinballGame->boardSubState++;
if (gCurrentPinballGame->stageTimer < 35)
m4aSongNumStart(MUS_TRAVEL_MODE);
gCurrentPinballGame->seedotCount = 0;
gCurrentPinballGame->seedotExitSequenceActive = 1;
gCurrentPinballGame->seedotExitSequenceTimer = 0;
}
var0 = (gCurrentPinballGame->stageTimer % 40) / 10;
gCurrentPinballGame->stageTimer++;
if (var0 == 0)
{
gCurrentPinballGame->travelArrowTiles[0] = 0;
gCurrentPinballGame->travelArrowTiles[1] = 0;
gCurrentPinballGame->travelArrowTiles[2] = 0;
}
else if (var0 == 1)
{
gCurrentPinballGame->travelArrowTiles[0] = 3;
gCurrentPinballGame->travelArrowTiles[1] = 1;
gCurrentPinballGame->travelArrowTiles[2] = 0;
}
else if (var0 == 2)
{
gCurrentPinballGame->travelArrowTiles[0] = 3;
gCurrentPinballGame->travelArrowTiles[1] = 3;
gCurrentPinballGame->travelArrowTiles[2] = 2;
}
else
{
gCurrentPinballGame->travelArrowTiles[0] = 3;
gCurrentPinballGame->travelArrowTiles[1] = 3;
gCurrentPinballGame->travelArrowTiles[2] = 3;
}
gCurrentPinballGame->prevTravelArrowTiles[0] = gCurrentPinballGame->travelArrowTiles[0];
gCurrentPinballGame->prevTravelArrowTiles[1] = gCurrentPinballGame->travelArrowTiles[1];
gCurrentPinballGame->prevTravelArrowTiles[2] = gCurrentPinballGame->travelArrowTiles[2];
break;
case 2:
ShowBonusTrapSprite();
gCurrentPinballGame->trapAnimState = 2;
LoadPortraitGraphics(0, 0);
gCurrentPinballGame->prevTravelArrowTiles[0] = gCurrentPinballGame->travelArrowTiles[0] = 0;
gCurrentPinballGame->prevTravelArrowTiles[1] = gCurrentPinballGame->travelArrowTiles[1] = 0;
gCurrentPinballGame->prevTravelArrowTiles[2] = gCurrentPinballGame->travelArrowTiles[2] = 0;
gCurrentPinballGame->boardSubState++;
break;
case 3:
AnimateBonusTrapSprite();
if (gCurrentPinballGame->ballCatchState == 4)
gCurrentPinballGame->boardSubState++;
break;
case 4:
gCurrentPinballGame->boardModeType = 3;
gCurrentPinballGame->boardSubState++;
gCurrentPinballGame->stageTimer = 0;
gCurrentPinballGame->portraitCycleFrame = 0;
gCurrentPinballGame->modeOutcomeValues[0] = 47;
LoadPortraitGraphics(7, 0);
break;
case 5:
if (gCurrentPinballGame->modeAnimTimer == 145)
{
gCurrentPinballGame->modeAnimTimer++;
gCurrentPinballGame->modeOutcomeValues[0] = 47;
LoadPortraitGraphics(7, 0);
if (JOY_NEW(A_BUTTON))
{
gCurrentPinballGame->modeAnimTimer = 144;
m4aMPlayAllStop();
LoadPortraitGraphics(0, 0);
if (gCurrentPinballGame->areaVisitCount < 5)
{
var0 = gCurrentPinballGame->areaRouletteFarSlot;
if (gCurrentPinballGame->travelRouletteSlotHitType == 1)
gCurrentPinballGame->areaRouletteSlotIndex = gCurrentPinballGame->areaRouletteNextSlot;
else
gCurrentPinballGame->areaRouletteSlotIndex = gCurrentPinballGame->areaRouletteFarSlot;
gCurrentPinballGame->areaRouletteNextSlot = (var0 + 1) % 6;
gCurrentPinballGame->areaRouletteFarSlot = (var0 + 2) % 6;
gCurrentPinballGame->areaVisitCount++;
}
else
{
gCurrentPinballGame->areaRouletteSlotIndex = 6;
gCurrentPinballGame->areaVisitCount = 0;
}
}
else if (JOY_NEW(B_BUTTON))
{
m4aMPlayAllStop();
m4aSongNumStart(SE_MENU_CANCEL);
gCurrentPinballGame->modeAnimTimer = 60;
gCurrentPinballGame->boardSubState = 6;
if (gCurrentPinballGame->allHolesLit)
gCurrentPinballGame->allHolesLitDelayTimer = 120;
}
}
if (gCurrentPinballGame->modeAnimTimer == 130)
{
gCurrentPinballGame->modeAnimTimer++;
if (gCurrentPinballGame->stageTimer < 490)
{
RunTravelEventCutscene();
if (gCurrentPinballGame->scoreCounterAnimationEnabled && gCurrentPinballGame->stageTimer >= 428)
gCurrentPinballGame->stageTimer = 428;
if (gCurrentPinballGame->stageTimer == 394)
{
gCurrentPinballGame->scoreCounterAnimationEnabled = TRUE;
gCurrentPinballGame->scoreAddedInFrame = 500000;
}
}
else
{
gCurrentPinballGame->modeAnimTimer = 120;
}
gCurrentPinballGame->stageTimer++;
}
else if (gCurrentPinballGame->modeAnimTimer == 0)
{
gCurrentPinballGame->boardSubState++;
gCurrentPinballGame->stageTimer = 0;
if (gCurrentPinballGame->travelModeCompletionCount < 99)
gCurrentPinballGame->travelModeCompletionCount++;
}
break;
case 6:
AnimateBonusTrapSprite();
gMain.fieldSpriteGroups[13]->available = 0;
CleanupTravelModeState();
gCurrentPinballGame->boardSubState++;
break;
case 7:
if (gCurrentPinballGame->stageTimer)
{
gCurrentPinballGame->stageTimer--;
}
else
{
RequestBoardStateTransition(1);
gCurrentPinballGame->boardSubState = 0;
}
break;
}
}

View File

@ -290,3 +290,55 @@ void SetMatrixScale(s16 xScale, s16 yScale, s16 matrixNum)
gOamBuffer[matrixNum * 4 + 2].affineParam = c2;
gOamBuffer[matrixNum * 4 + 3].affineParam = a; // TODO fake match as above
}
u16 IsInVblank(void)
{
if ((REG_IME & 1) // Interrupts enabled
&& (REG_DISPSTAT & DISPSTAT_VBLANK_INTR) // In VBLANK
&& (REG_IE & INTR_FLAG_VBLANK) // VBlank interrupt enabled
&& !(REG_DISPCNT & DISPCNT_FORCED_BLANK)) // Ignore VBlank interrupts during forced blank
return TRUE;
else
return FALSE;
}
void SetMainCallback(void (*func)(void))
{
gMainCallbackShadow = func;
if (!IsInVblank())
gMainCallback = func;
}
void ResetMainCallback(void)
{
gMainCallback = DefaultMainCallback;
gMainCallbackShadow = DefaultMainCallback;
}
void SetVBlankIntrFunc(void (*func)(void))
{
gVBlankIntrFuncShadow = func;
if (!IsInVblank())
*gVBlankIntrFuncPtr = func;
}
void ResetVBlankIntrFunc(void)
{
*gVBlankIntrFuncPtr = VBlankIntr;
gVBlankIntrFuncShadow = VBlankIntr;
}
void SetVCountIntrFunc(void (*func)(void))
{
gVCountIntrFuncShadow = func;
if (!IsInVblank())
*gVCountIntrFuncPtr = func;
}
void ResetVCountIntrFunc(void)
{
*gVCountIntrFuncPtr = VCountIntr;
gVCountIntrFuncShadow = VCountIntr;
}