; Sonic the Hedgehog 2 disassembled binary ; Nemesis, 2004: Created original disassembly for SNASM68K ; Aurochs, 2005: Translated to AS and annotated ; Xenowhirl, 2007: More annotation, overall cleanup, Z80 disassembly ; --------------------------------------------------------------------------- ; NOTES: ; ; Set your editor's tab width to 8 characters wide for viewing this file. ; ; It is highly suggested that you read the AS User's Manual before diving too ; far into this disassembly. At least read the section on nameless temporary ; symbols. Your brain may melt if you don't know how those work. ; ; See s2.notes.txt for more comments about this disassembly and other useful info. ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; ASSEMBLY OPTIONS: ; padToPowerOfTwo = 1 ; | If 1, pads the end of the ROM to the next power of two bytes (for real hardware) ; allOptimizations = 0 ; | If 1, enables all optimizations ; skipChecksumCheck = 0|allOptimizations ; | If 1, disables the unnecessary (and slow) bootup checksum calculation ; zeroOffsetOptimization = 0|allOptimizations ; | If 1, makes a handful of zero-offset instructions smaller ; removeJmpTos = 0|allOptimizations ; | If 1, many unnecessary JmpTos are removed, improving performance ; addsubOptimize = 0|allOptimizations ; | If 1, some add/sub instructions are optimized to addq/subq ; relativeLea = 1|allOptimizations ; | If 1, makes some instructions use pc-relative addressing, instead of absolute long ; useFullWaterTables = 0 ; | If 1, zone offset tables for water levels cover all level slots instead of only slots 8-$F ; | Set to 1 if you've shifted level IDs around or you want water in levels with a level slot below 8 gameRevision = 1 ; | If 0, a REV00 ROM is built ; | If 1, a REV01 ROM is built, which contains some fixes ; | If 2, a (probable) REV02 ROM is built, which contains more fixes ; | (Bit-perfect REV02 requires removeJmpTos & addsubOptimize be set to 1, ; | and also requires relativeLea to be 0) ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; AS-specific macros and assembler settings CPU 68000 include "s2.macrosetup.asm" ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Equates section - Names for variables. include "s2.constants.asm" ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; simplifying macros and functions include "s2.macros.asm" ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; start of ROM StartOfRom: if * <> 0 fatal "StartOfRom was $\{*} but it should be 0" endif ;Vectors: dc.l System_Stack, EntryPoint, ErrorTrap, ErrorTrap; 4 dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 8 dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 12 dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 16 dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 20 dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 24 dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 28 dc.l H_Int, ErrorTrap, V_Int, ErrorTrap; 32 dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 36 dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 40 dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 44 dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 48 dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 52 dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 56 dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 60 dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 64 ; byte_100: Header: dc.b "SEGA GENESIS " ; Console name dc.b "(C)SEGA 1992.SEP" ; Copyright/Date dc.b "SONIC THE HEDGEHOG 2 " ; Domestic name dc.b "SONIC THE HEDGEHOG 2 " ; International name if gameRevision=0 dc.b "GM 00001051-00" ; Version (REV00) elseif gameRevision=1 dc.b "GM 00001051-01" ; Version (REV01) else;if gameRevision=2 dc.b "GM 00001051-02" ; Version (REV02) endif ; word_18E Checksum: dc.w $D951 ; Checksum (patched later if incorrect) dc.b "J " ; I/O Support dc.l StartOfRom ; ROM Start ; dword_1A4 ROMEndLoc: dc.l EndOfRom-1 ; ROM End dc.l RAM_Start&$FFFFFF ; RAM Start dc.l (RAM_End-1)&$FFFFFF ; RAM End dc.b " " ; Backup RAM ID dc.l $20202020 ; Backup RAM start address dc.l $20202020 ; Backup RAM end address dc.b " " ; Modem support dc.b " " ; Notes dc.b "JUE " ; Country EndOfHeader: ; =========================================================================== ; Crash/Freeze the 68000. Note that the Z80 continues to run, so the music keeps playing. ; loc_200: ErrorTrap: nop nop bra.s ErrorTrap ; =========================================================================== ; loc_206: EntryPoint: tst.l (HW_Port_1_Control-1).l ; test ports A and B control bne.s PortA_Ok tst.w (HW_Expansion_Control-1).l ; test port C control ; loc_214: PortA_Ok: bne.s PortC_OK ; skip the VDP and Z80 setup code if port A, B or C is ok...? lea SetupValues(pc),a5 movem.w (a5)+,d5-d7 movem.l (a5)+,a0-a4 move.b HW_Version-Z80_Bus_Request(a1),d0 ; get hardware version andi.b #$F,d0 beq.s SkipSecurity ; branch if hardware is older than Genesis III move.l #'SEGA',Security_Addr-Z80_Bus_Request(a1) ; satisfy the TMSS ; loc_234: SkipSecurity: move.w (a4),d0 ; check if VDP works moveq #0,d0 movea.l d0,a6 move.l a6,usp ; set usp to $0 moveq #VDPInitValues_End-VDPInitValues-1,d1 ; run the following loop $18 times ; loc_23E: VDPInitLoop: move.b (a5)+,d5 ; add $8000 to value move.w d5,(a4) ; move value to VDP register add.w d7,d5 ; next register dbf d1,VDPInitLoop move.l (a5)+,(a4) ; set VRAM write mode move.w d0,(a3) ; clear the screen move.w d7,(a1) ; stop the Z80 move.w d7,(a2) ; reset the Z80 ; loc_250: WaitForZ80: btst d0,(a1) ; has the Z80 stopped? bne.s WaitForZ80 ; if not, branch moveq #Z80StartupCodeEnd-Z80StartupCodeBegin-1,d2 ; loc_256: Z80InitLoop: move.b (a5)+,(a0)+ dbf d2,Z80InitLoop move.w d0,(a2) move.w d0,(a1) ; start the Z80 move.w d7,(a2) ; reset the Z80 ; loc_262: ClrRAMLoop: move.l d0,-(a6) dbf d6,ClrRAMLoop ; clear the entire RAM move.l (a5)+,(a4) ; set VDP display mode and increment move.l (a5)+,(a4) ; set VDP to CRAM write moveq #bytesToLcnt($80),d3 ; loc_26E: ClrCRAMLoop: move.l d0,(a3) dbf d3,ClrCRAMLoop ; clear the CRAM move.l (a5)+,(a4) moveq #bytesToLcnt($50),d4 ; loc_278: ClrVDPStuff: ClrVSRAMLoop: move.l d0,(a3) dbf d4,ClrVSRAMLoop moveq #PSGInitValues_End-PSGInitValues-1,d5 ; loc_280: PSGInitLoop: move.b (a5)+,PSG_input-VDP_data_port(a3) ; reset the PSG dbf d5,PSGInitLoop move.w d0,(a2) movem.l (a6),d0-a6 ; clear all registers move #$2700,sr ; set the sr ; loc_292: PortC_OK: ;; bra.s GameProgram ; =========================================================================== ; byte_294: SetupValues: dc.w $8000,bytesToLcnt($10000),$100 dc.l Z80_RAM dc.l Z80_Bus_Request dc.l Z80_Reset dc.l VDP_data_port, VDP_control_port VDPInitValues: ; values for VDP registers dc.b 4 ; Command $8004 - HInt off, Enable HV counter read dc.b $14 ; Command $8114 - Display off, VInt off, DMA on, PAL off dc.b $30 ; Command $8230 - Scroll A Address $C000 dc.b $3C ; Command $833C - Window Address $F000 dc.b 7 ; Command $8407 - Scroll B Address $E000 dc.b $6C ; Command $856C - Sprite Table Address $D800 dc.b 0 ; Command $8600 - Null dc.b 0 ; Command $8700 - Background color Pal 0 Color 0 dc.b 0 ; Command $8800 - Null dc.b 0 ; Command $8900 - Null dc.b $FF ; Command $8AFF - Hint timing $FF scanlines dc.b 0 ; Command $8B00 - Ext Int off, VScroll full, HScroll full dc.b $81 ; Command $8C81 - 40 cell mode, shadow/highlight off, no interlace dc.b $37 ; Command $8D37 - HScroll Table Address $DC00 dc.b 0 ; Command $8E00 - Null dc.b 1 ; Command $8F01 - VDP auto increment 1 byte dc.b 1 ; Command $9001 - 64x32 cell scroll size dc.b 0 ; Command $9100 - Window H left side, Base Point 0 dc.b 0 ; Command $9200 - Window V upside, Base Point 0 dc.b $FF ; Command $93FF - DMA Length Counter $FFFF dc.b $FF ; Command $94FF - See above dc.b 0 ; Command $9500 - DMA Source Address $0 dc.b 0 ; Command $9600 - See above dc.b $80 ; Command $9780 - See above + VRAM fill mode VDPInitValues_End: dc.l vdpComm($0000,VRAM,DMA) ; value for VRAM write mode ; Z80 instructions (not the sound driver; that gets loaded later) Z80StartupCodeBegin: ; loc_2CA: if (*)+$26 < $10000 save CPU Z80 ; start assembling Z80 code phase 0 ; pretend we're at address 0 xor a ; clear a to 0 ld bc,((Z80_RAM_End-Z80_RAM)-zStartupCodeEndLoc)-1 ; prepare to loop this many times ld de,zStartupCodeEndLoc+1 ; initial destination address ld hl,zStartupCodeEndLoc ; initial source address ld sp,hl ; set the address the stack starts at ld (hl),a ; set first byte of the stack to 0 ldir ; loop to fill the stack (entire remaining available Z80 RAM) with 0 pop ix ; clear ix pop iy ; clear iy ld i,a ; clear i ld r,a ; clear r pop de ; clear de pop hl ; clear hl pop af ; clear af ex af,af' ; swap af with af' exx ; swap bc/de/hl with their shadow registers too pop bc ; clear bc pop de ; clear de pop hl ; clear hl pop af ; clear af ld sp,hl ; clear sp di ; clear iff1 (for interrupt handler) im 1 ; interrupt handling mode = 1 ld (hl),0E9h ; replace the first instruction with a jump to itself jp (hl) ; jump to the first instruction (to stay there forever) zStartupCodeEndLoc: dephase ; stop pretending restore padding off ; unfortunately our flags got reset so we have to set them again... else ; due to an address range limitation I could work around but don't think is worth doing so: message "Warning: using pre-assembled Z80 startup code." dc.w $AF01,$D91F,$1127,$0021,$2600,$F977,$EDB0,$DDE1,$FDE1,$ED47,$ED4F,$D1E1,$F108,$D9C1,$D1E1,$F1F9,$F3ED,$5636,$E9E9 endif Z80StartupCodeEnd: dc.w $8104 ; value for VDP display mode dc.w $8F02 ; value for VDP increment dc.l vdpComm($0000,CRAM,WRITE) ; value for CRAM write mode dc.l vdpComm($0000,VSRAM,WRITE) ; value for VSRAM write mode PSGInitValues: dc.b $9F,$BF,$DF,$FF ; values for PSG channel volumes PSGInitValues_End: ; =========================================================================== even ; loc_300: GameProgram: tst.w (VDP_control_port).l ; loc_306: CheckSumCheck: if gameRevision>0 move.w (VDP_control_port).l,d1 btst #1,d1 bne.s CheckSumCheck ; wait until DMA is completed endif btst #6,(HW_Expansion_Control).l beq.s ChecksumTest cmpi.l #'init',(Checksum_fourcc).w ; has checksum routine already run? beq.w GameInit ; loc_328: ChecksumTest: if skipChecksumCheck=0 ; checksum code movea.l #EndOfHeader,a0 ; start checking bytes after the header ($200) movea.l #ROMEndLoc,a1 ; stop at end of ROM move.l (a1),d0 moveq #0,d1 ; loc_338: ChecksumLoop: add.w (a0)+,d1 cmp.l a0,d0 bhs.s ChecksumLoop movea.l #Checksum,a1 ; read the checksum cmp.w (a1),d1 ; compare correct checksum to the one in ROM bne.w ChecksumError ; if they don't match, branch endif ;checksum_good: lea (System_Stack).w,a6 moveq #0,d7 move.w #bytesToLcnt($200),d6 - move.l d7,(a6)+ dbf d6,- move.b (HW_Version).l,d0 andi.b #$C0,d0 move.b d0,(Graphics_Flags).w move.l #'init',(Checksum_fourcc).w ; set flag so checksum won't be run again ; loc_370: GameInit: lea (RAM_Start&$FFFFFF).l,a6 moveq #0,d7 move.w #bytesToLcnt(System_Stack&$FFFF),d6 ; loc_37C: GameClrRAM: move.l d7,(a6)+ dbf d6,GameClrRAM bsr.w VDPSetupGame bsr.w JmpTo_SoundDriverLoad bsr.w JoypadInit move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen ; loc_394: MainGameLoop: move.b (Game_Mode).w,d0 andi.w #$3C,d0 jsr GameModesArray(pc,d0.w) bra.s MainGameLoop ; =========================================================================== ; loc_3A2: GameModesArray: ;; GameMode_SegaScreen: bra.w SegaScreen ; SEGA screen mode GameMode_TitleScreen: bra.w TitleScreen ; Title screen mode GameMode_Demo: bra.w Level ; Demo mode GameMode_Level: bra.w Level ; Zone play mode GameMode_SpecialStage: bra.w SpecialStage ; Special stage play mode GameMode_ContinueScreen:bra.w ContinueScreen ; Continue mode GameMode_2PResults: bra.w TwoPlayerResults ; 2P results mode GameMode_2PLevelSelect: bra.w LevelSelectMenu2P ; 2P level select mode GameMode_EndingSequence:bra.w JmpTo_EndingSequence ; End sequence mode GameMode_OptionsMenu: bra.w OptionsMenu ; Options mode GameMode_LevelSelect: bra.w LevelSelectMenu ; Level select mode ; =========================================================================== if skipChecksumCheck=0 ; checksum error code ; loc_3CE: ChecksumError: move.l d1,-(sp) bsr.w VDPSetupGame move.l (sp)+,d1 move.l #vdpComm($0000,CRAM,WRITE),(VDP_control_port).l moveq #$3F,d7 ; loc_3E2: Checksum_Red: move.w #$E,(VDP_data_port).l dbf d7,Checksum_Red ; loc_3EE: ChecksumFailed_Loop: bra.s ChecksumFailed_Loop endif ; =========================================================================== ; loc_3F0: LevelSelectMenu2P: ;; jmp (MenuScreen).l ; =========================================================================== ; loc_3F6: JmpTo_EndingSequence jmp (EndingSequence).l ; =========================================================================== ; loc_3FC: OptionsMenu: ;; jmp (MenuScreen).l ; =========================================================================== ; loc_402: LevelSelectMenu: ;; jmp (MenuScreen).l ; =========================================================================== ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; vertical and horizontal interrupt handlers ; VERTICAL INTERRUPT HANDLER: V_Int: movem.l d0-a6,-(sp) tst.b (Vint_routine).w beq.w Vint_Lag - move.w (VDP_control_port).l,d0 andi.w #8,d0 beq.s - move.l #vdpComm($0000,VSRAM,WRITE),(VDP_control_port).l move.l (Vscroll_Factor).w,(VDP_data_port).l btst #6,(Graphics_Flags).w beq.s + move.w #$700,d0 - dbf d0,- ; wait here in a loop doing nothing for a while... + move.b (Vint_routine).w,d0 move.b #VintID_Lag,(Vint_routine).w move.w #1,(Hint_flag).w andi.w #$3E,d0 move.w Vint_SwitchTbl(pc,d0.w),d0 jsr Vint_SwitchTbl(pc,d0.w) VintRet: addq.l #1,(Vint_runcount).w movem.l (sp)+,d0-a6 rte ; =========================================================================== Vint_SwitchTbl: offsetTable Vint_Lag_ptr offsetTableEntry.w Vint_Lag ; 0 Vint_SEGA_ptr: offsetTableEntry.w Vint_SEGA ; 2 Vint_Title_ptr: offsetTableEntry.w Vint_Title ; 4 Vint_Unused6_ptr: offsetTableEntry.w Vint_Unused6 ; 6 Vint_Level_ptr: offsetTableEntry.w Vint_Level ; 8 Vint_S2SS_ptr: offsetTableEntry.w Vint_S2SS ; $A Vint_TitleCard_ptr: offsetTableEntry.w Vint_TitleCard ; $C Vint_UnusedE_ptr: offsetTableEntry.w Vint_UnusedE ; $E Vint_Pause_ptr: offsetTableEntry.w Vint_Pause ; $10 Vint_Fade_ptr: offsetTableEntry.w Vint_Fade ; $12 Vint_PCM_ptr: offsetTableEntry.w Vint_PCM ; $14 Vint_Menu_ptr: offsetTableEntry.w Vint_Menu ; $16 Vint_Ending_ptr: offsetTableEntry.w Vint_Ending ; $18 Vint_CtrlDMA_ptr: offsetTableEntry.w Vint_CtrlDMA ; $1A ; =========================================================================== ;VintSub0 Vint_Lag: cmpi.b #GameModeID_TitleCard|GameModeID_Demo,(Game_Mode).w ; pre-level Demo Mode? beq.s loc_4C4 cmpi.b #GameModeID_TitleCard|GameModeID_Level,(Game_Mode).w ; pre-level Zone play mode? beq.s loc_4C4 cmpi.b #GameModeID_Demo,(Game_Mode).w ; Demo Mode? beq.s loc_4C4 cmpi.b #GameModeID_Level,(Game_Mode).w ; Zone play mode? beq.s loc_4C4 stopZ80 ; stop the Z80 bsr.w sndDriverInput ; give input to the sound driver startZ80 ; start the Z80 bra.s VintRet ; --------------------------------------------------------------------------- loc_4C4: tst.b (Water_flag).w beq.w Vint0_noWater move.w (VDP_control_port).l,d0 btst #6,(Graphics_Flags).w beq.s + move.w #$700,d0 - dbf d0,- ; do nothing for a while... + move.w #1,(Hint_flag).w stopZ80 tst.b (Water_fullscreen_flag).w bne.s loc_526 dma68kToVDP Normal_palette,$0000,palette_line_size*4,CRAM bra.s loc_54A ; --------------------------------------------------------------------------- loc_526: dma68kToVDP Underwater_palette,$0000,palette_line_size*4,CRAM loc_54A: move.w (Hint_counter_reserve).w,(a5) move.w #$8200|(VRAM_Plane_A_Name_Table/$400),(VDP_control_port).l ; Set scroll A PNT base to $C000 bsr.w sndDriverInput startZ80 bra.w VintRet ; --------------------------------------------------------------------------- Vint0_noWater: move.w (VDP_control_port).l,d0 move.l #vdpComm($0000,VSRAM,WRITE),(VDP_control_port).l move.l (Vscroll_Factor).w,(VDP_data_port).l btst #6,(Graphics_Flags).w beq.s + move.w #$700,d0 - dbf d0,- ; do nothing for a while... + move.w #1,(Hint_flag).w move.w (Hint_counter_reserve).w,(VDP_control_port).l move.w #$8200|(VRAM_Plane_A_Name_Table/$400),(VDP_control_port).l ; Set scroll A PNT base to $C000 move.l (Vscroll_Factor_P2).w,(Vscroll_Factor_P2_HInt).w stopZ80 dma68kToVDP Sprite_Table,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM bsr.w sndDriverInput startZ80 bra.w VintRet ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; This subroutine copies the H scroll table buffer (in main RAM) to the H scroll ; table (in VRAM). ;VintSub2 Vint_SEGA: bsr.w Do_ControllerPal dma68kToVDP Horiz_Scroll_Buf,VRAM_Horiz_Scroll_Table,VRAM_Horiz_Scroll_Table_Size,VRAM jsrto (SegaScr_VInt).l, JmpTo_SegaScr_VInt tst.w (Demo_Time_left).w beq.w + ; rts subq.w #1,(Demo_Time_left).w + rts ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ;VintSub14 Vint_PCM: move.b (Vint_runcount+3).w,d0 andi.w #$F,d0 bne.s + stopZ80 bsr.w ReadJoypads startZ80 + tst.w (Demo_Time_left).w beq.w + ; rts subq.w #1,(Demo_Time_left).w + rts ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ;VintSub4 Vint_Title: bsr.w Do_ControllerPal bsr.w ProcessDPLC tst.w (Demo_Time_left).w beq.w + ; rts subq.w #1,(Demo_Time_left).w + rts ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ;VintSub6 Vint_Unused6: bsr.w Do_ControllerPal rts ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ;VintSub10 Vint_Pause: cmpi.b #GameModeID_SpecialStage,(Game_Mode).w ; Special Stage? beq.w Vint_Pause_specialStage ;VintSub8 Vint_Level: stopZ80 bsr.w ReadJoypads tst.b (Teleport_timer).w beq.s loc_6F8 lea (VDP_control_port).l,a5 tst.w (Game_paused).w bne.w loc_748 subq.b #1,(Teleport_timer).w bne.s + move.b #0,(Teleport_flag).w + cmpi.b #$10,(Teleport_timer).w blo.s loc_6F8 lea (VDP_data_port).l,a6 move.l #vdpComm($0000,CRAM,WRITE),(VDP_control_port).l move.w #$EEE,d0 move.w #$1F,d1 - move.w d0,(a6) dbf d1,- move.l #vdpComm($0042,CRAM,WRITE),(VDP_control_port).l move.w #$1F,d1 - move.w d0,(a6) dbf d1,- bra.s loc_748 ; --------------------------------------------------------------------------- loc_6F8: tst.b (Water_fullscreen_flag).w bne.s loc_724 dma68kToVDP Normal_palette,$0000,palette_line_size*4,CRAM bra.s loc_748 ; --------------------------------------------------------------------------- loc_724: dma68kToVDP Underwater_palette,$0000,palette_line_size*4,CRAM loc_748: move.w (Hint_counter_reserve).w,(a5) move.w #$8200|(VRAM_Plane_A_Name_Table/$400),(VDP_control_port).l ; Set scroll A PNT base to $C000 dma68kToVDP Horiz_Scroll_Buf,VRAM_Horiz_Scroll_Table,VRAM_Horiz_Scroll_Table_Size,VRAM dma68kToVDP Sprite_Table,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM bsr.w ProcessDMAQueue bsr.w sndDriverInput startZ80 movem.l (Camera_RAM).w,d0-d7 movem.l d0-d7,(Camera_RAM_copy).w movem.l (Camera_X_pos_P2).w,d0-d7 movem.l d0-d7,(Camera_P2_copy).w movem.l (Scroll_flags).w,d0-d3 movem.l d0-d3,(Scroll_flags_copy).w move.l (Vscroll_Factor_P2).w,(Vscroll_Factor_P2_HInt).w cmpi.b #$5C,(Hint_counter_reserve+1).w bhs.s Do_Updates move.b #1,(Do_Updates_in_H_int).w rts ; --------------------------------------------------------------------------- ; Subroutine to run a demo for an amount of time ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_7E6: Demo_Time: Do_Updates: jsrto (LoadTilesAsYouMove).l, JmpTo_LoadTilesAsYouMove jsr (HudUpdate).l bsr.w ProcessDPLC2 tst.w (Demo_Time_left).w ; is there time left on the demo? beq.w + ; if not, branch subq.w #1,(Demo_Time_left).w ; subtract 1 from time left + rts ; End of function Do_Updates ; --------------------------------------------------------------------------- ;Vint10_specialStage Vint_Pause_specialStage: stopZ80 bsr.w ReadJoypads jsr (sndDriverInput).l tst.b (SS_Last_Alternate_HorizScroll_Buf).w beq.s loc_84A dma68kToVDP SS_Horiz_Scroll_Buf_2,VRAM_SS_Horiz_Scroll_Table,VRAM_SS_Horiz_Scroll_Table_Size,VRAM bra.s loc_86E ; --------------------------------------------------------------------------- loc_84A: dma68kToVDP SS_Horiz_Scroll_Buf_1,VRAM_SS_Horiz_Scroll_Table,VRAM_SS_Horiz_Scroll_Table_Size,VRAM loc_86E: startZ80 rts ; ========================================================================>>> ;VintSubA Vint_S2SS: stopZ80 bsr.w ReadJoypads bsr.w SSSet_VScroll dma68kToVDP Normal_palette,$0000,palette_line_size*4,CRAM dma68kToVDP SS_Sprite_Table,VRAM_SS_Sprite_Attribute_Table,VRAM_SS_Sprite_Attribute_Table_Size,VRAM tst.b (SS_Alternate_HorizScroll_Buf).w beq.s loc_906 dma68kToVDP SS_Horiz_Scroll_Buf_2,VRAM_SS_Horiz_Scroll_Table,VRAM_SS_Horiz_Scroll_Table_Size,VRAM bra.s loc_92A ; --------------------------------------------------------------------------- loc_906: dma68kToVDP SS_Horiz_Scroll_Buf_1,VRAM_SS_Horiz_Scroll_Table,VRAM_SS_Horiz_Scroll_Table_Size,VRAM loc_92A: tst.b (SSTrack_Orientation).w ; Is the current track frame flipped? beq.s ++ ; Branch if not moveq #0,d0 move.b (SSTrack_drawing_index).w,d0 ; Get drawing position cmpi.b #4,d0 ; Have we finished drawing and streaming track frame? bge.s ++ ; Branch if yes (nothing to draw) add.b d0,d0 ; Convert to index tst.b (SS_Alternate_PNT).w ; [(SSTrack_drawing_index) * 2] = subroutine beq.s + ; Branch if not using the alternate Plane A name table addi_.w #8,d0 ; ([(SSTrack_drawing_index) * 2] + 8) = subroutine + move.w SS_PNTA_Transfer_Table(pc,d0.w),d0 jsr SS_PNTA_Transfer_Table(pc,d0.w) + bsr.w SSRun_Animation_Timers addi_.b #1,(SSTrack_drawing_index).w ; Run track timer move.b (SSTrack_drawing_index).w,d0 ; Get new timer value cmp.b d1,d0 ; Is it less than the player animation timer? blt.s +++ ; Branch if so move.b #0,(SSTrack_drawing_index).w ; Start drawing new frame lea (VDP_control_port).l,a6 tst.b (SS_Alternate_PNT).w ; Are we using the alternate address for plane A? beq.s + ; Branch if not move.w #$8200|(VRAM_SS_Plane_A_Name_Table1/$400),(a6) ; Set PNT A base to $C000 bra.s ++ ; =========================================================================== ;off_97A SS_PNTA_Transfer_Table: offsetTable offsetTableEntry.w loc_A50 ; 0 offsetTableEntry.w loc_A76 ; 1 offsetTableEntry.w loc_A9C ; 2 offsetTableEntry.w loc_AC2 ; 3 offsetTableEntry.w loc_9B8 ; 4 offsetTableEntry.w loc_9DE ; 5 offsetTableEntry.w loc_A04 ; 6 offsetTableEntry.w loc_A2A ; 7 ; =========================================================================== + move.w #$8200|(VRAM_SS_Plane_A_Name_Table2/$400),(a6) ; Set PNT A base to $8000 + eori.b #1,(SS_Alternate_PNT).w ; Toggle flag + bsr.w ProcessDMAQueue jsr (sndDriverInput).l startZ80 bsr.w ProcessDPLC2 tst.w (Demo_Time_left).w beq.w + ; rts subq.w #1,(Demo_Time_left).w + rts ; --------------------------------------------------------------------------- ; (!) ; Each of these functions copies one fourth of pattern name table A into VRAM ; from a buffer in main RAM. $700 bytes are copied each frame, with the target ; are in VRAM depending on the current drawing position. loc_9B8: dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table1 + 0 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM rts ; --------------------------------------------------------------------------- loc_9DE: dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table1 + 1 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM rts ; --------------------------------------------------------------------------- loc_A04: dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table1 + 2 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM rts ; --------------------------------------------------------------------------- loc_A2A: dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table1 + 3 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM rts ; --------------------------------------------------------------------------- loc_A50: dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table2 + 0 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM rts ; --------------------------------------------------------------------------- loc_A76: dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table2 + 1 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM rts ; --------------------------------------------------------------------------- loc_A9C: dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table2 + 2 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM rts ; --------------------------------------------------------------------------- loc_AC2: dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table2 + 3 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_AE8 SSSet_VScroll: move.w (VDP_control_port).l,d0 move.l #vdpComm($0000,VSRAM,WRITE),(VDP_control_port).l move.l (Vscroll_Factor).w,(VDP_data_port).l rts ; End of function SSSet_VScroll ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_B02 SSRun_Animation_Timers: move.w (SS_Cur_Speed_Factor).w,d0 ; Get current speed factor cmp.w (SS_New_Speed_Factor).w,d0 ; Has the speed factor changed? beq.s + ; Branch if yes move.l (SS_New_Speed_Factor).w,(SS_Cur_Speed_Factor).w ; Save new speed factor move.b #0,(SSTrack_duration_timer).w ; Reset timer + subi_.b #1,(SSTrack_duration_timer).w ; Run track timer bgt.s + ; Branch if not expired yet lea (SSAnim_Base_Duration).l,a0 move.w (SS_Cur_Speed_Factor).w,d0 ; The current speed factor is an index lsr.w #1,d0 move.b (a0,d0.w),d1 move.b d1,(SS_player_anim_frame_timer).w ; New player animation length (later halved) move.b d1,(SSTrack_duration_timer).w ; New track timer subq.b #1,(SS_player_anim_frame_timer).w ; Subtract one rts ; --------------------------------------------------------------------------- + move.b (SS_player_anim_frame_timer).w,d1 ; Get current player animatino length addq.b #1,d1 ; Increase it rts ; End of function SSRun_Animation_Timers ; =========================================================================== ;byte_B46 SSAnim_Base_Duration: dc.b 60 dc.b 30 ; 1 dc.b 15 ; 2 dc.b 10 ; 3 dc.b 8 ; 4 dc.b 6 ; 5 dc.b 5 ; 6 dc.b 0 ; 7 ; =========================================================================== ;VintSub1A Vint_CtrlDMA: stopZ80 jsr (ProcessDMAQueue).l startZ80 rts ; =========================================================================== ;VintSubC Vint_TitleCard: stopZ80 bsr.w ReadJoypads tst.b (Water_fullscreen_flag).w bne.s loc_BB2 dma68kToVDP Normal_palette,$0000,palette_line_size*4,CRAM bra.s loc_BD6 ; --------------------------------------------------------------------------- loc_BB2: dma68kToVDP Underwater_palette,$0000,palette_line_size*4,CRAM loc_BD6: move.w (Hint_counter_reserve).w,(a5) dma68kToVDP Horiz_Scroll_Buf,VRAM_Horiz_Scroll_Table,VRAM_Horiz_Scroll_Table_Size,VRAM dma68kToVDP Sprite_Table,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM bsr.w ProcessDMAQueue jsr (DrawLevelTitleCard).l jsr (sndDriverInput).l startZ80 movem.l (Camera_RAM).w,d0-d7 movem.l d0-d7,(Camera_RAM_copy).w movem.l (Scroll_flags).w,d0-d1 movem.l d0-d1,(Scroll_flags_copy).w move.l (Vscroll_Factor_P2).w,(Vscroll_Factor_P2_HInt).w bsr.w ProcessDPLC rts ; =========================================================================== ;VintSubE Vint_UnusedE: bsr.w Do_ControllerPal addq.b #1,(VIntSubE_RunCount).w move.b #VintID_UnusedE,(Vint_routine).w rts ; =========================================================================== ;VintSub12 Vint_Fade: bsr.w Do_ControllerPal move.w (Hint_counter_reserve).w,(a5) bra.w ProcessDPLC ; =========================================================================== ;VintSub18 Vint_Ending: stopZ80 bsr.w ReadJoypads dma68kToVDP Normal_palette,$0000,palette_line_size*4,CRAM dma68kToVDP Sprite_Table,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM dma68kToVDP Horiz_Scroll_Buf,VRAM_Horiz_Scroll_Table,VRAM_Horiz_Scroll_Table_Size,VRAM bsr.w ProcessDMAQueue bsr.w sndDriverInput movem.l (Camera_RAM).w,d0-d7 movem.l d0-d7,(Camera_RAM_copy).w movem.l (Scroll_flags).w,d0-d3 movem.l d0-d3,(Scroll_flags_copy).w jsrto (LoadTilesAsYouMove).l, JmpTo_LoadTilesAsYouMove startZ80 move.w (Ending_VInt_Subrout).w,d0 beq.s + ; rts clr.w (Ending_VInt_Subrout).w move.w off_D3C-2(pc,d0.w),d0 jsr off_D3C(pc,d0.w) + rts ; =========================================================================== off_D3C: offsetTable offsetTableEntry.w (+) ; 1 offsetTableEntry.w (++) ; 2 ; =========================================================================== + dmaFillVRAM 0,VRAM_EndSeq_Plane_A_Name_Table,VRAM_EndSeq_Plane_Table_Size ; VRAM Fill $C000 with $2000 zeros rts ; --------------------------------------------------------------------------- + dmaFillVRAM 0,VRAM_EndSeq_Plane_B_Name_Table2,VRAM_EndSeq_Plane_Table_Size dmaFillVRAM 0,VRAM_EndSeq_Plane_A_Name_Table,VRAM_EndSeq_Plane_Table_Size lea (VDP_control_port).l,a6 move.w #$8B00,(a6) ; EXT-INT off, V scroll by screen, H scroll by screen move.w #$8400|(VRAM_EndSeq_Plane_B_Name_Table2/$2000),(a6) ; PNT B base: $4000 move.w #$9011,(a6) ; Scroll table size: 64x64 lea (Chunk_Table).l,a1 move.l #vdpComm(VRAM_EndSeq_Plane_A_Name_Table + planeLocH40($16,$21),VRAM,WRITE),d0 ;$50AC0003 moveq #$16,d1 moveq #$E,d2 jsrto (PlaneMapToVRAM_H40).l, PlaneMapToVRAM_H40 rts ; =========================================================================== ;VintSub16 Vint_Menu: stopZ80 bsr.w ReadJoypads dma68kToVDP Normal_palette,$0000,palette_line_size*4,CRAM dma68kToVDP Sprite_Table,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM dma68kToVDP Horiz_Scroll_Buf,VRAM_Horiz_Scroll_Table,VRAM_Horiz_Scroll_Table_Size,VRAM bsr.w ProcessDMAQueue bsr.w sndDriverInput startZ80 bsr.w ProcessDPLC tst.w (Demo_Time_left).w beq.w + ; rts subq.w #1,(Demo_Time_left).w + rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_E98 Do_ControllerPal: stopZ80 bsr.w ReadJoypads tst.b (Water_fullscreen_flag).w bne.s loc_EDA dma68kToVDP Normal_palette,$0000,palette_line_size*4,CRAM bra.s loc_EFE ; --------------------------------------------------------------------------- loc_EDA: dma68kToVDP Underwater_palette,$0000,palette_line_size*4,CRAM loc_EFE: dma68kToVDP Sprite_Table,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM dma68kToVDP Horiz_Scroll_Buf,VRAM_Horiz_Scroll_Table,VRAM_Horiz_Scroll_Table_Size,VRAM bsr.w sndDriverInput startZ80 rts ; End of function sub_E98 ; ||||||||||||||| E N D O F V - I N T ||||||||||||||||||||||||||||||||||| ; =========================================================================== ; Start of H-INT code H_Int: tst.w (Hint_flag).w beq.w + tst.w (Two_player_mode).w beq.w PalToCRAM move.w #0,(Hint_flag).w move.l a5,-(sp) move.l d0,-(sp) - move.w (VDP_control_port).l,d0 ; loop start: Make sure V_BLANK is over andi.w #4,d0 beq.s - ; loop end move.w (VDP_Reg1_val).w,d0 andi.b #$BF,d0 move.w d0,(VDP_control_port).l ; Display disable move.w #$8200|(VRAM_Plane_A_Name_Table_2P/$400),(VDP_control_port).l ; PNT A base: $A000 move.l #vdpComm($0000,VSRAM,WRITE),(VDP_control_port).l move.l (Vscroll_Factor_P2_HInt).w,(VDP_data_port).l stopZ80 dma68kToVDP Sprite_Table_2,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM startZ80 - move.w (VDP_control_port).l,d0 andi.w #4,d0 beq.s - move.w (VDP_Reg1_val).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l ; Display enable move.l (sp)+,d0 movea.l (sp)+,a5 + rte ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; game code ; --------------------------------------------------------------------------- ; loc_1000: PalToCRAM: move #$2700,sr move.w #0,(Hint_flag).w movem.l a0-a1,-(sp) lea (VDP_data_port).l,a1 lea (Underwater_palette).w,a0 ; load palette from RAM move.l #vdpComm($0000,CRAM,WRITE),4(a1) ; set VDP to write to CRAM address $00 rept 32 move.l (a0)+,(a1) ; move palette to CRAM (all 64 colors at once) endm move.w #$8ADF,4(a1) ; Write %1101 %1111 to register 10 (interrupt every 224th line) movem.l (sp)+,a0-a1 tst.b (Do_Updates_in_H_int).w bne.s loc_1072 rte ; =========================================================================== loc_1072: clr.b (Do_Updates_in_H_int).w movem.l d0-a6,-(sp) bsr.w Do_Updates movem.l (sp)+,d0-a6 rte ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Input our music/sound selection to the sound driver. sndDriverInput: lea (Music_to_play&$00FFFFFF).l,a0 lea (Z80_RAM+zComRange).l,a1 ; $A01B80 cmpi.b #$80,zAbsVar.QueueToPlay-zComRange(a1) ; If this (zReadyFlag) isn't $80, the driver is processing a previous sound request. bne.s loc_10C4 ; So we'll wait until at least the next frame before putting anything in there. _move.b 0(a0),d0 beq.s loc_10A4 _clr.b 0(a0) bra.s loc_10AE ; --------------------------------------------------------------------------- loc_10A4: move.b 4(a0),d0 ; If there was something in Music_to_play_2, check what that was. Else, just go to the loop. beq.s loc_10C4 clr.b 4(a0) loc_10AE: ; Check that the sound is not FE or FF move.b d0,d1 ; If it is, we need to put it in $A01B83 as $7F or $80 respectively subi.b #MusID_Pause,d1 bcs.s loc_10C0 addi.b #$7F,d1 move.b d1,zAbsVar.StopMusic-zComRange(a1) bra.s loc_10C4 ; --------------------------------------------------------------------------- loc_10C0: move.b d0,zAbsVar.QueueToPlay-zComRange(a1) loc_10C4: moveq #4-1,d1 ; FFE4 (Music_to_play_2) goes to 1B8C (zMusicToPlay), - move.b 1(a0,d1.w),d0 ; FFE3 (unk_FFE3) goes to 1B8B, (unknown) beq.s + ; FFE2 (SFX_to_play_2) goes to 1B8A (zSFXToPlay2), tst.b zAbsVar.SFXToPlay-zComRange(a1,d1.w) ; FFE1 (SFX_to_play) goes to 1B89 (zSFXToPlay). bne.s + clr.b 1(a0,d1.w) move.b d0,zAbsVar.SFXToPlay-zComRange(a1,d1.w) + dbf d1,- rts ; End of function sndDriverInput if ~~removeJmpTos ; sub_10E0: JmpTo_LoadTilesAsYouMove jmp (LoadTilesAsYouMove).l JmpTo_SegaScr_VInt jmp (SegaScr_VInt).l align 4 endif ; --------------------------------------------------------------------------- ; Subroutine to initialize joypads ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_10EC: JoypadInit: stopZ80 moveq #$40,d0 move.b d0,(HW_Port_1_Control).l ; init port 1 (joypad 1) move.b d0,(HW_Port_2_Control).l ; init port 2 (joypad 2) move.b d0,(HW_Expansion_Control).l ; init port 3 (extra) startZ80 rts ; End of function JoypadInit ; --------------------------------------------------------------------------- ; Subroutine to read joypad input, and send it to the RAM ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_111C: ReadJoypads: lea (Ctrl_1).w,a0 ; address where joypad states are written lea (HW_Port_1_Data).l,a1 ; first joypad port bsr.s Joypad_Read ; do the first joypad addq.w #2,a1 ; do the second joypad ; End of function ReadJoypads ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_112A: Joypad_Read: move.b #0,(a1) nop nop move.b (a1),d0 lsl.b #2,d0 andi.b #$C0,d0 move.b #$40,(a1) nop nop move.b (a1),d1 andi.b #$3F,d1 or.b d1,d0 not.b d0 move.b (a0),d1 eor.b d0,d1 move.b d0,(a0)+ and.b d0,d1 move.b d1,(a0)+ rts ; End of function Joypad_Read ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_1158: VDPSetupGame: lea (VDP_control_port).l,a0 lea (VDP_data_port).l,a1 lea (VDPSetupArray).l,a2 moveq #bytesToWcnt(VDPSetupArray_End-VDPSetupArray),d7 ; loc_116C: VDP_Loop: move.w (a2)+,(a0) dbf d7,VDP_Loop ; set the VDP registers move.w (VDPSetupArray+2).l,d0 move.w d0,(VDP_Reg1_val).w move.w #$8ADF,(Hint_counter_reserve).w ; H-INT every 224th scanline moveq #0,d0 move.l #vdpComm($0000,VSRAM,WRITE),(VDP_control_port).l move.w d0,(a1) move.w d0,(a1) move.l #vdpComm($0000,CRAM,WRITE),(VDP_control_port).l move.w #bytesToWcnt(palette_line_size*4),d7 ; loc_11A0: VDP_ClrCRAM: move.w d0,(a1) dbf d7,VDP_ClrCRAM clr.l (Vscroll_Factor).w clr.l (unk_F61A).w move.l d1,-(sp) dmaFillVRAM 0,$0000,$10000 ; fill entire VRAM with 0 move.l (sp)+,d1 rts ; End of function VDPSetupGame ; =========================================================================== ; word_11E2: VDPSetupArray: dc.w $8004 ; H-INT disabled dc.w $8134 ; Genesis mode, DMA enabled, VBLANK-INT enabled dc.w $8200|(VRAM_Plane_A_Name_Table/$400) ; PNT A base: $C000 dc.w $8328 ; PNT W base: $A000 dc.w $8400|(VRAM_Plane_B_Name_Table/$2000) ; PNT B base: $E000 dc.w $8500|(VRAM_Sprite_Attribute_Table/$200) ; Sprite attribute table base: $F800 dc.w $8600 dc.w $8700 ; Background palette/color: 0/0 dc.w $8800 dc.w $8900 dc.w $8A00 ; H-INT every scanline dc.w $8B00 ; EXT-INT off, V scroll by screen, H scroll by screen dc.w $8C81 ; H res 40 cells, no interlace, S/H disabled dc.w $8D00|(VRAM_Horiz_Scroll_Table/$400) ; H scroll table base: $FC00 dc.w $8E00 dc.w $8F02 ; VRAM pointer increment: $0002 dc.w $9001 ; Scroll table size: 64x32 dc.w $9100 ; Disable window dc.w $9200 ; Disable window VDPSetupArray_End: ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_1208: ClearScreen: stopZ80 dmaFillVRAM 0,$0000,$40 ; Fill first $40 bytes of VRAM with 0 dmaFillVRAM 0,VRAM_Plane_A_Name_Table,VRAM_Plane_Table_Size ; Clear Plane A pattern name table dmaFillVRAM 0,VRAM_Plane_B_Name_Table,VRAM_Plane_Table_Size ; Clear Plane B pattern name table tst.w (Two_player_mode).w beq.s + dmaFillVRAM 0,VRAM_Plane_A_Name_Table_2P,VRAM_Plane_Table_Size + clr.l (Vscroll_Factor).w clr.l (unk_F61A).w ; Bug: These '+4's shouldn't be here; clearRAM accidentally clears an additional 4 bytes clearRAM Sprite_Table,Sprite_Table_End+4 clearRAM Horiz_Scroll_Buf,Horiz_Scroll_Buf_End+4 startZ80 rts ; End of function ClearScreen ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; JumpTo load the sound driver ; sub_130A: JmpTo_SoundDriverLoad nop jmp (SoundDriverLoad).l ; End of function JmpTo_SoundDriverLoad ; =========================================================================== ; unused mostly-leftover subroutine to load the sound driver ; SoundDriverLoadS1: move.w #$100,(Z80_Bus_Request).l ; stop the Z80 move.w #$100,(Z80_Reset).l ; reset the Z80 lea (Z80_RAM).l,a1 move.b #$F3,(a1)+ ; di move.b #$F3,(a1)+ ; di move.b #$C3,(a1)+ ; jp move.b #0,(a1)+ ; jp address low byte move.b #0,(a1)+ ; jp address high byte move.w #0,(Z80_Reset).l nop nop nop nop move.w #$100,(Z80_Reset).l ; reset the Z80 move.w #0,(Z80_Bus_Request).l ; start the Z80 rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; If Music_to_play is clear, move d0 into Music_to_play, ; else move d0 into Music_to_play_2. ; sub_135E: PlayMusic: tst.b (Music_to_play).w bne.s + move.b d0,(Music_to_play).w rts + move.b d0,(Music_to_play_2).w rts ; End of function PlayMusic ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_1370 PlaySound: move.b d0,(SFX_to_play).w rts ; End of function PlaySound ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; play a sound in alternating speakers (as in the ring collection sound) ; sub_1376: PlaySoundStereo: move.b d0,(SFX_to_play_2).w rts ; End of function PlaySoundStereo ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; play a sound if the source is onscreen ; sub_137C: PlaySoundLocal: tst.b render_flags(a0) bpl.s + ; rts move.b d0,(SFX_to_play).w + rts ; End of function PlaySoundLocal ; --------------------------------------------------------------------------- ; Subroutine to pause the game ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_1388: PauseGame: nop tst.b (Life_count).w ; do you have any lives left? beq.w Unpause ; if not, branch tst.w (Game_paused).w ; is game already paused? bne.s + ; if yes, branch move.b (Ctrl_1_Press).w,d0 ; is Start button pressed? or.b (Ctrl_2_Press).w,d0 ; (either player) andi.b #button_start_mask,d0 beq.s Pause_DoNothing ; if not, branch + move.w #1,(Game_paused).w ; freeze time move.b #MusID_Pause,(Music_to_play).w ; pause music ; loc_13B2: Pause_Loop: move.b #VintID_Pause,(Vint_routine).w bsr.w WaitForVint tst.b (Slow_motion_flag).w ; is slow-motion cheat on? beq.s Pause_ChkStart ; if not, branch btst #button_A,(Ctrl_1_Press).w ; is button A pressed? beq.s Pause_ChkBC ; if not, branch move.b #GameModeID_TitleScreen,(Game_Mode).w ; => TitleScreen nop bra.s Pause_Resume ; =========================================================================== ; loc_13D4: Pause_ChkBC: btst #button_B,(Ctrl_1_Held).w ; is button B pressed? bne.s Pause_SlowMo ; if yes, branch btst #button_C,(Ctrl_1_Press).w ; is button C pressed? bne.s Pause_SlowMo ; if yes, branch ; loc_13E4: Pause_ChkStart: move.b (Ctrl_1_Press).w,d0 ; is Start button pressed? or.b (Ctrl_2_Press).w,d0 ; (either player) andi.b #button_start_mask,d0 beq.s Pause_Loop ; if not, branch ; loc_13F2: Pause_Resume: move.b #MusID_Unpause,(Music_to_play).w ; loc_13F8: Unpause: move.w #0,(Game_paused).w ; return_13FE: Pause_DoNothing: rts ; =========================================================================== ; loc_1400: Pause_SlowMo: move.w #1,(Game_paused).w move.b #MusID_Unpause,(Music_to_play).w rts ; End of function PauseGame ; --------------------------------------------------------------------------- ; Subroutine to transfer a plane map to VRAM ; --------------------------------------------------------------------------- ; control register: ; CD1 CD0 A13 A12 A11 A10 A09 A08 (D31-D24) ; A07 A06 A05 A04 A03 A02 A01 A00 (D23-D16) ; ? ? ? ? ? ? ? ? (D15-D8) ; CD5 CD4 CD3 CD2 ? ? A15 A14 (D7-D0) ; ; A00-A15 - address ; CD0-CD3 - code ; CD4 - 1 if VRAM copy DMA mode. 0 otherwise. ; CD5 - DMA operation ; ; Bits CD3-CD0: ; 0000 - VRAM read ; 0001 - VRAM write ; 0011 - CRAM write ; 0100 - VSRAM read ; 0101 - VSRAM write ; 1000 - CRAM read ; ; d0 = control register ; d1 = width ; d2 = heigth ; a1 = source address ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_140E: ShowVDPGraphics: PlaneMapToVRAM: PlaneMapToVRAM_H40: lea (VDP_data_port).l,a6 move.l #vdpCommDelta(planeLocH40(0,1)),d4 ; $800000 - move.l d0,VDP_control_port-VDP_data_port(a6) ; move d0 to VDP_control_port move.w d1,d3 - move.w (a1)+,(a6) ; from source address to destination in VDP dbf d3,- ; next tile add.l d4,d0 ; increase destination address by $80 (1 line) dbf d2,-- ; next line rts ; End of function PlaneMapToVRAM_H40 ; --------------------------------------------------------------------------- ; Alternate subroutine to transfer a plane map to VRAM ; (used for Special Stage background) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_142E: ShowVDPGraphics2: PlaneMapToVRAM2: PlaneMapToVRAM_H80_SpecialStage: lea (VDP_data_port).l,a6 move.l #vdpCommDelta(planeLocH80(0,1)),d4 ; $1000000 - move.l d0,VDP_control_port-VDP_data_port(a6) move.w d1,d3 - move.w (a1)+,(a6) dbf d3,- add.l d4,d0 dbf d2,-- rts ; End of function PlaneMapToVRAM_H80_SpecialStage ; --------------------------------------------------------------------------- ; Subroutine for queueing VDP commands (seems to only queue transfers to VRAM), ; to be issued the next time ProcessDMAQueue is called. ; Can be called a maximum of 18 times before the buffer needs to be cleared ; by issuing the commands (this subroutine DOES check for overflow) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_144E: DMA_68KtoVRAM: QueueCopyToVRAM: QueueVDPCommand: Add_To_DMA_Queue: QueueDMATransfer: movea.l (VDP_Command_Buffer_Slot).w,a1 cmpa.w #VDP_Command_Buffer_Slot,a1 beq.s QueueDMATransfer_Done ; return if there's no more room in the buffer ; piece together some VDP commands and store them for later... move.w #$9300,d0 ; command to specify DMA transfer length & $00FF move.b d3,d0 move.w d0,(a1)+ ; store command move.w #$9400,d0 ; command to specify DMA transfer length & $FF00 lsr.w #8,d3 move.b d3,d0 move.w d0,(a1)+ ; store command move.w #$9500,d0 ; command to specify source address & $0001FE lsr.l #1,d1 move.b d1,d0 move.w d0,(a1)+ ; store command move.w #$9600,d0 ; command to specify source address & $01FE00 lsr.l #8,d1 move.b d1,d0 move.w d0,(a1)+ ; store command move.w #$9700,d0 ; command to specify source address & $FE0000 lsr.l #8,d1 ;andi.b #$7F,d1 ; this instruction safely allows source to be in RAM; S3K added this move.b d1,d0 move.w d0,(a1)+ ; store command andi.l #$FFFF,d2 ; command to specify destination address and begin DMA lsl.l #2,d2 lsr.w #2,d2 swap d2 ori.l #vdpComm($0000,VRAM,DMA),d2 ; set bits to specify VRAM transfer move.l d2,(a1)+ ; store command move.l a1,(VDP_Command_Buffer_Slot).w ; set the next free slot address cmpa.w #VDP_Command_Buffer_Slot,a1 beq.s QueueDMATransfer_Done ; return if there's no more room in the buffer move.w #0,(a1) ; put a stop token at the end of the used part of the buffer ; return_14AA: QueueDMATransfer_Done: rts ; End of function QueueDMATransfer ; --------------------------------------------------------------------------- ; Subroutine for issuing all VDP commands that were queued ; (by earlier calls to QueueDMATransfer) ; Resets the queue when it's done ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_14AC: CopyToVRAM: IssueVDPCommands: Process_DMA: Process_DMA_Queue: ProcessDMAQueue: lea (VDP_control_port).l,a5 lea (VDP_Command_Buffer).w,a1 ; loc_14B6: ProcessDMAQueue_Loop: move.w (a1)+,d0 beq.s ProcessDMAQueue_Done ; branch if we reached a stop token ; issue a set of VDP commands... move.w d0,(a5) ; transfer length move.w (a1)+,(a5) ; transfer length move.w (a1)+,(a5) ; source address move.w (a1)+,(a5) ; source address move.w (a1)+,(a5) ; source address move.w (a1)+,(a5) ; destination move.w (a1)+,(a5) ; destination cmpa.w #VDP_Command_Buffer_Slot,a1 bne.s ProcessDMAQueue_Loop ; loop if we haven't reached the end of the buffer ; loc_14CE: ProcessDMAQueue_Done: move.w #0,(VDP_Command_Buffer).w move.l #VDP_Command_Buffer,(VDP_Command_Buffer_Slot).w rts ; End of function ProcessDMAQueue ; --------------------------------------------------------------------------- ; START OF NEMESIS DECOMPRESSOR ; For format explanation see http://info.sonicretro.org/Nemesis_compression ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Nemesis decompression to VRAM ; sub_14DE: NemDecA: NemDec: movem.l d0-a1/a3-a5,-(sp) lea (NemDec_WriteAndStay).l,a3 ; write all data to the same location lea (VDP_data_port).l,a4 ; specifically, to the VDP data port bra.s NemDecMain ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Nemesis decompression to RAM ; input: a4 = starting address of destination ; sub_14F0: NemDecB: NemDecToRAM: movem.l d0-a1/a3-a5,-(sp) lea (NemDec_WriteAndAdvance).l,a3 ; advance to the next location after each write ; sub_14FA: NemDecMain: lea (Decomp_Buffer).w,a1 move.w (a0)+,d2 lsl.w #1,d2 bcc.s + adda.w #NemDec_WriteAndStay_XOR-NemDec_WriteAndStay,a3 + lsl.w #2,d2 movea.w d2,a5 moveq #8,d3 moveq #0,d2 moveq #0,d4 bsr.w NemDecPrepare move.b (a0)+,d5 asl.w #8,d5 move.b (a0)+,d5 move.w #$10,d6 bsr.s NemDecRun movem.l (sp)+,d0-a1/a3-a5 rts ; End of function NemDec ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; part of the Nemesis decompressor ; sub_1528: NemDecRun: move.w d6,d7 subq.w #8,d7 move.w d5,d1 lsr.w d7,d1 cmpi.b #-4,d1 bhs.s loc_1574 andi.w #$FF,d1 add.w d1,d1 move.b (a1,d1.w),d0 ext.w d0 sub.w d0,d6 cmpi.w #9,d6 bhs.s + addq.w #8,d6 asl.w #8,d5 move.b (a0)+,d5 + move.b 1(a1,d1.w),d1 move.w d1,d0 andi.w #$F,d1 andi.w #$F0,d0 loc_155E: lsr.w #4,d0 loc_1560: lsl.l #4,d4 or.b d1,d4 subq.w #1,d3 bne.s NemDec_WriteIter_Part2 jmp (a3) ; dynamic jump! to NemDec_WriteAndStay, NemDec_WriteAndAdvance, NemDec_WriteAndStay_XOR, or NemDec_WriteAndAdvance_XOR ; =========================================================================== ; loc_156A: NemDec_WriteIter: moveq #0,d4 moveq #8,d3 ; loc_156E: NemDec_WriteIter_Part2: dbf d0,loc_1560 bra.s NemDecRun ; =========================================================================== loc_1574: subq.w #6,d6 cmpi.w #9,d6 bhs.s + addq.w #8,d6 asl.w #8,d5 move.b (a0)+,d5 + subq.w #7,d6 move.w d5,d1 lsr.w d6,d1 move.w d1,d0 andi.w #$F,d1 andi.w #$70,d0 cmpi.w #9,d6 bhs.s loc_155E addq.w #8,d6 asl.w #8,d5 move.b (a0)+,d5 bra.s loc_155E ; End of function NemDecRun ; =========================================================================== ; loc_15A0: NemDec_WriteAndStay: move.l d4,(a4) subq.w #1,a5 move.w a5,d4 bne.s NemDec_WriteIter rts ; --------------------------------------------------------------------------- ; loc_15AA: NemDec_WriteAndStay_XOR: eor.l d4,d2 move.l d2,(a4) subq.w #1,a5 move.w a5,d4 bne.s NemDec_WriteIter rts ; =========================================================================== ; loc_15B6: NemDec_WriteAndAdvance: move.l d4,(a4)+ subq.w #1,a5 move.w a5,d4 bne.s NemDec_WriteIter rts if *-NemDec_WriteAndAdvance > NemDec_WriteAndStay_XOR-NemDec_WriteAndStay fatal "the code in NemDec_WriteAndAdvance must not be larger than the code in NemDec_WriteAndStay" endif org NemDec_WriteAndAdvance+NemDec_WriteAndStay_XOR-NemDec_WriteAndStay ; --------------------------------------------------------------------------- ; loc_15C0: NemDec_WriteAndAdvance_XOR: eor.l d4,d2 move.l d2,(a4)+ subq.w #1,a5 move.w a5,d4 bne.s NemDec_WriteIter rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Part of the Nemesis decompressor ; sub_15CC: NemDecPrepare: move.b (a0)+,d0 - cmpi.b #$FF,d0 bne.s + rts ; --------------------------------------------------------------------------- + move.w d0,d7 loc_15D8: move.b (a0)+,d0 cmpi.b #$80,d0 bhs.s - move.b d0,d1 andi.w #$F,d7 andi.w #$70,d1 or.w d1,d7 andi.w #$F,d0 move.b d0,d1 lsl.w #8,d1 or.w d1,d7 moveq #8,d1 sub.w d0,d1 bne.s loc_1606 move.b (a0)+,d0 add.w d0,d0 move.w d7,(a1,d0.w) bra.s loc_15D8 ; --------------------------------------------------------------------------- loc_1606: move.b (a0)+,d0 lsl.w d1,d0 add.w d0,d0 moveq #1,d5 lsl.w d1,d5 subq.w #1,d5 - move.w d7,(a1,d0.w) addq.w #2,d0 dbf d5,- bra.s loc_15D8 ; End of function NemDecPrepare ; --------------------------------------------------------------------------- ; END OF NEMESIS DECOMPRESSOR ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; --------------------------------------------------------------------------- ; Subroutine to load pattern load cues (aka to queue pattern load requests) ; --------------------------------------------------------------------------- ; ARGUMENTS ; d0 = index of PLC list (see ArtLoadCues) ; NOTICE: This subroutine does not check for buffer overruns. The programmer ; (or hacker) is responsible for making sure that no more than ; 16 load requests are copied into the buffer. ; _________DO NOT PUT MORE THAN 16 LOAD REQUESTS IN A LIST!__________ ; (or if you change the size of Plc_Buffer, the limit becomes (Plc_Buffer_Only_End-Plc_Buffer)/6) ; sub_161E: PLCLoad: LoadPLC: movem.l a1-a2,-(sp) lea (ArtLoadCues).l,a1 add.w d0,d0 move.w (a1,d0.w),d0 lea (a1,d0.w),a1 lea (Plc_Buffer).w,a2 - tst.l (a2) beq.s + ; if it's zero, exit this loop addq.w #6,a2 bra.s - + move.w (a1)+,d0 bmi.s + ; if it's negative, skip the next loop - move.l (a1)+,(a2)+ move.w (a1)+,(a2)+ dbf d0,- + movem.l (sp)+,a1-a2 ; a1=object rts ; End of function LoadPLC ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Queue pattern load requests, but clear the PLQ first ; ARGUMENTS ; d0 = index of PLC list (see ArtLoadCues) ; NOTICE: This subroutine does not check for buffer overruns. The programmer ; (or hacker) is responsible for making sure that no more than ; 16 load requests are copied into the buffer. ; _________DO NOT PUT MORE THAN 16 LOAD REQUESTS IN A LIST!__________ ; (or if you change the size of Plc_Buffer, the limit becomes (Plc_Buffer_Only_End-Plc_Buffer)/6) ; sub_1650: LoadPLC2: movem.l a1-a2,-(sp) lea (ArtLoadCues).l,a1 add.w d0,d0 move.w (a1,d0.w),d0 lea (a1,d0.w),a1 bsr.s ClearPLC lea (Plc_Buffer).w,a2 move.w (a1)+,d0 bmi.s + ; if it's negative, skip the next loop - move.l (a1)+,(a2)+ move.w (a1)+,(a2)+ dbf d0,- + movem.l (sp)+,a1-a2 rts ; End of function LoadPLC2 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Clear the pattern load queue ($FFF680 - $FFF700) ClearPLC: lea (Plc_Buffer).w,a2 moveq #bytesToLcnt(Plc_Buffer_End-Plc_Buffer),d0 - clr.l (a2)+ dbf d0,- rts ; End of function ClearPLC ; --------------------------------------------------------------------------- ; Subroutine to use graphics listed in a pattern load cue ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_168A: RunPLC_RAM: tst.l (Plc_Buffer).w beq.s ++ ; rts tst.w (Plc_Buffer_Reg18).w bne.s ++ ; rts movea.l (Plc_Buffer).w,a0 lea_ NemDec_WriteAndStay,a3 nop lea (Decomp_Buffer).w,a1 move.w (a0)+,d2 bpl.s + adda.w #NemDec_WriteAndStay_XOR-NemDec_WriteAndStay,a3 + andi.w #$7FFF,d2 move.w d2,(Plc_Buffer_Reg18).w bsr.w NemDecPrepare move.b (a0)+,d5 asl.w #8,d5 move.b (a0)+,d5 moveq #$10,d6 moveq #0,d0 move.l a0,(Plc_Buffer).w move.l a3,(Plc_Buffer_Reg0).w move.l d0,(Plc_Buffer_Reg4).w move.l d0,(Plc_Buffer_Reg8).w move.l d0,(Plc_Buffer_RegC).w move.l d5,(Plc_Buffer_Reg10).w move.l d6,(Plc_Buffer_Reg14).w + rts ; End of function RunPLC_RAM ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Process one PLC from the queue ; sub_16E0: ProcessDPLC: tst.w (Plc_Buffer_Reg18).w beq.w + ; rts move.w #6,(Plc_Buffer_Reg1A).w moveq #0,d0 move.w (Plc_Buffer+4).w,d0 addi.w #$C0,(Plc_Buffer+4).w bra.s ProcessDPLC_Main ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Process one PLC from the queue ; loc_16FC: ProcessDPLC2: tst.w (Plc_Buffer_Reg18).w beq.s + ; rts move.w #3,(Plc_Buffer_Reg1A).w moveq #0,d0 move.w (Plc_Buffer+4).w,d0 addi.w #$60,(Plc_Buffer+4).w ; loc_1714: ProcessDPLC_Main: lea (VDP_control_port).l,a4 lsl.l #2,d0 ; set up target VRAM address lsr.w #2,d0 ori.w #vdpComm($0000,VRAM,WRITE)>>16,d0 swap d0 move.l d0,(a4) subq.w #4,a4 movea.l (Plc_Buffer).w,a0 movea.l (Plc_Buffer_Reg0).w,a3 move.l (Plc_Buffer_Reg4).w,d0 move.l (Plc_Buffer_Reg8).w,d1 move.l (Plc_Buffer_RegC).w,d2 move.l (Plc_Buffer_Reg10).w,d5 move.l (Plc_Buffer_Reg14).w,d6 lea (Decomp_Buffer).w,a1 - movea.w #8,a5 bsr.w NemDec_WriteIter subq.w #1,(Plc_Buffer_Reg18).w beq.s ProcessDPLC_Pop subq.w #1,(Plc_Buffer_Reg1A).w bne.s - move.l a0,(Plc_Buffer).w move.l a3,(Plc_Buffer_Reg0).w move.l d0,(Plc_Buffer_Reg4).w move.l d1,(Plc_Buffer_Reg8).w move.l d2,(Plc_Buffer_RegC).w move.l d5,(Plc_Buffer_Reg10).w move.l d6,(Plc_Buffer_Reg14).w + rts ; =========================================================================== ; pop one request off the buffer so that the next one can be filled ; loc_177A: ProcessDPLC_Pop: lea (Plc_Buffer).w,a0 moveq #bytesToLcnt(Plc_Buffer_Only_End-Plc_Buffer-6),d0 - move.l 6(a0),(a0)+ dbf d0,- rts ; End of function ProcessDPLC ; --------------------------------------------------------------------------- ; Subroutine to execute a pattern load cue directly from the ROM ; rather than loading them into the queue first ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| RunPLC_ROM: lea (ArtLoadCues).l,a1 add.w d0,d0 move.w (a1,d0.w),d0 lea (a1,d0.w),a1 move.w (a1)+,d1 - movea.l (a1)+,a0 moveq #0,d0 move.w (a1)+,d0 lsl.l #2,d0 lsr.w #2,d0 ori.w #vdpComm($0000,VRAM,WRITE)>>16,d0 swap d0 move.l d0,(VDP_control_port).l bsr.w NemDec dbf d1,- rts ; End of function RunPLC_ROM ; --------------------------------------------------------------------------- ; Enigma Decompression Algorithm ; ARGUMENTS: ; d0 = starting art tile (added to each 8x8 before writing to destination) ; a0 = source address ; a1 = destination address ; For format explanation see http://info.sonicretro.org/Enigma_compression ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; EniDec_17BC: EniDec: movem.l d0-d7/a1-a5,-(sp) movea.w d0,a3 ; store starting art tile move.b (a0)+,d0 ext.w d0 movea.w d0,a5 ; store first byte, extended to word move.b (a0)+,d4 ; store second byte lsl.b #3,d4 ; multiply by 8 movea.w (a0)+,a2 ; store third and fourth byte adda.w a3,a2 ; add starting art tile movea.w (a0)+,a4 ; store fifth and sixth byte adda.w a3,a4 ; add starting art tile move.b (a0)+,d5 ; store seventh byte asl.w #8,d5 ; shift up by a byte move.b (a0)+,d5 ; store eighth byte in lower register byte moveq #16,d6 ; 16 bits = 2 bytes EniDec_Loop: moveq #7,d0 ; process 7 bits at a time move.w d6,d7 sub.w d0,d7 move.w d5,d1 lsr.w d7,d1 andi.w #$7F,d1 ; keep only lower 7 bits move.w d1,d2 cmpi.w #$40,d1 ; is bit 6 set? bhs.s + ; if it is, branch moveq #6,d0 ; if not, process 6 bits instead of 7 lsr.w #1,d2 ; bitfield now becomes TTSSSS instead of TTTSSSS + bsr.w EniDec_ChkGetNextByte andi.w #$F,d2 ; keep only lower nybble lsr.w #4,d1 ; store upper nybble (max value = 7) add.w d1,d1 jmp EniDec_JmpTable(pc,d1.w) ; End of function EniDec ; =========================================================================== EniDec_Sub0: move.w a2,(a1)+ ; write to destination addq.w #1,a2 ; increment dbf d2,EniDec_Sub0 ; repeat bra.s EniDec_Loop ; =========================================================================== EniDec_Sub4: move.w a4,(a1)+ ; write to destination dbf d2,EniDec_Sub4 ; repeat bra.s EniDec_Loop ; =========================================================================== EniDec_Sub8: bsr.w EniDec_GetInlineCopyVal - move.w d1,(a1)+ dbf d2,- bra.s EniDec_Loop ; =========================================================================== EniDec_SubA: bsr.w EniDec_GetInlineCopyVal - move.w d1,(a1)+ addq.w #1,d1 dbf d2,- bra.s EniDec_Loop ; =========================================================================== EniDec_SubC: bsr.w EniDec_GetInlineCopyVal - move.w d1,(a1)+ subq.w #1,d1 dbf d2,- bra.s EniDec_Loop ; =========================================================================== EniDec_SubE: cmpi.w #$F,d2 beq.s EniDec_End - bsr.w EniDec_GetInlineCopyVal move.w d1,(a1)+ dbf d2,- bra.s EniDec_Loop ; =========================================================================== ; Enigma_JmpTable: EniDec_JmpTable: bra.s EniDec_Sub0 bra.s EniDec_Sub0 bra.s EniDec_Sub4 bra.s EniDec_Sub4 bra.s EniDec_Sub8 bra.s EniDec_SubA bra.s EniDec_SubC bra.s EniDec_SubE ; =========================================================================== EniDec_End: subq.w #1,a0 cmpi.w #16,d6 ; were we going to start on a completely new byte? bne.s + ; if not, branch subq.w #1,a0 + move.w a0,d0 lsr.w #1,d0 ; are we on an odd byte? bcc.s + ; if not, branch addq.w #1,a0 ; ensure we're on an even byte + movem.l (sp)+,d0-d7/a1-a5 rts ; S U B R O U T I N E EniDec_GetInlineCopyVal: move.w a3,d3 ; store starting art tile move.b d4,d1 add.b d1,d1 bcc.s + ; if d4 was < $80 subq.w #1,d6 ; get next bit number btst d6,d5 ; is the bit set? beq.s + ; if not, branch ori.w #high_priority,d3 ; set high priority bit + add.b d1,d1 bcc.s + ; if d4 was < $40 subq.w #1,d6 ; get next bit number btst d6,d5 beq.s + addi.w #palette_line_2,d3 ; set second palette line bit + add.b d1,d1 bcc.s + ; if d4 was < $20 subq.w #1,d6 ; get next bit number btst d6,d5 beq.s + addi.w #palette_line_1,d3 ; set first palette line bit + add.b d1,d1 bcc.s + ; if d4 was < $10 subq.w #1,d6 ; get next bit number btst d6,d5 beq.s + ori.w #flip_y,d3 ; set Y-flip bit + add.b d1,d1 bcc.s + ; if d4 was < 8 subq.w #1,d6 btst d6,d5 beq.s + ori.w #flip_x,d3 ; set X-flip bit + move.w d5,d1 move.w d6,d7 ; get remaining bits sub.w a5,d7 ; subtract minimum bit number bcc.s + ; if we're beyond that, branch move.w d7,d6 addi.w #16,d6 ; 16 bits = 2 bytes neg.w d7 ; calculate bit deficit lsl.w d7,d1 ; make space for this many bits move.b (a0),d5 ; get next byte rol.b d7,d5 ; make the upper X bits the lower X bits add.w d7,d7 and.w EniDec_AndVals-2(pc,d7.w),d5 ; only keep X lower bits add.w d5,d1 ; compensate for the bit deficit - move.w a5,d0 add.w d0,d0 and.w EniDec_AndVals-2(pc,d0.w),d1 ; only keep as many bits as required add.w d3,d1 ; add starting art tile move.b (a0)+,d5 ; get current byte, move onto next byte lsl.w #8,d5 ; shift up by a byte move.b (a0)+,d5 ; store next byte in lower register byte rts ; =========================================================================== + beq.s + ; if the exact number of bits are leftover, branch lsr.w d7,d1 ; remove unneeded bits move.w a5,d0 add.w d0,d0 and.w EniDec_AndVals-2(pc,d0.w),d1 ; only keep as many bits as required add.w d3,d1 ; add starting art tile move.w a5,d0 ; store number of bits used up by inline copy bra.s EniDec_ChkGetNextByte ; move onto next byte ; =========================================================================== + moveq #16,d6 ; 16 bits = 2 bytes bra.s - ; End of function EniDec_GetInlineCopyVal ; =========================================================================== ; word_190A: EniDec_AndVals: dc.w 1, 3, 7, $F dc.w $1F, $3F, $7F, $FF dc.w $1FF, $3FF, $7FF, $FFF dc.w $1FFF,$3FFF,$7FFF,$FFFF ; =========================================================================== EniDec_ChkGetNextByte: sub.w d0,d6 cmpi.w #9,d6 bhs.s + ; rts addq.w #8,d6 ; 8 bits = 1 byte asl.w #8,d5 ; shift up by a byte move.b (a0)+,d5 ; store next byte in lower register byte + rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; --------------------------------------------------------------------------- ; KOSINSKI DECOMPRESSION PROCEDURE ; (sometimes called KOZINSKI decompression) ; This is the only procedure in the game that stores variables on the stack. ; ARGUMENTS: ; a0 = source address ; a1 = destination address ; For format explanation see http://info.sonicretro.org/Kosinski_compression ; --------------------------------------------------------------------------- ; KozDec_193A: KosDec: subq.l #2,sp move.b (a0)+,1(sp) move.b (a0)+,(sp) move.w (sp),d5 moveq #$F,d4 - lsr.w #1,d5 move sr,d6 dbf d4,+ move.b (a0)+,1(sp) move.b (a0)+,(sp) move.w (sp),d5 moveq #$F,d4 + move d6,ccr bcc.s + move.b (a0)+,(a1)+ bra.s - ; --------------------------------------------------------------------------- + moveq #0,d3 lsr.w #1,d5 move sr,d6 dbf d4,+ move.b (a0)+,1(sp) move.b (a0)+,(sp) move.w (sp),d5 moveq #$F,d4 + move d6,ccr bcs.s +++ lsr.w #1,d5 dbf d4,+ move.b (a0)+,1(sp) move.b (a0)+,(sp) move.w (sp),d5 moveq #$F,d4 + roxl.w #1,d3 lsr.w #1,d5 dbf d4,+ move.b (a0)+,1(sp) move.b (a0)+,(sp) move.w (sp),d5 moveq #$F,d4 + roxl.w #1,d3 addq.w #1,d3 moveq #-1,d2 move.b (a0)+,d2 bra.s ++ ; --------------------------------------------------------------------------- + move.b (a0)+,d0 move.b (a0)+,d1 moveq #-1,d2 move.b d1,d2 lsl.w #5,d2 move.b d0,d2 andi.w #7,d1 beq.s ++ move.b d1,d3 addq.w #1,d3 / move.b (a1,d2.w),d0 move.b d0,(a1)+ dbf d3,- bra.s -- ; --------------------------------------------------------------------------- + move.b (a0)+,d1 beq.s + cmpi.b #1,d1 beq.w -- move.b d1,d3 bra.s - ; --------------------------------------------------------------------------- + addq.l #2,sp rts ; End of function KosDec ; =========================================================================== if gameRevision<2 nop endif ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_19DC: PalCycle_Load: bsr.w PalCycle_SuperSonic moveq #0,d2 moveq #0,d0 move.b (Current_Zone).w,d0 ; use level number as index into palette cycles add.w d0,d0 ; (multiply by element size = 2 bytes) move.w PalCycle(pc,d0.w),d0 ; load animated palettes offset index into d0 jmp PalCycle(pc,d0.w) ; jump to PalCycle + offset index ; --------------------------------------------------------------------------- rts ; End of function PalCycle_Load ; =========================================================================== ; off_19F4: PalCycle: zoneOrderedOffsetTable 2,1 zoneOffsetTableEntry.w PalCycle_EHZ ; 0 zoneOffsetTableEntry.w PalCycle_Null ; 1 zoneOffsetTableEntry.w PalCycle_WZ ; 2 zoneOffsetTableEntry.w PalCycle_Null ; 3 zoneOffsetTableEntry.w PalCycle_MTZ ; 4 zoneOffsetTableEntry.w PalCycle_MTZ ; 5 zoneOffsetTableEntry.w PalCycle_WFZ ; 6 zoneOffsetTableEntry.w PalCycle_HTZ ; 7 zoneOffsetTableEntry.w PalCycle_HPZ ; 8 zoneOffsetTableEntry.w PalCycle_Null ; 9 zoneOffsetTableEntry.w PalCycle_OOZ ; 10 zoneOffsetTableEntry.w PalCycle_MCZ ; 11 zoneOffsetTableEntry.w PalCycle_CNZ ; 12 zoneOffsetTableEntry.w PalCycle_CPZ ; 13 zoneOffsetTableEntry.w PalCycle_CPZ ; 14 zoneOffsetTableEntry.w PalCycle_ARZ ; 15 zoneOffsetTableEntry.w PalCycle_WFZ ; 16 zoneTableEnd ; =========================================================================== ; return_1A16: PalCycle_Null: rts ; =========================================================================== PalCycle_EHZ: lea (CyclingPal_EHZ_ARZ_Water).l,a0 subq.w #1,(PalCycle_Timer).w bpl.s + ; rts move.w #7,(PalCycle_Timer).w move.w (PalCycle_Frame).w,d0 addq.w #1,(PalCycle_Frame).w andi.w #3,d0 lsl.w #3,d0 move.l (a0,d0.w),(Normal_palette_line2+6).w move.l 4(a0,d0.w),(Normal_palette_line2+$1C).w + rts ; =========================================================================== ; PalCycle_Level2: PalCycle_WZ: subq.w #1,(PalCycle_Timer).w bpl.s ++ ; rts move.w #2,(PalCycle_Timer).w lea (CyclingPal_WoodConveyor).l,a0 move.w (PalCycle_Frame).w,d0 subq.w #2,(PalCycle_Frame).w bcc.s + move.w #6,(PalCycle_Frame).w + lea (Normal_palette_line4+6).w,a1 move.l (a0,d0.w),(a1)+ move.l 4(a0,d0.w),(a1) + rts ; =========================================================================== PalCycle_MTZ: subq.w #1,(PalCycle_Timer).w bpl.s ++ move.w #$11,(PalCycle_Timer).w lea (CyclingPal_MTZ1).l,a0 move.w (PalCycle_Frame).w,d0 addq.w #2,(PalCycle_Frame).w cmpi.w #$C,(PalCycle_Frame).w blo.s + move.w #0,(PalCycle_Frame).w + lea (Normal_palette_line3+$A).w,a1 move.w (a0,d0.w),(a1) + subq.w #1,(PalCycle_Timer2).w bpl.s ++ move.w #2,(PalCycle_Timer2).w lea (CyclingPal_MTZ2).l,a0 move.w (PalCycle_Frame2).w,d0 addq.w #2,(PalCycle_Frame2).w cmpi.w #6,(PalCycle_Frame2).w blo.s + move.w #0,(PalCycle_Frame2).w + lea (Normal_palette_line3+2).w,a1 move.l (a0,d0.w),(a1)+ move.w 4(a0,d0.w),(a1) + subq.w #1,(PalCycle_Timer3).w bpl.s ++ ; rts move.w #9,(PalCycle_Timer3).w lea (CyclingPal_MTZ3).l,a0 move.w (PalCycle_Frame3).w,d0 addq.w #2,(PalCycle_Frame3).w cmpi.w #$14,(PalCycle_Frame3).w blo.s + move.w #0,(PalCycle_Frame3).w + lea (Normal_palette_line3+$1E).w,a1 move.w (a0,d0.w),(a1) + rts ; =========================================================================== PalCycle_HTZ: lea (CyclingPal_Lava).l,a0 subq.w #1,(PalCycle_Timer).w bpl.s + ; rts move.w #0,(PalCycle_Timer).w move.w (PalCycle_Frame).w,d0 addq.w #1,(PalCycle_Frame).w andi.w #$F,d0 move.b PalCycle_HTZ_LavaDelayData(pc,d0.w),(PalCycle_Timer+1).w lsl.w #3,d0 move.l (a0,d0.w),(Normal_palette_line2+6).w move.l 4(a0,d0.w),(Normal_palette_line2+$1C).w + rts ; =========================================================================== ; byte_1B40: PalCycle_HTZ_LavaDelayData: ; number of frames between changes of the lava palette dc.b $B, $B, $B, $A dc.b 8, $A, $B, $B dc.b $B, $B, $D, $F dc.b $D, $B, $B, $B ; =========================================================================== PalCycle_HPZ: subq.w #1,(PalCycle_Timer).w bpl.s ++ ; rts move.w #4,(PalCycle_Timer).w lea (CyclingPal_HPZWater).l,a0 move.w (PalCycle_Frame).w,d0 subq.w #2,(PalCycle_Frame).w bcc.s + move.w #6,(PalCycle_Frame).w + lea (Normal_palette_line4+$12).w,a1 move.l (a0,d0.w),(a1)+ move.l 4(a0,d0.w),(a1) lea (CyclingPal_HPZUnderwater).l,a0 lea (Underwater_palette_line4+$12).w,a1 move.l (a0,d0.w),(a1)+ move.l 4(a0,d0.w),(a1) + rts ; =========================================================================== PalCycle_OOZ: subq.w #1,(PalCycle_Timer).w bpl.s + ; rts move.w #7,(PalCycle_Timer).w lea (CyclingPal_Oil).l,a0 move.w (PalCycle_Frame).w,d0 addq.w #2,(PalCycle_Frame).w andi.w #6,(PalCycle_Frame).w lea (Normal_palette_line3+$14).w,a1 move.l (a0,d0.w),(a1)+ move.l 4(a0,d0.w),(a1) + rts ; =========================================================================== PalCycle_MCZ: tst.b (Current_Boss_ID).w bne.s + ; rts subq.w #1,(PalCycle_Timer).w bpl.s + ; rts move.w #1,(PalCycle_Timer).w lea (CyclingPal_Lantern).l,a0 move.w (PalCycle_Frame).w,d0 addq.w #2,(PalCycle_Frame).w andi.w #6,(PalCycle_Frame).w move.w (a0,d0.w),(Normal_palette_line2+$16).w + rts ; =========================================================================== PalCycle_CNZ: subq.w #1,(PalCycle_Timer).w bpl.w CNZ_SkipToBossPalCycle move.w #7,(PalCycle_Timer).w lea (CyclingPal_CNZ1).l,a0 move.w (PalCycle_Frame).w,d0 addq.w #2,(PalCycle_Frame).w cmpi.w #6,(PalCycle_Frame).w blo.s + move.w #0,(PalCycle_Frame).w + lea (a0,d0.w),a0 lea (Normal_palette).w,a1 _move.w 0(a0),$4A(a1) move.w 6(a0),$4C(a1) move.w $C(a0),$4E(a1) move.w $12(a0),$56(a1) move.w $18(a0),$58(a1) move.w $1E(a0),$5A(a1) lea (CyclingPal_CNZ3).l,a0 lea (a0,d0.w),a0 _move.w 0(a0),$64(a1) move.w 6(a0),$66(a1) move.w $C(a0),$68(a1) lea (CyclingPal_CNZ4).l,a0 move.w (PalCycle_Frame_CNZ).w,d0 addq.w #2,(PalCycle_Frame_CNZ).w cmpi.w #$24,(PalCycle_Frame_CNZ).w blo.s + move.w #0,(PalCycle_Frame_CNZ).w + lea (Normal_palette_line4+$12).w,a1 move.w 4(a0,d0.w),(a1)+ move.w 2(a0,d0.w),(a1)+ move.w (a0,d0.w),(a1)+ CNZ_SkipToBossPalCycle: tst.b (Current_Boss_ID).w beq.w +++ ; rts subq.w #1,(PalCycle_Timer2).w bpl.w +++ ; rts move.w #3,(PalCycle_Timer2).w move.w (PalCycle_Frame2).w,d0 addq.w #2,(PalCycle_Frame2).w cmpi.w #6,(PalCycle_Frame2).w blo.s + move.w #0,(PalCycle_Frame2).w + lea (CyclingPal_CNZ1_B).l,a0 lea (a0,d0.w),a0 lea (Normal_palette).w,a1 _move.w 0(a0),$24(a1) move.w 6(a0),$26(a1) move.w $C(a0),$28(a1) lea (CyclingPal_CNZ2_B).l,a0 move.w (PalCycle_Frame3).w,d0 addq.w #2,(PalCycle_Frame3).w cmpi.w #$14,(PalCycle_Frame3).w blo.s + move.w #0,(PalCycle_Frame3).w + move.w (a0,d0.w),$3C(a1) lea (CyclingPal_CNZ3_B).l,a0 move.w (PalCycle_Frame2_CNZ).w,d0 addq.w #2,(PalCycle_Frame2_CNZ).w andi.w #$E,(PalCycle_Frame2_CNZ).w move.w (a0,d0.w),$3E(a1) + rts ; =========================================================================== PalCycle_CPZ: subq.w #1,(PalCycle_Timer).w bpl.s +++ ; rts move.w #7,(PalCycle_Timer).w lea (CyclingPal_CPZ1).l,a0 move.w (PalCycle_Frame).w,d0 addq.w #6,(PalCycle_Frame).w cmpi.w #$36,(PalCycle_Frame).w blo.s + move.w #0,(PalCycle_Frame).w + lea (Normal_palette_line4+$18).w,a1 move.l (a0,d0.w),(a1)+ move.w 4(a0,d0.w),(a1) lea (CyclingPal_CPZ2).l,a0 move.w (PalCycle_Frame2).w,d0 addq.w #2,(PalCycle_Frame2).w cmpi.w #$2A,(PalCycle_Frame2).w blo.s + move.w #0,(PalCycle_Frame2).w + move.w (a0,d0.w),(Normal_palette_line4+$1E).w lea (CyclingPal_CPZ3).l,a0 move.w (PalCycle_Frame3).w,d0 addq.w #2,(PalCycle_Frame3).w andi.w #$1E,(PalCycle_Frame3).w move.w (a0,d0.w),(Normal_palette_line3+$1E).w + rts ; =========================================================================== PalCycle_ARZ: lea (CyclingPal_EHZ_ARZ_Water).l,a0 subq.w #1,(PalCycle_Timer).w bpl.s + ; rts move.w #5,(PalCycle_Timer).w move.w (PalCycle_Frame).w,d0 addq.w #1,(PalCycle_Frame).w andi.w #3,d0 lsl.w #3,d0 lea (Normal_palette_line3+4).w,a1 move.l (a0,d0.w),(a1)+ move.l 4(a0,d0.w),(a1) + rts ; =========================================================================== PalCycle_WFZ: subq.w #1,(PalCycle_Timer).w bpl.s +++ move.w #1,(PalCycle_Timer).w lea (CyclingPal_WFZFire).l,a0 tst.b (WFZ_SCZ_Fire_Toggle).w beq.s + move.w #5,(PalCycle_Timer).w lea (CyclingPal_WFZBelt).l,a0 + move.w (PalCycle_Frame).w,d0 addq.w #8,(PalCycle_Frame).w cmpi.w #$20,(PalCycle_Frame).w blo.s + move.w #0,(PalCycle_Frame).w + lea (Normal_palette_line3+$E).w,a1 move.l (a0,d0.w),(a1)+ move.l 4(a0,d0.w),(a1) + subq.w #1,(PalCycle_Timer2).w bpl.s ++ ; subq.w move.w #3,(PalCycle_Timer2).w lea (CyclingPal_WFZ1).l,a0 move.w (PalCycle_Frame2).w,d0 addq.w #2,(PalCycle_Frame2).w cmpi.w #$44,(PalCycle_Frame2).w blo.s + ; move.w move.w #0,(PalCycle_Frame2).w + move.w (a0,d0.w),(Normal_palette_line3+$1C).w + subq.w #1,(PalCycle_Timer3).w bpl.s ++ ; rts move.w #5,(PalCycle_Timer3).w lea (CyclingPal_WFZ2).l,a0 move.w (PalCycle_Frame3).w,d0 addq.w #2,(PalCycle_Frame3).w cmpi.w #$18,(PalCycle_Frame3).w blo.s + move.w #0,(PalCycle_Frame3).w + move.w (a0,d0.w),(Normal_palette_line3+$1E).w + rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; word_1E5A: BINCLUDE "art/palettes/Title Water.bin"; S1 Title Screen Water palette (unused) ; word_1E7A: CyclingPal_EHZ_ARZ_Water: BINCLUDE "art/palettes/EHZ ARZ Water.bin"; Emerald Hill/Aquatic Ruin Rotating Water palette ; word_1E9A: CyclingPal_Lava: BINCLUDE "art/palettes/Hill Top Lava.bin"; Hill Top Lava palette ; word_1F1A: CyclingPal_WoodConveyor: BINCLUDE "art/palettes/Wood Conveyor.bin"; Wood Conveyor Belts palette ; byte_1F2A: CyclingPal_MTZ1: BINCLUDE "art/palettes/MTZ Cycle 1.bin"; Metropolis Cycle #1 palette ; word_1F36: CyclingPal_MTZ2: BINCLUDE "art/palettes/MTZ Cycle 2.bin"; Metropolis Cycle #2 palette ; word_1F42: CyclingPal_MTZ3: BINCLUDE "art/palettes/MTZ Cycle 3.bin"; Metropolis Cycle #3 palette ; word_1F56: CyclingPal_HPZWater: BINCLUDE "art/palettes/HPZ Water Cycle.bin"; Hidden Palace Water Cycle ; word_1F66: CyclingPal_HPZUnderwater: BINCLUDE "art/palettes/HPZ Underwater Cycle.bin"; Hidden Palace Underwater Cycle ; word_1F76: CyclingPal_Oil: BINCLUDE "art/palettes/OOZ Oil.bin"; Oil Ocean Oil palette ; word_1F86: CyclingPal_Lantern: BINCLUDE "art/palettes/MCZ Lantern.bin"; Mystic Cave Lanterns ; word_1F8E: CyclingPal_CNZ1: BINCLUDE "art/palettes/CNZ Cycle 1.bin"; Casino Night Cycles 1 & 2 ; word_1FB2: CyclingPal_CNZ3: BINCLUDE "art/palettes/CNZ Cycle 3.bin"; Casino Night Cycle 3 ; word_1FC4: CyclingPal_CNZ4: BINCLUDE "art/palettes/CNZ Cycle 4.bin"; Casino Night Cycle 4 ; word_1FEC: CyclingPal_CNZ1_B: BINCLUDE "art/palettes/CNZ Boss Cycle 1.bin"; Casino Night Boss Cycle 1 ; word_1FFE: CyclingPal_CNZ2_B: BINCLUDE "art/palettes/CNZ Boss Cycle 2.bin"; Casino Night Boss Cycle 2 ; word_2012: CyclingPal_CNZ3_B: BINCLUDE "art/palettes/CNZ Boss Cycle 3.bin"; Casino Night Boss Cycle 3 ; word_2022: CyclingPal_CPZ1: BINCLUDE "art/palettes/CPZ Cycle 1.bin"; Chemical Plant Cycle 1 ; word_2058: CyclingPal_CPZ2: BINCLUDE "art/palettes/CPZ Cycle 2.bin"; Chemical Plant Cycle 2 ; word_2082: CyclingPal_CPZ3: BINCLUDE "art/palettes/CPZ Cycle 3.bin"; Chemical Plant Cycle 3 ; word_20A2: CyclingPal_WFZFire: BINCLUDE "art/palettes/WFZ Fire Cycle.bin"; Wing Fortress Fire Cycle palette ; word_20C2: CyclingPal_WFZBelt: BINCLUDE "art/palettes/WFZ Conveyor Cycle.bin"; Wing Fortress Conveyor Belt Cycle palette ; word_20E2: CyclingPal_CPZ4: CyclingPal_WFZ1: BINCLUDE "art/palettes/WFZ Cycle 1.bin"; Wing Fortress Flashing Light Cycle 1 ; word_2126: CyclingPal_WFZ2: BINCLUDE "art/palettes/WFZ Cycle 2.bin"; Wing Fortress Flashing Light Cycle 2 ; ---------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_213E: PalCycle_SuperSonic: move.b (Super_Sonic_palette).w,d0 beq.s ++ ; rts ; return, if Sonic isn't super bmi.w PalCycle_SuperSonic_normal ; branch, if fade-in is done subq.b #1,d0 bne.s PalCycle_SuperSonic_revert ; branch for values greater than 1 ; fade from Sonic's to Super Sonic's palette ; run frame timer subq.b #1,(Palette_timer).w bpl.s ++ ; rts move.b #3,(Palette_timer).w ; increment palette frame and update Sonic's palette lea (CyclingPal_SSTransformation).l,a0 move.w (Palette_frame).w,d0 addq.w #8,(Palette_frame).w ; 1 palette entry = 1 word, Sonic uses 4 shades of blue cmpi.w #$30,(Palette_frame).w ; has palette cycle reached the 6th frame? blo.s + ; if not, branch move.b #-1,(Super_Sonic_palette).w ; mark fade-in as done move.b #0,(MainCharacter+obj_control).w ; restore Sonic's movement + lea (Normal_palette+4).w,a1 move.l (a0,d0.w),(a1)+ move.l 4(a0,d0.w),(a1) ; note: the fade in for Sonic's underwater palette is missing. ; branch to the code below (*) to fix this / rts ; =========================================================================== ; loc_2188: PalCycle_SuperSonic_revert: ; runs the fade in transition backwards ; run frame timer subq.b #1,(Palette_timer).w bpl.s - ; rts move.b #3,(Palette_timer).w ; decrement palette frame and update Sonic's palette lea (CyclingPal_SSTransformation).l,a0 move.w (Palette_frame).w,d0 subq.w #8,(Palette_frame).w ; previous frame bcc.s + ; branch, if it isn't the first frame move.b #0,(Palette_frame).w move.b #0,(Super_Sonic_palette).w ; stop palette cycle + lea (Normal_palette+4).w,a1 move.l (a0,d0.w),(a1)+ move.l 4(a0,d0.w),(a1) ; underwater palettes (*) lea (CyclingPal_CPZUWTransformation).l,a0 cmpi.b #chemical_plant_zone,(Current_Zone).w beq.s + cmpi.b #aquatic_ruin_zone,(Current_Zone).w bne.s - ; rts lea (CyclingPal_ARZUWTransformation).l,a0 + lea (Underwater_palette+4).w,a1 move.l (a0,d0.w),(a1)+ move.l 4(a0,d0.w),(a1) rts ; =========================================================================== ; loc_21E6: PalCycle_SuperSonic_normal: ; run frame timer subq.b #1,(Palette_timer).w bpl.s - ; rts move.b #7,(Palette_timer).w ; increment palette frame and update Sonic's palette lea (CyclingPal_SSTransformation).l,a0 move.w (Palette_frame).w,d0 addq.w #8,(Palette_frame).w ; next frame cmpi.w #$78,(Palette_frame).w ; is it the last frame? blo.s + ; if not, branch move.w #$30,(Palette_frame).w ; reset frame counter (Super Sonic's normal palette cycle starts at $30. Everything before that is for the palette fade) + lea (Normal_palette+4).w,a1 move.l (a0,d0.w),(a1)+ move.l 4(a0,d0.w),(a1) ; underwater palettes lea (CyclingPal_CPZUWTransformation).l,a0 cmpi.b #chemical_plant_zone,(Current_Zone).w beq.s + cmpi.b #aquatic_ruin_zone,(Current_Zone).w bne.w - ; rts lea (CyclingPal_ARZUWTransformation).l,a0 + lea (Underwater_palette+4).w,a1 move.l (a0,d0.w),(a1)+ move.l 4(a0,d0.w),(a1) rts ; End of function PalCycle_SuperSonic ; =========================================================================== ;---------------------------------------------------------------------------- ;Palette for transformation to Super Sonic ;---------------------------------------------------------------------------- ; Pal_2246: CyclingPal_SSTransformation: BINCLUDE "art/palettes/Super Sonic transformation.bin" ;---------------------------------------------------------------------------- ;Palette for transformation to Super Sonic while underwater in CPZ ;---------------------------------------------------------------------------- ; Pal_22C6: CyclingPal_CPZUWTransformation: BINCLUDE "art/palettes/CPZWater SS transformation.bin" ;---------------------------------------------------------------------------- ;Palette for transformation to Super Sonic while underwater in ARZ ;---------------------------------------------------------------------------- ; Pal_2346: CyclingPal_ARZUWTransformation: BINCLUDE "art/palettes/ARZWater SS transformation.bin" ; --------------------------------------------------------------------------- ; Subroutine to fade in from black ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_23C6: Pal_FadeTo: Pal_FadeFromBlack: move.w #$3F,(Palette_fade_range).w moveq #0,d0 lea (Normal_palette).w,a0 move.b (Palette_fade_start).w,d0 adda.w d0,a0 moveq #0,d1 move.b (Palette_fade_length).w,d0 ; loc_23DE: Pal_ToBlack: .palettewrite: move.w d1,(a0)+ dbf d0,.palettewrite ; fill palette with $000 (black) move.w #$15,d4 .nextframe: move.b #VintID_Fade,(Vint_routine).w bsr.w WaitForVint bsr.s .UpdateAllColours bsr.w RunPLC_RAM dbf d4,.nextframe rts ; End of function Pal_FadeFromBlack ; --------------------------------------------------------------------------- ; Subroutine to update all colours once ; --------------------------------------------------------------------------- ; sub_23FE: Pal_FadeIn: .UpdateAllColours: ; Update above-water palette moveq #0,d0 lea (Normal_palette).w,a0 lea (Target_palette).w,a1 move.b (Palette_fade_start).w,d0 adda.w d0,a0 adda.w d0,a1 move.b (Palette_fade_length).w,d0 .nextcolour: bsr.s .UpdateColour dbf d0,.nextcolour tst.b (Water_flag).w beq.s .skipunderwater ; Update underwater palette moveq #0,d0 lea (Underwater_palette).w,a0 lea (Underwater_target_palette).w,a1 move.b (Palette_fade_start).w,d0 adda.w d0,a0 adda.w d0,a1 move.b (Palette_fade_length).w,d0 .nextcolour2: bsr.s .UpdateColour dbf d0,.nextcolour2 .skipunderwater: rts ; --------------------------------------------------------------------------- ; Subroutine to update a single colour once ; --------------------------------------------------------------------------- ; sub_243E: Pal_AddColor: .UpdateColour: move.w (a1)+,d2 move.w (a0),d3 cmp.w d2,d3 beq.s .updatenone ;.updateblue: move.w d3,d1 addi.w #$200,d1 ; increase blue value cmp.w d2,d1 ; has blue reached threshold level? bhi.s .updategreen ; if yes, branch move.w d1,(a0)+ ; update palette rts ; loc_2454: Pal_AddGreen: .updategreen: move.w d3,d1 addi.w #$20,d1 ; increase green value cmp.w d2,d1 bhi.s .updatered move.w d1,(a0)+ ; update palette rts ; loc_2462: Pal_AddRed: .updatered: addq.w #2,(a0)+ ; increase red value rts ; loc_2466: Pal_AddNone: .updatenone: addq.w #2,a0 rts ; --------------------------------------------------------------------------- ; Subroutine to fade out to black ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_246A: Pal_FadeFrom: Pal_FadeToBlack: move.w #$3F,(Palette_fade_range).w move.w #$15,d4 .nextframe: move.b #VintID_Fade,(Vint_routine).w bsr.w WaitForVint bsr.s .UpdateAllColours bsr.w RunPLC_RAM dbf d4,.nextframe rts ; End of function Pal_FadeToBlack ; --------------------------------------------------------------------------- ; Subroutine to update all colours once ; --------------------------------------------------------------------------- ; sub_248A: Pal_FadeOut: .UpdateAllColours: ; Update above-water palette moveq #0,d0 lea (Normal_palette).w,a0 move.b (Palette_fade_start).w,d0 adda.w d0,a0 move.b (Palette_fade_length).w,d0 .nextcolour: bsr.s .UpdateColour dbf d0,.nextcolour ; Notice how this one lacks a check for ; if Water_flag is set, unlike Pal_FadeFromBlack? ; Update underwater palette moveq #0,d0 lea (Underwater_palette).w,a0 move.b (Palette_fade_start).w,d0 adda.w d0,a0 move.b (Palette_fade_length).w,d0 .nextcolour2: bsr.s .UpdateColour dbf d0,.nextcolour2 rts ; --------------------------------------------------------------------------- ; Subroutine to update a single colour once ; --------------------------------------------------------------------------- ; sub_24B8: Pal_DecColor: .UpdateColour: move.w (a0),d2 beq.s .updatenone ;.updatered: move.w d2,d1 andi.w #$E,d1 beq.s .updategreen subq.w #2,(a0)+ ; decrease red value rts ; loc_24C8: Pal_DecGreen: .updategreen: move.w d2,d1 andi.w #$E0,d1 beq.s .updateblue subi.w #$20,(a0)+ ; decrease green value rts ; loc_24D6: Pal_DecBlue: .updateblue: move.w d2,d1 andi.w #$E00,d1 beq.s .updatenone subi.w #$200,(a0)+ ; decrease blue value rts ; loc_24E4: Pal_DecNone: .updatenone: addq.w #2,a0 rts ; --------------------------------------------------------------------------- ; Subroutine to fade in from white ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_24E8: Pal_MakeWhite: Pal_FadeFromWhite: move.w #$3F,(Palette_fade_range).w moveq #0,d0 lea (Normal_palette).w,a0 move.b (Palette_fade_start).w,d0 adda.w d0,a0 move.w #$EEE,d1 move.b (Palette_fade_length).w,d0 .palettewrite: move.w d1,(a0)+ dbf d0,.palettewrite move.w #$15,d4 .nextframe: move.b #VintID_Fade,(Vint_routine).w bsr.w WaitForVint bsr.s .UpdateAllColours bsr.w RunPLC_RAM dbf d4,.nextframe rts ; End of function Pal_FadeFromWhite ; --------------------------------------------------------------------------- ; Subroutine to update all colours once ; --------------------------------------------------------------------------- ; sub_2522: Pal_WhiteToBlack: .UpdateAllColours: ; Update above-water palette moveq #0,d0 lea (Normal_palette).w,a0 lea (Target_palette).w,a1 move.b (Palette_fade_start).w,d0 adda.w d0,a0 adda.w d0,a1 move.b (Palette_fade_length).w,d0 .nextcolour: bsr.s .UpdateColour dbf d0,.nextcolour tst.b (Water_flag).w beq.s .skipunderwater ; Update underwater palette moveq #0,d0 lea (Underwater_palette).w,a0 lea (Underwater_target_palette).w,a1 move.b (Palette_fade_start).w,d0 adda.w d0,a0 adda.w d0,a1 move.b (Palette_fade_length).w,d0 .nextcolour2: bsr.s .UpdateColour dbf d0,.nextcolour2 .skipunderwater: rts ; --------------------------------------------------------------------------- ; Subroutine to update a single colour once ; --------------------------------------------------------------------------- ; sub_2562: Pal_DecColor2: .UpdateColour: move.w (a1)+,d2 move.w (a0),d3 cmp.w d2,d3 beq.s .updatenone ;.updateblue: move.w d3,d1 subi.w #$200,d1 ; decrease blue value bcs.s .updategreen cmp.w d2,d1 blo.s .updategreen move.w d1,(a0)+ rts ; loc_257A: Pal_DecGreen2: .updategreen: move.w d3,d1 subi.w #$20,d1 ; decrease green value bcs.s .updatered cmp.w d2,d1 blo.s .updatered move.w d1,(a0)+ rts ; loc_258A: Pal_DecRed2: .updatered: subq.w #2,(a0)+ ; decrease red value rts ; loc_258E: Pal_DecNone2: .updatenone: addq.w #2,a0 rts ; --------------------------------------------------------------------------- ; Subroutine to fade out to white (used when you enter a special stage) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_2592: Pal_MakeFlash: Pal_FadeToWhite: move.w #$3F,(Palette_fade_range).w move.w #$15,d4 .nextframe: move.b #VintID_Fade,(Vint_routine).w bsr.w WaitForVint bsr.s .UpdateAllColours bsr.w RunPLC_RAM dbf d4,.nextframe rts ; End of function Pal_FadeToWhite ; --------------------------------------------------------------------------- ; Subroutine to update all colours once ; --------------------------------------------------------------------------- ; sub_25B2: Pal_ToWhite: .UpdateAllColours: ; Update above-water palette moveq #0,d0 lea (Normal_palette).w,a0 move.b (Palette_fade_start).w,d0 adda.w d0,a0 move.b (Palette_fade_length).w,d0 .nextcolour: bsr.s .UpdateColour dbf d0,.nextcolour ; Notice how this one lacks a check for ; if Water_flag is set, unlike Pal_FadeFromWhite? ; Update underwater palette moveq #0,d0 lea (Underwater_palette).w,a0 move.b (Palette_fade_start).w,d0 adda.w d0,a0 move.b (Palette_fade_length).w,d0 .nextcolour2: bsr.s .UpdateColour dbf d0,.nextcolour2 rts ; --------------------------------------------------------------------------- ; Subroutine to update a single colour once ; --------------------------------------------------------------------------- ; sub_25E0: Pal_AddColor2: .UpdateColour: move.w (a0),d2 cmpi.w #$EEE,d2 beq.s .updatenone ;.updatered: move.w d2,d1 andi.w #$E,d1 cmpi.w #$E,d1 beq.s .updategreen addq.w #2,(a0)+ ; increase red value rts ; loc_25F8: Pal_AddGreen2: .updategreen: move.w d2,d1 andi.w #$E0,d1 cmpi.w #$E0,d1 beq.s .updateblue addi.w #$20,(a0)+ ; increase green value rts ; loc_260A: Pal_AddBlue2: .updateblue: move.w d2,d1 andi.w #$E00,d1 cmpi.w #$E00,d1 beq.s .updatenone addi.w #$200,(a0)+ ; increase blue value rts ; loc_261C: Pal_AddNone2: .updatenone: addq.w #2,a0 rts ; End of function Pal_AddColor2 ; Unused - dead code/data for old SEGA screen: ; =========================================================================== ; PalCycle_Sega: tst.b (PalCycle_Timer+1).w bne.s loc_2680 lea (Normal_palette_line2).w,a1 lea (Pal_Sega1).l,a0 moveq #5,d1 move.w (PalCycle_Frame).w,d0 loc_2636: bpl.s loc_2640 addq.w #2,a0 subq.w #1,d1 addq.w #2,d0 bra.s loc_2636 ; =========================================================================== loc_2640: move.w d0,d2 andi.w #$1E,d2 bne.s loc_264A addq.w #2,d0 loc_264A: cmpi.w #$60,d0 bhs.s loc_2654 move.w (a0)+,(a1,d0.w) loc_2654: addq.w #2,d0 dbf d1,loc_2640 move.w (PalCycle_Frame).w,d0 addq.w #2,d0 move.w d0,d2 andi.w #$1E,d2 bne.s loc_266A addq.w #2,d0 loc_266A: cmpi.w #$64,d0 blt.s loc_2678 move.w #$401,(PalCycle_Timer).w moveq #-$C,d0 loc_2678: move.w d0,(PalCycle_Frame).w moveq #1,d0 rts ; =========================================================================== loc_2680: subq.b #1,(PalCycle_Timer).w bpl.s loc_26D2 move.b #4,(PalCycle_Timer).w move.w (PalCycle_Frame).w,d0 addi.w #$C,d0 cmpi.w #$30,d0 blo.s loc_269E moveq #0,d0 rts ; =========================================================================== loc_269E: move.w d0,(PalCycle_Frame).w lea (Pal_Sega2).l,a0 lea (a0,d0.w),a0 lea (Normal_palette+4).w,a1 move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.w (a0)+,(a1) lea (Normal_palette_line2).w,a1 moveq #0,d0 moveq #$2C,d1 loc_26BE: move.w d0,d2 andi.w #$1E,d2 bne.s loc_26C8 addq.w #2,d0 loc_26C8: move.w (a0),(a1,d0.w) addq.w #2,d0 dbf d1,loc_26BE loc_26D2: moveq #1,d0 rts ; =========================================================================== ;---------------------------------------------------------------------------- ; Unused palette for the Sega logo ;---------------------------------------------------------------------------- ; Pal_26D6: Pal_Sega1: BINCLUDE "art/palettes/Unused Sega logo.bin" ;---------------------------------------------------------------------------- ; Unused palette for the Sega logo (fading?) ;---------------------------------------------------------------------------- ; Pal_26E2: Pal_Sega2: BINCLUDE "art/palettes/Unused Sega logo 2.bin" ; end of dead code/data ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_2712: PalLoad1: PalLoad_ForFade: lea (PalPointers).l,a1 lsl.w #3,d0 adda.w d0,a1 movea.l (a1)+,a2 movea.w (a1)+,a3 adda.w #Target_palette-Normal_palette,a3 move.w (a1)+,d7 - move.l (a2)+,(a3)+ dbf d7,- rts ; End of function PalLoad_ForFade ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_272E: PalLoad2: PalLoad_Now: lea (PalPointers).l,a1 lsl.w #3,d0 adda.w d0,a1 movea.l (a1)+,a2 movea.w (a1)+,a3 move.w (a1)+,d7 - move.l (a2)+,(a3)+ dbf d7,- rts ; End of function PalLoad_Now ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_2746: PalLoad3_Water: PalLoad_Water_Now: lea (PalPointers).l,a1 lsl.w #3,d0 adda.w d0,a1 movea.l (a1)+,a2 movea.w (a1)+,a3 suba.l #Normal_palette-Underwater_palette,a3 move.w (a1)+,d7 - move.l (a2)+,(a3)+ dbf d7,- rts ; End of function PalLoad_Water_Now ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_2764: PalLoad4_Water: PalLoad_Water_ForFade: lea (PalPointers).l,a1 lsl.w #3,d0 adda.w d0,a1 movea.l (a1)+,a2 movea.w (a1)+,a3 suba.l #Normal_palette-Underwater_target_palette,a3 move.w (a1)+,d7 - move.l (a2)+,(a3)+ dbf d7,- rts ; End of function PalLoad_Water_ForFade ; =========================================================================== ;---------------------------------------------------------------------------- ; Palette pointers ; (PALETTE DESCRIPTOR ARRAY) ; This struct array defines the palette to use for each level. ;---------------------------------------------------------------------------- palptr macro ptr,lineno dc.l ptr ; Pointer to palette dc.w (Normal_palette+lineno*palette_line_size)&$FFFF ; Location in ram to load palette into dc.w bytesToLcnt(ptr_End-ptr) ; Size of palette in (bytes / 4) endm PalPointers: PalPtr_SEGA: palptr Pal_SEGA, 0 PalPtr_Title: palptr Pal_Title, 1 PalPtr_MenuB: palptr Pal_MenuB, 0 PalPtr_BGND: palptr Pal_BGND, 0 PalPtr_EHZ: palptr Pal_EHZ, 1 PalPtr_EHZ2: palptr Pal_EHZ, 1 PalPtr_WZ: palptr Pal_WZ, 1 PalPtr_EHZ3: palptr Pal_EHZ, 1 PalPtr_MTZ: palptr Pal_MTZ, 1 PalPtr_MTZ2: palptr Pal_MTZ, 1 PalPtr_WFZ: palptr Pal_WFZ, 1 PalPtr_HTZ: palptr Pal_HTZ, 1 PalPtr_HPZ: palptr Pal_HPZ, 1 PalPtr_EHZ4: palptr Pal_EHZ, 1 PalPtr_OOZ: palptr Pal_OOZ, 1 PalPtr_MCZ: palptr Pal_MCZ, 1 PalPtr_CNZ: palptr Pal_CNZ, 1 PalPtr_CPZ: palptr Pal_CPZ, 1 PalPtr_DEZ: palptr Pal_DEZ, 1 PalPtr_ARZ: palptr Pal_ARZ, 1 PalPtr_SCZ: palptr Pal_SCZ, 1 PalPtr_HPZ_U: palptr Pal_HPZ_U, 0 PalPtr_CPZ_U: palptr Pal_CPZ_U, 0 PalPtr_ARZ_U: palptr Pal_ARZ_U, 0 PalPtr_SS: palptr Pal_SS, 0 PalPtr_MCZ_B: palptr Pal_MCZ_B, 1 PalPtr_CNZ_B: palptr Pal_CNZ_B, 1 PalPtr_SS1: palptr Pal_SS1, 3 PalPtr_SS2: palptr Pal_SS2, 3 PalPtr_SS3: palptr Pal_SS3, 3 PalPtr_SS4: palptr Pal_SS4, 3 PalPtr_SS5: palptr Pal_SS5, 3 PalPtr_SS6: palptr Pal_SS6, 3 PalPtr_SS7: palptr Pal_SS7, 3 PalPtr_SS1_2p: palptr Pal_SS1_2p,3 PalPtr_SS2_2p: palptr Pal_SS2_2p,3 PalPtr_SS3_2p: palptr Pal_SS3_2p,3 PalPtr_OOZ_B: palptr Pal_OOZ_B, 1 PalPtr_Menu: palptr Pal_Menu, 0 PalPtr_Result: palptr Pal_Result,0 ; ---------------------------------------------------------------------------- ; This macro defines Pal_ABC and Pal_ABC_End, so palptr can compute the size of ; the palette automatically ; path2 is used for the Sonic and Tails palette, which has 2 palette lines palette macro {INTLABEL},path,path2 __LABEL__ label * BINCLUDE "art/palettes/path" if "path2"<>"" BINCLUDE "art/palettes/path2" endif __LABEL___End label * endm Pal_SEGA: palette Sega screen.bin ; SEGA screen palette (Sonic and initial background) Pal_Title: palette Title screen.bin ; Title screen Palette Pal_MenuB: palette S2B Level Select.bin ; Leftover S2B level select palette Pal_BGND: palette SonicAndTails.bin,SonicAndTails2.bin ; "Sonic and Miles" background palette (also usually the primary palette line) Pal_EHZ: palette EHZ.bin ; Emerald Hill Zone palette Pal_WZ: palette Wood Zone.bin ; Wood Zone palette Pal_MTZ: palette MTZ.bin ; Metropolis Zone palette Pal_WFZ: palette WFZ.bin ; Wing Fortress Zone palette Pal_HTZ: palette HTZ.bin ; Hill Top Zone palette Pal_HPZ: palette HPZ.bin ; Hidden Palace Zone palette Pal_HPZ_U: palette HPZ underwater.bin ; Hidden Palace Zone underwater palette Pal_OOZ: palette OOZ.bin ; Oil Ocean Zone palette Pal_MCZ: palette MCZ.bin ; Mystic Cave Zone palette Pal_CNZ: palette CNZ.bin ; Casino Night Zone palette Pal_CPZ: palette CPZ.bin ; Chemical Plant Zone palette Pal_CPZ_U: palette CPZ underwater.bin ; Chemical Plant Zone underwater palette Pal_DEZ: palette DEZ.bin ; Death Egg Zone palette Pal_ARZ: palette ARZ.bin ; Aquatic Ruin Zone palette Pal_ARZ_U: palette ARZ underwater.bin ; Aquatic Ruin Zone underwater palette Pal_SCZ: palette SCZ.bin ; Sky Chase Zone palette Pal_MCZ_B: palette MCZ Boss.bin ; Mystic Cave Zone boss palette Pal_CNZ_B: palette CNZ Boss.bin ; Casino Night Zone boss palette Pal_OOZ_B: palette OOZ Boss.bin ; Oil Ocean Zone boss palette Pal_Menu: palette Menu.bin ; Menu palette Pal_SS: palette Special Stage Main.bin ; Special Stage palette Pal_SS1: palette Special Stage 1.bin ; Special Stage 1 palette Pal_SS2: palette Special Stage 2.bin ; Special Stage 2 palette Pal_SS3: palette Special Stage 3.bin ; Special Stage 3 palette Pal_SS4: palette Special Stage 4.bin ; Special Stage 4 palette Pal_SS5: palette Special Stage 5.bin ; Special Stage 5 palette Pal_SS6: palette Special Stage 6.bin ; Special Stage 6 palette Pal_SS7: palette Special Stage 7.bin ; Special Stage 7 palette Pal_SS1_2p:palette Special Stage 1 2p.bin ; Special Stage 1 2p palette Pal_SS2_2p:palette Special Stage 2 2p.bin ; Special Stage 2 2p palette Pal_SS3_2p:palette Special Stage 3 2p.bin ; Special Stage 3 2p palette Pal_Result:palette Special Stage Results Screen.bin ; Special Stage Results Screen palette ; =========================================================================== if gameRevision<2 nop endif ; --------------------------------------------------------------------------- ; Subroutine to perform vertical synchronization ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_3384: DelayProgram: WaitForVint: move #$2300,sr - tst.b (Vint_routine).w bne.s - rts ; End of function WaitForVint ; --------------------------------------------------------------------------- ; Subroutine to generate a pseudo-random number in d0 ; d0 = (RNG & $FFFF0000) | ((RNG*41 & $FFFF) + ((RNG*41 & $FFFF0000) >> 16)) ; RNG = ((RNG*41 + ((RNG*41 & $FFFF) << 16)) & $FFFF0000) | (RNG*41 & $FFFF) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_3390: RandomNumber: move.l (RNG_seed).w,d1 bne.s + move.l #$2A6D365A,d1 ; if the RNG is 0, reset it to this crazy number ; set the high word of d0 to be the high word of the RNG ; and multiply the RNG by 41 + move.l d1,d0 asl.l #2,d1 add.l d0,d1 asl.l #3,d1 add.l d0,d1 ; add the low word of the RNG to the high word of the RNG ; and set the low word of d0 to be the result move.w d1,d0 swap d1 add.w d1,d0 move.w d0,d1 swap d1 move.l d1,(RNG_seed).w rts ; End of function RandomNumber ; --------------------------------------------------------------------------- ; Subroutine to calculate sine and cosine of an angle ; d0 = input byte = angle (360 degrees == 256) ; d0 = output word = 255 * sine(angle) ; d1 = output word = 255 * cosine(angle) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_33B6: CalcSine: andi.w #$FF,d0 add.w d0,d0 addi.w #$80,d0 move.w Sine_Data(pc,d0.w),d1 ; cos subi.w #$80,d0 move.w Sine_Data(pc,d0.w),d0 ; sin rts ; End of function CalcSine ; =========================================================================== ; word_33CE: Sine_Data: BINCLUDE "misc/sinewave.bin" ; --------------------------------------------------------------------------- ; Subroutine to calculate arctangent of y/x ; d1 = input x ; d2 = input y ; d0 = output angle (360 degrees == 256) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_364E: CalcAngle: movem.l d3-d4,-(sp) moveq #0,d3 moveq #0,d4 move.w d1,d3 move.w d2,d4 or.w d3,d4 beq.s CalcAngle_Zero ; special case return if x and y are both 0 move.w d2,d4 absw.w d3 ; calculate absolute value of x absw.w d4 ; calculate absolute value of y cmp.w d3,d4 bhs.w + lsl.l #8,d4 divu.w d3,d4 moveq #0,d0 move.b Angle_Data(pc,d4.w),d0 bra.s ++ + lsl.l #8,d3 divu.w d4,d3 moveq #$40,d0 sub.b Angle_Data(pc,d3.w),d0 + tst.w d1 bpl.w + neg.w d0 addi.w #$80,d0 + tst.w d2 bpl.w + neg.w d0 addi.w #$100,d0 + movem.l (sp)+,d3-d4 rts ; =========================================================================== ; loc_36AA: CalcAngle_Zero: move.w #$40,d0 movem.l (sp)+,d3-d4 rts ; End of function CalcAngle ; =========================================================================== ; byte_36B4: Angle_Data: BINCLUDE "misc/angles.bin" ; =========================================================================== if gameRevision<2 nop endif ; loc_37B8: SegaScreen: move.b #MusID_Stop,d0 bsr.w PlayMusic ; stop music bsr.w ClearPLC bsr.w Pal_FadeToBlack clearRAM Misc_Variables,Misc_Variables_End clearRAM SegaScr_Object_RAM,SegaScr_Object_RAM_End ; fill object RAM with 0 lea (VDP_control_port).l,a6 move.w #$8004,(a6) ; H-INT disabled move.w #$8200|(VRAM_SegaScr_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000 move.w #$8400|(VRAM_SegaScr_Plane_B_Name_Table/$2000),(a6) ; PNT B base: $A000 move.w #$8700,(a6) ; Background palette/color: 0/0 move.w #$8B03,(a6) ; EXT-INT disabled, V scroll by screen, H scroll by line move.w #$8C81,(a6) ; H res 40 cells, no interlace, S/H disabled move.w #$9003,(a6) ; Scroll table size: 128x32 ($2000 bytes) clr.b (Water_fullscreen_flag).w clr.w (Two_player_mode).w move #$2700,sr move.w (VDP_Reg1_val).w,d0 andi.b #$BF,d0 move.w d0,(VDP_control_port).l bsr.w ClearScreen dmaFillVRAM 0,VRAM_SegaScr_Plane_A_Name_Table,VRAM_SegaScr_Plane_Table_Size ; clear Plane A pattern name table move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Sega_Logo),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_SEGA).l,a0 bsr.w NemDec move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Trails),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_IntroTrails).l,a0 bsr.w NemDec move.l #vdpComm(tiles_to_bytes(ArtTile_ArtUnc_Giant_Sonic),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_SilverSonic).l,a0 ; ?? seems unused here bsr.w NemDec lea (Chunk_Table).l,a1 lea (MapEng_SEGA).l,a0 move.w #make_art_tile(ArtTile_VRAM_Start,0,0),d0 bsr.w EniDec lea (Chunk_Table).l,a1 move.l #vdpComm(VRAM_SegaScr_Plane_B_Name_Table,VRAM,WRITE),d0 moveq #$27,d1 ; 40 cells wide moveq #$1B,d2 ; 28 cells tall bsr.w PlaneMapToVRAM_H80_Sega tst.b (Graphics_Flags).w ; are we on a Japanese Mega Drive? bmi.s SegaScreen_Contin ; if not, branch ; load an extra sprite to hide the TM (trademark) symbol on the SEGA screen lea (SegaHideTM).w,a1 move.b #ObjID_SegaHideTM,id(a1) ; load objB1 at $FFFFB080 move.b #$4E,subtype(a1) ; <== ObjB1_SubObjData ; loc_38CE: SegaScreen_Contin: moveq #PalID_SEGA,d0 bsr.w PalLoad_Now move.w #-$A,(PalCycle_Frame).w move.w #0,(PalCycle_Timer).w move.w #0,(SegaScr_VInt_Subrout).w move.w #0,(SegaScr_PalDone_Flag).w lea (SegaScreenObject).w,a1 move.b #ObjID_SonicOnSegaScr,id(a1) ; load objB0 (sega screen?) at $FFFFB040 move.b #$4C,subtype(a1) ; <== ObjB0_SubObjData move.w #4*60,(Demo_Time_left).w ; 4 seconds move.w (VDP_Reg1_val).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l ; loc_390E: Sega_WaitPalette: move.b #VintID_SEGA,(Vint_routine).w bsr.w WaitForVint jsrto (RunObjects).l, JmpTo_RunObjects jsr (BuildSprites).l tst.b (SegaScr_PalDone_Flag).w beq.s Sega_WaitPalette move.b #SndID_SegaSound,d0 bsr.w PlaySound ; play "SEGA" sound move.b #VintID_SEGA,(Vint_routine).w bsr.w WaitForVint move.w #3*60,(Demo_Time_left).w ; 3 seconds ; loc_3940: Sega_WaitEnd: move.b #VintID_PCM,(Vint_routine).w bsr.w WaitForVint tst.w (Demo_Time_left).w beq.s Sega_GotoTitle move.b (Ctrl_1_Press).w,d0 ; is Start button pressed? or.b (Ctrl_2_Press).w,d0 ; (either player) andi.b #button_start_mask,d0 beq.s Sega_WaitEnd ; if not, branch ; loc_395E: Sega_GotoTitle: clr.w (SegaScr_PalDone_Flag).w clr.w (SegaScr_VInt_Subrout).w move.b #GameModeID_TitleScreen,(Game_Mode).w ; => TitleScreen rts ; --------------------------------------------------------------------------- ; Subroutine that does the exact same thing as PlaneMapToVRAM_H80_SpecialStage ; (this one is used at the Sega screen) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_396E: ShowVDPGraphics3: PlaneMapToVRAM3: PlaneMapToVRAM_H80_Sega: lea (VDP_data_port).l,a6 move.l #vdpCommDelta(planeLocH80(0,1)),d4 ; $1000000 - move.l d0,VDP_control_port-VDP_data_port(a6) move.w d1,d3 - move.w (a1)+,(a6) dbf d3,- add.l d4,d0 dbf d2,-- rts ; End of function PlaneMapToVRAM_H80_Sega ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos ; sub_3990: JmpTo_RunObjects jmp (RunObjects).l align 4 endif ; =========================================================================== ; loc_3998: TitleScreen: move.b #MusID_Stop,d0 bsr.w PlayMusic bsr.w ClearPLC bsr.w Pal_FadeToBlack move #$2700,sr lea (VDP_control_port).l,a6 move.w #$8004,(a6) ; H-INT disabled move.w #$8200|(VRAM_TtlScr_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000 move.w #$8400|(VRAM_TtlScr_Plane_B_Name_Table/$2000),(a6) ; PNT B base: $E000 move.w #$9001,(a6) ; Scroll table size: 64x32 move.w #$9200,(a6) ; Disable window move.w #$8B03,(a6) ; EXT-INT disabled, V scroll by screen, H scroll by line move.w #$8720,(a6) ; Background palette/color: 2/0 clr.b (Water_fullscreen_flag).w move.w #$8C81,(a6) ; H res 40 cells, no interlace, S/H disabled bsr.w ClearScreen clearRAM Sprite_Table_Input,Sprite_Table_Input_End ; fill $AC00-$AFFF with $0 clearRAM TtlScr_Object_RAM,TtlScr_Object_RAM_End ; fill object RAM ($B000-$D5FF) with $0 clearRAM Misc_Variables,Misc_Variables_End ; clear CPU player RAM and following variables clearRAM Camera_RAM,Camera_RAM_End ; clear camera RAM and following variables move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_CreditText),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_CreditText).l,a0 bsr.w NemDec lea (off_B2B0).l,a1 jsr (loc_B272).l clearRAM Target_palette,Target_palette_End ; fill palette with 0 (black) moveq #PalID_BGND,d0 bsr.w PalLoad_ForFade bsr.w Pal_FadeFromBlack move #$2700,sr move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Title),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_Title).l,a0 bsr.w NemDec move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_TitleSprites),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_TitleSprites).l,a0 bsr.w NemDec move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_MenuJunk),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_MenuJunk).l,a0 bsr.w NemDec move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Player1VS2),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_Player1VS2).l,a0 bsr.w NemDec move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_FontStuff_TtlScr),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_FontStuff).l,a0 bsr.w NemDec move.b #0,(Last_star_pole_hit).w move.b #0,(Last_star_pole_hit_2P).w move.w #0,(Debug_placement_mode).w move.w #0,(Demo_mode_flag).w move.w #0,(unk_FFDA).w move.w #0,(PalCycle_Timer).w move.w #0,(Two_player_mode).w move.b #0,(Level_started_flag).w bsr.w Pal_FadeToBlack move #$2700,sr lea (Chunk_Table).l,a1 lea (MapEng_TitleScreen).l,a0 move.w #make_art_tile(ArtTile_ArtNem_Title,2,0),d0 bsr.w EniDec lea (Chunk_Table).l,a1 move.l #vdpComm(VRAM_TtlScr_Plane_B_Name_Table,VRAM,WRITE),d0 moveq #$27,d1 moveq #$1B,d2 jsrto (PlaneMapToVRAM_H40).l, PlaneMapToVRAM_H40 lea (Chunk_Table).l,a1 lea (MapEng_TitleBack).l,a0 move.w #make_art_tile(ArtTile_ArtNem_Title,2,0),d0 bsr.w EniDec lea (Chunk_Table).l,a1 move.l #vdpComm(VRAM_TtlScr_Plane_B_Name_Table + planeLocH40($28,0),VRAM,WRITE),d0 moveq #$17,d1 moveq #$1B,d2 jsrto (PlaneMapToVRAM_H40).l, PlaneMapToVRAM_H40 lea (Chunk_Table).l,a1 lea (MapEng_TitleLogo).l,a0 move.w #make_art_tile(ArtTile_ArtNem_Title,3,1),d0 bsr.w EniDec lea (Chunk_Table+$858).l,a1 lea (CopyrightText).l,a2 moveq #bytesToWcnt(CopyrightText_End-CopyrightText),d6 - move.w (a2)+,(a1)+ ; load mappings for copyright 1992 sega message dbf d6,- lea (Chunk_Table).l,a1 move.l #vdpComm(VRAM_TtlScr_Plane_A_Name_Table,VRAM,WRITE),d0 moveq #$27,d1 moveq #$1B,d2 jsrto (PlaneMapToVRAM_H40).l, PlaneMapToVRAM_H40 clearRAM Normal_palette,Target_palette_End ; fill two palettes with 0 (black) moveq #PalID_Title,d0 bsr.w PalLoad_ForFade move.b #0,(Debug_mode_flag).w move.w #0,(Two_player_mode).w move.w #$280,(Demo_Time_left).w clr.w (Ctrl_1).w move.b #ObjID_IntroStars,(IntroSonic+id).w ; load Obj0E (flashing intro star) move.b #2,(IntroSonic+subtype).w ; Sonic jsr (RunObjects).l jsr (BuildSprites).l moveq #PLCID_Std1,d0 bsr.w LoadPLC2 move.w #0,(Correct_cheat_entries).w move.w #0,(Correct_cheat_entries_2).w nop nop nop nop nop nop move.w #4,(Sonic_Pos_Record_Index).w move.w #0,(Sonic_Pos_Record_Buf).w lea (Results_Data_2P).w,a1 moveq #bytesToWcnt(Results_Data_2P_End-Results_Data_2P),d0 - move.w #-1,(a1)+ dbf d0,- move.w #-$280,(Camera_X_pos).w move.w (VDP_Reg1_val).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l bsr.w Pal_FadeFromBlack ; loc_3C14: TitleScreen_Loop: move.b #VintID_Title,(Vint_routine).w bsr.w WaitForVint jsr (RunObjects).l jsrto (SwScrl_Title).l, JmpTo_SwScrl_Title jsr (BuildSprites).l ; write alternating 0s and 4s, 80 times, at every 4th word, ; starting at Sprite_Table+6 lea (Sprite_Table+4).w,a1 moveq #0,d0 moveq #79,d6 - tst.w (a1) bne.s + bchg #2,d0 move.w d0,2(a1) + addq.w #8,a1 dbf d6,- bsr.w RunPLC_RAM bsr.w TailsNameCheat tst.w (Demo_Time_left).w beq.w TitleScreen_Demo tst.b (IntroSonic+objoff_2F).w beq.w TitleScreen_Loop move.b (Ctrl_1_Press).w,d0 or.b (Ctrl_2_Press).w,d0 andi.b #button_start_mask,d0 beq.w TitleScreen_Loop ; loop until Start is pressed move.b #GameModeID_Level,(Game_Mode).w ; => Level (Zone play mode) move.b #3,(Life_count).w move.b #3,(Life_count_2P).w moveq #0,d0 move.w d0,(Ring_count).w move.l d0,(Timer).w move.l d0,(Score).w move.w d0,(Ring_count_2P).w move.l d0,(Timer_2P).w move.l d0,(Score_2P).w move.b d0,(Continue_count).w move.l #5000,(Next_Extra_life_score).w move.l #5000,(Next_Extra_life_score_2P).w move.b #MusID_FadeOut,d0 ; prepare to stop music (fade out) bsr.w PlaySound moveq #0,d0 move.b (Title_screen_option).w,d0 bne.s TitleScreen_CheckIfChose2P ; branch if not a 1-player game moveq #0,d0 move.w d0,(Two_player_mode_copy).w move.w d0,(Two_player_mode).w if emerald_hill_zone_act_1=0 move.w d0,(Current_ZoneAndAct).w ; emerald_hill_zone_act_1 else move.w #emerald_hill_zone_act_1,(Current_ZoneAndAct).w endif tst.b (Level_select_flag).w ; has level select cheat been entered? beq.s + ; if not, branch btst #button_A,(Ctrl_1_Held).w ; is A held down? beq.s + ; if not, branch move.b #GameModeID_LevelSelect,(Game_Mode).w ; => LevelSelectMenu rts ; --------------------------------------------------------------------------- + move.w d0,(Current_Special_StageAndAct).w move.w d0,(Got_Emerald).w move.l d0,(Got_Emeralds_array).w move.l d0,(Got_Emeralds_array+4).w rts ; =========================================================================== ; loc_3CF6: TitleScreen_CheckIfChose2P: subq.b #1,d0 bne.s TitleScreen_ChoseOptions moveq #1,d1 move.w d1,(Two_player_mode_copy).w move.w d1,(Two_player_mode).w moveq #0,d0 move.w d0,(Got_Emerald).w move.l d0,(Got_Emeralds_array).w move.l d0,(Got_Emeralds_array+4).w move.b #GameModeID_2PLevelSelect,(Game_Mode).w ; => LevelSelectMenu2P move.b #emerald_hill_zone,(Current_Zone_2P).w rts ; --------------------------------------------------------------------------- ; loc_3D20: TitleScreen_ChoseOptions: move.b #GameModeID_OptionsMenu,(Game_Mode).w ; => OptionsMenu move.b #0,(Options_menu_box).w rts ; =========================================================================== ; loc_3D2E: TitleScreen_Demo: move.b #MusID_FadeOut,d0 bsr.w PlaySound move.w (Demo_number).w,d0 andi.w #7,d0 add.w d0,d0 move.w DemoLevels(pc,d0.w),d0 move.w d0,(Current_ZoneAndAct).w addq.w #1,(Demo_number).w cmpi.w #(DemoLevels_End-DemoLevels)/2,(Demo_number).w blo.s + move.w #0,(Demo_number).w + move.w #1,(Demo_mode_flag).w move.b #GameModeID_Demo,(Game_Mode).w ; => Level (Demo mode) cmpi.w #emerald_hill_zone_act_1,(Current_ZoneAndAct).w bne.s + move.w #1,(Two_player_mode).w + move.b #3,(Life_count).w move.b #3,(Life_count_2P).w moveq #0,d0 move.w d0,(Ring_count).w move.l d0,(Timer).w move.l d0,(Score).w move.w d0,(Ring_count_2P).w move.l d0,(Timer_2P).w move.l d0,(Score_2P).w move.l #5000,(Next_Extra_life_score).w move.l #5000,(Next_Extra_life_score_2P).w rts ; =========================================================================== ; word_3DAC: DemoLevels: dc.w emerald_hill_zone_act_1 ; EHZ (2P) dc.w chemical_plant_zone_act_1 ; CPZ dc.w aquatic_ruin_zone_act_1 ; ARZ dc.w casino_night_zone_act_1 ; CNZ DemoLevels_End: ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_3DB4: TailsNameCheat: lea (TailsNameCheat_Buttons).l,a0 move.w (Correct_cheat_entries).w,d0 adda.w d0,a0 move.b (Ctrl_1_Press).w,d0 andi.b #button_up_mask|button_down_mask|button_left_mask|button_right_mask,d0 beq.s ++ ; rts cmp.b (a0),d0 bne.s + addq.w #1,(Correct_cheat_entries).w tst.b 1(a0) ; read the next entry bne.s ++ ; if it's not zero, return bchg #7,(Graphics_Flags).w ; turn on the cheat that changes MILES to "TAILS" move.b #SndID_Ring,d0 ; play the ring sound for a successfully entered cheat bsr.w PlaySound + move.w #0,(Correct_cheat_entries).w + rts ; End of function TailsNameCheat ; =========================================================================== ; byte_3DEE: TailsNameCheat_Buttons: dc.b button_up_mask dc.b button_down_mask dc.b button_down_mask dc.b button_down_mask dc.b button_up_mask dc.b 0 ; end ; --------------------------------------------------------------------------------- ; Nemesis compressed art ; 10 blocks ; Player 1 2 VS Text ; --------------------------------------------------------------------------------- ; ArtNem_3DF4: ArtNem_Player1VS2: BINCLUDE "art/nemesis/1Player2VS.bin" charset '0','9',0 ; Add character set for numbers charset '*',$A ; Add character for star charset '@',$B ; Add character for copyright symbol charset ':',$C ; Add character for colon charset '.',$D ; Add character for period charset 'A','Z',$E ; Add character set for letters ; word_3E82: CopyrightText: dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + '@',0,0) ; (C) dc.w make_art_tile(ArtTile_VRAM_Start,0,0) ; dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + '1',0,0) ; 1 dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + '9',0,0) ; 9 dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + '9',0,0) ; 9 dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + '2',0,0) ; 2 dc.w make_art_tile(ArtTile_VRAM_Start,0,0) ; dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + 'S',0,0) ; S dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + 'E',0,0) ; E dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + 'G',0,0) ; G dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + 'A',0,0) ; A CopyrightText_End: charset ; Revert character set if ~~removeJmpTos ; sub_3E98: JmpTo_SwScrl_Title jmp (SwScrl_Title).l align 4 endif ;---------------------------------------------------------------------------- ; 1P Music Playlist ;---------------------------------------------------------------------------- ; byte_3EA0: MusicList: zoneOrderedTable 1,1 zoneTableEntry.b MusID_EHZ ; 0 ; EHZ zoneTableEntry.b MusID_EHZ ; 1 zoneTableEntry.b MusID_MTZ ; 2 zoneTableEntry.b MusID_OOZ ; 3 zoneTableEntry.b MusID_MTZ ; 4 ; MTZ1,2 zoneTableEntry.b MusID_MTZ ; 5 ; MTZ3 zoneTableEntry.b MusID_WFZ ; 6 ; WFZ zoneTableEntry.b MusID_HTZ ; 7 ; HTZ zoneTableEntry.b MusID_HPZ ; 8 zoneTableEntry.b MusID_SCZ ; 9 zoneTableEntry.b MusID_OOZ ; 10 ; OOZ zoneTableEntry.b MusID_MCZ ; 11 ; MCZ zoneTableEntry.b MusID_CNZ ; 12 ; CNZ zoneTableEntry.b MusID_CPZ ; 13 ; CPZ zoneTableEntry.b MusID_DEZ ; 14 ; DEZ zoneTableEntry.b MusID_ARZ ; 15 ; ARZ zoneTableEntry.b MusID_SCZ ; 16 ; SCZ zoneTableEnd even ;---------------------------------------------------------------------------- ; 2P Music Playlist ;---------------------------------------------------------------------------- ; byte_3EB2: MusicList2: zoneOrderedTable 1,1 zoneTableEntry.b MusID_EHZ_2P ; 0 ; EHZ 2P zoneTableEntry.b MusID_EHZ ; 1 zoneTableEntry.b MusID_MTZ ; 2 zoneTableEntry.b MusID_OOZ ; 3 zoneTableEntry.b MusID_MTZ ; 4 zoneTableEntry.b MusID_MTZ ; 5 zoneTableEntry.b MusID_WFZ ; 6 zoneTableEntry.b MusID_HTZ ; 7 zoneTableEntry.b MusID_HPZ ; 8 zoneTableEntry.b MusID_SCZ ; 9 zoneTableEntry.b MusID_OOZ ; 10 zoneTableEntry.b MusID_MCZ_2P ; 11 ; MCZ 2P zoneTableEntry.b MusID_CNZ_2P ; 12 ; CNZ 2P zoneTableEntry.b MusID_CPZ ; 13 zoneTableEntry.b MusID_DEZ ; 14 zoneTableEntry.b MusID_ARZ ; 15 zoneTableEntry.b MusID_SCZ ; 16 zoneTableEnd even ; =========================================================================== ; --------------------------------------------------------------------------- ; Level ; DEMO AND ZONE LOOP (MLS values $08, $0C; bit 7 set indicates that load routine is running) ; --------------------------------------------------------------------------- ; loc_3EC4: Level: bset #GameModeFlag_TitleCard,(Game_Mode).w ; add $80 to screen mode (for pre level sequence) tst.w (Demo_mode_flag).w ; test the old flag for the credits demos (now unused) bmi.s + move.b #MusID_FadeOut,d0 bsr.w PlaySound ; fade out music + bsr.w ClearPLC bsr.w Pal_FadeToBlack tst.w (Demo_mode_flag).w bmi.s Level_ClrRam move #$2700,sr bsr.w ClearScreen jsr (LoadTitleCard).l ; load title card patterns move #$2300,sr moveq #0,d0 move.w d0,(Timer_frames).w move.b (Current_Zone).w,d0 ; multiply d0 by 12, the size of a level art load block add.w d0,d0 add.w d0,d0 move.w d0,d1 add.w d0,d0 add.w d1,d0 lea (LevelArtPointers).l,a2 lea (a2,d0.w),a2 moveq #0,d0 move.b (a2),d0 ; PLC1 ID beq.s + bsr.w LoadPLC + moveq #PLCID_Std2,d0 bsr.w LoadPLC bsr.w Level_SetPlayerMode moveq #PLCID_Miles1up,d0 tst.w (Two_player_mode).w bne.s + cmpi.w #2,(Player_mode).w bne.s Level_ClrRam addq.w #PLCID_MilesLife-PLCID_Miles1up,d0 + tst.b (Graphics_Flags).w bpl.s + addq.w #PLCID_Tails1up-PLCID_Miles1up,d0 + bsr.w LoadPLC ; loc_3F48: Level_ClrRam: clearRAM Sprite_Table_Input,Sprite_Table_Input_End clearRAM Object_RAM,Object_RAM_End ; clear object RAM clearRAM MiscLevelVariables,MiscLevelVariables_End clearRAM Misc_Variables,Misc_Variables_End clearRAM Oscillating_Data,Oscillating_variables_End ; Bug: The '+C0' shouldn't be here; CNZ_saucer_data is only $40 bytes large clearRAM CNZ_saucer_data,CNZ_saucer_data_End+$C0 cmpi.w #chemical_plant_zone_act_2,(Current_ZoneAndAct).w ; CPZ 2 beq.s Level_InitWater cmpi.b #aquatic_ruin_zone,(Current_Zone).w ; ARZ beq.s Level_InitWater cmpi.b #hidden_palace_zone,(Current_Zone).w ; HPZ bne.s + Level_InitWater: move.b #1,(Water_flag).w move.w #0,(Two_player_mode).w + lea (VDP_control_port).l,a6 move.w #$8B03,(a6) ; EXT-INT disabled, V scroll by screen, H scroll by line move.w #$8200|(VRAM_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000 move.w #$8400|(VRAM_Plane_B_Name_Table/$2000),(a6) ; PNT B base: $E000 move.w #$8500|(VRAM_Sprite_Attribute_Table/$200),(a6) ; Sprite attribute table base: $F800 move.w #$9001,(a6) ; Scroll table size: 64x32 move.w #$8004,(a6) ; H-INT disabled move.w #$8720,(a6) ; Background palette/color: 2/0 move.w #$8C81,(a6) ; H res 40 cells, no interlace tst.b (Debug_options_flag).w beq.s ++ btst #button_C,(Ctrl_1_Held).w beq.s + move.w #$8C89,(a6) ; H res 40 cells, no interlace, S/H enabled + btst #button_A,(Ctrl_1_Held).w beq.s + move.b #1,(Debug_mode_flag).w + move.w #$8ADF,(Hint_counter_reserve).w ; H-INT every 223rd scanline tst.w (Two_player_mode).w beq.s + move.w #$8A6B,(Hint_counter_reserve).w ; H-INT every 108th scanline move.w #$8014,(a6) ; H-INT enabled move.w #$8C87,(a6) ; H res 40 cells, double res interlace + move.w (Hint_counter_reserve).w,(a6) clr.w (VDP_Command_Buffer).w move.l #VDP_Command_Buffer,(VDP_Command_Buffer_Slot).w tst.b (Water_flag).w ; does level have water? beq.s Level_LoadPal ; if not, branch move.w #$8014,(a6) ; H-INT enabled moveq #0,d0 move.w (Current_ZoneAndAct).w,d0 if ~~useFullWaterTables subi.w #hidden_palace_zone_act_1,d0 endif ror.b #1,d0 lsr.w #6,d0 andi.w #$FFFE,d0 lea (WaterHeight).l,a1 ; load water height array move.w (a1,d0.w),d0 move.w d0,(Water_Level_1).w ; set water heights move.w d0,(Water_Level_2).w move.w d0,(Water_Level_3).w clr.b (Water_routine).w ; clear water routine counter clr.b (Water_fullscreen_flag).w ; clear water movement move.b #1,(Water_on).w ; enable water ; loc_407C: Level_LoadPal: moveq #PalID_BGND,d0 bsr.w PalLoad_Now ; load Sonic's palette line tst.b (Water_flag).w ; does level have water? beq.s Level_GetBgm ; if not, branch moveq #PalID_HPZ_U,d0 ; palette number $15 cmpi.b #hidden_palace_zone,(Current_Zone).w beq.s Level_WaterPal ; branch if level is HPZ moveq #PalID_CPZ_U,d0 ; palette number $16 cmpi.b #chemical_plant_zone,(Current_Zone).w beq.s Level_WaterPal ; branch if level is CPZ moveq #PalID_ARZ_U,d0 ; palette number $17 ; loc_409E: Level_WaterPal: bsr.w PalLoad_Water_Now ; load underwater palette (with d0) tst.b (Last_star_pole_hit).w ; is it the start of the level? beq.s Level_GetBgm ; if yes, branch move.b (Saved_Water_move).w,(Water_fullscreen_flag).w ; loc_40AE: Level_GetBgm: tst.w (Demo_mode_flag).w bmi.s + moveq #0,d0 move.b (Current_Zone).w,d0 lea_ MusicList,a1 tst.w (Two_player_mode).w beq.s Level_PlayBgm lea_ MusicList2,a1 ; loc_40C8: Level_PlayBgm: move.b (a1,d0.w),d0 ; load from music playlist move.w d0,(Level_Music).w ; store level music bsr.w PlayMusic ; play level music move.b #ObjID_TitleCard,(TitleCard+id).w ; load Obj34 (level title card) at $FFFFB080 ; loc_40DA: Level_TtlCard: move.b #VintID_TitleCard,(Vint_routine).w bsr.w WaitForVint jsr (RunObjects).l jsr (BuildSprites).l bsr.w RunPLC_RAM move.w (TitleCard_ZoneName+x_pos).w,d0 cmp.w (TitleCard_ZoneName+titlecard_x_target).w,d0 ; has title card sequence finished? bne.s Level_TtlCard ; if not, branch tst.l (Plc_Buffer).w ; are there any items in the pattern load cue? bne.s Level_TtlCard ; if yes, branch move.b #VintID_TitleCard,(Vint_routine).w bsr.w WaitForVint jsr (Hud_Base).l + moveq #PalID_BGND,d0 bsr.w PalLoad_ForFade ; load Sonic's palette line bsr.w LevelSizeLoad jsrto (DeformBgLayer).l, JmpTo_DeformBgLayer clr.w (Vscroll_Factor_FG).w move.w #-$E0,(Vscroll_Factor_P2_FG).w clearRAM Horiz_Scroll_Buf,Horiz_Scroll_Buf_End bsr.w LoadZoneTiles jsrto (loadZoneBlockMaps).l, JmpTo_loadZoneBlockMaps jsr (loc_402D4).l jsrto (DrawInitialBG).l, JmpTo_DrawInitialBG jsr (FloorLog_Unk).l bsr.w LoadCollisionIndexes bsr.w WaterEffects bsr.w InitPlayers move.w #0,(Ctrl_1_Logical).w move.w #0,(Ctrl_2_Logical).w move.w #0,(Ctrl_1).w move.w #0,(Ctrl_2).w move.b #1,(Control_Locked).w move.b #1,(Control_Locked_P2).w move.b #0,(Level_started_flag).w ; Level_ChkWater: tst.b (Water_flag).w ; does level have water? beq.s + ; if not, branch move.b #ObjID_WaterSurface,(WaterSurface1+id).w ; load Obj04 (water surface) at $FFFFB380 move.w #$60,(WaterSurface1+x_pos).w ; set horizontal offset move.b #ObjID_WaterSurface,(WaterSurface2+id).w ; load Obj04 (water surface) at $FFFFB3C0 move.w #$120,(WaterSurface2+x_pos).w ; set different horizontal offset + cmpi.b #chemical_plant_zone,(Current_Zone).w ; check if zone == CPZ bne.s + ; branch if not move.b #ObjID_CPZPylon,(CPZPylon+id).w ; load Obj7C (CPZ pylon) at $FFFFB340 + cmpi.b #oil_ocean_zone,(Current_Zone).w ; check if zone == OOZ bne.s Level_ClrHUD ; branch if not move.b #ObjID_Oil,(Oil+id).w ; load Obj07 (OOZ oil) at $FFFFB380 ; Level_LoadObj: misnomer now Level_ClrHUD: moveq #0,d0 tst.b (Last_star_pole_hit).w ; are you starting from a lamppost? bne.s Level_FromCheckpoint ; if yes, branch move.w d0,(Ring_count).w ; clear rings move.l d0,(Timer).w ; clear time move.b d0,(Extra_life_flags).w ; clear extra lives counter move.w d0,(Ring_count_2P).w ; ditto for player 2 move.l d0,(Timer_2P).w move.b d0,(Extra_life_flags_2P).w ; loc_41E4: Level_FromCheckpoint: move.b d0,(Time_Over_flag).w move.b d0,(Time_Over_flag_2P).w move.b d0,(SlotMachine_Routine).w move.w d0,(SlotMachineInUse).w move.w d0,(Debug_placement_mode).w move.w d0,(Level_Inactive_flag).w move.b d0,(Teleport_timer).w move.b d0,(Teleport_flag).w move.w d0,(Rings_Collected).w move.w d0,(Rings_Collected_2P).w move.w d0,(Monitors_Broken).w move.w d0,(Monitors_Broken_2P).w move.w d0,(Loser_Time_Left).w bsr.w OscillateNumInit move.b #1,(Update_HUD_score).w move.b #1,(Update_HUD_rings).w move.b #1,(Update_HUD_timer).w move.b #1,(Update_HUD_timer_2P).w jsr (ObjectsManager).l jsr (RingsManager).l jsr (SpecialCNZBumpers).l jsr (RunObjects).l jsr (BuildSprites).l jsrto (AniArt_Load).l, JmpTo_AniArt_Load bsr.w SetLevelEndType move.w #0,(Demo_button_index).w move.w #0,(Demo_button_index_2P).w lea (DemoScriptPointers).l,a1 moveq #0,d0 move.b (Current_Zone).w,d0 ; load zone value lsl.w #2,d0 movea.l (a1,d0.w),a1 tst.w (Demo_mode_flag).w bpl.s + lea (EndingDemoScriptPointers).l,a1 move.w (Ending_demo_number).w,d0 subq.w #1,d0 lsl.w #2,d0 movea.l (a1,d0.w),a1 + move.b 1(a1),(Demo_press_counter).w tst.b (Current_Zone).w ; emerald_hill_zone bne.s + lea (Demo_EHZ_Tails).l,a1 move.b 1(a1),(Demo_press_counter_2P).w + move.w #$668,(Demo_Time_left).w tst.w (Demo_mode_flag).w bpl.s + move.w #$21C,(Demo_Time_left).w cmpi.w #4,(Ending_demo_number).w bne.s + move.w #$1FE,(Demo_Time_left).w + tst.b (Water_flag).w beq.s ++ moveq #PalID_HPZ_U,d0 cmpi.b #hidden_palace_zone,(Current_Zone).w beq.s + moveq #PalID_CPZ_U,d0 cmpi.b #chemical_plant_zone,(Current_Zone).w beq.s + moveq #PalID_ARZ_U,d0 + bsr.w PalLoad_Water_ForFade + move.w #-1,(TitleCard_ZoneName+titlecard_leaveflag).w move.b #$E,(TitleCard_Left+routine).w ; make the left part move offscreen move.w #$A,(TitleCard_Left+titlecard_location).w - move.b #VintID_TitleCard,(Vint_routine).w bsr.w WaitForVint jsr (RunObjects).l jsr (BuildSprites).l bsr.w RunPLC_RAM tst.b (TitleCard_Background+id).w bne.s - ; loop while the title card background is still loaded lea (TitleCard).w,a1 move.b #$16,TitleCard_ZoneName-TitleCard+routine(a1) move.w #$2D,TitleCard_ZoneName-TitleCard+anim_frame_duration(a1) move.b #$16,TitleCard_Zone-TitleCard+routine(a1) move.w #$2D,TitleCard_Zone-TitleCard+anim_frame_duration(a1) tst.b TitleCard_ActNumber-TitleCard+id(a1) beq.s + ; branch if the act number has been unloaded move.b #$16,TitleCard_ActNumber-TitleCard+routine(a1) move.w #$2D,TitleCard_ActNumber-TitleCard+anim_frame_duration(a1) + move.b #0,(Control_Locked).w move.b #0,(Control_Locked_P2).w move.b #1,(Level_started_flag).w ; Level_StartGame: loc_435A: bclr #GameModeFlag_TitleCard,(Game_Mode).w ; clear $80 from the game mode ; --------------------------------------------------------------------------- ; Main level loop (when all title card and loading sequences are finished) ; --------------------------------------------------------------------------- ; loc_4360: Level_MainLoop: bsr.w PauseGame move.b #VintID_Level,(Vint_routine).w bsr.w WaitForVint addq.w #1,(Timer_frames).w ; add 1 to level timer bsr.w MoveSonicInDemo bsr.w WaterEffects jsr (RunObjects).l tst.w (Level_Inactive_flag).w bne.w Level jsrto (DeformBgLayer).l, JmpTo_DeformBgLayer bsr.w UpdateWaterSurface jsr (RingsManager).l cmpi.b #casino_night_zone,(Current_Zone).w ; is it CNZ? bne.s + ; if not, branch past jsr jsr (SpecialCNZBumpers).l + jsrto (AniArt_Load).l, JmpTo_AniArt_Load bsr.w PalCycle_Load bsr.w RunPLC_RAM bsr.w OscillateNumDo bsr.w ChangeRingFrame bsr.w CheckLoadSignpostArt jsr (BuildSprites).l jsr (ObjectsManager).l cmpi.b #GameModeID_Demo,(Game_Mode).w ; check if in demo mode beq.s + cmpi.b #GameModeID_Level,(Game_Mode).w ; check if in normal play mode beq.w Level_MainLoop rts ; --------------------------------------------------------------------------- + tst.w (Level_Inactive_flag).w bne.s + tst.w (Demo_Time_left).w beq.s + cmpi.b #GameModeID_Demo,(Game_Mode).w beq.w Level_MainLoop move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen rts ; --------------------------------------------------------------------------- + cmpi.b #GameModeID_Demo,(Game_Mode).w bne.s + move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen + move.w #1*60,(Demo_Time_left).w ; 1 second move.w #$3F,(Palette_fade_range).w clr.w (PalChangeSpeed).w - move.b #VintID_Level,(Vint_routine).w bsr.w WaitForVint bsr.w MoveSonicInDemo jsr (RunObjects).l jsr (BuildSprites).l jsr (ObjectsManager).l subq.w #1,(PalChangeSpeed).w bpl.s + move.w #2,(PalChangeSpeed).w bsr.w Pal_FadeToBlack.UpdateAllColours + tst.w (Demo_Time_left).w bne.s - rts ; --------------------------------------------------------------------------- ; Subroutine to set the player mode, which is forced to Sonic and Tails in ; the demo mode and in 2P mode ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_4450: Level_SetPlayerMode: cmpi.b #GameModeID_TitleCard|GameModeID_Demo,(Game_Mode).w ; pre-level demo mode? beq.s + ; if yes, branch tst.w (Two_player_mode).w ; 2P mode? bne.s + ; if yes, branch move.w (Player_option).w,(Player_mode).w ; use the option chosen in the Options screen rts ; --------------------------------------------------------------------------- + move.w #0,(Player_mode).w ; force Sonic and Tails rts ; End of function Level_SetPlayerMode ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_446E: InitPlayers: move.w (Player_mode).w,d0 bne.s InitPlayers_Alone ; branch if this isn't a Sonic and Tails game move.b #ObjID_Sonic,(MainCharacter+id).w ; load Obj01 Sonic object at $FFFFB000 move.b #ObjID_SpindashDust,(Sonic_Dust+id).w ; load Obj08 Sonic's spindash dust/splash object at $FFFFD100 cmpi.b #wing_fortress_zone,(Current_Zone).w beq.s + ; skip loading Tails if this is WFZ cmpi.b #death_egg_zone,(Current_Zone).w beq.s + ; skip loading Tails if this is DEZ cmpi.b #sky_chase_zone,(Current_Zone).w beq.s + ; skip loading Tails if this is SCZ move.b #ObjID_Tails,(Sidekick+id).w ; load Obj02 Tails object at $FFFFB040 move.w (MainCharacter+x_pos).w,(Sidekick+x_pos).w move.w (MainCharacter+y_pos).w,(Sidekick+y_pos).w subi.w #$20,(Sidekick+x_pos).w addi_.w #4,(Sidekick+y_pos).w move.b #ObjID_SpindashDust,(Tails_Dust+id).w ; load Obj08 Tails' spindash dust/splash object at $FFFFD140 + rts ; =========================================================================== ; loc_44BE: InitPlayers_Alone: ; either Sonic or Tails but not both subq.w #1,d0 bne.s InitPlayers_TailsAlone ; branch if this is a Tails alone game move.b #ObjID_Sonic,(MainCharacter+id).w ; load Obj01 Sonic object at $FFFFB000 move.b #ObjID_SpindashDust,(Sonic_Dust+id).w ; load Obj08 Sonic's spindash dust/splash object at $FFFFD100 rts ; =========================================================================== ; loc_44D0: InitPlayers_TailsAlone: move.b #ObjID_Tails,(MainCharacter+id).w ; load Obj02 Tails object at $FFFFB000 move.b #ObjID_SpindashDust,(Tails_Dust+id).w ; load Obj08 Tails' spindash dust/splash object at $FFFFD100 addi_.w #4,(MainCharacter+y_pos).w rts ; End of function InitPlayers ; --------------------------------------------------------------------------- ; Subroutine to move the water or oil surface sprites to where the screen is at ; (the closest match I could find to this subroutine in Sonic 1 is Obj1B_Action) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_44E4: UpdateWaterSurface: tst.b (Water_flag).w beq.s ++ ; rts move.w (Camera_X_pos).w,d1 btst #0,(Timer_frames+1).w beq.s + addi.w #$20,d1 + ; match obj x-position to screen position move.w d1,d0 addi.w #$60,d0 move.w d0,(WaterSurface1+x_pos).w addi.w #$120,d1 move.w d1,(WaterSurface2+x_pos).w + rts ; End of function UpdateWaterSurface ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; --------------------------------------------------------------------------- ; Subroutine to do special water effects ; --------------------------------------------------------------------------- ; sub_450E: ; LZWaterEffects: WaterEffects: tst.b (Water_flag).w ; does level have water? beq.s NonWaterEffects ; if not, branch tst.b (Deform_lock).w bne.s MoveWater cmpi.b #6,(MainCharacter+routine).w ; is player dead? bhs.s MoveWater ; if yes, branch bsr.w DynamicWater ; loc_4526: ; LZMoveWater: MoveWater: clr.b (Water_fullscreen_flag).w moveq #0,d0 cmpi.b #aquatic_ruin_zone,(Current_Zone).w ; is level ARZ? beq.s + ; if yes, branch move.b (Oscillating_Data).w,d0 lsr.w #1,d0 + add.w (Water_Level_2).w,d0 move.w d0,(Water_Level_1).w ; calculate distance between water surface and top of screen move.w (Water_Level_1).w,d0 sub.w (Camera_Y_pos).w,d0 bhs.s + tst.w d0 bpl.s + move.b #$DF,(Hint_counter_reserve+1).w ; H-INT every 224th scanline move.b #1,(Water_fullscreen_flag).w + cmpi.w #$DF,d0 blo.s + move.w #$DF,d0 + move.b d0,(Hint_counter_reserve+1).w ; H-INT every d0 scanlines ; loc_456A: NonWaterEffects: cmpi.b #oil_ocean_zone,(Current_Zone).w ; is the level OOZ? bne.s + ; if not, branch bsr.w OilSlides ; call oil slide routine + cmpi.b #wing_fortress_zone,(Current_Zone).w ; is the level WFZ? bne.s + ; if not, branch bsr.w WindTunnel ; call wind and block break routine + rts ; End of function WaterEffects ; =========================================================================== if useFullWaterTables WaterHeight: zoneOrderedTable 2,2 zoneTableEntry.w $600, $600 ; EHZ zoneTableEntry.w $600, $600 ; Zone 1 zoneTableEntry.w $600, $600 ; WZ zoneTableEntry.w $600, $600 ; Zone 3 zoneTableEntry.w $600, $600 ; MTZ zoneTableEntry.w $600, $600 ; MTZ zoneTableEntry.w $600, $600 ; WFZ zoneTableEntry.w $600, $600 ; HTZ zoneTableEntry.w $600, $600 ; HPZ zoneTableEntry.w $600, $600 ; Zone 9 zoneTableEntry.w $600, $600 ; OOZ zoneTableEntry.w $600, $600 ; MCZ zoneTableEntry.w $600, $600 ; CNZ zoneTableEntry.w $600, $710 ; CPZ zoneTableEntry.w $600, $600 ; DEZ zoneTableEntry.w $410, $510 ; ARZ zoneTableEntry.w $600, $600 ; SCZ zoneTableEnd else ; word_4584: WaterHeight: dc.w $600, $600 ; HPZ dc.w $600, $600 ; Zone 9 dc.w $600, $600 ; OOZ dc.w $600, $600 ; MCZ dc.w $600, $600 ; CNZ dc.w $600, $710 ; CPZ dc.w $600, $600 ; DEZ dc.w $410, $510 ; ARZ endif ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_45A4: ; LZDynamicWater: DynamicWater: moveq #0,d0 move.w (Current_ZoneAndAct).w,d0 if ~~useFullWaterTables subi.w #hidden_palace_zone_act_1,d0 endif ror.b #1,d0 lsr.w #6,d0 andi.w #$FFFE,d0 move.w Dynamic_water_routine_table(pc,d0.w),d0 jsr Dynamic_water_routine_table(pc,d0.w) moveq #0,d1 move.b (Water_on).w,d1 move.w (Water_Level_3).w,d0 sub.w (Water_Level_2).w,d0 beq.s ++ ; rts bcc.s + neg.w d1 + add.w d1,(Water_Level_2).w + rts ; End of function DynamicWater ; =========================================================================== if useFullWaterTables Dynamic_water_routine_table: zoneOrderedOffsetTable 2,2 zoneOffsetTableEntry.w DynamicWaterNull ; EHZ 1 zoneOffsetTableEntry.w DynamicWaterNull ; EHZ 2 zoneOffsetTableEntry.w DynamicWaterNull ; Zone 1 zoneOffsetTableEntry.w DynamicWaterNull ; Zone 1 zoneOffsetTableEntry.w DynamicWaterNull ; WZ 1 zoneOffsetTableEntry.w DynamicWaterNull ; WZ 2 zoneOffsetTableEntry.w DynamicWaterNull ; Zone 3 zoneOffsetTableEntry.w DynamicWaterNull ; Zone 3 zoneOffsetTableEntry.w DynamicWaterNull ; MTZ 1 zoneOffsetTableEntry.w DynamicWaterNull ; MTZ 2 zoneOffsetTableEntry.w DynamicWaterNull ; MTZ 3 zoneOffsetTableEntry.w DynamicWaterNull ; MTZ 4 zoneOffsetTableEntry.w DynamicWaterNull ; WFZ 1 zoneOffsetTableEntry.w DynamicWaterNull ; WFZ 2 zoneOffsetTableEntry.w DynamicWaterNull ; HTZ 1 zoneOffsetTableEntry.w DynamicWaterNull ; HTZ 2 zoneOffsetTableEntry.w DynamicWaterNull ; HPZ 1 zoneOffsetTableEntry.w DynamicWaterNull ; HPZ 2 zoneOffsetTableEntry.w DynamicWaterNull ; Zone 9 zoneOffsetTableEntry.w DynamicWaterNull ; Zone 9 zoneOffsetTableEntry.w DynamicWaterNull ; OOZ 1 zoneOffsetTableEntry.w DynamicWaterNull ; OOZ 2 zoneOffsetTableEntry.w DynamicWaterNull ; MCZ 1 zoneOffsetTableEntry.w DynamicWaterNull ; MCZ 2 zoneOffsetTableEntry.w DynamicWaterNull ; CNZ 1 zoneOffsetTableEntry.w DynamicWaterNull ; CNZ 2 zoneOffsetTableEntry.w DynamicWaterNull ; CPZ 1 zoneOffsetTableEntry.w DynamicWaterCPZ2 ; CPZ 2 zoneOffsetTableEntry.w DynamicWaterNull ; DEZ 1 zoneOffsetTableEntry.w DynamicWaterNull ; DEZ 2 zoneOffsetTableEntry.w DynamicWaterNull ; ARZ 1 zoneOffsetTableEntry.w DynamicWaterNull ; ARZ 2 zoneOffsetTableEntry.w DynamicWaterNull ; SCZ 1 zoneOffsetTableEntry.w DynamicWaterNull ; SCZ 2 zoneTableEnd else ; off_45D8: Dynamic_water_routine_table: offsetTable offsetTableEntry.w DynamicWaterNull ; HPZ 1 offsetTableEntry.w DynamicWaterNull ; HPZ 2 offsetTableEntry.w DynamicWaterNull ; Zone 9 offsetTableEntry.w DynamicWaterNull ; Zone 9 offsetTableEntry.w DynamicWaterNull ; OOZ 1 offsetTableEntry.w DynamicWaterNull ; OOZ 2 offsetTableEntry.w DynamicWaterNull ; MCZ 1 offsetTableEntry.w DynamicWaterNull ; MCZ 2 offsetTableEntry.w DynamicWaterNull ; CNZ 1 offsetTableEntry.w DynamicWaterNull ; CNZ 2 offsetTableEntry.w DynamicWaterNull ; CPZ 1 offsetTableEntry.w DynamicWaterCPZ2 ; CPZ 2 offsetTableEntry.w DynamicWaterNull ; DEZ 1 offsetTableEntry.w DynamicWaterNull ; DEZ 2 offsetTableEntry.w DynamicWaterNull ; ARZ 1 offsetTableEntry.w DynamicWaterNull ; ARZ 2 endif ; =========================================================================== ; return_45F8: DynamicWaterNull: rts ; =========================================================================== ; loc_45FA: DynamicWaterCPZ2: cmpi.w #$1DE0,(Camera_X_pos).w blo.s + ; rts move.w #$510,(Water_Level_3).w + rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Equates: windtunnel_min_x_pos = 0 windtunnel_max_x_pos = 4 windtunnel_min_y_pos = 2 windtunnel_max_y_pos = 6 ; sub_460A: WindTunnel: tst.w (Debug_placement_mode).w bne.w WindTunnel_End ; don't interact with wind tunnels while in debug mode lea (WindTunnelsCoordinates).l,a2 moveq #(WindTunnelsCoordinates_End-WindTunnelsCoordinates)/8-1,d1 lea (MainCharacter).w,a1 ; a1=character - ; check for current wind tunnel if the main character is inside it move.w x_pos(a1),d0 cmp.w windtunnel_min_x_pos(a2),d0 blo.w WindTunnel_Leave ; branch, if main character is too far left cmp.w windtunnel_max_x_pos(a2),d0 bhs.w WindTunnel_Leave ; branch, if main character is too far right move.w y_pos(a1),d2 cmp.w windtunnel_min_y_pos(a2),d2 blo.w WindTunnel_Leave ; branch, if main character is too far up cmp.w windtunnel_max_y_pos(a2),d2 bhs.s WindTunnel_Leave ; branch, if main character is too far down tst.b (WindTunnel_holding_flag).w bne.w WindTunnel_End cmpi.b #4,routine(a1) ; is the main character hurt, dying, etc. ? bhs.s WindTunnel_LeaveHurt ; if yes, branch move.b #1,(WindTunnel_flag).w ; affects character animation and bubble movement subi_.w #4,x_pos(a1) ; move main character to the left move.w #-$400,x_vel(a1) move.w #0,y_vel(a1) move.b #AniIDSonAni_Float2,anim(a1) bset #1,status(a1) ; set "in-air" bit btst #button_up,(Ctrl_1_Held).w ; is Up being pressed? beq.s + ; if not, branch subq.w #1,y_pos(a1) ; move up + btst #button_down,(Ctrl_1_Held).w ; is Down being pressed? beq.s + ; if not, branch addq.w #1,y_pos(a1) ; move down + rts ; =========================================================================== ; loc_4690: WindTunnel_Leave: addq.w #8,a2 dbf d1,- ; check next tunnel ; when all wind tunnels have been checked tst.b (WindTunnel_flag).w beq.s WindTunnel_End move.b #AniIDSonAni_Walk,anim(a1) ; loc_46A2: WindTunnel_LeaveHurt: ; the main character is hurt or dying, leave the tunnel and don't check the other clr.b (WindTunnel_flag).w ; return_46A6: WindTunnel_End: rts ; End of function WindTunnel ; =========================================================================== ; word_46A8: WindTunnelsCoordinates: dc.w $1510,$400,$1AF0,$580 dc.w $20F0,$618,$2500,$680 WindTunnelsCoordinates_End: ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_46B8: OilSlides: lea (MainCharacter).w,a1 ; a1=character move.b (Ctrl_1_Held_Logical).w,d2 bsr.s + lea (Sidekick).w,a1 ; a1=character move.b (Ctrl_2_Held_Logical).w,d2 + btst #1,status(a1) bne.s + move.w y_pos(a1),d0 add.w d0,d0 andi.w #$F00,d0 move.w x_pos(a1),d1 lsr.w #7,d1 andi.w #$7F,d1 add.w d1,d0 lea (Level_Layout).w,a2 move.b (a2,d0.w),d0 lea OilSlides_Chunks_End(pc),a2 moveq #OilSlides_Chunks_End-OilSlides_Chunks-1,d1 - cmp.b -(a2),d0 dbeq d1,- beq.s loc_4712 + if status_sec_isSliding = 7 tst.b status_secondary(a1) bpl.s + ; rts else btst #status_sec_isSliding,status_secondary(a1) beq.s + ; rts endif move.w #5,move_lock(a1) andi.b #(~status_sec_isSliding_mask)&$FF,status_secondary(a1) + rts ; =========================================================================== loc_4712: lea (OilSlides_Speeds).l,a2 move.b (a2,d1.w),d0 beq.s loc_476E move.b inertia(a1),d1 tst.b d0 bpl.s + cmp.b d0,d1 ble.s ++ subi.w #$40,inertia(a1) bra.s ++ ; =========================================================================== + cmp.b d0,d1 bge.s + addi.w #$40,inertia(a1) + bclr #0,status(a1) tst.b d1 bpl.s + bset #0,status(a1) + move.b #AniIDSonAni_Slide,anim(a1) ori.b #status_sec_isSliding_mask,status_secondary(a1) move.b (Vint_runcount+3).w,d0 andi.b #$1F,d0 bne.s + ; rts move.w #SndID_OilSlide,d0 jsr (PlaySound).l + rts ; =========================================================================== loc_476E: move.w #4,d1 move.w inertia(a1),d0 btst #button_left,d2 beq.s + move.b #AniIDSonAni_Walk,anim(a1) bset #0,status(a1) sub.w d1,d0 tst.w d0 bpl.s + sub.w d1,d0 + btst #button_right,d2 beq.s + move.b #AniIDSonAni_Walk,anim(a1) bclr #0,status(a1) add.w d1,d0 tst.w d0 bmi.s + add.w d1,d0 + move.w #4,d1 tst.w d0 beq.s +++ bmi.s ++ sub.w d1,d0 bhi.s + move.w #0,d0 move.b #AniIDSonAni_Wait,anim(a1) + bra.s ++ ; =========================================================================== + add.w d1,d0 bhi.s + move.w #0,d0 move.b #AniIDSonAni_Wait,anim(a1) + move.w d0,inertia(a1) ori.b #status_sec_isSliding_mask,status_secondary(a1) rts ; End of function OilSlides ; =========================================================================== OilSlides_Speeds: dc.b -8, -8, -8, 8, 8, 0, 0, 0, -8, -8, 0, 8, 8, 8, 0, 8 dc.b 8, 8, 0, -8, 0, 0, -8, 8, -8, -8, -8, 8, 8, 8, -8, -8 ; 16 ; These are the IDs of the chunks where Sonic and Tails will slide OilSlides_Chunks: dc.b $2F,$30,$31,$33,$35,$38,$3A,$3C,$63,$64,$83,$90,$91,$93,$A1,$A3 dc.b $BD,$C7,$C8,$CE,$D7,$D8,$E6,$EB,$EC,$ED,$F1,$F2,$F3,$F4,$FA,$FD ; 16 OilSlides_Chunks_End: even ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_481E: MoveSonicInDemo: tst.w (Demo_mode_flag).w ; is demo mode on? bne.w MoveDemo_On ; if yes, branch rts ; --------------------------------------------------------------------------- ; demo recording routine ; (unused/dead code, but obviously used during development) ; --------------------------------------------------------------------------- ; MoveDemo_Record: loc_4828: ; calculate output location of recorded player 1 demo? lea (DemoScriptPointers).l,a1 moveq #0,d0 move.b (Current_Zone).w,d0 lsl.w #2,d0 movea.l (a1,d0.w),a1 move.w (Demo_button_index).w,d0 adda.w d0,a1 move.b (Ctrl_1_Held).w,d0 ; load input of player 1 cmp.b (a1),d0 ; is same button held? bne.s + ; if not, branch addq.b #1,1(a1) ; increment press length counter cmpi.b #$FF,1(a1) ; is button held too long? beq.s + ; if yes, branch bra.s MoveDemo_Record_P2 ; go to player 2 ; =========================================================================== + move.b d0,2(a1) ; store last button press move.b #0,3(a1) ; reset hold length counter addq.w #2,(Demo_button_index).w ; advance to next button press andi.w #$3FF,(Demo_button_index).w ; wrap at max button press changes 1024 ; loc_486A: MoveDemo_Record_P2: cmpi.b #emerald_hill_zone,(Current_Zone).w bne.s ++ ; rts lea ($FEC000).l,a1 ; output location of recorded player 2 demo? (unknown) move.w (Demo_button_index_2P).w,d0 adda.w d0,a1 move.b (Ctrl_2_Held).w,d0 ; load input of player 2 cmp.b (a1),d0 ; is same button held? bne.s + ; if not, branch addq.b #1,1(a1) ; increment press length counter cmpi.b #$FF,1(a1) ; is button held too long? beq.s + ; if yes, branch bra.s ++ ; if not, return ; =========================================================================== + move.b d0,2(a1) ; store last button press move.b #0,3(a1) ; reset hold length counter addq.w #2,(Demo_button_index_2P).w ; advance to next button press andi.w #$3FF,(Demo_button_index_2P).w ; wrap at max button press changes 1024 + rts ; end of inactive recording code ; =========================================================================== ; continue with MoveSonicInDemo: ; loc_48AA: MoveDemo_On: move.b (Ctrl_1_Press).w,d0 or.b (Ctrl_2_Press).w,d0 andi.b #button_start_mask,d0 beq.s + tst.w (Demo_mode_flag).w bmi.s + move.b #GameModeID_TitleScreen,(Game_Mode).w ; => TitleScreen + lea (DemoScriptPointers).l,a1 ; load pointer to input data moveq #0,d0 move.b (Current_Zone).w,d0 cmpi.b #GameModeID_SpecialStage,(Game_Mode).w ; special stage mode? bne.s MoveDemo_On_P1 ; if yes, branch moveq #6,d0 ; loc_48DA: MoveDemo_On_P1: lsl.w #2,d0 movea.l (a1,d0.w),a1 move.w (Demo_button_index).w,d0 adda.w d0,a1 ; a1 now points to the current button press data move.b (a1),d0 ; load button press lea (Ctrl_1_Held).w,a0 move.b d0,d1 moveq #0,d2 ; this was modified from (a0) to #0 in Rev01 of Sonic 1 to nullify the following line eor.b d2,d0 ; does nothing now (used to let you hold a button to prevent Sonic from jumping in demos) move.b d1,(a0)+ ; save button press data from demo to Ctrl_1_Held and.b d1,d0 ; does nothing now move.b d0,(a0)+ ; save the same thing to Ctrl_1_Press subq.b #1,(Demo_press_counter).w ; decrement counter until next press bcc.s MoveDemo_On_P2 ; if it isn't 0 yet, branch move.b 3(a1),(Demo_press_counter).w ; reset counter to length of next press addq.w #2,(Demo_button_index).w ; advance to next button press ; loc_4908: MoveDemo_On_P2: if emerald_hill_zone_act_1<$100 ; will it fit within a byte? cmpi.b #emerald_hill_zone_act_1,(Current_Zone).w else cmpi.w #emerald_hill_zone_act_1,(Current_ZoneAndAct).w ; avoid a range overflow error endif bne.s MoveDemo_On_SkipP2 ; if it's not the EHZ demo, branch to skip player 2 lea (Demo_EHZ_Tails).l,a1 ; same as the corresponding remainder of MoveDemo_On_P1, but for player 2 move.w (Demo_button_index_2P).w,d0 adda.w d0,a1 move.b (a1),d0 lea (Ctrl_2_Held).w,a0 move.b d0,d1 moveq #0,d2 eor.b d2,d0 move.b d1,(a0)+ and.b d1,d0 move.b d0,(a0)+ subq.b #1,(Demo_press_counter_2P).w bcc.s + ; rts move.b 3(a1),(Demo_press_counter_2P).w addq.w #2,(Demo_button_index_2P).w + rts ; =========================================================================== ; loc_4940: MoveDemo_On_SkipP2: move.w #0,(Ctrl_2).w rts ; End of function MoveSonicInDemo ; =========================================================================== ; --------------------------------------------------------------------------- ; DEMO SCRIPT POINTERS ; Contains an array of pointers to the script controlling the players actions ; to use for each level. ; --------------------------------------------------------------------------- ; off_4948: DemoScriptPointers: zoneOrderedTable 4,1 zoneTableEntry.l Demo_EHZ ; $00 zoneTableEntry.l Demo_EHZ ; $01 zoneTableEntry.l Demo_EHZ ; $02 zoneTableEntry.l Demo_EHZ ; $03 zoneTableEntry.l Demo_EHZ ; $04 zoneTableEntry.l Demo_EHZ ; $05 zoneTableEntry.l Demo_EHZ ; $06 zoneTableEntry.l Demo_EHZ ; $07 zoneTableEntry.l Demo_EHZ ; $08 zoneTableEntry.l Demo_EHZ ; $09 zoneTableEntry.l Demo_EHZ ; $0A zoneTableEntry.l Demo_EHZ ; $0B zoneTableEntry.l Demo_CNZ ; $0C zoneTableEntry.l Demo_CPZ ; $0D zoneTableEntry.l Demo_EHZ ; $0E zoneTableEntry.l Demo_ARZ ; $0F zoneTableEntry.l Demo_EHZ ; $10 zoneTableEnd ; --------------------------------------------------------------------------- ; dword_498C: EndingDemoScriptPointers: ; these values are invalid addresses, but they were used for the ending ; demos, which aren't present in Sonic 2 dc.l $8B0837 dc.l $42085C ; 1 dc.l $6A085F ; 2 dc.l $2F082C ; 3 dc.l $210803 ; 4 dc.l $28300808 ; 5 dc.l $2E0815 ; 6 dc.l $F0846 ; 7 dc.l $1A08FF ; 8 dc.l $8CA0000 ; 9 dc.l 0 ; 10 dc.l 0 ; 11 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_49BC: LoadCollisionIndexes: moveq #0,d0 move.b (Current_Zone).w,d0 lsl.w #2,d0 move.l #Primary_Collision,(Collision_addr).w move.w d0,-(sp) movea.l Off_ColP(pc,d0.w),a0 lea (Primary_Collision).w,a1 bsr.w KosDec move.w (sp)+,d0 movea.l Off_ColS(pc,d0.w),a0 lea (Secondary_Collision).w,a1 bra.w KosDec ; End of function LoadCollisionIndexes ; =========================================================================== ; --------------------------------------------------------------------------- ; Pointers to primary collision indexes ; Contains an array of pointers to the primary collision index data for each ; level. 1 pointer for each level, pointing the primary collision index. ; --------------------------------------------------------------------------- Off_ColP: zoneOrderedTable 4,1 zoneTableEntry.l ColP_EHZHTZ zoneTableEntry.l ColP_Invalid ; 1 zoneTableEntry.l ColP_MTZ ; 2 zoneTableEntry.l ColP_Invalid ; 3 zoneTableEntry.l ColP_MTZ ; 4 zoneTableEntry.l ColP_MTZ ; 5 zoneTableEntry.l ColP_WFZSCZ ; 6 zoneTableEntry.l ColP_EHZHTZ ; 7 zoneTableEntry.l ColP_HPZ ; 8 zoneTableEntry.l ColP_Invalid ; 9 zoneTableEntry.l ColP_OOZ ; 10 zoneTableEntry.l ColP_MCZ ; 11 zoneTableEntry.l ColP_CNZ ; 12 zoneTableEntry.l ColP_CPZDEZ ; 13 zoneTableEntry.l ColP_CPZDEZ ; 14 zoneTableEntry.l ColP_ARZ ; 15 zoneTableEntry.l ColP_WFZSCZ ; 16 zoneTableEnd ; --------------------------------------------------------------------------- ; Pointers to secondary collision indexes ; Contains an array of pointers to the secondary collision index data for ; each level. 1 pointer for each level, pointing the secondary collision ; index. ; --------------------------------------------------------------------------- Off_ColS: zoneOrderedTable 4,1 zoneTableEntry.l ColS_EHZHTZ zoneTableEntry.l ColP_Invalid ; 1 zoneTableEntry.l ColP_MTZ ; 2 zoneTableEntry.l ColP_Invalid ; 3 zoneTableEntry.l ColP_MTZ ; 4 zoneTableEntry.l ColP_MTZ ; 5 zoneTableEntry.l ColS_WFZSCZ ; 6 zoneTableEntry.l ColS_EHZHTZ ; 7 zoneTableEntry.l ColS_HPZ ; 8 zoneTableEntry.l ColP_Invalid ; 9 zoneTableEntry.l ColP_OOZ ; 10 zoneTableEntry.l ColP_MCZ ; 11 zoneTableEntry.l ColS_CNZ ; 12 zoneTableEntry.l ColS_CPZDEZ ; 13 zoneTableEntry.l ColS_CPZDEZ ; 14 zoneTableEntry.l ColS_ARZ ; 15 zoneTableEntry.l ColS_WFZSCZ ; 16 zoneTableEnd ; --------------------------------------------------------------------------- ; Oscillating number subroutine ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_4A70: OscillateNumInit: lea (Oscillating_Numbers).w,a1 lea (Osc_Data).l,a2 moveq #bytesToWcnt(Osc_Data_End-Osc_Data),d1 ; loc_4A7C: Osc_Loop: move.w (a2)+,(a1)+ dbf d1,Osc_Loop rts ; End of function OscillateNumInit ; =========================================================================== ; word_4A84: Osc_Data: dc.w %0000000001111101 ; oscillation direction bitfield dc.w $80, 0 ; baseline values dc.w $80, 0 dc.w $80, 0 dc.w $80, 0 dc.w $80, 0 dc.w $80, 0 dc.w $80, 0 dc.w $80, 0 dc.w $80, 0 dc.w $3848, $EE dc.w $2080, $B4 dc.w $3080,$10E dc.w $5080,$1C2 dc.w $7080,$276 dc.w $80, 0 dc.w $4000, $FE Osc_Data_End: ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_4AC6: OscillateNumDo: tst.w (Two_player_mode).w bne.s + cmpi.b #6,(MainCharacter+routine).w bhs.s OscillateNumDo_Return + lea (Oscillating_Numbers).w,a1 lea (Osc_Data2).l,a2 move.w (a1)+,d3 moveq #bytesToLcnt(Osc_Data2_End-Osc_Data2),d1 - move.w (a2)+,d2 move.w (a2)+,d4 btst d1,d3 bne.s + move.w 2(a1),d0 add.w d2,d0 move.w d0,2(a1) _add.w d0,0(a1) _cmp.b 0(a1),d4 bhi.s ++ bset d1,d3 bra.s ++ ; =========================================================================== + move.w 2(a1),d0 sub.w d2,d0 move.w d0,2(a1) _add.w d0,0(a1) _cmp.b 0(a1),d4 bls.s + bclr d1,d3 + addq.w #4,a1 dbf d1,- move.w d3,(Oscillation_Control).w ; return_4B22: OscillateNumDo_Return: rts ; End of function OscillateNumDo ; =========================================================================== ; word_4B24: Osc_Data2: dc.w 2, $10 dc.w 2, $18 dc.w 2, $20 dc.w 2, $30 dc.w 4, $20 dc.w 8, 8 dc.w 8, $40 dc.w 4, $40 dc.w 2, $38 dc.w 2, $38 dc.w 2, $20 dc.w 3, $30 dc.w 5, $50 dc.w 7, $70 dc.w 2, $40 dc.w 2, $40 Osc_Data2_End: ; --------------------------------------------------------------------------- ; Subroutine to change global object animation variables (like rings) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_4B64: ChangeRingFrame: subq.b #1,(Logspike_anim_counter).w bpl.s + move.b #$B,(Logspike_anim_counter).w subq.b #1,(Logspike_anim_frame).w ; animate unused log spikes andi.b #7,(Logspike_anim_frame).w + subq.b #1,(Rings_anim_counter).w bpl.s + move.b #7,(Rings_anim_counter).w addq.b #1,(Rings_anim_frame).w ; animate rings in the level (obj25) andi.b #3,(Rings_anim_frame).w + subq.b #1,(Unknown_anim_counter).w bpl.s + move.b #7,(Unknown_anim_counter).w addq.b #1,(Unknown_anim_frame).w ; animate nothing (deleted special stage object is my best guess) cmpi.b #6,(Unknown_anim_frame).w blo.s + move.b #0,(Unknown_anim_frame).w + tst.b (Ring_spill_anim_counter).w beq.s + ; rts moveq #0,d0 move.b (Ring_spill_anim_counter).w,d0 add.w (Ring_spill_anim_accum).w,d0 move.w d0,(Ring_spill_anim_accum).w rol.w #7,d0 andi.w #3,d0 move.b d0,(Ring_spill_anim_frame).w ; animate scattered rings (obj37) subq.b #1,(Ring_spill_anim_counter).w + rts ; End of function ChangeRingFrame ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| nosignpost macro actid cmpi.w #actid,(Current_ZoneAndAct).w beq.ATTRIBUTE + ; rts endm ; sub_4BD2: SetLevelEndType: move.w #0,(Level_Has_Signpost).w ; set level type to non-signpost tst.w (Two_player_mode).w ; is it two-player competitive mode? bne.s LevelEnd_SetSignpost ; if yes, branch nosignpost.w emerald_hill_zone_act_2 nosignpost.w metropolis_zone_act_3 nosignpost.w wing_fortress_zone_act_1 nosignpost.w hill_top_zone_act_2 nosignpost.w oil_ocean_zone_act_2 nosignpost.s mystic_cave_zone_act_2 nosignpost.s casino_night_zone_act_2 nosignpost.s chemical_plant_zone_act_2 nosignpost.s death_egg_zone_act_1 nosignpost.s aquatic_ruin_zone_act_2 nosignpost.s sky_chase_zone_act_1 ; loc_4C40: LevelEnd_SetSignpost: move.w #1,(Level_Has_Signpost).w ; set level type to signpost + rts ; End of function SetLevelEndType ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_4C48: CheckLoadSignpostArt: tst.w (Level_Has_Signpost).w beq.s + ; rts tst.w (Debug_placement_mode).w bne.s + ; rts move.w (Camera_X_pos).w,d0 move.w (Camera_Max_X_pos).w,d1 subi.w #$100,d1 cmp.w d1,d0 blt.s SignpostUpdateTailsBounds tst.b (Update_HUD_timer).w beq.s SignpostUpdateTailsBounds cmp.w (Camera_Min_X_pos).w,d1 beq.s SignpostUpdateTailsBounds move.w d1,(Camera_Min_X_pos).w ; prevent camera from scrolling back to the left tst.w (Two_player_mode).w bne.s + ; rts moveq #PLCID_Signpost,d0 ; <== PLC_1F bra.w LoadPLC2 ; load signpost art ; --------------------------------------------------------------------------- ; loc_4C80: SignpostUpdateTailsBounds: tst.w (Two_player_mode).w beq.s + ; rts move.w (Camera_X_pos_P2).w,d0 move.w (Tails_Max_X_pos).w,d1 subi.w #$100,d1 cmp.w d1,d0 blt.s + ; rts tst.b (Update_HUD_timer_2P).w beq.s + ; rts cmp.w (Tails_Min_X_pos).w,d1 beq.s + ; rts move.w d1,(Tails_Min_X_pos).w ; prevent Tails from going past new left boundary + rts ; End of function CheckLoadSignpostArt ; =========================================================================== ; macro to simplify editing the demo scripts demoinput macro buttons,duration btns_mask := 0 idx := 0 rept strlen("buttons") btn := substr("buttons",idx,1) switch btn case "U" btns_mask := btns_mask|button_up_mask case "D" btns_mask := btns_mask|button_down_mask case "L" btns_mask := btns_mask|button_left_mask case "R" btns_mask := btns_mask|button_right_mask case "A" btns_mask := btns_mask|button_A_mask case "B" btns_mask := btns_mask|button_B_mask case "C" btns_mask := btns_mask|button_C_mask case "S" btns_mask := btns_mask|button_start_mask endcase idx := idx+1 endm dc.b btns_mask,duration-1 endm ; --------------------------------------------------------------------------- ; EHZ Demo Script (Sonic) ; --------------------------------------------------------------------------- ; byte_4CA8: Demo_Def: Demo_EHZ: demoinput , $4C demoinput R, $43 demoinput RC, 9 demoinput R, $3F demoinput RC, 6 demoinput R, $B0 demoinput RC, $A demoinput R, $46 demoinput , $1E demoinput L, $F demoinput , 5 demoinput L, 5 demoinput , 9 demoinput L, $3F demoinput , 5 demoinput R, $67 demoinput , $62 demoinput R, $12 demoinput , $22 demoinput D, 8 demoinput DC, 7 demoinput D, $E demoinput , $3C demoinput R, $A demoinput , $1E demoinput D, 7 demoinput DC, 7 demoinput D, 2 demoinput , $F demoinput R, $100 demoinput R, $2F demoinput , $23 demoinput C, 8 demoinput RC, $10 demoinput R, 3 demoinput , $30 demoinput RC, $24 demoinput R, $BE demoinput , $C demoinput L, $14 demoinput , $17 demoinput D, 3 demoinput DC, 7 demoinput D, 3 demoinput , $64 demoinput S, 1 demoinput A, 1 demoinput , 1 ; --------------------------------------------------------------------------- ; EHZ Demo Script (Tails) ; --------------------------------------------------------------------------- ; byte_4D08: Demo_EHZ_Tails: demoinput , $3C demoinput R, $10 demoinput UR, $44 demoinput URC, $7 demoinput UR, $7 demoinput R, $CA demoinput , $12 demoinput R, $2 demoinput RC, $9 demoinput R, $53 demoinput , $12 demoinput R, $B demoinput RC, $F demoinput R, $24 demoinput , $B demoinput C, $5 demoinput , $E demoinput R, $56 demoinput , $1F demoinput R, $5B demoinput , $11 demoinput R, $100 demoinput R, $C1 demoinput , $21 demoinput L, $E demoinput , $E demoinput C, $5 demoinput RC, $10 demoinput C, $6 demoinput , $D demoinput L, $6 demoinput , $5F demoinput R, $74 demoinput , $19 demoinput L, $45 demoinput , $9 demoinput D, $31 demoinput , $9 demoinput R, $E demoinput , $24 demoinput R, $28 demoinput , $5 demoinput R, $1 demoinput , $1 demoinput , $1 demoinput , $1 demoinput , $1 demoinput , $1 ; --------------------------------------------------------------------------- ; CNZ Demo Script ; --------------------------------------------------------------------------- Demo_CNZ: demoinput , $49 demoinput R, $11 demoinput UR, 1 demoinput R, 2 demoinput UR, 7 demoinput R, $61 demoinput RC, 6 demoinput C, 2 demoinput , 9 demoinput L, 3 demoinput DL, 4 demoinput L, 2 demoinput , $1A demoinput R, $12 demoinput RC, $1A demoinput C, 5 demoinput RC, $24 demoinput R, $1B demoinput , 8 demoinput L, $11 demoinput , $F demoinput R, $78 demoinput RC, $17 demoinput C, 1 demoinput , $10 demoinput L, $12 demoinput , 8 demoinput R, $53 demoinput , $70 demoinput R, $75 demoinput , $38 demoinput R, $17 demoinput , 5 demoinput L, $27 demoinput , $D demoinput L, $13 demoinput , $6A demoinput C, $11 demoinput RC, 3 demoinput DRC, 6 demoinput DR, $15 demoinput R, 6 demoinput , 6 demoinput L, $D demoinput , $49 demoinput L, $A demoinput , $1F demoinput R, 7 demoinput , $30 demoinput L, 2 demoinput , $100 demoinput , $50 demoinput R, 1 demoinput RC, $C demoinput R, $2B demoinput , $5F ; --------------------------------------------------------------------------- ; CPZ Demo Script ; --------------------------------------------------------------------------- Demo_CPZ: demoinput , $47 demoinput R, $1C demoinput RC, 8 demoinput R, $A demoinput , $1C demoinput R, $E demoinput RC, $29 demoinput R, $100 demoinput R, $E8 demoinput DR, 5 demoinput D, 2 demoinput L, $34 demoinput DL, $68 demoinput L, 1 demoinput , $16 demoinput C, 1 demoinput LC, 8 demoinput L, $F demoinput , $18 demoinput R, 2 demoinput DR, 2 demoinput R, $D demoinput , $20 demoinput RC, 7 demoinput R, $B demoinput , $1C demoinput L, $E demoinput , $1D demoinput L, 7 demoinput , $100 demoinput , $E0 demoinput R, $F demoinput , $1D demoinput L, 3 demoinput , $26 demoinput R, 7 demoinput , 7 demoinput C, 5 demoinput , $29 demoinput L, $12 demoinput , $18 demoinput R, $1A demoinput , $11 demoinput L, $2E demoinput , $14 demoinput S, 1 demoinput A, 1 demoinput , 1 ; --------------------------------------------------------------------------- ; ARZ Demo Script ; --------------------------------------------------------------------------- Demo_ARZ: demoinput , $43 demoinput R, $4B demoinput RC, 9 demoinput R, $50 demoinput RC, $C demoinput R, 6 demoinput , $1B demoinput R, $61 demoinput RC, $15 demoinput R, $55 demoinput , $41 demoinput R, 5 demoinput UR, 1 demoinput R, $5C demoinput , $47 demoinput R, $3C demoinput RC, 9 demoinput R, $28 demoinput , $B demoinput R, $93 demoinput RC, $33 demoinput R, $23 demoinput , $23 demoinput R, $4D demoinput , $1F demoinput L, 2 demoinput UL, 3 demoinput L, 1 demoinput , $B demoinput L, $D demoinput , $11 demoinput R, 6 demoinput , $62 demoinput R, 4 demoinput RC, 6 demoinput R, $17 demoinput , $1C demoinput R, $57 demoinput RC, $B demoinput R, $17 demoinput , $16 demoinput R, $D demoinput , $2C demoinput C, 2 demoinput RC, $1B demoinput R, $83 demoinput , $C demoinput S, 1 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_4E98: LoadZoneTiles: moveq #0,d0 move.b (Current_Zone).w,d0 add.w d0,d0 add.w d0,d0 move.w d0,d1 add.w d0,d0 add.w d1,d0 lea (LevelArtPointers).l,a2 lea (a2,d0.w),a2 move.l (a2)+,d0 andi.l #$FFFFFF,d0 ; 8x8 tile pointer movea.l d0,a0 lea (Chunk_Table).l,a1 bsr.w KosDec move.w a1,d3 cmpi.b #hill_top_zone,(Current_Zone).w bne.s + lea (ArtKos_HTZ).l,a0 lea (Chunk_Table+tiles_to_bytes(ArtTile_ArtKos_NumTiles_HTZ_Main)).l,a1 bsr.w KosDec ; patch for HTZ move.w #tiles_to_bytes(ArtTile_ArtKos_NumTiles_HTZ),d3 + cmpi.b #wing_fortress_zone,(Current_Zone).w bne.s + lea (ArtKos_WFZ).l,a0 lea (Chunk_Table+tiles_to_bytes(ArtTile_ArtKos_NumTiles_WFZ_Main)).l,a1 bsr.w KosDec ; patch for WFZ move.w #tiles_to_bytes(ArtTile_ArtKos_NumTiles_WFZ),d3 + cmpi.b #death_egg_zone,(Current_Zone).w bne.s + move.w #tiles_to_bytes(ArtTile_ArtKos_NumTiles_DEZ),d3 + move.w d3,d7 andi.w #$FFF,d3 lsr.w #1,d3 rol.w #4,d7 andi.w #$F,d7 - move.w d7,d2 lsl.w #7,d2 lsl.w #5,d2 move.l #$FFFFFF,d1 move.w d2,d1 jsr (QueueDMATransfer).l move.w d7,-(sp) move.b #VintID_TitleCard,(Vint_routine).w bsr.w WaitForVint bsr.w RunPLC_RAM move.w (sp)+,d7 move.w #$800,d3 dbf d7,- rts ; End of function LoadZoneTiles ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo_loadZoneBlockMaps jmp (loadZoneBlockMaps).l JmpTo_DeformBgLayer jmp (DeformBgLayer).l JmpTo_AniArt_Load jmp (AniArt_Load).l JmpTo_DrawInitialBG jmp (DrawInitialBG).l align 4 endif ; =========================================================================== ; loc_4F64: SpecialStage: cmpi.b #7,(Current_Special_Stage).w blo.s + move.b #0,(Current_Special_Stage).w + move.w #SndID_SpecStageEntry,d0 ; play that funky special stage entry sound bsr.w PlaySound move.b #MusID_FadeOut,d0 ; fade out the music bsr.w PlayMusic bsr.w Pal_FadeToWhite tst.w (Two_player_mode).w beq.s + move.w #0,(Two_player_mode).w st.b (SS_2p_Flag).w ; set to -1 bra.s ++ ; =========================================================================== + sf.b (SS_2p_Flag).w ; set to 0 ; (!) + move #$2700,sr ; Mask all interrupts lea (VDP_control_port).l,a6 move.w #$8B03,(a6) ; EXT-INT disabled, V scroll by screen, H scroll by line move.w #$8004,(a6) ; H-INT disabled move.w #$8ADF,(Hint_counter_reserve).w ; H-INT every 224th scanline move.w #$8200|(VRAM_SS_Plane_A_Name_Table1/$400),(a6) ; PNT A base: $C000 move.w #$8400|(VRAM_SS_Plane_B_Name_Table/$2000),(a6) ; PNT B base: $A000 move.w #$8C08,(a6) ; H res 32 cells, no interlace, S/H enabled move.w #$9003,(a6) ; Scroll table size: 128x32 move.w #$8700,(a6) ; Background palette/color: 0/0 move.w #$8D00|(VRAM_SS_Horiz_Scroll_Table/$400),(a6) ; H scroll table base: $FC00 move.w #$8500|(VRAM_SS_Sprite_Attribute_Table/$200),(a6) ; Sprite attribute table base: $F800 move.w (VDP_Reg1_val).w,d0 andi.b #$BF,d0 move.w d0,(VDP_control_port).l ; /------------------------------------------------------------------------\ ; | We're gonna zero-fill a bunch of VRAM regions. This was done by macro, | ; | so there's gonna be a lot of wasted cycles. | ; \------------------------------------------------------------------------/ dmaFillVRAM 0,VRAM_SS_Plane_A_Name_Table2,VRAM_SS_Plane_Table_Size ; clear Plane A pattern name table 1 dmaFillVRAM 0,VRAM_SS_Plane_A_Name_Table1,VRAM_SS_Plane_Table_Size ; clear Plane A pattern name table 2 dmaFillVRAM 0,VRAM_SS_Plane_B_Name_Table,VRAM_SS_Plane_Table_Size ; clear Plane B pattern name table dmaFillVRAM 0,VRAM_SS_Horiz_Scroll_Table,VRAM_SS_Horiz_Scroll_Table_Size ; clear Horizontal scroll table clr.l (Vscroll_Factor).w clr.l (unk_F61A).w clr.b (SpecialStage_Started).w ; /------------------------------------------------------------------------\ ; | Now we clear out some regions in main RAM where we want to store some | ; | of our data structures. | ; \------------------------------------------------------------------------/ ; Bug: These '+4's shouldn't be here; clearRAM accidentally clears an additional 4 bytes clearRAM SS_Sprite_Table,SS_Sprite_Table_End+4 clearRAM SS_Horiz_Scroll_Buf_1,SS_Horiz_Scroll_Buf_1_End+4 clearRAM SS_Misc_Variables,SS_Misc_Variables_End+4 clearRAM SS_Sprite_Table_Input,SS_Sprite_Table_Input_End clearRAM SS_Object_RAM,SS_Object_RAM_End move #$2300,sr lea (VDP_control_port).l,a6 move.w #$8F02,(a6) ; VRAM pointer increment: $0002 bsr.w ssInitTableBuffers bsr.w ssLdComprsdData move.w #0,(SpecialStage_CurrentSegment).w moveq #PLCID_SpecialStage,d0 bsr.w RunPLC_ROM clr.b (Level_started_flag).w move.l #0,(Camera_X_pos).w ; probably means something else in this context move.l #0,(Camera_Y_pos).w move.l #0,(Camera_X_pos_copy).w move.l #0,(Camera_Y_pos_copy).w cmpi.w #1,(Player_mode).w ; is this a Tails alone game? bgt.s + ; if yes, branch move.b #ObjID_SonicSS,(MainCharacter+id).w ; load Obj09 (special stage Sonic) tst.w (Player_mode).w ; is this a Sonic and Tails game? bne.s ++ ; if not, branch + move.b #ObjID_TailsSS,(Sidekick+id).w ; load Obj10 (special stage Tails) + move.b #ObjID_SSHUD,(SpecialStageHUD+id).w ; load Obj5E (special stage HUD) move.b #ObjID_StartBanner,(SpecialStageStartBanner+id).w ; load Obj5F (special stage banner) move.b #ObjID_SSNumberOfRings,(SpecialStageNumberOfRings+id).w ; load Obj87 (special stage ring count) move.w #$80,(SS_Offset_X).w move.w #$36,(SS_Offset_Y).w bsr.w SSPlaneB_Background bsr.w SSDecompressPlayerArt bsr.w SSInitPalAndData move.l #$C0000,(SS_New_Speed_Factor).w clr.w (Ctrl_1_Logical).w clr.w (Ctrl_2_Logical).w - move.b #VintID_S2SS,(Vint_routine).w bsr.w WaitForVint move.b (SSTrack_drawing_index).w,d0 bne.s - bsr.w SSTrack_Draw - move.b #VintID_S2SS,(Vint_routine).w bsr.w WaitForVint bsr.w SSTrack_Draw bsr.w SSLoadCurrentPerspective bsr.w SSObjectsManager move.b (SSTrack_duration_timer).w,d0 subq.w #1,d0 bne.s - jsr (Obj5A_CreateRingsToGoText).l bsr.w SS_ScrollBG jsr (RunObjects).l jsr (BuildSprites).l bsr.w RunPLC_RAM move.b #VintID_CtrlDMA,(Vint_routine).w bsr.w WaitForVint move.w #MusID_SpecStage,d0 bsr.w PlayMusic move.w (VDP_Reg1_val).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l bsr.w Pal_FadeFromWhite - bsr.w PauseGame move.w (Ctrl_1).w,(Ctrl_1_Logical).w move.w (Ctrl_2).w,(Ctrl_2_Logical).w cmpi.b #GameModeID_SpecialStage,(Game_Mode).w ; special stage mode? bne.w SpecialStage_Unpause ; if not, branch move.b #VintID_S2SS,(Vint_routine).w bsr.w WaitForVint bsr.w SSTrack_Draw bsr.w SSSetGeometryOffsets bsr.w SSLoadCurrentPerspective bsr.w SSObjectsManager bsr.w SS_ScrollBG jsr (RunObjects).l jsr (BuildSprites).l bsr.w RunPLC_RAM tst.b (SpecialStage_Started).w beq.s - moveq #PLCID_SpecStageBombs,d0 bsr.w LoadPLC - bsr.w PauseGame cmpi.b #GameModeID_SpecialStage,(Game_Mode).w ; special stage mode? bne.w SpecialStage_Unpause ; if not, branch move.b #VintID_S2SS,(Vint_routine).w bsr.w WaitForVint bsr.w SSTrack_Draw bsr.w SSSetGeometryOffsets bsr.w SSLoadCurrentPerspective bsr.w SSObjectsManager bsr.w SS_ScrollBG bsr.w PalCycle_SS tst.b (SS_Pause_Only_flag).w beq.s + move.w (Ctrl_1).w,d0 andi.w #(button_start_mask<<8)|button_start_mask,d0 move.w d0,(Ctrl_1_Logical).w move.w (Ctrl_2).w,d0 andi.w #(button_start_mask<<8)|button_start_mask,d0 move.w d0,(Ctrl_2_Logical).w bra.s ++ ; =========================================================================== + move.w (Ctrl_1).w,(Ctrl_1_Logical).w move.w (Ctrl_2).w,(Ctrl_2_Logical).w + jsr (RunObjects).l tst.b (SS_Check_Rings_flag).w bne.s + jsr (BuildSprites).l bsr.w RunPLC_RAM bra.s - ; =========================================================================== + andi.b #7,(Emerald_count).w tst.b (SS_2p_Flag).w beq.s + lea (SS2p_RingBuffer).w,a0 move.w (a0)+,d0 add.w (a0)+,d0 add.w (a0)+,d0 add.w (a0)+,d0 add.w (a0)+,d0 add.w (a0)+,d0 bra.s ++ ; =========================================================================== + move.w (Ring_count).w,d0 add.w (Ring_count_2P).w,d0 + cmp.w (SS_Perfect_rings_left).w,d0 bne.s + st.b (Perfect_rings_flag).w + bsr.w Pal_FadeToWhite tst.w (Two_player_mode_copy).w bne.w loc_540C move #$2700,sr lea (VDP_control_port).l,a6 move.w #$8200|(VRAM_Menu_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000 move.w #$8400|(VRAM_Menu_Plane_B_Name_Table/$2000),(a6) ; PNT B base: $E000 move.w #$9001,(a6) ; Scroll table size: 64x32 move.w #$8C81,(a6) ; H res 40 cells, no interlace, S/H disabled bsr.w ClearScreen jsrto (Hud_Base).l, JmpTo_Hud_Base clr.w (VDP_Command_Buffer).w move.l #VDP_Command_Buffer,(VDP_Command_Buffer_Slot).w move #$2300,sr moveq #PalID_Result,d0 bsr.w PalLoad_Now moveq #PLCID_Std1,d0 bsr.w LoadPLC2 move.l #vdpComm(tiles_to_bytes(ArtTile_VRAM_Start+2),VRAM,WRITE),d0 lea SpecialStage_ResultsLetters(pc),a0 jsrto (LoadTitleCardSS).l, JmpTo_LoadTitleCardSS move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_SpecialStageResults),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_SpecialStageResults).l,a0 bsr.w NemDec move.w (Player_mode).w,d0 beq.s ++ subq.w #1,d0 beq.s + clr.w (Ring_count).w bra.s ++ ; =========================================================================== + clr.w (Ring_count_2P).w + move.w (Ring_count).w,(Bonus_Countdown_1).w move.w (Ring_count_2P).w,(Bonus_Countdown_2).w clr.w (Total_Bonus_Countdown).w tst.b (Got_Emerald).w beq.s + move.w #1000,(Total_Bonus_Countdown).w + move.b #1,(Update_HUD_score).w move.b #1,(Update_Bonus_score).w move.w #MusID_EndLevel,d0 jsr (PlaySound).l clearRAM SS_Sprite_Table_Input,SS_Sprite_Table_Input_End clearRAM SS_Object_RAM,SS_Object_RAM_End move.b #ObjID_SSResults,(SpecialStageResults+id).w ; load Obj6F (special stage results) at $FFFFB800 - move.b #VintID_Level,(Vint_routine).w bsr.w WaitForVint jsr (RunObjects).l jsr (BuildSprites).l bsr.w RunPLC_RAM tst.w (Level_Inactive_flag).w beq.s - tst.l (Plc_Buffer).w bne.s - move.w #SndID_SpecStageEntry,d0 bsr.w PlaySound bsr.w Pal_FadeToWhite tst.w (Two_player_mode_copy).w bne.s loc_540C move.b #GameModeID_Level,(Game_Mode).w ; => Level (Zone play mode) rts ; =========================================================================== loc_540C: move.w #VsRSID_SS,(Results_Screen_2P).w move.b #GameModeID_2PResults,(Game_Mode).w ; => TwoPlayerResults rts ; =========================================================================== ; loc_541A: SpecialStage_Unpause: move.b #MusID_Unpause,(Music_to_play).w move.b #VintID_Level,(Vint_routine).w bra.w WaitForVint ; =========================================================================== ; --------------------------------------------------------------------------- ; Animated color of the twinkling stars in the special stage background ; --------------------------------------------------------------------------- ; loc_542A: Pal_UNK8: Pal_SpecialStageStars: dc.w $EEE, $CCC, $AAA, $888, $888, $AAA, $CCC, $EEE ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_543A PalCycle_SS: move.b (Vint_runcount+3).w,d0 andi.b #3,d0 bne.s + move.b (SS_Star_color_1).w,d0 addi_.b #1,(SS_Star_color_1).w andi.w #7,d0 add.w d0,d0 move.w Pal_SpecialStageStars(pc,d0.w),(Normal_palette+$1C).w move.b (SS_Star_color_2).w,d0 addi_.b #1,(SS_Star_color_2).w andi.w #7,d0 add.w d0,d0 move.w Pal_SpecialStageStars(pc,d0.w),(Normal_palette+$1E).w + cmpi.b #6,(Current_Special_Stage).w bne.s + cmpi.b #3,(Current_Special_Act).w beq.w SSCheckpoint_rainbow / tst.b (SS_Checkpoint_Rainbow_flag).w beq.s + ; rts move.b (Vint_runcount+3).w,d0 andi.b #7,d0 bne.s + ; rts move.b (SS_Rainbow_palette).w,d0 addi_.b #1,(SS_Rainbow_palette).w andi.b #3,d0 add.w d0,d0 move.w d0,d1 add.w d0,d0 add.w d1,d0 move.w word_54C4(pc,d0.w),(Normal_palette_line4+$16).w move.w word_54C6(pc,d0.w),(Normal_palette_line4+$18).w move.w word_54C8(pc,d0.w),(Normal_palette_line4+$1A).w + rts ; =========================================================================== ; special stage rainbow blinking sprite palettes... (chaos emerald colors?) ;word_54BC: dc.w $0EE, $0C0, $0EE, $0C0 word_54C4: dc.w $0EE word_54C6: dc.w $0CC word_54C8: dc.w $088, $0E0, $0C0, $080, $EE0, $CC0, $880, $E0E, $C0C, $808 ; =========================================================================== ;loc_54DC SSCheckpoint_rainbow: tst.b (SS_Pause_Only_flag).w beq.s - moveq #0,d0 move.b (Vint_runcount+3).w,d0 andi.b #1,d0 bne.w - move.w (Ring_count).w,d2 add.w (Ring_count_2P).w,d2 cmp.w (SS_Ring_Requirement).w,d2 blt.w - lea (Normal_palette+2).w,a0 movea.l a0,a1 move.w (a0)+,d0 moveq #$B,d1 - move.w (a0)+,(a1)+ dbf d1,- move.w d0,(a1) rts ; End of function PalCycle_SS ;|||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_5514 SSLoadCurrentPerspective: cmpi.b #4,(SSTrack_drawing_index).w bne.s + ; rts movea.l #SSRAM_MiscKoz_SpecialPerspective,a0 moveq #0,d0 move.b (SSTrack_mapping_frame).w,d0 add.w d0,d0 adda.w (a0,d0.w),a0 move.l a0,(SS_CurrentPerspective).w + rts ; End of function SSLoadCurrentPerspective ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_5534 SSObjectsManager: cmpi.b #4,(SSTrack_drawing_index).w bne.w return_55DC moveq #0,d0 move.b (SpecialStage_CurrentSegment).w,d0 cmp.b (SpecialStage_LastSegment2).w,d0 beq.w return_55DC move.b d0,(SpecialStage_LastSegment2).w movea.l (SS_CurrentLevelLayout).w,a1 move.b (a1,d0.w),d3 andi.w #$7F,d3 lea (Ani_SSTrack_Len).l,a0 move.b (a0,d3.w),d3 add.w d3,d3 add.w d3,d3 movea.l (SS_CurrentLevelObjectLocations).w,a0 - bsr.w SSSingleObjLoad bne.s return_55DC moveq #0,d0 move.b (a0)+,d0 bmi.s ++ move.b d0,d1 andi.b #$40,d1 bne.s + addq.w #1,(SS_Perfect_rings_left).w move.b #ObjID_SSRing,id(a1) add.w d0,d0 add.w d0,d0 add.w d3,d0 move.w d0,objoff_30(a1) move.b (a0)+,angle(a1) bra.s - ; =========================================================================== + andi.w #$3F,d0 move.b #ObjID_SSBomb,id(a1) add.w d0,d0 add.w d0,d0 add.w d3,d0 move.w d0,objoff_30(a1) move.b (a0)+,angle(a1) bra.s - ; =========================================================================== + move.l a0,(SS_CurrentLevelObjectLocations).w addq.b #1,d0 beq.s return_55DC addq.b #1,d0 beq.s ++ addq.b #1,d0 beq.s + st.b (SS_NoCheckpoint_flag).w sf.b (SS_NoCheckpointMsg_flag).w bra.s ++ ; =========================================================================== + tst.b (SS_2p_Flag).w bne.s + move.b #ObjID_SSEmerald,id(a1) rts ; =========================================================================== + move.b #ObjID_SSMessage,id(a1) return_55DC: rts ; End of function SSObjectsManager ; =========================================================================== SSTrackPNTCommands: dc.l vdpComm(VRAM_SS_Plane_A_Name_Table2 + 0 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE) dc.l vdpComm(VRAM_SS_Plane_A_Name_Table2 + 1 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE) dc.l vdpComm(VRAM_SS_Plane_A_Name_Table2 + 2 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE) dc.l vdpComm(VRAM_SS_Plane_A_Name_Table2 + 3 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE) dc.l vdpComm(VRAM_SS_Plane_A_Name_Table1 + 0 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE) dc.l vdpComm(VRAM_SS_Plane_A_Name_Table1 + 1 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE) dc.l vdpComm(VRAM_SS_Plane_A_Name_Table1 + 2 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE) dc.l vdpComm(VRAM_SS_Plane_A_Name_Table1 + 3 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE) Ani_SSTrack_Len: dc.b SSTrackAni_TurnThenRise_End - SSTrackAni_TurnThenRise ; 0 dc.b SSTrackAni_TurnThenDrop_End - SSTrackAni_TurnThenDrop ; 1 dc.b SSTrackAni_TurnThenStraight_End - SSTrackAni_TurnThenStraight ; 2 dc.b SSTrackAni_Straight_End - SSTrackAni_Straight ; 3 dc.b SSTrackAni_StraightThenTurn_End - SSTrackAni_StraightThenTurn ; 4 dc.b 0 ; 5 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_5604 SSTrack_Draw: moveq #0,d0 move.b (SSTrack_drawing_index).w,d0 ; Get drawing position cmpi.b #4,d0 ; Is it time to draw a new frame? bge.w SSTrackSetOrientation ; Branch if not add.w d0,d0 ; Multiply by 4 add.w d0,d0 bne.w SSTrack_BeginDraw ; Branch if we don't need to start a new segment move.l (SSTrack_last_mappings).w,(SSTrack_last_mappings_copy).w ; Save last mappings move.b (SSTrack_mapping_frame).w,(SSTrack_last_mapping_frame).w ; Save last frame moveq #0,d1 moveq #0,d2 moveq #0,d3 moveq #0,d4 move.b (SpecialStage_CurrentSegment).w,d1 ; Get current segment ID move.b (SSTrack_anim_frame).w,d2 ; Get current frame movea.l (SS_CurrentLevelLayout).w,a1 ; Pointer to level layout move.b (a1,d1.w),d3 ; Get segment geometry type andi.b #$7F,d3 ; Strip flip flag move.b d3,(SSTrack_anim).w ; Set this as new animation move.w d3,d1 ; Copy to d1 add.w d3,d3 ; Turn it into an index lea (Ani_SpecialStageTrack).l,a1 ; Animation table adda.w (a1,d3.w),a1 ; Add offset so a1 points to animation data adda.w d2,a1 ; Offset into current animation frame moveq #0,d4 move.b (a1),d4 ; d4 = animation frame to draw move.b d4,(SSTrack_mapping_frame).w ; Save to RAM lsl.w #2,d4 lea (Map_SpecialStageTrack).l,a1 ; Mappings table movea.l (a1,d4.w),a0 ; a0 = pointer to mappings for current track frame movea.l a0,a1 ; Copy to a1 moveq #0,d2 move.b (a0)+,d2 ; Skip the first 2 bytes move.b (a0)+,d2 ; Why not 'addq.l #2,a0'? move.b (a0)+,d2 ; Get byte lsl.w #8,d2 ; Shift it up to be the high byte of a word move.b (a0)+,d2 ; Read another byte; why not 'move.w (a0)+,d2'? addq.w #4,d2 ; Add 4 adda.w d2,a1 ; Use as offset from start of file movea.l a1,a2 ; Save to a2 moveq #0,d2 move.b (a1)+,d2 ; Skip the first 2 bytes move.b (a1)+,d2 ; Why not 'addq.l #2,a1'? move.b (a1)+,d2 ; Get byte lsl.w #8,d2 ; Shift it up to be the high byte of a word move.b (a1)+,d2 ; Read another byte; why not 'move.w (a1)+,d2'? addq.w #4,d2 ; Add 4 adda.w d2,a2 ; Use as offset from previous offset move.b (a2)+,d2 ; Ignore the first 3 bytes move.b (a2)+,d2 ; Why not 'addq.l #3,a2'? move.b (a2)+,d2 move.b (a2)+,d2 ; Get byte (unused) move.l a0,(SSTrack_mappings_bitflags).w ; Save pointer to bit flags mappings move.l a0,(SSTrack_last_mappings).w ; ... twice move.l a1,(SSTrack_mappings_uncompressed).w ; Save pointer to uncompressed mappings move.l a2,(SSTrack_mappings_RLE).w ; Save pointer to RLE mappings lea_ Ani_SSTrack_Len,a4 ; Pointer to animation lengths move.b (a4,d1.w),d2 ; Get length of current animation move.b (SSTrack_anim_frame).w,(SSTrack_last_anim_frame).w ; Save old frame addi_.b #1,(SSTrack_anim_frame).w ; Increment current frame cmp.b (SSTrack_anim_frame).w,d2 ; Compare with animation length bne.s SSTrack_BeginDraw ; If not equal, branch move.b #0,(SSTrack_anim_frame).w ; Reset to start move.b (SpecialStage_CurrentSegment).w,(SpecialStage_LastSegment).w ; Save old segment addi_.b #1,(SpecialStage_CurrentSegment).w ; Increment current segment ;loc_56D2 SSTrack_BeginDraw: tst.b (SS_Alternate_PNT).w ; Are we using the alternate PNT? beq.s + ; Branch if not addi.w #$10,d0 ; Change where we will be drawing + lea_ SSTrackPNTCommands,a3 ; Table of VRAM commands movea.l (a3,d0.w),a3 ; Get command to set destination in VRAM for current frame move.l a3,(VDP_control_port).l ; Send it to VDP lea (VDP_data_port).l,a6 bsr.w SSTrackSetOrientation ; Set oriantation flags movea.l (SSTrack_mappings_bitflags).w,a0 ; Get pointer to bit flags mappings movea.l (SSTrack_mappings_uncompressed).w,a1 ; Get pointer to uncompressed mappings movea.l (SSTrack_mappings_RLE).w,a2 ; Get pointer to RLE mappings lea (SSDrawRegBuffer).w,a3 ; Pointer to register buffer from last draw movem.w (a3)+,d2-d7 ; Restore registers from previous call (or set them to zero) lea (SSPNT_UncLUT).l,a3 ; Pattern name list for drawing routines lea (SSPNT_RLELUT).l,a4 ; RLE-encoded pattern name list for drawing routines movea.w #-8,a5 ; Initialize loop counter: draws 7 lines moveq #0,d0 tst.b (SSTrack_Orientation).w ; Is the current segment flipped? bne.w SSTrackDrawLineFlipLoop ; Branch if yes ;loc_5722 SSTrackDrawLineLoop: adda_.w #1,a5 ; Increment loop counter cmpa.w #0,a5 ; Have all 7 lines been drawn? beq.w SSTrackDraw_return ; If yes, return ;loc_572E SSTrackDrawLoop_Inner: moveq #0,d1 subq.w #1,d7 ; Subtract 1 from bit counter bpl.s + ; Branch if we still have bits we can use move.b (a0)+,d6 ; Get a new byte from bit flags moveq #7,d7 ; We now have 8 fresh new bits + add.b d6,d6 ; Do we have to use RLE compression? bcc.s SSTrackDrawRLE ; Branch if yes subq.b #1,d5 ; Subtract 1 from bit counter bpl.s + ; Branch if we still have bits we can use move.b (a1)+,d4 ; Get a new byte from uncompressed mappings pointer moveq #7,d5 ; We now have 8 fresh new bits + add.b d4,d4 ; Do we need a 10-bit index? bcc.s + ; Branch if not moveq #$A,d0 ; d0 = 10 bits sub.b d5,d0 ; d0 = 10 - d5 subq.b #3,d0 ; d0 = 7 - d5; why not shorten it to 'moveq #7,d0 \n sub.b d5,d0'? add.w d0,d0 ; Convert into table index move.w SSTrackDrawUnc_Read10LUT(pc,d0.w),d0 jmp SSTrackDrawUnc_Read10LUT(pc,d0.w) ; =========================================================================== ;off_5758 SSTrackDrawUnc_Read10LUT: offsetTable offsetTableEntry.w SSTrackDrawUnc_Read10_Got7 ; 0 offsetTableEntry.w SSTrackDrawUnc_Read10_Got6 ; 1 offsetTableEntry.w SSTrackDrawUnc_Read10_Got5 ; 2 offsetTableEntry.w SSTrackDrawUnc_Read10_Got4 ; 3 offsetTableEntry.w SSTrackDrawUnc_Read10_Got3 ; 4 offsetTableEntry.w SSTrackDrawUnc_Read10_Got2 ; 5 offsetTableEntry.w SSTrackDrawUnc_Read10_Got1 ; 6 offsetTableEntry.w SSTrackDrawUnc_Read10_Got0 ; 7 ; =========================================================================== + moveq #6,d0 ; d0 = 6 sub.b d5,d0 ; d0 = 6 - d5 addq.b #1,d0 ; d0 = 7 - d5; why not shorten it to 'moveq #7,d0 \n sub.b d5,d0'? add.w d0,d0 ; Convert into table index move.w SSTrackDrawUnc_Read6LUT(pc,d0.w),d0 jmp SSTrackDrawUnc_Read6LUT(pc,d0.w) ; =========================================================================== ;off_5778 SSTrackDrawUnc_Read6LUT: offsetTable offsetTableEntry.w SSTrackDrawUnc_Read6_Got7 ; 0 offsetTableEntry.w SSTrackDrawUnc_Read6_Got6 ; 1 offsetTableEntry.w SSTrackDrawUnc_Read6_Got5 ; 2 offsetTableEntry.w SSTrackDrawUnc_Read6_Got4 ; 3 offsetTableEntry.w SSTrackDrawUnc_Read6_Got3 ; 4 offsetTableEntry.w SSTrackDrawUnc_Read6_Got2 ; 5 offsetTableEntry.w SSTrackDrawUnc_Read6_Got1 ; 6 offsetTableEntry.w SSTrackDrawUnc_Read6_Got0 ; 7 ; =========================================================================== SSTrackDrawRLE: subq.b #1,d3 ; Subtract 1 from bit counter bpl.s ++ ; Branch if we still have bits we can use move.b (a2)+,d2 ; Get a new byte from RLE mappings pointer cmpi.b #-1,d2 ; Is d2 equal to -1? bne.s + ; Branch if not moveq #0,d3 ; Set bit counter to zero bra.w SSTrackDrawLineLoop ; =========================================================================== + moveq #7,d3 ; We now have 8 fresh new bits + add.b d2,d2 ; Do we need a 7-bit index? bcc.s + ; Branch if not moveq #7,d0 ; d0 = 7 sub.b d3,d0 ; d0 = 10 - d3 add.b d0,d0 ; Convert into table index move.w SSTrackDrawRLE_Read7LUT(pc,d0.w),d0 jmp SSTrackDrawRLE_Read7LUT(pc,d0.w) ; =========================================================================== ;off_57AE SSTrackDrawRLE_Read7LUT: offsetTable offsetTableEntry.w SSTrackDrawRLE_Read7_Got7 ; 0 offsetTableEntry.w SSTrackDrawRLE_Read7_Got6 ; 1 offsetTableEntry.w SSTrackDrawRLE_Read7_Got5 ; 2 offsetTableEntry.w SSTrackDrawRLE_Read7_Got4 ; 3 offsetTableEntry.w SSTrackDrawRLE_Read7_Got3 ; 4 offsetTableEntry.w SSTrackDrawRLE_Read7_Got2 ; 5 offsetTableEntry.w SSTrackDrawRLE_Read7_Got1 ; 6 offsetTableEntry.w SSTrackDrawRLE_Read7_Got0 ; 7 ; =========================================================================== + moveq #6,d0 ; d0 = 6 sub.b d3,d0 ; d0 = 6 - d3 addq.b #1,d0 ; d0 = 7 - d3; why not shorten it to 'moveq #7,d0 \n sub.b d3,d0'? add.b d0,d0 ; Convert into table index move.w SSTrackDrawRLE_Read6LUT(pc,d0.w),d0 jmp SSTrackDrawRLE_Read6LUT(pc,d0.w) ; =========================================================================== ;off_57CE SSTrackDrawRLE_Read6LUT: offsetTable offsetTableEntry.w SSTrackDrawRLE_Read6_Got7 ; 0 offsetTableEntry.w SSTrackDrawRLE_Read6_Got6 ; 1 offsetTableEntry.w SSTrackDrawRLE_Read6_Got5 ; 2 offsetTableEntry.w SSTrackDrawRLE_Read6_Got4 ; 3 offsetTableEntry.w SSTrackDrawRLE_Read6_Got3 ; 4 offsetTableEntry.w SSTrackDrawRLE_Read6_Got2 ; 5 offsetTableEntry.w SSTrackDrawRLE_Read6_Got1 ; 6 offsetTableEntry.w SSTrackDrawRLE_Read6_Got0 ; 7 ; =========================================================================== ;loc_57DE SSTrackDrawUnc_Read10_Got0: ; Reads 10 bits from uncompressed mappings, 0 bits in bit buffer moveq #0,d0 move.b (a1)+,d0 lsl.w #2,d0 move.b (a1)+,d4 rol.b #2,d4 move.b d4,d1 andi.b #3,d1 or.b d1,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #6,d5 bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5806 SSTrackDrawUnc_Read10_Got1: ; Reads 10 bits from uncompressed mappings, 1 bit in bit buffer move.b d4,d0 lsl.w #2,d0 andi.w #$200,d0 move.b (a1)+,d1 lsl.w #1,d1 or.w d1,d0 move.b (a1)+,d4 rol.b #1,d4 move.b d4,d1 andi.b #1,d1 or.b d1,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #7,d5 bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5836 SSTrackDrawUnc_Read10_Got2: ; Reads 10 bits from uncompressed mappings, 2 bits in bit buffer move.b d4,d0 lsl.w #2,d0 andi.w #$300,d0 move.b (a1)+,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #0,d5 ; Bit buffer now empty bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5856 SSTrackDrawUnc_Read10_Got3: ; Reads 10 bits from uncompressed mappings, 3 bits in bit buffer move.b d4,d0 lsl.w #2,d0 andi.w #$380,d0 move.b (a1)+,d4 ror.b #1,d4 move.b d4,d1 andi.b #$7F,d1 or.b d1,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #1,d5 ; Bit buffer now has 1 bit bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5880 SSTrackDrawUnc_Read10_Got4: ; Reads 10 bits from uncompressed mappings, 4 bits in bit buffer move.b d4,d0 lsl.w #2,d0 andi.w #$3C0,d0 move.b (a1)+,d4 ror.b #2,d4 move.b d4,d1 andi.b #$3F,d1 or.b d1,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #2,d5 ; Bit buffer now has 2 bits bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_58AA SSTrackDrawUnc_Read10_Got5: ; Reads 10 bits from uncompressed mappings, 5 bits in bit buffer move.b d4,d0 lsl.w #2,d0 andi.w #$3E0,d0 move.b (a1)+,d4 ror.b #3,d4 move.b d4,d1 andi.b #$1F,d1 or.b d1,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #3,d5 ; Bit buffer now has 3 bits bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_58D4 SSTrackDrawUnc_Read10_Got6: ; Reads 10 bits from uncompressed mappings, 6 bits in bit buffer move.b d4,d0 lsl.w #2,d0 andi.w #$3F0,d0 move.b (a1)+,d4 ror.b #4,d4 move.b d4,d1 andi.b #$F,d1 or.b d1,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #4,d5 ; Bit buffer now has 4 bits bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_58FE SSTrackDrawUnc_Read10_Got7: ; Reads 10 bits from uncompressed mappings, 7 bits in bit buffer move.b d4,d0 lsl.w #2,d0 andi.w #$3F8,d0 move.b (a1)+,d4 rol.b #3,d4 move.b d4,d1 andi.b #7,d1 or.b d1,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #5,d5 ; Bit buffer now has 5 bits bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5928 SSTrackDrawUnc_Read6_Got0: ; Reads 6 bits from uncompressed mappings, 0 bits in bit buffer move.b (a1)+,d4 ror.b #2,d4 move.b d4,d0 andi.w #$3F,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #2,d5 ; Bit buffer now has 2 bits bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5944 SSTrackDrawUnc_Read6_Got1: ; Reads 6 bits from uncompressed mappings, 1 bit in bit buffer move.b d4,d0 lsr.b #2,d0 andi.w #$20,d0 move.b (a1)+,d4 ror.b #3,d4 move.b d4,d1 andi.b #$1F,d1 or.b d1,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #3,d5 ; Bit buffer now has 3 bits bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_596A SSTrackDrawUnc_Read6_Got2: ; Reads 6 bits from uncompressed mappings, 2 bits in bit buffer move.b d4,d0 lsr.b #2,d0 andi.w #$30,d0 move.b (a1)+,d4 ror.b #4,d4 move.b d4,d1 andi.b #$F,d1 or.b d1,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #4,d5 ; Bit buffer now has 4 bits bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5990 SSTrackDrawUnc_Read6_Got3: ; Reads 6 bits from uncompressed mappings, 3 bits in bit buffer move.b d4,d0 lsr.b #2,d0 andi.w #$38,d0 move.b (a1)+,d4 rol.b #3,d4 move.b d4,d1 andi.b #7,d1 or.b d1,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #5,d5 ; Bit buffer now has 5 bits bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_59B6 SSTrackDrawUnc_Read6_Got4: ; Reads 6 bits from uncompressed mappings, 4 bits in bit buffer move.b d4,d0 lsr.b #2,d0 andi.w #$3C,d0 move.b (a1)+,d4 rol.b #2,d4 move.b d4,d1 andi.b #3,d1 or.b d1,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #6,d5 ; Bit buffer now has 6 bits bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_59DC SSTrackDrawUnc_Read6_Got5: ; Reads 6 bits from uncompressed mappings, 5 bits in bit buffer move.b d4,d0 lsr.b #2,d0 andi.w #$3E,d0 move.b (a1)+,d4 rol.b #1,d4 move.b d4,d1 andi.b #1,d1 or.b d1,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #7,d5 ; Bit buffer now has 7 bits bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5A02 SSTrackDrawUnc_Read6_Got6: ; Reads 6 bits from uncompressed mappings, 6 bits in bit buffer lsr.b #2,d4 andi.w #$3F,d4 add.w d4,d4 move.w (a3,d4.w),d4 ori.w #palette_line_3,d4 move.w d4,(a6) moveq #0,d5 ; Bit buffer now empty bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5A1A SSTrackDrawUnc_Read6_Got7: ; Reads 6 bits from uncompressed mappings, 7 bits in bit buffer ror.b #2,d4 move.b d4,d0 andi.w #$3F,d0 add.w d0,d0 move.w (a3,d0.w),d0 ori.w #palette_line_3,d0 move.w d0,(a6) moveq #1,d5 ; Bit buffer now has 1 bit bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5A34 SSTrackDrawRLE_Read7_Got0: ; Reads 7 bits from RLE-compressed mappings, 0 bits in bit buffer move.b (a2)+,d2 ror.b #1,d2 move.b d2,d0 andi.w #$7F,d0 moveq #1,d3 ; Bit buffer now has 1 bit cmpi.b #$7F,d0 beq.w SSTrackDrawLineLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0 add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5A66 SSTrackDrawRLE_Read7_Got1: ; Reads 7 bits from RLE-compressed mappings, 1 bit in bit buffer move.b d2,d1 lsr.b #1,d1 andi.b #$40,d1 move.b (a2)+,d2 ror.b #2,d2 move.b d2,d0 andi.w #$3F,d0 or.b d1,d0 moveq #2,d3 ; Bit buffer now has 2 bits cmpi.b #$7F,d0 beq.w SSTrackDrawLineLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0 add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5AA2 SSTrackDrawRLE_Read7_Got2: ; Reads 7 bits from RLE-compressed mappings, 2 bits in bit buffer move.b d2,d1 lsr.b #1,d1 andi.b #$60,d1 move.b (a2)+,d2 ror.b #3,d2 move.b d2,d0 andi.w #$1F,d0 or.b d1,d0 moveq #3,d3 ; Bit buffer now has 3 bits cmpi.b #$7F,d0 beq.w SSTrackDrawLineLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0 add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5ADE SSTrackDrawRLE_Read7_Got3: ; Reads 7 bits from RLE-compressed mappings, 3 bits in bit buffer move.b d2,d1 lsr.b #1,d1 andi.b #$70,d1 move.b (a2)+,d2 ror.b #4,d2 move.b d2,d0 andi.w #$F,d0 or.b d1,d0 moveq #4,d3 ; Bit buffer now has 4 bits cmpi.b #$7F,d0 beq.w SSTrackDrawLineLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0 add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5B1A SSTrackDrawRLE_Read7_Got4: ; Reads 7 bits from RLE-compressed mappings, 4 bits in bit buffer move.b d2,d1 lsr.b #1,d1 andi.b #$78,d1 move.b (a2)+,d2 rol.b #3,d2 move.b d2,d0 andi.w #7,d0 or.b d1,d0 moveq #5,d3 ; Bit buffer now has 5 bits cmpi.b #$7F,d0 beq.w SSTrackDrawLineLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0 add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5B56 SSTrackDrawRLE_Read7_Got5: ; Reads 7 bits from RLE-compressed mappings, 5 bits in bit buffer move.b d2,d1 lsr.b #1,d1 andi.b #$7C,d1 move.b (a2)+,d2 rol.b #2,d2 move.b d2,d0 andi.w #3,d0 or.b d1,d0 moveq #6,d3 ; Bit buffer now has 6 bits cmpi.b #$7F,d0 beq.w SSTrackDrawLineLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0 add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5B92 SSTrackDrawRLE_Read7_Got6: ; Reads 7 bits from RLE-compressed mappings, 6 bits in bit buffer move.b d2,d1 lsr.b #1,d1 andi.b #$7E,d1 move.b (a2)+,d2 rol.b #1,d2 move.b d2,d0 andi.w #1,d0 or.b d1,d0 moveq #7,d3 ; Bit buffer now has 7 bits cmpi.b #$7F,d0 beq.w SSTrackDrawLineLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0 add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5BCE SSTrackDrawRLE_Read7_Got7: ; Reads 7 bits from RLE-compressed mappings, 7 bits in bit buffer lsr.b #1,d2 andi.w #$7F,d2 moveq #0,d3 ; Bit buffer now empty cmpi.b #$7F,d2 beq.w SSTrackDrawLineLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d2 add.w d2,d2 add.w d2,d2 move.w (a4,d2.w),d1 move.w 2(a4,d2.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5BFC SSTrackDrawRLE_Read6_Got0: ; Reads 6 bits from RLE-compressed mappings, 0 bits in bit buffer move.b (a2)+,d2 ror.b #2,d2 move.b d2,d0 andi.w #$3F,d0 add.w d0,d0 add.w d0,d0 moveq #2,d3 ; Bit buffer now has 2 bits move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5C22 SSTrackDrawRLE_Read6_Got1: ; Reads 6 bits from RLE-compressed mappings, 1 bit in bit buffer move.b d2,d0 lsr.b #2,d0 andi.w #$20,d0 move.b (a2)+,d2 ror.b #3,d2 move.b d2,d1 andi.b #$1F,d1 or.b d1,d0 moveq #3,d3 ; Bit buffer now has 3 bits add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5C52 SSTrackDrawRLE_Read6_Got2: ; Reads 6 bits from RLE-compressed mappings, 2 bits in bit buffer move.b d2,d0 lsr.b #2,d0 andi.w #$30,d0 move.b (a2)+,d2 ror.b #4,d2 move.b d2,d1 andi.b #$F,d1 or.b d1,d0 add.w d0,d0 add.w d0,d0 moveq #4,d3 ; Bit buffer now has 4 bits move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5C82 SSTrackDrawRLE_Read6_Got3: ; Reads 6 bits from RLE-compressed mappings, 3 bits in bit buffer move.b d2,d0 lsr.b #2,d0 andi.w #$38,d0 move.b (a2)+,d2 rol.b #3,d2 move.b d2,d1 andi.b #7,d1 or.b d1,d0 add.w d0,d0 add.w d0,d0 moveq #5,d3 ; Bit buffer now has 5 bits move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5CB2 SSTrackDrawRLE_Read6_Got4: ; Reads 6 bits from RLE-compressed mappings, 4 bits in bit buffer move.b d2,d0 lsr.b #2,d0 andi.w #$3C,d0 move.b (a2)+,d2 rol.b #2,d2 move.b d2,d1 andi.b #3,d1 or.b d1,d0 add.w d0,d0 add.w d0,d0 moveq #6,d3 ; Bit buffer now has 6 bits move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5CE2 SSTrackDrawRLE_Read6_Got5: ; Reads 6 bits from RLE-compressed mappings, 5 bits in bit buffer move.b d2,d0 lsr.b #2,d0 andi.w #$3E,d0 move.b (a2)+,d2 rol.b #1,d2 move.b d2,d1 andi.b #1,d1 or.b d1,d0 add.w d0,d0 add.w d0,d0 moveq #7,d3 ; Bit buffer now has 7 bits move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5D12 SSTrackDrawRLE_Read6_Got6: ; Reads 6 bits from RLE-compressed mappings, 6 bits in bit buffer lsr.b #2,d2 andi.w #$3F,d2 add.w d2,d2 add.w d2,d2 moveq #0,d3 ; Bit buffer now empty move.w (a4,d2.w),d1 move.w 2(a4,d2.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5D34 SSTrackDrawRLE_Read6_Got7: ; Reads 6 bits from RLE-compressed mappings, 7 bits in bit buffer ror.b #2,d2 move.b d2,d0 andi.w #$3F,d0 add.w d0,d0 add.w d0,d0 moveq #1,d3 ; Bit buffer now has 1 bit move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,(a6) dbf d0,- bra.w SSTrackDrawLoop_Inner ; =========================================================================== ;loc_5D58 SSTrackDraw_return: cmpi.b #3,(SSTrack_drawing_index).w ; Have we drawed a full frame? beq.s + ; Branch if yes move.l a0,(SSTrack_mappings_bitflags).w ; Save pointer move.l a1,(SSTrack_mappings_uncompressed).w ; Save pointer move.l a2,(SSTrack_mappings_RLE).w ; Save pointer lea (SSDrawRegBuffer_End).w,a3 ; Pointer to end of registry buffer movem.w d2-d7,-(a3) ; Save the bit buffers and bit counters rts ; =========================================================================== + lea (SSDrawRegBuffer).w,a2 ; Pointer to registry buffer moveq #0,d0 rept 6 move.w d0,(a2)+ ; Clear bit buffers and bit counters endm rts ; =========================================================================== ;loc_5D8A SSTrackDrawLineFlipLoop: adda_.w #1,a5 ; Increment loop counter cmpa.w #0,a5 ; Have all 8 lines been drawn? beq.w SSTrackDraw_return ; If yes, return lea (PNT_Buffer).w,a6 ; Destination buffer swap d0 ; High word starts at 0 addi.w #$100,d0 ; Adding $100 means seek to end of current line/start of next line andi.w #$F00,d0 ; Keep to confines adda.w d0,a6 ; Seek to end of current line swap d0 ; Leaves the low word of d0 free for use ;loc_5DA8 SSTrackDrawFlipLoop_Inner: moveq #0,d1 subq.w #1,d7 ; Subtract 1 from bit counter bpl.s + ; Branch if we still have bits we can use move.b (a0)+,d6 ; Get a new byte from bit flags moveq #7,d7 ; We now have 8 fresh new bits + add.b d6,d6 ; Do we have to use RLE compression? bcc.s SSTrackDrawFlipRLE ; Branch if yes subq.b #1,d5 ; Subtract 1 from bit counter bpl.s + ; Branch if we still have bits we can use move.b (a1)+,d4 ; Get a new byte from uncompressed mappings pointer moveq #7,d5 ; We now have 8 fresh new bits + add.b d4,d4 ; Do we need a 10-bit index? bcc.s + ; Branch if not move.w #$A,d0 ; d0 = 10 bits sub.b d5,d0 ; d0 = 10 - d5 subq.b #3,d0 ; d0 = 7 - d5; why not shorten it to 'moveq #7,d0 \n sub.b d5,d0'? add.w d0,d0 ; Convert into table index move.w SSTrackDrawFlipUnc_Read10LUT(pc,d0.w),d0 jmp SSTrackDrawFlipUnc_Read10LUT(pc,d0.w) ; =========================================================================== ;off_5DD4 SSTrackDrawFlipUnc_Read10LUT: offsetTable offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got7 ; 0 offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got6 ; 1 offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got5 ; 2 offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got4 ; 3 offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got3 ; 4 offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got2 ; 5 offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got1 ; 6 offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got0 ; 7 ; =========================================================================== + move.w #6,d0 ; d0 = 6 sub.b d5,d0 ; d0 = 6 - d5 addq.b #1,d0 ; d0 = 7 - d5; why not shorten it to 'moveq #7,d0 \n sub.b d5,d0'? add.w d0,d0 ; Convert into table index move.w SSTrackDrawFlipUnc_Read6LUT(pc,d0.w),d0 jmp SSTrackDrawFlipUnc_Read6LUT(pc,d0.w) ; =========================================================================== ;off_5DF6 SSTrackDrawFlipUnc_Read6LUT: offsetTable offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got7 ; 0 offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got6 ; 1 offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got5 ; 2 offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got4 ; 3 offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got3 ; 4 offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got2 ; 5 offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got1 ; 6 offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got0 ; 7 ; =========================================================================== ;loc_5E06 SSTrackDrawFlipRLE: subq.b #1,d3 ; Subtract 1 from bit counter bpl.s ++ ; Branch if we still have bits we can use move.b (a2)+,d2 ; Get a new byte from RLE mappings pointer cmpi.b #-1,d2 ; Is d2 equal to -1? bne.s + ; Branch if not moveq #0,d3 ; Set bit counter to zero bra.w SSTrackDrawLineFlipLoop ; =========================================================================== + moveq #7,d3 ; We now have 8 fresh new bits + add.b d2,d2 ; Do we need a 7-bit index? bcc.s + ; Branch if not move.w #7,d0 ; d0 = 7 sub.b d3,d0 ; d0 = 10 - d3 add.b d0,d0 ; Convert into table index move.w SSTrackDrawFlipRLE_Read7LUT(pc,d0.w),d0 jmp SSTrackDrawFlipRLE_Read7LUT(pc,d0.w) ; =========================================================================== ;off_5E2E SSTrackDrawFlipRLE_Read7LUT: offsetTable offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got7 ; 0 offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got6 ; 1 offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got5 ; 2 offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got4 ; 3 offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got3 ; 4 offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got2 ; 5 offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got1 ; 6 offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got0 ; 7 ; =========================================================================== + move.w #6,d0 ; d0 = 6 sub.b d3,d0 ; d0 = 6 - d3 addq.b #1,d0 ; d0 = 7 - d3; why not shorten it to 'moveq #7,d0 \n sub.b d3,d0'? add.b d0,d0 ; Convert into table index move.w SSTrackDrawFlipRLE_Read6LUT(pc,d0.w),d0 jmp SSTrackDrawFlipRLE_Read6LUT(pc,d0.w) ; =========================================================================== ;off_5E50 SSTrackDrawFlipRLE_Read6LUT: offsetTable offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got7 ; 0 offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got6 ; 1 offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got5 ; 2 offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got4 ; 3 offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got3 ; 4 offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got2 ; 5 offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got1 ; 6 offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got0 ; 7 ; =========================================================================== ;loc_5E60 SSTrackDrawFlipUnc_Read10_Got0: ; Reads 10 bits from uncompressed mappings, 0 bits in bit buffer move.w #0,d0 move.b (a1)+,d0 lsl.w #2,d0 move.b (a1)+,d4 rol.b #2,d4 move.b d4,d1 andi.b #3,d1 or.b d1,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #6,d5 ; Bit buffer now has 6 bits bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_5E8A SSTrackDrawFlipUnc_Read10_Got1: ; Reads 10 bits from uncompressed mappings, 1 bit in bit buffer move.b d4,d0 lsl.w #2,d0 andi.w #$200,d0 move.b (a1)+,d1 lsl.w #1,d1 or.w d1,d0 move.b (a1)+,d4 rol.b #1,d4 move.b d4,d1 andi.b #1,d1 or.b d1,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #7,d5 ; Bit buffer now has 7 bits bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_5EBA SSTrackDrawFlipUnc_Read10_Got2: ; Reads 10 bits from uncompressed mappings, 2 bits in bit buffer move.b d4,d0 lsl.w #2,d0 andi.w #$300,d0 move.b (a1)+,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #0,d5 ; Bit buffer now empty bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_5EDA SSTrackDrawFlipUnc_Read10_Got3: ; Reads 10 bits from uncompressed mappings, 3 bits in bit buffer move.b d4,d0 lsl.w #2,d0 andi.w #$380,d0 move.b (a1)+,d4 ror.b #1,d4 move.b d4,d1 andi.b #$7F,d1 or.b d1,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #1,d5 ; Bit buffer now has 1 bit bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_5F04 SSTrackDrawFlipUnc_Read10_Got4: ; Reads 10 bits from uncompressed mappings, 4 bits in bit buffer move.b d4,d0 lsl.w #2,d0 andi.w #$3C0,d0 move.b (a1)+,d4 ror.b #2,d4 move.b d4,d1 andi.b #$3F,d1 or.b d1,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #2,d5 ; Bit buffer now has 2 bits bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_5F2E SSTrackDrawFlipUnc_Read10_Got5: ; Reads 10 bits from uncompressed mappings, 5 bits in bit buffer move.b d4,d0 lsl.w #2,d0 andi.w #$3E0,d0 move.b (a1)+,d4 ror.b #3,d4 move.b d4,d1 andi.b #$1F,d1 or.b d1,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #3,d5 ; Bit buffer now has 3 bits bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_5F58 SSTrackDrawFlipUnc_Read10_Got6: ; Reads 10 bits from uncompressed mappings, 6 bits in bit buffer move.b d4,d0 lsl.w #2,d0 andi.w #$3F0,d0 move.b (a1)+,d4 ror.b #4,d4 move.b d4,d1 andi.b #$F,d1 or.b d1,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #4,d5 ; Bit buffer now has 4 bits bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_5F82 SSTrackDrawFlipUnc_Read10_Got7: ; Reads 10 bits from uncompressed mappings, 7 bits in bit buffer move.b d4,d0 lsl.w #2,d0 andi.w #$3F8,d0 move.b (a1)+,d4 rol.b #3,d4 move.b d4,d1 andi.b #7,d1 or.b d1,d0 addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #5,d5 ; Bit buffer now has 5 bits bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_5FAC SSTrackDrawFlipUnc_Read6_Got0: ; Reads 6 bits from uncompressed mappings, 0 bits in bit buffer move.b (a1)+,d4 ror.b #2,d4 move.b d4,d0 andi.w #$3F,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #2,d5 ; Bit buffer now has 2 bits bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_5FC8 SSTrackDrawFlipUnc_Read6_Got1: ; Reads 6 bits from uncompressed mappings, 1 bit in bit buffer move.b d4,d0 lsr.b #2,d0 andi.w #$20,d0 move.b (a1)+,d4 ror.b #3,d4 move.b d4,d1 andi.b #$1F,d1 or.b d1,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #3,d5 ; Bit buffer now has 3 bits bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_5FEE SSTrackDrawFlipUnc_Read6_Got2: ; Reads 6 bits from uncompressed mappings, 2 bits in bit buffer move.b d4,d0 lsr.b #2,d0 andi.w #$30,d0 move.b (a1)+,d4 ror.b #4,d4 move.b d4,d1 andi.b #$F,d1 or.b d1,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #4,d5 ; Bit buffer now has 4 bits bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_6014 SSTrackDrawFlipUnc_Read6_Got3: ; Reads 6 bits from uncompressed mappings, 3 bits in bit buffer move.b d4,d0 lsr.b #2,d0 andi.w #$38,d0 move.b (a1)+,d4 rol.b #3,d4 move.b d4,d1 andi.b #7,d1 or.b d1,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #5,d5 ; Bit buffer now has 5 bits bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_603A SSTrackDrawFlipUnc_Read6_Got4: ; Reads 6 bits from uncompressed mappings, 4 bits in bit buffer move.b d4,d0 lsr.b #2,d0 andi.w #$3C,d0 move.b (a1)+,d4 rol.b #2,d4 move.b d4,d1 andi.b #3,d1 or.b d1,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #6,d5 ; Bit buffer now has 6 bits bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_6060 SSTrackDrawFlipUnc_Read6_Got5: ; Reads 6 bits from uncompressed mappings, 5 bits in bit buffer move.b d4,d0 lsr.b #2,d0 andi.w #$3E,d0 move.b (a1)+,d4 rol.b #1,d4 move.b d4,d1 andi.b #1,d1 or.b d1,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #7,d5 ; Bit buffer now has 7 bits bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_6086 SSTrackDrawFlipUnc_Read6_Got6: ; Reads 6 bits from uncompressed mappings, 6 bits in bit buffer lsr.b #2,d4 andi.w #$3F,d4 add.w d4,d4 move.w (a3,d4.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #0,d5 ; Bit buffer now empty bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_609E SSTrackDrawFlipUnc_Read6_Got7: ; Reads 6 bits from uncompressed mappings, 7 bits in bit buffer ror.b #2,d4 move.b d4,d0 andi.w #$3F,d0 add.w d0,d0 move.w (a3,d0.w),d0 eori.w #flip_x|palette_line_3,d0 move.w d0,-(a6) moveq #1,d5 ; Bit buffer now has 1 bit bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_60B8 SSTrackDrawFlipRLE_Read7_Got0: ; Reads 7 bits from RLE-compressed mappings, 0 bits in bit buffer move.b (a2)+,d2 ror.b #1,d2 move.b d2,d0 andi.w #$7F,d0 moveq #1,d3 ; Bit buffer now has 1 bit cmpi.b #$7F,d0 beq.w SSTrackDrawLineFlipLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0 add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_60EA SSTrackDrawFlipRLE_Read7_Got1: ; Reads 7 bits from RLE-compressed mappings, 1 bit in bit buffer move.b d2,d1 lsr.b #1,d1 andi.b #$40,d1 move.b (a2)+,d2 ror.b #2,d2 move.b d2,d0 andi.w #$3F,d0 or.b d1,d0 moveq #2,d3 ; Bit buffer now has 2 bits cmpi.b #$7F,d0 beq.w SSTrackDrawLineFlipLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0 add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_6126 SSTrackDrawFlipRLE_Read7_Got2: ; Reads 7 bits from RLE-compressed mappings, 2 bits in bit buffer move.b d2,d1 lsr.b #1,d1 andi.b #$60,d1 move.b (a2)+,d2 ror.b #3,d2 move.b d2,d0 andi.w #$1F,d0 or.b d1,d0 moveq #3,d3 ; Bit buffer now has 3 bits cmpi.b #$7F,d0 beq.w SSTrackDrawLineFlipLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0 add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_6162 SSTrackDrawFlipRLE_Read7_Got3: ; Reads 7 bits from RLE-compressed mappings, 3 bits in bit buffer move.b d2,d1 lsr.b #1,d1 andi.b #$70,d1 move.b (a2)+,d2 ror.b #4,d2 move.b d2,d0 andi.w #$F,d0 or.b d1,d0 moveq #4,d3 ; Bit buffer now has 4 bits cmpi.b #$7F,d0 beq.w SSTrackDrawLineFlipLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0 add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_619E SSTrackDrawFlipRLE_Read7_Got4: ; Reads 7 bits from RLE-compressed mappings, 4 bits in bit buffer move.b d2,d1 lsr.b #1,d1 andi.b #$78,d1 move.b (a2)+,d2 rol.b #3,d2 move.b d2,d0 andi.w #7,d0 or.b d1,d0 moveq #5,d3 ; Bit buffer now has 5 bits cmpi.b #$7F,d0 beq.w SSTrackDrawLineFlipLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0 add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_61DA SSTrackDrawFlipRLE_Read7_Got5: ; Reads 7 bits from RLE-compressed mappings, 5 bits in bit buffer move.b d2,d1 lsr.b #1,d1 andi.b #$7C,d1 move.b (a2)+,d2 rol.b #2,d2 move.b d2,d0 andi.w #3,d0 or.b d1,d0 moveq #6,d3 ; Bit buffer now has 6 bits cmpi.b #$7F,d0 beq.w SSTrackDrawLineFlipLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0 add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_6216 SSTrackDrawFlipRLE_Read7_Got6: ; Reads 7 bits from RLE-compressed mappings, 6 bits in bit buffer move.b d2,d1 lsr.b #1,d1 andi.b #$7E,d1 move.b (a2)+,d2 rol.b #1,d2 move.b d2,d0 andi.w #1,d0 or.b d1,d0 moveq #7,d3 ; Bit buffer now has 7 bits cmpi.b #$7F,d0 beq.w SSTrackDrawLineFlipLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0 add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_6252 SSTrackDrawFlipRLE_Read7_Got7: ; Reads 7 bits from RLE-compressed mappings, 7 bits in bit buffer lsr.b #1,d2 andi.w #$7F,d2 moveq #0,d3 ; Bit buffer now empty cmpi.b #$7F,d2 beq.w SSTrackDrawLineFlipLoop addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d2 add.w d2,d2 add.w d2,d2 move.w (a4,d2.w),d1 move.w 2(a4,d2.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_6280 SSTrackDrawFlipRLE_Read6_Got0: ; Reads 6 bits from RLE-compressed mappings, 0 bits in bit buffer move.b (a2)+,d2 ror.b #2,d2 move.b d2,d0 andi.w #$3F,d0 add.w d0,d0 add.w d0,d0 moveq #2,d3 ; Bit buffer now has 2 bits move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_62A6 SSTrackDrawFlipRLE_Read6_Got1: ; Reads 6 bits from RLE-compressed mappings, 1 bit in bit buffer move.b d2,d0 lsr.b #2,d0 andi.w #$20,d0 move.b (a2)+,d2 ror.b #3,d2 move.b d2,d1 andi.b #$1F,d1 or.b d1,d0 moveq #3,d3 ; Bit buffer now has 3 bits add.w d0,d0 add.w d0,d0 move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_62D6 SSTrackDrawFlipRLE_Read6_Got2: ; Reads 6 bits from RLE-compressed mappings, 2 bits in bit buffer move.b d2,d0 lsr.b #2,d0 andi.w #$30,d0 move.b (a2)+,d2 ror.b #4,d2 move.b d2,d1 andi.b #$F,d1 or.b d1,d0 add.w d0,d0 add.w d0,d0 moveq #4,d3 ; Bit buffer now has 4 bits move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_6306 SSTrackDrawFlipRLE_Read6_Got3: ; Reads 6 bits from RLE-compressed mappings, 3 bits in bit buffer move.b d2,d0 lsr.b #2,d0 andi.w #$38,d0 move.b (a2)+,d2 rol.b #3,d2 move.b d2,d1 andi.b #7,d1 or.b d1,d0 add.w d0,d0 add.w d0,d0 moveq #5,d3 ; Bit buffer now has 5 bits move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_6336 SSTrackDrawFlipRLE_Read6_Got4: ; Reads 6 bits from RLE-compressed mappings, 4 bits in bit buffer move.b d2,d0 lsr.b #2,d0 andi.w #$3C,d0 move.b (a2)+,d2 rol.b #2,d2 move.b d2,d1 andi.b #3,d1 or.b d1,d0 add.w d0,d0 add.w d0,d0 moveq #6,d3 ; Bit buffer now has 6 bits move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_6366 SSTrackDrawFlipRLE_Read6_Got5: ; Reads 6 bits from RLE-compressed mappings, 5 bits in bit buffer move.b d2,d0 lsr.b #2,d0 andi.w #$3E,d0 move.b (a2)+,d2 rol.b #1,d2 move.b d2,d1 andi.b #1,d1 or.b d1,d0 add.w d0,d0 add.w d0,d0 moveq #7,d3 ; Bit buffer now has 7 bits move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_6396 SSTrackDrawFlipRLE_Read6_Got6: ; Reads 6 bits from RLE-compressed mappings, 6 bits in bit buffer lsr.b #2,d2 andi.w #$3F,d2 add.w d2,d2 add.w d2,d2 moveq #0,d3 ; Bit buffer now empty move.w (a4,d2.w),d1 move.w 2(a4,d2.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ;loc_63B8 SSTrackDrawFlipRLE_Read6_Got7: ; Reads 6 bits from RLE-compressed mappings, 7 bits in bit buffer ror.b #2,d2 move.b d2,d0 andi.w #$3F,d0 add.w d0,d0 add.w d0,d0 moveq #1,d3 ; Bit buffer now has 1 bit move.w (a4,d0.w),d1 move.w 2(a4,d0.w),d0 ori.w #palette_line_3|high_priority,d1 - move.w d1,-(a6) dbf d0,- bra.w SSTrackDrawFlipLoop_Inner ; =========================================================================== ; frames of animation of the special stage track ; this chooses how objects curve along the track as well as which track frame to draw ; off_63DC: Ani_SpecialStageTrack: offsetTable offsetTableEntry.w SSTrackAni_TurnThenRise ; 0 offsetTableEntry.w SSTrackAni_TurnThenDrop ; 1 offsetTableEntry.w SSTrackAni_TurnThenStraight ; 2 offsetTableEntry.w SSTrackAni_Straight ; 3 offsetTableEntry.w SSTrackAni_StraightThenTurn ; 4 ; byte_63E6: SSTrackAni_TurnThenRise: dc.b $26,$27,$28,$29,$2A,$2B,$26 ; turning dc.b 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, $A, $B, $C, $D, $E, $F,$10 ; rise SSTrackAni_TurnThenRise_End: ; byte_63FE: SSTrackAni_TurnThenDrop: dc.b $26,$27,$28,$29,$2A,$2B,$26 ; turning dc.b $15,$16,$17,$18,$19,$1A,$1B,$1C,$1D,$1E,$1F,$20,$21,$22,$23,$24,$25 ; drop SSTrackAni_TurnThenDrop_End: ; byte_6416: SSTrackAni_TurnThenStraight: dc.b $26,$27,$28,$29,$2A,$2B,$26 ; turning dc.b $2C,$2D,$2E,$2F,$30 ; exit turn SSTrackAni_TurnThenStraight_End: ; byte_6422: SSTrackAni_Straight: dc.b $11,$12,$13,$14,$11,$12,$13,$14 ; straight dc.b $11,$12,$13,$14,$11,$12,$13,$14 ; straight SSTrackAni_Straight_End: ; byte_6432: SSTrackAni_StraightThenTurn: dc.b $11,$12,$13,$14 ; straight dc.b $31,$32,$33,$34,$35,$36,$37 ; enter turn SSTrackAni_StraightThenTurn_End: even ; =========================================================================== ; pointers to the mappings for each frame of the special stage track ; indexed into by the numbers used in the above animations ; ; Format of each mappings file: ; File is divided in 3 segments, with the same structure: ; Segment structure: ; 4-byte unsigned length of segment (not counting the 4 bytes used for length); ; the first 2 bytes of each length is ignored, and only the last 2 bytes are ; actually used. ; Rest of the segment is mappings data, as follows: ; 1st segment: ; Mappings data is a bitstream indicating whether to draw a single tile at ; a time using the uncompressed mappings (see 2nd segment) or a sequence of ; tiles using the RLE mappings (see 3rd segment). ; 2nd segment: ; Mappings data is a bitstream: the first bit in each cycle determines how ; many bits from the stream are to be used as an index to the uncompressed ; pattern name list SSPNT_UncLUT: if the first bit is set, 10 bits form an ; index into SSPNT_UncLUT_Part2, otherwise 6 bits are used as an index into ; SSPNT_UncLUT. ; These tiles are drawn in palette line 3. ; 3nd segment: ; Mappings data is a bitstream: the first bit in each cycle determines how ; many bits from the stream are to be used as an index to the RLE-compressed ; pattern name list SSPNT_RLELUT: if the first bit is set, 7 bits form an ; index into SSPNT_RLELUT_Part2, otherwise 6 bits are used as an index into ; SSPNT_RLELUT. ; These tiles are drawn in palette line 3, with the high priority bit set. ; off_643E: Map_SpecialStageTrack: dc.l MapSpec_Rise1 ; 0 dc.l MapSpec_Rise2 ; 1 dc.l MapSpec_Rise3 ; 2 dc.l MapSpec_Rise4 ; 3 dc.l MapSpec_Rise5 ; 4 dc.l MapSpec_Rise6 ; 5 dc.l MapSpec_Rise7 ; 6 dc.l MapSpec_Rise8 ; 7 dc.l MapSpec_Rise9 ; 8 dc.l MapSpec_Rise10 ; 9 dc.l MapSpec_Rise11 ; $A dc.l MapSpec_Rise12 ; $B dc.l MapSpec_Rise13 ; $C dc.l MapSpec_Rise14 ; $D ; This may flip the special stage's horizontal orientation dc.l MapSpec_Rise15 ; $E dc.l MapSpec_Rise16 ; $F dc.l MapSpec_Rise17 ; $10 dc.l MapSpec_Straight1 ; $11 dc.l MapSpec_Straight2 ; $12 ; This may flip the special stage's horizontal orientation dc.l MapSpec_Straight3 ; $13 dc.l MapSpec_Straight4 ; $14 dc.l MapSpec_Drop1 ; $15 dc.l MapSpec_Drop2 ; $16 dc.l MapSpec_Drop3 ; $17 dc.l MapSpec_Drop4 ; $18 dc.l MapSpec_Drop5 ; $19 dc.l MapSpec_Drop6 ; $1A ; This may flip the special stage's horizontal orientation dc.l MapSpec_Drop7 ; $1B dc.l MapSpec_Drop8 ; $1C dc.l MapSpec_Drop9 ; $1D dc.l MapSpec_Drop10 ; $1E dc.l MapSpec_Drop11 ; $1F dc.l MapSpec_Drop12 ; $20 dc.l MapSpec_Drop13 ; $21 dc.l MapSpec_Drop14 ; $22 dc.l MapSpec_Drop15 ; $23 dc.l MapSpec_Drop16 ; $24 dc.l MapSpec_Drop17 ; $25 dc.l MapSpec_Turning1 ; $26 dc.l MapSpec_Turning2 ; $27 dc.l MapSpec_Turning3 ; $28 dc.l MapSpec_Turning4 ; $29 dc.l MapSpec_Turning5 ; $2A dc.l MapSpec_Turning6 ; $2B dc.l MapSpec_Unturn1 ; $2C dc.l MapSpec_Unturn2 ; $2D dc.l MapSpec_Unturn3 ; $2E dc.l MapSpec_Unturn4 ; $2F dc.l MapSpec_Unturn5 ; $30 dc.l MapSpec_Turn1 ; $31 dc.l MapSpec_Turn2 ; $32 dc.l MapSpec_Turn3 ; $33 dc.l MapSpec_Turn4 ; $34 dc.l MapSpec_Turn5 ; $35 dc.l MapSpec_Turn6 ; $36 dc.l MapSpec_Turn7 ; $37 ; These are pattern names. They get sent to either the pattern name table ; buffer or one region of one of the plane A name tables in the special stage. ; They are indexed by the second segment of the mappings in Map_SpecialStageTrack, above. ;word_651E SSPNT_UncLUT: dc.w make_block_tile($0001,0,0,0,1), make_block_tile($0007,0,0,0,1), make_block_tile($002C,0,0,0,1), make_block_tile($000B,0,0,0,1) ; $00 dc.w make_block_tile($0024,0,0,0,1), make_block_tile($0024,1,0,0,1), make_block_tile($0039,0,0,0,1), make_block_tile($002B,1,0,0,1) ; $04 dc.w make_block_tile($005D,0,0,0,1), make_block_tile($005D,1,0,0,1), make_block_tile($002B,0,0,0,1), make_block_tile($004A,0,0,0,1) ; $08 dc.w make_block_tile($0049,0,0,0,1), make_block_tile($0037,0,0,0,1), make_block_tile($0049,1,0,0,1), make_block_tile($0045,0,0,0,1) ; $0C dc.w make_block_tile($0045,1,0,0,1), make_block_tile($003A,1,0,0,1), make_block_tile($0048,0,0,0,1), make_block_tile($0050,1,0,0,1) ; $10 dc.w make_block_tile($0036,0,0,0,1), make_block_tile($0037,1,0,0,1), make_block_tile($003A,0,0,0,1), make_block_tile($0050,0,0,0,1) ; $14 dc.w make_block_tile($0042,1,0,0,1), make_block_tile($0042,0,0,0,1), make_block_tile($0015,1,0,0,1), make_block_tile($001D,0,0,0,1) ; $18 dc.w make_block_tile($004B,0,0,0,1), make_block_tile($0017,1,0,0,1), make_block_tile($0048,1,0,0,1), make_block_tile($0036,1,0,0,1) ; $1C dc.w make_block_tile($0038,0,0,0,1), make_block_tile($004B,1,0,0,1), make_block_tile($0015,0,0,0,1), make_block_tile($0021,0,0,0,1) ; $20 dc.w make_block_tile($0017,0,0,0,1), make_block_tile($0033,0,0,0,1), make_block_tile($001A,0,0,0,1), make_block_tile($002A,0,0,0,1) ; $24 dc.w make_block_tile($005E,0,0,0,1), make_block_tile($0028,0,0,0,1), make_block_tile($0030,0,0,0,1), make_block_tile($0021,1,0,0,1) ; $28 dc.w make_block_tile($0038,1,0,0,1), make_block_tile($001A,1,0,0,1), make_block_tile($0025,0,0,0,1), make_block_tile($005E,1,0,0,1) ; $2C dc.w make_block_tile($0025,1,0,0,1), make_block_tile($0033,1,0,0,1), make_block_tile($0003,0,0,0,1), make_block_tile($0014,1,0,0,1) ; $30 dc.w make_block_tile($0014,0,0,0,1), make_block_tile($0004,0,0,0,1), make_block_tile($004E,0,0,0,1), make_block_tile($0003,1,0,0,1) ; $34 dc.w make_block_tile($000C,0,0,0,1), make_block_tile($002A,1,0,0,1), make_block_tile($0002,0,0,0,1), make_block_tile($0051,0,0,0,1) ; $38 dc.w make_block_tile($0040,0,0,0,1), make_block_tile($003D,0,0,0,1), make_block_tile($0019,0,0,0,1), make_block_tile($0052,0,0,0,1) ; $3C ;word_659E SSPNT_UncLUT_Part2: dc.w make_block_tile($0009,0,0,0,1), make_block_tile($005A,0,0,0,1), make_block_tile($0030,1,0,0,1), make_block_tile($004E,1,0,0,1) ; $40 dc.w make_block_tile($0052,1,0,0,1), make_block_tile($0051,1,0,0,1), make_block_tile($0009,1,0,0,1), make_block_tile($0040,1,0,0,1) ; $44 dc.w make_block_tile($002F,0,0,0,1), make_block_tile($005A,1,0,0,1), make_block_tile($0018,1,0,0,1), make_block_tile($0034,0,0,0,1) ; $48 dc.w make_block_tile($0019,1,0,0,1), make_block_tile($002F,1,0,0,1), make_block_tile($003D,1,0,0,1), make_block_tile($003E,0,0,0,1) ; $4C dc.w make_block_tile($0018,0,0,0,1), make_block_tile($000C,1,0,0,1), make_block_tile($0012,0,0,0,1), make_block_tile($0004,1,0,0,1) ; $50 dc.w make_block_tile($0026,0,0,0,1), make_block_tile($0034,1,0,0,1), make_block_tile($0005,1,0,0,1), make_block_tile($003B,0,0,0,1) ; $54 dc.w make_block_tile($003E,1,0,0,1), make_block_tile($003B,1,0,0,1), make_block_tile($0000,0,0,0,1), make_block_tile($0002,1,0,0,1) ; $58 dc.w make_block_tile($0005,0,0,0,1), make_block_tile($000D,0,0,0,1), make_block_tile($0055,0,0,0,1), make_block_tile($00AF,0,0,0,1) ; $5C dc.w make_block_tile($001C,0,0,0,1), make_block_tile($001B,0,0,0,1), make_block_tile($000D,1,0,0,1), make_block_tile($0016,0,0,0,1) ; $60 dc.w make_block_tile($0012,1,0,0,1), make_block_tile($001F,0,0,0,1), make_block_tile($0032,1,0,0,1), make_block_tile($0013,0,0,0,1) ; $64 dc.w make_block_tile($0092,0,0,0,1), make_block_tile($0026,1,0,0,1), make_block_tile($0010,0,0,0,1), make_block_tile($004D,0,0,0,1) ; $68 dc.w make_block_tile($0047,0,0,0,1), make_block_tile($0092,1,0,0,1), make_block_tile($0000,1,0,0,1), make_block_tile($0062,0,0,0,1) ; $6C dc.w make_block_tile($0066,0,0,0,1), make_block_tile($0090,0,0,0,1), make_block_tile($0008,0,0,0,1), make_block_tile($007C,1,0,0,1) ; $70 dc.w make_block_tile($0067,1,0,0,1), make_block_tile($00F7,1,0,0,1), make_block_tile($000E,0,0,0,1), make_block_tile($0060,0,0,0,1) ; $74 dc.w make_block_tile($0032,0,0,0,1), make_block_tile($0094,0,0,0,1), make_block_tile($001C,1,0,0,1), make_block_tile($0105,1,0,0,1) ; $78 dc.w make_block_tile($00B0,1,0,0,1), make_block_tile($0059,0,0,0,1), make_block_tile($000F,0,0,0,1), make_block_tile($0067,0,0,0,1) ; $7C dc.w make_block_tile($0068,0,0,0,1), make_block_tile($0094,1,0,0,1), make_block_tile($007C,0,0,0,1), make_block_tile($00B0,0,0,0,1) ; $80 dc.w make_block_tile($00B1,0,0,0,1), make_block_tile($0006,0,0,0,1), make_block_tile($0041,1,0,0,1), make_block_tile($0087,0,0,0,1) ; $84 dc.w make_block_tile($0093,0,0,0,1), make_block_tile($00CC,0,0,0,1), make_block_tile($001F,1,0,0,1), make_block_tile($0068,1,0,0,1) ; $88 dc.w make_block_tile($0041,0,0,0,1), make_block_tile($008F,0,0,0,1), make_block_tile($0090,1,0,0,1), make_block_tile($00C2,0,0,0,1) ; $8C dc.w make_block_tile($0013,1,0,0,1), make_block_tile($00C2,1,0,0,1), make_block_tile($005C,0,0,0,1), make_block_tile($0064,0,0,0,1) ; $90 dc.w make_block_tile($00D8,0,0,0,1), make_block_tile($001B,1,0,0,1), make_block_tile($00CC,1,0,0,1), make_block_tile($0011,1,0,0,1) ; $94 dc.w make_block_tile($0055,1,0,0,1), make_block_tile($00E2,1,0,0,1), make_block_tile($00F3,1,0,0,1), make_block_tile($0044,0,0,0,1) ; $98 dc.w make_block_tile($00D8,1,0,0,1), make_block_tile($0085,0,0,0,1), make_block_tile($00A1,0,0,0,1), make_block_tile($00C1,0,0,0,1) ; $9C dc.w make_block_tile($0119,0,0,0,1), make_block_tile($0089,1,0,0,1), make_block_tile($000A,1,0,0,1), make_block_tile($0022,1,0,0,1) ; $A0 dc.w make_block_tile($003F,0,0,0,1), make_block_tile($005B,0,0,0,1), make_block_tile($007F,0,0,0,1), make_block_tile($0086,1,0,0,1) ; $A4 dc.w make_block_tile($0008,1,0,0,1), make_block_tile($0080,0,0,0,1), make_block_tile($0066,1,0,0,1), make_block_tile($00E0,1,0,0,1) ; $A8 dc.w make_block_tile($00C1,1,0,0,1), make_block_tile($0020,0,0,0,1), make_block_tile($0022,0,0,0,1), make_block_tile($0054,0,0,0,1) ; $AC dc.w make_block_tile($00D2,0,0,0,1), make_block_tile($0059,1,0,0,1), make_block_tile($00B1,1,0,0,1), make_block_tile($0060,1,0,0,1) ; $B0 dc.w make_block_tile($0119,1,0,0,1), make_block_tile($00A4,1,0,0,1), make_block_tile($008F,1,0,0,1), make_block_tile($000A,0,0,0,1) ; $B4 dc.w make_block_tile($0061,0,0,0,1), make_block_tile($0075,0,0,0,1), make_block_tile($0095,0,0,0,1), make_block_tile($00B6,0,0,0,1) ; $B8 dc.w make_block_tile($00E0,0,0,0,1), make_block_tile($0010,1,0,0,1), make_block_tile($0098,1,0,0,1), make_block_tile($005B,1,0,0,1) ; $BC dc.w make_block_tile($00D2,1,0,0,1), make_block_tile($0016,1,0,0,1), make_block_tile($0053,0,0,0,1), make_block_tile($0091,0,0,0,1) ; $C0 dc.w make_block_tile($0096,0,0,0,1), make_block_tile($00A4,0,0,0,1), make_block_tile($00DD,0,0,0,1), make_block_tile($00E6,0,0,0,1) ; $C4 dc.w make_block_tile($007A,1,0,0,1), make_block_tile($004D,1,0,0,1), make_block_tile($00E6,1,0,0,1), make_block_tile($0011,0,0,0,1) ; $C8 dc.w make_block_tile($0057,0,0,0,1), make_block_tile($007A,0,0,0,1), make_block_tile($0086,0,0,0,1), make_block_tile($009E,0,0,0,1) ; $CC dc.w make_block_tile($00DA,0,0,0,1), make_block_tile($0058,0,0,0,1), make_block_tile($00DC,0,0,0,1), make_block_tile($00E3,0,0,0,1) ; $D0 dc.w make_block_tile($0063,1,0,0,1), make_block_tile($003C,0,0,0,1), make_block_tile($0056,0,0,0,1), make_block_tile($0069,0,0,0,1) ; $D4 dc.w make_block_tile($007E,0,0,0,1), make_block_tile($00AE,0,0,0,1), make_block_tile($00B5,0,0,0,1), make_block_tile($00B8,0,0,0,1) ; $D8 dc.w make_block_tile($00CD,0,0,0,1), make_block_tile($00FB,0,0,0,1), make_block_tile($00FF,0,0,0,1), make_block_tile($005C,1,0,0,1) ; $DC dc.w make_block_tile($00CD,1,0,0,1), make_block_tile($0074,1,0,0,1), make_block_tile($00EA,1,0,0,1), make_block_tile($00FF,1,0,0,1) ; $E0 dc.w make_block_tile($00B5,1,0,0,1), make_block_tile($0043,0,0,0,1), make_block_tile($006C,0,0,0,1), make_block_tile($0074,0,0,0,1) ; $E4 dc.w make_block_tile($0077,0,0,0,1), make_block_tile($0089,0,0,0,1), make_block_tile($0097,0,0,0,1), make_block_tile($009F,0,0,0,1) ; $E8 dc.w make_block_tile($00A0,0,0,0,1), make_block_tile($0113,0,0,0,1), make_block_tile($011B,0,0,0,1), make_block_tile($0078,1,0,0,1) ; $EC dc.w make_block_tile($000F,1,0,0,1), make_block_tile($00E1,1,0,0,1), make_block_tile($00FB,1,0,0,1), make_block_tile($0128,1,0,0,1) ; $F0 dc.w make_block_tile($0063,0,0,0,1), make_block_tile($0084,0,0,0,1), make_block_tile($008D,0,0,0,1), make_block_tile($00CB,0,0,0,1) ; $F4 dc.w make_block_tile($00D7,0,0,0,1), make_block_tile($00E9,0,0,0,1), make_block_tile($0128,0,0,0,1), make_block_tile($0138,0,0,0,1) ; $F8 dc.w make_block_tile($00AE,1,0,0,1), make_block_tile($00EC,1,0,0,1), make_block_tile($0031,0,0,0,1), make_block_tile($004C,0,0,0,1) ; $FC dc.w make_block_tile($00E2,0,0,0,1), make_block_tile($00EA,0,0,0,1), make_block_tile($0064,1,0,0,1), make_block_tile($0029,0,0,0,1) ; $100 dc.w make_block_tile($002D,0,0,0,1), make_block_tile($006D,0,0,0,1), make_block_tile($0078,0,0,0,1), make_block_tile($0088,0,0,0,1) ; $104 dc.w make_block_tile($00B4,0,0,0,1), make_block_tile($00BE,0,0,0,1), make_block_tile($00CF,0,0,0,1), make_block_tile($00E1,0,0,0,1) ; $108 dc.w make_block_tile($00E4,0,0,0,1), make_block_tile($0054,1,0,0,1), make_block_tile($00D6,1,0,0,1), make_block_tile($00D7,1,0,0,1) ; $10C dc.w make_block_tile($0061,1,0,0,1), make_block_tile($012B,1,0,0,1), make_block_tile($0047,1,0,0,1), make_block_tile($0035,0,0,0,1) ; $110 dc.w make_block_tile($006A,0,0,0,1), make_block_tile($0072,0,0,0,1), make_block_tile($0073,0,0,0,1), make_block_tile($0098,0,0,0,1) ; $114 dc.w make_block_tile($00D5,0,0,0,1), make_block_tile($00D6,0,0,0,1), make_block_tile($0116,0,0,0,1), make_block_tile($011E,0,0,0,1) ; $118 dc.w make_block_tile($0126,0,0,0,1), make_block_tile($0127,0,0,0,1), make_block_tile($012F,0,0,0,1), make_block_tile($015D,0,0,0,1) ; $11C dc.w make_block_tile($0069,1,0,0,1), make_block_tile($0088,1,0,0,1), make_block_tile($0075,1,0,0,1), make_block_tile($0097,1,0,0,1) ; $120 dc.w make_block_tile($00B4,1,0,0,1), make_block_tile($00D1,1,0,0,1), make_block_tile($00D4,1,0,0,1), make_block_tile($00D5,1,0,0,1) ; $124 dc.w make_block_tile($00CB,1,0,0,1), make_block_tile($00E4,1,0,0,1), make_block_tile($0091,1,0,0,1), make_block_tile($0062,1,0,0,1) ; $128 dc.w make_block_tile($0006,1,0,0,1), make_block_tile($00B8,1,0,0,1), make_block_tile($0065,0,0,0,1), make_block_tile($006E,0,0,0,1) ; $12C dc.w make_block_tile($0071,0,0,0,1), make_block_tile($007D,0,0,0,1), make_block_tile($00D1,0,0,0,1), make_block_tile($00E7,0,0,0,1) ; $130 dc.w make_block_tile($00F9,0,0,0,1), make_block_tile($0108,0,0,0,1), make_block_tile($012E,0,0,0,1), make_block_tile($014B,0,0,0,1) ; $134 dc.w make_block_tile($0081,1,0,0,1), make_block_tile($0085,1,0,0,1), make_block_tile($0077,1,0,0,1), make_block_tile($007E,1,0,0,1) ; $138 dc.w make_block_tile($0095,1,0,0,1), make_block_tile($00DF,1,0,0,1), make_block_tile($0087,1,0,0,1), make_block_tile($006C,1,0,0,1) ; $13C dc.w make_block_tile($00F5,1,0,0,1), make_block_tile($0108,1,0,0,1), make_block_tile($0079,1,0,0,1), make_block_tile($006D,1,0,0,1) ; $140 dc.w make_block_tile($012A,1,0,0,1), make_block_tile($00AA,1,0,0,1), make_block_tile($001E,0,0,0,1), make_block_tile($0027,0,0,0,1) ; $144 dc.w make_block_tile($0046,0,0,0,1), make_block_tile($005F,0,0,0,1), make_block_tile($0070,0,0,0,1), make_block_tile($0079,0,0,0,1) ; $148 dc.w make_block_tile($009A,0,0,0,1), make_block_tile($00AA,0,0,0,1), make_block_tile($00C3,0,0,0,1), make_block_tile($00D3,0,0,0,1) ; $14C dc.w make_block_tile($00D4,0,0,0,1), make_block_tile($00DE,0,0,0,1), make_block_tile($00DF,0,0,0,1), make_block_tile($00F8,0,0,0,1) ; $150 dc.w make_block_tile($0100,0,0,0,1), make_block_tile($0101,0,0,0,1), make_block_tile($012B,0,0,0,1), make_block_tile($0133,0,0,0,1) ; $154 dc.w make_block_tile($0136,0,0,0,1), make_block_tile($0143,0,0,0,1), make_block_tile($0151,0,0,0,1), make_block_tile($002E,1,0,0,1) ; $158 dc.w make_block_tile($009E,1,0,0,1), make_block_tile($0099,1,0,0,1), make_block_tile($00D3,1,0,0,1), make_block_tile($00DD,1,0,0,1) ; $15C dc.w make_block_tile($00DE,1,0,0,1), make_block_tile($00E9,1,0,0,1), make_block_tile($00EF,1,0,0,1), make_block_tile($00F0,1,0,0,1) ; $160 dc.w make_block_tile($00F8,1,0,0,1), make_block_tile($0127,1,0,0,1), make_block_tile($00BE,1,0,0,1), make_block_tile($0096,1,0,0,1) ; $164 dc.w make_block_tile($004F,0,0,0,1), make_block_tile($006F,0,0,0,1), make_block_tile($0081,0,0,0,1), make_block_tile($008B,0,0,0,1) ; $168 dc.w make_block_tile($008E,0,0,0,1), make_block_tile($009C,0,0,0,1), make_block_tile($00A3,0,0,0,1), make_block_tile($00B3,0,0,0,1) ; $16C dc.w make_block_tile($00C0,0,0,0,1), make_block_tile($00CE,0,0,0,1), make_block_tile($00F0,0,0,0,1), make_block_tile($00F1,0,0,0,1) ; $170 dc.w make_block_tile($00F5,0,0,0,1), make_block_tile($00F7,0,0,0,1), make_block_tile($0102,0,0,0,1), make_block_tile($0104,0,0,0,1) ; $174 dc.w make_block_tile($0105,0,0,0,1), make_block_tile($0109,0,0,0,1), make_block_tile($010C,0,0,0,1), make_block_tile($0114,0,0,0,1) ; $178 dc.w make_block_tile($0118,0,0,0,1), make_block_tile($0120,0,0,0,1), make_block_tile($0124,0,0,0,1), make_block_tile($0125,0,0,0,1) ; $17C dc.w make_block_tile($012A,0,0,0,1), make_block_tile($0130,0,0,0,1), make_block_tile($0132,0,0,0,1), make_block_tile($0137,0,0,0,1) ; $180 dc.w make_block_tile($0159,0,0,0,1), make_block_tile($0165,0,0,0,1), make_block_tile($003F,1,0,0,1), make_block_tile($006B,1,0,0,1) ; $184 dc.w make_block_tile($0080,1,0,0,1), make_block_tile($0053,1,0,0,1), make_block_tile($00C6,1,0,0,1), make_block_tile($00CF,1,0,0,1) ; $188 dc.w make_block_tile($00D9,1,0,0,1), make_block_tile($00DC,1,0,0,1), make_block_tile($0056,1,0,0,1), make_block_tile($00B6,1,0,0,1) ; $18C dc.w make_block_tile($00F9,1,0,0,1), make_block_tile($0102,1,0,0,1), make_block_tile($0104,1,0,0,1), make_block_tile($0115,1,0,0,1) ; $190 dc.w make_block_tile($006A,1,0,0,1), make_block_tile($0113,1,0,0,1), make_block_tile($0072,1,0,0,1), make_block_tile($0035,1,0,0,1) ; $194 dc.w make_block_tile($0138,1,0,0,1), make_block_tile($015D,1,0,0,1), make_block_tile($0143,1,0,0,1), make_block_tile($0023,0,0,0,1) ; $198 dc.w make_block_tile($0076,0,0,0,1), make_block_tile($007B,0,0,0,1), make_block_tile($008A,0,0,0,1), make_block_tile($009D,0,0,0,1) ; $19C dc.w make_block_tile($00A6,0,0,0,1), make_block_tile($00A8,0,0,0,1), make_block_tile($00AC,0,0,0,1), make_block_tile($00B2,0,0,0,1) ; $1A0 dc.w make_block_tile($00B7,0,0,0,1), make_block_tile($00BB,0,0,0,1), make_block_tile($00BC,0,0,0,1), make_block_tile($00BD,0,0,0,1) ; $1A4 dc.w make_block_tile($00C6,0,0,0,1), make_block_tile($00E5,0,0,0,1), make_block_tile($00E8,0,0,0,1), make_block_tile($00EE,0,0,0,1) ; $1A8 dc.w make_block_tile($00F4,0,0,0,1), make_block_tile($010A,0,0,0,1), make_block_tile($010D,0,0,0,1), make_block_tile($0111,0,0,0,1) ; $1AC dc.w make_block_tile($0115,0,0,0,1), make_block_tile($011A,0,0,0,1), make_block_tile($011F,0,0,0,1), make_block_tile($0122,0,0,0,1) ; $1B0 dc.w make_block_tile($0123,0,0,0,1), make_block_tile($0139,0,0,0,1), make_block_tile($013A,0,0,0,1), make_block_tile($013C,0,0,0,1) ; $1B4 dc.w make_block_tile($0142,0,0,0,1), make_block_tile($0144,0,0,0,1), make_block_tile($0147,0,0,0,1), make_block_tile($0148,0,0,0,1) ; $1B8 dc.w make_block_tile($015E,0,0,0,1), make_block_tile($015F,0,0,0,1), make_block_tile($0163,0,0,0,1), make_block_tile($0168,0,0,0,1) ; $1BC dc.w make_block_tile($016A,0,0,0,1), make_block_tile($016C,0,0,0,1), make_block_tile($0170,0,0,0,1), make_block_tile($00E5,1,0,0,1) ; $1C0 dc.w make_block_tile($00CE,1,0,0,1), make_block_tile($00EE,1,0,0,1), make_block_tile($00F1,1,0,0,1), make_block_tile($0084,1,0,0,1) ; $1C4 dc.w make_block_tile($00FD,1,0,0,1), make_block_tile($0100,1,0,0,1), make_block_tile($00B9,1,0,0,1), make_block_tile($0117,1,0,0,1) ; $1C8 dc.w make_block_tile($0071,1,0,0,1), make_block_tile($0109,1,0,0,1), make_block_tile($010D,1,0,0,1), make_block_tile($0065,1,0,0,1) ; $1CC dc.w make_block_tile($0125,1,0,0,1), make_block_tile($0122,1,0,0,1), make_block_tile($0031,1,0,0,1), make_block_tile($003C,1,0,0,1) ; $1D0 dc.w make_block_tile($010F,1,0,0,1), make_block_tile($00C5,1,0,0,1), make_block_tile($0133,1,0,0,1), make_block_tile($0137,1,0,0,1) ; $1D4 dc.w make_block_tile($011F,1,0,0,1), make_block_tile($002E,0,0,0,1), make_block_tile($006B,0,0,0,1), make_block_tile($0082,0,0,0,1) ; $1D8 dc.w make_block_tile($0083,0,0,0,1), make_block_tile($008C,0,0,0,1), make_block_tile($0099,0,0,0,1), make_block_tile($009B,0,0,0,1) ; $1DC dc.w make_block_tile($00A2,0,0,0,1), make_block_tile($00A5,0,0,0,1), make_block_tile($00A7,0,0,0,1), make_block_tile($00A9,0,0,0,1) ; $1E0 dc.w make_block_tile($00AB,0,0,0,1), make_block_tile($00AD,0,0,0,1), make_block_tile($00B9,0,0,0,1), make_block_tile($00BA,0,0,0,1) ; $1E4 dc.w make_block_tile($00BF,0,0,0,1), make_block_tile($00C4,0,0,0,1), make_block_tile($00C5,0,0,0,1), make_block_tile($00C7,0,0,0,1) ; $1E8 dc.w make_block_tile($00C8,0,0,0,1), make_block_tile($00C9,0,0,0,1), make_block_tile($00CA,0,0,0,1), make_block_tile($00D0,0,0,0,1) ; $1EC dc.w make_block_tile($00D9,0,0,0,1), make_block_tile($00DB,0,0,0,1), make_block_tile($00EB,0,0,0,1), make_block_tile($00EC,0,0,0,1) ; $1F0 dc.w make_block_tile($00ED,0,0,0,1), make_block_tile($00EF,0,0,0,1), make_block_tile($00F2,0,0,0,1), make_block_tile($00F3,0,0,0,1) ; $1F4 dc.w make_block_tile($00F6,0,0,0,1), make_block_tile($00FA,0,0,0,1), make_block_tile($00FC,0,0,0,1), make_block_tile($00FD,0,0,0,1) ; $1F8 dc.w make_block_tile($00FE,0,0,0,1), make_block_tile($0103,0,0,0,1), make_block_tile($0106,0,0,0,1), make_block_tile($0107,0,0,0,1) ; $2FC dc.w make_block_tile($010B,0,0,0,1), make_block_tile($010E,0,0,0,1), make_block_tile($010F,0,0,0,1), make_block_tile($0110,0,0,0,1) ; $200 dc.w make_block_tile($0112,0,0,0,1), make_block_tile($0117,0,0,0,1), make_block_tile($011C,0,0,0,1), make_block_tile($011D,0,0,0,1) ; $204 dc.w make_block_tile($0121,0,0,0,1), make_block_tile($0129,0,0,0,1), make_block_tile($012C,0,0,0,1), make_block_tile($012D,0,0,0,1) ; $208 dc.w make_block_tile($0131,0,0,0,1), make_block_tile($0134,0,0,0,1), make_block_tile($0135,0,0,0,1), make_block_tile($013B,0,0,0,1) ; $20C dc.w make_block_tile($013D,0,0,0,1), make_block_tile($013E,0,0,0,1), make_block_tile($013F,0,0,0,1), make_block_tile($0140,0,0,0,1) ; $210 dc.w make_block_tile($0141,0,0,0,1), make_block_tile($0145,0,0,0,1), make_block_tile($0146,0,0,0,1), make_block_tile($0149,0,0,0,1) ; $214 dc.w make_block_tile($014A,0,0,0,1), make_block_tile($014C,0,0,0,1), make_block_tile($014D,0,0,0,1), make_block_tile($014E,0,0,0,1) ; $218 dc.w make_block_tile($014F,0,0,0,1), make_block_tile($0150,0,0,0,1), make_block_tile($0152,0,0,0,1), make_block_tile($0153,0,0,0,1) ; $21C dc.w make_block_tile($0154,0,0,0,1), make_block_tile($0155,0,0,0,1), make_block_tile($0156,0,0,0,1), make_block_tile($0157,0,0,0,1) ; $220 dc.w make_block_tile($0158,0,0,0,1), make_block_tile($015A,0,0,0,1), make_block_tile($015B,0,0,0,1), make_block_tile($015C,0,0,0,1) ; $224 dc.w make_block_tile($0160,0,0,0,1), make_block_tile($0161,0,0,0,1), make_block_tile($0162,0,0,0,1), make_block_tile($0164,0,0,0,1) ; $228 dc.w make_block_tile($0166,0,0,0,1), make_block_tile($0167,0,0,0,1), make_block_tile($0169,0,0,0,1), make_block_tile($016B,0,0,0,1) ; $22C dc.w make_block_tile($016D,0,0,0,1), make_block_tile($016E,0,0,0,1), make_block_tile($016F,0,0,0,1), make_block_tile($0171,0,0,0,1) ; $230 dc.w make_block_tile($0172,0,0,0,1), make_block_tile($0173,0,0,0,1), make_block_tile($006E,1,0,0,1), make_block_tile($007D,1,0,0,1) ; $234 dc.w make_block_tile($00C3,1,0,0,1), make_block_tile($00DB,1,0,0,1), make_block_tile($00E7,1,0,0,1), make_block_tile($00E8,1,0,0,1) ; $238 dc.w make_block_tile($00EB,1,0,0,1), make_block_tile($00ED,1,0,0,1), make_block_tile($00F2,1,0,0,1), make_block_tile($00F6,1,0,0,1) ; $23C dc.w make_block_tile($00FA,1,0,0,1), make_block_tile($00FC,1,0,0,1), make_block_tile($00FE,1,0,0,1), make_block_tile($002D,1,0,0,1) ; $240 dc.w make_block_tile($0103,1,0,0,1), make_block_tile($0106,1,0,0,1), make_block_tile($0107,1,0,0,1), make_block_tile($010B,1,0,0,1) ; $244 dc.w make_block_tile($0073,1,0,0,1), make_block_tile($009A,1,0,0,1), make_block_tile($0129,1,0,0,1), make_block_tile($012C,1,0,0,1) ; $248 dc.w make_block_tile($012D,1,0,0,1), make_block_tile($0111,1,0,0,1), make_block_tile($013C,1,0,0,1), make_block_tile($0120,1,0,0,1) ; $24C dc.w make_block_tile($0146,1,0,0,1), make_block_tile($00A9,1,0,0,1), make_block_tile($009C,1,0,0,1), make_block_tile($0116,1,0,0,1) ; $250 dc.w make_block_tile($014F,1,0,0,1), make_block_tile($014C,1,0,0,1), make_block_tile($006F,1,0,0,1), make_block_tile($0158,1,0,0,1) ; $254 dc.w make_block_tile($0156,1,0,0,1), make_block_tile($0159,1,0,0,1), make_block_tile($015A,1,0,0,1), make_block_tile($0161,1,0,0,1) ; $258 dc.w make_block_tile($007B,1,0,0,1), make_block_tile($0166,1,0,0,1), make_block_tile($011C,1,0,0,1), make_block_tile($0118,1,0,0,1) ; $25C dc.w make_block_tile($00A0,1,0,0,1), make_block_tile($00A3,1,0,0,1), make_block_tile($0167,1,0,0,1), make_block_tile($00A1,1,0,0,1) ; $260 ; These are run-length encoded pattern names. They get sent to either the ; pattern name table buffer or one region of one of the plane A name tables ; in the special stage. ; They are indexed by the third segment of the mappings in Map_SpecialStageTrack, above. ; Format: PNT,count ;word_69E6 SSPNT_RLELUT: dc.w make_block_tile($0007,0,0,0,0),$0001, make_block_tile($0001,0,0,0,0),$0001 ; $00 dc.w make_block_tile($004A,0,0,0,0),$0001, make_block_tile($0039,0,0,0,0),$0003 ; $02 dc.w make_block_tile($0001,0,0,0,0),$0005, make_block_tile($0028,0,0,0,0),$0007 ; $04 dc.w make_block_tile($002C,0,0,0,0),$0001, make_block_tile($0001,0,0,0,0),$0002 ; $06 dc.w make_block_tile($0028,0,0,0,0),$0005, make_block_tile($0039,0,0,0,0),$0001 ; $08 dc.w make_block_tile($0028,0,0,0,0),$0009, make_block_tile($0001,0,0,0,0),$0004 ; $0A dc.w make_block_tile($0028,0,0,0,0),$0006, make_block_tile($0028,0,0,0,0),$0003 ; $0C dc.w make_block_tile($004A,0,0,0,0),$0002, make_block_tile($0001,0,0,0,0),$0003 ; $0E dc.w make_block_tile($0028,0,0,0,0),$0004, make_block_tile($0039,0,0,0,0),$0002 ; $10 dc.w make_block_tile($0039,0,0,0,0),$0004, make_block_tile($0001,0,0,0,0),$0006 ; $12 dc.w make_block_tile($0007,0,0,0,0),$0002, make_block_tile($002C,0,0,0,0),$0002 ; $14 dc.w make_block_tile($0028,0,0,0,0),$0001, make_block_tile($001D,0,0,0,0),$0001 ; $16 dc.w make_block_tile($0028,0,0,0,0),$0008, make_block_tile($0028,0,0,0,0),$0002 ; $18 dc.w make_block_tile($0007,0,0,0,0),$0003, make_block_tile($0001,0,0,0,0),$0007 ; $1A dc.w make_block_tile($0028,0,0,0,0),$000B, make_block_tile($0039,0,0,0,0),$0005 ; $1C dc.w make_block_tile($001D,0,0,0,0),$0003, make_block_tile($001D,0,0,0,0),$0004 ; $1E dc.w make_block_tile($001D,0,0,0,0),$0002, make_block_tile($001D,0,0,0,0),$0005 ; $20 dc.w make_block_tile($0028,0,0,0,0),$000D, make_block_tile($000B,0,0,0,0),$0001 ; $22 dc.w make_block_tile($0028,0,0,0,0),$000A, make_block_tile($0039,0,0,0,0),$0006 ; $24 dc.w make_block_tile($0039,0,0,0,0),$0007, make_block_tile($002C,0,0,0,0),$0003 ; $26 dc.w make_block_tile($001D,0,0,0,0),$0009, make_block_tile($004A,0,0,0,0),$0003 ; $28 dc.w make_block_tile($001D,0,0,0,0),$0007, make_block_tile($0028,0,0,0,0),$000F ; $2A dc.w make_block_tile($001D,0,0,0,0),$000B, make_block_tile($001D,0,0,0,0),$0011 ; $2C dc.w make_block_tile($001D,0,0,0,0),$000D, make_block_tile($001D,0,0,0,0),$0008 ; $2E dc.w make_block_tile($0028,0,0,0,0),$0011, make_block_tile($001D,0,0,0,0),$0006 ; $30 dc.w make_block_tile($000B,0,0,0,0),$0002, make_block_tile($001D,0,0,0,0),$0015 ; $32 dc.w make_block_tile($0028,0,0,0,0),$000C, make_block_tile($001D,0,0,0,0),$000A ; $34 dc.w make_block_tile($0028,0,0,0,0),$000E, make_block_tile($0001,0,0,0,0),$0008 ; $36 dc.w make_block_tile($001D,0,0,0,0),$000F, make_block_tile($0028,0,0,0,0),$0010 ; $38 dc.w make_block_tile($0007,0,0,0,0),$0006, make_block_tile($001D,0,0,0,0),$0013 ; $3A dc.w make_block_tile($004A,0,0,0,0),$0004, make_block_tile($001D,0,0,0,0),$0017 ; $3C dc.w make_block_tile($0007,0,0,0,0),$0004, make_block_tile($000B,0,0,0,0),$0003 ; $3E ;word_6AE6 SSPNT_RLELUT_Part2: dc.w make_block_tile($001D,0,0,0,0),$001B, make_block_tile($004A,0,0,0,0),$0006 ; $40 dc.w make_block_tile($001D,0,0,0,0),$001D, make_block_tile($004A,0,0,0,0),$0005 ; $42 dc.w make_block_tile($0001,0,0,0,0),$0009, make_block_tile($0007,0,0,0,0),$0005 ; $44 dc.w make_block_tile($001D,0,0,0,0),$001E, make_block_tile($001D,0,0,0,0),$0019 ; $46 dc.w make_block_tile($0001,0,0,0,0),$0011, make_block_tile($001D,0,0,0,0),$000C ; $48 dc.w make_block_tile($001D,0,0,0,0),$007F, make_block_tile($002C,0,0,0,0),$0004 ; $4A dc.w make_block_tile($001D,0,0,0,0),$000E, make_block_tile($001D,0,0,0,0),$001C ; $4C dc.w make_block_tile($004A,0,0,0,0),$000A, make_block_tile($001D,0,0,0,0),$001A ; $4E dc.w make_block_tile($004A,0,0,0,0),$0007, make_block_tile($001D,0,0,0,0),$0018 ; $50 dc.w make_block_tile($000B,0,0,0,0),$0004, make_block_tile($001D,0,0,0,0),$0012 ; $52 dc.w make_block_tile($001D,0,0,0,0),$0010, make_block_tile($0001,0,0,0,0),$000F ; $54 dc.w make_block_tile($000B,0,0,0,0),$0005, make_block_tile($0001,0,0,0,0),$000D ; $56 dc.w make_block_tile($0001,0,0,0,0),$0013, make_block_tile($004A,0,0,0,0),$0009 ; $58 dc.w make_block_tile($004A,0,0,0,0),$000B, make_block_tile($004A,0,0,0,0),$000C ; $5A dc.w make_block_tile($002C,0,0,0,0),$0005, make_block_tile($001D,0,0,0,0),$0014 ; $5C dc.w make_block_tile($000B,0,0,0,0),$0007, make_block_tile($001D,0,0,0,0),$0016 ; $5E dc.w make_block_tile($0001,0,0,0,0),$000C, make_block_tile($0001,0,0,0,0),$000E ; $60 dc.w make_block_tile($004A,0,0,0,0),$0008, make_block_tile($001D,0,0,0,0),$005F ; $62 dc.w make_block_tile($0001,0,0,0,0),$000A, make_block_tile($000B,0,0,0,0),$0006 ; $64 dc.w make_block_tile($000B,0,0,0,0),$0008, make_block_tile($000B,0,0,0,0),$000A ; $66 dc.w make_block_tile($0039,0,0,0,0),$0008, make_block_tile($000B,0,0,0,0),$0009 ; $68 dc.w make_block_tile($002C,0,0,0,0),$0006, make_block_tile($0001,0,0,0,0),$0010 ; $6A dc.w make_block_tile($000B,0,0,0,0),$000C, make_block_tile($0001,0,0,0,0),$000B ; $6C dc.w make_block_tile($0001,0,0,0,0),$0012, make_block_tile($0007,0,0,0,0),$0007 ; $6E dc.w make_block_tile($001D,0,0,0,0),$001F, make_block_tile($0028,0,0,0,0),$0012 ; $70 dc.w make_block_tile($000B,0,0,0,0),$000B, make_block_tile($002C,0,0,0,0),$0007 ; $72 dc.w make_block_tile($002C,0,0,0,0),$000B, make_block_tile($001D,0,0,0,0),$0023 ; $74 dc.w make_block_tile($0001,0,0,0,0),$0015, make_block_tile($002C,0,0,0,0),$0008 ; $76 dc.w make_block_tile($001D,0,0,0,0),$002E, make_block_tile($001D,0,0,0,0),$003F ; $78 dc.w make_block_tile($0001,0,0,0,0),$0014, make_block_tile($000B,0,0,0,0),$000D ; $7A dc.w make_block_tile($002C,0,0,0,0),$0009, make_block_tile($002C,0,0,0,0),$000A ; $7C dc.w make_block_tile($001D,0,0,0,0),$0025, make_block_tile($001D,0,0,0,0),$0055 ; $7E dc.w make_block_tile($001D,0,0,0,0),$0071, make_block_tile($001D,0,0,0,0),$007C ; $80 dc.w make_block_tile($004A,0,0,0,0),$000D, make_block_tile($002C,0,0,0,0),$000C ; $82 dc.w make_block_tile($002C,0,0,0,0),$000F, make_block_tile($002C,0,0,0,0),$0010 ; $84 ;unknown ;byte_6BFE: dc.b $FF,$FB,$FF,$FB,$FF,$FA,$FF,$FA; 528 dc.b $FF,$FA,$FF,$FA ; 544 ; =========================================================================== ; (!) ;loc_6C0A SSTrackSetOrientation: move.b (SS_Alternate_HorizScroll_Buf).w,(SS_Last_Alternate_HorizScroll_Buf).w moveq #0,d1 movea.l (SSTrack_mappings_bitflags).w,a0 ; Get frame mappings pointer cmpa.l #MapSpec_Straight2,a0 ; Is the track rising or one of the first straight frame? blt.s + ; Branch if yes cmpa.l #MapSpec_Straight3,a0 ; Is it straight path frame 3 or higher? bge.s + ; Branch if yes ; We only get here for straight frame 2 movea.l (SS_CurrentLevelLayout).w,a5 ; Get current level layout move.b (SpecialStage_CurrentSegment).w,d1 ; Get current segment move.b (a5,d1.w),d1 ; Get segment geometry bpl.s +++ ; Branch if not flipped - st.b (SSTrack_Orientation).w ; Mark as being flipped move.b (SSTrack_drawing_index).w,d0 ; Get drawing position cmp.b (SS_player_anim_frame_timer).w,d0 ; Is it lower than the player's frame? blt.w return_6C9A ; Return if yes st.b (SS_Alternate_HorizScroll_Buf).w ; Use the alternate horizontal scroll buffer rts ; =========================================================================== + cmpa.l #MapSpec_Rise14,a0 ; Is the track one of the first 13 rising frames? blt.s + ; Branch if yes cmpa.l #MapSpec_Rise15,a0 ; Is it rising frame 15 or higher? bge.s + ; Branch if yes ; We only get here for straight frame 14 movea.l (SS_CurrentLevelLayout).w,a5 ; Get current level layout move.b (SpecialStage_CurrentSegment).w,d1 ; Get current segment move.b (a5,d1.w),d1 ; Get segment geometry bpl.s ++ ; Branch if not flipped bra.s - ; =========================================================================== + cmpa.l #MapSpec_Drop6,a0 ; Is the track before drop frame 6? blt.s return_6C9A ; Return is yes cmpa.l #MapSpec_Drop7,a0 ; Is it drop frame 7 or higher? bge.s return_6C9A ; Return if yes ; We only get here for straight frame 6 movea.l (SS_CurrentLevelLayout).w,a5 ; Get current level layout move.b (SpecialStage_CurrentSegment).w,d1 ; Get current segment move.b (a5,d1.w),d1 ; Get segment geometry bmi.s - ; Branch if flipped + sf.b (SSTrack_Orientation).w ; Mark as being unflipped move.b (SSTrack_drawing_index).w,d0 ; Get drawing position cmp.b (SS_player_anim_frame_timer).w,d0 ; Is it lower than the player's frame? blt.s return_6C9A ; Return if yes sf.b (SS_Alternate_HorizScroll_Buf).w ; Don't use the alternate horizontal scroll buffer return_6C9A: rts ; End of function SSTrack_Draw ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Initialize the PNT and H scroll table buffers. ssInitTableBuffers: lea (SS_Horiz_Scroll_Buf_1).w,a1 lea (SS_Horiz_Scroll_Buf_2).w,a2 moveq #0,d0 ; Scroll of 0 for PNTA and PNTB on lines 0 and 1 (normal) or lines 6 and 7 (flipped) moveq #0,d1 ; Scroll of 0 for PNTB on lines 2 and 3 (normal) or lines 4 and 5 (flipped) moveq #0,d2 ; Scroll of 0 for PNTB on lines 4 and 5 (normal) or lines 2 and 3 (flipped) moveq #0,d3 ; Scroll of 0 for PNTB on lines 6 and 7 (normal) or lines 0 and 1 (flipped) move.w #-$100,d1 ; Scroll of 3 screens for PNTA on lines 2 and 3 (normal) or lines 4 and 5 (flipped) move.w #-$200,d2 ; Scroll of 2 screens for PNTA on lines 4 and 5 (normal) or lines 2 and 3 (flipped) move.w #-$300,d3 ; Scroll of 1 screen for PNTA on lines 6 and 7 (normal) or lines 0 and 1 (flipped) swap d1 swap d2 swap d3 moveq #$1F,d4 - move.l d0,(a1)+ move.l d0,(a1)+ move.l d1,(a1)+ move.l d1,(a1)+ move.l d2,(a1)+ move.l d2,(a1)+ move.l d3,(a1)+ move.l d3,(a1)+ move.l d3,(a2)+ move.l d3,(a2)+ move.l d2,(a2)+ move.l d2,(a2)+ move.l d1,(a2)+ move.l d1,(a2)+ move.l d0,(a2)+ move.l d0,(a2)+ dbf d4,- rts ; End of function ssInitTableBuffers ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Load compressed special stage data into RAM, or VRAM for the art. ssLdComprsdData: lea (ArtKos_Special).l,a0 lea (Chunk_Table).l,a1 bsr.w KosDec move.l #vdpComm(tiles_to_bytes(ArtTile_VRAM_Start),VRAM,WRITE),(VDP_control_port).l lea (VDP_data_port).l,a1 movea.l #Chunk_Table,a0 move.w (a0)+,d0 subq.w #1,d0 - rept 7 move.l (a0),(a1) endm move.l (a0)+,(a1) dbf d0,- lea (MiscKoz_SpecialPerspective).l,a0 lea (SSRAM_MiscKoz_SpecialPerspective).l,a1 bsr.w KosDec lea (MiscKoz_SpecialLevelLayout).l,a0 lea (SSRAM_MiscNem_SpecialLevelLayout).w,a4 bsr.w NemDecToRAM lea (MiscKoz_SpecialObjectLocations).l,a0 lea (SSRAM_MiscKoz_SpecialObjectLocations).w,a1 bsr.w KosDec rts ; End of function ssLdComprsdData ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_6D52 SSPlaneB_Background: move #$2700,sr movea.l #Chunk_Table,a1 lea (MapEng_SpecialBackBottom).l,a0 move.w #make_art_tile(ArtTile_ArtNem_SpecialBack,0,0),d0 bsr.w EniDec movea.l #Chunk_Table+$400,a1 lea (MapEng_SpecialBack).l,a0 move.w #make_art_tile(ArtTile_ArtNem_SpecialBack,0,0),d0 bsr.w EniDec lea (Chunk_Table).l,a1 move.l #vdpComm(VRAM_SS_Plane_B_Name_Table + $0000,VRAM,WRITE),d0 moveq #$1F,d1 moveq #$1F,d2 jsrto (PlaneMapToVRAM_H80_SpecialStage).l, PlaneMapToVRAM_H80_SpecialStage lea (Chunk_Table).l,a1 move.l #vdpComm(VRAM_SS_Plane_B_Name_Table + $0040,VRAM,WRITE),d0 moveq #$1F,d1 moveq #$1F,d2 jsrto (PlaneMapToVRAM_H80_SpecialStage).l, PlaneMapToVRAM_H80_SpecialStage lea (Chunk_Table).l,a1 move.l #vdpComm(VRAM_SS_Plane_B_Name_Table + $0080,VRAM,WRITE),d0 moveq #$1F,d1 moveq #$1F,d2 jsrto (PlaneMapToVRAM_H80_SpecialStage).l, PlaneMapToVRAM_H80_SpecialStage lea (Chunk_Table).l,a1 move.l #vdpComm(VRAM_SS_Plane_B_Name_Table + $00C0,VRAM,WRITE),d0 moveq #$1F,d1 moveq #$1F,d2 jsrto (PlaneMapToVRAM_H80_SpecialStage).l, PlaneMapToVRAM_H80_SpecialStage move #$2300,sr rts ; End of function SSPlaneB_Background ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_6DD4 SSDecompressPlayerArt: lea (ArtNem_SpecialSonicAndTails).l,a0 lea (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF).l,a4 bra.w NemDecToRAM ; End of function SSDecompressPlayerArt ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_6DE4 SS_ScrollBG: bsr.w SSPlaneB_SetHorizOffset bsr.w SSTrack_SetVscroll rts ; End of function SS_ScrollBG ; =========================================================================== ; special stage background vertical and horizontal scroll offsets off_6DEE: offsetTable offsetTableEntry.w byte_6E04 ; 0 offsetTableEntry.w byte_6E09 ; 1 offsetTableEntry.w byte_6E0E ; 2 offsetTableEntry.w byte_6E13 ; 3 offsetTableEntry.w byte_6E18 ; 4 offsetTableEntry.w byte_6E1D ; 5 offsetTableEntry.w byte_6E22 ; 6 offsetTableEntry.w byte_6E27 ; 7 offsetTableEntry.w byte_6E2C ; 8 offsetTableEntry.w byte_6E31 ; 9 offsetTableEntry.w byte_6E36 ; $A byte_6E04: dc.b 2, 2, 2, 2, 2 byte_6E09: dc.b 4, 4, 5, 4, 5 byte_6E0E: dc.b $B, $B, $B, $B, $C byte_6E13: dc.b 0, 0, 1, 0, 0 byte_6E18: dc.b 1, 1, 1, 1, 1 byte_6E1D: dc.b 9, 9, 8, 9, 9 byte_6E22: dc.b 9, 9, 9, 9, $A byte_6E27: dc.b 7, 7, 6, 7, 7 byte_6E2C: dc.b 0, 1, 1, 1, 0 byte_6E31: dc.b 4, 3, 3, 3, 4 byte_6E36: dc.b 0, 0,$FF, 0, 0 even ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_6E3C SSPlaneB_SetHorizOffset: moveq #0,d7 moveq #0,d6 moveq #0,d0 move.b (SSTrack_last_anim_frame).w,d2 ; Get last track animation frame move.b (SSTrack_anim).w,d0 ; Get current track animation add.w d0,d0 ; Convert it to an index move.w off_6E54(pc,d0.w),d0 jmp off_6E54(pc,d0.w) ; =========================================================================== off_6E54: offsetTable offsetTableEntry.w + ; 0 ; Turn, then rise offsetTableEntry.w + ; 1 ; Turn, then drop offsetTableEntry.w + ; 2 ; Turn, then straight offsetTableEntry.w ++ ; 3 ; rts ; Straight offsetTableEntry.w ++ ; 4 ; rts ; Straight, then turn ; =========================================================================== + moveq #0,d1 cmpi.b #1,d2 ; Was the last frame the first in this segment? blt.s ++ ; Branch if yes moveq #2,d1 cmpi.b #2,d2 ; Was the last frame frame 1? blt.s ++ ; Branch if yes moveq #4,d1 cmpi.b #$A,d2 ; Was the last frame less than $A? blt.s ++ ; Branch if yes moveq #2,d1 cmpi.b #$B,d2 ; Was the last frame $A? blt.s ++ ; Branch if yes moveq #0,d1 cmpi.b #$C,d2 ; Was the last frame $B? blt.s ++ ; Branch if yes + rts ; =========================================================================== + moveq #0,d0 moveq #0,d2 move.b (SSTrack_drawing_index).w,d0 ; Get drawing position lea_ off_6DEE,a0 ; a0 = pointer to background scroll data adda.w (a0,d1.w),a0 ; a0 = pointer to background scroll data for current animation frame move.b (a0,d0.w),d2 ; Get background offset for current frame duration tst.b (SS_Last_Alternate_HorizScroll_Buf).w ; Was the alternate horizontal scroll buffer used last time? bne.s + ; Branch if yes tst.b (SS_Alternate_HorizScroll_Buf).w ; Is the alternate horizontal scroll buffer being used now? beq.s +++ ; Branch if not bra.s ++ ; =========================================================================== + tst.b (SS_Alternate_HorizScroll_Buf).w ; Is the alternate horizontal scroll buffer still being used? bne.s ++ ; Branch if yes lea (SS_Horiz_Scroll_Buf_1 + 2).w,a1 ; Load horizontal scroll buffer for PNT B bra.s +++ ; =========================================================================== + lea (SS_Horiz_Scroll_Buf_2 + 2).w,a1 ; Load alternate horizontal scroll buffer for PNT B neg.w d2 ; Change the sign of the background offset bra.s ++ ; =========================================================================== + lea (SS_Horiz_Scroll_Buf_1 + 2).w,a1 ; Load horizontal scroll buffer for PNT B tst.b (SS_Alternate_HorizScroll_Buf).w ; Is the alternate horizontal scroll buffer being used now? beq.s + ; Branch if not lea (SS_Horiz_Scroll_Buf_2 + 2).w,a1 ; Load alternate horizontal scroll buffer for PNT B neg.w d2 ; Change the sign of the background offset + move.w #$FF,d0 ; 256 lines - sub.w d2,(a1)+ ; Change current line's offset adda_.l #2,a1 ; Skip PNTA entry dbf d0,- rts ; End of function SSPlaneB_SetHorizOffset ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_6EE0 SSTrack_SetVscroll: move.w (Vscroll_Factor_BG).w,(SSTrack_LastVScroll).w ; Save last vertical scroll value moveq #0,d7 ; Set flag to decrease vertical scroll moveq #0,d0 moveq #0,d2 move.b (SSTrack_last_anim_frame).w,d2 ; Get last track animation frame move.b (SSTrack_anim).w,d0 ; Get current track animation add.w d0,d0 ; Convert it to index move.w off_6EFE(pc,d0.w),d0 jmp off_6EFE(pc,d0.w) ; =========================================================================== off_6EFE: offsetTable offsetTableEntry.w loc_6F0A ; 0 ; Turn, then rise offsetTableEntry.w loc_6F2A ; 1 ; Turn, then drop offsetTableEntry.w + ; 2 ; rts ; Turn, then straight offsetTableEntry.w loc_6F4C ; 3 ; Straight offsetTableEntry.w + ; 4 ; rts ; Straight, then turn ; =========================================================================== + rts ; =========================================================================== loc_6F0A: move.b +(pc,d2.w),d1 ; Get current frame's vertical scroll offset bpl.s SSTrack_ApplyVscroll ; Branch if positive rts ; =========================================================================== ; Special stage vertical scroll index for 'turn, then rise' animation + dc.b -1 dc.b -1 ; 1 dc.b -1 ; 2 dc.b -1 ; 3 dc.b -1 ; 4 dc.b -1 ; 5 dc.b -1 ; 6 dc.b -1 ; 7 dc.b -1 ; 8 dc.b -1 ; 9 dc.b 8 ; 10 dc.b 8 ; 11 dc.b 2 ; 12 dc.b 4 ; 13 dc.b 4 ; 14 dc.b 4 ; 15 dc.b 4 ; 16 dc.b 4 ; 17 dc.b 4 ; 18 dc.b $A ; 19 dc.b $C ; 20 dc.b $E ; 21 dc.b $12 ; 22 dc.b $10 ; 23 ; =========================================================================== loc_6F2A: st d7 ; Set flag to increase vertical scroll move.b +(pc,d2.w),d1 ; Get current frame's vertical scroll offset bpl.s SSTrack_ApplyVscroll ; Branch if positive rts ; =========================================================================== ; Special stage vertical scroll index for 'turn, then drop' animation + dc.b -1 dc.b -1 ; 1 dc.b -1 ; 2 dc.b -1 ; 3 dc.b -1 ; 4 dc.b -1 ; 5 dc.b -1 ; 6 dc.b -1 ; 7 dc.b -1 ; 8 dc.b -1 ; 9 dc.b -1 ; 10 dc.b $10 ; 11 dc.b $12 ; 12 dc.b $E ; 13 dc.b $C ; 14 dc.b $A ; 15 dc.b 4 ; 16 dc.b 4 ; 17 dc.b 4 ; 18 dc.b 4 ; 19 dc.b 4 ; 20 dc.b 4 ; 21 dc.b 2 ; 22 dc.b 0 ; 23 ; =========================================================================== loc_6F4C: tst.b (SS_Pause_Only_flag).w ; Is the game paused? bne.s + ; rts ; Return if yes move.b ++(pc,d2.w),d1 ; Get current frame's vertical scroll offset bpl.s SSTrack_ApplyVscroll ; Branch if positive + rts ; =========================================================================== ; Special stage vertical scroll index for 'straight' animation -- bobbing up and down + rept 4 dc.b 6 dc.b 6 dc.b $14 dc.b $14 endm ; =========================================================================== ;loc_6F6A SSTrack_ApplyVscroll: moveq #0,d0 moveq #0,d2 move.b (SSTrack_drawing_index).w,d0 ; Get drawing position lea_ off_6DEE,a0 ; a0 = pointer to background scroll data adda.w (a0,d1.w),a0 ; a0 = pointer to background scroll data for current animation frame move.b (a0,d0.w),d2 ; Get background offset for current frame duration tst.b d7 ; Are we supposed to increase the vertical scroll? bpl.s + ; Branch if not add.w d2,(Vscroll_Factor_BG).w ; Increase vertical scroll rts ; =========================================================================== + sub.w d2,(Vscroll_Factor_BG).w ; Decrease vertical scroll rts ; End of function SSTrack_SetVscroll ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_6F8E: SSSingleObjLoad: lea (SS_Dynamic_Object_RAM).w,a1 move.w #(SS_Dynamic_Object_RAM_End-SS_Dynamic_Object_RAM)/object_size-1,d5 - tst.b id(a1) beq.s + ; rts lea next_object(a1),a1 ; a1=object dbf d5,- + rts ; End of function sub_6F8E ; =========================================================================== ;loc_6FA4: SSSingleObjLoad2: movea.l a0,a1 move.w #SS_Dynamic_Object_RAM_End,d5 sub.w a0,d5 if object_size=$40 lsr.w #6,d5 else divu.w #object_size,d5 endif subq.w #1,d5 bcs.s + ; rts - tst.b id(a1) beq.s + ; rts lea next_object(a1),a1 dbf d5,- + rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 5E - HUD from Special Stage ; ---------------------------------------------------------------------------- ; Sprite_6FC0: Obj5E: move.b routine(a0),d0 bne.w JmpTo_DisplaySprite move.l #Obj5E_MapUnc_7070,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_SpecialHUD,0,0),art_tile(a0) move.b #4,render_flags(a0) move.b #0,priority(a0) move.b #1,routine(a0) bset #6,render_flags(a0) moveq #0,d1 tst.b (SS_2p_Flag).w beq.s + addq.w #6,d1 tst.b (Graphics_Flags).w bpl.s ++ addq.w #1,d1 bra.s ++ ; --------------------------------------------------------------------------- + move.w (Player_mode).w,d1 andi.w #3,d1 tst.b (Graphics_Flags).w bpl.s + addq.w #3,d1 ; set special stage tails name to "TAILS" instead of MILES + add.w d1,d1 moveq #0,d2 moveq #0,d3 lea (SSHUDLayout).l,a1 lea sub2_x_pos(a0),a2 adda.w (a1,d1.w),a1 move.b (a1)+,d3 move.b d3,mainspr_childsprites(a0) subq.w #1,d3 moveq #0,d0 move.b (a1)+,d0 - move.w d0,(a2,d2.w) move.b (a1)+,sub2_mapframe-sub2_x_pos(a2,d2.w) ; sub2_mapframe addq.w #next_subspr,d2 dbf d3,- rts ; =========================================================================== ; off_7042: SSHUDLayout: offsetTable offsetTableEntry.w SSHUD_SonicMilesTotal ; 0 offsetTableEntry.w SSHUD_Sonic ; 1 offsetTableEntry.w SSHUD_Miles ; 2 offsetTableEntry.w SSHUD_SonicTailsTotal ; 3 offsetTableEntry.w SSHUD_Sonic_2 ; 4 offsetTableEntry.w SSHUD_Tails ; 5 offsetTableEntry.w SSHUD_SonicMiles ; 6 offsetTableEntry.w SSHUD_SonicTails ; 7 ; byte_7052: SSHUD_SonicMilesTotal: dc.b 3 ; Sprite count dc.b $80 ; X-pos dc.b 0, 1, 3 ; Sprite 1 frame, Sprite 2 frame, etc ; byte_7057: SSHUD_Sonic: dc.b 1 dc.b $D4 dc.b 0 ; byte_705A: SSHUD_Miles: dc.b 1 dc.b $38 dc.b 1 ; byte_705D: SSHUD_SonicTailsTotal: dc.b 3 dc.b $80 dc.b 0, 2, 3 ; byte_7062: SSHUD_Sonic_2: dc.b 1 dc.b $D4 dc.b 0 ; byte_7065: SSHUD_Tails: dc.b 1 dc.b $38 dc.b 2 ; 2 player ; byte_7068: SSHUD_SonicMiles: dc.b 2 dc.b $80 dc.b 0, 1 ; byte_706C: SSHUD_SonicTails: dc.b 2 dc.b $80 dc.b 0, 2 ; ----------------------------------------------------------------------------------- ; sprite mappings ; ----------------------------------------------------------------------------------- Obj5E_MapUnc_7070: BINCLUDE "mappings/sprite/obj5E.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 5F - Start banner/"Ending controller" from Special Stage ; ---------------------------------------------------------------------------- ; Sprite_70F0: Obj5F: moveq #0,d0 move.b routine(a0),d0 move.w Obj5F_Index(pc,d0.w),d1 jmp Obj5F_Index(pc,d1.w) ; =========================================================================== ; off_70FE: Obj5F_Index: offsetTable offsetTableEntry.w Obj5F_Init ; 0 offsetTableEntry.w Obj5F_Main ; 2 offsetTableEntry.w loc_71B4 ; 4 offsetTableEntry.w loc_710A ; 6 offsetTableEntry.w return_723E ; 8 offsetTableEntry.w loc_7218 ; $A ; =========================================================================== loc_710A: moveq #0,d0 move.b angle(a0),d0 bsr.w CalcSine muls.w objoff_14(a0),d0 muls.w objoff_14(a0),d1 asr.w #8,d0 asr.w #8,d1 add.w d1,x_pos(a0) add.w d0,y_pos(a0) cmpi.w #0,x_pos(a0) blt.w JmpTo_DeleteObject cmpi.w #$100,x_pos(a0) bgt.w JmpTo_DeleteObject cmpi.w #0,y_pos(a0) blt.w JmpTo_DeleteObject if removeJmpTos JmpTo_DisplaySprite endif jmpto (DisplaySprite).l, JmpTo_DisplaySprite ; =========================================================================== ; loc_714A: Obj5F_Init: tst.b (SS_2p_Flag).w beq.s + move.w #8,d0 jsrto (Obj5A_PrintPhrase).l, JmpTo_Obj5A_PrintPhrase + move.w #$80,x_pos(a0) move.w #-$40,y_pos(a0) move.w #$100,y_vel(a0) move.l #Obj5F_MapUnc_7240,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_SpecialStart,0,0),art_tile(a0) move.b #4,render_flags(a0) move.b #1,priority(a0) move.b #2,routine(a0) ; loc_718A: Obj5F_Main: jsrto (ObjectMove).l, JmpTo_ObjectMove cmpi.w #$48,y_pos(a0) blt.w JmpTo_DisplaySprite move.w #0,y_vel(a0) move.w #$48,y_pos(a0) move.b #4,routine(a0) move.b #$F,objoff_2A(a0) jmpto (DisplaySprite).l, JmpTo_DisplaySprite ; =========================================================================== loc_71B4: subi_.b #1,objoff_2A(a0) if ~~removeJmpTos bne.w JmpTo_DisplaySprite else bne.s JmpTo_DisplaySprite endif moveq #6,d6 ; WARNING: the build script needs editing if you rename this label word_728C_user: lea (Obj5F_MapUnc_7240+$4C).l,a2 ; word_728C moveq #2,d3 move.w #8,objoff_14(a0) move.b #6,routine(a0) - bsr.w SSSingleObjLoad bne.s + moveq #0,d0 move.w #bytesToLcnt(object_size),d1 - move.l (a0,d0.w),(a1,d0.w) addq.w #4,d0 dbf d1,- if object_size&3 move.w (a0,d0.w),(a1,d0.w) endif move.b d3,mapping_frame(a1) addq.w #1,d3 move.w #-$28,d2 move.w 8(a2),d1 bsr.w CalcAngle move.b d0,angle(a1) lea $A(a2),a2 + dbf d6,-- move.b #$A,routine(a0) move.w #$1E,objoff_2A(a0) rts ; =========================================================================== loc_7218: subi_.w #1,objoff_2A(a0) bpl.s +++ ; rts tst.b (SS_2p_Flag).w beq.s + move.w #$A,d0 jsrto (Obj5A_PrintPhrase).l, JmpTo_Obj5A_PrintPhrase bra.s ++ ; =========================================================================== + jsrto (Obj5A_CreateRingReqMessage).l, JmpTo_Obj5A_CreateRingReqMessage + st.b (SpecialStage_Started).w jmpto (DeleteObject).l, JmpTo_DeleteObject ; =========================================================================== + rts ; =========================================================================== if removeJmpTos JmpTo_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== return_723E: rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ; WARNING: the build script needs editing if you rename this label ; or if you change the meaning of frame 2 in these mappings Obj5F_MapUnc_7240: BINCLUDE "mappings/sprite/obj5F_a.bin" ; ----------------------------------------------------------------------------------- ; sprite mappings ; ----------------------------------------------------------------------------------- Obj5F_MapUnc_72D2: BINCLUDE "mappings/sprite/obj5F_b.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 87 - Number of rings in Special Stage ; ---------------------------------------------------------------------------- ; Sprite_7356: Obj87: moveq #0,d0 move.b objoff_A(a0),d0 move.w Obj87_Index(pc,d0.w),d1 jmp Obj87_Index(pc,d1.w) ; =========================================================================== ; off_7364: Obj87_Index: offsetTable offsetTableEntry.w Obj87_Init ; 0 offsetTableEntry.w loc_7480 ; 2 offsetTableEntry.w loc_753E ; 4 offsetTableEntry.w loc_75DE ; 6 ; =========================================================================== ; loc_736C: Obj87_Init: move.b #2,objoff_A(a0) ; => loc_7480 move.l #Obj5F_MapUnc_72D2,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_SpecialHUD,2,0),art_tile(a0) move.b #4,render_flags(a0) bset #6,render_flags(a0) move.b #2,mainspr_childsprites(a0) move.w #$20,d0 moveq #0,d1 lea sub2_x_pos(a0),a1 move.w #$48,(a1) ; sub2_x_pos move.w d0,sub2_y_pos-sub2_x_pos(a1) ; sub2_y_pos move.w d1,mainspr_height-sub2_x_pos(a1) ; mainspr_height and sub2_mapframe move.w #$E0,sub3_x_pos-sub2_x_pos(a1) ; sub3_x_pos move.w d0,sub3_y_pos-sub2_x_pos(a1) ; sub3_y_pos move.w d1,mapping_frame-sub2_x_pos(a1) ; mapping_frame and sub3_mapframe move.w d0,sub4_y_pos-sub2_x_pos(a1) ; sub4_y_pos move.w d0,sub5_y_pos-sub2_x_pos(a1) ; sub5_y_pos move.w d0,sub6_y_pos-sub2_x_pos(a1) ; sub6_y_pos move.w d0,sub7_y_pos-sub2_x_pos(a1) ; sub7_y_pos tst.b (SS_2p_Flag).w bne.s +++ cmpi.w #0,(Player_mode).w beq.s + subi_.b #1,mainspr_childsprites(a0) move.w #$94,(a1) ; sub2_x_pos rts ; =========================================================================== + bsr.w SSSingleObjLoad bne.s + ; rts move.b #ObjID_SSNumberOfRings,id(a1) ; load obj87 move.b #4,objoff_A(a1) ; => loc_753E move.l #Obj5F_MapUnc_72D2,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_SpecialHUD,2,0),art_tile(a1) move.b #4,render_flags(a1) bset #6,render_flags(a1) move.b #1,mainspr_childsprites(a1) lea sub2_x_pos(a1),a2 move.w #$80,(a2) ; sub2_x_pos move.w d0,sub2_y_pos-sub2_x_pos(a2) ; sub2_y_pos move.w d1,mainspr_height-sub2_x_pos(a2) ; mainspr_height and sub2_mapframe move.w d0,sub3_y_pos-sub2_x_pos(a2) ; sub3_y_pos move.w d0,sub4_y_pos-sub2_x_pos(a2) ; sub4_y_pos / rts ; =========================================================================== + bsr.w SSSingleObjLoad bne.s - ; rts move.b #ObjID_SSNumberOfRings,id(a1) ; load obj87 move.b #6,objoff_A(a1) ; => loc_75DE move.l #Obj5F_MapUnc_72D2,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_SpecialHUD,2,0),art_tile(a1) move.b #4,render_flags(a1) bset #6,render_flags(a1) move.b #0,mainspr_childsprites(a1) lea sub2_x_pos(a1),a2 move.w #$2C,d0 move.w #$A,d1 move.w d0,sub2_y_pos-sub2_x_pos(a2) ; sub2_y_pos move.w d1,mainspr_height-sub2_x_pos(a2) ; mainspr_height and sub2_mapframe move.w d0,sub3_y_pos-sub2_x_pos(a2) ; sub3_y_pos move.w d1,mapping_frame-sub2_x_pos(a2) ; mapping_frame and sub3_mapframe move.w d0,sub4_y_pos-sub2_x_pos(a2) ; sub4_y_pos move.w d1,sub4_mapframe-1-sub2_x_pos(a2) ; something and sub4_mapframe rts ; =========================================================================== loc_7480: moveq #0,d0 moveq #0,d3 moveq #0,d5 lea sub2_x_pos(a0),a1 movea.l a1,a2 addq.w #5,a2 ; a2 = sub2_mapframe(a0) cmpi.w #2,(Player_mode).w beq.s loc_74EA move.b (MainCharacter+ss_rings_hundreds).w,d0 beq.s + addq.w #1,d3 move.b d0,(a2) lea next_subspr(a2),a2 + move.b (MainCharacter+ss_rings_tens).w,d0 tst.b d3 bne.s + tst.b d0 beq.s ++ + addq.w #1,d3 move.b d0,(a2) lea next_subspr(a2),a2 + addq.w #1,d3 move.b (MainCharacter+ss_rings_units).w,(a2) lea next_subspr(a2),a2 move.w d3,d4 subq.w #1,d4 move.w #$48,d1 tst.w (Player_mode).w beq.s + addi.w #$54,d1 / move.w d1,(a1,d5.w) addi_.w #8,d1 addq.w #next_subspr,d5 dbf d4,- cmpi.w #1,(Player_mode).w beq.s loc_7536 loc_74EA: moveq #0,d0 moveq #0,d4 move.b (Sidekick+ss_rings_hundreds).w,d0 beq.s + addq.w #1,d4 move.b d0,(a2) lea next_subspr(a2),a2 + move.b (Sidekick+ss_rings_tens).w,d0 tst.b d4 bne.s + tst.b d0 beq.s ++ + addq.w #1,d4 move.b d0,(a2) lea next_subspr(a2),a2 + move.b (Sidekick+ss_rings_units).w,(a2) addq.w #1,d4 add.w d4,d3 subq.w #1,d4 move.w #$E0,d1 tst.w (Player_mode).w beq.s + subi.w #$44,d1 / move.w d1,(a1,d5.w) addi_.w #8,d1 addq.w #6,d5 dbf d4,- loc_7536: move.b d3,mainspr_childsprites(a0) jmpto (DisplaySprite).l, JmpTo_DisplaySprite ; =========================================================================== loc_753E: moveq #0,d0 moveq #0,d1 moveq #0,d2 moveq #1,d3 move.b (MainCharacter+ss_rings_units).w,d0 add.b (Sidekick+ss_rings_units).w,d0 move.b (MainCharacter+ss_rings_tens).w,d1 add.b (Sidekick+ss_rings_tens).w,d1 move.b (MainCharacter+ss_rings_hundreds).w,d2 add.b (Sidekick+ss_rings_hundreds).w,d2 cmpi.b #10,d0 blo.s + addq.w #1,d1 subi.b #10,d0 + tst.b d1 beq.s ++ cmpi.b #10,d1 blo.s + addi_.b #1,d2 subi.b #10,d1 + addq.w #1,d3 tst.b d2 beq.s ++ addq.w #1,d3 bra.s ++ ; =========================================================================== + tst.b d2 beq.s + addq.w #2,d3 + lea sub2_x_pos(a0),a1 move.b d3,mainspr_childsprites(a0) cmpi.b #2,d3 blt.s + beq.s ++ move.w #$78,(a1) ; sub2_x_pos move.b d2,sub2_mapframe-sub2_x_pos(a1) ; sub2_mapframe move.w #$80,sub3_x_pos-sub2_x_pos(a1) ; sub3_x_pos move.b d1,sub3_mapframe-sub2_x_pos(a1) ; sub3_mapframe move.w #$88,sub4_x_pos-sub2_x_pos(a1) ; sub4_x_pos move.b d0,sub4_mapframe-sub2_x_pos(a1) ; sub4_mapframe jmpto (DisplaySprite).l, JmpTo_DisplaySprite ; =========================================================================== + move.w #$80,(a1) ; sub2_x_pos move.b d0,sub2_mapframe-sub2_x_pos(a1) ; sub2_mapframe jmpto (DisplaySprite).l, JmpTo_DisplaySprite ; =========================================================================== + move.w #$7C,(a1) ; sub2_x_pos move.b d1,sub2_mapframe-sub2_x_pos(a1) ; sub2_mapframe move.w #$84,sub3_x_pos-sub2_x_pos(a1) ; sub3_x_pos move.b d0,sub3_mapframe-sub2_x_pos(a1) ; sub3_mapframe jmpto (DisplaySprite).l, JmpTo_DisplaySprite ; =========================================================================== loc_75DE: move.b (SS_2P_BCD_Score).w,d0 bne.s + rts ; =========================================================================== + lea sub2_x_pos(a0),a1 moveq #0,d2 move.b d0,d1 andi.b #$F0,d0 beq.s + addq.w #1,d2 move.w #$20,(a1) ; sub2_x_pos lea next_subspr(a1),a1 subi.b #$10,d0 beq.s + addq.w #1,d2 move.w #$30,(a1) ; sub3_x_pos lea next_subspr(a1),a1 subi.b #$10,d0 beq.s + addq.w #1,d2 move.w #$40,(a1) ; sub4_x_pos bra.s ++ ; =========================================================================== + andi.b #$F,d1 beq.s + addq.w #1,d2 move.w #$B8,(a1) ; sub?_x_pos lea next_subspr(a1),a1 subi_.b #1,d1 beq.s + addq.w #1,d2 move.w #$C8,(a1) ; sub?_x_pos lea next_subspr(a1),a1 subi_.b #1,d1 beq.s + addq.w #1,d2 move.w #$D8,(a1) ; sub?_x_pos + move.b d2,mainspr_childsprites(a0) jmpto (DisplaySprite).l, JmpTo_DisplaySprite ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_7650 SSSetGeometryOffsets: move.b (SSTrack_drawing_index).w,d0 ; Get drawing position cmp.b (SS_player_anim_frame_timer).w,d0 ; Compare to player frame duration beq.s + ; If both are equal, branch rts ; =========================================================================== + moveq #0,d0 move.b (SSTrack_mapping_frame).w,d0 ; Get current track mapping frame add.w d0,d0 ; Convert to index lea SSCurveOffsets(pc,d0.w),a2 ; Load current curve offsets into a2 move.b (a2)+,d0 ; Get x offset tst.b (SSTrack_Orientation).w ; Is track flipped? beq.s + ; Branch if not neg.b d0 ; Change sign of offset + ext.w d0 ; Extend to word addi.w #$80,d0 ; Add 128 (why?) move.w d0,(SS_Offset_X).w ; Set X geometry offset move.b (a2),d0 ; Get y offset ext.w d0 ; Extend to word addi.w #$36,d0 ; Add $36 (why?) move.w d0,(SS_Offset_Y).w ; Set Y geometry offset rts ; End of function SSSetGeometryOffsets ; =========================================================================== ; Position offsets to sort-of rotate the plane sonic/tails are in ; when the special stage track is curving, so they follow it better. ; Each word seems to be (x_offset, y_offset) ; See also Ani_SpecialStageTrack. SSCurveOffsets: ; word_768A: dc.b $13, 0, $13, 0, $13, 0, $13, 0 ; $00 dc.b 9, -$A, 0,-$1C, 0,-$1C, 0,-$20 ; $04 dc.b 0,-$24, 0,-$2A, 0,-$10, 0, 6 ; $08 dc.b 0, $E, 0, $10, 0, $12, 0, $12 ; $0C dc.b 9, $12 ; $10; upward curve dc.b 0, 0, 0, 0, 0, 0, 0, 0 ; $11; straight dc.b $13, 0, $13, 0, $13, 0, $13, 0 ; $15 dc.b $B, $C, 0, $C, 0, $12, 0, $A ; $19 dc.b 0, 8, 0, 2, 0, $10, 0,-$20 ; $1D dc.b 0,-$1F, 0,-$1E, 0,-$1B, 0,-$18 ; $21 dc.b 0, -$E ; $25; downward curve dc.b $13, 0, $13, 0, $13, 0, $13, 0 ; $26 dc.b $13, 0, $13, 0 ; $2B; turning dc.b $13, 0, $13, 0, $13, 0, $13, 0 ; $2C dc.b $B, 0 ; $30; exit turn dc.b 0, 0, 0, 0, 0, 0, 0, 0 ; $31 dc.b 0, 0, 0, 0, 3, 0 ; $35; straight ; =========================================================================== ; Subroutine to advance to the next act and get an encoded version ; of the ring requirements. ; Output: ; d0, d1: Binary coded decimal version of ring requirements (maximum of 299 rings) ; d2: Number of digits in the ring requirements - 1 (minimum 2 digits) ;loc_76FA SSStartNewAct: moveq #0,d1 moveq #1,d2 move.w (Current_Special_StageAndAct).w,d0 move.b d0,d1 lsr.w #8,d0 add.w d0,d0 add.w d0,d0 add.w d1,d0 tst.w (Player_mode).w bne.s + move.b SpecialStage_RingReq_Team(pc,d0.w),d1 bra.s ++ ; =========================================================================== + move.b SpecialStage_RingReq_Alone(pc,d0.w),d1 + move.w d1,(SS_Ring_Requirement).w moveq #0,d0 cmpi.w #100,d1 blt.s + addq.w #1,d2 ; The following code does a more complete binary coded decimal conversion: if 1==0 - addi.w #$100,d0 subi.w #100,d1 cmpi.w #100,d1 bgt.s - else ; This code (the original) is limited to 299 rings: subi.w #100,d1 move.w #$100,d0 cmpi.w #100,d1 blt.s + subi.w #100,d1 addi.w #$100,d0 endif + divu.w #10,d1 lsl.w #4,d1 or.b d1,d0 swap d1 or.b d1,d0 move.w d0,d1 addi_.w #1,(Current_Special_StageAndAct).w rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; Ring requirement values for Sonic and Tails games ; ; This array stores the number of rings you need to get to complete each round ; of each special stage, while playing with both sonic and tails. 4 bytes per ; stage, corresponding to the four possible parts of the level. Last part is unused. ; ---------------------------------------------------------------------------- ; Misc_7756: SpecialStage_RingReq_Team: dc.b 40, 80,140,120 ; 4 dc.b 50,100,140,150 ; 8 dc.b 60,110,160,170 ; 12 dc.b 40,100,150,160 ; 16 dc.b 55,110,200,200 ; 20 dc.b 80,140,220,220 ; 24 dc.b 100,190,210,210 ; 28 ; ---------------------------------------------------------------------------- ; Ring requirement values for Sonic or Tails alone games ; ; This array stores the number of rings you need to get to complete each round ; of each special stage, while playing with either sonic or tails. 4 bytes per ; stage, corresponding to the four possible parts of the level. Last part is unused. ; ---------------------------------------------------------------------------- ; Misc_7772: SpecialStage_RingReq_Alone: dc.b 30, 70,130,110 ; 4 dc.b 50,100,140,140 ; 8 dc.b 50,110,160,160 ; 12 dc.b 40,110,150,150 ; 16 dc.b 50, 90,160,160 ; 20 dc.b 80,140,210,210 ; 24 dc.b 100,150,190,190 ; 28 ; special stage palette table ; word_778E: SpecialStage_Palettes: dc.w PalID_SS1 dc.w PalID_SS2 dc.w PalID_SS3 dc.w PalID_SS4 dc.w PalID_SS5 dc.w PalID_SS6 dc.w PalID_SS7 dc.w PalID_SS1_2p dc.w PalID_SS2_2p dc.w PalID_SS3_2p ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_77A2 SSInitPalAndData: clr.b (Current_Special_Act).w move.b #-1,(SpecialStage_LastSegment2).w move.w #0,(Ring_count).w move.w #0,(Ring_count_2P).w move.b #0,(Perfect_rings_flag).w move.b #0,(Got_Emerald).w move.b #4,(SS_Star_color_2).w lea (SS2p_RingBuffer).w,a2 moveq #0,d0 move.w d0,(a2)+ move.w d0,(a2)+ move.w d0,(a2)+ move.w d0,(a2)+ move.w d0,(a2)+ move.w d0,(a2)+ moveq #PalID_SS,d0 bsr.w PalLoad_ForFade lea_ SpecialStage_Palettes,a1 moveq #0,d0 move.b (Current_Special_Stage).w,d0 add.w d0,d0 move.w d0,d1 tst.b (SS_2p_Flag).w beq.s + cmpi.b #4,d0 blo.s + addi_.w #6,d0 + move.w (a1,d0.w),d0 bsr.w PalLoad_ForFade lea (SSRAM_MiscKoz_SpecialObjectLocations).w,a0 adda.w (a0,d1.w),a0 move.l a0,(SS_CurrentLevelObjectLocations).w lea (SSRAM_MiscNem_SpecialLevelLayout).w,a0 adda.w (a0,d1.w),a0 move.l a0,(SS_CurrentLevelLayout).w rts ; End of function SSInitPalAndData ; =========================================================================== ; temporarily remap characters to title card letter format ; Characters are encoded as Aa, Bb, Cc, etc. through a macro charset 'A',0 ; can't have an embedded 0 in a string charset 'B',"\4\8\xC\4\x10\x14\x18\x1C\x1E\x22\x26\x2A\4\4\x30\x34\x38\x3C\x40\x44\x48\x4C\x52\x56\4" charset 'a',"\4\4\4\4\4\4\4\4\2\4\4\4\6\4\4\4\4\4\4\4\4\4\6\4\4" charset '.',"\x5A" ; letter lookup string llookup := "ABCDEFGHIJKLMNOPQRSTUVWXYZ ." ; macro for defining title card letters in conjunction with the remapped character set titleLetters macro letters ; ". ZYXWVUTSRQPONMLKJIHGFEDCBA" used := %0110000000000110000000010000 ; set to initial state c := 0 rept strlen(letters) t := substr(letters,c,1) if ~~(used&1< ObjDB_Tails_Init move.b #ObjID_ContinueText,(ContinueText+id).w ; load ObjDA (continue screen text) move.b #ObjID_ContinueIcons,(ContinueIcons+id).w ; load ObjDA (continue icons) move.b #4,(ContinueIcons+routine).w ; => loc_7AD0 jsr (RunObjects).l jsr (BuildSprites).l move.b #VintID_Menu,(Vint_routine).w bsr.w WaitForVint move.w (VDP_Reg1_val).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l bsr.w Pal_FadeFromBlack - move.b #VintID_Menu,(Vint_routine).w bsr.w WaitForVint cmpi.b #4,(MainCharacter+routine).w bhs.s + move #$2700,sr move.w (Demo_Time_left).w,d1 divu.w #60,d1 andi.l #$F,d1 jsr (ContScrCounter).l move #$2300,sr + jsr (RunObjects).l jsr (BuildSprites).l cmpi.w #$180,(Sidekick+x_pos).w bhs.s + cmpi.b #4,(MainCharacter+routine).w bhs.s - tst.w (Demo_Time_left).w bne.w - move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen rts ; --------------------------------------------------------------------------- + move.b #GameModeID_Level,(Game_Mode).w ; => Level (Zone play mode) move.b #3,(Life_count).w move.b #3,(Life_count_2P).w moveq #0,d0 move.w d0,(Ring_count).w move.l d0,(Timer).w move.l d0,(Score).w move.b d0,(Last_star_pole_hit).w move.w d0,(Ring_count_2P).w move.l d0,(Timer_2P).w move.l d0,(Score_2P).w move.b d0,(Last_star_pole_hit_2P).w move.l #5000,(Next_Extra_life_score).w move.l #5000,(Next_Extra_life_score_2P).w subq.b #1,(Continue_count).w rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_7A04: ContinueScreen_LoadLetters: move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_TitleCard),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_TitleCard).l,a0 bsr.w NemDec lea (Level_Layout).w,a4 lea (ArtNem_TitleCard2).l,a0 bsr.w NemDecToRAM lea (ContinueScreen_AdditionalLetters).l,a0 move.l #vdpComm(tiles_to_bytes(ArtTile_ContinueScreen_Additional),VRAM,WRITE),(VDP_control_port).l lea (Level_Layout).w,a1 lea (VDP_data_port).l,a6 - moveq #0,d0 move.b (a0)+,d0 bmi.s + ; rts lsl.w #5,d0 lea (a1,d0.w),a2 moveq #0,d1 move.b (a0)+,d1 lsl.w #3,d1 subq.w #1,d1 - move.l (a2)+,(a6) dbf d1,- bra.s -- ; --------------------------------------------------------------------------- + rts ; End of function ContinueScreen_LoadLetters ; =========================================================================== ; temporarily remap characters to title card letter format ; Characters are encoded as Aa, Bb, Cc, etc. through a macro charset 'A',0 ; can't have an embedded 0 in a string charset 'B',"\4\8\xC\4\x10\x14\x18\x1C\x1E\x22\x26\x2A\4\4\x30\x34\x38\x3C\x40\x44\x48\x4C\x52\x56\4" charset 'a',"\4\4\4\4\4\4\4\4\2\4\4\4\6\4\4\4\4\4\4\4\4\4\6\4\4" charset '.',"\x5A" ; Defines which letters load for the continue screen ; Each letter occurs only once, and the letters ENOZ (i.e. ZONE) aren't loaded here ; However, this is hidden by the titleLetters macro, and normal titles can be used ; (the macro is defined near SpecialStage_ResultsLetters, which uses it before here) ; word_7A5E: ContinueScreen_AdditionalLetters: titleLetters "CONTINUE" charset ; revert character set ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object DA - Continue text ; ---------------------------------------------------------------------------- ; loc_7A68: ObjDA: ; (screen-space obj) moveq #0,d0 move.b routine(a0),d0 move.w ObjDA_Index(pc,d0.w),d1 jmp ObjDA_Index(pc,d1.w) ; =========================================================================== ; Obj_DA_subtbl: ObjDA_Index: offsetTable offsetTableEntry.w ObjDA_Init ; 0 offsetTableEntry.w JmpTo2_DisplaySprite ; 2 offsetTableEntry.w loc_7AD0 ; 4 offsetTableEntry.w loc_7B46 ; 6 ; =========================================================================== ; loc_7A7E: ObjDA_Init: addq.b #2,routine(a0) move.l #ObjDA_MapUnc_7CB6,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_ContinueText,0,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo_Adjust2PArtPointer move.b #0,render_flags(a0) move.b #$3C,width_pixels(a0) move.w #$120,x_pixel(a0) move.w #$C0,y_pixel(a0) JmpTo2_DisplaySprite jmp (DisplaySprite).l ; =========================================================================== ; word_7AB2: ObjDA_XPositions: dc.w $116, $12A, $102, $13E, $EE, $152, $DA, $166 dc.w $C6, $17A, $B2, $18E, $9E, $1A2, $8A; 8 ; =========================================================================== loc_7AD0: movea.l a0,a1 lea_ ObjDA_XPositions,a2 moveq #0,d1 move.b (Continue_count).w,d1 subq.b #2,d1 bcc.s + jmp (DeleteObject).l ; =========================================================================== + moveq #1,d3 cmpi.b #$E,d1 blo.s + moveq #0,d3 moveq #$E,d1 + move.b d1,d2 andi.b #1,d2 - _move.b #ObjID_ContinueIcons,id(a1) ; load objDA move.w (a2)+,x_pixel(a1) tst.b d2 beq.s + subi.w #$A,x_pixel(a1) + move.w #$D0,y_pixel(a1) move.b #4,mapping_frame(a1) move.b #6,routine(a1) move.l #ObjDA_MapUnc_7CB6,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_ContinueText_2,0,1),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo_Adjust2PArtPointer2 move.b #0,render_flags(a1) lea next_object(a1),a1 ; load obj addr dbf d1,- lea -next_object(a1),a1 ; load obj addr move.b d3,subtype(a1) loc_7B46: tst.b subtype(a0) beq.s + cmpi.b #4,(MainCharacter+routine).w blo.s + move.b (Vint_runcount+3).w,d0 andi.b #1,d0 bne.s + tst.w (MainCharacter+x_vel).w bne.s JmpTo2_DeleteObject rts ; =========================================================================== + move.b (Vint_runcount+3).w,d0 andi.b #$F,d0 bne.s JmpTo3_DisplaySprite bchg #0,mapping_frame(a0) JmpTo3_DisplaySprite jmp (DisplaySprite).l ; =========================================================================== JmpTo2_DeleteObject jmp (DeleteObject).l ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object DB - Sonic lying down or Tails nagging (on the continue screen) ; ---------------------------------------------------------------------------- ; Sprite_7B82: ObjDB: ; a0=character moveq #0,d0 move.b routine(a0),d0 move.w ObjDB_Index(pc,d0.w),d1 jsr ObjDB_Index(pc,d1.w) jmp (DisplaySprite).l ; =========================================================================== ; off_7B96: ObjDB_States: ObjDB_Index: offsetTable offsetTableEntry.w ObjDB_Sonic_Init ; 0 offsetTableEntry.w ObjDB_Sonic_Wait ; 2 offsetTableEntry.w ObjDB_Sonic_Run ; 4 offsetTableEntry.w ObjDB_Tails_Init ; 6 offsetTableEntry.w ObjDB_Tails_Wait ; 8 offsetTableEntry.w ObjDB_Tails_Run ; $A ; =========================================================================== ; loc_7BA2: ObjDB_Sonic_Init: addq.b #2,routine(a0) ; => ObjDB_Sonic_Wait move.w #$9C,x_pos(a0) move.w #$19C,y_pos(a0) move.l #Mapunc_Sonic,mappings(a0) move.w #make_art_tile(ArtTile_ArtUnc_Sonic,0,0),art_tile(a0) move.b #4,render_flags(a0) move.b #2,priority(a0) move.b #$20,anim(a0) ; loc_7BD2: ObjDB_Sonic_Wait: tst.b (Ctrl_1_Press).w ; is start pressed? bmi.s ObjDB_Sonic_StartRunning ; if yes, branch jsr (Sonic_Animate).l jmp (LoadSonicDynPLC).l ; --------------------------------------------------------------------------- ; loc_7BE4: ObjDB_Sonic_StartRunning: addq.b #2,routine(a0) ; => ObjDB_Sonic_Run move.b #$21,anim(a0) clr.w inertia(a0) move.b #SndID_SpindashRev,d0 ; super peel-out sound bsr.w PlaySound ; loc_7BFA: ObjDB_Sonic_Run: cmpi.w #$800,inertia(a0) bne.s + move.w #$1000,x_vel(a0) bra.s ++ ; --------------------------------------------------------------------------- + addi.w #$20,inertia(a0) + jsr (ObjectMove).l jsr (Sonic_Animate).l jmp (LoadSonicDynPLC).l ; =========================================================================== ; loc_7C22: ObjDB_Tails_Init: addq.b #2,routine(a0) ; => ObjDB_Tails_Wait move.w #$B8,x_pos(a0) move.w #$1A0,y_pos(a0) move.l #ObjDA_MapUnc_7CB6,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_ContinueTails,0,0),art_tile(a0) move.b #4,render_flags(a0) move.b #2,priority(a0) move.b #0,anim(a0) ; loc_7C52: ObjDB_Tails_Wait: tst.b (Ctrl_1_Press).w ; is start pressed? bmi.s ObjDB_Tails_StartRunning ; if yes, branch lea (Ani_objDB).l,a1 jmp (AnimateSprite).l ; --------------------------------------------------------------------------- ; loc_7C64: ObjDB_Tails_StartRunning: addq.b #2,routine(a0) ; => ObjDB_Tails_Run move.l #MapUnc_Tails,mappings(a0) move.w #make_art_tile(ArtTile_ArtUnc_Tails,0,0),art_tile(a0) move.b #0,anim(a0) clr.w inertia(a0) move.b #SndID_SpindashRev,d0 ; super peel-out sound bsr.w PlaySound ; loc_7C88: ObjDB_Tails_Run: cmpi.w #$720,inertia(a0) bne.s + move.w #$1000,x_vel(a0) bra.s ++ ; --------------------------------------------------------------------------- + addi.w #$18,inertia(a0) + jsr (ObjectMove).l jsr (Tails_Animate).l jmp (LoadTailsDynPLC).l ; =========================================================================== ; animation script for continue screen Tails nagging ; off_7CB0 Ani_objDB: offsetTable offsetTableEntry.w + ; 0 + dc.b 9, 2, 3,$FF even ; ------------------------------------------------------------------------------- ; Sprite mappings for text, countdown, stars, and Tails on the continue screen ; Art starts at $A000 in VRAM ; ------------------------------------------------------------------------------- ObjDA_MapUnc_7CB6: BINCLUDE "mappings/sprite/objDA.bin" if ~~removeJmpTos JmpTo_Adjust2PArtPointer2 jmp (Adjust2PArtPointer2).l JmpTo_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; loc_7D50: TwoPlayerResults: bsr.w Pal_FadeToBlack move #$2700,sr move.w (VDP_Reg1_val).w,d0 andi.b #$BF,d0 move.w d0,(VDP_control_port).l bsr.w ClearScreen lea (VDP_control_port).l,a6 move.w #$8004,(a6) ; H-INT disabled move.w #$8200|(VRAM_Menu_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000 move.w #$8400|(VRAM_Menu_Plane_B_Name_Table/$2000),(a6) ; PNT B base: $E000 move.w #$8200|(VRAM_Menu_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000 move.w #$8700,(a6) ; Background palette/color: 0/0 move.w #$8C81,(a6) ; H res 40 cells, no interlace, S/H disabled move.w #$9001,(a6) ; Scroll table size: 64x32 clearRAM Sprite_Table_Input,Sprite_Table_Input_End clearRAM VSRslts_Object_RAM,VSRslts_Object_RAM_End move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_FontStuff),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_FontStuff).l,a0 bsr.w NemDec move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_1P2PWins),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_1P2PWins).l,a0 bsr.w NemDec lea (Chunk_Table).l,a1 lea (MapEng_MenuBack).l,a0 move.w #make_art_tile(ArtTile_VRAM_Start,3,0),d0 bsr.w EniDec lea (Chunk_Table).l,a1 move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0 moveq #$27,d1 moveq #$1B,d2 jsrto (PlaneMapToVRAM_H40).l, PlaneMapToVRAM_H40 move.w (Results_Screen_2P).w,d0 add.w d0,d0 add.w d0,d0 add.w d0,d0 lea TwoPlayerResultsPointers(pc),a2 movea.l (a2,d0.w),a0 movea.l 4(a2,d0.w),a2 lea (Chunk_Table).l,a1 move.w #make_art_tile(ArtTile_VRAM_Start,0,0),d0 bsr.w EniDec jsr (a2) ; dynamic call! to Setup2PResults_Act, Setup2PResults_Zone, Setup2PResults_Game, Setup2PResults_SpecialAct, or Setup2PResults_SpecialZone, assuming the pointers in TwoPlayerResultsPointers have not been changed lea (Chunk_Table).l,a1 move.l #vdpComm(tiles_to_bytes(ArtTile_TwoPlayerResults),VRAM,WRITE),d0 moveq #$27,d1 moveq #$1B,d2 jsrto (PlaneMapToVRAM_H40).l, PlaneMapToVRAM_H40 clr.w (VDP_Command_Buffer).w move.l #VDP_Command_Buffer,(VDP_Command_Buffer_Slot).w clr.b (Level_started_flag).w clr.w (Anim_Counters).w lea (Anim_SonicMilesBG).l,a2 jsrto (Dynamic_Normal).l, JmpTo_Dynamic_Normal moveq #PLCID_Std1,d0 bsr.w LoadPLC2 moveq #PalID_Menu,d0 bsr.w PalLoad_ForFade moveq #0,d0 move.b #MusID_2PResult,d0 cmp.w (Level_Music).w,d0 beq.s + move.w d0,(Level_Music).w bsr.w PlayMusic + move.w #$707,(Demo_Time_left).w clr.w (Two_player_mode).w clr.l (Camera_X_pos).w clr.l (Camera_Y_pos).w clr.l (Vscroll_Factor).w clr.l (Vscroll_Factor_P2).w clr.l (Vscroll_Factor_P2_HInt).w move.b #ObjID_HUD,(VSResults_HUD+id).w move.b #VintID_Menu,(Vint_routine).w bsr.w WaitForVint move.w (VDP_Reg1_val).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l bsr.w Pal_FadeFromBlack - move.b #VintID_Menu,(Vint_routine).w bsr.w WaitForVint lea (Anim_SonicMilesBG).l,a2 jsrto (Dynamic_Normal).l, JmpTo_Dynamic_Normal jsr (RunObjects).l jsr (BuildSprites).l bsr.w RunPLC_RAM tst.l (Plc_Buffer).w bne.s - move.b (Ctrl_1_Press).w,d0 or.b (Ctrl_2_Press).w,d0 andi.b #button_start_mask,d0 beq.s - ; stay on that screen until either player presses start move.w (Results_Screen_2P).w,d0 ; were we at the act results screen? (VsRSID_Act) bne.w TwoPlayerResultsDone_Zone ; if not, branch tst.b (Current_Act).w ; did we just finish act 1? bne.s + ; if not, branch addq.b #1,(Current_Act).w ; go to the next act move.b #1,(Current_Act_2P).w move.b #GameModeID_Level,(Game_Mode).w ; => Level (Zone play mode) move.b #0,(Last_star_pole_hit).w move.b #0,(Last_star_pole_hit_2P).w moveq #1,d0 move.w d0,(Two_player_mode).w move.w d0,(Two_player_mode_copy).w moveq #0,d0 move.l d0,(Score).w move.l d0,(Score_2P).w move.l #5000,(Next_Extra_life_score).w move.l #5000,(Next_Extra_life_score_2P).w rts ; =========================================================================== + ; Displays results for the zone move.b #2,(Current_Act_2P).w bsr.w sub_84A4 lea (SS_Total_Won).w,a4 clr.w (a4) bsr.s sub_7F9A bsr.s sub_7F9A move.b (a4),d1 sub.b 1(a4),d1 beq.s + ; if there's a tie, branch move.w #VsRSID_Zone,(Results_Screen_2P).w move.b #GameModeID_2PResults,(Game_Mode).w ; => TwoPlayerResults rts ; =========================================================================== + ; There's a tie, play a special stage move.b (Current_Zone_2P).w,d0 addq.b #1,d0 move.b d0,(Current_Special_Stage).w move.w #VsRSID_SS,(Results_Screen_2P).w move.b #1,(SpecialStage_flag_2P).w move.b #GameModeID_SpecialStage,(Game_Mode).w ; => SpecialStage moveq #1,d0 move.w d0,(Two_player_mode).w move.w d0,(Two_player_mode_copy).w move.b #0,(Last_star_pole_hit).w move.b #0,(Last_star_pole_hit_2P).w rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_7F9A: moveq #0,d1 move.b (a5),d1 sub.b 1(a5),d1 beq.s ++ bcs.s + addq.b #1,(a4) bra.s ++ ; =========================================================================== + addq.b #1,1(a4) + addq.w #2,a5 rts ; End of function sub_7F9A ; =========================================================================== ; loc_7FB2: TwoPlayerResultsDone_Zone: subq.w #1,d0 ; were we at the zone results screen? (VsRSID_Zone) bne.s TwoPlayerResultsDone_Game ; if not, branch ; loc_7FB6: TwoPlayerResultsDone_ZoneOrSpecialStages: lea (Results_Data_2P).w,a4 moveq #0,d0 moveq #0,d1 rept 3 move.w (a4)+,d0 add.l d0,d1 move.w (a4)+,d0 add.l d0,d1 addq.w #2,a4 endm move.w (a4)+,d0 add.l d0,d1 move.w (a4)+,d0 add.l d0,d1 swap d1 tst.w d1 ; have all levels been completed? bne.s + ; if not, branch move.w #VsRSID_Game,(Results_Screen_2P).w move.b #GameModeID_2PResults,(Game_Mode).w ; => TwoPlayerResults rts ; =========================================================================== + tst.w (Game_Over_2P).w beq.s + ; if there's a Game Over, clear the results lea (Results_Data_2P).w,a1 moveq #bytesToWcnt(Results_Data_2P_End-Results_Data_2P),d0 - move.w #-1,(a1)+ dbf d0,- move.b #3,(Life_count).w move.b #3,(Life_count_2P).w + move.b #GameModeID_2PLevelSelect,(Game_Mode).w ; => LevelSelectMenu2P rts ; =========================================================================== ; loc_8020: TwoPlayerResultsDone_Game: subq.w #1,d0 ; were we at the game results screen? (VsRSID_Game) bne.s TwoPlayerResultsDone_SpecialStage ; if not, branch move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen rts ; =========================================================================== ; loc_802C: TwoPlayerResultsDone_SpecialStage: subq.w #1,d0 ; were we at the special stage results screen? (VsRSID_SS) bne.w TwoPlayerResultsDone_SpecialStages ; if not, branch cmpi.b #3,(Current_Zone_2P).w ; do we come from the special stage "zone"? beq.s + ; if yes, branch move.w #VsRSID_Zone,(Results_Screen_2P).w ; show zone results after tiebreaker special stage move.b #GameModeID_2PResults,(Game_Mode).w ; => TwoPlayerResults rts ; =========================================================================== + tst.b (Current_Act_2P).w beq.s + cmpi.b #2,(Current_Act_2P).w beq.s loc_80AC bsr.w sub_84A4 lea (SS_Total_Won).w,a4 clr.w (a4) bsr.s sub_8094 bsr.s sub_8094 move.b (a4),d1 sub.b 1(a4),d1 bne.s loc_80AC + addq.b #1,(Current_Act_2P).w addq.b #1,(Current_Special_Stage).w move.w #VsRSID_SS,(Results_Screen_2P).w move.b #1,(SpecialStage_flag_2P).w move.b #GameModeID_SpecialStage,(Game_Mode).w ; => SpecialStage move.w #1,(Two_player_mode).w move.w #0,(Level_Music).w rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_8094: moveq #0,d1 move.b (a5),d1 sub.b 1(a5),d1 beq.s ++ bcs.s + addq.b #1,(a4) bra.s ++ ; =========================================================================== + addq.b #1,1(a4) + addq.w #2,a5 rts ; End of function sub_8094 ; =========================================================================== loc_80AC: move.w #VsRSID_SSZone,(Results_Screen_2P).w move.b #GameModeID_2PResults,(Game_Mode).w ; => TwoPlayerResults rts ; =========================================================================== ; loc_80BA: BranchTo_loc_7FB6: TwoPlayerResultsDone_SpecialStages: ; we were at the special stages results screen (VsRSID_SSZone) bra.w TwoPlayerResultsDone_ZoneOrSpecialStages ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 21 - Score/Rings/Time display (in 2P results) ; ---------------------------------------------------------------------------- ; Sprite_80BE: Obj21: ; (screen-space obj) moveq #0,d0 move.b routine(a0),d0 move.w Obj21_Index(pc,d0.w),d1 jmp Obj21_Index(pc,d1.w) ; =========================================================================== ; JmpTbl_80CC: Obj21_States: Obj21_Index: offsetTable offsetTableEntry.w Obj21_Init ; 0 offsetTableEntry.w Obj21_Main ; 2 ; --------------------------------------------------------------------------- ; word_80D0: Obj21_PositionTable: ; x, y dc.w $F0, $148 dc.w $F0, $130 dc.w $E0, $148 dc.w $F0, $148 dc.w $F0, $148 ; =========================================================================== ; loc_80E4: Obj21_Init: addq.b #2,routine(a0) ; => Obj21_Main move.w (Results_Screen_2P).w,d0 add.w d0,d0 add.w d0,d0 move.l Obj21_PositionTable(pc,d0.w),x_pixel(a0) ; and y_pixel(a0) move.l #Obj21_MapUnc_8146,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_1P2PWins,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo2_Adjust2PArtPointer move.b #0,render_flags(a0) move.b #0,priority(a0) moveq #2,d1 move.b (SS_Total_Won).w,d0 ; d0 = SS_Total_Won_1P sub.b (SS_Total_Won+1).w,d0 ; - SS_Total_Won_2P beq.s ++ bcs.s + moveq #0,d1 bra.s ++ ; --------------------------------------------------------------------------- + moveq #1,d1 + move.b d1,mapping_frame(a0) ; loc_812C: Obj21_Main: andi.w #tile_mask,art_tile(a0) btst #3,(Vint_runcount+3).w beq.s JmpTo4_DisplaySprite ori.w #palette_line_1,art_tile(a0) JmpTo4_DisplaySprite jmp (DisplaySprite).l ; =========================================================================== ; -------------------------------------------------------------------------- ; sprite mappings ; -------------------------------------------------------------------------- Obj21_MapUnc_8146: BINCLUDE "mappings/sprite/obj21.bin" ; =========================================================================== ; loc_819A: Setup2PResults_Act: move.w #$1F2,d2 moveq #0,d0 bsr.w sub_8672 move.w #$216,d2 moveq #0,d1 move.b (Current_Act_2P).w,d1 addq.b #1,d1 bsr.w sub_86B0 move.w #$33E,d2 move.l (Score).w,d1 bsr.w sub_86F6 move.w #$352,d2 move.l (Score_2P).w,d1 bsr.w sub_86F6 move.w #$3DA,d2 moveq #0,d0 move.w (Timer_minute_word).w,d1 bsr.w sub_86B0 move.w #$3E0,d2 moveq #0,d1 move.b (Timer_second).w,d1 bsr.w sub_86B0 move.w #$3E6,d2 moveq #0,d1 move.b (Timer_frame).w,d1 mulu.w #$1B0,d1 lsr.l #8,d1 bsr.w sub_86B0 move.w #$3EE,d2 moveq #0,d0 move.w (Timer_minute_word_2P).w,d1 bsr.w sub_86B0 move.w #$3F4,d2 moveq #0,d1 move.b (Timer_second_2P).w,d1 bsr.w sub_86B0 move.w #$3FA,d2 moveq #0,d1 move.b (Timer_centisecond_2P).w,d1 mulu.w #$1B0,d1 lsr.l #8,d1 bsr.w sub_86B0 move.w #$486,d2 moveq #0,d0 move.w (Ring_count).w,d1 bsr.w sub_86B0 move.w #$49A,d2 move.w (Ring_count_2P).w,d1 bsr.w sub_86B0 move.w #$526,d2 moveq #0,d0 move.w (Rings_Collected).w,d1 bsr.w sub_86B0 move.w #$53A,d2 move.w (Rings_Collected_2P).w,d1 bsr.w sub_86B0 move.w #$5C6,d2 moveq #0,d0 move.w (Monitors_Broken).w,d1 bsr.w sub_86B0 move.w #$5DA,d2 move.w (Monitors_Broken_2P).w,d1 bsr.w sub_86B0 bsr.w sub_8476 move.w #$364,d2 move.w #$6000,d0 move.l (Score).w,d1 sub.l (Score_2P).w,d1 bsr.w sub_8652 move.w #$404,d2 move.l (Timer_2P).w,d1 sub.l (Timer).w,d1 bsr.w sub_8652 move.w #$4A4,d2 moveq #0,d1 move.w (Ring_count).w,d1 sub.w (Ring_count_2P).w,d1 bsr.w sub_8652 move.w #$544,d2 moveq #0,d1 move.w (Rings_Collected).w,d1 sub.w (Rings_Collected_2P).w,d1 bsr.w sub_8652 move.w #$5E4,d2 moveq #0,d1 move.w (Monitors_Broken).w,d1 sub.w (Monitors_Broken_2P).w,d1 bsr.w sub_8652 move.w #$706,d2 moveq #0,d0 moveq #0,d1 move.b (a4),d1 bsr.w sub_86B0 move.w #$70E,d2 moveq #0,d1 move.b 1(a4),d1 bsr.w sub_86B0 move.w (a4),(SS_Total_Won).w rts ; =========================================================================== ; loc_82FA: Setup2PResults_Zone: move.w #$242,d2 moveq #0,d0 bsr.w sub_8672 bsr.w sub_84A4 lea (SS_Total_Won).w,a4 clr.w (a4) move.w #$398,d6 bsr.w sub_854A move.w #$488,d6 bsr.w sub_854A move.w #$618,d6 bsr.w sub_854A rts ; =========================================================================== ; loc_8328: Setup2PResults_Game: lea (Results_Data_2P).w,a5 lea (SS_Total_Won).w,a4 clr.w (a4) move.w #$208,d6 bsr.w sub_84C4 move.w #$258,d6 bsr.w sub_84C4 move.w #$2A8,d6 bsr.w sub_84C4 move.w #$348,d6 bsr.w sub_84C4 move.w #$398,d6 bsr.w sub_84C4 move.w #$3E8,d6 bsr.w sub_84C4 move.w #$488,d6 bsr.w sub_84C4 move.w #$4D8,d6 bsr.w sub_84C4 move.w #$528,d6 bsr.w sub_84C4 move.w #$5C8,d6 bsr.w sub_84C4 move.w #$618,d6 bsr.w sub_84C4 move.w #$668,d6 bsr.w sub_84C4 move.w #$70A,d2 moveq #0,d0 moveq #0,d1 move.b (a4),d1 bsr.w sub_86B0 move.w #$710,d2 moveq #0,d1 move.b 1(a4),d1 bsr.w sub_86B0 rts ; =========================================================================== ; loc_83B0: Setup2PResults_SpecialAct: move.w #$266,d2 moveq #0,d1 move.b (Current_Act_2P).w,d1 addq.b #1,d1 bsr.w sub_86B0 move.w #$4D6,d2 moveq #0,d0 move.w (SS2p_RingBuffer).w,d1 ; P1 SS act 1 rings bsr.w sub_86B0 move.w #$4E6,d2 move.w (SS2p_RingBuffer+2).w,d1 ; P2 SS act 1 rings bsr.w sub_86B0 move.w #$576,d2 moveq #0,d0 move.w (SS2p_RingBuffer+4).w,d1 ; P1 SS act 2 rings bsr.w sub_86B0 move.w #$586,d2 move.w (SS2p_RingBuffer+6).w,d1 ; P2 SS act 2 rings bsr.w sub_86B0 move.w #$616,d2 moveq #0,d0 move.w (SS2p_RingBuffer+8).w,d1 ; P1 SS act 3 rings bsr.w sub_86B0 move.w #$626,d2 move.w (SS2p_RingBuffer+$A).w,d1 ; P2 SS act 3 rings bsr.w sub_86B0 bsr.w sub_8476 move.w #$6000,d0 move.w #$4F0,d2 moveq #0,d1 move.w (SS2p_RingBuffer).w,d1 ; P1 SS act 1 rings sub.w (SS2p_RingBuffer+2).w,d1 ; P2 SS act 1 rings bsr.w sub_8652 move.w #$590,d2 moveq #0,d1 move.w (SS2p_RingBuffer+4).w,d1 ; P1 SS act 2 rings sub.w (SS2p_RingBuffer+6).w,d1 ; P2 SS act 2 rings bsr.w sub_8652 move.w #$630,d2 moveq #0,d1 move.w (SS2p_RingBuffer+8).w,d1 ; P1 SS act 3 rings sub.w (SS2p_RingBuffer+$A).w,d1 ; P2 SS act 3 rings bsr.w sub_8652 move.w (a4),(SS_Total_Won).w rts ; =========================================================================== ; loc_8452: Setup2PResults_SpecialZone: bsr.w sub_84A4 lea (SS_Total_Won).w,a4 clr.w (a4) move.w #$4D4,d6 bsr.w sub_85CE move.w #$574,d6 bsr.w sub_85CE move.w #$614,d6 bsr.w sub_85CE rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_8476: lea (EHZ_Results_2P).w,a4 move.b (Current_Zone_2P).w,d0 beq.s + lea (MCZ_Results_2P).w,a4 subq.b #1,d0 beq.s + lea (CNZ_Results_2P).w,a4 subq.b #1,d0 beq.s + lea (SS_Results_2P).w,a4 + moveq #0,d0 move.b (Current_Act_2P).w,d0 add.w d0,d0 lea (a4,d0.w),a4 clr.w (a4) rts ; End of function sub_8476 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_84A4: lea (EHZ_Results_2P).w,a5 move.b (Current_Zone_2P).w,d0 beq.s + ; rts lea (MCZ_Results_2P).w,a5 subq.b #1,d0 beq.s + ; rts lea (CNZ_Results_2P).w,a5 subq.b #1,d0 beq.s + ; rts lea (SS_Results_2P).w,a5 + rts ; End of function sub_84A4 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_84C4: move.w (a5),d0 bmi.s + move.w d6,d2 moveq #0,d0 moveq #0,d1 move.b (a5),d1 bsr.w sub_86B0 addq.w #8,d6 move.w d6,d2 moveq #0,d1 move.b 1(a5),d1 bsr.w sub_86B0 addi.w #$12,d6 move.w d6,d2 move.w #$6000,d0 moveq #0,d1 move.b (a5),d1 sub.b 1(a5),d1 bsr.w sub_8652 addq.w #2,a5 rts ; =========================================================================== + addq.w #4,d6 not.w d0 bne.s + lea (Text2P_NoGame).l,a1 move.w d6,d2 bsr.w loc_8698 addi.w #$16,d6 move.w d6,d2 lea (Text2P_Blank).l,a1 bsr.w loc_8698 addq.w #2,a5 rts ; =========================================================================== + moveq #0,d0 lea (Text2P_GameOver).l,a1 move.w d6,d2 bsr.w loc_8698 addi.w #$16,d6 move.w d6,d2 move.w #$6000,d0 moveq #0,d1 move.b (a5),d1 sub.b 1(a5),d1 bsr.w sub_8652 addq.w #2,a5 rts ; End of function sub_84C4 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_854A: move.w (a5),d0 bmi.s loc_8582 move.w d6,d2 moveq #0,d0 moveq #0,d1 move.b (a5),d1 bsr.w sub_86B0 addq.w #8,d6 move.w d6,d2 moveq #0,d1 move.b 1(a5),d1 bsr.w sub_86B0 addi.w #$C,d6 move.w d6,d2 move.w #$6000,d0 moveq #0,d1 move.b (a5),d1 sub.b 1(a5),d1 bsr.w sub_8652 addq.w #2,a5 rts ; =========================================================================== loc_8582: not.w d0 bne.s loc_85A6 lea (Text2P_NoGame).l,a1 move.w d6,d2 bsr.w loc_8698 addi.w #$14,d6 move.w d6,d2 lea (Text2P_Blank).l,a1 bsr.w loc_8698 addq.w #2,a5 rts ; =========================================================================== loc_85A6: moveq #0,d0 lea (Text2P_GameOver).l,a1 move.w d6,d2 bsr.w loc_8698 addi.w #$14,d6 move.w d6,d2 move.w #$6000,d0 moveq #0,d1 move.b (a5),d1 sub.b 1(a5),d1 bsr.w sub_8652 addq.w #2,a5 rts ; End of function sub_854A ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_85CE: move.w (a5),d0 bmi.s + move.w d6,d2 moveq #0,d0 moveq #0,d1 move.b (a5),d1 bsr.w sub_86B0 addi.w #$C,d6 move.w d6,d2 moveq #0,d1 move.b 1(a5),d1 bsr.w sub_86B0 addi.w #$10,d6 move.w d6,d2 move.w #$6000,d0 moveq #0,d1 move.b (a5),d1 sub.b 1(a5),d1 bsr.w sub_8652 addq.w #2,a5 rts ; =========================================================================== + not.w d0 bne.s loc_862C lea (Text2P_NoGame).l,a1 move.w d6,d2 addq.w #4,d2 bsr.w loc_8698 addi.w #$14,d6 move.w d6,d2 lea (Text2P_Blank).l,a1 bsr.s loc_8698 addq.w #2,a5 rts ; =========================================================================== loc_862C: moveq #0,d0 lea (Text2P_GameOver).l,a1 move.w d6,d2 bsr.s loc_8698 addi.w #$14,d6 move.w d6,d2 move.w #$6000,d0 moveq #0,d1 move.b (a5),d1 sub.b 1(a5),d1 bsr.w sub_8652 addq.w #2,a5 rts ; End of function sub_85CE ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_8652: lea (Text2P_Tied).l,a1 beq.s ++ bcs.s + lea (Text2P_1P).l,a1 addq.b #1,(a4) bra.s ++ ; =========================================================================== + lea (Text2P_2P).l,a1 addq.b #1,1(a4) + bra.s loc_8698 ; End of function sub_8652 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_8672: lea (Text2P_EmeraldHill).l,a1 move.b (Current_Zone_2P).w,d1 beq.s loc_8698 lea (Text2P_MysticCave).l,a1 subq.b #1,d1 beq.s loc_8698 lea (Text2P_CasinoNight).l,a1 subq.b #1,d1 beq.s loc_8698 lea (Text2P_SpecialStage).l,a1 loc_8698: lea (Chunk_Table).l,a2 lea (a2,d2.w),a2 moveq #0,d1 move.b (a1)+,d1 - move.b (a1)+,d0 move.w d0,(a2)+ dbf d1,- rts ; End of function sub_8672 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_86B0: lea (Chunk_Table).l,a2 lea (a2,d2.w),a2 lea (word_86F0).l,a3 moveq #0,d2 moveq #2,d5 - moveq #0,d3 move.w (a3)+,d4 - sub.w d4,d1 bcs.s + addq.w #1,d3 bra.s - ; --------------------------------------------------------------------------- + add.w d4,d1 tst.w d5 beq.s ++ tst.w d3 beq.s + moveq #1,d2 + tst.w d2 beq.s ++ + addi.b #$10,d3 move.b d3,d0 move.w d0,(a2) + addq.w #2,a2 dbf d5,-- rts ; End of function sub_86B0 ; =========================================================================== word_86F0: dc.w 100 dc.w 10 ; 1 dc.w 1 ; 2 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_86F6: lea (Chunk_Table).l,a2 lea (a2,d2.w),a2 lea (dword_8732).l,a3 moveq #0,d2 moveq #5,d5 - moveq #0,d3 move.l (a3)+,d4 - sub.l d4,d1 bcs.s + addq.w #1,d3 bra.s - ; =========================================================================== + add.l d4,d1 tst.w d3 beq.s + moveq #1,d2 + tst.w d2 beq.s + addi.b #$10,d3 move.b d3,d0 move.w d0,(a2) + addq.w #2,a2 dbf d5,-- rts ; End of function sub_86F6 ; =========================================================================== dword_8732: dc.l 100000 dc.l 10000 dc.l 1000 dc.l 100 dc.l 10 dc.l 1 ; set the character set for menu text charset '@',"\27\30\31\32\33\34\35\36\37\38\39\40\41\42\43\44\45\46\47\48\49\50\51\52\53\54\55" charset '0',"\16\17\18\19\20\21\22\23\24\25" charset '*',$1A charset ':',$1C charset '.',$1D charset ' ',0 ; Menu text menutxt macro text dc.b strlen(text)-1 dc.b text endm Text2P_EmeraldHill: menutxt "EMERALD HILL" ; byte_874A: rev02even Text2P_MysticCave: menutxt " MYSTIC CAVE" ; byte_8757: rev02even Text2P_CasinoNight: menutxt "CASINO NIGHT" ; byte_8764: rev02even Text2P_SpecialStage: menutxt "SPECIAL STAGE" ; byte_8771: rev02even Text2P_Special: menutxt " SPECIAL " ; byte_877F: rev02even Text2P_Zone: menutxt "ZONE " ; byte_878C: rev02even Text2P_Stage: menutxt "STAGE" ; byte_8792: rev02even Text2P_GameOver: menutxt "GAME OVER" ; byte_8798: rev02even Text2P_TimeOver: menutxt "TIME OVER" rev02even Text2P_NoGame: menutxt "NO GAME" ; byte_87AC: rev02even Text2P_Tied: menutxt "TIED" ; byte_87B4: rev02even Text2P_1P: menutxt " 1P" ; byte_87B9: rev02even Text2P_2P: menutxt " 2P" ; byte_87BD: rev02even Text2P_Blank: menutxt " " ; byte_87C1: rev02even charset ; reset character set ; ------------------------------------------------------------------------ ; MENU ANIMATION SCRIPT ; ------------------------------------------------------------------------ ;word_87C6: Anim_SonicMilesBG: zoneanimstart ; Sonic/Miles animated background zoneanimdecl -1, ArtUnc_MenuBack, 1, 6, $A dc.b 0,$C7 dc.b $A, 5 dc.b $14, 5 dc.b $1E,$C7 dc.b $14, 5 dc.b $A, 5 even zoneanimend ; off_87DC: TwoPlayerResultsPointers: VsResultsScreen_Act: dc.l Map_2PActResults, Setup2PResults_Act VsResultsScreen_Zone: dc.l Map_2PZoneResults, Setup2PResults_Zone VsResultsScreen_Game: dc.l Map_2PGameResults, Setup2PResults_Game VsResultsScreen_SS: dc.l Map_2PSpecialStageActResults, Setup2PResults_SpecialAct VsResultsScreen_SSZone: dc.l Map_2PSpecialStageZoneResults, Setup2PResults_SpecialZone ; 2P single act results screen (enigma compressed) ; byte_8804: Map_2PActResults: BINCLUDE "mappings/misc/2P Act Results.bin" ; 2P zone results screen (enigma compressed) ; byte_88CE: Map_2PZoneResults: BINCLUDE "mappings/misc/2P Zone Results.bin" ; 2P game results screen (after all 4 zones) (enigma compressed) ; byte_8960: Map_2PGameResults: BINCLUDE "mappings/misc/2P Game Results.bin" ; 2P special stage act results screen (enigma compressed) ; byte_8AA4: Map_2PSpecialStageActResults: BINCLUDE "mappings/misc/2P Special Stage Act Results.bin" ; 2P special stage zone results screen (enigma compressed) ; byte_8B30: Map_2PSpecialStageZoneResults: BINCLUDE "mappings/misc/2P Special Stage Zone Results.bin" even if ~~removeJmpTos JmpTo2_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo_Dynamic_Normal jmp (Dynamic_Normal).l align 4 endif ; =========================================================================== ; loc_8BD4: MenuScreen: bsr.w Pal_FadeToBlack move #$2700,sr move.w (VDP_Reg1_val).w,d0 andi.b #$BF,d0 move.w d0,(VDP_control_port).l bsr.w ClearScreen lea (VDP_control_port).l,a6 move.w #$8004,(a6) ; H-INT disabled move.w #$8200|(VRAM_Menu_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000 move.w #$8400|(VRAM_Menu_Plane_B_Name_Table/$2000),(a6) ; PNT B base: $E000 move.w #$8200|(VRAM_Menu_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000 move.w #$8700,(a6) ; Background palette/color: 0/0 move.w #$8C81,(a6) ; H res 40 cells, no interlace, S/H disabled move.w #$9001,(a6) ; Scroll table size: 64x32 clearRAM Sprite_Table_Input,Sprite_Table_Input_End clearRAM Menus_Object_RAM,Menus_Object_RAM_End ; load background + graphics of font/LevSelPics clr.w (VDP_Command_Buffer).w move.l #VDP_Command_Buffer,(VDP_Command_Buffer_Slot).w move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_FontStuff),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_FontStuff).l,a0 bsr.w NemDec move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_MenuBox),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_MenuBox).l,a0 bsr.w NemDec move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_LevelSelectPics),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_LevelSelectPics).l,a0 bsr.w NemDec lea (Chunk_Table).l,a1 lea (MapEng_MenuBack).l,a0 move.w #make_art_tile(ArtTile_VRAM_Start,3,0),d0 bsr.w EniDec lea (Chunk_Table).l,a1 move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0 moveq #$27,d1 moveq #$1B,d2 jsrto (PlaneMapToVRAM_H40).l, JmpTo_PlaneMapToVRAM_H40 ; fullscreen background cmpi.b #GameModeID_OptionsMenu,(Game_Mode).w ; options menu? beq.w MenuScreen_Options ; if yes, branch cmpi.b #GameModeID_LevelSelect,(Game_Mode).w ; level select menu? beq.w MenuScreen_LevelSelect ; if yes, branch ;MenuScreen_LevSel2P: lea (Chunk_Table).l,a1 lea (MapEng_LevSel2P).l,a0 move.w #make_art_tile(ArtTile_ArtNem_MenuBox,0,0),d0 bsr.w EniDec lea (Chunk_Table+$198).l,a1 lea (MapEng_LevSel2P).l,a0 move.w #make_art_tile(ArtTile_ArtNem_MenuBox,1,0),d0 bsr.w EniDec lea (Chunk_Table+$330).l,a1 lea (MapEng_LevSelIcon).l,a0 move.w #make_art_tile(ArtTile_ArtNem_LevelSelectPics,0,0),d0 bsr.w EniDec lea (Chunk_Table+$498).l,a2 moveq #$F,d1 - move.w #$207B,(a2)+ dbf d1,- bsr.w Update2PLevSelSelection addq.b #1,(Current_Zone_2P).w andi.b #3,(Current_Zone_2P).w bsr.w ClearOld2PLevSelSelection addq.b #1,(Current_Zone_2P).w andi.b #3,(Current_Zone_2P).w bsr.w ClearOld2PLevSelSelection addq.b #1,(Current_Zone_2P).w andi.b #3,(Current_Zone_2P).w bsr.w ClearOld2PLevSelSelection addq.b #1,(Current_Zone_2P).w andi.b #3,(Current_Zone_2P).w clr.w (Player_mode).w clr.b (Current_Act_2P).w clr.w (Results_Screen_2P).w ; VsRSID_Act clr.b (Level_started_flag).w clr.w (Anim_Counters).w clr.w (Game_Over_2P).w lea (Anim_SonicMilesBG).l,a2 jsrto (Dynamic_Normal).l, JmpTo2_Dynamic_Normal moveq #PalID_Menu,d0 bsr.w PalLoad_ForFade lea (Normal_palette_line3).w,a1 lea (Target_palette_line3).w,a2 moveq #bytesToLcnt($20),d1 - move.l (a1),(a2)+ clr.l (a1)+ dbf d1,- move.b #MusID_Options,d0 jsrto (PlayMusic).l, JmpTo_PlayMusic move.w #$707,(Demo_Time_left).w clr.w (Two_player_mode).w clr.l (Camera_X_pos).w clr.l (Camera_Y_pos).w move.b #VintID_Menu,(Vint_routine).w bsr.w WaitForVint move.w (VDP_Reg1_val).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l bsr.w Pal_FadeFromBlack ;loc_8DA8: LevelSelect2P_Main: move.b #VintID_Menu,(Vint_routine).w bsr.w WaitForVint move #$2700,sr bsr.w ClearOld2PLevSelSelection bsr.w LevelSelect2P_Controls bsr.w Update2PLevSelSelection move #$2300,sr lea (Anim_SonicMilesBG).l,a2 jsrto (Dynamic_Normal).l, JmpTo2_Dynamic_Normal move.b (Ctrl_1_Press).w,d0 or.b (Ctrl_2_Press).w,d0 andi.b #button_start_mask,d0 bne.s LevelSelect2P_PressStart bra.w LevelSelect2P_Main ; =========================================================================== ;loc_8DE2: LevelSelect2P_PressStart: bsr.w Chk2PZoneCompletion bmi.s loc_8DF4 move.w #SndID_Error,d0 jsrto (PlaySound).l, JmpTo_PlaySound bra.w LevelSelect2P_Main ; =========================================================================== loc_8DF4: moveq #0,d0 move.b (Current_Zone_2P).w,d0 add.w d0,d0 move.w LevelSelect2P_LevelOrder(pc,d0.w),d0 bmi.s loc_8E3A move.w d0,(Current_ZoneAndAct).w move.w #1,(Two_player_mode).w move.b #GameModeID_Level,(Game_Mode).w ; => Level (Zone play mode) move.b #0,(Last_star_pole_hit).w move.b #0,(Last_star_pole_hit_2P).w moveq #0,d0 move.l d0,(Score).w move.l d0,(Score_2P).w move.l #5000,(Next_Extra_life_score).w move.l #5000,(Next_Extra_life_score_2P).w rts ; =========================================================================== loc_8E3A: move.b #4,(Current_Special_Stage).w move.b #GameModeID_SpecialStage,(Game_Mode).w ; => SpecialStage moveq #1,d0 move.w d0,(Two_player_mode).w move.w d0,(Two_player_mode_copy).w rts ; =========================================================================== ; word_8E52: LevelSelect2P_LevelOrder: dc.w emerald_hill_zone_act_1 dc.w mystic_cave_zone_act_1 dc.w casino_night_zone_act_1 dc.w $FFFF ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_8E5A: LevelSelect2P_Controls: move.b (Ctrl_1_Press).w,d0 or.b (Ctrl_2_Press).w,d0 move.b d0,d1 andi.b #button_up_mask|button_down_mask,d0 beq.s + bchg #1,(Current_Zone_2P).w + andi.b #button_left_mask|button_right_mask,d1 beq.s + ; rts bchg #0,(Current_Zone_2P).w + rts ; End of function LevelSelect2P_Controls ; --------------------------------------------------------------------------- ; Subroutine to update the 2P level select selection graphically ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_8E7E: Update2PLevSelSelection: moveq #0,d0 move.b (Current_Zone_2P).w,d0 lsl.w #4,d0 ; 16 bytes per entry lea (LevSel2PIconData).l,a3 lea (a3,d0.w),a3 move.w #$6000,d0 ; highlight text lea (Chunk_Table+$48).l,a2 movea.l (a3)+,a1 bsr.w MenuScreenTextToRAM lea (Chunk_Table+$94).l,a2 movea.l (a3)+,a1 bsr.w MenuScreenTextToRAM lea (Chunk_Table+$D8).l,a2 movea.l 4(a3),a1 bsr.w Chk2PZoneCompletion ; has the zone been completed? bmi.s + ; if not, branch lea (Chunk_Table+$468).l,a1 ; display large X instead of icon + moveq #2,d1 - move.l (a1)+,(a2)+ move.l (a1)+,(a2)+ lea $1A(a2),a2 dbf d1,- lea (Chunk_Table).l,a1 move.l (a3)+,d0 moveq #$10,d1 moveq #$B,d2 jsrto (PlaneMapToVRAM_H40).l, JmpTo_PlaneMapToVRAM_H40 lea (Pal_LevelIcons).l,a1 moveq #0,d0 move.b (a3),d0 lsl.w #5,d0 lea (a1,d0.w),a1 lea (Normal_palette_line3).w,a2 moveq #bytesToLcnt(palette_line_size),d1 - move.l (a1)+,(a2)+ dbf d1,- rts ; End of function Update2PLevSelSelection ; --------------------------------------------------------------------------- ; Subroutine to check if a 2P zone has been completed ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_8EFE: Chk2PZoneCompletion: moveq #0,d0 move.b (Current_Zone_2P).w,d0 ; multiply d0 by 6 move.w d0,d1 add.w d0,d0 add.w d1,d0 add.w d0,d0 lea (Results_Data_2P).w,a5 lea (a5,d0.w),a5 move.w (a5),d0 add.w 2(a5),d0 rts ; End of function Chk2PZoneCompletion ; --------------------------------------------------------------------------- ; Subroutine to clear the old 2P level select selection ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_8F1C: ClearOld2PLevSelSelection: moveq #0,d0 move.b (Current_Zone_2P).w,d0 lsl.w #4,d0 lea (LevSel2PIconData).l,a3 lea (a3,d0.w),a3 moveq #0,d0 lea (Chunk_Table+$1E0).l,a2 movea.l (a3)+,a1 bsr.w MenuScreenTextToRAM lea (Chunk_Table+$22C).l,a2 movea.l (a3)+,a1 bsr.w MenuScreenTextToRAM lea (Chunk_Table+$270).l,a2 lea (Chunk_Table+$498).l,a1 bsr.w Chk2PZoneCompletion bmi.s + lea (Chunk_Table+$468).l,a1 + moveq #2,d1 - move.l (a1)+,(a2)+ move.l (a1)+,(a2)+ lea $1A(a2),a2 dbf d1,- lea (Chunk_Table+$198).l,a1 move.l (a3)+,d0 moveq #$10,d1 moveq #$B,d2 jmpto (PlaneMapToVRAM_H40).l, JmpTo_PlaneMapToVRAM_H40 ; End of function ClearOld2PLevSelSelection ; =========================================================================== ; off_8F7E: LevSel2PIconData: ; macro to declare icon data for a 2P level select icon iconData macro txtlabel,txtlabel2,vramAddr,iconPal,iconAddr dc.l txtlabel, txtlabel2 ; text locations dc.l vdpComm(vramAddr,VRAM,WRITE) ; VRAM location to place data dc.l iconPal<<24|iconAddr ; icon palette and plane data location endm iconData Text2P_EmeraldHill,Text2P_Zone,VRAM_Plane_A_Name_Table+planeLocH40(2,2),0,$FF0330 iconData Text2P_MysticCave,Text2P_Zone,VRAM_Plane_A_Name_Table+planeLocH40(22,2),5,$FF03A8 iconData Text2P_CasinoNight,Text2P_Zone,VRAM_Plane_A_Name_Table+planeLocH40(2,15),6,$FF03C0 iconData Text2P_Special,Text2P_Stage,VRAM_Plane_A_Name_Table+planeLocH40(22,15),$C,$FF0450 ; --------------------------------------------------------------------------- ; Common menu screen subroutine for transferring text to RAM ; ARGUMENTS: ; d0 = starting art tile ; a1 = data source ; a2 = destination ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_8FBE: MenuScreenTextToRAM: moveq #0,d1 move.b (a1)+,d1 - move.b (a1)+,d0 move.w d0,(a2)+ dbf d1,- rts ; End of function MenuScreenTextToRAM ; =========================================================================== ; loc_8FCC: MenuScreen_Options: lea (Chunk_Table).l,a1 lea (MapEng_Options).l,a0 move.w #make_art_tile(ArtTile_ArtNem_MenuBox,0,0),d0 bsr.w EniDec lea (Chunk_Table+$160).l,a1 lea (MapEng_Options).l,a0 move.w #make_art_tile(ArtTile_ArtNem_MenuBox,1,0),d0 bsr.w EniDec clr.b (Options_menu_box).w bsr.w OptionScreen_DrawSelected addq.b #1,(Options_menu_box).w bsr.w OptionScreen_DrawUnselected addq.b #1,(Options_menu_box).w bsr.w OptionScreen_DrawUnselected clr.b (Options_menu_box).w clr.b (Level_started_flag).w clr.w (Anim_Counters).w lea (Anim_SonicMilesBG).l,a2 jsrto (Dynamic_Normal).l, JmpTo2_Dynamic_Normal moveq #PalID_Menu,d0 bsr.w PalLoad_ForFade move.b #MusID_Options,d0 jsrto (PlayMusic).l, JmpTo_PlayMusic clr.w (Two_player_mode).w clr.l (Camera_X_pos).w clr.l (Camera_Y_pos).w clr.w (Correct_cheat_entries).w clr.w (Correct_cheat_entries_2).w move.b #VintID_Menu,(Vint_routine).w bsr.w WaitForVint move.w (VDP_Reg1_val).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l bsr.w Pal_FadeFromBlack ; loc_9060: OptionScreen_Main: move.b #VintID_Menu,(Vint_routine).w bsr.w WaitForVint move #$2700,sr bsr.w OptionScreen_DrawUnselected bsr.w OptionScreen_Controls bsr.w OptionScreen_DrawSelected move #$2300,sr lea (Anim_SonicMilesBG).l,a2 jsrto (Dynamic_Normal).l, JmpTo2_Dynamic_Normal move.b (Ctrl_1_Press).w,d0 or.b (Ctrl_2_Press).w,d0 andi.b #button_start_mask,d0 bne.s OptionScreen_Select bra.w OptionScreen_Main ; =========================================================================== ; loc_909A: OptionScreen_Select: move.b (Options_menu_box).w,d0 bne.s OptionScreen_Select_Not1P ; Start a single player game moveq #0,d0 move.w d0,(Two_player_mode).w move.w d0,(Two_player_mode_copy).w move.w d0,(Current_ZoneAndAct).w ; emerald_hill_zone_act_1 move.b #GameModeID_Level,(Game_Mode).w ; => Level (Zone play mode) rts ; =========================================================================== ; loc_90B6: OptionScreen_Select_Not1P: subq.b #1,d0 bne.s OptionScreen_Select_Other ; Start a 2P VS game moveq #1,d0 move.w d0,(Two_player_mode).w move.w d0,(Two_player_mode_copy).w move.b #GameModeID_2PLevelSelect,(Game_Mode).w ; => LevelSelectMenu2P move.b #0,(Current_Zone_2P).w move.w #0,(Player_mode).w rts ; =========================================================================== ; loc_90D8: OptionScreen_Select_Other: ; When pressing START on the sound test option, return to the SEGA screen move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_90E0: OptionScreen_Controls: moveq #0,d2 move.b (Options_menu_box).w,d2 move.b (Ctrl_1_Press).w,d0 or.b (Ctrl_2_Press).w,d0 btst #button_up,d0 beq.s + subq.b #1,d2 bcc.s + move.b #2,d2 + btst #button_down,d0 beq.s + addq.b #1,d2 cmpi.b #3,d2 blo.s + moveq #0,d2 + move.b d2,(Options_menu_box).w lsl.w #2,d2 move.b OptionScreen_Choices(pc,d2.w),d3 ; number of choices for the option movea.l OptionScreen_Choices(pc,d2.w),a1 ; location where the choice is stored (in RAM) move.w (a1),d2 btst #button_left,d0 beq.s + subq.b #1,d2 bcc.s + move.b d3,d2 + btst #button_right,d0 beq.s + addq.b #1,d2 cmp.b d3,d2 bls.s + moveq #0,d2 + btst #button_A,d0 beq.s + addi.b #$10,d2 cmp.b d3,d2 bls.s + moveq #0,d2 + move.w d2,(a1) cmpi.b #2,(Options_menu_box).w bne.s + ; rts andi.w #button_B_mask|button_C_mask,d0 beq.s + ; rts move.w (Sound_test_sound).w,d0 addi.w #$80,d0 jsrto (PlayMusic).l, JmpTo_PlayMusic lea (level_select_cheat).l,a0 lea (continues_cheat).l,a2 lea (Level_select_flag).w,a1 moveq #0,d2 ; flag to tell the routine to enable the continues cheat bsr.w CheckCheats + rts ; End of function OptionScreen_Controls ; =========================================================================== ; word_917A: OptionScreen_Choices: dc.l (3-1)<<24|(Player_option&$FFFFFF) dc.l (2-1)<<24|(Two_player_items&$FFFFFF) dc.l ($80-1)<<24|(Sound_test_sound&$FFFFFF) ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_9186 OptionScreen_DrawSelected: bsr.w OptionScreen_SelectTextPtr moveq #0,d1 move.b (Options_menu_box).w,d1 lsl.w #3,d1 lea (OptScrBoxData).l,a3 lea (a3,d1.w),a3 move.w #palette_line_3,d0 lea (Chunk_Table+$30).l,a2 movea.l (a3)+,a1 bsr.w MenuScreenTextToRAM lea (Chunk_Table+$B6).l,a2 moveq #0,d1 cmpi.b #2,(Options_menu_box).w beq.s + move.b (Options_menu_box).w,d1 lsl.w #2,d1 lea OptionScreen_Choices(pc),a1 movea.l (a1,d1.w),a1 move.w (a1),d1 lsl.w #2,d1 + movea.l (a4,d1.w),a1 bsr.w MenuScreenTextToRAM cmpi.b #2,(Options_menu_box).w bne.s + lea (Chunk_Table+$C2).l,a2 bsr.w OptionScreen_HexDumpSoundTest + lea (Chunk_Table).l,a1 move.l (a3)+,d0 moveq #$15,d1 moveq #7,d2 jmpto (PlaneMapToVRAM_H40).l, JmpTo_PlaneMapToVRAM_H40 ; =========================================================================== ;loc_91F8 OptionScreen_DrawUnselected: bsr.w OptionScreen_SelectTextPtr moveq #0,d1 move.b (Options_menu_box).w,d1 lsl.w #3,d1 lea (OptScrBoxData).l,a3 lea (a3,d1.w),a3 moveq #palette_line_0,d0 lea (Chunk_Table+$190).l,a2 movea.l (a3)+,a1 bsr.w MenuScreenTextToRAM lea (Chunk_Table+$216).l,a2 moveq #0,d1 cmpi.b #2,(Options_menu_box).w beq.s + move.b (Options_menu_box).w,d1 lsl.w #2,d1 lea OptionScreen_Choices(pc),a1 movea.l (a1,d1.w),a1 move.w (a1),d1 lsl.w #2,d1 + movea.l (a4,d1.w),a1 bsr.w MenuScreenTextToRAM cmpi.b #2,(Options_menu_box).w bne.s + lea (Chunk_Table+$222).l,a2 bsr.w OptionScreen_HexDumpSoundTest + lea (Chunk_Table+$160).l,a1 move.l (a3)+,d0 moveq #$15,d1 moveq #7,d2 jmpto (PlaneMapToVRAM_H40).l, JmpTo_PlaneMapToVRAM_H40 ; =========================================================================== ;loc_9268 OptionScreen_SelectTextPtr: lea (off_92D2).l,a4 tst.b (Graphics_Flags).w bpl.s + lea (off_92DE).l,a4 + tst.b (Options_menu_box).w beq.s + lea (off_92EA).l,a4 + cmpi.b #2,(Options_menu_box).w bne.s + ; rts lea (off_92F2).l,a4 + rts ; =========================================================================== ;loc_9296 OptionScreen_HexDumpSoundTest: move.w (Sound_test_sound).w,d1 move.b d1,d2 lsr.b #4,d1 bsr.s + move.b d2,d1 + andi.w #$F,d1 cmpi.b #$A,d1 blo.s + addi.b #4,d1 + addi.b #$10,d1 move.b d1,d0 move.w d0,(a2)+ rts ; =========================================================================== ; off_92BA: OptScrBoxData: ; macro to declare the data for an options screen box boxData macro txtlabel,vramAddr dc.l txtlabel, vdpComm(vramAddr,VRAM,WRITE) endm boxData TextOptScr_PlayerSelect,VRAM_Plane_A_Name_Table+planeLocH40(9,3) boxData TextOptScr_VsModeItems,VRAM_Plane_A_Name_Table+planeLocH40(9,11) boxData TextOptScr_SoundTest,VRAM_Plane_A_Name_Table+planeLocH40(9,19) off_92D2: dc.l TextOptScr_SonicAndMiles dc.l TextOptScr_SonicAlone dc.l TextOptScr_MilesAlone off_92DE: dc.l TextOptScr_SonicAndTails dc.l TextOptScr_SonicAlone dc.l TextOptScr_TailsAlone off_92EA: dc.l TextOptScr_AllKindsItems dc.l TextOptScr_TeleportOnly off_92F2: dc.l TextOptScr_0 ; =========================================================================== ; loc_92F6: MenuScreen_LevelSelect: ; Load foreground (sans zone icon) lea (Chunk_Table).l,a1 lea (MapEng_LevSel).l,a0 ; 2 bytes per 8x8 tile, compressed move.w #make_art_tile(ArtTile_VRAM_Start,0,0),d0 bsr.w EniDec lea (Chunk_Table).l,a1 move.l #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE),d0 moveq #$27,d1 moveq #$1B,d2 ; 40x28 = whole screen jsrto (PlaneMapToVRAM_H40).l, JmpTo_PlaneMapToVRAM_H40 ; display patterns ; Draw sound test number moveq #palette_line_0,d3 bsr.w LevelSelect_DrawSoundNumber ; Load zone icon lea (Chunk_Table+$8C0).l,a1 lea (MapEng_LevSelIcon).l,a0 move.w #make_art_tile(ArtTile_ArtNem_LevelSelectPics,0,0),d0 bsr.w EniDec bsr.w LevelSelect_DrawIcon clr.w (Player_mode).w clr.w (Results_Screen_2P).w ; VsRSID_Act clr.b (Level_started_flag).w clr.w (Anim_Counters).w ; Animate background (loaded back in MenuScreen) lea (Anim_SonicMilesBG).l,a2 jsrto (Dynamic_Normal).l, JmpTo2_Dynamic_Normal ; background moveq #PalID_Menu,d0 bsr.w PalLoad_ForFade lea (Normal_palette_line3).w,a1 lea (Target_palette_line3).w,a2 moveq #bytesToLcnt(palette_line_size),d1 - move.l (a1),(a2)+ clr.l (a1)+ dbf d1,- move.b #MusID_Options,d0 jsrto (PlayMusic).l, JmpTo_PlayMusic move.w #$707,(Demo_Time_left).w clr.w (Two_player_mode).w clr.l (Camera_X_pos).w clr.l (Camera_Y_pos).w clr.w (Correct_cheat_entries).w clr.w (Correct_cheat_entries_2).w move.b #VintID_Menu,(Vint_routine).w bsr.w WaitForVint move.w (VDP_Reg1_val).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l bsr.w Pal_FadeFromBlack ;loc_93AC: LevelSelect_Main: ; routine running during level select move.b #VintID_Menu,(Vint_routine).w bsr.w WaitForVint move #$2700,sr moveq #palette_line_0-palette_line_0,d3 ; palette line << 13 bsr.w LevelSelect_MarkFields ; unmark fields bsr.w LevSelControls ; possible change selected fields move.w #palette_line_3-palette_line_0,d3 ; palette line << 13 bsr.w LevelSelect_MarkFields ; mark fields bsr.w LevelSelect_DrawIcon move #$2300,sr lea (Anim_SonicMilesBG).l,a2 jsrto (Dynamic_Normal).l, JmpTo2_Dynamic_Normal move.b (Ctrl_1_Press).w,d0 or.b (Ctrl_2_Press).w,d0 andi.b #button_start_mask,d0 ; start pressed? bne.s LevelSelect_PressStart ; yes bra.w LevelSelect_Main ; no ; =========================================================================== ;loc_93F0: LevelSelect_PressStart: move.w (Level_select_zone).w,d0 add.w d0,d0 move.w LevelSelect_Order(pc,d0.w),d0 bmi.w LevelSelect_Return ; sound test cmpi.w #$4000,d0 bne.s LevelSelect_StartZone ;LevelSelect_SpecialStage: move.b #GameModeID_SpecialStage,(Game_Mode).w ; => SpecialStage clr.w (Current_ZoneAndAct).w move.b #3,(Life_count).w move.b #3,(Life_count_2P).w moveq #0,d0 move.w d0,(Ring_count).w move.l d0,(Timer).w move.l d0,(Score).w move.w d0,(Ring_count_2P).w move.l d0,(Timer_2P).w move.l d0,(Score_2P).w move.l #5000,(Next_Extra_life_score).w move.l #5000,(Next_Extra_life_score_2P).w move.w (Player_option).w,(Player_mode).w rts ; =========================================================================== ;loc_944C: LevelSelect_Return: move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen rts ; =========================================================================== ; ----------------------------------------------------------------------------- ; Level Select Level Order ; One entry per item in the level select menu. Just set the value for the item ; you want to link to the level/act number of the level you want to load when ; the player selects that item. ; ----------------------------------------------------------------------------- ;Misc_9454: LevelSelect_Order: dc.w emerald_hill_zone_act_1 dc.w emerald_hill_zone_act_2 ; 1 dc.w chemical_plant_zone_act_1 ; 2 dc.w chemical_plant_zone_act_2 ; 3 dc.w aquatic_ruin_zone_act_1 ; 4 dc.w aquatic_ruin_zone_act_2 ; 5 dc.w casino_night_zone_act_1 ; 6 dc.w casino_night_zone_act_2 ; 7 dc.w hill_top_zone_act_1 ; 8 dc.w hill_top_zone_act_2 ; 9 dc.w mystic_cave_zone_act_1 ; 10 dc.w mystic_cave_zone_act_2 ; 11 dc.w oil_ocean_zone_act_1 ; 12 dc.w oil_ocean_zone_act_2 ; 13 dc.w metropolis_zone_act_1 ; 14 dc.w metropolis_zone_act_2 ; 15 dc.w metropolis_zone_act_3 ; 16 dc.w sky_chase_zone_act_1 ; 17 dc.w wing_fortress_zone_act_1 ; 18 dc.w death_egg_zone_act_1 ; 19 dc.w $4000 ; 20 - special stage dc.w $FFFF ; 21 - sound test ; =========================================================================== ;loc_9480: LevelSelect_StartZone: andi.w #$3FFF,d0 move.w d0,(Current_ZoneAndAct).w move.b #GameModeID_Level,(Game_Mode).w ; => Level (Zone play mode) move.b #3,(Life_count).w move.b #3,(Life_count_2P).w moveq #0,d0 move.w d0,(Ring_count).w move.l d0,(Timer).w move.l d0,(Score).w move.w d0,(Ring_count_2P).w move.l d0,(Timer_2P).w move.l d0,(Score_2P).w move.b d0,(Continue_count).w move.l #5000,(Next_Extra_life_score).w move.l #5000,(Next_Extra_life_score_2P).w move.b #MusID_FadeOut,d0 jsrto (PlaySound).l, JmpTo_PlaySound moveq #0,d0 move.w d0,(Two_player_mode_copy).w move.w d0,(Two_player_mode).w rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Change what you're selecting in the level select ; --------------------------------------------------------------------------- ; loc_94DC: LevSelControls: move.b (Ctrl_1_Press).w,d1 andi.b #button_up_mask|button_down_mask,d1 bne.s + ; up/down pressed subq.w #1,(LevSel_HoldTimer).w bpl.s LevSelControls_CheckLR + move.w #$B,(LevSel_HoldTimer).w move.b (Ctrl_1_Held).w,d1 andi.b #button_up_mask|button_down_mask,d1 beq.s LevSelControls_CheckLR ; up/down not pressed, check for left & right move.w (Level_select_zone).w,d0 btst #button_up,d1 beq.s + subq.w #1,d0 ; decrease by 1 bcc.s + ; >= 0? moveq #$15,d0 ; set to $15 + btst #button_down,d1 beq.s + addq.w #1,d0 ; yes, add 1 cmpi.w #$16,d0 blo.s + ; smaller than $16? moveq #0,d0 ; if not, set to 0 + move.w d0,(Level_select_zone).w rts ; =========================================================================== ; loc_9522: LevSelControls_CheckLR: cmpi.w #$15,(Level_select_zone).w ; are we in the sound test? bne.s LevSelControls_SwitchSide ; no move.w (Sound_test_sound).w,d0 move.b (Ctrl_1_Press).w,d1 btst #button_left,d1 beq.s + subq.b #1,d0 bcc.s + moveq #$7F,d0 + btst #button_right,d1 beq.s + addq.b #1,d0 cmpi.w #$80,d0 blo.s + moveq #0,d0 + btst #button_A,d1 beq.s + addi.b #$10,d0 andi.b #$7F,d0 + move.w d0,(Sound_test_sound).w andi.w #button_B_mask|button_C_mask,d1 beq.s + ; rts move.w (Sound_test_sound).w,d0 addi.w #$80,d0 jsrto (PlayMusic).l, JmpTo_PlayMusic lea (debug_cheat).l,a0 lea (super_sonic_cheat).l,a2 lea (Debug_options_flag).w,a1 moveq #1,d2 ; flag to tell the routine to enable the Super Sonic cheat bsr.w CheckCheats + rts ; =========================================================================== ; loc_958A: LevSelControls_SwitchSide: ; not in soundtest, not up/down pressed move.b (Ctrl_1_Press).w,d1 andi.b #button_left_mask|button_right_mask,d1 beq.s + ; no direction key pressed move.w (Level_select_zone).w,d0 ; left or right pressed move.b LevelSelect_SwitchTable(pc,d0.w),d0 ; set selected zone according to table move.w d0,(Level_select_zone).w + rts ; =========================================================================== ;byte_95A2: LevelSelect_SwitchTable: dc.b $E dc.b $F ; 1 dc.b $11 ; 2 dc.b $11 ; 3 dc.b $12 ; 4 dc.b $12 ; 5 dc.b $13 ; 6 dc.b $13 ; 7 dc.b $14 ; 8 dc.b $14 ; 9 dc.b $15 ; 10 dc.b $15 ; 11 dc.b $C ; 12 dc.b $D ; 13 dc.b 0 ; 14 dc.b 1 ; 15 dc.b 1 ; 16 dc.b 2 ; 17 dc.b 4 ; 18 dc.b 6 ; 19 dc.b 8 ; 20 dc.b $A ; 21 even ; =========================================================================== ;loc_95B8: LevelSelect_MarkFields: lea (Chunk_Table).l,a4 lea (LevSel_MarkTable).l,a5 lea (VDP_data_port).l,a6 moveq #0,d0 move.w (Level_select_zone).w,d0 lsl.w #2,d0 lea (a5,d0.w),a3 moveq #0,d0 move.b (a3),d0 mulu.w #$50,d0 moveq #0,d1 move.b 1(a3),d1 add.w d1,d0 lea (a4,d0.w),a1 moveq #0,d1 move.b (a3),d1 lsl.w #7,d1 add.b 1(a3),d1 addi.w #VRAM_Plane_A_Name_Table,d1 lsl.l #2,d1 lsr.w #2,d1 ori.w #vdpComm($0000,VRAM,WRITE)>>16,d1 swap d1 move.l d1,4(a6) moveq #$D,d2 - move.w (a1)+,d0 add.w d3,d0 move.w d0,(a6) dbf d2,- addq.w #2,a3 moveq #0,d0 move.b (a3),d0 beq.s + mulu.w #$50,d0 moveq #0,d1 move.b 1(a3),d1 add.w d1,d0 lea (a4,d0.w),a1 moveq #0,d1 move.b (a3),d1 lsl.w #7,d1 add.b 1(a3),d1 addi.w #VRAM_Plane_A_Name_Table,d1 lsl.l #2,d1 lsr.w #2,d1 ori.w #vdpComm($0000,VRAM,WRITE)>>16,d1 swap d1 move.l d1,4(a6) move.w (a1)+,d0 add.w d3,d0 move.w d0,(a6) + cmpi.w #$15,(Level_select_zone).w bne.s + ; rts bsr.w LevelSelect_DrawSoundNumber + rts ; =========================================================================== ;loc_965A: LevelSelect_DrawSoundNumber: move.l #vdpComm(VRAM_Plane_A_Name_Table+planeLocH40(34,18),VRAM,WRITE),(VDP_control_port).l move.w (Sound_test_sound).w,d0 move.b d0,d2 lsr.b #4,d0 bsr.s + move.b d2,d0 + andi.w #$F,d0 cmpi.b #$A,d0 blo.s + addi.b #4,d0 + addi.b #$10,d0 add.w d3,d0 move.w d0,(a6) rts ; =========================================================================== ;loc_9688: LevelSelect_DrawIcon: move.w (Level_select_zone).w,d0 lea (LevSel_IconTable).l,a3 lea (a3,d0.w),a3 lea (Chunk_Table+$8C0).l,a1 moveq #0,d0 move.b (a3),d0 lsl.w #3,d0 move.w d0,d1 add.w d0,d0 add.w d1,d0 lea (a1,d0.w),a1 move.l #vdpComm(VRAM_Plane_A_Name_Table+planeLocH40(27,22),VRAM,WRITE),d0 moveq #3,d1 moveq #2,d2 jsrto (PlaneMapToVRAM_H40).l, JmpTo_PlaneMapToVRAM_H40 lea (Pal_LevelIcons).l,a1 moveq #0,d0 move.b (a3),d0 lsl.w #5,d0 lea (a1,d0.w),a1 lea (Normal_palette_line3).w,a2 moveq #bytesToLcnt(palette_line_size),d1 - move.l (a1)+,(a2)+ dbf d1,- rts ; =========================================================================== ;byte_96D8 LevSel_IconTable: dc.b 0,0 ;0 EHZ dc.b 7,7 ;2 CPZ dc.b 8,8 ;4 ARZ dc.b 6,6 ;6 CNZ dc.b 2,2 ;8 HTZ dc.b 5,5 ;$A MCZ dc.b 4,4 ;$C OOZ dc.b 1,1,1 ;$E MTZ dc.b 9 ;$11 SCZ dc.b $A ;$12 WFZ dc.b $B ;$13 DEZ dc.b $C ;$14 Special Stage dc.b $E ;$15 Sound Test even ;byte_96EE: LevSel_MarkTable: ; 4 bytes per level select entry ; line primary, 2*column ($E fields), line secondary, 2*column secondary (1 field) dc.b 3, 6, 3,$24 ;0 dc.b 3, 6, 4,$24 dc.b 6, 6, 6,$24 dc.b 6, 6, 7,$24 dc.b 9, 6, 9,$24 ;4 dc.b 9, 6, $A,$24 dc.b $C, 6, $C,$24 dc.b $C, 6, $D,$24 dc.b $F, 6, $F,$24 ;8 dc.b $F, 6,$10,$24 dc.b $12, 6,$12,$24 dc.b $12, 6,$13,$24 dc.b $15, 6,$15,$24 ;$C dc.b $15, 6,$16,$24 ; --- second column --- dc.b 3,$2C, 3,$48 dc.b 3,$2C, 4,$48 dc.b 3,$2C, 5,$48 ;$10 dc.b 6,$2C, 0, 0 dc.b 9,$2C, 0, 0 dc.b $C,$2C, 0, 0 dc.b $F,$2C, 0, 0 ;$14 dc.b $12,$2C,$12,$48 ; =========================================================================== ; loc_9746: CheckCheats: ; This is called from 2 places: the options screen and the level select screen move.w (Correct_cheat_entries).w,d0 ; Get the number of correct sound IDs entered so far adda.w d0,a0 ; Skip to the next entry move.w (Sound_test_sound).w,d0 ; Get the current sound test sound cmp.b (a0),d0 ; Compare it to the cheat bne.s + ; If they're different, branch addq.w #1,(Correct_cheat_entries).w ; Add 1 to the number of correct entries tst.b 1(a0) ; Is the next entry 0? bne.s ++ ; If not, branch move.w #$101,(a1) ; Enable the cheat move.b #SndID_Ring,d0 ; Play the ring sound jsrto (PlaySound).l, JmpTo_PlaySound + move.w #0,(Correct_cheat_entries).w ; Clear the number of correct entries + move.w (Correct_cheat_entries_2).w,d0 ; Do the same procedure with the other cheat adda.w d0,a2 move.w (Sound_test_sound).w,d0 cmp.b (a2),d0 bne.s ++ addq.w #1,(Correct_cheat_entries_2).w tst.b 1(a2) bne.s +++ ; rts tst.w d2 ; Test this to determine which cheat to enable bne.s + ; If not 0, branch move.b #$F,(Continue_count).w ; Give 15 continues ; The next line causes the bug where the OOZ music plays until reset. ; Remove "&$7F" to fix the bug. move.b #SndID_ContinueJingle&$7F,d0 ; Play the continue jingle jsrto (PlayMusic).l, JmpTo_PlayMusic bra.s ++ ; =========================================================================== + move.w #7,(Got_Emerald).w ; Give 7 emeralds to the player move.b #MusID_Emerald,d0 ; Play the emerald jingle jsrto (PlayMusic).l, JmpTo_PlayMusic + move.w #0,(Correct_cheat_entries_2).w ; Clear the number of correct entries + rts ; =========================================================================== level_select_cheat: dc.b $19, $65, 9, $17, 0 ; 17th September 1965, Yuji Naka's birthdate rev02even ; byte_97B7 continues_cheat: dc.b 1, 1, 2, 4, 0 ; 24th November, Sonic 2's release date in the EU and US: "Sonic 2sday" rev02even debug_cheat: dc.b 1, 9, 9, 2, 1, 1, 2, 4, 0 ; 24th November 1992, Sonic 2's release date in the EU and US: "Sonic 2sday" rev02even ; byte_97C5 super_sonic_cheat: dc.b 4, 1, 2, 6, 0 ; Book of Genesis, 41:26 rev02even ; set the character set for menu text charset '@',"\27\30\31\32\33\34\35\36\37\38\39\40\41\42\43\44\45\46\47\48\49\50\51\52\53\54\55" charset '0',"\16\17\18\19\20\21\22\23\24\25" charset '*',$1A charset ':',$1C charset '.',$1D charset ' ',0 ; options screen menu text TextOptScr_PlayerSelect: menutxt "* PLAYER SELECT *" ; byte_97CA: TextOptScr_SonicAndMiles: menutxt "SONIC AND MILES" ; byte_97DC: TextOptScr_SonicAndTails: menutxt "SONIC AND TAILS" ; byte_97EC: TextOptScr_SonicAlone: menutxt "SONIC ALONE " ; byte_97FC: TextOptScr_MilesAlone: menutxt "MILES ALONE " ; byte_980C: TextOptScr_TailsAlone: menutxt "TAILS ALONE " ; byte_981C: TextOptScr_VsModeItems: menutxt "* VS MODE ITEMS *" ; byte_982C: TextOptScr_AllKindsItems: menutxt "ALL KINDS ITEMS" ; byte_983E: TextOptScr_TeleportOnly: menutxt "TELEPORT ONLY " ; byte_984E: TextOptScr_SoundTest: menutxt "* SOUND TEST *" ; byte_985E: TextOptScr_0: menutxt " 00 " ; byte_9870: charset ; reset character set ; level select picture palettes ; byte_9880: Pal_LevelIcons: BINCLUDE "art/palettes/Level Select Icons.bin" ; 2-player level select screen mappings (Enigma compressed) ; byte_9A60: MapEng_LevSel2P: BINCLUDE "mappings/misc/Level Select 2P.bin" ; options screen mappings (Enigma compressed) ; byte_9AB2: MapEng_Options: BINCLUDE "mappings/misc/Options Screen.bin" ; level select screen mappings (Enigma compressed) ; byte_9ADE: MapEng_LevSel: BINCLUDE "mappings/misc/Level Select.bin" ; 1P and 2P level select icon mappings (Enigma compressed) ; byte_9C32: MapEng_LevSelIcon: BINCLUDE "mappings/misc/Level Select Icons.bin" if ~~removeJmpTos JmpTo_PlaySound jmp (PlaySound).l JmpTo_PlayMusic jmp (PlayMusic).l ; loc_9C70: JmpTo_PlaneMapToVRAM JmpTo_PlaneMapToVRAM_H40 jmp (PlaneMapToVRAM_H40).l JmpTo2_Dynamic_Normal jmp (Dynamic_Normal).l align 4 endif ; =========================================================================== ; loc_9C7C: EndingSequence: clearRAM EndSeq_Object_RAM,EndSeq_Object_RAM_End clearRAM Misc_Variables,Misc_Variables_End clearRAM Camera_RAM,Camera_RAM_End move #$2700,sr move.w (VDP_Reg1_val).w,d0 andi.b #$BF,d0 move.w d0,(VDP_control_port).l stopZ80 dmaFillVRAM 0,VRAM_Plane_A_Name_Table,VRAM_Plane_Table_Size ; clear Plane A pattern name table clr.l (Vscroll_Factor).w clr.l (unk_F61A).w startZ80 lea (VDP_control_port).l,a6 move.w #$8B03,(a6) ; EXT-INT disabled, V scroll by screen, H scroll by line move.w #$8200|(VRAM_EndSeq_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000 move.w #$8400|(VRAM_EndSeq_Plane_B_Name_Table1/$2000),(a6) ; PNT B base: $E000 move.w #$8500|(VRAM_Sprite_Attribute_Table/$200),(a6) ; Sprite attribute table base: $F800 move.w #$9001,(a6) ; Scroll table size: 64x32 move.w #$8004,(a6) ; H-INT disabled move.w #$8720,(a6) ; Background palette/color: 2/0 move.w #$8ADF,(Hint_counter_reserve).w ; H-INT every 224th scanline move.w (Hint_counter_reserve).w,(a6) clr.b (Super_Sonic_flag).w cmpi.b #7,(Emerald_count).w bne.s + cmpi.w #2,(Player_mode).w beq.s + st (Super_Sonic_flag).w move.b #-1,(Super_Sonic_palette).w move.b #$F,(Palette_timer).w move.w #$30,(Palette_frame).w + moveq #0,d0 cmpi.w #2,(Player_mode).w beq.s + tst.b (Super_Sonic_flag).w bne.s ++ bra.w +++ ; =========================================================================== + addq.w #2,d0 + addq.w #2,d0 + move.w d0,(Ending_Routine).w bsr.w EndingSequence_LoadCharacterArt bsr.w EndingSequence_LoadFlickyArt move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_EndingFinalTornado),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_EndingFinalTornado).l,a0 jsrto (NemDec).l, JmpTo_NemDec move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_EndingPics),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_EndingPics).l,a0 jsrto (NemDec).l, JmpTo_NemDec move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_EndingMiniTornado),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_EndingMiniTornado).l,a0 jsrto (NemDec).l, JmpTo_NemDec move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Tornado),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_Tornado).l,a0 jsrto (NemDec).l, JmpTo_NemDec move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Clouds),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_Clouds).l,a0 jsrto (NemDec).l, JmpTo_NemDec move.w #death_egg_zone_act_1,(Current_ZoneAndAct).w move #$2300,sr moveq #MusID_Ending,d0 jsrto (PlayMusic).l, JmpTo2_PlayMusic move.l #$EEE0EEE,d1 lea (Normal_palette).w,a1 moveq #bytesToLcnt(palette_line_size*4),d0 - move.l d1,(a1)+ dbf d0,- lea (Pal_AC7E).l,a1 lea (Target_palette).w,a2 moveq #bytesToLcnt(palette_line_size*4),d0 - move.l (a1)+,(a2)+ dbf d0,- clr.b (Screen_Shaking_Flag).w moveq #0,d0 move.w d0,(Debug_placement_mode).w move.w d0,(Level_Inactive_flag).w move.w d0,(Timer_frames).w move.w d0,(Camera_X_pos).w move.w d0,(Camera_Y_pos).w move.w d0,(Camera_X_pos_copy).w move.w d0,(Camera_Y_pos_copy).w move.w d0,(Camera_BG_X_pos).w move.w #$C8,(Camera_BG_Y_pos).w move.l d0,(Vscroll_Factor).w move.b d0,(Horiz_block_crossed_flag_BG).w move.b d0,(Verti_block_crossed_flag_BG).w move.w d0,(Ending_VInt_Subrout).w move.w d0,(Credits_Trigger).w ; Bug: The '+4' shouldn't be here; clearRAM accidentally clears an additional 4 bytes clearRAM Horiz_Scroll_Buf,Horiz_Scroll_Buf_End+4 move.w #$7FFF,(PalCycle_Timer).w lea (CutScene).w,a1 move.b #ObjID_CutScene,id(a1) ; load objCA (end of game cutscene) at $FFFFB100 move.b #6,routine(a1) move.w #$60,objoff_3C(a1) move.w #1,objoff_30(a1) cmpi.w #4,(Ending_Routine).w bne.s + move.w #$10,objoff_2E(a1) move.w #$100,objoff_3C(a1) + move.b #VintID_Ending,(Vint_routine).w bsr.w WaitForVint move.w (VDP_Reg1_val).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l - move.b #VintID_Ending,(Vint_routine).w bsr.w WaitForVint addq.w #1,(Timer_frames).w jsr (RandomNumber).l jsr (RunObjects).l jsr (BuildSprites).l tst.b (Ending_PalCycle_flag).w beq.s + jsrto (PalCycle_Load).l, JmpTo_PalCycle_Load + bsr.w EndgameCredits tst.w (Level_Inactive_flag).w beq.w - rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_9EF4 EndgameCredits: tst.b (Credits_Trigger).w beq.w +++ ; rts bsr.w Pal_FadeToBlack lea (VDP_control_port).l,a6 move.w #$8004,(a6) ; H-INT disabled move.w #$8200|(VRAM_EndSeq_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000 move.w #$8400|(VRAM_EndSeq_Plane_B_Name_Table1/$2000),(a6) ; PNT B base: $E000 move.w #$9001,(a6) ; Scroll table size: 64x32 move.w #$9200,(a6) ; Disable window move.w #$8B03,(a6) ; EXT-INT disabled, V scroll by screen, H scroll by line move.w #$8700,(a6) ; Background palette/color: 0/0 clr.b (Water_fullscreen_flag).w move.w #$8C81,(a6) ; H res 40 cells, no interlace, S/H disabled jsrto (ClearScreen).l, JmpTo_ClearScreen clearRAM Sprite_Table_Input,Sprite_Table_Input_End clearRAM EndSeq_Object_RAM,EndSeq_Object_RAM_End clearRAM Misc_Variables,Misc_Variables_End clearRAM Camera_RAM,Camera_RAM_End clr.b (Screen_Shaking_Flag).w moveq #0,d0 move.w d0,(Level_Inactive_flag).w move.w d0,(Timer_frames).w move.w d0,(Camera_X_pos).w move.w d0,(Camera_Y_pos).w move.w d0,(Camera_X_pos_copy).w move.w d0,(Camera_Y_pos_copy).w move.w d0,(Camera_BG_X_pos).w move.w d0,(Camera_BG_Y_pos).w move.l d0,(Vscroll_Factor).w move.b d0,(Horiz_block_crossed_flag_BG).w move.b d0,(Verti_block_crossed_flag_BG).w move.w d0,(Ending_VInt_Subrout).w move.w d0,(Credits_Trigger).w ; Bug: The '+4' shouldn't be here; clearRAM accidentally clears an additional 4 bytes clearRAM Horiz_Scroll_Buf,Horiz_Scroll_Buf_End+4 moveq #MusID_Credits,d0 jsrto (PlaySound).l, JmpTo2_PlaySound clr.w (Target_palette).w move.w #$EEE,(Target_palette+$C).w move.w #$EE,(Target_palette_line2+$C).w move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_CreditText_CredScr),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_CreditText).l,a0 jsrto (NemDec).l, JmpTo_NemDec clr.w (CreditsScreenIndex).w - jsrto (ClearScreen).l, JmpTo_ClearScreen bsr.w ShowCreditsScreen bsr.w Pal_FadeFromBlack ; Here's how to calculate new duration values for the below instructions. ; Each slide of the credits is displayed for $18E frames at 60 FPS, or $144 frames at 50 FPS. ; We also need to take into account how many frames the fade-in/fade-out take: which is $16 each. ; Also, there are 21 slides to display. ; That said, by doing '($18E+$16+$16)*21', we get the total number of frames it takes until ; the credits reach the Sonic 2 splash (which is technically not an actual slide in the credits). ; Dividing this by 60 will give us how many seconds it takes. The result being 154.7. ; Doing the same for 50 FPS, by dividing the result of '($144+$16+$16)*21' by 50, will give us 154.56. ; Now that we have the time it should take for the credits to end, we can adjust the calculation to account ; for any slides we may have added. For example, if you added a slide, bringing the total to 22, ; performing '((154.7*60)/22)-($16+$16)' will give you the new value to put in the 'move.w' instruction below. move.w #$18E,d0 btst #6,(Graphics_Flags).w beq.s + move.w #$144,d0 / move.b #VintID_Ending,(Vint_routine).w bsr.w WaitForVint dbf d0,- bsr.w Pal_FadeToBlack lea (off_B2CA).l,a1 addq.w #1,(CreditsScreenIndex).w move.w (CreditsScreenIndex).w,d0 lsl.w #2,d0 move.l (a1,d0.w),d0 bpl.s -- bsr.w Pal_FadeToBlack jsrto (ClearScreen).l, JmpTo_ClearScreen move.l #vdpComm($0000,VRAM,WRITE),(VDP_control_port).l lea (ArtNem_EndingTitle).l,a0 jsrto (NemDec).l, JmpTo_NemDec lea (MapEng_EndGameLogo).l,a0 lea (Chunk_Table).l,a1 move.w #0,d0 jsrto (EniDec).l, JmpTo_EniDec lea (Chunk_Table).l,a1 move.l #vdpComm(VRAM_Plane_A_Name_Table+planeLocH40(12,11),VRAM,WRITE),d0 moveq #$F,d1 moveq #5,d2 jsrto (PlaneMapToVRAM_H40).l, JmpTo2_PlaneMapToVRAM_H40 clr.w (CreditsScreenIndex).w bsr.w EndgameLogoFlash move.w #$3B,d0 - move.b #VintID_Ending,(Vint_routine).w bsr.w WaitForVint dbf d0,- move.w #$257,d6 - move.b #VintID_Ending,(Vint_routine).w bsr.w WaitForVint addq.w #1,(CreditsScreenIndex).w bsr.w EndgameLogoFlash cmpi.w #$5E,(CreditsScreenIndex).w blo.s - move.b (Ctrl_1_Press).w,d1 andi.b #button_B_mask|button_C_mask|button_A_mask|button_start_mask,d1 bne.s + dbf d6,- + st (Level_Inactive_flag).w move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen / rts ; End of function sub_9EF4 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_A0C0 EndgameLogoFlash: lea (Normal_palette+2).w,a2 move.w (CreditsScreenIndex).w,d0 cmpi.w #$24,d0 bhs.s - btst #0,d0 bne.s - lsr.w #1,d0 move.b byte_A0EC(pc,d0.w),d0 mulu.w #$18,d0 lea pal_A0FE(pc,d0.w),a1 moveq #5,d0 - move.l (a1)+,(a2)+ dbf d0,- rts ; End of function EndgameLogoFlash ; =========================================================================== byte_A0EC: dc.b 0 dc.b 1 ; 1 dc.b 2 ; 2 dc.b 3 ; 3 dc.b 4 ; 4 dc.b 3 ; 5 dc.b 2 ; 6 dc.b 1 ; 7 dc.b 0 ; 8 dc.b 5 ; 9 dc.b 6 ; 10 dc.b 7 ; 11 dc.b 8 ; 12 dc.b 7 ; 13 dc.b 6 ; 14 dc.b 5 ; 15 dc.b 0 ; 16 dc.b 0 ; 17 ; palette cycle for the end-of-game logo pal_A0FE: BINCLUDE "art/palettes/Ending Cycle.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object CA - Cut scene at end of game ; ---------------------------------------------------------------------------- ; Sprite_A1D6: ObjCA: addq.w #1,objoff_32(a0) cmpi.w #4,(Ending_Routine).w beq.s + cmpi.w #2,(Ending_Routine).w bne.s + st (Super_Sonic_flag).w move.w #$100,(Ring_count).w move.b #-1,(Super_Sonic_palette).w + moveq #0,d0 move.b routine(a0),d0 move.w ObjCA_Index(pc,d0.w),d1 jmp ObjCA_Index(pc,d1.w) ; =========================================================================== ; off_A208: ObjCA_Index: offsetTable offsetTableEntry.w ObjCA_Init ; 0 offsetTableEntry.w loc_A240 ; 2 offsetTableEntry.w loc_A24E ; 4 offsetTableEntry.w loc_A240 ; 6 offsetTableEntry.w loc_A256 ; 8 offsetTableEntry.w loc_A30A ; $A offsetTableEntry.w loc_A34C ; $C offsetTableEntry.w loc_A38E ; $E ; =========================================================================== ; loc_A218: ObjCA_Init: moveq #4,d0 move.w #$180,d1 btst #6,(Graphics_Flags).w beq.s sub_A22A move.w #$100,d1 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_A22A: lea (EndSeqPaletteChanger).w,a1 move.b #ObjID_TtlScrPalChanger,id(a1) ; load objC9 (palette change handler) at $FFFFB0C0 move.b d0,subtype(a1) addq.b #2,routine(a0) move.w d1,objoff_3C(a0) rts ; End of function sub_A22A ; =========================================================================== loc_A240: subq.w #1,objoff_3C(a0) bmi.s + rts ; =========================================================================== + addq.b #2,routine(a0) rts ; =========================================================================== loc_A24E: moveq #6,d0 move.w #$80,d1 bra.s sub_A22A ; =========================================================================== loc_A256: move.w objoff_2E(a0),d0 cmpi.w #$10,d0 bhs.s + addq.w #4,objoff_2E(a0) clr.b routine(a0) move.l a0,-(sp) movea.l off_A29C(pc,d0.w),a0 lea (Chunk_Table).l,a1 move.w #make_art_tile(ArtTile_ArtNem_EndingPics,0,0),d0 jsrto (EniDec).l, JmpTo_EniDec move #$2700,sr lea (Chunk_Table).l,a1 move.l #vdpComm(VRAM_Plane_A_Name_Table + planeLocH40(14,8),VRAM,WRITE),d0 moveq #$B,d1 moveq #8,d2 jsrto (PlaneMapToVRAM_H40).l, JmpTo2_PlaneMapToVRAM_H40 move #$2300,sr movea.l (sp)+,a0 ; load 0bj address rts ; =========================================================================== off_A29C: dc.l MapEng_Ending1 dc.l MapEng_Ending2 dc.l MapEng_Ending3 dc.l MapEng_Ending4 ; =========================================================================== + move.w #2,(Ending_VInt_Subrout).w st (Control_Locked).w st (Ending_PalCycle_flag).w lea (MainCharacter).w,a1 ; a1=character move.w (Ending_Routine).w,d0 move.w ObjCA_State5_States(pc,d0.w),d0 jsr ObjCA_State5_States(pc,d0.w) move.w #$80,d1 bsr.w sub_A22A move.w #$40,objoff_3C(a0) rts ; =========================================================================== ObjCA_State5_States: offsetTable offsetTableEntry.w loc_A2E0 ; 0 offsetTableEntry.w loc_A2EE ; 2 offsetTableEntry.w loc_A2F2 ; 4 ; =========================================================================== loc_A2E0: moveq #8,d0 - move.b #ObjID_Sonic,id(a1) ; load Sonic object move.b #$81,obj_control(a1) rts ; =========================================================================== loc_A2EE: moveq #$C,d0 bra.s - ; =========================================================================== loc_A2F2: moveq #$E,d0 move.b #ObjID_Tails,id(a1) ; load Tails object move.b #$81,obj_control(a1) move.b #ObjID_TailsTails,(Tails_Tails_Cutscene+id).w ; load Obj05 (Tails' tails) at $FFFFB080 move.w a1,(Tails_Tails_Cutscene+parent).w rts ; =========================================================================== loc_A30A: subq.w #1,objoff_3C(a0) bpl.s + moveq #$A,d0 move.w #$80,d1 bsr.w sub_A22A move.w #$C0,objoff_3C(a0) + lea (MainCharacter).w,a1 ; a1=character move.b #AniIDSonAni_Float2,anim(a1) move.w #$A0,x_pos(a1) move.w #$50,y_pos(a1) cmpi.w #2,(Ending_Routine).w bne.s + ; rts move.b #AniIDSonAni_Walk,anim(a1) move.w #$1000,inertia(a1) + rts ; =========================================================================== loc_A34C: subq.w #1,objoff_3C(a0) bmi.s + moveq #0,d4 moveq #0,d5 move.w #0,(Camera_X_pos_diff).w move.w #$100,(Camera_Y_pos_diff).w bra.w SwScrl_DEZ ; =========================================================================== + addq.b #2,routine(a0) move.w #$100,objoff_3C(a0) cmpi.w #4,(Ending_Routine).w bne.s return_A38C move.w #$880,objoff_3C(a0) btst #6,(Graphics_Flags).w beq.s return_A38C move.w #$660,objoff_3C(a0) return_A38C: rts ; =========================================================================== loc_A38E: btst #6,(Graphics_Flags).w beq.s + cmpi.w #$E40,objoff_32(a0) beq.s loc_A3BE bra.w ++ ; =========================================================================== + cmpi.w #$1140,objoff_32(a0) beq.s loc_A3BE + subq.w #1,objoff_3C(a0) bne.s + lea (word_AD62).l,a2 jsrto (LoadChildObject).l, JmpTo_LoadChildObject + bra.w loc_AB9C ; =========================================================================== loc_A3BE: addq.b #2,routine(a0) st (Credits_Trigger).w rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object CC - Trigger for rescue plane and birds from ending sequence ; ---------------------------------------------------------------------------- ; Sprite_A3C8: ObjCC: jsrto (ObjB2_Animate_Pilot).l, JmpTo_ObjB2_Animate_Pilot moveq #0,d0 move.b routine(a0),d0 move.w ObjCC_Index(pc,d0.w),d1 jmp ObjCC_Index(pc,d1.w) ; =========================================================================== ; loc_A3DA: ObjCC_Index: offsetTable offsetTableEntry.w ObjCC_Init ; 0 offsetTableEntry.w ObjCC_Main ; 2 ; =========================================================================== ; loc_A3DE: ObjCC_Init: lea (ObjB2_SubObjData).l,a1 jsrto (LoadSubObject_Part3).l, JmpTo_LoadSubObject_Part3 cmpi.w #2,(Player_mode).w bne.s + move.b #4,mapping_frame(a0) move.b #1,anim(a0) + move.w #-$10,x_pos(a0) move.w #$C0,y_pos(a0) move.w #$100,x_vel(a0) move.w #-$80,y_vel(a0) move.b #$14,objoff_35(a0) move.b #3,priority(a0) move.w #4,(Ending_VInt_Subrout).w move.l a0,-(sp) lea (MapEng_EndingTailsPlane).l,a0 cmpi.w #4,(Ending_Routine).w bne.s + lea (MapEng_EndingSonicPlane).l,a0 + lea (Chunk_Table).l,a1 move.w #make_art_tile(ArtTile_ArtNem_EndingFinalTornado,0,1),d0 jsrto (EniDec).l, JmpTo_EniDec movea.l (sp)+,a0 ; load 0bj address move.w #$C00,(Normal_palette_line3).w jmpto (DisplaySprite).l, JmpTo5_DisplaySprite ; =========================================================================== ; loc_A456: ObjCC_Main: moveq #0,d0 move.b routine_secondary(a0),d0 move.w ObjCC_State2_States(pc,d0.w),d1 jsr ObjCC_State2_States(pc,d1.w) jmpto (DisplaySprite).l, JmpTo5_DisplaySprite ; =========================================================================== ObjCC_State2_States: offsetTable offsetTableEntry.w loc_A474 ; 0 offsetTableEntry.w loc_A4B6 ; 2 offsetTableEntry.w loc_A5A6 ; 4 offsetTableEntry.w loc_A6C6 ; 6 offsetTableEntry.w loc_A7DE ; 8 offsetTableEntry.w loc_A83E ; $A ; =========================================================================== loc_A474: cmpi.w #$A0,x_pos(a0) beq.s + jsrto (ObjectMove).l, JmpTo2_ObjectMove - lea (Ani_objB2_a).l,a1 jmpto (AnimateSprite).l, JmpTo_AnimateSprite ; =========================================================================== + addq.b #2,routine_secondary(a0) move.w #$480,objoff_3C(a0) btst #6,(Graphics_Flags).w beq.s + move.w #$3D0,objoff_3C(a0) + move.w #$40,objoff_32(a0) st (CutScene+objoff_34).w clr.w x_vel(a0) clr.w y_vel(a0) bra.s - ; =========================================================================== loc_A4B6: bsr.w sub_ABBA bsr.w sub_A524 subq.w #1,objoff_3C(a0) bmi.s + bra.s - ; =========================================================================== + addq.b #2,routine_secondary(a0) move.w #2,objoff_3C(a0) clr.w objoff_32(a0) clr.b mapping_frame(a0) cmpi.w #2,(Ending_Routine).w beq.s + move.b #7,mapping_frame(a0) cmpi.w #4,(Ending_Routine).w bne.s + move.b #$18,mapping_frame(a0) + clr.b anim(a0) clr.b anim_frame(a0) clr.b anim_frame_duration(a0) move.l #ObjCF_MapUnc_ADA2,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0) jsr (Adjust2PArtPointer).l subi.w #$14,x_pos(a0) addi.w #$14,y_pos(a0) bra.w sub_A58C ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_A524: lea (MainCharacter).w,a1 ; a1=character move.w (Ending_Routine).w,d0 move.w off_A534(pc,d0.w),d0 jmp off_A534(pc,d0.w) ; End of function sub_A524 ; =========================================================================== off_A534: offsetTable offsetTableEntry.w loc_A53A ; 0 offsetTableEntry.w loc_A55C ; 2 offsetTableEntry.w loc_A582 ; 4 ; =========================================================================== loc_A53A: move.w y_pos(a0),d0 subi.w #$1C,d0 - move.w d0,y_pos(a1) move.w x_pos(a0),x_pos(a1) move.l #$1000505,mapping_frame(a1) move.w #$100,anim_frame_duration(a1) rts ; =========================================================================== loc_A55C: tst.w objoff_32(a0) beq.s + subq.w #1,objoff_32(a0) addi.l #$8000,x_pos(a1) addq.w #1,y_pos(a1) rts ; =========================================================================== + move.w #$C0,x_pos(a1) move.w #$90,y_pos(a1) rts ; =========================================================================== loc_A582: move.w y_pos(a0),d0 subi.w #$18,d0 bra.s - ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_A58C: tst.b (Super_Sonic_flag).w bne.w return_A38C loc_A594: lea (MainCharacter).w,a1 ; a1=character move.w #$200,x_pos(a1) move.w #0,y_pos(a1) rts ; End of function sub_A58C ; =========================================================================== loc_A5A6: bsr.s sub_A58C subq.w #1,objoff_3C(a0) bpl.s + ; rts move.w #2,objoff_3C(a0) move.w objoff_32(a0),d0 cmpi.w #$1C,d0 bhs.s ++ addq.w #1,objoff_32(a0) move.w (Ending_Routine).w,d1 move.w off_A5FC(pc,d1.w),d1 lea off_A5FC(pc,d1.w),a1 move.b (a1,d0.w),mapping_frame(a0) add.w d0,d0 add.w d0,d0 move.l word_A656(pc,d0.w),d1 move.w d1,y_pos(a0) swap d1 move.w d1,x_pos(a0) + rts ; =========================================================================== + addq.b #2,routine_secondary(a0) move.w #$60,objoff_3C(a0) clr.b objoff_31(a0) clr.w objoff_32(a0) rts ; =========================================================================== off_A5FC: offsetTable offsetTableEntry.w byte_A602 ; 0 offsetTableEntry.w byte_A61E ; 2 offsetTableEntry.w byte_A63A ; 4 byte_A602: dc.b 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, $A, $A dc.b $A, $B, $B, $B, $B, $B, $B, $B, $B, $B, $B, $B; 16 byte_A61E: dc.b 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3 dc.b 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4; 16 byte_A63A: dc.b $18,$18,$18,$18,$19,$19,$19,$19,$19,$19,$19, 9, 9, 9, $A, $A dc.b $A, $B, $B, $B, $B, $B, $B, $B, $B, $B, $B, $B; 16 word_A656: dc.w $A0, $70, $B0, $70, $B6, $71, $BC, $72 dc.w $C4, $74, $C8, $75, $CA, $76, $CC, $77; 8 dc.w $CE, $78, $D0, $79, $D2, $7A, $D4, $7B; 16 dc.w $D6, $7C, $D9, $7E, $DC, $81, $DE, $84; 24 dc.w $E1, $87, $E4, $8B, $E7, $8F, $EC, $94; 32 dc.w $F0, $99, $F5, $9D, $F9, $A4, $100, $AC; 40 dc.w $108, $B8, $112, $C4, $11F, $D3, $12C, $FA; 48 ; =========================================================================== loc_A6C6: subq.w #1,objoff_3C(a0) bmi.s loc_A720 tst.b (Super_Sonic_flag).w beq.s + ; rts subq.b #1,objoff_31(a0) bpl.s + ; rts addq.b #3,objoff_31(a0) move.w objoff_32(a0),d0 addq.w #4,objoff_32(a0) cmpi.w #$78,d0 bhs.s + ; rts cmpi.w #$C,d0 blo.s ++ bsr.w loc_A594 move.l word_A766(pc,d0.w),d1 move.w d1,y_pos(a0) swap d1 move.w d1,x_pos(a0) lsr.w #2,d0 move.b byte_A748(pc,d0.w),mapping_frame(a0) + rts ; =========================================================================== + move.l word_A766(pc,d0.w),d0 lea (MainCharacter).w,a1 ; a1=character move.w d0,y_pos(a1) swap d0 move.w d0,x_pos(a1) rts ; =========================================================================== loc_A720: addq.b #2,routine_secondary(a0) clr.w objoff_3C(a0) clr.w objoff_32(a0) lea (word_AD6E).l,a2 jsrto (LoadChildObject).l, JmpTo_LoadChildObject tst.b (Super_Sonic_flag).w bne.w return_A38C lea (word_AD6A).l,a2 jmpto (LoadChildObject).l, JmpTo_LoadChildObject ; =========================================================================== byte_A748: dc.b $12,$12,$12,$12,$12,$12,$12,$13,$13,$13,$13,$13,$13,$14,$14,$14 dc.b $14,$15,$15,$15,$16,$16,$16,$16,$16,$16,$16,$16,$16, 0; 16 word_A766: dc.w $C0, $90 ; 1 dc.w $B0, $91 ; 3 dc.w $A8, $92 ; 5 dc.w $9B, $96 ; 7 dc.w $99, $98 ; 9 dc.w $98, $99 ; 11 dc.w $99, $9A ; 13 dc.w $9B, $9C ; 15 dc.w $9F, $9E ; 17 dc.w $A4, $A0 ; 19 dc.w $AC, $A2 ; 21 dc.w $B7, $A5 ; 23 dc.w $C4, $A8 ; 25 dc.w $D3, $AB ; 27 dc.w $DE, $AE ; 29 dc.w $E8, $B0 ; 31 dc.w $EF, $B2 ; 33 dc.w $F4, $B5 ; 35 dc.w $F9, $B8 ; 37 dc.w $FC, $BB ; 39 dc.w $FE, $BE ; 41 dc.w $FF, $C0 ; 43 dc.w $100, $C2 ; 45 dc.w $101, $C5 ; 47 dc.w $102, $C8 ; 49 dc.w $102, $CC ; 51 dc.w $101, $D1 ; 53 dc.w $FD, $D7 ; 55 dc.w $F9, $DE ; 57 dc.w $F9,$118 ; 59 ; =========================================================================== loc_A7DE: bsr.w loc_A594 subq.w #1,objoff_3C(a0) bpl.s + ; rts move.w #2,objoff_3C(a0) move.w objoff_32(a0),d0 cmpi.w #$1C,d0 bhs.s ++ addq.w #4,objoff_32(a0) lea word_A822(pc,d0.w),a1 move.w (a1)+,d0 add.w d0,(Horiz_Scroll_Buf).w move.w (a1)+,d0 add.w d0,(Vscroll_Factor_FG).w + rts ; =========================================================================== + addq.b #2,routine_secondary(a0) bset #3,status(a0) clr.b objoff_31(a0) clr.w objoff_32(a0) rts ; =========================================================================== word_A822: dc.w -$3A dc.w $88 ; 1 dc.w -$C ; 2 dc.w $22 ; 3 dc.w -8 ; 4 dc.w $10 ; 5 dc.w -4 ; 6 dc.w 8 ; 7 dc.w -2 ; 8 dc.w 4 ; 9 dc.w -1 ; 10 dc.w 2 ; 11 dc.w -1 ; 12 dc.w 2 ; 13 ; =========================================================================== loc_A83E: tst.b (Super_Sonic_flag).w beq.w return_A38C move.b #$17,mapping_frame(a0) subq.b #1,objoff_31(a0) bpl.s + ; rts addq.b #3,objoff_31(a0) move.w objoff_32(a0),d0 cmpi.w #$20,d0 bhs.s + ; rts addq.w #4,objoff_32(a0) move.l word_A874(pc,d0.w),d1 move.w d1,y_pos(a0) swap d1 move.w d1,x_pos(a0) + rts ; =========================================================================== word_A874: dc.w $60,$88 ; 1 dc.w $50,$68 ; 3 dc.w $44,$46 ; 5 dc.w $3C,$36 ; 7 dc.w $36,$2A ; 9 dc.w $33,$24 ; 11 dc.w $31,$20 ; 13 dc.w $30,$1E ; 15 ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object CE - Sonic and Tails jumping off the plane from ending sequence ; ---------------------------------------------------------------------------- ; Sprite_A894: ObjCE: moveq #0,d0 move.b routine(a0),d0 move.w ObjCE_Index(pc,d0.w),d1 jmp ObjCE_Index(pc,d1.w) ; =========================================================================== ; off_A8A2: ObjCE_Index: offsetTable offsetTableEntry.w ObjCE_Init ; 0 offsetTableEntry.w loc_A902 ; 2 offsetTableEntry.w loc_A936 ; 4 offsetTableEntry.w BranchTo_JmpTo5_DisplaySprite ; 6 ; =========================================================================== ; loc_A8AA: ObjCE_Init: lea (ObjB3_SubObjData).l,a1 jsrto (LoadSubObject_Part3).l, JmpTo_LoadSubObject_Part3 move.l #ObjCF_MapUnc_ADA2,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,1),art_tile(a0) move.b #1,priority(a0) jsr (Adjust2PArtPointer).l move.b #$C,mapping_frame(a0) cmpi.w #4,(Ending_Routine).w bne.s + move.b #$F,mapping_frame(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,1,1),art_tile(a0) + move.w #$E8,d0 move.w d0,x_pos(a0) move.w d0,objoff_30(a0) move.w #$118,d0 move.w d0,y_pos(a0) move.w d0,objoff_32(a0) rts ; =========================================================================== loc_A902: movea.w objoff_2C(a0),a1 ; a1=object btst #3,status(a1) bne.s + loc_A90E: move.w objoff_30(a0),d0 add.w (Horiz_Scroll_Buf).w,d0 move.w d0,x_pos(a0) move.w objoff_32(a0),d0 sub.w (Vscroll_Factor_FG).w,d0 move.w d0,y_pos(a0) BranchTo_JmpTo5_DisplaySprite jmpto (DisplaySprite).l, JmpTo5_DisplaySprite ; =========================================================================== + addq.b #2,routine(a0) clr.w objoff_3C(a0) jmpto (DisplaySprite).l, JmpTo5_DisplaySprite ; =========================================================================== loc_A936: subq.w #1,objoff_3C(a0) bpl.s BranchTo2_JmpTo5_DisplaySprite move.w #4,objoff_3C(a0) move.w objoff_34(a0),d0 cmpi.w #4,d0 bhs.s ++ addq.w #2,objoff_34(a0) lea byte_A980(pc,d0.w),a1 cmpi.w #2,(Ending_Routine).w bne.s + lea byte_A984(pc,d0.w),a1 + move.b (a1)+,d0 ext.w d0 add.w d0,x_pos(a0) move.b (a1)+,d0 ext.w d0 add.w d0,y_pos(a0) addq.b #1,mapping_frame(a0) BranchTo2_JmpTo5_DisplaySprite jmpto (DisplaySprite).l, JmpTo5_DisplaySprite ; =========================================================================== + addq.b #2,routine(a0) jmpto (DisplaySprite).l, JmpTo5_DisplaySprite ; =========================================================================== byte_A980: dc.b -8, 0 dc.b -$44,-$38 ; 2 byte_A984: dc.b -8, 0 dc.b -$50,-$40 ; 2 ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object CF - "Plane's helixes" from ending sequence ; ---------------------------------------------------------------------------- ; Sprite_A988: ObjCF: moveq #0,d0 move.b routine(a0),d0 move.w ObjCF_Index(pc,d0.w),d1 jmp ObjCF_Index(pc,d1.w) ; =========================================================================== ; off_A996: ObjCF_Index: offsetTable offsetTableEntry.w ObjCF_Init ; 0 offsetTableEntry.w ObjCF_Animate ; 2 ; =========================================================================== ; loc_A99A: ObjCF_Init: lea (ObjB3_SubObjData).l,a1 jsrto (LoadSubObject_Part3).l, JmpTo_LoadSubObject_Part3 move.l #ObjCF_MapUnc_ADA2,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,1),art_tile(a0) move.b #3,priority(a0) jsr (Adjust2PArtPointer).l move.b #5,mapping_frame(a0) move.b #2,anim(a0) move.w #$10F,d0 move.w d0,x_pos(a0) move.w d0,objoff_30(a0) move.w #$15E,d0 move.w d0,y_pos(a0) move.w d0,objoff_32(a0) rts ; =========================================================================== ; loc_A9E4: ObjCF_Animate: lea (Ani_objCF).l,a1 jsrto (AnimateSprite).l, JmpTo_AnimateSprite bra.w loc_A90E ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object CB - Background clouds from ending sequence ; ---------------------------------------------------------------------------- ; Sprite_A9F2: ObjCB: moveq #0,d0 move.b routine(a0),d0 move.w ObjCB_Index(pc,d0.w),d1 jmp ObjCB_Index(pc,d1.w) ; =========================================================================== ; off_AA00: ObjCB_Index: offsetTable offsetTableEntry.w ObjCB_Init ; 0 offsetTableEntry.w loc_AA76 ; 2 offsetTableEntry.w loc_AA8A ; 4 ; =========================================================================== ; loc_AA06: ObjCB_Init: lea (ObjB3_SubObjData).l,a1 jsrto (LoadSubObject_Part3).l, JmpTo_LoadSubObject_Part3 move.w art_tile(a0),d0 andi.w #$1FFF,d0 ori.w #palette_mask,d0 move.w d0,art_tile(a0) move.b #$30,width_pixels(a0) move.l (RNG_seed).w,d0 ror.l #1,d0 move.l d0,(RNG_seed).w move.w d0,d1 andi.w #3,d0 move.b ObjCB_Frames(pc,d0.w),mapping_frame(a0) add.w d0,d0 move.w ObjCB_YSpeeds(pc,d0.w),y_vel(a0) tst.b (CutScene+$34).w beq.s + andi.w #$FF,d1 move.w d1,y_pos(a0) move.w #$150,x_pos(a0) rts ; =========================================================================== + andi.w #$1FF,d1 move.w d1,x_pos(a0) move.w #$100,y_pos(a0) rts ; =========================================================================== ; byte_AA6A: ObjCB_Frames: dc.b 0 dc.b 1 ; 1 dc.b 2 ; 2 dc.b 0 ; 3 ; word_AA6E: ObjCB_YSpeeds: dc.w -$300 dc.w -$200 ; 1 dc.w -$100 ; 2 dc.w -$300 ; 3 ; =========================================================================== loc_AA76: tst.b (CutScene+objoff_34).w beq.s loc_AA8A addq.b #2,routine(a0) move.w y_vel(a0),x_vel(a0) clr.w y_vel(a0) loc_AA8A: jsrto (ObjectMove).l, JmpTo2_ObjectMove tst.b (CutScene+objoff_34).w beq.s + cmpi.w #-$20,x_pos(a0) blt.w JmpTo3_DeleteObject jmpto (DisplaySprite).l, JmpTo5_DisplaySprite ; =========================================================================== + tst.w y_pos(a0) bmi.w JmpTo3_DeleteObject jmpto (DisplaySprite).l, JmpTo5_DisplaySprite ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object CD - Birds from ending sequence ; ---------------------------------------------------------------------------- endingbird_delay = objoff_3C ; delay before doing the next action ; Sprite_AAAE: ObjCD: moveq #0,d0 move.b routine(a0),d0 move.w ObjCD_Index(pc,d0.w),d1 jmp ObjCD_Index(pc,d1.w) ; =========================================================================== ; off_AABC: ObjCD_Index: offsetTable offsetTableEntry.w ObjCD_Init ; 0 offsetTableEntry.w ObjCD_Main ; 2 ; =========================================================================== ; loc_AAC0: ObjCD_Init: lea (Obj28_SubObjData).l,a1 jsrto (LoadSubObject_Part3).l, JmpTo_LoadSubObject_Part3 move.l (RNG_seed).w,d0 ror.l #3,d0 move.l d0,(RNG_seed).w move.l d0,d1 andi.w #$7F,d0 move.w #-$A0,d2 add.w d0,d2 move.w d2,x_pos(a0) ror.l #3,d1 andi.w #$FF,d1 moveq #8,d2 add.w d1,d2 move.w d2,y_pos(a0) move.w #$100,x_vel(a0) moveq #$20,d0 cmpi.w #$20,d1 blo.s + neg.w d0 + move.w d0,y_vel(a0) move.w #$C0,endingbird_delay(a0) rts ; =========================================================================== ; loc_AB0E: ObjCD_Main: moveq #0,d0 move.b routine_secondary(a0),d0 move.w ObjCD_Main_States(pc,d0.w),d1 jsr ObjCD_Main_States(pc,d1.w) jsrto (ObjectMove).l, JmpTo2_ObjectMove lea (Ani_objCD).l,a1 jsrto (AnimateSprite).l, JmpTo_AnimateSprite jmpto (DisplaySprite).l, JmpTo5_DisplaySprite ; =========================================================================== ObjCD_Main_States: offsetTable offsetTableEntry.w loc_AB34 ; 0 offsetTableEntry.w loc_AB5C ; 2 offsetTableEntry.w loc_AB8E ; 4 ; =========================================================================== loc_AB34: subq.w #1,endingbird_delay(a0) bpl.s + ; rts addq.b #2,routine_secondary(a0) move.w y_vel(a0),objoff_2E(a0) clr.w x_vel(a0) move.w y_pos(a0),objoff_32(a0) move.w #$80,y_vel(a0) move.w #$180,endingbird_delay(a0) + rts ; =========================================================================== loc_AB5C: subq.w #1,endingbird_delay(a0) bmi.s ++ move.w y_pos(a0),d0 moveq #-4,d1 cmp.w objoff_32(a0),d0 bhs.s + neg.w d1 + add.w d1,y_vel(a0) rts ; =========================================================================== + addq.b #2,routine_secondary(a0) move.w #-$100,x_vel(a0) move.w objoff_2E(a0),y_vel(a0) move.w #$C0,endingbird_delay(a0) rts ; =========================================================================== loc_AB8E: subq.w #1,endingbird_delay(a0) bmi.s + rts ; =========================================================================== + addq.w #4,sp if removeJmpTos JmpTo3_DeleteObject endif jmpto (DeleteObject).l, JmpTo3_DeleteObject ; =========================================================================== loc_AB9C: subq.w #1,objoff_30(a0) bpl.s + ; rts move.l (RNG_seed).w,d0 andi.w #$1F,d0 move.w d0,objoff_30(a0) lea (word_AD5E).l,a2 jsrto (LoadChildObject).l, JmpTo_LoadChildObject + rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_ABBA: subq.w #1,objoff_30(a0) bpl.s + ; rts tst.b objoff_35(a0) beq.s + ; rts subq.b #1,objoff_35(a0) move.l (RNG_seed).w,d0 andi.w #$F,d0 move.w d0,objoff_30(a0) lea (word_AD66).l,a2 jsrto (LoadChildObject).l, JmpTo_LoadChildObject + rts ; End of function sub_ABBA ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_ABE2: EndingSequence_LoadCharacterArt: move.w (Ending_Routine).w,d0 move.w EndingSequence_LoadCharacterArt_Characters(pc,d0.w),d0 jmp EndingSequence_LoadCharacterArt_Characters(pc,d0.w) ; End of function EndingSequence_LoadCharacterArt ; =========================================================================== EndingSequence_LoadCharacterArt_Characters: offsetTable offsetTableEntry.w EndingSequence_LoadCharacterArt_Sonic ; 0 offsetTableEntry.w EndingSequence_LoadCharacterArt_SuperSonic ; 2 offsetTableEntry.w EndingSequence_LoadCharacterArt_Tails ; 4 ; =========================================================================== ; loc_ABF4: EndingSequence_LoadCharacterArt_Sonic: move.l #vdpComm(tiles_to_bytes(ArtTile_EndingCharacter),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_EndingSonic).l,a0 jmpto (NemDec).l, JmpTo_NemDec ; =========================================================================== ; loc_AC08: EndingSequence_LoadCharacterArt_SuperSonic: move.l #vdpComm(tiles_to_bytes(ArtTile_EndingCharacter),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_EndingSuperSonic).l,a0 jmpto (NemDec).l, JmpTo_NemDec ; =========================================================================== ; loc_AC1C: EndingSequence_LoadCharacterArt_Tails: move.l #vdpComm(tiles_to_bytes(ArtTile_EndingCharacter),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_EndingTails).l,a0 jmpto (NemDec).l, JmpTo_NemDec ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_AC30: EndingSequence_LoadFlickyArt: move.w (Ending_Routine).w,d0 move.w EndingSequence_LoadFlickyArt_Flickies(pc,d0.w),d0 jmp EndingSequence_LoadFlickyArt_Flickies(pc,d0.w) ; End of function EndingSequence_LoadFlickyArt ; =========================================================================== EndingSequence_LoadFlickyArt_Flickies: offsetTable offsetTableEntry.w EndingSequence_LoadFlickyArt_Bird ; 0 offsetTableEntry.w EndingSequence_LoadFlickyArt_Eagle ; 2 offsetTableEntry.w EndingSequence_LoadFlickyArt_Chicken ; 4 ; =========================================================================== ; loc_AC42: EndingSequence_LoadFlickyArt_Bird: move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Animal_2),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_Bird).l,a0 jmpto (NemDec).l, JmpTo_NemDec ; =========================================================================== ; loc_AC56: EndingSequence_LoadFlickyArt_Eagle: move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Animal_2),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_Eagle).l,a0 jmpto (NemDec).l, JmpTo_NemDec ; =========================================================================== ; loc_AC6A: EndingSequence_LoadFlickyArt_Chicken: move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Animal_2),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_Chicken).l,a0 jmpto (NemDec).l, JmpTo_NemDec ; =========================================================================== Pal_AC7E: BINCLUDE "art/palettes/Ending Sonic.bin" Pal_AC9E: BINCLUDE "art/palettes/Ending Sonic Far.bin" Pal_ACDE: BINCLUDE "art/palettes/Ending Background.bin" Pal_AD1E: BINCLUDE "art/palettes/Ending Photos.bin" Pal_AD3E: BINCLUDE "art/palettes/Ending Super Sonic.bin" word_AD5E: dc.w objoff_3E dc.b ObjID_EndingSeqClouds dc.b $00 word_AD62: dc.w objoff_3E dc.b ObjID_EndingSeqTrigger dc.b $00 word_AD66: dc.w objoff_3E dc.b ObjID_EndingSeqBird dc.b $00 word_AD6A: dc.w objoff_3E dc.b ObjID_EndingSeqSonic dc.b $00 word_AD6E: dc.w objoff_3E dc.b ObjID_TornadoHelixes dc.b $00 ; off_AD72: Obj28_SubObjData: subObjData Obj28_MapUnc_11E1C,make_art_tile(ArtTile_ArtNem_Animal_2,0,0),4,2,8,0 ; animation script ; byte_AD7C Ani_objCD: offsetTable offsetTableEntry.w byte_AD7E ; 0 byte_AD7E: dc.b 5, 0, 1,$FF ; animation script ; off_AD82 Ani_objCF: offsetTable offsetTableEntry.w byte_AD88 ; 0 offsetTableEntry.w byte_AD8E ; 1 offsetTableEntry.w byte_AD9E ; 2 byte_AD88: dc.b 3, 0, 0, 1,$FA, 0 byte_AD8E: dc.b 3, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4,$FA, 0 byte_AD9E: dc.b 1, 5, 6,$FF even ; ----------------------------------------------------------------------------- ; sprite mappings ; ----------------------------------------------------------------------------- ObjCF_MapUnc_ADA2: BINCLUDE "mappings/sprite/objCF.bin" ; -------------------------------------------------------------------------------------- ; Enigma compressed art mappings ; "Sonic the Hedgehog 2" mappings ; MapEng_B23A: MapEng_EndGameLogo: BINCLUDE "mappings/misc/Sonic 2 end of game logo.bin" even ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_B262 ShowCreditsScreen: lea off_B2CA(pc),a1 move.w (CreditsScreenIndex).w,d0 lsl.w #2,d0 move.l (a1,d0.w),d0 movea.l d0,a1 loc_B272: move #$2700,sr lea (VDP_data_port).l,a6 - move.l (a1)+,d0 bmi.s ++ movea.l d0,a2 move.w (a1)+,d0 bsr.s sub_B29E move.l d0,4(a6) move.b (a2)+,d0 lsl.w #8,d0 - move.b (a2)+,d0 bmi.s + move.w d0,(a6) bra.s - ; =========================================================================== + bra.s -- ; =========================================================================== + move #$2300,sr rts ; End of function ShowCreditsScreen ; --------------------------------------------------------------------------- ; Subroutine to convert a VRAM address into a 32-bit VRAM write command word ; Input: ; d0 VRAM address (word) ; Output: ; d0 32-bit VDP command word for a VRAM write to specified address. ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_B29E: andi.l #$FFFF,d0 lsl.l #2,d0 lsr.w #2,d0 ori.w #vdpComm($0000,VRAM,WRITE)>>16,d0 swap d0 rts ; End of function sub_B29E ; =========================================================================== ; macro for declaring pointer/position structures for intro/credit text vram_pnt := VRAM_Plane_A_Name_Table creditsPtrs macro addr,pos if "addr"<>"" dc.l addr dc.w vram_pnt + pos shift shift creditsPtrs ALLARGS else dc.w -1 endif endm textLoc function col,line,(($80 * line) + (2 * col)) ; intro text pointers (one intro screen) vram_pnt := VRAM_TtlScr_Plane_A_Name_Table off_B2B0: creditsPtrs byte_BD1A,textLoc($0F,$09), byte_BCEE,textLoc($11,$0C), \ byte_BCF6,textLoc($03,$0F), byte_BCE9,textLoc($12,$12) ; credits screen pointer table off_B2CA: dc.l off_B322, off_B336, off_B34A, off_B358 ; 3 dc.l off_B366, off_B374, off_B388, off_B3A8 ; 7 dc.l off_B3C2, off_B3DC, off_B3F0, off_B41C ; 11 dc.l off_B436, off_B450, off_B45E, off_B490 ; 15 dc.l off_B4B0, off_B4C4, off_B4F0, off_B51C ; 19 dc.l off_B548, -1 ; 21 ; credits text pointers for each screen of credits vram_pnt := VRAM_Plane_A_Name_Table off_B322: creditsPtrs byte_BC46,textLoc($0E,$0B), byte_BC51,textLoc($18,$0B), byte_BC55,textLoc($02,$0F) off_B336: creditsPtrs byte_B55C,textLoc($03,$0B), byte_B56F,textLoc($16,$0B), byte_B581,textLoc($06,$0F) off_B34A: creditsPtrs byte_B56F,textLoc($0C,$0B), byte_B59F,textLoc($07,$0F) off_B358: creditsPtrs byte_B5BC,textLoc($0C,$0B), byte_B5CD,textLoc($06,$0F) off_B366: creditsPtrs byte_B5EB,textLoc($05,$0B), byte_B60C,textLoc($07,$0F) off_B374: creditsPtrs byte_B628,textLoc($08,$0A), byte_B642,textLoc($04,$0E), byte_B665,textLoc($0A,$10) off_B388: creditsPtrs byte_B67B,textLoc($04,$08), byte_B69C,textLoc($11,$0A), byte_B6A4,textLoc($09,$0C), byte_B6BC,textLoc($04,$10), byte_B6DE,textLoc($08,$12) off_B3A8: creditsPtrs byte_B6F8,textLoc($0B,$09), byte_B70B,textLoc($09,$0B), byte_B723,textLoc($0A,$0F), byte_B738,textLoc($03,$11) off_B3C2: creditsPtrs byte_B75C,textLoc($04,$09), byte_B642,textLoc($04,$0D), byte_B77E,textLoc($07,$0F), byte_B799,textLoc($07,$11) off_B3DC: creditsPtrs byte_B7B5,textLoc($08,$0A), byte_B75C,textLoc($04,$0C), byte_B799,textLoc($07,$10) off_B3F0: creditsPtrs byte_B7F2,textLoc($09,$06), byte_B6BC,textLoc($04,$0A), byte_B80B,textLoc($0A,$0C), byte_B821,textLoc($09,$0E), byte_B839,textLoc($07,$10), byte_B855,textLoc($0B,$12), byte_B869,textLoc($0B,$14) off_B41C: creditsPtrs byte_B7B5,textLoc($09,$09), byte_B87D,textLoc($0A,$0B), byte_B893,textLoc($0B,$0F), byte_B8A8,textLoc($07,$11) off_B436: creditsPtrs byte_B8C5,textLoc($06,$09), byte_B8E2,textLoc($05,$0D), byte_B902,textLoc($03,$0F), byte_B90F,textLoc($04,$11) off_B450: creditsPtrs byte_B932,textLoc($04,$0B), byte_B954,textLoc($05,$0F) off_B45E: creditsPtrs byte_B974,textLoc($04,$05), byte_B995,textLoc($0F,$09), byte_B9A1,textLoc($0F,$0B), byte_B9AD,textLoc($0F,$0D), byte_B9B8,textLoc($10,$0F), byte_B9C1,textLoc($11,$11), byte_B9C8,textLoc($11,$13), byte_B9D0,textLoc($0F,$15) off_B490: creditsPtrs byte_B9DB,textLoc($03,$08), byte_BA00,textLoc($08,$0C), byte_BA1B,textLoc($06,$0E), byte_BA3A,textLoc($09,$10), byte_BA52,textLoc($0A,$12) off_B4B0: creditsPtrs byte_BA69,textLoc($09,$0A), byte_BA81,textLoc($05,$0E), byte_B7CE,textLoc($03,$10) off_B4C4: creditsPtrs byte_B55C,textLoc($0B,$06), byte_BAA2,textLoc($0A,$08), byte_BAB8,textLoc($03,$0C), byte_BADC,textLoc($07,$0E), byte_BAF7,textLoc($05,$10), byte_BB16,textLoc($07,$12), byte_BB32,textLoc($02,$14) off_B4F0: creditsPtrs byte_BB58,textLoc($06,$06), byte_BB75,textLoc($12,$08), byte_BB7B,textLoc($06,$0C), byte_BC9F,textLoc($05,$0E), byte_BBD8,textLoc($08,$10), byte_BBF2,textLoc($08,$12), byte_BC0C,textLoc($09,$14) off_B51C: creditsPtrs byte_BB58,textLoc($06,$06), byte_BB75,textLoc($12,$08), byte_BB98,textLoc($03,$0C), byte_BBBC,textLoc($07,$0E), byte_BCBE,textLoc($07,$10), byte_BCD9,textLoc($0D,$12), byte_BC25,textLoc($04,$14) off_B548: creditsPtrs byte_BC7B,textLoc($0B,$09), byte_BC8F,textLoc($12,$0D), byte_BC95,textLoc($10,$11) ; temporarily remap characters to credit text format ; let's encode 2-wide characters like Aa, Bb, Cc, etc. and hide it with a macro charset '@',"\x3B\2\4\6\8\xA\xC\xE\x10\x12\x13\x15\x17\x19\x1B\x1D\x1F\x21\x23\x25\x27\x29\x2B\x2D\x2F\x31\x33" charset 'a',"\3\5\7\9\xB\xD\xF\x11\x12\x14\x16\x18\x1A\x1C\x1E\x20\x22\x24\x26\x28\x2A\x2C\x2E\x30\x32\x34" charset '!',"\x3D\x39\x3F\x36" charset '\H',"\x39\x37\x38" charset '9',"\x3E\x40\x41" charset '1',"\x3C\x35" charset '.',"\x3A" charset ' ',0 ; macro for defining credit text in conjunction with the remapped character set vram_src := ArtTile_ArtNem_CreditText_CredScr creditText macro pal,ss if ((vram_src & $FF) <> $0) && ((vram_src & $FF) <> $1) fatal "The low byte of vram_src was $\{vram_src & $FF}, but it must be $00 or $01." endif c := 0 dc.b (make_art_tile(vram_src,pal,0) & $FF00) >> 8 rept strlen(ss) t := substr(ss,c,1) dc.b t l := lowstring(t) if t="I" elseif l<>t dc.b l elseif t="1" dc.b "!" elseif t="2" dc.b "$" elseif t="9" dc.b "#" endif c := c+1 endm dc.b -1 rev02even endm ; credits text data (palette index followed by a string) vram_src := ArtTile_ArtNem_CreditText_CredScr byte_B55C: creditText 1,"EXECUTIVE" byte_B56F: creditText 1,"PRODUCER" byte_B581: creditText 0,"HAYAO NAKAYAMA" byte_B59F: creditText 0,"SHINOBU TOYODA" byte_B5BC: creditText 1,"DIRECTOR" byte_B5CD: creditText 0,"MASAHARU YOSHII" byte_B5EB: creditText 1,"CHIEF PROGRAMMER" byte_B60C: creditText 0,"YUJI NAKA (YU2)" byte_B628: creditText 1,"GAME PLANNER" byte_B642: creditText 0,"HIROKAZU YASUHARA" byte_B665: creditText 0,"(CAROL YAS)" byte_B67B: creditText 1,"CHARACTER DESIGN" byte_B69C: creditText 1,"AND" byte_B6A4: creditText 1,"CHIEF ARTIST" byte_B6BC: creditText 0,"YASUSHI YAMAGUCHI" byte_B6DE: creditText 0,"(JUDY TOTOYA)" byte_B6F8: creditText 1,"ASSISTANT" byte_B70B: creditText 1,"PROGRAMMERS" byte_B723: creditText 0,"BILL WILLIS" byte_B738: creditText 0,"MASANOBU YAMAMOTO" byte_B75C: creditText 1,"OBJECT PLACEMENT" byte_B77E: creditText 0,"TAKAHIRO ANTO" byte_B799: creditText 0,"YUTAKA SUGANO" byte_B7B5: creditText 1,"SPECIALSTAGE" byte_B7CE: creditText 0,"CAROL ANN HANSHAW" byte_B7F2: creditText 1,"ZONE ARTISTS" byte_B80B: creditText 0,"CRAIG STITT" byte_B821: creditText 0,"BRENDA ROSS" byte_B839: creditText 0,"JINA ISHIWATARI" byte_B855: creditText 0,"TOM PAYNE" byte_B869: creditText 0,"PHENIX RIE" byte_B87D: creditText 1,"ART AND CG" byte_B893: creditText 0,"TIM SKELLY" byte_B8A8: creditText 0,"PETER MORAWIEC" byte_B8C5: creditText 1,"MUSIC COMPOSER" byte_B8E2: creditText 0,"MASATO NAKAMURA" byte_B902: creditText 0,"( @1992" byte_B90F: creditText 0,"DREAMS COME TRUE)" byte_B932: creditText 1,"SOUND PROGRAMMER" byte_B954: creditText 0,"TOMOYUKI SHIMADA" byte_B974: creditText 1,"SOUND ASSISTANTS" byte_B995: creditText 0,"MACKY" byte_B9A1: creditText 0,"JIMITA" byte_B9AD: creditText 0,"MILPO" byte_B9B8: creditText 0,"IPPO" byte_B9C1: creditText 0,"S.O" byte_B9C8: creditText 0,"OYZ" byte_B9D0: creditText 0,"N.GEE" byte_B9DB: creditText 1,"PROJECT ASSISTANTS" byte_BA00: creditText 0,"SYUICHI KATAGI" byte_BA1B: creditText 0,"TAKAHIRO HAMANO" byte_BA3A: creditText 0,"YOSHIKI OOKA" byte_BA52: creditText 0,"STEVE WOITA" byte_BA69: creditText 1,"GAME MANUAL" byte_BA81: creditText 0,"YOUICHI TAKAHASHI" byte_BAA2: creditText 1,"SUPPORTERS" byte_BAB8: creditText 0,"DAIZABUROU SAKURAI" byte_BADC: creditText 0,"HISASHI SUZUKI" if gameRevision=0 byte_BAF7: creditText 0,"TOHMAS KALINSKE" ; typo else byte_BAF7: creditText 0,"THOMAS KALINSKE" endif byte_BB16: creditText 0,"FUJIO MINEGISHI" byte_BB32: creditText 0,"TAKAHARU UTSUNOMIYA" byte_BB58: creditText 1,"SPECIAL THANKS" byte_BB75: creditText 1,"TO" byte_BB7B: creditText 0,"CINDY CLAVERAN" byte_BB98: creditText 0,"DEBORAH MCCRACKEN" byte_BBBC: creditText 0,"TATSUO YAMADA" byte_BBD8: creditText 0,"DAISUKE SAITO" byte_BBF2: creditText 0,"KUNITAKE AOKI" byte_BC0C: creditText 0,"TSUNEKO AOKI" byte_BC25: creditText 0,"MASAAKI KAWAMURA" byte_BC46: creditText 0,"SONIC" byte_BC51: creditText 1,"2" byte_BC55: creditText 0,"CAST OF CHARACTERS" byte_BC7B: creditText 0,"PRESENTED" byte_BC8F: creditText 0,"BY" byte_BC95: creditText 0,"SEGA" byte_BC9F: creditText 0,"FRANCE TANTIADO" byte_BCBE: creditText 0,"RICK MACARAEG" byte_BCD9: creditText 0,"LOCKY P" charset ; have to revert character set before changing again ; temporarily remap characters to intro text format charset '@',"\x3A\1\3\5\7\9\xB\xD\xF\x11\x12\x14\x16\x18\x1A\x1C\x1E\x20\x22\x24\x26\x28\x2A\x2C\x2E\x30\x32" charset 'a',"\2\4\6\8\xA\xC\xE\x10\x11\x13\x15\x17\x19\x1B\x1D\x1F\x21\x23\x25\x27\x29\x2B\x2D\x2F\x31\x33" charset '!',"\x3C\x38\x3E\x35" charset '\H',"\x38\x36\x37" charset '9',"\x3D\x3F\x40" charset '1',"\x3B\x34" charset '.',"\x39" charset ' ',0 ; intro text vram_src := ArtTile_ArtNem_CreditText byte_BCE9: creditText 0,"IN" byte_BCEE: creditText 0,"AND" byte_BCF6: creditText 0,"MILES 'TAILS' PROWER" byte_BD1A: creditText 0,"SONIC" charset ; revert character set even ; ------------------------------------------------------------------------------- ; Nemesis compressed art ; 64 blocks ; Standard font used in credits ; ------------------------------------------------------------------------------- ; ArtNem_BD26: ArtNem_CreditText: BINCLUDE "art/nemesis/Credit Text.bin" ; =========================================================================== if ~~removeJmpTos JmpTo5_DisplaySprite jmp (DisplaySprite).l JmpTo3_DeleteObject jmp (DeleteObject).l JmpTo2_PlaySound jmp (PlaySound).l JmpTo_ObjB2_Animate_Pilot jmp (ObjB2_Animate_Pilot).l JmpTo_AnimateSprite jmp (AnimateSprite).l JmpTo_NemDec jmp (NemDec).l JmpTo_EniDec jmp (EniDec).l JmpTo_ClearScreen jmp (ClearScreen).l JmpTo2_PlayMusic jmp (PlayMusic).l JmpTo_LoadChildObject jmp (LoadChildObject).l ; JmpTo2_PlaneMapToVRAM_H40 JmpTo2_PlaneMapToVRAM_H40 jmp (PlaneMapToVRAM_H40).l JmpTo2_ObjectMove jmp (ObjectMove).l JmpTo_PalCycle_Load jmp (PalCycle_Load).l JmpTo_LoadSubObject_Part3 jmp (LoadSubObject_Part3).l align 4 endif ; --------------------------------------------------------------------------- ; Subroutine to load level boundaries and start locations ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_BFBC: LevelSizeLoad: clr.w (Scroll_flags).w clr.w (Scroll_flags_BG).w clr.w (Scroll_flags_BG2).w clr.w (Scroll_flags_BG3).w clr.w (Scroll_flags_P2).w clr.w (Scroll_flags_BG_P2).w clr.w (Scroll_flags_BG2_P2).w clr.w (Scroll_flags_BG3_P2).w clr.w (Scroll_flags_copy).w clr.w (Scroll_flags_BG_copy).w clr.w (Scroll_flags_BG2_copy).w clr.w (Scroll_flags_BG3_copy).w clr.w (Scroll_flags_copy_P2).w clr.w (Scroll_flags_BG_copy_P2).w clr.w (Scroll_flags_BG2_copy_P2).w clr.w (Scroll_flags_BG3_copy_P2).w clr.b (Deform_lock).w clr.b (Screen_Shaking_Flag_HTZ).w clr.b (Screen_Shaking_Flag).w clr.b (Scroll_lock).w clr.b (Scroll_lock_P2).w moveq #0,d0 move.b d0,(Dynamic_Resize_Routine).w ; load level boundaries if gameRevision=2 move.w d0,(WFZ_LevEvent_Subrout).w move.w d0,(WFZ_BG_Y_Speed).w move.w d0,(Camera_BG_X_offset).w move.w d0,(Camera_BG_Y_offset).w endif move.w (Current_ZoneAndAct).w,d0 ror.b #1,d0 lsr.w #4,d0 lea LevelSize(pc,d0.w),a0 move.l (a0)+,d0 move.l d0,(Camera_Min_X_pos).w move.l d0,(unk_EEC0).w ; unused besides this one write... move.l d0,(Tails_Min_X_pos).w move.l (a0)+,d0 move.l d0,(Camera_Min_Y_pos).w ; Warning: unk_EEC4 is only a word long, this line also writes to Camera_Max_Y_pos ; If you remove this instruction, the camera will scroll up until it kills Sonic move.l d0,(unk_EEC4).w ; unused besides this one write... move.l d0,(Tails_Min_Y_pos).w move.w #$1010,(Horiz_block_crossed_flag).w move.w #(224/2)-16,(Camera_Y_pos_bias).w move.w #(224/2)-16,(Camera_Y_pos_bias_P2).w bra.w + ; =========================================================================== ; ---------------------------------------------------------------------------- ; LEVEL SIZE ARRAY ; This array defines the screen boundaries for each act in the game. ; ---------------------------------------------------------------------------- ; xstart xend ystart yend ; ZID ; Zone LevelSize: zoneOrderedTable 2,8 ; WrdArr_LvlSize zoneTableEntry.w $0, $29A0, $0, $320 ; EHZ act 1 zoneTableEntry.w $0, $2940, $0, $420 ; EHZ act 2 zoneTableEntry.w $0, $3FFF, $0, $720 ; $01 zoneTableEntry.w $0, $3FFF, $0, $720 zoneTableEntry.w $0, $3FFF, $0, $720 ; $02 zoneTableEntry.w $0, $3FFF, $0, $720 zoneTableEntry.w $0, $3FFF, $0, $720 ; $03 zoneTableEntry.w $0, $3FFF, $0, $720 zoneTableEntry.w $0, $2280, -$100, $800 ; MTZ act 1 zoneTableEntry.w $0, $1E80, -$100, $800 ; MTZ act 2 zoneTableEntry.w $0, $2A80, -$100, $800 ; MTZ act 3 zoneTableEntry.w $0, $3FFF, -$100, $800 zoneTableEntry.w $0, $3FFF, $0, $720 ; WFZ zoneTableEntry.w $0, $3FFF, $0, $720 zoneTableEntry.w $0, $2800, $0, $720 ; HTZ act 1 zoneTableEntry.w $0, $3280, $0, $720 ; HTZ act 2 zoneTableEntry.w $0, $3FFF, $0, $720 ; $08 zoneTableEntry.w $0, $3FFF, $0, $720 zoneTableEntry.w $0, $3FFF, $0, $720 ; $09 zoneTableEntry.w $0, $3FFF, $0, $720 zoneTableEntry.w $0, $2F80, $0, $680 ; OOZ act 1 zoneTableEntry.w $0, $2D00, $0, $680 ; OOZ act 2 zoneTableEntry.w $0, $2380, $3C0, $720 ; MCZ act 1 zoneTableEntry.w $0, $3FFF, $60, $720 ; MCZ act 2 zoneTableEntry.w $0, $27A0, $0, $720 ; CNZ act 1 zoneTableEntry.w $0, $2A80, $0, $720 ; CNZ act 2 zoneTableEntry.w $0, $2780, $0, $720 ; CPZ act 1 zoneTableEntry.w $0, $2A80, $0, $720 ; CPZ act 2 zoneTableEntry.w $0, $1000, $C8, $C8 ; DEZ zoneTableEntry.w $0, $1000, $C8, $C8 zoneTableEntry.w $0, $28C0, $200, $600 ; ARZ act 1 zoneTableEntry.w $0, $3FFF, $180, $710 ; ARZ act 2 zoneTableEntry.w $0, $3FFF, $0, $000 ; SCZ zoneTableEntry.w $0, $3FFF, $0, $720 zoneTableEnd ; =========================================================================== + tst.b (Last_star_pole_hit).w ; was a star pole hit yet? beq.s + ; if not, branch jsr (Obj79_LoadData).l ; load the previously saved data move.w (MainCharacter+x_pos).w,d1 move.w (MainCharacter+y_pos).w,d0 bra.s ++ ; =========================================================================== + ; Put the character at the start location for the level move.w (Current_ZoneAndAct).w,d0 ror.b #1,d0 lsr.w #5,d0 lea StartLocations(pc,d0.w),a1 moveq #0,d1 move.w (a1)+,d1 move.w d1,(MainCharacter+x_pos).w moveq #0,d0 move.w (a1),d0 move.w d0,(MainCharacter+y_pos).w + subi.w #$A0,d1 bcc.s + moveq #0,d1 + move.w (Camera_Max_X_pos).w,d2 cmp.w d2,d1 blo.s + move.w d2,d1 + move.w d1,(Camera_X_pos).w move.w d1,(Camera_X_pos_P2).w subi.w #$60,d0 bcc.s + moveq #0,d0 + cmp.w (Camera_Max_Y_pos_now).w,d0 blt.s + move.w (Camera_Max_Y_pos_now).w,d0 + move.w d0,(Camera_Y_pos).w move.w d0,(Camera_Y_pos_P2).w bsr.w InitCameraValues rts ; End of function LevelSizeLoad ; =========================================================================== ; -------------------------------------------------------------------------------------- ; CHARACTER START LOCATION ARRAY ; 2 entries per act, corresponding to the X and Y locations that you want the player to ; appear at when the level starts. ; -------------------------------------------------------------------------------------- StartLocations: zoneOrderedTable 2,4 ; WrdArr_StartLoc zoneTableBinEntry 2, "startpos/EHZ_1.bin" ; $00 zoneTableBinEntry 2, "startpos/EHZ_2.bin" zoneTableEntry.w $60, $28F ; $01 zoneTableEntry.w $60, $2AF zoneTableEntry.w $60, $1AC ; $02 zoneTableEntry.w $60, $1AC zoneTableEntry.w $60, $28F ; $03 zoneTableEntry.w $60, $2AF zoneTableBinEntry 2, "startpos/MTZ_1.bin" ; $04 zoneTableBinEntry 2, "startpos/MTZ_2.bin" zoneTableBinEntry 2, "startpos/MTZ_3.bin" ; $05 zoneTableEntry.w $60, $2AF zoneTableBinEntry 2, "startpos/WFZ.bin" ; $06 zoneTableEntry.w $1E0, $4CC zoneTableBinEntry 2, "startpos/HTZ_1.bin" ; $07 zoneTableBinEntry 2, "startpos/HTZ_2.bin" zoneTableEntry.w $230, $1AC ; $08 zoneTableEntry.w $230, $1AC zoneTableEntry.w $60, $28F ; $09 zoneTableEntry.w $60, $2AF zoneTableBinEntry 2, "startpos/OOZ_1.bin" ; $0A zoneTableBinEntry 2, "startpos/OOZ_2.bin" zoneTableBinEntry 2, "startpos/MCZ_1.bin" ; $0B zoneTableBinEntry 2, "startpos/MCZ_2.bin" zoneTableBinEntry 2, "startpos/CNZ_1.bin" ; $0C zoneTableBinEntry 2, "startpos/CNZ_2.bin" zoneTableBinEntry 2, "startpos/CPZ_1.bin" ; $0D zoneTableBinEntry 2, "startpos/CPZ_2.bin" zoneTableBinEntry 2, "startpos/DEZ.bin" ; $0E zoneTableEntry.w $60, $12D zoneTableBinEntry 2, "startpos/ARZ_1.bin" ; $0F zoneTableBinEntry 2, "startpos/ARZ_2.bin" zoneTableBinEntry 2, "startpos/SCZ.bin" ; $10 zoneTableEntry.w $140, $70 zoneTableEnd ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_C258: InitCameraValues: tst.b (Last_star_pole_hit).w ; was a star pole hit yet? bne.s + ; if yes, branch move.w d0,(Camera_BG_Y_pos).w move.w d0,(Camera_BG2_Y_pos).w move.w d1,(Camera_BG_X_pos).w move.w d1,(Camera_BG2_X_pos).w move.w d1,(Camera_BG3_X_pos).w move.w d0,(Camera_BG_Y_pos_P2).w move.w d0,(Camera_BG2_Y_pos_P2).w move.w d1,(Camera_BG_X_pos_P2).w move.w d1,(Camera_BG2_X_pos_P2).w move.w d1,(Camera_BG3_X_pos_P2).w + moveq #0,d2 move.b (Current_Zone).w,d2 add.w d2,d2 move.w InitCam_Index(pc,d2.w),d2 jmp InitCam_Index(pc,d2.w) ; End of function InitCameraValues ; =========================================================================== ; off_C296: InitCam_Index: zoneOrderedOffsetTable 2,1 zoneOffsetTableEntry.w InitCam_EHZ zoneOffsetTableEntry.w InitCam_Null0 ; 1 zoneOffsetTableEntry.w InitCam_WZ ; 2 zoneOffsetTableEntry.w InitCam_Null0 ; 3 zoneOffsetTableEntry.w InitCam_Std ; 4 MTZ zoneOffsetTableEntry.w InitCam_Std ; 5 MTZ3 zoneOffsetTableEntry.w InitCam_Null1 ; 6 zoneOffsetTableEntry.w InitCam_HTZ ; 7 zoneOffsetTableEntry.w InitCam_HPZ ; 8 zoneOffsetTableEntry.w InitCam_Null2 ; 9 zoneOffsetTableEntry.w InitCam_OOZ ; 10 zoneOffsetTableEntry.w InitCam_MCZ ; 11 zoneOffsetTableEntry.w InitCam_CNZ ; 12 zoneOffsetTableEntry.w InitCam_CPZ ; 13 zoneOffsetTableEntry.w InitCam_Null3 ; 14 zoneOffsetTableEntry.w InitCam_ARZ ; 15 zoneOffsetTableEntry.w InitCam_SCZ ; 16 zoneTableEnd ; =========================================================================== ;loc_C2B8: InitCam_EHZ: clr.l (Camera_BG_X_pos).w clr.l (Camera_BG_Y_pos).w clr.l (Camera_BG2_Y_pos).w clr.l (Camera_BG3_Y_pos).w lea (TempArray_LayerDef).w,a2 clr.l (a2)+ clr.l (a2)+ clr.l (a2)+ clr.l (Camera_BG_X_pos_P2).w clr.l (Camera_BG_Y_pos_P2).w clr.l (Camera_BG2_Y_pos_P2).w clr.l (Camera_BG3_Y_pos_P2).w rts ; =========================================================================== ; wtf: InitCam_Null0: if gameRevision=0 rts endif ; =========================================================================== ; Wood_Zone_BG: InitCam_WZ: if gameRevision=0 asr.w #2,d0 addi.w #$400,d0 move.w d0,(Camera_BG_Y_pos).w asr.w #3,d1 move.w d1,(Camera_BG_X_pos).w rts endif ; =========================================================================== ;loc_C2E4: InitCam_Std: asr.w #2,d0 move.w d0,(Camera_BG_Y_pos).w asr.w #3,d1 move.w d1,(Camera_BG_X_pos).w rts ; =========================================================================== ;return_C2F2: InitCam_Null1: rts ; =========================================================================== ;loc_C2F4: InitCam_HTZ: clr.l (Camera_BG_X_pos).w clr.l (Camera_BG_Y_pos).w clr.l (Camera_BG2_Y_pos).w clr.l (Camera_BG3_Y_pos).w lea (TempArray_LayerDef).w,a2 clr.l (a2)+ clr.l (a2)+ clr.l (a2)+ clr.l (Camera_BG_X_pos_P2).w clr.l (Camera_BG_Y_pos_P2).w clr.l (Camera_BG2_Y_pos_P2).w clr.l (Camera_BG3_Y_pos_P2).w rts ; =========================================================================== ; Hidden_Palace_Zone_BG: InitCam_HPZ: if gameRevision=0 asr.w #1,d0 move.w d0,(Camera_BG_Y_pos).w clr.l (Camera_BG_X_pos).w rts endif ; =========================================================================== ; Unknown_Zone_BG: InitCam_CCZ: if gameRevision=0 asl.l #4,d0 move.l d0,d2 asl.l #1,d0 add.l d2,d0 asr.l #8,d0 addq.w #1,d0 move.w d0,(Camera_BG_Y_pos).w clr.l (Camera_BG_X_pos).w rts endif ; =========================================================================== ;return_C320: InitCam_Null2: rts ; =========================================================================== ;loc_C322: InitCam_OOZ: lsr.w #3,d0 addi.w #$50,d0 move.w d0,(Camera_BG_Y_pos).w clr.l (Camera_BG_X_pos).w rts ; =========================================================================== ;loc_C332: InitCam_MCZ: clr.l (Camera_BG_X_pos).w clr.l (Camera_BG_X_pos_P2).w tst.b (Current_Act).w bne.s + divu.w #3,d0 subi.w #$140,d0 move.w d0,(Camera_BG_Y_pos).w move.w d0,(Camera_BG_Y_pos_P2).w rts ; =========================================================================== + divu.w #6,d0 subi.w #$10,d0 move.w d0,(Camera_BG_Y_pos).w move.w d0,(Camera_BG_Y_pos_P2).w rts ; =========================================================================== ;loc_C364: InitCam_CNZ: clr.l (Camera_BG_X_pos).w clr.l (Camera_BG_Y_pos).w clr.l (Camera_BG_Y_pos_P2).w rts ; =========================================================================== ;loc_C372: InitCam_CPZ: lsr.w #2,d0 move.w d0,(Camera_BG_Y_pos).w move.w d0,(Camera_BG_Y_pos_P2).w lsr.w #1,d1 move.w d1,(Camera_BG2_X_pos).w lsr.w #2,d1 move.w d1,(Camera_BG_X_pos).w rts ; =========================================================================== ;return_C38A: InitCam_Null3: rts ; =========================================================================== ;loc_C38C: InitCam_ARZ: tst.b (Current_Act).w beq.s + subi.w #$E0,d0 lsr.w #1,d0 move.w d0,(Camera_BG_Y_pos).w bra.s loc_C3A6 ; =========================================================================== + subi.w #$180,d0 move.w d0,(Camera_BG_Y_pos).w loc_C3A6: muls.w #$119,d1 asr.l #8,d1 move.w d1,(Camera_BG_X_pos).w move.w d1,(Camera_ARZ_BG_X_pos).w clr.w (Camera_BG_X_pos+2).w clr.w (Camera_ARZ_BG_X_pos+2).w clr.l (Camera_BG2_Y_pos).w clr.l (Camera_BG3_Y_pos).w rts ; =========================================================================== ;loc_C3C6: InitCam_SCZ: clr.l (Camera_BG_X_pos).w clr.l (Camera_BG_Y_pos).w rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_C3D0: DeformBgLayer: tst.b (Deform_lock).w beq.s + rts ; --------------------------------------------------------------------------- + clr.w (Scroll_flags).w clr.w (Scroll_flags_BG).w clr.w (Scroll_flags_BG2).w clr.w (Scroll_flags_BG3).w clr.w (Scroll_flags_P2).w clr.w (Scroll_flags_BG_P2).w clr.w (Scroll_flags_BG2_P2).w clr.w (Scroll_flags_BG3_P2).w clr.w (Camera_X_pos_diff).w clr.w (Camera_Y_pos_diff).w clr.w (Camera_X_pos_diff_P2).w clr.w (Camera_Y_pos_diff_P2).w cmpi.b #sky_chase_zone,(Current_Zone).w bne.w + tst.w (Debug_placement_mode).w beq.w loc_C4D0 ; skip normal scrolling for SCZ + tst.b (Scroll_lock).w bne.s DeformBgLayerAfterScrollVert lea (MainCharacter).w,a0 ; a0=character lea (Camera_X_pos).w,a1 lea (Camera_Min_X_pos).w,a2 lea (Scroll_flags).w,a3 lea (Camera_X_pos_diff).w,a4 lea (Horiz_scroll_delay_val).w,a5 lea (Sonic_Pos_Record_Buf).w,a6 cmpi.w #2,(Player_mode).w bne.s + lea (Horiz_scroll_delay_val_P2).w,a5 lea (Tails_Pos_Record_Buf).w,a6 + bsr.w ScrollHoriz lea (Horiz_block_crossed_flag).w,a2 bsr.w SetHorizScrollFlags lea (Camera_Y_pos).w,a1 lea (Camera_Min_X_pos).w,a2 lea (Camera_Y_pos_diff).w,a4 move.w (Camera_Y_pos_bias).w,d3 cmpi.w #2,(Player_mode).w bne.s + move.w (Camera_Y_pos_bias_P2).w,d3 + bsr.w ScrollVerti lea (Verti_block_crossed_flag).w,a2 bsr.w SetVertiScrollFlags DeformBgLayerAfterScrollVert: tst.w (Two_player_mode).w beq.s loc_C4D0 tst.b (Scroll_lock_P2).w bne.s loc_C4D0 lea (Sidekick).w,a0 ; a0=character lea (Camera_X_pos_P2).w,a1 lea (Tails_Min_X_pos).w,a2 lea (Scroll_flags_P2).w,a3 lea (Camera_X_pos_diff_P2).w,a4 lea (Horiz_scroll_delay_val_P2).w,a5 lea (Tails_Pos_Record_Buf).w,a6 bsr.w ScrollHoriz lea (Horiz_block_crossed_flag_P2).w,a2 bsr.w SetHorizScrollFlags lea (Camera_Y_pos_P2).w,a1 lea (Tails_Min_X_pos).w,a2 lea (Camera_Y_pos_diff_P2).w,a4 move.w (Camera_Y_pos_bias_P2).w,d3 bsr.w ScrollVerti lea (Verti_block_crossed_flag_P2).w,a2 bsr.w SetVertiScrollFlags loc_C4D0: bsr.w RunDynamicLevelEvents move.w (Camera_Y_pos).w,(Vscroll_Factor_FG).w move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w move.l (Camera_X_pos).w,(Camera_X_pos_copy).w move.l (Camera_Y_pos).w,(Camera_Y_pos_copy).w moveq #0,d0 move.b (Current_Zone).w,d0 add.w d0,d0 move.w SwScrl_Index(pc,d0.w),d0 jmp SwScrl_Index(pc,d0.w) ; End of function DeformBgLayer ; =========================================================================== ; --------------------------------------------------------------------------- ; JUMP TABLE FOR SOFTWARE SCROLL MANAGERS ; ; "Software scrolling" is my term for what Nemesis (and by extension, the rest ; of the world) calls "rasterized layer deformation".* Software scroll managers ; are needed to achieve certain special camera effects - namely, locking the ; screen for a boss fight and defining the limits of said screen lock, or in ; the case of Sky Chase Zone ($10), moving the camera at a fixed rate through ; a predefined course. ; They are also used for things like controlling the parallax scrolling and ; water ripple effects in EHZ, and moving the clouds in HTZ and the stars in DEZ. ; --------------------------------------------------------------------------- SwScrl_Index: zoneOrderedOffsetTable 2,1 ; JmpTbl_SwScrlMgr zoneOffsetTableEntry.w SwScrl_EHZ ; $00 zoneOffsetTableEntry.w SwScrl_Minimal ; $01 zoneOffsetTableEntry.w SwScrl_Lev2 ; $02 zoneOffsetTableEntry.w SwScrl_Minimal ; $03 zoneOffsetTableEntry.w SwScrl_MTZ ; $04 zoneOffsetTableEntry.w SwScrl_MTZ ; $05 zoneOffsetTableEntry.w SwScrl_WFZ ; $06 zoneOffsetTableEntry.w SwScrl_HTZ ; $07 zoneOffsetTableEntry.w SwScrl_HPZ ; $08 zoneOffsetTableEntry.w SwScrl_Minimal ; $09 zoneOffsetTableEntry.w SwScrl_OOZ ; $0A zoneOffsetTableEntry.w SwScrl_MCZ ; $0B zoneOffsetTableEntry.w SwScrl_CNZ ; $0C zoneOffsetTableEntry.w SwScrl_CPZ ; $0D zoneOffsetTableEntry.w SwScrl_DEZ ; $0E zoneOffsetTableEntry.w SwScrl_ARZ ; $0F zoneOffsetTableEntry.w SwScrl_SCZ ; $10 zoneTableEnd ; =========================================================================== ; loc_C51E: SwScrl_Title: move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w addq.w #1,(Camera_X_pos).w move.w (Camera_X_pos).w,d2 neg.w d2 asr.w #2,d2 lea (Horiz_Scroll_Buf).w,a1 moveq #0,d0 move.w #bytesToLcnt($280),d1 - move.l d0,(a1)+ dbf d1,- move.w d2,d0 move.w #bytesToLcnt($80),d1 - move.l d0,(a1)+ dbf d1,- move.w d0,d3 move.b (Vint_runcount+3).w,d1 andi.w #7,d1 bne.s + subq.w #1,(TempArray_LayerDef).w + move.w (TempArray_LayerDef).w,d1 andi.w #$1F,d1 lea SwScrl_RippleData(pc),a2 lea (a2,d1.w),a2 move.w #bytesToLcnt($40),d1 - move.b (a2)+,d0 ext.w d0 add.w d3,d0 move.l d0,(a1)+ dbf d1,- rts ; =========================================================================== ; loc_C57E: SwScrl_EHZ: tst.w (Two_player_mode).w bne.w SwScrl_EHZ_2P move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w lea (Horiz_Scroll_Buf).w,a1 move.w (Camera_X_pos).w,d0 neg.w d0 move.w d0,d2 swap d0 move.w #0,d0 move.w #bytesToLcnt($58),d1 - move.l d0,(a1)+ dbf d1,- move.w d2,d0 asr.w #6,d0 move.w #bytesToLcnt($E8),d1 - move.l d0,(a1)+ dbf d1,- move.w d0,d3 move.b (Vint_runcount+3).w,d1 andi.w #7,d1 bne.s + subq.w #1,(TempArray_LayerDef).w + move.w (TempArray_LayerDef).w,d1 andi.w #$1F,d1 lea (SwScrl_RippleData).l,a2 lea (a2,d1.w),a2 move.w #bytesToLcnt($54),d1 - move.b (a2)+,d0 ext.w d0 add.w d3,d0 move.l d0,(a1)+ dbf d1,- move.w #0,d0 move.w #bytesToLcnt($2C),d1 - move.l d0,(a1)+ dbf d1,- move.w d2,d0 asr.w #4,d0 move.w #bytesToLcnt($40),d1 - move.l d0,(a1)+ dbf d1,- move.w d2,d0 asr.w #4,d0 move.w d0,d1 asr.w #1,d1 add.w d1,d0 move.w #bytesToLcnt($40),d1 - move.l d0,(a1)+ dbf d1,- move.l d0,d4 swap d4 move.w d2,d0 asr.w #1,d0 move.w d2,d1 asr.w #3,d1 sub.w d1,d0 ext.l d0 asl.l #8,d0 divs.w #$30,d0 ext.l d0 asl.l #8,d0 moveq #0,d3 move.w d2,d3 asr.w #3,d3 move.w #bytesToLcnt($3C),d1 ; $3C bytes - move.w d4,(a1)+ move.w d3,(a1)+ swap d3 add.l d0,d3 swap d3 dbf d1,- move.w #($48)/8-1,d1 ; $48 bytes - move.w d4,(a1)+ move.w d3,(a1)+ move.w d4,(a1)+ move.w d3,(a1)+ swap d3 add.l d0,d3 add.l d0,d3 swap d3 dbf d1,- move.w #($B4)/12-1,d1 ; $B4 bytes - move.w d4,(a1)+ move.w d3,(a1)+ move.w d4,(a1)+ move.w d3,(a1)+ move.w d4,(a1)+ move.w d3,(a1)+ swap d3 add.l d0,d3 add.l d0,d3 add.l d0,d3 swap d3 dbf d1,- ; note there is a bug here. the bottom 8 pixels haven't had their hscroll values set. only the EHZ scrolling code has this bug. rts ; =========================================================================== ; horizontal offsets for the water rippling effect ; byte_C682: SwScrl_RippleData: dc.b 1, 2, 1, 3, 1, 2, 2, 1, 2, 3, 1, 2, 1, 2, 0, 0; 16 dc.b 2, 0, 3, 2, 2, 3, 2, 2, 1, 3, 0, 0, 1, 0, 1, 3; 32 dc.b 1, 2, 1, 3, 1, 2, 2, 1, 2, 3, 1, 2, 1, 2, 0, 0; 48 dc.b 2, 0, 3, 2, 2, 3, 2, 2, 1, 3, 0, 0, 1, 0, 1, 3; 64 dc.b 1, 2 ; 66 ; =========================================================================== ; loc_C6C4: SwScrl_EHZ_2P: move.b (Vint_runcount+3).w,d1 andi.w #7,d1 bne.s + subq.w #1,(TempArray_LayerDef).w + move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w andi.l #$FFFEFFFE,(Vscroll_Factor).w lea (Horiz_Scroll_Buf).w,a1 move.w (Camera_X_pos).w,d0 move.w #bytesToLcnt($2C),d1 bsr.s sub_C71A moveq #0,d0 move.w d0,(Vscroll_Factor_P2_BG).w subi.w #$E0,(Vscroll_Factor_P2_BG).w move.w (Camera_Y_pos_P2).w,(Vscroll_Factor_P2_FG).w subi.w #$E0,(Vscroll_Factor_P2_FG).w andi.l #$FFFEFFFE,(Vscroll_Factor_P2).w lea (Horiz_Scroll_Buf+$1B0).w,a1 move.w (Camera_X_pos_P2).w,d0 move.w #bytesToLcnt($3C),d1 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_C71A: neg.w d0 move.w d0,d2 swap d0 move.w #0,d0 - move.l d0,(a1)+ dbf d1,- move.w d2,d0 asr.w #6,d0 move.w #bytesToLcnt($74),d1 - move.l d0,(a1)+ dbf d1,- move.w d0,d3 move.w (TempArray_LayerDef).w,d1 andi.w #$1F,d1 lea_ SwScrl_RippleData,a2 lea (a2,d1.w),a2 move.w #bytesToLcnt($2C),d1 - move.b (a2)+,d0 ext.w d0 add.w d3,d0 move.l d0,(a1)+ dbf d1,- move.w #0,d0 move.w #bytesToLcnt($14),d1 - move.l d0,(a1)+ dbf d1,- move.w d2,d0 asr.w #4,d0 move.w #bytesToLcnt($20),d1 - move.l d0,(a1)+ dbf d1,- move.w d2,d0 asr.w #4,d0 move.w d0,d1 asr.w #1,d1 add.w d1,d0 move.w #bytesToLcnt($20),d1 - move.l d0,(a1)+ dbf d1,- move.w d2,d0 asr.w #1,d0 move.w d2,d1 asr.w #3,d1 sub.w d1,d0 ext.l d0 asl.l #8,d0 divs.w #$30,d0 ext.l d0 asl.l #8,d0 moveq #0,d3 move.w d2,d3 asr.w #3,d3 move.w #bytesToLcnt($A0),d1 - move.w d2,(a1)+ move.w d3,(a1)+ swap d3 add.l d0,d3 swap d3 dbf d1,- rts ; End of function sub_C71A ; =========================================================================== ; unused... ; loc_C7BA: SwScrl_Lev2: if gameRevision<2 move.w (Camera_X_pos_diff).w,d4 ext.l d4 asl.l #5,d4 move.w (Camera_Y_pos_diff).w,d5 ext.l d5 asl.l #6,d5 bsr.w SetHorizVertiScrollFlagsBG move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w lea (Horiz_Scroll_Buf).w,a1 move.w #bytesToLcnt($380),d1 move.w (Camera_X_pos).w,d0 neg.w d0 swap d0 move.w (Camera_BG_X_pos).w,d0 neg.w d0 - move.l d0,(a1)+ dbf d1,- endif rts ; =========================================================================== ; loc_C7F2: SwScrl_MTZ: move.w (Camera_X_pos_diff).w,d4 ext.l d4 asl.l #5,d4 move.w (Camera_Y_pos_diff).w,d5 ext.l d5 asl.l #6,d5 bsr.w SetHorizVertiScrollFlagsBG move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w lea (Horiz_Scroll_Buf).w,a1 move.w #bytesToLcnt($380),d1 move.w (Camera_X_pos).w,d0 neg.w d0 swap d0 move.w (Camera_BG_X_pos).w,d0 neg.w d0 - move.l d0,(a1)+ dbf d1,- rts ; =========================================================================== ; loc_C82A: SwScrl_WFZ: move.w (Camera_BG_X_pos_diff).w,d4 ext.l d4 asl.l #8,d4 moveq #2,d6 bsr.w SetHorizScrollFlagsBG move.w (Camera_BG_Y_pos_diff).w,d5 ext.l d5 lsl.l #8,d5 moveq #6,d6 bsr.w SetVertiScrollFlagsBG move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w move.l (Camera_BG_X_pos).w,d0 ; This can be removed if the getaway ship's entry uses d0 instead. move.l d0,d1 lea (TempArray_LayerDef).w,a2 move.l d0,(a2)+ ; Static parts of BG (generally no clouds in them) move.l d1,(a2)+ ; Eggman's getaway ship ; Note: this is bugged: this tallies only the cloud speeds. It works fine ; if you are standing still, but makes the clouds move faster when going ; right and slower when going left. This is exactly the opposite of what ; should happen. addi.l #$8000,(a2)+ ; Larger clouds addi.l #$4000,(a2)+ ; Medium clouds addi.l #$2000,(a2)+ ; Small clouds lea (SwScrl_WFZ_Transition_Array).l,a3 cmpi.w #$2700,(Camera_X_pos).w bhs.s .got_array lea (SwScrl_WFZ_Normal_Array).l,a3 .got_array: lea (TempArray_LayerDef).w,a2 lea (Horiz_Scroll_Buf).w,a1 move.w (Camera_BG_Y_pos).w,d1 andi.w #$7FF,d1 moveq #0,d0 moveq #0,d3 ; Find the first visible scrolling section .seg_loop: move.b (a3)+,d0 ; Number of lines in this segment addq.w #1,a3 ; Skip index sub.w d0,d1 ; Does this segment have any visible lines? bcc.s .seg_loop ; Branch if not neg.w d1 ; d1 = number of lines to draw in this segment move.w #bytesToLcnt($380),d2 ; Number of rows in hscroll buffer move.w (Camera_X_pos).w,d0 neg.w d0 swap d0 move.b -1(a3),d3 ; Fetch TempArray_LayerDef index move.w (a2,d3.w),d0 ; Fetch scroll value for this row... neg.w d0 ; ... and flip sign for VDP .row_loop: move.l d0,(a1)+ subq.w #1,d1 ; Has the current segment finished? bne.s .next_row ; Branch if not move.b (a3)+,d1 ; Fetch a new line count move.b (a3)+,d3 ; Fetch TempArray_LayerDef index move.w (a2,d3.w),d0 ; Fetch scroll value for this row... neg.w d0 ; ... and flip sign for VDP .next_row: dbf d2,.row_loop rts ; =========================================================================== ; WFZ BG scrolling data ; Each pair of bytes corresponds to one scrolling segment of the BG, and ; the bytes have the following meaning: ; number of lines, index into TempArray_LayerDef ; byte_C8CA SwScrl_WFZ_Transition_Array: dc.b $C0, 0,$C0, 0,$80, 0,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C dc.b $30,$10,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C,$30,$10,$20, 8; 16 dc.b $30, $C,$30,$10,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C,$30,$10; 32 dc.b $80, 4,$80, 4,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C,$30,$10; 48 dc.b $20, 8,$30, $C,$30,$10,$C0, 0,$C0, 0,$80, 0; 64 ;byte_C916 SwScrl_WFZ_Normal_Array: dc.b $C0, 0,$C0, 0,$80, 0,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C dc.b $30,$10,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C,$30,$10,$20, 8; 16 dc.b $30, $C,$30,$10,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C,$30,$10; 32 dc.b $20, 8,$30, $C,$30,$10,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C; 48 dc.b $30,$10,$20, 8,$30, $C,$30,$10,$C0, 0,$C0, 0,$80, 0; 64 ; Note: this array is missing $80 lines compared to the transition array. ; This causes the lower clouds to read data from the start of SwScrl_HTZ. ; These are the missing entries: if 1==0 dc.b $20, 8,$30, $C,$30,$10 endif ; =========================================================================== ; loc_C964: SwScrl_HTZ: tst.w (Two_player_mode).w bne.w SwScrl_HTZ_2P ; never used in normal gameplay tst.b (Screen_Shaking_Flag_HTZ).w bne.w HTZ_Screen_Shake move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w lea (Horiz_Scroll_Buf).w,a1 move.w (Camera_X_pos).w,d0 neg.w d0 move.w d0,d2 swap d0 move.w d2,d0 asr.w #3,d0 move.w #bytesToLcnt($200),d1 - move.l d0,(a1)+ dbf d1,- move.l d0,d4 move.w (TempArray_LayerDef+$22).w,d0 addq.w #4,(TempArray_LayerDef+$22).w sub.w d0,d2 move.w d2,d0 move.w d0,d1 asr.w #1,d0 asr.w #4,d1 sub.w d1,d0 ext.l d0 asl.l #8,d0 divs.w #$70,d0 ext.l d0 asl.l #8,d0 lea (TempArray_LayerDef).w,a2 moveq #0,d3 move.w d1,d3 swap d3 add.l d0,d3 swap d3 move.w d3,(a2)+ swap d3 add.l d0,d3 swap d3 move.w d3,(a2)+ swap d3 add.l d0,d3 swap d3 move.w d3,(a2)+ move.w d3,(a2)+ swap d3 add.l d0,d3 add.l d0,d3 swap d3 moveq #3,d1 - move.w d3,(a2)+ move.w d3,(a2)+ move.w d3,(a2)+ swap d3 add.l d0,d3 add.l d0,d3 add.l d0,d3 swap d3 dbf d1,- add.l d0,d0 add.l d0,d0 move.w d3,d4 move.l d4,(a1)+ move.l d4,(a1)+ move.l d4,(a1)+ swap d3 add.l d0,d3 swap d3 move.w d3,d4 move.l d4,(a1)+ move.l d4,(a1)+ move.l d4,(a1)+ move.l d4,(a1)+ move.l d4,(a1)+ swap d3 add.l d0,d3 swap d3 move.w d3,d4 move.w #6,d1 - move.l d4,(a1)+ dbf d1,- swap d3 add.l d0,d3 add.l d0,d3 swap d3 move.w d3,d4 move.w #7,d1 - move.l d4,(a1)+ dbf d1,- swap d3 add.l d0,d3 add.l d0,d3 swap d3 move.w d3,d4 move.w #9,d1 - move.l d4,(a1)+ dbf d1,- swap d3 add.l d0,d3 add.l d0,d3 add.l d0,d3 swap d3 move.w d3,d4 move.w #$E,d1 - move.l d4,(a1)+ dbf d1,- swap d3 add.l d0,d3 add.l d0,d3 add.l d0,d3 swap d3 move.w #2,d2 - move.w d3,d4 move.w #$F,d1 - move.l d4,(a1)+ dbf d1,- swap d3 add.l d0,d3 add.l d0,d3 add.l d0,d3 add.l d0,d3 swap d3 dbf d2,-- rts ; =========================================================================== ;loc_CA92: HTZ_Screen_Shake: move.w (Camera_BG_X_pos_diff).w,d4 ext.l d4 lsl.l #8,d4 moveq #2,d6 bsr.w SetHorizScrollFlagsBG move.w (Camera_BG_Y_pos_diff).w,d5 ext.l d5 lsl.l #8,d5 moveq #0,d6 bsr.w SetVertiScrollFlagsBG move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w move.w (Camera_Y_pos).w,(Vscroll_Factor_FG).w move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w moveq #0,d2 tst.b (Screen_Shaking_Flag).w beq.s + move.w (Timer_frames).w,d0 andi.w #$3F,d0 lea_ SwScrl_RippleData,a1 lea (a1,d0.w),a1 moveq #0,d0 move.b (a1)+,d0 add.w d0,(Vscroll_Factor_FG).w add.w d0,(Vscroll_Factor_BG).w add.w d0,(Camera_Y_pos_copy).w move.b (a1)+,d2 add.w d2,(Camera_X_pos_copy).w + lea (Horiz_Scroll_Buf).w,a1 move.w #bytesToLcnt($380),d1 move.w (Camera_X_pos).w,d0 add.w d2,d0 neg.w d0 swap d0 move.w (Camera_BG_X_pos).w,d0 add.w d2,d0 neg.w d0 - move.l d0,(a1)+ dbf d1,- rts ; =========================================================================== ; loc_CB10: SwScrl_HTZ_2P: move.w (Camera_X_pos_diff).w,d4 ext.l d4 asl.l #6,d4 move.w (Camera_Y_pos_diff).w,d5 ext.l d5 asl.l #2,d5 moveq #0,d5 bsr.w SetHorizVertiScrollFlagsBG move.b #0,(Scroll_flags_BG).w move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w andi.l #$FFFEFFFE,(Vscroll_Factor).w lea (Horiz_Scroll_Buf).w,a1 move.w #bytesToLcnt($1C0),d1 move.w (Camera_X_pos).w,d0 neg.w d0 swap d0 move.w (Camera_BG_X_pos).w,d0 neg.w d0 - move.l d0,(a1)+ dbf d1,- move.w (Camera_X_pos_diff_P2).w,d4 ext.l d4 asl.l #6,d4 add.l d4,(Camera_BG_X_pos_P2).w moveq #0,d0 move.w d0,(Vscroll_Factor_P2_BG).w subi.w #$E0,(Vscroll_Factor_P2_BG).w move.w (Camera_Y_pos_P2).w,(Vscroll_Factor_P2_FG).w subi.w #$E0,(Vscroll_Factor_P2_FG).w andi.l #$FFFEFFFE,(Vscroll_Factor_P2).w lea (Horiz_Scroll_Buf+$1B0).w,a1 move.w #bytesToLcnt($1D0),d1 move.w (Camera_X_pos_P2).w,d0 neg.w d0 swap d0 move.w (Camera_BG_X_pos_P2).w,d0 neg.w d0 - move.l d0,(a1)+ dbf d1,- rts ; =========================================================================== ; unused... ; loc_CBA0: SwScrl_HPZ: move.w (Camera_X_pos_diff).w,d4 ext.l d4 asl.l #6,d4 moveq #2,d6 bsr.w SetHorizScrollFlagsBG move.w (Camera_Y_pos_diff).w,d5 ext.l d5 asl.l #7,d5 moveq #6,d6 bsr.w SetVertiScrollFlagsBG move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w lea (TempArray_LayerDef).w,a1 move.w (Camera_X_pos).w,d2 neg.w d2 move.w d2,d0 asr.w #1,d0 move.w #7,d1 - move.w d0,(a1)+ dbf d1,- move.w d2,d0 asr.w #3,d0 sub.w d2,d0 ext.l d0 asl.l #3,d0 divs.w #8,d0 ext.l d0 asl.l #4,d0 asl.l #8,d0 moveq #0,d3 move.w d2,d3 asr.w #1,d3 lea (TempArray_LayerDef+$60).w,a2 swap d3 add.l d0,d3 swap d3 move.w d3,(a1)+ move.w d3,(a1)+ move.w d3,(a1)+ move.w d3,-(a2) move.w d3,-(a2) move.w d3,-(a2) swap d3 add.l d0,d3 swap d3 move.w d3,(a1)+ move.w d3,(a1)+ move.w d3,-(a2) move.w d3,-(a2) swap d3 add.l d0,d3 swap d3 move.w d3,(a1)+ move.w d3,-(a2) swap d3 add.l d0,d3 swap d3 move.w d3,(a1)+ move.w d3,-(a2) move.w (Camera_BG_X_pos).w,d0 neg.w d0 move.w #$19,d1 - move.w d0,(a1)+ dbf d1,- adda.w #$E,a1 move.w d2,d0 asr.w #1,d0 move.w #$17,d1 - move.w d0,(a1)+ dbf d1,- lea (TempArray_LayerDef).w,a2 move.w (Camera_BG_Y_pos).w,d0 move.w d0,d2 andi.w #$3F0,d0 lsr.w #3,d0 lea (a2,d0.w),a2 bra.w SwScrl_HPZ_Continued ; =========================================================================== ; loc_CC66: SwScrl_OOZ: move.w (Camera_X_pos_diff).w,d0 ext.l d0 asl.l #5,d0 add.l d0,(Camera_BG_X_pos).w move.w (Camera_Y_pos_diff).w,d0 ext.l d0 asl.l #5,d0 move.l (Camera_BG_Y_pos).w,d3 add.l d3,d0 moveq #4,d6 bsr.w SetVertiScrollFlagsBG2 move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w lea (Horiz_Scroll_Buf+$380).w,a1 move.w (Camera_X_pos).w,d0 neg.w d0 swap d0 move.w (Camera_BG_X_pos).w,d7 neg.w d7 move.w (Camera_BG_Y_pos).w,d1 subi.w #$50,d1 bcc.s + moveq #0,d1 + subi.w #$B0,d1 bcs.s + moveq #0,d1 + move.w #$DF,d6 add.w d6,d1 move.w d7,d0 bsr.s OOZ_BGScroll_Lines bsr.s OOZ_BGScroll_MediumClouds bsr.s OOZ_BGScroll_SlowClouds bsr.s OOZ_BGScroll_FastClouds move.w d7,d0 asr.w #4,d0 moveq #6,d1 bsr.s OOZ_BGScroll_Lines move.b (Vint_runcount+3).w,d1 andi.w #7,d1 bne.s + subq.w #1,(TempArray_LayerDef).w + move.w (TempArray_LayerDef).w,d1 andi.w #$1F,d1 lea SwScrl_RippleData(pc),a2 lea (a2,d1.w),a2 moveq #$20,d1 - move.b (a2)+,d0 ext.w d0 move.l d0,-(a1) subq.w #1,d6 bmi.s + ; rts dbf d1,- bsr.s OOZ_BGScroll_MediumClouds bsr.s OOZ_BGScroll_SlowClouds bsr.s OOZ_BGScroll_FastClouds bsr.s OOZ_BGScroll_SlowClouds bsr.s OOZ_BGScroll_MediumClouds move.w d7,d0 moveq #$47,d1 bsr.s OOZ_BGScroll_Lines + rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_CD0A OOZ_BGScroll_FastClouds: move.w d7,d0 asr.w #2,d0 bra.s + ; End of function OOZ_BGScroll_FastClouds ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_CD10 OOZ_BGScroll_MediumClouds: move.w d7,d0 asr.w #3,d0 bra.s + ; End of function OOZ_BGScroll_MediumClouds ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_CD16 OOZ_BGScroll_SlowClouds: move.w d7,d0 asr.w #4,d0 + moveq #7,d1 ; End of function OOZ_BGScroll_SlowClouds ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Scrolls min(d6,d1+1) lines by an (constant) amount specified in d0 ;sub_CD1C OOZ_BGScroll_Lines: move.l d0,-(a1) subq.w #1,d6 bmi.s + dbf d1,OOZ_BGScroll_Lines rts ; =========================================================================== + addq.l #4,sp rts ; End of function OOZ_BGScroll_Lines ; =========================================================================== ; loc_CD2C: SwScrl_MCZ: tst.w (Two_player_mode).w bne.w SwScrl_MCZ_2P move.w (Camera_Y_pos).w,d0 move.l (Camera_BG_Y_pos).w,d3 tst.b (Current_Act).w bne.s + divu.w #3,d0 subi.w #$140,d0 bra.s ++ ; =========================================================================== + divu.w #6,d0 subi.w #$10,d0 + swap d0 moveq #6,d6 bsr.w SetVertiScrollFlagsBG2 move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w moveq #0,d2 tst.b (Screen_Shaking_Flag).w beq.s + move.w (Timer_frames).w,d0 andi.w #$3F,d0 lea_ SwScrl_RippleData,a1 lea (a1,d0.w),a1 moveq #0,d0 move.b (a1)+,d0 add.w d0,(Vscroll_Factor_FG).w add.w d0,(Vscroll_Factor_BG).w add.w d0,(Camera_Y_pos_copy).w move.b (a1)+,d2 add.w d2,(Camera_X_pos_copy).w + lea (TempArray_LayerDef).w,a2 lea $1E(a2),a3 move.w (Camera_X_pos).w,d0 ext.l d0 asl.l #4,d0 divs.w #$A,d0 ext.l d0 asl.l #4,d0 asl.l #8,d0 move.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,$E(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,$C(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,$A(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,8(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,6(a2) move.w d1,$10(a2) move.w d1,$1C(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,4(a2) move.w d1,$12(a2) move.w d1,$1A(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,2(a2) move.w d1,$14(a2) move.w d1,$18(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,(a2) move.w d1,$16(a2) lea (SwScrl_MCZ_RowHeights).l,a3 lea (TempArray_LayerDef).w,a2 lea (Horiz_Scroll_Buf).w,a1 move.w (Camera_BG_Y_pos).w,d1 moveq #0,d0 - move.b (a3)+,d0 addq.w #2,a2 sub.w d0,d1 bcc.s - neg.w d1 subq.w #2,a2 move.w #bytesToLcnt($380),d2 move.w (Camera_X_pos).w,d0 neg.w d0 swap d0 move.w (a2)+,d0 neg.w d0 - move.l d0,(a1)+ subq.w #1,d1 bne.s + move.b (a3)+,d1 move.w (a2)+,d0 neg.w d0 + dbf d2,- rts ; =========================================================================== ; byte_CE6C: SwScrl_MCZ_RowHeights: dc.b $25 dc.b $17 ; 1 dc.b $12 ; 2 dc.b 7 ; 3 dc.b 7 ; 4 dc.b 2 ; 5 dc.b 2 ; 6 dc.b $30 ; 7 dc.b $D ; 8 dc.b $13 ; 9 dc.b $20 ; 10 dc.b $40 ; 11 dc.b $20 ; 12 dc.b $13 ; 13 dc.b $D ; 14 dc.b $30 ; 15 dc.b 2 ; 16 dc.b 2 ; 17 dc.b 7 ; 18 dc.b 7 ; 19 dc.b $20 ; 20 dc.b $12 ; 21 dc.b $17 ; 22 dc.b $25 ; 23 even ; =========================================================================== ; loc_CE84: SwScrl_MCZ_2P: moveq #0,d0 move.w (Camera_Y_pos).w,d0 tst.b (Current_Act).w bne.s + divu.w #3,d0 subi.w #$140,d0 bra.s ++ ; =========================================================================== + divu.w #6,d0 subi.w #$10,d0 + move.w d0,(Camera_BG_Y_pos).w move.w d0,(Vscroll_Factor_BG).w andi.l #$FFFEFFFE,(Vscroll_Factor).w lea (TempArray_LayerDef).w,a2 lea $1E(a2),a3 move.w (Camera_X_pos).w,d0 ext.l d0 asl.l #4,d0 divs.w #$A,d0 ext.l d0 asl.l #4,d0 asl.l #8,d0 move.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,$E(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,$C(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,$A(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,8(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,6(a2) move.w d1,$10(a2) move.w d1,$1C(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,4(a2) move.w d1,$12(a2) move.w d1,$1A(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,2(a2) move.w d1,$14(a2) move.w d1,$18(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,(a2) move.w d1,$16(a2) lea (SwScrl_MCZ2P_RowHeights).l,a3 lea (TempArray_LayerDef).w,a2 lea (Horiz_Scroll_Buf).w,a1 move.w (Camera_BG_Y_pos).w,d1 lsr.w #1,d1 moveq #0,d0 - move.b (a3)+,d0 addq.w #2,a2 sub.w d0,d1 bcc.s - neg.w d1 subq.w #2,a2 move.w #bytesToLcnt($1C0),d2 move.w (Camera_X_pos).w,d0 neg.w d0 swap d0 move.w (a2)+,d0 neg.w d0 - move.l d0,(a1)+ subq.w #1,d1 bne.s + move.b (a3)+,d1 move.w (a2)+,d0 neg.w d0 + dbf d2,- bra.s + ; =========================================================================== ; byte_CF90: SwScrl_MCZ2P_RowHeights: dc.b $13 dc.b $B dc.b 9 ; 1 dc.b 4 ; 2 dc.b 3 ; 3 dc.b 1 ; 4 dc.b 1 ; 5 dc.b $18 ; 6 dc.b 6 ; 7 dc.b $A ; 8 dc.b $10 ; 9 dc.b $20 ; 10 dc.b $10 ; 11 dc.b $A ; 12 dc.b 6 ; 13 dc.b $18 ; 14 dc.b 1 ; 15 dc.b 1 ; 16 dc.b 3 ; 17 dc.b 4 ; 18 dc.b $10 ; 19 dc.b 9 ; 20 dc.b $B ; 21 dc.b $13 ; 22 even ; =========================================================================== + moveq #0,d0 move.w (Camera_Y_pos_P2).w,d0 tst.b (Current_Act).w bne.s + divu.w #3,d0 subi.w #$140,d0 bra.s ++ ; =========================================================================== + divu.w #6,d0 subi.w #$10,d0 + move.w d0,(Camera_BG_Y_pos_P2).w move.w d0,(Vscroll_Factor_P2_BG).w subi.w #$E0,(Vscroll_Factor_P2_BG).w move.w (Camera_Y_pos_P2).w,(Vscroll_Factor_P2_FG).w subi.w #$E0,(Vscroll_Factor_P2_FG).w andi.l #$FFFEFFFE,(Vscroll_Factor_P2).w lea (TempArray_LayerDef).w,a2 lea $1E(a2),a3 move.w (Camera_X_pos_P2).w,d0 ext.l d0 asl.l #4,d0 divs.w #$A,d0 ext.l d0 asl.l #4,d0 asl.l #8,d0 move.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,$E(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,$C(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,$A(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,8(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,6(a2) move.w d1,$10(a2) move.w d1,$1C(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,4(a2) move.w d1,$12(a2) move.w d1,$1A(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,2(a2) move.w d1,$14(a2) move.w d1,$18(a2) swap d1 add.l d0,d1 swap d1 move.w d1,(a3)+ move.w d1,(a2) move.w d1,$16(a2) lea_ SwScrl_MCZ2P_RowHeights+1,a3 lea (TempArray_LayerDef).w,a2 lea (Horiz_Scroll_Buf+$1B0).w,a1 move.w (Camera_BG_Y_pos_P2).w,d1 lsr.w #1,d1 moveq #$17,d0 bra.s + ; =========================================================================== - move.b (a3)+,d0 + addq.w #2,a2 sub.w d0,d1 bcc.s - neg.w d1 subq.w #2,a2 move.w #bytesToLcnt($1D0),d2 move.w (Camera_X_pos_P2).w,d0 neg.w d0 swap d0 move.w (a2)+,d0 neg.w d0 - move.l d0,(a1)+ subq.w #1,d1 bne.s + move.b (a3)+,d1 move.w (a2)+,d0 neg.w d0 + dbf d2,- rts ; =========================================================================== ; loc_D0C6: SwScrl_CNZ: tst.w (Two_player_mode).w bne.w SwScrl_CNZ_2P move.w (Camera_Y_pos).w,d0 lsr.w #6,d0 move.w d0,(Camera_BG_Y_pos).w move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w move.w (Camera_X_pos).w,d2 bsr.w sub_D160 lea (SwScrl_CNZ_RowHeights).l,a3 lea (TempArray_LayerDef).w,a2 lea (Horiz_Scroll_Buf).w,a1 move.w (Camera_BG_Y_pos).w,d1 moveq #0,d0 - move.b (a3)+,d0 addq.w #2,a2 sub.w d0,d1 bcc.s - neg.w d1 subq.w #2,a2 move.w #bytesToLcnt($380),d2 move.w (Camera_X_pos).w,d0 neg.w d0 swap d0 move.w (a2)+,d0 neg.w d0 - move.l d0,(a1)+ subq.w #1,d1 bne.s + - move.w (a2)+,d0 neg.w d0 move.b (a3)+,d1 beq.s ++ + dbf d2,-- rts ; =========================================================================== + move.w #bytesToLcnt($40),d1 move.w d0,d3 move.b (Vint_runcount+3).w,d0 lsr.w #3,d0 neg.w d0 andi.w #$1F,d0 lea_ SwScrl_RippleData,a4 lea (a4,d0.w),a4 - move.b (a4)+,d0 ext.w d0 add.w d3,d0 move.l d0,(a1)+ dbf d1,- subi.w #$10,d2 bra.s -- ; =========================================================================== ; byte_D156: SwScrl_CNZ_RowHeights: dc.b $10 dc.b $10 ; 1 dc.b $10 ; 2 dc.b $10 ; 3 dc.b $10 ; 4 dc.b $10 ; 5 dc.b $10 ; 6 dc.b $10 ; 7 dc.b 0 ; 8 dc.b -$10 ; 9 even ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_D160: lea (TempArray_LayerDef).w,a1 move.w d2,d0 asr.w #3,d0 sub.w d2,d0 ext.l d0 asl.l #5,d0 asl.l #8,d0 moveq #0,d3 move.w d2,d3 move.w #6,d1 - move.w d3,(a1)+ swap d3 add.l d0,d3 swap d3 dbf d1,- move.w d2,d0 asr.w #3,d0 move.w d0,4(a1) asr.w #1,d0 move.w d0,(a1)+ move.w d0,(a1)+ rts ; End of function sub_D160 ; =========================================================================== ; loc_D194: SwScrl_CNZ_2P: move.w (Camera_Y_pos).w,d0 lsr.w #6,d0 move.w d0,(Camera_BG_Y_pos).w move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w andi.l #$FFFEFFFE,(Vscroll_Factor).w move.w (Camera_X_pos).w,d2 bsr.w sub_D160 lea (Horiz_Scroll_Buf).w,a1 move.w (Camera_BG_Y_pos).w,d1 moveq #0,d0 move.w (Camera_X_pos).w,d0 move.w #$6F,d2 lea (SwScrl_CNZ2P_RowHeights+2).l,a3 bsr.s sub_D216 move.w (Camera_Y_pos_P2).w,d0 lsr.w #6,d0 move.w d0,(Camera_BG_Y_pos_P2).w move.w d0,(Vscroll_Factor_P2_BG).w subi.w #$E0,(Vscroll_Factor_P2_BG).w move.w (Camera_Y_pos_P2).w,(Vscroll_Factor_P2_FG).w subi.w #$E0,(Vscroll_Factor_P2_FG).w andi.l #$FFFEFFFE,(Vscroll_Factor_P2).w move.w (Camera_X_pos_P2).w,d2 bsr.w sub_D160 lea (Horiz_Scroll_Buf+$1B0).w,a1 move.w (Camera_BG_Y_pos_P2).w,d1 moveq #0,d0 move.w (Camera_X_pos_P2).w,d0 move.w #bytesToLcnt($1D0),d2 lea (SwScrl_CNZ2P_RowHeights+1).l,a3 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_D216: lsr.w #1,d1 lea (TempArray_LayerDef).w,a2 moveq #0,d3 - move.b (a3)+,d3 addq.w #2,a2 sub.w d3,d1 bcc.s - neg.w d1 subq.w #2,a2 neg.w d0 swap d0 move.w (a2)+,d0 neg.w d0 - move.l d0,(a1)+ subq.w #1,d1 bne.s + - move.w (a2)+,d0 neg.w d0 move.b (a3)+,d1 beq.s ++ + dbf d2,-- rts ; =========================================================================== + move.w #bytesToLcnt($20),d1 move.w d0,d3 move.b (Vint_runcount+3).w,d0 lsr.w #3,d0 neg.w d0 andi.w #$1F,d0 lea_ SwScrl_RippleData,a4 lea (a4,d0.w),a4 - move.b (a4)+,d0 ext.w d0 add.w d3,d0 move.l d0,(a1)+ dbf d1,- subq.w #8,d2 bra.s -- ; End of function sub_D216 ; =========================================================================== ; byte_D270: SwScrl_CNZ2P_RowHeights: dc.b 4 dc.b 4 ; 1 dc.b 8 ; 2 dc.b 8 ; 3 dc.b 8 ; 4 dc.b 8 ; 5 dc.b 8 ; 6 dc.b 8 ; 7 dc.b 8 ; 8 dc.b 8 ; 9 dc.b 0 ; 10 dc.b $78 ; 11 even ; =========================================================================== ; loc_D27C: SwScrl_CPZ: move.w (Camera_X_pos_diff).w,d4 ext.l d4 asl.l #5,d4 move.w (Camera_Y_pos_diff).w,d5 ext.l d5 asl.l #6,d5 bsr.w SetHorizVertiScrollFlagsBG move.w (Camera_X_pos_diff).w,d4 ext.l d4 asl.l #7,d4 moveq #4,d6 bsr.w SetHorizScrollFlagsBG2 move.w (Camera_BG_Y_pos).w,d0 move.w d0,(Camera_BG2_Y_pos).w move.w d0,(Vscroll_Factor_BG).w move.b (Scroll_flags_BG).w,d0 or.b (Scroll_flags_BG2).w,d0 move.b d0,(Scroll_flags_BG3).w clr.b (Scroll_flags_BG).w clr.b (Scroll_flags_BG2).w move.b (Vint_runcount+3).w,d1 andi.w #7,d1 bne.s + subq.w #1,(TempArray_LayerDef).w + lea (CPZ_CameraSections+1).l,a0 move.w (Camera_BG_Y_pos).w,d0 move.w d0,d2 andi.w #$3F0,d0 lsr.w #4,d0 lea (a0,d0.w),a0 move.w d0,d4 lea (Horiz_Scroll_Buf).w,a1 move.w #$E,d1 move.w (Camera_X_pos).w,d0 neg.w d0 swap d0 andi.w #$F,d2 move.w (Camera_BG_X_pos).w,d0 cmpi.b #$12,d4 beq.s loc_D34A blo.s + move.w (Camera_BG2_X_pos).w,d0 + neg.w d0 add.w d2,d2 jmp ++(pc,d2.w) ; =========================================================================== - move.w (Camera_BG_X_pos).w,d0 cmpi.b #$12,d4 beq.s +++ blo.s + move.w (Camera_BG2_X_pos).w,d0 + neg.w d0 + rept 16 move.l d0,(a1)+ endm addq.b #1,d4 dbf d1,- rts ; =========================================================================== loc_D34A: move.w #bytesToLcnt($40),d0 sub.w d2,d0 move.w d0,d2 bra.s ++ ; =========================================================================== + move.w #$F,d2 + move.w (Camera_BG_X_pos).w,d3 neg.w d3 move.w (TempArray_LayerDef).w,d0 andi.w #$1F,d0 lea_ SwScrl_RippleData,a2 lea (a2,d0.w),a2 - move.b (a2)+,d0 ext.w d0 add.w d3,d0 move.l d0,(a1)+ dbf d2,- addq.b #1,d4 dbf d1,-- rts ; =========================================================================== ; loc_D382: SwScrl_DEZ: move.w (Camera_X_pos_diff).w,d4 ext.l d4 asl.l #8,d4 move.w (Camera_Y_pos_diff).w,d5 ext.l d5 asl.l #8,d5 bsr.w SetHorizVertiScrollFlagsBG move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w move.w (Camera_X_pos).w,d4 lea (TempArray_LayerDef).w,a2 move.w d4,(a2)+ addq.w #3,(a2)+ ; these random-seeming numbers control how fast each row of stars scrolls by addq.w #2,(a2)+ addq.w #4,(a2)+ addq.w #1,(a2)+ addq.w #2,(a2)+ addq.w #4,(a2)+ addq.w #3,(a2)+ addq.w #4,(a2)+ addq.w #2,(a2)+ addq.w #6,(a2)+ addq.w #3,(a2)+ addq.w #4,(a2)+ addq.w #1,(a2)+ addq.w #2,(a2)+ addq.w #4,(a2)+ addq.w #3,(a2)+ addq.w #2,(a2)+ addq.w #3,(a2)+ addq.w #4,(a2)+ addq.w #1,(a2)+ addq.w #3,(a2)+ addq.w #4,(a2)+ addq.w #2,(a2)+ addq.w #1,(a2) move.w (a2)+,d0 ; this is to make one row go at half speed (1 pixel every other frame) moveq #0,d1 move.w d0,d1 lsr.w #1,d0 move.w d0,(a2)+ addq.w #3,(a2)+ ; more star speeds... addq.w #2,(a2)+ addq.w #4,(a2)+ swap d1 move.l d1,d0 lsr.l #3,d1 sub.l d1,d0 swap d0 move.w d0,4(a2) swap d0 sub.l d1,d0 swap d0 move.w d0,2(a2) swap d0 sub.l d1,d0 swap d0 move.w d0,(a2)+ addq.w #4,a2 addq.w #1,(a2)+ move.w d4,(a2)+ move.w d4,(a2)+ move.w d4,(a2)+ lea (SwScrl_DEZ_RowHeights).l,a3 lea (TempArray_LayerDef).w,a2 lea (Horiz_Scroll_Buf).w,a1 move.w (Camera_BG_Y_pos).w,d1 moveq #0,d0 - move.b (a3)+,d0 addq.w #2,a2 sub.w d0,d1 bcc.s - neg.w d1 subq.w #2,a2 move.w #bytesToLcnt($380),d2 move.w (Camera_X_pos).w,d0 neg.w d0 swap d0 move.w (a2)+,d0 neg.w d0 - move.l d0,(a1)+ subq.w #1,d1 bne.s + move.b (a3)+,d1 move.w (a2)+,d0 neg.w d0 + dbf d2,- moveq #0,d2 tst.b (Screen_Shaking_Flag).w beq.s ++ ; rts subq.w #1,(DEZ_Shake_Timer).w bpl.s + clr.b (Screen_Shaking_Flag).w + move.w (Timer_frames).w,d0 andi.w #$3F,d0 lea_ SwScrl_RippleData,a1 lea (a1,d0.w),a1 moveq #0,d0 move.b (a1)+,d0 add.w d0,(Vscroll_Factor_FG).w add.w d0,(Vscroll_Factor_BG).w add.w d0,(Camera_Y_pos_copy).w move.b (a1)+,d2 add.w d2,(Camera_X_pos_copy).w + rts ; =========================================================================== ; byte_D48A: SwScrl_DEZ_RowHeights: dc.b $80 dc.b 8 ; 1 dc.b 8 ; 2 dc.b 8 ; 3 dc.b 8 ; 4 dc.b 8 ; 5 dc.b 8 ; 6 dc.b 8 ; 7 dc.b 8 ; 8 dc.b 8 ; 9 dc.b 8 ; 10 dc.b 8 ; 11 dc.b 8 ; 12 dc.b 8 ; 13 dc.b 8 ; 14 dc.b 8 ; 15 dc.b 8 ; 16 dc.b 8 ; 17 dc.b 8 ; 18 dc.b 8 ; 19 dc.b 8 ; 20 dc.b 8 ; 21 dc.b 8 ; 22 dc.b 8 ; 23 dc.b 8 ; 24 dc.b 8 ; 25 dc.b 8 ; 26 dc.b 8 ; 27 dc.b 8 ; 28 dc.b 3 ; 29 dc.b 5 ; 30 dc.b 8 ; 31 dc.b $10 ; 32 dc.b $80 ; 33 dc.b $80 ; 34 dc.b $80 ; 35 even ; =========================================================================== ; loc_D4AE: SwScrl_ARZ: move.w (Camera_X_pos_diff).w,d4 ext.l d4 muls.w #$119,d4 moveq #2,d6 bsr.w SetHorizScrollFlagsBG_ARZ move.w (Camera_Y_pos_diff).w,d5 ext.l d5 asl.l #7,d5 tst.b (Current_Act).w bne.s + asl.l #1,d5 + moveq #6,d6 bsr.w SetVertiScrollFlagsBG move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w moveq #0,d2 tst.b (Screen_Shaking_Flag).w beq.s .screenNotShaking move.w (Timer_frames).w,d0 andi.w #$3F,d0 lea_ SwScrl_RippleData,a1 lea (a1,d0.w),a1 moveq #0,d0 ; Shake camera Y-pos (note that BG scrolling is not affected by this, causing it to distort) move.b (a1)+,d0 add.w d0,(Vscroll_Factor_FG).w add.w d0,(Vscroll_Factor_BG).w add.w d0,(Camera_Y_pos_copy).w ; Shake camera X-pos move.b (a1)+,d2 add.w d2,(Camera_X_pos_copy).w .screenNotShaking: lea (TempArray_LayerDef).w,a2 ; Starts at BG scroll row 1 lea 6(a2),a3 ; Starts at BG scroll row 4 ; Set up the speed of each row (there are 16 rows in total) move.w (Camera_X_pos).w,d0 ext.l d0 asl.l #4,d0 divs.w #$A,d0 ext.l d0 asl.l #4,d0 asl.l #8,d0 move.l d0,d1 ; Set row 4's speed swap d1 move.w d1,(a3)+ ; Top row of background moves 10 ($A) times slower than foreground swap d1 add.l d1,d1 add.l d0,d1 ; Set rows 5-10's speed rept 6 swap d1 move.w d1,(a3)+ ; Next row moves 3 times faster than top row, then next row is 4 times faster, then 5, etc. swap d1 add.l d0,d1 endm ; Set row 11's speed swap d1 move.w d1,(a3)+ ; These instructions reveal that ARZ had slightly different scrolling, ; at one point: ; Above the background's mountains is a row of leaves, which is actually ; composed of three separately-scrolling rows. According to this code, ; the first and third rows were meant to scroll at a different speed to the ; second. Possibly due to how bad it looks, the speed values are overwritten ; a few instructions later, so all three move at the same speed. ; This code seems to pre-date the Simon Wai build, which uses the final's ; scrolling. move.w d1,(a2) ; Set row 1's speed move.w d1,4(a2) ; Set row 3's speed move.w (Camera_BG_X_pos).w,d0 move.w d0,2(a2) ; Set row 2's speed move.w d0,$16(a2) ; Set row 12's speed _move.w d0,0(a2) ; Overwrite row 1's speed (now same as row 2's) move.w d0,4(a2) ; Overwrite row 3's speed (now same as row 2's) move.w d0,$18(a2) ; Set row 13's speed move.w d0,$1A(a2) ; Set row 14's speed move.w d0,$1C(a2) ; Set row 15's speed move.w d0,$1E(a2) ; Set row 16's speed lea (SwScrl_ARZ_RowHeights).l,a3 lea (TempArray_LayerDef).w,a2 lea (Horiz_Scroll_Buf).w,a1 move.w (Camera_BG_Y_pos).w,d1 moveq #0,d0 ; Find which row of background is visible at the top of the screen .findTopRowLoop: move.b (a3)+,d0 ; Get row height addq.w #2,a2 ; Next row speed (note: is off by 2. This is fixed below) sub.w d0,d1 bcc.s .findTopRowLoop ; If current row is above the screen, loop and do next row neg.w d1 ; d1 now contains how many pixels of the row is currently on-screen subq.w #2,a2 ; Get correct row speed move.w #bytesToLcnt($380),d2 ; Actual size of Horiz_Scroll_Buf move.w (Camera_X_pos).w,d0 neg.w d0 swap d0 ; Store FG X-pos in upper 16-bits... move.w (a2)+,d0 ; ...and BG X-pos in lower 16 bits, as Horiz_Scroll_Buf expects it neg.w d0 - move.l d0,(a1)+ ; Write 1 FG Horizontal Scroll value, and 1 BG Horizontal Scroll value subq.w #1,d1 ; Loop until row at top of screen is done bne.s + move.b (a3)+,d1 ; Once that row is done, go to next row... move.w (a2)+,d0 ; ...and use next speed neg.w d0 + dbf d2,- ; Loop until Horiz_Scroll_Buf is full rts ; =========================================================================== ; byte_D5CE: SwScrl_ARZ_RowHeights: dc.b $B0 dc.b $70 ; 1 dc.b $30 ; 2 dc.b $60 ; 3 dc.b $15 ; 4 dc.b $C ; 5 dc.b $E ; 6 dc.b 6 ; 7 dc.b $C ; 8 dc.b $1F ; 9 dc.b $30 ; 10 dc.b $C0 ; 11 dc.b $F0 ; 12 dc.b $F0 ; 13 dc.b $F0 ; 14 dc.b $F0 ; 15 even ; =========================================================================== ; loc_D5DE: SwScrl_SCZ: tst.w (Debug_placement_mode).w bne.w SwScrl_Minimal lea (Camera_X_pos).w,a1 lea (Scroll_flags).w,a3 lea (Camera_X_pos_diff).w,a4 move.w (Tornado_Velocity_X).w,d0 move.w (a1),d4 add.w (a1),d0 move.w d0,d1 sub.w (a1),d1 asl.w #8,d1 move.w d0,(a1) move.w d1,(a4) lea (Horiz_block_crossed_flag).w,a2 bsr.w SetHorizScrollFlags lea (Camera_Y_pos).w,a1 lea (Camera_Y_pos_diff).w,a4 move.w (Tornado_Velocity_Y).w,d0 move.w (a1),d4 add.w (a1),d0 move.w d0,d1 sub.w (a1),d1 asl.w #8,d1 move.w d0,(a1) move.w d1,(a4) lea (Verti_block_crossed_flag).w,a2 bsr.w SetVertiScrollFlags move.w (Camera_X_pos_diff).w,d4 beq.s + move.w #$100,d4 + ext.l d4 asl.l #7,d4 moveq #0,d5 bsr.w SetHorizVertiScrollFlagsBG move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w lea (Horiz_Scroll_Buf).w,a1 move.w #bytesToLcnt($380),d1 move.w (Camera_X_pos).w,d0 neg.w d0 swap d0 move.w (Camera_BG_X_pos).w,d0 neg.w d0 - move.l d0,(a1)+ dbf d1,- rts ; =========================================================================== ; loc_D666: SwScrl_Minimal: move.w (Camera_X_pos_diff).w,d4 ext.l d4 asl.l #5,d4 move.w (Camera_Y_pos_diff).w,d5 ext.l d5 asl.l #6,d5 bsr.w SetHorizVertiScrollFlagsBG move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w lea (Horiz_Scroll_Buf).w,a1 move.w #bytesToLcnt($380),d1 move.w (Camera_X_pos).w,d0 neg.w d0 swap d0 move.w (Camera_BG_X_pos).w,d0 neg.w d0 - move.l d0,(a1)+ dbf d1,- rts ; =========================================================================== ; unused... ; loc_D69E: SwScrl_HPZ_Continued: lea (Horiz_Scroll_Buf).w,a1 move.w #$E,d1 move.w (Camera_X_pos).w,d0 neg.w d0 swap d0 andi.w #$F,d2 add.w d2,d2 move.w (a2)+,d0 jmp +(pc,d2.w) ; =========================================================================== - move.w (a2)+,d0 + rept 16 move.l d0,(a1)+ endm dbf d1,- rts ; --------------------------------------------------------------------------- ; Subroutine to set horizontal scroll flags ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_D6E2: SetHorizScrollFlags: move.w (a1),d0 ; get camera X pos andi.w #$10,d0 move.b (a2),d1 eor.b d1,d0 ; has the camera crossed a 16-pixel boundary? bne.s ++ ; if not, branch eori.b #$10,(a2) move.w (a1),d0 ; get camera X pos sub.w d4,d0 ; subtract previous camera X pos bpl.s + ; branch if the camera has moved forward bset #2,(a3) ; set moving back in level bit rts ; =========================================================================== + bset #3,(a3) ; set moving forward in level bit + rts ; End of function SetHorizScrollFlags ; --------------------------------------------------------------------------- ; Subroutine to scroll the camera horizontally ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_D704: ScrollHoriz: move.w (a1),d4 ; get camera X pos tst.b (Teleport_flag).w bne.s .return ; if a teleport is in progress, return move.w (a5),d1 ; should scrolling be delayed? beq.s .scrollNotDelayed ; if not, branch subi.w #$100,d1 ; reduce delay value move.w d1,(a5) moveq #0,d1 move.b (a5),d1 ; get delay value lsl.b #2,d1 ; multiply by 4, the size of a position buffer entry addq.b #4,d1 move.w 2(a5),d0 ; get current position buffer index sub.b d1,d0 move.w (a6,d0.w),d0 ; get Sonic's position a certain number of frames ago andi.w #$3FFF,d0 bra.s .checkIfShouldScroll ; use that value for scrolling ; =========================================================================== ; loc_D72E: .scrollNotDelayed: move.w x_pos(a0),d0 ; loc_D732: .checkIfShouldScroll: sub.w (a1),d0 subi.w #(320/2)-16,d0 ; is the player less than 144 pixels from the screen edge? blt.s .scrollLeft ; if he is, scroll left subi.w #16,d0 ; is the player more than 159 pixels from the screen edge? bge.s .scrollRight ; if he is, scroll right clr.w (a4) ; otherwise, don't scroll ; return_D742: .return: rts ; =========================================================================== ; loc_D744: .scrollLeft: cmpi.w #-16,d0 bgt.s .maxNotReached move.w #-16,d0 ; limit scrolling to 16 pixels per frame ; loc_D74E: .maxNotReached: add.w (a1),d0 ; get new camera position cmp.w (a2),d0 ; is it greater than the minimum position? bgt.s .doScroll ; if it is, branch move.w (a2),d0 ; prevent camera from going any further back bra.s .doScroll ; =========================================================================== ; loc_D758: .scrollRight: cmpi.w #16,d0 blo.s .maxNotReached2 move.w #16,d0 ; loc_D762: .maxNotReached2: add.w (a1),d0 ; get new camera position cmp.w Camera_Max_X_pos-Camera_Min_X_pos(a2),d0 ; is it less than the max position? blt.s .doScroll ; if it is, branch move.w Camera_Max_X_pos-Camera_Min_X_pos(a2),d0 ; prevent camera from going any further forward ; loc_D76E: .doScroll: move.w d0,d1 sub.w (a1),d1 ; subtract old camera position asl.w #8,d1 ; shift up by a byte move.w d0,(a1) ; set new camera position move.w d1,(a4) ; set difference between old and new positions rts ; End of function ScrollHoriz ; --------------------------------------------------------------------------- ; Subroutine to scroll the camera vertically ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; The upper 16 bits of Camera_Y_pos is the actual Y-pos, the lower ones seem ; unused, yet this code goes to a strange extent to manage them. ;sub_D77A: ScrollVerti: moveq #0,d1 move.w y_pos(a0),d0 sub.w (a1),d0 ; subtract camera Y pos cmpi.w #-$100,(Camera_Min_Y_pos).w ; does the level wrap vertically? bne.s .noWrap ; if not, branch andi.w #$7FF,d0 ; loc_D78E: .noWrap: btst #2,status(a0) ; is the player rolling? beq.s .notRolling ; if not, branch subq.w #5,d0 ; subtract difference between standing and rolling heights ; loc_D798: .notRolling: btst #1,status(a0) ; is the player in the air? beq.s .checkBoundaryCrossed_onGround ; if not, branch ;.checkBoundaryCrossed_inAir: ; If Sonic's in the air, he has $20 pixels above and below him to move without disturbing the camera. ; The camera movement is also only capped at $10 pixels. addi.w #$20,d0 sub.w d3,d0 bcs.s .doScroll_fast ; If Sonic is above the boundary, scroll to catch up to him subi.w #$40,d0 bcc.s .doScroll_fast ; If Sonic is below the boundary, scroll to catch up to him tst.b (Camera_Max_Y_Pos_Changing).w ; is the max Y pos changing? bne.s .scrollUpOrDown_maxYPosChanging ; if it is, branch bra.s .doNotScroll ; =========================================================================== ; loc_D7B6: .checkBoundaryCrossed_onGround: ; On the ground, the camera follows Sonic very strictly. sub.w d3,d0 ; subtract camera bias bne.s .decideScrollType ; If Sonic has moved, scroll to catch up to him tst.b (Camera_Max_Y_Pos_Changing).w ; is the max Y pos changing? bne.s .scrollUpOrDown_maxYPosChanging ; if it is, branch ; loc_D7C0: .doNotScroll: clr.w (a4) ; clear Y position difference (Camera_Y_pos_bias) rts ; =========================================================================== ; loc_D7C4: .decideScrollType: cmpi.w #(224/2)-16,d3 ; is the camera bias normal? bne.s .doScroll_slow ; if not, branch mvabs.w inertia(a0),d1 ; get player ground velocity, force it to be positive cmpi.w #$800,d1 ; is the player travelling very fast? bhs.s .doScroll_fast ; if he is, branch ;.doScroll_medium: move.w #6<<8,d1 ; If player is going too fast, cap camera movement to 6 pixels per frame cmpi.w #6,d0 ; is player going down too fast? bgt.s .scrollDown_max ; if so, move camera at capped speed cmpi.w #-6,d0 ; is player going up too fast? blt.s .scrollUp_max ; if so, move camera at capped speed bra.s .scrollUpOrDown ; otherwise, move camera at player's speed ; =========================================================================== ; loc_D7EA: .doScroll_slow: move.w #2<<8,d1 ; If player is going too fast, cap camera movement to 2 pixels per frame cmpi.w #2,d0 ; is player going down too fast? bgt.s .scrollDown_max ; if so, move camera at capped speed cmpi.w #-2,d0 ; is player going up too fast? blt.s .scrollUp_max ; if so, move camera at capped speed bra.s .scrollUpOrDown ; otherwise, move camera at player's speed ; =========================================================================== ; loc_D7FC: .doScroll_fast: ; related code appears in ScrollBG ; S3K uses 24 instead of 16 move.w #16<<8,d1 ; If player is going too fast, cap camera movement to $10 pixels per frame cmpi.w #16,d0 ; is player going down too fast? bgt.s .scrollDown_max ; if so, move camera at capped speed cmpi.w #-16,d0 ; is player going up too fast? blt.s .scrollUp_max ; if so, move camera at capped speed bra.s .scrollUpOrDown ; otherwise, move camera at player's speed ; =========================================================================== ; loc_D80E: .scrollUpOrDown_maxYPosChanging: moveq #0,d0 ; Distance for camera to move = 0 move.b d0,(Camera_Max_Y_Pos_Changing).w ; clear camera max Y pos changing flag ; loc_D814: .scrollUpOrDown: moveq #0,d1 move.w d0,d1 ; get position difference add.w (a1),d1 ; add old camera Y position tst.w d0 ; is the camera to scroll down? bpl.w .scrollDown ; if it is, branch bra.w .scrollUp ; =========================================================================== ; loc_D824: .scrollUp_max: neg.w d1 ; make the value negative (since we're going backwards) ext.l d1 asl.l #8,d1 ; move this into the upper word, so it lines up with the actual y_pos value in Camera_Y_pos add.l (a1),d1 ; add the two, getting the new Camera_Y_pos value swap d1 ; actual Y-coordinate is now the low word ; loc_D82E: .scrollUp: cmp.w Camera_Min_Y_pos-Camera_Min_X_pos(a2),d1 ; is the new position less than the minimum Y pos? bgt.s .doScroll ; if not, branch cmpi.w #-$100,d1 bgt.s .minYPosReached andi.w #$7FF,d1 andi.w #$7FF,(a1) bra.s .doScroll ; =========================================================================== ; loc_D844: .minYPosReached: move.w Camera_Min_Y_pos-Camera_Min_X_pos(a2),d1 ; prevent camera from going any further up bra.s .doScroll ; =========================================================================== ; loc_D84A: .scrollDown_max: ext.l d1 asl.l #8,d1 ; move this into the upper word, so it lines up with the actual y_pos value in Camera_Y_pos add.l (a1),d1 ; add the two, getting the new Camera_Y_pos value swap d1 ; actual Y-coordinate is now the low word ; loc_D852: .scrollDown: cmp.w Camera_Max_Y_pos_now-Camera_Min_X_pos(a2),d1 ; is the new position greater than the maximum Y pos? blt.s .doScroll ; if not, branch subi.w #$800,d1 bcs.s .maxYPosReached subi.w #$800,(a1) bra.s .doScroll ; =========================================================================== ; loc_D864: .maxYPosReached: move.w Camera_Max_Y_pos_now-Camera_Min_X_pos(a2),d1 ; prevent camera from going any further down ; loc_D868: .doScroll: move.w (a1),d4 ; get old pos (used by SetVertiScrollFlags) swap d1 ; actual Y-coordinate is now the high word, as Camera_Y_pos expects it move.l d1,d3 sub.l (a1),d3 ror.l #8,d3 move.w d3,(a4) ; set difference between old and new positions move.l d1,(a1) ; set new camera Y pos rts ; End of function ScrollVerti ; --------------------------------------------------------------------------- ; Subroutine to set vertical scroll flags ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| SetVertiScrollFlags: move.w (a1),d0 ; get camera Y pos andi.w #$10,d0 move.b (a2),d1 eor.b d1,d0 ; has the camera crossed a 16-pixel boundary? bne.s ++ ; if not, branch eori.b #$10,(a2) move.w (a1),d0 ; get camera Y pos sub.w d4,d0 ; subtract old camera Y pos bpl.s + ; branch if the camera has scrolled down bset #0,(a3) ; set moving up in level bit rts ; =========================================================================== + bset #1,(a3) ; set moving down in level bit + rts ; End of function SetVertiScrollFlags ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; d4 is horizontal, d5 vertical, derived from $FFFFEEB0 & $FFFFEEB2 respectively ;sub_D89A: ;Hztl_Vrtc_Bg_Deformation: SetHorizVertiScrollFlagsBG: ; used by lev2, MTZ, HTZ, CPZ, DEZ, SCZ, Minimal move.l (Camera_BG_X_pos).w,d2 move.l d2,d0 add.l d4,d0 ; add x-shift for this frame move.l d0,(Camera_BG_X_pos).w move.l d0,d1 swap d1 andi.w #$10,d1 move.b (Horiz_block_crossed_flag_BG).w,d3 eor.b d3,d1 bne.s ++ eori.b #$10,(Horiz_block_crossed_flag_BG).w sub.l d2,d0 bpl.s + bset #2,(Scroll_flags_BG).w bra.s ++ ; =========================================================================== + bset #3,(Scroll_flags_BG).w + move.l (Camera_BG_Y_pos).w,d3 move.l d3,d0 add.l d5,d0 ; add y-shift for this frame move.l d0,(Camera_BG_Y_pos).w move.l d0,d1 swap d1 andi.w #$10,d1 move.b (Verti_block_crossed_flag_BG).w,d2 eor.b d2,d1 bne.s ++ ; rts eori.b #$10,(Verti_block_crossed_flag_BG).w sub.l d3,d0 bpl.s + bset #0,(Scroll_flags_BG).w rts ; =========================================================================== + bset #1,(Scroll_flags_BG).w + rts ; End of function SetHorizVertiScrollFlagsBG ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_D904: ;Horizontal_Bg_Deformation: SetHorizScrollFlagsBG: ; used by WFZ, HTZ, HPZ move.l (Camera_BG_X_pos).w,d2 move.l d2,d0 add.l d4,d0 ; add x-shift for this frame move.l d0,(Camera_BG_X_pos).w move.l d0,d1 swap d1 andi.w #$10,d1 move.b (Horiz_block_crossed_flag_BG).w,d3 eor.b d3,d1 bne.s ++ ; rts eori.b #$10,(Horiz_block_crossed_flag_BG).w sub.l d2,d0 bpl.s + bset d6,(Scroll_flags_BG).w bra.s ++ ; rts ; =========================================================================== + addq.b #1,d6 bset d6,(Scroll_flags_BG).w + rts ; End of function SetHorizScrollFlagsBG ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_D938: ;Vertical_Bg_Deformation1: SetVertiScrollFlagsBG: ; used by WFZ, HTZ, HPZ, ARZ move.l (Camera_BG_Y_pos).w,d3 move.l d3,d0 add.l d5,d0 ; add y-shift for this frame ;loc_D940: ;Vertical_Bg_Deformation2: SetVertiScrollFlagsBG2: move.l d0,(Camera_BG_Y_pos).w move.l d0,d1 swap d1 andi.w #$10,d1 move.b (Verti_block_crossed_flag_BG).w,d2 eor.b d2,d1 bne.s ++ ; rts eori.b #$10,(Verti_block_crossed_flag_BG).w sub.l d3,d0 bpl.s + bset d6,(Scroll_flags_BG).w ; everytime Verti_block_crossed_flag_BG changes from $10 to $00 rts ; =========================================================================== + addq.b #1,d6 bset d6,(Scroll_flags_BG).w ; everytime Verti_block_crossed_flag_BG changes from $00 to $10 + rts ; End of function SetVertiScrollFlagsBG ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_D96C: ;ARZ_Bg_Deformation: SetHorizScrollFlagsBG_ARZ: ; only used by ARZ move.l (Camera_ARZ_BG_X_pos).w,d0 add.l d4,d0 move.l d0,(Camera_ARZ_BG_X_pos).w lea (Camera_BG_X_pos).w,a1 move.w (a1),d2 move.w (Camera_ARZ_BG_X_pos).w,d0 sub.w d2,d0 bcs.s + bhi.s ++ rts ; =========================================================================== + cmpi.w #-$10,d0 bgt.s ++ move.w #-$10,d0 bra.s ++ ; =========================================================================== + cmpi.w #$10,d0 blo.s + move.w #$10,d0 + add.w (a1),d0 move.w d0,(a1) move.w d0,d1 andi.w #$10,d1 move.b (Horiz_block_crossed_flag_BG).w,d3 eor.b d3,d1 bne.s ++ ; rts eori.b #$10,(Horiz_block_crossed_flag_BG).w sub.w d2,d0 bpl.s + bset d6,(Scroll_flags_BG).w bra.s ++ ; rts ; =========================================================================== + addq.b #1,d6 bset d6,(Scroll_flags_BG).w + rts ; End of function SetHorizScrollFlagsBG_ARZ ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_D9C8: ;CPZ_Bg_Deformation: SetHorizScrollFlagsBG2: ; only used by CPZ move.l (Camera_BG2_X_pos).w,d2 move.l d2,d0 add.l d4,d0 move.l d0,(Camera_BG2_X_pos).w move.l d0,d1 swap d1 andi.w #$10,d1 move.b (Horiz_block_crossed_flag_BG2).w,d3 eor.b d3,d1 bne.s ++ ; rts eori.b #$10,(Horiz_block_crossed_flag_BG2).w sub.l d2,d0 bpl.s + bset d6,(Scroll_flags_BG2).w bra.s ++ ; rts ; =========================================================================== + addq.b #1,d6 bset d6,(Scroll_flags_BG2).w + rts ; End of function SetHorizScrollFlagsBG2 ; =========================================================================== ; some apparently unused code ;SetHorizScrollFlagsBG3: move.l (Camera_BG3_X_pos).w,d2 move.l d2,d0 add.l d4,d0 move.l d0,(Camera_BG3_X_pos).w move.l d0,d1 swap d1 andi.w #$10,d1 move.b (Horiz_block_crossed_flag_BG3).w,d3 eor.b d3,d1 bne.s ++ ; rts eori.b #$10,(Horiz_block_crossed_flag_BG3).w sub.l d2,d0 bpl.s + bset d6,(Scroll_flags_BG3).w bra.s ++ ; rts ; =========================================================================== + addq.b #1,d6 bset d6,(Scroll_flags_BG3).w + rts ; =========================================================================== ; Unused - dead code leftover from S1: lea (VDP_control_port).l,a5 lea (VDP_data_port).l,a6 lea (Scroll_flags_BG).w,a2 lea (Camera_BG_X_pos).w,a3 lea (Level_Layout+$80).w,a4 move.w #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE)>>16,d2 bsr.w Draw_BG1 lea (Scroll_flags_BG2).w,a2 lea (Camera_BG2_X_pos).w,a3 bra.w Draw_BG2 ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to display correct tiles as you move ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_DA5C: LoadTilesAsYouMove: lea (VDP_control_port).l,a5 lea (VDP_data_port).l,a6 lea (Scroll_flags_BG_copy).w,a2 lea (Camera_BG_copy).w,a3 lea (Level_Layout+$80).w,a4 ; first background line move.w #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE)>>16,d2 bsr.w Draw_BG1 lea (Scroll_flags_BG2_copy).w,a2 ; referred to in CPZ deformation routine, but cleared right after lea (Camera_BG2_copy).w,a3 bsr.w Draw_BG2 ; Essentially unused, though lea (Scroll_flags_BG3_copy).w,a2 lea (Camera_BG3_copy).w,a3 bsr.w Draw_BG3 ; used in CPZ deformation routine tst.w (Two_player_mode).w beq.s + lea (Scroll_flags_copy_P2).w,a2 lea (Camera_P2_copy).w,a3 ; second player camera lea (Level_Layout).w,a4 move.w #vdpComm(VRAM_Plane_A_Name_Table_2P,VRAM,WRITE)>>16,d2 bsr.w Draw_FG_P2 + lea (Scroll_flags_copy).w,a2 lea (Camera_RAM_copy).w,a3 lea (Level_Layout).w,a4 move.w #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE)>>16,d2 tst.b (Screen_redraw_flag).w ; comment out this line to disable blast processing beq.s Draw_FG move.b #0,(Screen_redraw_flag).w moveq #-$10,d4 moveq #$F,d6 ; loc_DACE: Draw_All: movem.l d4-d6,-(sp) ; This whole routine basically redraws the whole moveq #-$10,d5 ; area instead of merely a line of tiles move.w d4,d1 bsr.w CalcBlockVRAMPos move.w d1,d4 moveq #-$10,d5 bsr.w DrawBlockRow1 ; draw the current row movem.l (sp)+,d4-d6 addi.w #$10,d4 ; move onto the next row dbf d6,Draw_All ; repeat for all rows move.b #0,(Scroll_flags_copy).w rts ; =========================================================================== ; loc_DAF6: Draw_FG: tst.b (a2) ; is any scroll flag set? beq.s return_DB5A ; if not, branch bclr #0,(a2) ; has the level scrolled up? beq.s + ; if not, branch moveq #-$10,d4 moveq #-$10,d5 bsr.w CalcBlockVRAMPos moveq #-$10,d4 moveq #-$10,d5 bsr.w DrawBlockRow1 ; redraw upper row + bclr #1,(a2) ; has the level scrolled down? beq.s + ; if not, branch move.w #224,d4 moveq #-$10,d5 bsr.w CalcBlockVRAMPos move.w #224,d4 moveq #-$10,d5 bsr.w DrawBlockRow1 ; redraw bottom row + bclr #2,(a2) ; has the level scrolled to the left? beq.s + ; if not, branch moveq #-$10,d4 moveq #-$10,d5 bsr.w CalcBlockVRAMPos moveq #-$10,d4 moveq #-$10,d5 bsr.w DrawBlockCol1 ; redraw left-most column + bclr #3,(a2) ; has the level scrolled to the right? beq.s return_DB5A ; if not, return moveq #-$10,d4 move.w #320,d5 bsr.w CalcBlockVRAMPos moveq #-$10,d4 move.w #320,d5 bsr.w DrawBlockCol1 ; redraw right-most column return_DB5A: rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_DB5C: Draw_FG_P2: tst.b (a2) beq.s return_DBC0 bclr #0,(a2) beq.s + moveq #-$10,d4 moveq #-$10,d5 bsr.w CalcBlockVRAMPosB moveq #-$10,d4 moveq #-$10,d5 bsr.w DrawBlockRow1 + bclr #1,(a2) beq.s + move.w #$E0,d4 moveq #-$10,d5 bsr.w CalcBlockVRAMPosB move.w #$E0,d4 moveq #-$10,d5 bsr.w DrawBlockRow1 + bclr #2,(a2) beq.s + moveq #-$10,d4 moveq #-$10,d5 bsr.w CalcBlockVRAMPosB moveq #-$10,d4 moveq #-$10,d5 bsr.w DrawBlockCol1 + bclr #3,(a2) beq.s return_DBC0 moveq #-$10,d4 move.w #320,d5 bsr.w CalcBlockVRAMPosB moveq #-$10,d4 move.w #320,d5 bsr.w DrawBlockCol1 return_DBC0: rts ; End of function Draw_FG_P2 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_DBC2: Draw_BG1: tst.b (a2) beq.w return_DC90 bclr #0,(a2) beq.s + moveq #-$10,d4 moveq #-$10,d5 bsr.w CalcBlockVRAMPos moveq #-$10,d4 moveq #-$10,d5 bsr.w DrawBlockRow1 + bclr #1,(a2) beq.s + move.w #$E0,d4 moveq #-$10,d5 bsr.w CalcBlockVRAMPos move.w #$E0,d4 moveq #-$10,d5 bsr.w DrawBlockRow1 + bclr #2,(a2) beq.s + moveq #-$10,d4 moveq #-$10,d5 bsr.w CalcBlockVRAMPos moveq #-$10,d4 moveq #-$10,d5 bsr.w DrawBlockCol1 + bclr #3,(a2) beq.s + moveq #-$10,d4 move.w #320,d5 bsr.w CalcBlockVRAMPos moveq #-$10,d4 move.w #320,d5 bsr.w DrawBlockCol1 + bclr #4,(a2) beq.s + moveq #-$10,d4 moveq #0,d5 bsr.w CalcBlockVRAMPos2 moveq #-$10,d4 moveq #0,d5 moveq #$1F,d6 bsr.w DrawBlockRow2 + bclr #5,(a2) beq.s + move.w #$E0,d4 moveq #0,d5 bsr.w CalcBlockVRAMPos2 move.w #$E0,d4 moveq #0,d5 moveq #$1F,d6 bsr.w DrawBlockRow2 + bclr #6,(a2) beq.s + moveq #-$10,d4 moveq #-$10,d5 bsr.w CalcBlockVRAMPos moveq #-$10,d4 moveq #-$10,d5 moveq #$1F,d6 bsr.w DrawBlockRow + bclr #7,(a2) beq.s return_DC90 move.w #$E0,d4 moveq #-$10,d5 bsr.w CalcBlockVRAMPos move.w #$E0,d4 moveq #-$10,d5 moveq #$1F,d6 bsr.w DrawBlockRow return_DC90: rts ; End of function Draw_BG1 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_DC92: Draw_BG2: tst.b (a2) beq.w ++ ; rts bclr #0,(a2) beq.s + move.w #$70,d4 moveq #-$10,d5 bsr.w CalcBlockVRAMPos move.w #$70,d4 moveq #-$10,d5 moveq #2,d6 bsr.w DrawBlockCol2 + bclr #1,(a2) beq.s + ; rts move.w #$70,d4 move.w #320,d5 bsr.w CalcBlockVRAMPos move.w #$70,d4 move.w #320,d5 moveq #2,d6 bsr.w DrawBlockCol2 + rts ; End of function Draw_BG2 ; =========================================================================== ; Scrap Brain Zone 1 block positioning array -- S1 left-over ; Each entry is an index into BGCameraLookup; used to decide the camera to use ; for given block for reloading BG. A entry of 0 means assume X = 0 for section, ; but otherwise loads camera Y for selected camera. ;byte_DCD6 SBZ_CameraSections: dc.b 0 dc.b 0 ; 1 dc.b 0 ; 2 dc.b 0 ; 3 dc.b 0 ; 4 dc.b 6 ; 5 dc.b 6 ; 6 dc.b 6 ; 7 dc.b 6 ; 8 dc.b 6 ; 9 dc.b 6 ; 10 dc.b 6 ; 11 dc.b 6 ; 12 dc.b 6 ; 13 dc.b 6 ; 14 dc.b 4 ; 15 dc.b 4 ; 16 dc.b 4 ; 17 dc.b 4 ; 18 dc.b 4 ; 19 dc.b 4 ; 20 dc.b 4 ; 21 dc.b 2 ; 22 dc.b 2 ; 23 dc.b 2 ; 24 dc.b 2 ; 25 dc.b 2 ; 26 dc.b 2 ; 27 dc.b 2 ; 28 dc.b 2 ; 29 dc.b 2 ; 30 dc.b 2 ; 31 dc.b 2 ; 32 even ; =========================================================================== ; Scrap Brain Zone 1 drawing code -- S1 left-over ; Compare with CPZ drawing code ; begin unused routine moveq #-$10,d4 bclr #0,(a2) bne.s + bclr #1,(a2) beq.s +++ move.w #$E0,d4 + lea_ SBZ_CameraSections+1,a0 move.w (Camera_BG_Y_pos).w,d0 add.w d4,d0 andi.w #$1F0,d0 lsr.w #4,d0 move.b (a0,d0.w),d0 lea (BGCameraLookup).l,a3 movea.w (a3,d0.w),a3 ; Camera, either BG, BG2 or BG3 depending on Y beq.s + moveq #-$10,d5 movem.l d4-d5,-(sp) bsr.w CalcBlockVRAMPos movem.l (sp)+,d4-d5 bsr.w DrawBlockRow1 bra.s ++ ; =========================================================================== + moveq #0,d5 movem.l d4-d5,-(sp) bsr.w CalcBlockVRAMPos2 movem.l (sp)+,d4-d5 moveq #$1F,d6 bsr.w DrawBlockRow2 + tst.b (a2) bne.s + rts ; =========================================================================== + moveq #-$10,d4 moveq #-$10,d5 move.b (a2),d0 andi.b #-$58,d0 beq.s + lsr.b #1,d0 move.b d0,(a2) move.w #320,d5 + lea_ SBZ_CameraSections,a0 move.w (Camera_BG_Y_pos).w,d0 andi.w #$1F0,d0 lsr.w #4,d0 lea (a0,d0.w),a0 bra.w loc_DE86 ; end unused routine ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_DD82: Draw_BG3: tst.b (a2) beq.w ++ ; rts cmpi.b #chemical_plant_zone,(Current_Zone).w beq.w Draw_BG3_CPZ ; S1 left-over: GHZ used this bclr #0,(a2) beq.s + move.w #$40,d4 moveq #-$10,d5 bsr.w CalcBlockVRAMPos move.w #$40,d4 moveq #-$10,d5 moveq #2,d6 bsr.w DrawBlockCol2 + bclr #1,(a2) beq.s + ; rts move.w #$40,d4 move.w #320,d5 bsr.w CalcBlockVRAMPos move.w #$40,d4 move.w #320,d5 moveq #2,d6 bsr.w DrawBlockCol2 + rts ; =========================================================================== ; Chemical Plant Zone 1 block positioning array ; Each entry is an index into BGCameraLookup; used to decide the camera to use ; for given block for reloading BG. A entry of 0 means assume X = 0 for section, ; but otherwise loads camera Y for selected camera. ;byte_DDD0 CPZ_CameraSections: dc.b 2 dc.b 2 ; 1 dc.b 2 ; 2 dc.b 2 ; 3 dc.b 2 ; 4 dc.b 2 ; 5 dc.b 2 ; 6 dc.b 2 ; 7 dc.b 2 ; 8 dc.b 2 ; 9 dc.b 2 ; 10 dc.b 2 ; 11 dc.b 2 ; 12 dc.b 2 ; 13 dc.b 2 ; 14 dc.b 2 ; 15 dc.b 2 ; 16 dc.b 2 ; 17 dc.b 2 ; 18 dc.b 2 ; 19 dc.b 4 ; 20 dc.b 4 ; 21 dc.b 4 ; 22 dc.b 4 ; 23 dc.b 4 ; 24 dc.b 4 ; 25 dc.b 4 ; 26 dc.b 4 ; 27 dc.b 4 ; 28 dc.b 4 ; 29 dc.b 4 ; 30 dc.b 4 ; 31 dc.b 4 ; 32 dc.b 4 ; 33 dc.b 4 ; 34 dc.b 4 ; 35 dc.b 4 ; 36 dc.b 4 ; 37 dc.b 4 ; 38 dc.b 4 ; 39 dc.b 4 ; 40 dc.b 4 ; 41 dc.b 4 ; 42 dc.b 4 ; 43 dc.b 4 ; 44 dc.b 4 ; 45 dc.b 4 ; 46 dc.b 4 ; 47 dc.b 4 ; 48 dc.b 4 ; 49 dc.b 4 ; 50 dc.b 4 ; 51 dc.b 4 ; 52 dc.b 4 ; 53 dc.b 4 ; 54 dc.b 4 ; 55 dc.b 4 ; 56 dc.b 4 ; 57 dc.b 4 ; 58 dc.b 4 ; 59 dc.b 4 ; 60 dc.b 4 ; 61 dc.b 4 ; 62 dc.b 4 ; 63 dc.b 4 ; 64 even ; =========================================================================== ; loc_DE12: Draw_BG3_CPZ: moveq #-$10,d4 ; bit0 = top row bclr #0,(a2) bne.s + bclr #1,(a2) beq.s ++ move.w #$E0,d4 ; bit1 = bottom row + lea_ CPZ_CameraSections+1,a0 move.w (Camera_BG_Y_pos).w,d0 add.w d4,d0 andi.w #$3F0,d0 lsr.w #4,d0 move.b (a0,d0.w),d0 movea.w BGCameraLookup(pc,d0.w),a3 ; Camera, either BG, BG2 or BG3 depending on Y moveq #-$10,d5 movem.l d4-d5,-(sp) bsr.w CalcBlockVRAMPos movem.l (sp)+,d4-d5 bsr.w DrawBlockRow1 + tst.b (a2) bne.s + rts ; =========================================================================== + moveq #-$10,d4 moveq #-$10,d5 move.b (a2),d0 andi.b #-$58,d0 beq.s + lsr.b #1,d0 move.b d0,(a2) move.w #320,d5 + lea_ CPZ_CameraSections,a0 move.w (Camera_BG_Y_pos).w,d0 andi.w #$7F0,d0 lsr.w #4,d0 lea (a0,d0.w),a0 bra.w loc_DE86 ; =========================================================================== ;word_DE7E BGCameraLookup: dc.w Camera_BG_copy ; BG Camera dc.w Camera_BG_copy ; BG Camera dc.w Camera_BG2_copy ; BG2 Camera dc.w Camera_BG3_copy ; BG3 Camera ; =========================================================================== loc_DE86: tst.w (Two_player_mode).w bne.s ++ moveq #$F,d6 move.l #vdpCommDelta($0080),d7 - moveq #0,d0 move.b (a0)+,d0 btst d0,(a2) beq.s + movea.w BGCameraLookup(pc,d0.w),a3 ; Camera, either BG, BG2 or BG3 depending on Y movem.l d4-d5/a0,-(sp) movem.l d4-d5,-(sp) bsr.w GetBlockPtr movem.l (sp)+,d4-d5 bsr.w CalcBlockVRAMPos bsr.w ProcessAndWriteBlock2 movem.l (sp)+,d4-d5/a0 + addi.w #$10,d4 dbf d6,- clr.b (a2) rts ; =========================================================================== + moveq #$F,d6 move.l #vdpCommDelta($0080),d7 - moveq #0,d0 move.b (a0)+,d0 btst d0,(a2) beq.s + movea.w BGCameraLookup(pc,d0.w),a3 ; Camera, either BG, BG2 or BG3 depending on Y movem.l d4-d5/a0,-(sp) movem.l d4-d5,-(sp) bsr.w GetBlockPtr movem.l (sp)+,d4-d5 bsr.w CalcBlockVRAMPos bsr.w ProcessAndWriteBlock2_2P movem.l (sp)+,d4-d5/a0 + addi.w #$10,d4 dbf d6,- clr.b (a2) rts ; End of function Draw_BG3 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_DF04: DrawBlockCol1: moveq #$F,d6 DrawBlockCol2: add.w (a3),d5 ; add camera X pos add.w 4(a3),d4 ; add camera Y pos move.l #vdpCommDelta($0080),d7 ; store VDP command for line increment move.l d0,d1 ; copy byte-swapped VDP command for later access bsr.w GetBlockAddr tst.w (Two_player_mode).w bne.s ++ - move.w (a0),d3 ; get ID of the 16x16 block andi.w #$3FF,d3 lsl.w #3,d3 ; multiply by 8, the size in bytes of a 16x16 lea (Block_Table).w,a1 adda.w d3,a1 ; a1 = address of the current 16x16 in the block table move.l d1,d0 bsr.w ProcessAndWriteBlock2 adda.w #$10,a0 ; move onto the 16x16 vertically below this one addi.w #$100,d1 ; draw on alternate 8x8 lines andi.w #$FFF,d1 addi.w #$10,d4 ; add 16 to Y offset move.w d4,d0 andi.w #$70,d0 ; have we reached a new 128x128? bne.s + ; if not, branch bsr.w GetBlockAddr ; otherwise, renew the block address + dbf d6,- ; repeat 16 times rts ; =========================================================================== / move.w (a0),d3 andi.w #$3FF,d3 lsl.w #3,d3 lea (Block_Table).w,a1 adda.w d3,a1 move.l d1,d0 bsr.w ProcessAndWriteBlock2_2P adda.w #$10,a0 addi.w #$80,d1 andi.w #$FFF,d1 addi.w #$10,d4 move.w d4,d0 andi.w #$70,d0 bne.s + bsr.w GetBlockAddr + dbf d6,- rts ; End of function DrawBlockCol1 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_DF8A: DrawTiles_Vertical: DrawBlockRow: add.w (a3),d5 add.w 4(a3),d4 bra.s DrawBlockRow3 ; End of function DrawBlockRow ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_DF92: DrawTiles_Vertical1: DrawBlockRow1: moveq #$15,d6 add.w (a3),d5 ; add X pos ; loc_DF96: DrawTiles_Vertical2: DrawBlockRow2: add.w 4(a3),d4 ; add Y pos ; loc_DF9A: DrawTiles_Vertical3: DrawBlockRow3: tst.w (Two_player_mode).w bne.s DrawBlockRow_2P move.l a2,-(sp) move.w d6,-(sp) lea (Block_cache).w,a2 move.l d0,d1 or.w d2,d1 swap d1 ; make VRAM write command move.l d1,-(sp) move.l d1,(a5) ; set up a VRAM write at that address swap d1 bsr.w GetBlockAddr - move.w (a0),d3 ; get ID of the 16x16 block andi.w #$3FF,d3 lsl.w #3,d3 ; multiply by 8, the size in bytes of a 16x16 lea (Block_Table).w,a1 adda.w d3,a1 ; a1 = address of current 16x16 in the block table bsr.w ProcessAndWriteBlock addq.w #2,a0 ; move onto next 16x16 addq.b #4,d1 ; increment VRAM write address bpl.s + andi.b #$7F,d1 ; restrict to a single 8x8 line swap d1 move.l d1,(a5) ; set up a VRAM write at a new address swap d1 + addi.w #$10,d5 ; add 16 to X offset move.w d5,d0 andi.w #$70,d0 ; have we reached a new 128x128? bne.s + ; if not, branch bsr.w GetBlockAddr ; otherwise, renew the block address + dbf d6,- ; repeat 22 times move.l (sp)+,d1 addi.l #vdpCommDelta($0080),d1 ; move onto next line lea (Block_cache).w,a2 move.l d1,(a5) ; write to this VRAM address swap d1 move.w (sp)+,d6 - move.l (a2)+,(a6) ; write stored 8x8s addq.b #4,d1 ; increment VRAM write address bmi.s + ori.b #$80,d1 ; force to bottom 8x8 line swap d1 move.l d1,(a5) ; set up a VRAM write at a new address swap d1 + dbf d6,- ; repeat 22 times movea.l (sp)+,a2 rts ; =========================================================================== ; loc_E018: DrawBlockRow_2P: move.l d0,d1 or.w d2,d1 swap d1 move.l d1,(a5) swap d1 tst.b d1 bmi.s +++ bsr.w GetBlockAddr - move.w (a0),d3 andi.w #$3FF,d3 lsl.w #3,d3 lea (Block_Table).w,a1 adda.w d3,a1 bsr.w ProcessAndWriteBlock_2P addq.w #2,a0 addq.b #4,d1 bpl.s + andi.b #$7F,d1 swap d1 move.l d1,(a5) swap d1 + addi.w #$10,d5 move.w d5,d0 andi.w #$70,d0 bne.s + bsr.w GetBlockAddr + dbf d6,- rts ; =========================================================================== + bsr.w GetBlockAddr - move.w (a0),d3 andi.w #$3FF,d3 lsl.w #3,d3 lea (Block_Table).w,a1 adda.w d3,a1 bsr.w ProcessAndWriteBlock_2P addq.w #2,a0 addq.b #4,d1 bmi.s + ori.b #$80,d1 swap d1 move.l d1,(a5) swap d1 + addi.w #$10,d5 move.w d5,d0 andi.w #$70,d0 bne.s + bsr.w GetBlockAddr + dbf d6,- rts ; End of function DrawBlockRow1 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_E09E: GetBlockAddr: movem.l d4-d5,-(sp) move.w d4,d3 ; d3 = camera Y pos + offset add.w d3,d3 andi.w #$F00,d3 ; limit to units of $100 ($100 = $80 * 2, $80 = height of a 128x128) lsr.w #3,d5 ; divide by 8 move.w d5,d0 lsr.w #4,d0 ; divide by 16 (overall division of 128) andi.w #$7F,d0 add.w d3,d0 ; get offset of current 128x128 in the level layout table moveq #-1,d3 clr.w d3 ; d3 = $FFFF0000 move.b (a4,d0.w),d3 ; get tile ID of the current 128x128 tile lsl.w #7,d3 ; multiply by 128, the size in bytes of a 128x128 in RAM andi.w #$70,d4 ; round down to nearest 16-pixel boundary andi.w #$E,d5 ; force this to be a multiple of 16 add.w d4,d3 ; add vertical offset of current 16x16 add.w d5,d3 ; add horizontal offset of current 16x16 movea.l d3,a0 ; store address, in the metablock table, of the current 16x16 movem.l (sp)+,d4-d5 rts ; End of function GetBlockAddr ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_E0D4: ProcessAndWriteBlock: btst #3,(a0) ; is this 16x16 to be Y-flipped? bne.s ProcessAndWriteBlock_FlipY ; if it is, branch btst #2,(a0) ; is this 16x16 to be X-flipped? bne.s ProcessAndWriteBlock_FlipX ; if it is, branch move.l (a1)+,(a6) ; write top two 8x8s to VRAM move.l (a1)+,(a2)+ ; store bottom two 8x8s for later writing rts ; =========================================================================== ProcessAndWriteBlock_FlipX: move.l (a1)+,d3 eori.l #(flip_x<<16)|flip_x,d3 ; toggle X-flip flag of the 8x8s swap d3 ; swap the position of the 8x8s move.l d3,(a6) ; write top two 8x8s to VRAM move.l (a1)+,d3 eori.l #(flip_x<<16)|flip_x,d3 swap d3 move.l d3,(a2)+ ; store bottom two 8x8s for later writing rts ; =========================================================================== ProcessAndWriteBlock_FlipY: btst #2,(a0) ; is this 16x16 to be X-flipped as well? bne.s ProcessAndWriteBlock_FlipXY ; if it is, branch move.l (a1)+,d0 move.l (a1)+,d3 eori.l #(flip_y<<16)|flip_y,d3 ; toggle Y-flip flag of the 8x8s move.l d3,(a6) ; write bottom two 8x8s to VRAM eori.l #(flip_y<<16)|flip_y,d0 move.l d0,(a2)+ ; store top two 8x8s for later writing rts ; =========================================================================== ProcessAndWriteBlock_FlipXY: move.l (a1)+,d0 move.l (a1)+,d3 eori.l #((flip_x|flip_y)<<16)|flip_x|flip_y,d3 ; toggle X and Y-flip flags of the 8x8s swap d3 move.l d3,(a6) ; write bottom two 8x8s to VRAM eori.l #((flip_x|flip_y)<<16)|flip_x|flip_y,d0 swap d0 move.l d0,(a2)+ ; store top two 8x8s for later writing rts ; End of function ProcessAndWriteBlock ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_E136: ProcessAndWriteBlock_2P: btst #3,(a0) bne.s loc_E154 btst #2,(a0) bne.s loc_E146 move.l (a1)+,(a6) rts ; =========================================================================== loc_E146: move.l (a1)+,d3 eori.l #(flip_x<<16)|flip_x,d3 swap d3 move.l d3,(a6) rts ; =========================================================================== loc_E154: btst #2,(a0) bne.s loc_E166 move.l (a1)+,d3 eori.l #(flip_y<<16)|flip_y,d3 move.l d3,(a6) rts ; =========================================================================== loc_E166: move.l (a1)+,d3 eori.l #((flip_x|flip_y)<<16)|flip_x|flip_y,d3 swap d3 move.l d3,(a6) rts ; End of function ProcessAndWriteBlock_2P ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_E174: ProcessAndWriteBlock2: or.w d2,d0 swap d0 ; make VRAM write command btst #3,(a0) ; is the 16x16 to be Y-flipped? bne.s ProcessAndWriteBlock2_FlipY ; if it is, branch btst #2,(a0) ; is the 16x16 to be X-flipped? bne.s ProcessAndWriteBlock2_FlipX ; if it is, branch move.l d0,(a5) ; write to this VRAM address move.l (a1)+,(a6) ; write top two 8x8s add.l d7,d0 ; move onto next line move.l d0,(a5) move.l (a1)+,(a6) ; write bottom two 8x8s rts ; =========================================================================== ProcessAndWriteBlock2_FlipX: move.l d0,(a5) move.l (a1)+,d3 eori.l #(flip_x<<16)|flip_x,d3 ; toggle X-flip flag of the 8x8s swap d3 ; swap the position of the 8x8s move.l d3,(a6) ; write top two 8x8s add.l d7,d0 ; move onto next line move.l d0,(a5) move.l (a1)+,d3 eori.l #(flip_x<<16)|flip_x,d3 swap d3 move.l d3,(a6) ; write bottom two 8x8s rts ; =========================================================================== ProcessAndWriteBlock2_FlipY: btst #2,(a0) ; is the 16x16 to be X-flipped as well? bne.s ProcessAndWriteBlock2_FlipXY ; if it is, branch move.l d5,-(sp) move.l d0,(a5) move.l (a1)+,d5 move.l (a1)+,d3 eori.l #(flip_y<<16)|flip_y,d3 ; toggle Y-flip flag of 8x8s move.l d3,(a6) ; write bottom two 8x8s add.l d7,d0 ; move onto next line move.l d0,(a5) eori.l #(flip_y<<16)|flip_y,d5 move.l d5,(a6) ; write top two 8x8s move.l (sp)+,d5 rts ; =========================================================================== ProcessAndWriteBlock2_FlipXY: move.l d5,-(sp) move.l d0,(a5) move.l (a1)+,d5 move.l (a1)+,d3 eori.l #((flip_x|flip_y)<<16)|flip_x|flip_y,d3 ; toggle X and Y-flip flags of 8x8s swap d3 ; swap the position of the 8x8s move.l d3,(a6) ; write bottom two 8x8s add.l d7,d0 move.l d0,(a5) eori.l #((flip_x|flip_y)<<16)|flip_x|flip_y,d5 swap d5 move.l d5,(a6) ; write top two 8x8s move.l (sp)+,d5 rts ; End of function ProcessAndWriteBlock2 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_E1FA: ProcessAndWriteBlock2_2P: or.w d2,d0 swap d0 btst #3,(a0) bne.s loc_E220 btst #2,(a0) bne.s loc_E210 move.l d0,(a5) move.l (a1)+,(a6) rts ; =========================================================================== loc_E210: move.l d0,(a5) move.l (a1)+,d3 eori.l #(flip_x<<16)|flip_x,d3 swap d3 move.l d3,(a6) rts ; =========================================================================== loc_E220: btst #2,(a0) bne.s loc_E234 move.l d0,(a5) move.l (a1)+,d3 eori.l #(flip_y<<16)|flip_y,d3 move.l d3,(a6) rts ; =========================================================================== loc_E234: move.l d0,(a5) move.l (a1)+,d3 eori.l #((flip_x|flip_y)<<16)|flip_x|flip_y,d3 swap d3 move.l d3,(a6) rts ; End of function ProcessAndWriteBlock2_2P ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_E244 GetBlockPtr: add.w (a3),d5 add.w 4(a3),d4 lea (Block_Table).w,a1 move.w d4,d3 ; d3 = camera Y pos + offset add.w d3,d3 andi.w #$F00,d3 ; limit to units of $100 ($100 = $80 * 2, $80 = height of a 128x128) lsr.w #3,d5 ; divide by 8 move.w d5,d0 lsr.w #4,d0 ; divide by 16 (overall division of 128) andi.w #$7F,d0 add.w d3,d0 ; get offset of current 128x128 in the level layout table moveq #-1,d3 clr.w d3 ; d3 = $FFFF0000 move.b (a4,d0.w),d3 ; get tile ID of the current 128x128 tile lsl.w #7,d3 ; multiply by 128, the size in bytes of a 128x128 in RAM andi.w #$70,d4 ; round down to nearest 16-pixel boundary andi.w #$E,d5 ; force this to be a multiple of 16 add.w d4,d3 ; add vertical offset of current 16x16 add.w d5,d3 ; add horizontal offset of current 16x16 movea.l d3,a0 ; store address, in the metablock table, of the current 16x16 move.w (a0),d3 andi.w #$3FF,d3 lsl.w #3,d3 adda.w d3,a1 rts ; End of function GetBlockPtr ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_E286: Calc_VRAM_Pos: CalcBlockVRAMPos: add.w (a3),d5 ; add X pos CalcBlockVRAMPos2: tst.w (Two_player_mode).w bne.s CalcBlockVRAMPos_2P add.w 4(a3),d4 ; add Y pos andi.w #$F0,d4 ; round down to the nearest 16-pixel boundary andi.w #$1F0,d5 ; round down to the nearest 16-pixel boundary lsl.w #4,d4 ; make it into units of $100 - the height in plane A of a 16x16 lsr.w #2,d5 ; make it into units of 4 - the width in plane A of a 16x16 add.w d5,d4 ; combine the two to get final address ; access a VDP address in plane name table A ($C000) or B ($E000) if d2 has bit 13 unset or set moveq #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE)&$FFFF,d0 swap d0 move.w d4,d0 ; make word-swapped VDP command rts ; =========================================================================== ; loc_E2A8: CalcBlockVRAMPos_2P: add.w 4(a3),d4 loc_E2AC: andi.w #$1F0,d4 andi.w #$1F0,d5 lsl.w #3,d4 lsr.w #2,d5 add.w d5,d4 ; access a VDP address in plane name table A ($C000) or B ($E000) if d2 has bit 13 unset or set moveq #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE)&$FFFF,d0 swap d0 move.w d4,d0 rts ; End of function CalcBlockVRAMPos ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;loc_E2C2: CalcBlockVRAMPosB: tst.w (Two_player_mode).w bne.s + add.w 4(a3),d4 add.w (a3),d5 andi.w #$F0,d4 andi.w #$1F0,d5 lsl.w #4,d4 lsr.w #2,d5 add.w d5,d4 ; access a VDP address in 2p plane name table A ($A000) or B ($8000) if d2 has bit 13 unset or set moveq #vdpComm(VRAM_Plane_A_Name_Table_2P,VRAM,WRITE)&$FFFF,d0 swap d0 move.w d4,d0 rts ; =========================================================================== ; interestingly, this subroutine was in the Sonic 1 ROM, unused + add.w 4(a3),d4 add.w (a3),d5 andi.w #$1F0,d4 andi.w #$1F0,d5 lsl.w #3,d4 lsr.w #2,d5 add.w d5,d4 ; access a VDP address in 2p plane name table A ($A000) or B ($8000) if d2 has bit 13 unset or set moveq #vdpComm(VRAM_Plane_A_Name_Table_2P,VRAM,WRITE)&$FFFF,d0 swap d0 move.w d4,d0 rts ; End of function CalcBlockVRAMPosB ; =========================================================================== ; Loads the background in its initial state into VRAM (plane B). ; Especially important for levels that never re-load the background dynamically ;loc_E300: DrawInitialBG: lea (VDP_control_port).l,a5 lea (VDP_data_port).l,a6 lea (Camera_BG_X_pos).w,a3 lea (Level_Layout+$80).w,a4 ; background move.w #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE)>>16,d2 moveq #0,d4 cmpi.b #casino_night_zone,(Current_Zone).w beq.w ++ tst.w (Two_player_mode).w beq.w + cmpi.b #mystic_cave_zone,(Current_Zone).w beq.w loc_E396 + moveq #-$10,d4 + moveq #$F,d6 - movem.l d4-d6,-(sp) moveq #0,d5 move.w d4,d1 bsr.w CalcBlockVRAMPos move.w d1,d4 moveq #0,d5 moveq #$1F,d6 move #$2700,sr bsr.w DrawBlockRow move #$2300,sr movem.l (sp)+,d4-d6 addi.w #$10,d4 dbf d6,- rts ; =========================================================================== ; dead code moveq #-$10,d4 moveq #$F,d6 - movem.l d4-d6,-(sp) moveq #0,d5 move.w d4,d1 bsr.w CalcBlockVRAMPosB move.w d1,d4 moveq #0,d5 moveq #$1F,d6 move #$2700,sr bsr.w DrawBlockRow move #$2300,sr movem.l (sp)+,d4-d6 addi.w #$10,d4 dbf d6,- rts ; =========================================================================== loc_E396: moveq #0,d4 moveq #$1F,d6 - movem.l d4-d6,-(sp) moveq #0,d5 move.w d4,d1 bsr.w loc_E2AC move.w d1,d4 moveq #0,d5 moveq #$1F,d6 move #$2700,sr bsr.w DrawBlockRow3 move #$2300,sr movem.l (sp)+,d4-d6 addi.w #$10,d4 dbf d6,- rts ; =========================================================================== ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; loadZoneBlockMaps ; Loads block and bigblock mappings for the current Zone. loadZoneBlockMaps: moveq #0,d0 move.b (Current_Zone).w,d0 add.w d0,d0 add.w d0,d0 move.w d0,d1 add.w d0,d0 add.w d1,d0 lea (LevelArtPointers).l,a2 lea (a2,d0.w),a2 move.l a2,-(sp) addq.w #4,a2 move.l (a2)+,d0 andi.l #$FFFFFF,d0 ; pointer to block mappings movea.l d0,a0 lea (Block_Table).w,a1 jsrto (KosDec).l, JmpTo_KosDec ; load block maps cmpi.b #hill_top_zone,(Current_Zone).w bne.s + lea (Block_Table+$980).w,a1 lea (BM16_HTZ).l,a0 jsrto (KosDec).l, JmpTo_KosDec ; patch for Hill Top Zone block map + tst.w (Two_player_mode).w beq.s + ; In 2P mode, adjust the block table to halve the pattern index on each block lea (Block_Table).w,a1 move.w #bytesToWcnt(Block_Table_End-Block_Table),d2 - move.w (a1),d0 ; read an entry move.w d0,d1 andi.w #$F800,d0 ; filter for upper five bits andi.w #$7FF,d1 ; filter for lower eleven bits (patternIndex) lsr.w #1,d1 ; halve the pattern index or.w d1,d0 ; put the parts back together move.w d0,(a1)+ ; change the entry with the adjusted value dbf d2,- + move.l (a2)+,d0 andi.l #$FFFFFF,d0 ; pointer to chunk mappings movea.l d0,a0 lea (Chunk_Table).l,a1 jsrto (KosDec).l, JmpTo_KosDec bsr.w loadLevelLayout movea.l (sp)+,a2 ; zone specific pointer in LevelArtPointers addq.w #4,a2 moveq #0,d0 move.b (a2),d0 ; PLC2 ID beq.s + jsrto (LoadPLC).l, JmpTo_LoadPLC + addq.w #4,a2 moveq #0,d0 move.b (a2),d0 ; palette ID jsrto (PalLoad_Now).l, JmpTo_PalLoad_Now rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| loadLevelLayout: moveq #0,d0 move.w (Current_ZoneAndAct).w,d0 ror.b #1,d0 lsr.w #6,d0 lea (Off_Level).l,a0 move.w (a0,d0.w),d0 lea (a0,d0.l),a0 lea (Level_Layout).w,a1 jmpto (KosDec).l, JmpTo_KosDec ; End of function loadLevelLayout ; =========================================================================== lea (Level_Layout).w,a3 move.w #bytesToLcnt(Level_Layout_End-Level_Layout),d1 moveq #0,d0 - move.l d0,(a3)+ dbf d1,- lea (Level_Layout).w,a3 moveq #0,d1 bsr.w sub_E4A2 lea (Level_Layout+$80).w,a3 moveq #2,d1 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_E4A2: moveq #0,d0 move.w (Current_ZoneAndAct).w,d0 ror.b #1,d0 lsr.w #5,d0 add.w d1,d0 lea (Off_Level).l,a1 move.w (a1,d0.w),d0 lea (a1,d0.l),a1 moveq #0,d1 move.w d1,d2 move.b (a1)+,d1 move.b (a1)+,d2 move.l d1,d5 addq.l #1,d5 moveq #0,d3 move.w #$80,d3 divu.w d5,d3 subq.w #1,d3 - movea.l a3,a0 move.w d3,d4 - move.l a1,-(sp) move.w d1,d0 - move.b (a1)+,(a0)+ dbf d0,- movea.l (sp)+,a1 dbf d4,-- lea (a1,d5.w),a1 lea $100(a3),a3 dbf d2,--- rts ; End of function sub_E4A2 ; =========================================================================== lea ($FE0000).l,a1 lea ($FE0080).l,a2 lea (Chunk_Table).l,a3 move.w #$3F,d1 - bsr.w sub_E59C bsr.w sub_E59C dbf d1,- lea ($FE0000).l,a1 lea ($FF0000).l,a2 move.w #$3F,d1 - move.w #0,(a2)+ dbf d1,- move.w #$3FBF,d1 - move.w (a1)+,(a2)+ dbf d1,- rts ; =========================================================================== lea ($FE0000).l,a1 lea (Chunk_Table).l,a3 moveq #$1F,d0 - move.l (a1)+,(a3)+ dbf d0,- moveq #0,d7 lea ($FE0000).l,a1 move.w #$FF,d5 loc_E55A: lea (Chunk_Table).l,a3 move.w d7,d6 - movem.l a1-a3,-(sp) move.w #$3F,d0 - cmpm.w (a1)+,(a3)+ bne.s + dbf d0,- movem.l (sp)+,a1-a3 adda.w #$80,a1 dbf d5,loc_E55A bra.s ++ ; =========================================================================== + movem.l (sp)+,a1-a3 adda.w #$80,a3 dbf d6,-- moveq #$1F,d0 - move.l (a1)+,(a3)+ dbf d0,- addq.l #1,d7 dbf d5,loc_E55A / bra.s - ; infinite loop ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_E59C: moveq #7,d0 - move.l (a3)+,(a1)+ move.l (a3)+,(a1)+ move.l (a3)+,(a1)+ move.l (a3)+,(a1)+ move.l (a3)+,(a2)+ move.l (a3)+,(a2)+ move.l (a3)+,(a2)+ move.l (a3)+,(a2)+ dbf d0,- adda.w #$80,a1 adda.w #$80,a2 rts ; End of function sub_E59C ; =========================================================================== if gameRevision=0 nop endif if ~~removeJmpTos ; JmpTo_PalLoad2 JmpTo_PalLoad_Now jmp (PalLoad_Now).l JmpTo_LoadPLC jmp (LoadPLC).l JmpTo_KosDec jmp (KosDec).l align 4 endif ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; screen resizing, earthquakage, etc ; sub_E5D0: RunDynamicLevelEvents: moveq #0,d0 move.b (Current_Zone).w,d0 add.w d0,d0 move.w DynamicLevelEventIndex(pc,d0.w),d0 jsr DynamicLevelEventIndex(pc,d0.w) moveq #2,d1 move.w (Camera_Max_Y_pos).w,d0 sub.w (Camera_Max_Y_pos_now).w,d0 beq.s ++ ; rts bcc.s +++ neg.w d1 move.w (Camera_Y_pos).w,d0 cmp.w (Camera_Max_Y_pos).w,d0 bls.s + move.w d0,(Camera_Max_Y_pos_now).w andi.w #$FFFE,(Camera_Max_Y_pos_now).w + add.w d1,(Camera_Max_Y_pos_now).w move.b #1,(Camera_Max_Y_Pos_Changing).w + rts ; =========================================================================== + move.w (Camera_Y_pos).w,d0 addi_.w #8,d0 cmp.w (Camera_Max_Y_pos_now).w,d0 blo.s + btst #1,(MainCharacter+status).w beq.s + add.w d1,d1 add.w d1,d1 + add.w d1,(Camera_Max_Y_pos_now).w move.b #1,(Camera_Max_Y_Pos_Changing).w rts ; End of function RunDynamicLevelEvents ; =========================================================================== ; off_E636: DynamicLevelEventIndex: zoneOrderedOffsetTable 2,1 zoneOffsetTableEntry.w LevEvents_EHZ ; 0 ; EHZ zoneOffsetTableEntry.w LevEvents_001 ; 1 ; LEV1 zoneOffsetTableEntry.w LevEvents_002 ; 2 ; LEV2 zoneOffsetTableEntry.w LevEvents_003 ; 3 ; LEV3 zoneOffsetTableEntry.w LevEvents_MTZ ; 4 ; MTZ zoneOffsetTableEntry.w LevEvents_MTZ3 ; 5 ; MTZ3 zoneOffsetTableEntry.w LevEvents_WFZ ; 6 ; WFZ zoneOffsetTableEntry.w LevEvents_HTZ ; 7 ; HTZ zoneOffsetTableEntry.w LevEvents_HPZ ; 8 ; HPZ zoneOffsetTableEntry.w LevEvents_009 ; 9 ; LEV9 zoneOffsetTableEntry.w LevEvents_OOZ ; $A ; OOZ zoneOffsetTableEntry.w LevEvents_MCZ ; $B ; MCZ zoneOffsetTableEntry.w LevEvents_CNZ ; $C ; CNZ zoneOffsetTableEntry.w LevEvents_CPZ ; $D ; CPZ zoneOffsetTableEntry.w LevEvents_DEZ ; $E ; DEZ zoneOffsetTableEntry.w LevEvents_ARZ ; $F ; ARZ zoneOffsetTableEntry.w LevEvents_SCZ ; $10 ; SCZ zoneTableEnd ; =========================================================================== ; loc_E658: LevEvents_EHZ: tst.b (Current_Act).w bne.s LevEvents_EHZ2 rts ; --------------------------------------------------------------------------- LevEvents_EHZ2: moveq #0,d0 move.b (Dynamic_Resize_Routine).w,d0 move.w LevEvents_EHZ2_Index(pc,d0.w),d0 jmp LevEvents_EHZ2_Index(pc,d0.w) ; =========================================================================== ; off_E66E: LevEvents_EHZ2_Index: offsetTable offsetTableEntry.w LevEvents_EHZ2_Routine1 ; 0 offsetTableEntry.w LevEvents_EHZ2_Routine2 ; 2 offsetTableEntry.w LevEvents_EHZ2_Routine3 ; 4 offsetTableEntry.w LevEvents_EHZ2_Routine4 ; 6 ; =========================================================================== ; loc_E676: LevEvents_EHZ2_Routine1: tst.w (Two_player_mode).w bne.s ++ cmpi.w #$2780,(Camera_X_pos).w blo.s + ; rts move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w move.w #$390,(Camera_Max_Y_pos).w move.w #$390,(Tails_Max_Y_pos).w addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_EHZ2_Routine2 + rts ; --------------------------------------------------------------------------- + move.w #$2920,(Camera_Max_X_pos).w move.w #$2920,(Tails_Max_X_pos).w rts ; =========================================================================== ; loc_E6B0: LevEvents_EHZ2_Routine2: cmpi.w #$28F0,(Camera_X_pos).w blo.s + ; rts move.w #$28F0,(Camera_Min_X_pos).w move.w #$2940,(Camera_Max_X_pos).w move.w #$28F0,(Tails_Min_X_pos).w move.w #$2940,(Tails_Max_X_pos).w addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_EHZ2_Routine3 move.w #MusID_FadeOut,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic clr.b (ScreenShift).w move.b #2,(Current_Boss_ID).w moveq #PLCID_EhzBoss,d0 jsrto (LoadPLC).l, JmpTo2_LoadPLC + rts ; =========================================================================== ; loc_E6EE: LevEvents_EHZ2_Routine3: cmpi.w #$388,(Camera_Y_pos).w blo.s + move.w #$388,(Camera_Min_Y_pos).w move.w #$388,(Tails_Min_Y_pos).w + addq.b #1,(ScreenShift).w cmpi.b #$5A,(ScreenShift).w blo.s ++ jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad bne.s + move.b #ObjID_EHZBoss,id(a1) ; load obj56 (EHZ boss) move.b #$81,subtype(a1) move.w #$29D0,x_pos(a1) move.w #$426,y_pos(a1) + addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_EHZ2_Routine4 move.w #MusID_Boss,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic + rts ; =========================================================================== ; loc_E738: LevEvents_EHZ2_Routine4: tst.b (Boss_defeated_flag).w beq.s + move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w + rts ; =========================================================================== ; return_E752: LevEvents_001: rts ; =========================================================================== ; return_E754: LevEvents_002: rts ; =========================================================================== ; return_E756: LevEvents_003: rts ; =========================================================================== ; return_E758: LevEvents_MTZ: rts ; =========================================================================== ; loc_E75A: LevEvents_MTZ3: moveq #0,d0 move.b (Dynamic_Resize_Routine).w,d0 move.w LevEvents_MTZ3_Index(pc,d0.w),d0 jmp LevEvents_MTZ3_Index(pc,d0.w) ; =========================================================================== ; off_E768: LevEvents_MTZ3_Index: offsetTable offsetTableEntry.w LevEvents_MTZ3_Routine1 ; 0 offsetTableEntry.w LevEvents_MTZ3_Routine2 ; 2 offsetTableEntry.w LevEvents_MTZ3_Routine3 ; 4 offsetTableEntry.w LevEvents_MTZ3_Routine4 ; 6 offsetTableEntry.w LevEvents_MTZ3_Routine5 ; 8 ; =========================================================================== ; loc_E772: LevEvents_MTZ3_Routine1: cmpi.w #$2530,(Camera_X_pos).w blo.s + move.w #$500,(Camera_Max_Y_pos_now).w move.w #$450,(Camera_Max_Y_pos).w move.w #$450,(Tails_Max_Y_pos).w addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_MTZ3_Routine2 + rts ; =========================================================================== ; loc_E792: LevEvents_MTZ3_Routine2: cmpi.w #$2980,(Camera_X_pos).w blo.s + move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w move.w #$400,(Camera_Max_Y_pos).w move.w #$400,(Tails_Max_Y_pos).w addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_MTZ3_Routine3 + rts ; =========================================================================== ; loc_E7B8: LevEvents_MTZ3_Routine3: cmpi.w #$2A80,(Camera_X_pos).w blo.s + move.w #$2AB0,(Camera_Min_X_pos).w move.w #$2AB0,(Camera_Max_X_pos).w move.w #$2AB0,(Tails_Min_X_pos).w move.w #$2AB0,(Tails_Max_X_pos).w addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_MTZ3_Routine4 move.w #MusID_FadeOut,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic clr.b (ScreenShift).w move.b #7,(Current_Boss_ID).w moveq #PLCID_MtzBoss,d0 jsrto (LoadPLC).l, JmpTo2_LoadPLC + rts ; =========================================================================== ; loc_E7F6: LevEvents_MTZ3_Routine4: cmpi.w #$400,(Camera_Y_pos).w blo.s + move.w #$400,(Camera_Min_Y_pos).w move.w #$400,(Tails_Min_Y_pos).w + addq.b #1,(ScreenShift).w cmpi.b #$5A,(ScreenShift).w blo.s ++ jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad bne.s + move.b #ObjID_MTZBoss,id(a1) ; load obj54 (MTZ boss) + addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_MTZ3_Routine5 move.w #MusID_Boss,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic + rts ; =========================================================================== ; loc_E82E: LevEvents_MTZ3_Routine5: move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w rts ; =========================================================================== ; loc_E842: LevEvents_WFZ: moveq #0,d0 move.b (Dynamic_Resize_Routine).w,d0 move.w LevEvents_WFZ_Index(pc,d0.w),d0 jsr LevEvents_WFZ_Index(pc,d0.w) move.w (WFZ_LevEvent_Subrout).w,d0 move.w LevEvents_WFZ_Index2(pc,d0.w),d0 jmp LevEvents_WFZ_Index2(pc,d0.w) ; =========================================================================== ; off_E85C: LevEvents_WFZ_Index2: offsetTable offsetTableEntry.w LevEvents_WFZ_Routine5 ; 0 offsetTableEntry.w LevEvents_WFZ_Routine6 ; 2 offsetTableEntry.w LevEvents_WFZ_RoutineNull ; 4 ; =========================================================================== ; off_E862: LevEvents_WFZ_Index: offsetTable offsetTableEntry.w LevEvents_WFZ_Routine1 ; 0 offsetTableEntry.w LevEvents_WFZ_Routine2 ; 2 offsetTableEntry.w LevEvents_WFZ_Routine3 ; 4 offsetTableEntry.w LevEvents_WFZ_Routine4 ; 6 ; =========================================================================== ; loc_E86A: LevEvents_WFZ_Routine1: move.l (Camera_X_pos).w,(Camera_BG_X_pos).w move.l (Camera_Y_pos).w,(Camera_BG_Y_pos).w moveq #0,d0 move.w d0,(Camera_BG_X_pos_diff).w move.w d0,(Camera_BG_Y_pos_diff).w move.w d0,(Camera_BG_X_offset).w move.w d0,(Camera_BG_Y_offset).w addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_WFZ_Routine2 rts ; =========================================================================== ; loc_E88E: LevEvents_WFZ_Routine2: cmpi.w #$2BC0,(Camera_X_pos).w blo.s + cmpi.w #$580,(Camera_Y_pos).w blo.s + addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_WFZ_Routine3 move.w #0,(WFZ_BG_Y_Speed).w + move.w (Camera_X_pos_diff).w,(Camera_BG_X_pos_diff).w move.w (Camera_Y_pos_diff).w,(Camera_BG_Y_pos_diff).w move.w (Camera_X_pos).w,d0 move.w (Camera_Y_pos).w,d1 bra.w ScrollBG ; =========================================================================== ; loc_E8C0: LevEvents_WFZ_Routine3: cmpi.w #$800,(Camera_BG_X_offset).w beq.s + addq.w #2,(Camera_BG_X_offset).w + cmpi.w #$600,(Camera_BG_X_offset).w blt.s LevEvents_WFZ_Routine3_Part2 move.w (WFZ_BG_Y_Speed).w,d0 moveq #4,d1 cmpi.w #$840,d0 bhs.s + add.w d1,d0 move.w d0,(WFZ_BG_Y_Speed).w + lsr.w #8,d0 add.w d0,(Camera_BG_Y_offset).w ; loc_E8EC: LevEvents_WFZ_Routine3_Part2: move.w (Camera_X_pos_diff).w,(Camera_BG_X_pos_diff).w move.w (Camera_Y_pos_diff).w,(Camera_BG_Y_pos_diff).w move.w (Camera_X_pos).w,d0 move.w (Camera_Y_pos).w,d1 bra.w ScrollBG ; =========================================================================== ; loc_E904: LevEvents_WFZ_Routine4: cmpi.w #-$2C0,(Camera_BG_X_offset).w beq.s ++ subi_.w #2,(Camera_BG_X_offset).w cmpi.w #$1B81,(Camera_BG_Y_offset).w beq.s ++ move.w (WFZ_BG_Y_Speed).w,d0 beq.s + moveq #4,d1 neg.w d1 add.w d1,d0 move.w d0,(WFZ_BG_Y_Speed).w lsr.w #8,d0 + addq.w #1,d0 add.w d0,(Camera_BG_Y_offset).w + move.w (Camera_X_pos_diff).w,(Camera_BG_X_pos_diff).w move.w (Camera_Y_pos_diff).w,(Camera_BG_Y_pos_diff).w move.w (Camera_X_pos).w,d0 move.w (Camera_Y_pos).w,d1 bra.w ScrollBG ; =========================================================================== ; loc_E94A: LevEvents_WFZ_Routine5: cmpi.w #$2880,(Camera_X_pos).w blo.s + ; rts cmpi.w #$400,(Camera_Y_pos).w blo.s + ; rts addq.w #2,(WFZ_LevEvent_Subrout).w ; => LevEvents_WFZ_Routine6 moveq #PLCID_WfzBoss,d0 jsrto (LoadPLC).l, JmpTo2_LoadPLC move.w #$2880,(Camera_Min_X_pos).w + rts ; =========================================================================== ; loc_E96C: LevEvents_WFZ_Routine6: cmpi.w #$500,(Camera_Y_pos).w blo.s + ; rts addq.w #2,(WFZ_LevEvent_Subrout).w ; => LevEvents_WFZ_RoutineNull st (Control_Locked).w moveq #PLCID_Tornado,d0 jsrto (LoadPLC).l, JmpTo2_LoadPLC + rts ; =========================================================================== ; return_E984: LevEvents_WFZ_RoutineNull: rts ; =========================================================================== ; loc_E986: LevEvents_HTZ: tst.b (Current_Act).w bne.w LevEvents_HTZ2 moveq #0,d0 move.b (Dynamic_Resize_Routine).w,d0 move.w LevEvents_HTZ_Index(pc,d0.w),d0 jmp LevEvents_HTZ_Index(pc,d0.w) ; =========================================================================== ; off_E99C: LevEvents_HTZ_Index: offsetTable offsetTableEntry.w LevEvents_HTZ_Routine1 ; 0 left of earthquake offsetTableEntry.w LevEvents_HTZ_Routine2 ; 2 earthquake offsetTableEntry.w LevEvents_HTZ_Routine3 ; 4 right of earthquake ; =========================================================================== ; loc_E9A2: LevEvents_HTZ_Routine1: cmpi.w #$400,(Camera_Y_pos).w blo.s LevEvents_HTZ_Routine1_Part2 cmpi.w #$1800,(Camera_X_pos).w blo.s LevEvents_HTZ_Routine1_Part2 move.b #1,(Screen_Shaking_Flag_HTZ).w move.l (Camera_X_pos).w,(Camera_BG_X_pos).w move.l (Camera_Y_pos).w,(Camera_BG_Y_pos).w moveq #0,d0 move.w d0,(Camera_BG_X_pos_diff).w move.w d0,(Camera_BG_Y_pos_diff).w move.w d0,(Camera_BG_X_offset).w move.w #320,(Camera_BG_Y_offset).w subi.w #$100,(Camera_BG_Y_pos).w move.w #0,(HTZ_Terrain_Delay).w addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ_Routine2 - rts ; =========================================================================== LevEvents_HTZ_Routine1_Part2: tst.b (Screen_Shaking_Flag_HTZ).w beq.s - ; rts move.w #$200,d0 moveq #0,d1 move.w d1,(Camera_BG_X_pos_diff).w move.w d1,(Camera_BG_Y_pos_diff).w bsr.w ScrollBG or.w d0,d1 bne.s - ; rts move.b #0,(Screen_Shaking_Flag_HTZ).w rts ; =========================================================================== ; loc_EA0E: LevEvents_HTZ_Routine2: cmpi.w #$1978,(Camera_X_pos).w blo.w LevEvents_HTZ_Routine2_Continue cmpi.w #$1E00,(Camera_X_pos).w blo.s .keep_shaking move.b #0,(Screen_Shaking_Flag).w bra.s LevEvents_HTZ_Routine2_Continue ; --------------------------------------------------------------------------- .keep_shaking: tst.b (HTZ_Terrain_Direction).w bne.s .sinking cmpi.w #320,(Camera_BG_Y_offset).w beq.s .flip_delay move.w (Timer_frames).w,d0 move.w d0,d1 andi.w #3,d0 bne.s LevEvents_HTZ_Routine2_Continue addq.w #1,(Camera_BG_Y_offset).w andi.w #$3F,d1 bne.s LevEvents_HTZ_Routine2_Continue move.w #SndID_Rumbling2,d0 ; rumbling sound jsr (PlaySound).l bra.s LevEvents_HTZ_Routine2_Continue ; --------------------------------------------------------------------------- .sinking: cmpi.w #224,(Camera_BG_Y_offset).w beq.s .flip_delay move.w (Timer_frames).w,d0 move.w d0,d1 andi.w #3,d0 bne.s LevEvents_HTZ_Routine2_Continue subq.w #1,(Camera_BG_Y_offset).w andi.w #$3F,d1 bne.s LevEvents_HTZ_Routine2_Continue move.w #SndID_Rumbling2,d0 jsr (PlaySound).l bra.s LevEvents_HTZ_Routine2_Continue ; --------------------------------------------------------------------------- .flip_delay: move.b #0,(Screen_Shaking_Flag).w subq.w #1,(HTZ_Terrain_Delay).w bpl.s LevEvents_HTZ_Routine2_Continue move.w #$78,(HTZ_Terrain_Delay).w eori.b #1,(HTZ_Terrain_Direction).w move.b #1,(Screen_Shaking_Flag).w ; loc_EAA0: LevEvents_HTZ_Routine2_Continue: cmpi.w #$1800,(Camera_X_pos).w blo.s .exit_left cmpi.w #$1F00,(Camera_X_pos).w bhs.s .exit_right move.w (Camera_X_pos_diff).w,(Camera_BG_X_pos_diff).w move.w (Camera_Y_pos_diff).w,(Camera_BG_Y_pos_diff).w move.w (Camera_X_pos).w,d0 move.w (Camera_Y_pos).w,d1 bra.w ScrollBG ; --------------------------------------------------------------------------- .exit_left: move.l #$4000000,(Camera_BG_X_pos).w moveq #0,d0 move.l d0,(Camera_BG_Y_pos).w move.l d0,(Camera_BG_X_offset).w move.b d0,(HTZ_Terrain_Direction).w subq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ_Routine1 move.w #MusID_StopSFX,d0 jsr (PlaySound).l rts ; --------------------------------------------------------------------------- .exit_right: move.l #$4000000,(Camera_BG_X_pos).w moveq #0,d0 move.l d0,(Camera_BG_Y_pos).w move.l d0,(Camera_BG_X_offset).w move.b d0,(HTZ_Terrain_Direction).w addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ_Routine3 move.w #MusID_StopSFX,d0 jsr (PlaySound).l rts ; =========================================================================== ; loc_EB14: LevEvents_HTZ_Routine3: cmpi.w #$1F00,(Camera_X_pos).w bhs.s LevEvents_HTZ_Routine3_Part2 move.b #1,(Screen_Shaking_Flag_HTZ).w move.l (Camera_X_pos).w,(Camera_BG_X_pos).w move.l (Camera_Y_pos).w,(Camera_BG_Y_pos).w moveq #0,d0 move.w d0,(Camera_BG_X_pos_diff).w move.w d0,(Camera_BG_Y_pos_diff).w move.w d0,(Camera_BG_X_offset).w move.w #320,(Camera_BG_Y_offset).w subi.w #$100,(Camera_BG_Y_pos).w move.w #0,(HTZ_Terrain_Delay).w subq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ_Routine2 - rts ; --------------------------------------------------------------------------- ; loc_EB54: LevEvents_HTZ_Routine3_Part2: tst.b (Screen_Shaking_Flag_HTZ).w beq.s - ; rts move.w #$200,d0 moveq #0,d1 move.w d1,(Camera_BG_X_pos_diff).w move.w d1,(Camera_BG_Y_pos_diff).w bsr.w ScrollBG or.w d0,d1 bne.s - ; rts move.b #0,(Screen_Shaking_Flag_HTZ).w rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Computes how much the background layer has been scrolled in X and Y and ; stores result to Camera_BG_X_pos_diff and Camera_BG_Y_pos_diff. ; Caps maximum scroll speed to 16 pixels per frame in either direction. ; This is used to decide how much of the BG needs to be reloaded. ; ; Used for rising lava/terrain in HTZ, and for WFZ->DEZ transition in WFZ. ; ; Input: ; d0 Target X position of background ; d1 Target Y position of background ;sub_EB78 ScrollBG: sub.w (Camera_BG_X_pos).w,d0 sub.w (Camera_BG_X_offset).w,d0 bpl.s .going_right cmpi.w #-16,d0 bgt.s .skip_x_cap move.w #-16,d0 .skip_x_cap: bra.s .move_x ; =========================================================================== .going_right: cmpi.w #16,d0 blo.s .move_x move.w #16,d0 .move_x: move.b d0,(Camera_BG_X_pos_diff).w sub.w (Camera_BG_Y_pos).w,d1 sub.w (Camera_BG_Y_offset).w,d1 bpl.s .going_down cmpi.w #-16,d1 bgt.s .skip_y_cap move.w #-16,d1 .skip_y_cap: bra.s .move_y ; =========================================================================== .going_down: cmpi.w #16,d1 blo.s .move_y move.w #16,d1 .move_y: move.b d1,(Camera_BG_Y_pos_diff).w rts ; End of function ScrollBG ; =========================================================================== ; unused/dead code ; This code is probably meant for testing the background scrolling code ; used by HTZ and WFZ. It would allows the BG position to be shifted up ; and down by the second controller. btst #button_up,(Ctrl_2_Held).w beq.s + tst.w (Camera_BG_Y_offset).w beq.s + subq.w #1,(Camera_BG_Y_offset).w + btst #button_down,(Ctrl_2_Held).w beq.s + cmpi.w #$700,(Camera_BG_Y_offset).w beq.s + addq.w #1,(Camera_BG_Y_offset).w + rts ; =========================================================================== ; sub_EBEA: LevEvents_HTZ2: bsr.w LevEvents_HTZ2_Prepare moveq #0,d0 move.b (Dynamic_Resize_Routine).w,d0 move.w LevEvents_HTZ2_Index(pc,d0.w),d0 jmp LevEvents_HTZ2_Index(pc,d0.w) ; =========================================================================== ; off_EBFC: LevEvents_HTZ2_Index: offsetTable offsetTableEntry.w LevEvents_HTZ2_Routine1 ; 0 earthquake left offsetTableEntry.w LevEvents_HTZ2_Routine2 ; 2 earthquake (top) offsetTableEntry.w LevEvents_HTZ2_Routine3 ; 4 earthquake right (top) offsetTableEntry.w LevEvents_HTZ2_Routine4 ; 6 earthquake (bottom) offsetTableEntry.w LevEvents_HTZ2_Routine5 ; 8 earthquake right (bottom) offsetTableEntry.w LevEvents_HTZ2_Routine6 ; $A boss area cutoff offsetTableEntry.w LevEvents_HTZ2_Routine7 ; $C boss area camera shift offsetTableEntry.w LevEvents_HTZ2_Routine8 ; $E boss begin offsetTableEntry.w LevEvents_HTZ2_Routine9 ; $10 boss end / extend camera ; =========================================================================== ; loc_EC0E: LevEvents_HTZ2_Routine1: cmpi.w #$14C0,(Camera_X_pos).w blo.s LevEvents_HTZ2_Routine1_Part2 move.b #1,(Screen_Shaking_Flag_HTZ).w move.l (Camera_X_pos).w,(Camera_BG_X_pos).w move.l (Camera_Y_pos).w,(Camera_BG_Y_pos).w moveq #0,d0 move.w d0,(Camera_BG_X_pos_diff).w move.w d0,(Camera_BG_Y_pos_diff).w move.w d0,(Camera_BG_X_offset).w move.w #$2C0,(Camera_BG_Y_offset).w subi.w #$100,(Camera_BG_Y_pos).w move.w #0,(HTZ_Terrain_Delay).w addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine2 cmpi.w #$380,(Camera_Y_pos).w blo.s + ; rts move.w #-$680,(Camera_BG_X_offset).w addi.w #$480,(Camera_BG_X_pos).w move.w #$300,(Camera_BG_Y_offset).w addq.b #6,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine5 / rts ; --------------------------------------------------------------------------- LevEvents_HTZ2_Routine1_Part2: tst.b (Screen_Shaking_Flag_HTZ).w beq.s - ; rts move.w #$200,d0 moveq #0,d1 move.w d1,(Camera_BG_X_pos_diff).w move.w d1,(Camera_BG_Y_pos_diff).w bsr.w ScrollBG or.w d0,d1 bne.s - ; rts move.b #0,(Screen_Shaking_Flag_HTZ).w rts ; =========================================================================== ; loc_EC90: LevEvents_HTZ2_Routine2: cmpi.w #$1678,(Camera_X_pos).w blo.w LevEvents_HTZ2_Routine2_Continue cmpi.w #$1A00,(Camera_X_pos).w blo.s .keep_shaking move.b #0,(Screen_Shaking_Flag).w bra.s LevEvents_HTZ2_Routine2_Continue ; --------------------------------------------------------------------------- .keep_shaking: tst.b (HTZ_Terrain_Direction).w bne.s .sinking cmpi.w #$2C0,(Camera_BG_Y_offset).w beq.s .flip_delay move.w (Timer_frames).w,d0 move.w d0,d1 andi.w #3,d0 bne.s LevEvents_HTZ2_Routine2_Continue addq.w #1,(Camera_BG_Y_offset).w andi.w #$3F,d1 bne.s LevEvents_HTZ2_Routine2_Continue move.w #SndID_Rumbling2,d0 jsr (PlaySound).l bra.s LevEvents_HTZ2_Routine2_Continue ; --------------------------------------------------------------------------- .sinking: cmpi.w #0,(Camera_BG_Y_offset).w beq.s .flip_delay move.w (Timer_frames).w,d0 move.w d0,d1 andi.w #3,d0 bne.s LevEvents_HTZ2_Routine2_Continue subq.w #1,(Camera_BG_Y_offset).w andi.w #$3F,d1 bne.s LevEvents_HTZ2_Routine2_Continue move.w #SndID_Rumbling2,d0 jsr (PlaySound).l bra.s LevEvents_HTZ2_Routine2_Continue ; --------------------------------------------------------------------------- .flip_delay: move.b #0,(Screen_Shaking_Flag).w subq.w #1,(HTZ_Terrain_Delay).w bpl.s LevEvents_HTZ2_Routine2_Continue move.w #$78,(HTZ_Terrain_Delay).w eori.b #1,(HTZ_Terrain_Direction).w move.b #1,(Screen_Shaking_Flag).w ; loc_ED22: LevEvents_HTZ2_Routine2_Continue: cmpi.w #$14C0,(Camera_X_pos).w blo.s .exit_left cmpi.w #$1B00,(Camera_X_pos).w bhs.s .exit_right move.w (Camera_X_pos_diff).w,(Camera_BG_X_pos_diff).w move.w (Camera_Y_pos_diff).w,(Camera_BG_Y_pos_diff).w move.w (Camera_X_pos).w,d0 move.w (Camera_Y_pos).w,d1 bra.w ScrollBG ; --------------------------------------------------------------------------- .exit_left: move.l #$4000000,(Camera_BG_X_pos).w moveq #0,d0 move.l d0,(Camera_BG_Y_pos).w move.l d0,(Camera_BG_X_offset).w move.b d0,(HTZ_Terrain_Direction).w subq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine1 move.w #MusID_StopSFX,d0 jsr (PlaySound).l rts ; --------------------------------------------------------------------------- .exit_right: move.l #$4000000,(Camera_BG_X_pos).w moveq #0,d0 move.l d0,(Camera_BG_Y_pos).w move.l d0,(Camera_BG_X_offset).w move.b d0,(HTZ_Terrain_Direction).w addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine3 move.w #MusID_StopSFX,d0 jsr (PlaySound).l rts ; =========================================================================== ; loc_ED96: LevEvents_HTZ2_Routine3: cmpi.w #$1B00,(Camera_X_pos).w bhs.s LevEvents_HTZ2_Routine3_Part2 move.b #1,(Screen_Shaking_Flag_HTZ).w move.l (Camera_X_pos).w,(Camera_BG_X_pos).w move.l (Camera_Y_pos).w,(Camera_BG_Y_pos).w moveq #0,d0 move.w d0,(Camera_BG_X_pos_diff).w move.w d0,(Camera_BG_Y_pos_diff).w move.w d0,(Camera_BG_X_offset).w move.w #$2C0,(Camera_BG_Y_offset).w subi.w #$100,(Camera_BG_Y_pos).w move.w #0,(HTZ_Terrain_Delay).w subq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine2 - rts ; =========================================================================== LevEvents_HTZ2_Routine3_Part2: tst.b (Screen_Shaking_Flag_HTZ).w beq.s - ; rts move.w #$200,d0 moveq #0,d1 move.w d1,(Camera_BG_X_pos_diff).w move.w d1,(Camera_BG_Y_pos_diff).w bsr.w ScrollBG or.w d0,d1 bne.s - ; rts move.b #0,(Screen_Shaking_Flag_HTZ).w rts ; =========================================================================== ; loc_EDFA: LevEvents_HTZ2_Routine4: cmpi.w #$15F0,(Camera_X_pos).w blo.w LevEvents_HTZ2_Routine4_Continue cmpi.w #$1AC0,(Camera_X_pos).w bhs.s LevEvents_HTZ2_Routine4_Continue tst.b (HTZ_Terrain_Direction).w bne.s .sinking cmpi.w #$300,(Camera_BG_Y_offset).w beq.s .flip_delay move.w (Timer_frames).w,d0 move.w d0,d1 andi.w #3,d0 bne.s LevEvents_HTZ2_Routine4_Continue addq.w #1,(Camera_BG_Y_offset).w andi.w #$3F,d1 bne.s LevEvents_HTZ2_Routine4_Continue move.w #SndID_Rumbling2,d0 jsr (PlaySound).l bra.s LevEvents_HTZ2_Routine4_Continue ; =========================================================================== .sinking: cmpi.w #0,(Camera_BG_Y_offset).w beq.s .flip_delay move.w (Timer_frames).w,d0 move.w d0,d1 andi.w #3,d0 bne.s LevEvents_HTZ2_Routine4_Continue subq.w #1,(Camera_BG_Y_offset).w andi.w #$3F,d1 bne.s LevEvents_HTZ2_Routine4_Continue move.w #SndID_Rumbling2,d0 jsr (PlaySound).l bra.s LevEvents_HTZ2_Routine4_Continue ; =========================================================================== .flip_delay: move.b #0,(Screen_Shaking_Flag).w subq.w #1,(HTZ_Terrain_Delay).w bpl.s LevEvents_HTZ2_Routine4_Continue move.w #$78,(HTZ_Terrain_Delay).w eori.b #1,(HTZ_Terrain_Direction).w move.b #1,(Screen_Shaking_Flag).w LevEvents_HTZ2_Routine4_Continue: cmpi.w #$14C0,(Camera_X_pos).w blo.s .exit_left cmpi.w #$1B00,(Camera_X_pos).w bhs.s .exit_right move.w (Camera_X_pos_diff).w,(Camera_BG_X_pos_diff).w move.w (Camera_Y_pos_diff).w,(Camera_BG_Y_pos_diff).w move.w (Camera_X_pos).w,d0 move.w (Camera_Y_pos).w,d1 bra.w ScrollBG ; =========================================================================== .exit_left: move.l #$4000000,(Camera_BG_X_pos).w moveq #0,d0 move.l d0,(Camera_BG_Y_pos).w move.l d0,(Camera_BG_X_offset).w move.b d0,(HTZ_Terrain_Direction).w subq.b #6,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine1 move.w #MusID_StopSFX,d0 jsr (PlaySound).l rts ; =========================================================================== .exit_right: move.l #$4000000,(Camera_BG_X_pos).w moveq #0,d0 move.l d0,(Camera_BG_Y_pos).w move.l d0,(Camera_BG_X_offset).w move.b d0,(HTZ_Terrain_Direction).w addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine5 move.w #MusID_StopSFX,d0 jsr (PlaySound).l rts ; =========================================================================== ; loc_EEF8: LevEvents_HTZ2_Routine5: cmpi.w #$1B00,(Camera_X_pos).w bhs.s LevEvents_HTZ2_Routine5_Part2 move.b #1,(Screen_Shaking_Flag_HTZ).w move.l (Camera_X_pos).w,(Camera_BG_X_pos).w move.l (Camera_Y_pos).w,(Camera_BG_Y_pos).w moveq #0,d0 move.w d0,(Camera_BG_X_pos_diff).w move.w d0,(Camera_BG_Y_pos_diff).w move.w #-$680,(Camera_BG_X_offset).w addi.w #$480,(Camera_BG_X_pos).w move.w #$300,(Camera_BG_Y_offset).w subi.w #$100,(Camera_BG_Y_pos).w move.w #0,(HTZ_Terrain_Delay).w subq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine4 - rts ; =========================================================================== LevEvents_HTZ2_Routine5_Part2: tst.b (Screen_Shaking_Flag_HTZ).w beq.s - ; rts move.w #$200,d0 moveq #0,d1 move.w d1,(Camera_BG_X_pos_diff).w move.w d1,(Camera_BG_Y_pos_diff).w bsr.w ScrollBG or.w d0,d1 bne.s - ; rts move.b #0,(Screen_Shaking_Flag_HTZ).w rts ; =========================================================================== rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_EF66: LevEvents_HTZ2_Prepare: cmpi.w #$2B00,(Camera_X_pos).w blo.s + ; rts cmpi.b #$A,(Dynamic_Resize_Routine).w bge.s + ; rts move.b #$A,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine6 move.b #0,(Screen_Shaking_Flag_HTZ).w + rts ; End of function LevEvents_HTZ2_Prepare ; =========================================================================== ; loc_EF84: LevEvents_HTZ2_Routine6: cmpi.w #$2C50,(Camera_X_pos).w blo.s + ; rts move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w move.w #$480,(Camera_Max_Y_pos).w move.w #$480,(Tails_Max_Y_pos).w addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine7 + rts ; =========================================================================== ; loc_EFAA: LevEvents_HTZ2_Routine7: cmpi.w #$2EDF,(Camera_X_pos).w blo.s + ; rts move.w #$2EE0,(Camera_Min_X_pos).w move.w #$2F5E,(Camera_Max_X_pos).w move.w #$2EE0,(Tails_Min_X_pos).w move.w #$2F5E,(Tails_Max_X_pos).w addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine8 move.w #MusID_FadeOut,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic clr.b (ScreenShift).w move.b #3,(Current_Boss_ID).w moveq #PLCID_HtzBoss,d0 jmpto (LoadPLC).l, JmpTo2_LoadPLC ; =========================================================================== + rts ; =========================================================================== ; loc_EFE8: LevEvents_HTZ2_Routine8: cmpi.w #$478,(Camera_Y_pos).w blo.s + move.w #$478,(Camera_Min_Y_pos).w move.w #$478,(Tails_Min_Y_pos).w + addq.b #1,(ScreenShift).w cmpi.b #$5A,(ScreenShift).w blo.s ++ ; rts jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad bne.s + move.b #ObjID_HTZBoss,id(a1) ; load obj52 (HTZ boss) + addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine9 move.w #MusID_Boss,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic + rts ; =========================================================================== ; loc_F020: LevEvents_HTZ2_Routine9: tst.b (Boss_defeated_flag).w beq.s ++ ; rts move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w cmpi.w #$30E0,(Camera_X_pos).w blo.s ++ ; rts cmpi.w #$428,(Camera_Min_Y_pos).w blo.s + subq.w #2,(Camera_Min_Y_pos).w + cmpi.w #$430,(Camera_Max_Y_pos).w blo.s + subq.w #2,(Camera_Max_Y_pos).w + rts ; =========================================================================== ; return_F05A: LevEvents_HPZ: rts ; =========================================================================== ; return_F05C: LevEvents_009: rts ; =========================================================================== ; loc_F05E: LevEvents_OOZ: tst.b (Current_Act).w bne.s LevEvents_OOZ2 rts ; --------------------------------------------------------------------------- ; loc_F066: LevEvents_OOZ2: moveq #0,d0 move.b (Dynamic_Resize_Routine).w,d0 move.w LevEvents_OOZ2_Index(pc,d0.w),d0 jmp LevEvents_OOZ2_Index(pc,d0.w) ; =========================================================================== ; off_F074: LevEvents_OOZ2_Index: offsetTable offsetTableEntry.w LevEvents_OOZ2_Routine1 ; 0 offsetTableEntry.w LevEvents_OOZ2_Routine2 ; 2 offsetTableEntry.w LevEvents_OOZ2_Routine3 ; 4 offsetTableEntry.w LevEvents_OOZ2_Routine4 ; 6 ; =========================================================================== ; loc_F07C: LevEvents_OOZ2_Routine1: cmpi.w #$2668,(Camera_X_pos).w blo.s + ; rts move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w move.w #$2D8,(Oil+y_pos).w move.w #$1E0,(Camera_Max_Y_pos).w move.w #$1E0,(Tails_Max_Y_pos).w addq.b #2,(Dynamic_Resize_Routine).w + rts ; =========================================================================== ; loc_F0A8: LevEvents_OOZ2_Routine2: cmpi.w #$2880,(Camera_X_pos).w blo.s + ; rts move.w #$2880,(Camera_Min_X_pos).w move.w #$28C0,(Camera_Max_X_pos).w move.w #$2880,(Tails_Min_X_pos).w move.w #$28C0,(Tails_Max_X_pos).w addq.b #2,(Dynamic_Resize_Routine).w move.w #MusID_FadeOut,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic clr.b (ScreenShift).w move.b #8,(Current_Boss_ID).w moveq #PLCID_OozBoss,d0 jsrto (LoadPLC).l, JmpTo2_LoadPLC moveq #PalID_OOZ_B,d0 jsrto (PalLoad_Now).l, JmpTo2_PalLoad_Now + rts ; =========================================================================== ; loc_F0EC: LevEvents_OOZ2_Routine3: cmpi.w #$1D8,(Camera_Y_pos).w blo.s + move.w #$1D8,(Camera_Min_Y_pos).w move.w #$1D8,(Tails_Min_Y_pos).w + addq.b #1,(ScreenShift).w cmpi.b #$5A,(ScreenShift).w blo.s ++ ; rts jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad bne.s + move.b #ObjID_OOZBoss,id(a1) ; load obj55 (OOZ boss) + addq.b #2,(Dynamic_Resize_Routine).w move.w #MusID_Boss,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic + rts ; =========================================================================== ; loc_F124: LevEvents_OOZ2_Routine4: tst.b (Boss_defeated_flag).w beq.s + ; rts move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w + rts ; =========================================================================== ; loc_F13E: LevEvents_MCZ: tst.b (Current_Act).w bne.s LevEvents_MCZ2 rts ; --------------------------------------------------------------------------- ; loc_F146: LevEvents_MCZ2: moveq #0,d0 move.b (Dynamic_Resize_Routine).w,d0 move.w LevEvents_MCZ2_Index(pc,d0.w),d0 jmp LevEvents_MCZ2_Index(pc,d0.w) ; =========================================================================== ; off_F154: LevEvents_MCZ2_Index: offsetTable offsetTableEntry.w LevEvents_MCZ2_Routine1 ; 0 offsetTableEntry.w LevEvents_MCZ2_Routine2 ; 2 offsetTableEntry.w LevEvents_MCZ2_Routine3 ; 4 offsetTableEntry.w LevEvents_MCZ2_Routine4 ; 6 ; =========================================================================== ; loc_F15C: LevEvents_MCZ2_Routine1: tst.w (Two_player_mode).w bne.s ++ cmpi.w #$2080,(Camera_X_pos).w blo.s + ; rts move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w move.w #$5D0,(Camera_Max_Y_pos).w move.w #$5D0,(Tails_Max_Y_pos).w addq.b #2,(Dynamic_Resize_Routine).w + rts ; --------------------------------------------------------------------------- + move.w #$2100,(Camera_Max_X_pos).w move.w #$2100,(Tails_Max_X_pos).w rts ; =========================================================================== ; loc_F196: LevEvents_MCZ2_Routine2: cmpi.w #$20F0,(Camera_X_pos).w blo.s + ; rts move.w #$20F0,(Camera_Max_X_pos).w move.w #$20F0,(Camera_Min_X_pos).w move.w #$20F0,(Tails_Max_X_pos).w move.w #$20F0,(Tails_Min_X_pos).w addq.b #2,(Dynamic_Resize_Routine).w move.w #MusID_FadeOut,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic clr.b (ScreenShift).w move.l #vdpComm(tiles_to_bytes(ArtTile_ArtUnc_FallingRocks),VRAM,WRITE),(VDP_control_port).l lea (VDP_data_port).l,a6 lea (ArtUnc_FallingRocks).l,a2 moveq #7,d0 - rept 8 move.l (a2)+,(a6) endm dbf d0,- move.b #5,(Current_Boss_ID).w moveq #PLCID_MczBoss,d0 jsrto (LoadPLC).l, JmpTo2_LoadPLC moveq #PalID_MCZ_B,d0 jsrto (PalLoad_Now).l, JmpTo2_PalLoad_Now + rts ; =========================================================================== ; loc_F206: LevEvents_MCZ2_Routine3: cmpi.w #$5C8,(Camera_Y_pos).w blo.s + move.w #$5C8,(Camera_Min_Y_pos).w move.w #$5C8,(Tails_Min_Y_pos).w + addq.b #1,(ScreenShift).w cmpi.b #$5A,(ScreenShift).w blo.s ++ ; rts jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad bne.s + move.b #ObjID_MCZBoss,id(a1) ; load obj57 (MCZ boss) + addq.b #2,(Dynamic_Resize_Routine).w move.w #MusID_Boss,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic + rts ; =========================================================================== ; loc_F23E: LevEvents_MCZ2_Routine4: tst.b (Screen_Shaking_Flag).w beq.s + move.w (Timer_frames).w,d0 andi.w #$1F,d0 bne.s + move.w #SndID_Rumbling2,d0 jsrto (PlaySound).l, JmpTo3_PlaySound + move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w rts ; =========================================================================== ; loc_F26A: LevEvents_CNZ: jsr (SlotMachine).l tst.b (Current_Act).w bne.s LevEvents_CNZ2 rts ; no events for act 1 ; =========================================================================== ; loc_F278: LevEvents_CNZ2: moveq #0,d0 move.b (Dynamic_Resize_Routine).w,d0 move.w LevEvents_CNZ2_Index(pc,d0.w),d0 jmp LevEvents_CNZ2_Index(pc,d0.w) ; =========================================================================== ; off_F286: LevEvents_CNZ2_Index: offsetTable offsetTableEntry.w LevEvents_CNZ2_Routine1 ; 0 offsetTableEntry.w LevEvents_CNZ2_Routine2 ; 2 offsetTableEntry.w LevEvents_CNZ2_Routine3 ; 4 offsetTableEntry.w LevEvents_CNZ2_Routine4 ; 6 ; =========================================================================== ; loc_F28E: LevEvents_CNZ2_Routine1: tst.w (Two_player_mode).w bne.s ++ cmpi.w #$27C0,(Camera_X_pos).w blo.s + ; rts move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w move.w #$62E,(Camera_Max_Y_pos).w move.w #$62E,(Tails_Max_Y_pos).w move.b #$F9,(Level_Layout+$C54).w addq.b #2,(Dynamic_Resize_Routine).w + rts ; =========================================================================== + move.w #$26A0,(Camera_Max_X_pos).w move.w #$26A0,(Tails_Max_X_pos).w rts ; =========================================================================== ; loc_F2CE: LevEvents_CNZ2_Routine2: cmpi.w #$2890,(Camera_X_pos).w blo.s + ; rts move.b #$F9,(Level_Layout+$C50).w move.w #$2860,(Camera_Min_X_pos).w move.w #$28E0,(Camera_Max_X_pos).w move.w #$2860,(Tails_Min_X_pos).w move.w #$28E0,(Tails_Max_X_pos).w addq.b #2,(Dynamic_Resize_Routine).w move.w #MusID_FadeOut,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic clr.b (ScreenShift).w move.b #6,(Current_Boss_ID).w moveq #PLCID_CnzBoss,d0 jsrto (LoadPLC).l, JmpTo2_LoadPLC moveq #PalID_CNZ_B,d0 jsrto (PalLoad_Now).l, JmpTo2_PalLoad_Now + rts ; =========================================================================== ; loc_F318: LevEvents_CNZ2_Routine3: cmpi.w #$4E0,(Camera_Y_pos).w blo.s + move.w #$4E0,(Camera_Min_Y_pos).w move.w #$4E0,(Tails_Min_Y_pos).w + addq.b #1,(ScreenShift).w cmpi.b #$5A,(ScreenShift).w blo.s ++ ; rts jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad bne.s + move.b #ObjID_CNZBoss,id(a1) ; load obj51 + addq.b #2,(Dynamic_Resize_Routine).w move.w #MusID_Boss,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic + rts ; =========================================================================== ; loc_F350: LevEvents_CNZ2_Routine4: cmpi.w #$2A00,(Camera_X_pos).w blo.s + ; rts move.w #$5D0,(Camera_Max_Y_pos).w move.w #$5D0,(Tails_Max_Y_pos).w move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w + rts ; =========================================================================== ; loc_F378: LevEvents_CPZ: tst.b (Current_Act).w bne.s LevEvents_CPZ2 rts ; =========================================================================== ; loc_F380: LevEvents_CPZ2: moveq #0,d0 move.b (Dynamic_Resize_Routine).w,d0 move.w LevEvents_CPZ2_Index(pc,d0.w),d0 jmp LevEvents_CPZ2_Index(pc,d0.w) ; =========================================================================== ; off_F38E: LevEvents_CPZ2_Index: offsetTable offsetTableEntry.w LevEvents_CPZ2_Routine1 ; 0 offsetTableEntry.w LevEvents_CPZ2_Routine2 ; 2 offsetTableEntry.w LevEvents_CPZ2_Routine3 ; 4 offsetTableEntry.w LevEvents_CPZ2_Routine4 ; 6 ; =========================================================================== ; loc_F396: LevEvents_CPZ2_Routine1: cmpi.w #$2680,(Camera_X_pos).w blo.s + ; rts move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w move.w #$450,(Camera_Max_Y_pos).w move.w #$450,(Tails_Max_Y_pos).w addq.b #2,(Dynamic_Resize_Routine).w + rts ; =========================================================================== ; loc_F3BC: LevEvents_CPZ2_Routine2: cmpi.w #$2A20,(Camera_X_pos).w blo.s + ; rts move.w #$2A20,(Camera_Min_X_pos).w move.w #$2A20,(Camera_Max_X_pos).w move.w #$2A20,(Tails_Min_X_pos).w move.w #$2A20,(Tails_Max_X_pos).w addq.b #2,(Dynamic_Resize_Routine).w move.w #MusID_FadeOut,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic clr.b (ScreenShift).w move.b #1,(Current_Boss_ID).w moveq #PLCID_CpzBoss,d0 jmpto (LoadPLC).l, JmpTo2_LoadPLC ; =========================================================================== + rts ; =========================================================================== ; loc_F3FA: LevEvents_CPZ2_Routine3: cmpi.w #$448,(Camera_Y_pos).w blo.s + move.w #$448,(Camera_Min_Y_pos).w move.w #$448,(Tails_Min_Y_pos).w + addq.b #1,(ScreenShift).w cmpi.b #$5A,(ScreenShift).w blo.s ++ jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad bne.s + move.b #ObjID_CPZBoss,id(a1) ; load obj5D + addq.b #2,(Dynamic_Resize_Routine).w move.w #MusID_Boss,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic + rts ; =========================================================================== ; loc_F432: LevEvents_CPZ2_Routine4: move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w rts ; =========================================================================== ; loc_F446: LevEvents_DEZ: moveq #0,d0 move.b (Dynamic_Resize_Routine).w,d0 move.w LevEvents_DEZ_Index(pc,d0.w),d0 jmp LevEvents_DEZ_Index(pc,d0.w) ; =========================================================================== ; off_F454: LevEvents_DEZ_Index: offsetTable offsetTableEntry.w LevEvents_DEZ_Routine1 ; 0 offsetTableEntry.w LevEvents_DEZ_Routine2 ; 2 offsetTableEntry.w LevEvents_DEZ_Routine3 ; 4 offsetTableEntry.w LevEvents_DEZ_Routine4 ; 6 offsetTableEntry.w LevEvents_DEZ_Routine5 ; 8 ; =========================================================================== ; loc_F45E: LevEvents_DEZ_Routine1: move.w #320,d0 cmp.w (Camera_X_pos).w,d0 bhi.s + ; rts addq.b #2,(Dynamic_Resize_Routine).w jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad bne.s + ; rts move.b #ObjID_MechaSonic,id(a1) ; load objAF (silver sonic) move.b #$48,subtype(a1) move.w #$348,x_pos(a1) move.w #$A0,y_pos(a1) moveq #PLCID_FieryExplosion,d0 jmpto (LoadPLC).l, JmpTo2_LoadPLC ; =========================================================================== + rts ; =========================================================================== ; return_F490: LevEvents_DEZ_Routine2: rts ; =========================================================================== ; loc_F492: LevEvents_DEZ_Routine3: move.w (Camera_X_pos).w,(Camera_Min_X_pos).w cmpi.w #$300,(Camera_X_pos).w blo.s + ; rts addq.b #2,(Dynamic_Resize_Routine).w moveq #PLCID_DezBoss,d0 jmpto (LoadPLC).l, JmpTo2_LoadPLC ; =========================================================================== + rts ; =========================================================================== ; loc_F4AC: LevEvents_DEZ_Routine4: move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w #$680,d0 cmp.w (Camera_X_pos).w,d0 bhi.s + ; rts addq.b #2,(Dynamic_Resize_Routine).w move.w d0,(Camera_Min_X_pos).w addi.w #$C0,d0 move.w d0,(Camera_Max_X_pos).w + rts ; =========================================================================== ; return_F4CE: LevEvents_DEZ_Routine5: rts ; =========================================================================== ; loc_F4D0: LevEvents_ARZ: tst.b (Current_Act).w bne.s LevEvents_ARZ2 rts ; =========================================================================== ; loc_F4D8: LevEvents_ARZ2: moveq #0,d0 move.b (Dynamic_Resize_Routine).w,d0 move.w LevEvents_ARZ2_Index(pc,d0.w),d0 jmp LevEvents_ARZ2_Index(pc,d0.w) ; =========================================================================== ; off_F4E6: LevEvents_ARZ2_Index: offsetTable offsetTableEntry.w LevEvents_ARZ2_Routine1 ; 0 offsetTableEntry.w LevEvents_ARZ2_Routine2 ; 2 offsetTableEntry.w LevEvents_ARZ2_Routine3 ; 4 offsetTableEntry.w LevEvents_ARZ2_Routine4 ; 6 ; =========================================================================== ; loc_F4EE: LevEvents_ARZ2_Routine1: cmpi.w #$2810,(Camera_X_pos).w blo.s + ; rts move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w move.w #$400,(Camera_Max_Y_pos).w move.w #$400,(Tails_Max_Y_pos).w addq.b #2,(Dynamic_Resize_Routine).w move.b #4,(Current_Boss_ID).w moveq #PLCID_ArzBoss,d0 jsrto (LoadPLC).l, JmpTo2_LoadPLC + rts ; =========================================================================== ; loc_F520: LevEvents_ARZ2_Routine2: cmpi.w #$2A40,(Camera_X_pos).w blo.s + ; rts move.w #$2A40,(Camera_Max_X_pos).w move.w #$2A40,(Camera_Min_X_pos).w move.w #$2A40,(Tails_Max_X_pos).w move.w #$2A40,(Tails_Min_X_pos).w addq.b #2,(Dynamic_Resize_Routine).w move.w #MusID_FadeOut,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic clr.b (ScreenShift).w jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad bne.s + ; rts move.b #ObjID_ARZBoss,id(a1) ; load obj89 + rts ; =========================================================================== ; loc_F55C: LevEvents_ARZ2_Routine3: cmpi.w #$3F8,(Camera_Y_pos).w blo.s + move.w #$3F8,(Camera_Min_Y_pos).w move.w #$3F8,(Tails_Min_Y_pos).w + addq.b #1,(ScreenShift).w cmpi.b #$5A,(ScreenShift).w blo.s + ; rts addq.b #2,(Dynamic_Resize_Routine).w move.w #MusID_Boss,d0 jsrto (PlayMusic).l, JmpTo3_PlayMusic + rts ; =========================================================================== ; loc_F58A: LevEvents_ARZ2_Routine4: move.w (Camera_X_pos).w,(Camera_Min_X_pos).w move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w move.w (Camera_X_pos).w,(Tails_Min_X_pos).w rts ; =========================================================================== ; loc_F59E: LevEvents_SCZ: tst.b (Current_Act).w bne.w LevEvents_SCZ2 moveq #0,d0 move.b (Dynamic_Resize_Routine).w,d0 move.w LevEvents_SCZ_Index(pc,d0.w),d0 jmp LevEvents_SCZ_Index(pc,d0.w) ; =========================================================================== ; off_F5B4: LevEvents_SCZ_Index: offsetTable offsetTableEntry.w LevEvents_SCZ_Routine1 ; 0 offsetTableEntry.w LevEvents_SCZ_Routine2 ; 2 offsetTableEntry.w LevEvents_SCZ_Routine3 ; 4 offsetTableEntry.w LevEvents_SCZ_Routine4 ; 6 offsetTableEntry.w LevEvents_SCZ_RoutineNull ; 8 ; =========================================================================== ; loc_F5BE: LevEvents_SCZ_Routine1: move.w #1,(Tornado_Velocity_X).w move.w #0,(Tornado_Velocity_Y).w addq.b #2,(Dynamic_Resize_Routine).w rts ; =========================================================================== ; loc_F5D0: LevEvents_SCZ_Routine2: cmpi.w #$1180,(Camera_X_pos).w blo.s + move.w #-1,(Tornado_Velocity_X).w move.w #1,(Tornado_Velocity_Y).w move.w #$500,(Camera_Max_Y_pos).w addq.b #2,(Dynamic_Resize_Routine).w + rts ; =========================================================================== ; loc_F5F0: LevEvents_SCZ_Routine3: cmpi.w #$500,(Camera_Y_pos).w blo.s + move.w #1,(Tornado_Velocity_X).w move.w #0,(Tornado_Velocity_Y).w addq.b #2,(Dynamic_Resize_Routine).w + rts ; =========================================================================== ; loc_F60A: LevEvents_SCZ_Routine4: cmpi.w #$1400,(Camera_X_pos).w blo.s LevEvents_SCZ_RoutineNull move.w #0,(Tornado_Velocity_X).w move.w #0,(Tornado_Velocity_Y).w addq.b #2,(Dynamic_Resize_Routine).w ; return_F622: LevEvents_SCZ_RoutineNull: rts ; =========================================================================== ; return_F624: LevEvents_SCZ2: rts ; =========================================================================== ; loc_F626: PlayLevelMusic: move.w (Level_Music).w,d0 jmpto (PlayMusic).l, JmpTo3_PlayMusic ; =========================================================================== ; loc_F62E: LoadPLC_AnimalExplosion: moveq #0,d0 move.b (Current_Zone).w,d0 lea (Animal_PLCTable).l,a2 move.b (a2,d0.w),d0 jsrto (LoadPLC).l, JmpTo2_LoadPLC moveq #PLCID_Explosion,d0 jsrto (LoadPLC).l, JmpTo2_LoadPLC rts ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo_SingleObjLoad jmp (SingleObjLoad).l JmpTo3_PlaySound jmp (PlaySound).l ; JmpTo2_PalLoad2 JmpTo2_PalLoad_Now jmp (PalLoad_Now).l JmpTo2_LoadPLC jmp (LoadPLC).l JmpTo3_PlayMusic jmp (PlayMusic).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 11 - Bridge in Emerald Hill Zone and Hidden Palace Zone ; ---------------------------------------------------------------------------- ; OST Variables: Obj11_child1 = objoff_30 ; pointer to first set of bridge segments Obj11_child2 = objoff_34 ; pointer to second set of bridge segments, if applicable ; Sprite_F66C: Obj11: btst #6,render_flags(a0) ; is this a child sprite object? bne.w + ; if yes, branch moveq #0,d0 move.b routine(a0),d0 move.w Obj11_Index(pc,d0.w),d1 jmp Obj11_Index(pc,d1.w) ; =========================================================================== + ; child sprite objects only need to be drawn move.w #$180,d0 bra.w DisplaySprite3 ; =========================================================================== ; off_F68C: Obj11_Index: offsetTable offsetTableEntry.w Obj11_Init ; 0 offsetTableEntry.w Obj11_EHZ ; 2 offsetTableEntry.w Obj11_Display ; 4 offsetTableEntry.w Obj11_HPZ ; 6 ; =========================================================================== ; loc_F694: Obj11_Main: Obj11_Init: addq.b #2,routine(a0) move.l #Obj11_MapUnc_FC70,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_EHZ_Bridge,2,0),art_tile(a0) move.b #3,priority(a0) cmpi.b #hidden_palace_zone,(Current_Zone).w ; is this an HPZ bridge? bne.s + ; if not, branch addq.b #4,routine(a0) move.l #Obj11_MapUnc_FC28,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_HPZ_Bridge,3,0),art_tile(a0) + bsr.w Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$80,width_pixels(a0) move.w y_pos(a0),d2 move.w d2,objoff_3C(a0) move.w x_pos(a0),d3 lea subtype(a0),a2 ; copy bridge subtype to a2 moveq #0,d1 move.b (a2),d1 ; d1 = subtype move.w d1,d0 lsr.w #1,d0 lsl.w #4,d0 ; (d0 div 2) * 16 sub.w d0,d3 ; x position of left half swap d1 ; store subtype in high word for later move.w #8,d1 bsr.s Obj11_MakeBdgSegment move.w sub6_x_pos(a1),d0 subq.w #8,d0 move.w d0,x_pos(a1) ; center of first subsprite object move.l a1,Obj11_child1(a0) ; pointer to first subsprite object swap d1 ; retrieve subtype subq.w #8,d1 bls.s + ; branch, if subtype <= 8 (bridge has no more than 8 logs) ; else, create a second subsprite object for the rest of the bridge move.w d1,d4 bsr.s Obj11_MakeBdgSegment move.l a1,Obj11_child2(a0) ; pointer to second subsprite object move.w d4,d0 add.w d0,d0 add.w d4,d0 ; d0*3 move.w sub2_x_pos(a1,d0.w),d0 subq.w #8,d0 move.w d0,x_pos(a1) ; center of second subsprite object + bra.s Obj11_EHZ ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_F728: Obj11_MakeBdgSegment: jsrto (SingleObjLoad2).l, JmpTo_SingleObjLoad2 bne.s + ; rts _move.b id(a0),id(a1) ; load obj11 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) move.b render_flags(a0),render_flags(a1) bset #6,render_flags(a1) move.b #$40,mainspr_width(a1) move.b d1,mainspr_childsprites(a1) subq.b #1,d1 lea sub2_x_pos(a1),a2 ; starting address for subsprite data - move.w d3,(a2)+ ; sub?_x_pos move.w d2,(a2)+ ; sub?_y_pos move.w #0,(a2)+ ; sub?_mapframe addi.w #$10,d3 ; width of a log, x_pos for next log dbf d1,- ; repeat for d1 logs + rts ; End of function Obj11_MakeBdgSegment ; =========================================================================== ; loc_F77A: Obj11_Action: Obj11_EHZ: move.b status(a0),d0 andi.b #standing_mask,d0 bne.s + tst.b objoff_3E(a0) beq.s loc_F7BC subq.b #4,objoff_3E(a0) bra.s loc_F7B8 + andi.b #p2_standing,d0 beq.s ++ move.b objoff_3F(a0),d0 sub.b objoff_3B(a0),d0 beq.s ++ bcc.s + addq.b #1,objoff_3F(a0) bra.s ++ ; --------------------------------------------------------------------------- + subq.b #1,objoff_3F(a0) + cmpi.b #$40,objoff_3E(a0) beq.s loc_F7B8 addq.b #4,objoff_3E(a0) loc_F7B8: bsr.w Obj11_Depress loc_F7BC: moveq #0,d1 move.b subtype(a0),d1 lsl.w #3,d1 move.w d1,d2 addq.w #8,d1 add.w d2,d2 moveq #8,d3 move.w x_pos(a0),d4 bsr.w sub_F872 ; loc_F7D4: Obj11_Unload: ; this is essentially MarkObjGone, except we need to delete our subsprite objects as well tst.w (Two_player_mode).w ; is it two player mode? beq.s + ; if not, branch rts ; --------------------------------------------------------------------------- + move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.s + rts ; --------------------------------------------------------------------------- + ; delete first subsprite object movea.l Obj11_child1(a0),a1 ; a1=object bsr.w DeleteObject2 cmpi.b #8,subtype(a0) bls.s + ; if bridge has more than 8 logs, delete second subsprite object movea.l Obj11_child2(a0),a1 ; a1=object bsr.w DeleteObject2 + bra.w DeleteObject ; =========================================================================== ; loc_F80C: BranchTo_DisplaySprite: Obj11_Display: bra.w DisplaySprite ; =========================================================================== ; loc_F810: Obj11_Action_HPZ: Obj11_HPZ: move.b status(a0),d0 andi.b #standing_mask,d0 bne.s + tst.b objoff_3E(a0) beq.s loc_F852 subq.b #4,objoff_3E(a0) bra.s loc_F84E ; =========================================================================== + andi.b #p2_standing,d0 beq.s ++ move.b objoff_3F(a0),d0 sub.b objoff_3B(a0),d0 beq.s ++ bcc.s + addq.b #1,objoff_3F(a0) bra.s ++ ; =========================================================================== + subq.b #1,objoff_3F(a0) + cmpi.b #$40,objoff_3E(a0) beq.s loc_F84E addq.b #4,objoff_3E(a0) loc_F84E: bsr.w Obj11_Depress loc_F852: moveq #0,d1 move.b subtype(a0),d1 lsl.w #3,d1 move.w d1,d2 addq.w #8,d1 add.w d2,d2 moveq #8,d3 move.w x_pos(a0),d4 bsr.w sub_F872 bsr.w sub_F912 bra.w Obj11_Unload ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_F872: lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 moveq #$3B,d5 movem.l d1-d4,-(sp) bsr.s + movem.l (sp)+,d1-d4 lea (MainCharacter).w,a1 ; a1=character subq.b #1,d6 moveq #$3F,d5 + btst d6,status(a0) beq.s loc_F8F0 btst #1,status(a1) bne.s + moveq #0,d0 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s + cmp.w d2,d0 blo.s ++ + bclr #3,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; =========================================================================== + lsr.w #4,d0 move.b d0,(a0,d5.w) movea.l Obj11_child1(a0),a2 cmpi.w #8,d0 blo.s + movea.l Obj11_child2(a0),a2 ; a2=object subi_.w #8,d0 + add.w d0,d0 move.w d0,d1 add.w d0,d0 add.w d1,d0 move.w sub2_y_pos(a2,d0.w),d0 subq.w #8,d0 moveq #0,d1 move.b y_radius(a1),d1 sub.w d1,d0 move.w d0,y_pos(a1) moveq #0,d4 rts ; =========================================================================== loc_F8F0: move.w d1,-(sp) jsrto (PlatformObject11_cont).l, JmpTo_PlatformObject11_cont move.w (sp)+,d1 btst d6,status(a0) beq.s + ; rts moveq #0,d0 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 lsr.w #4,d0 move.b d0,(a0,d5.w) + rts ; End of function sub_F872 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_F912: moveq #0,d0 tst.w (MainCharacter+x_vel).w bne.s + move.b (Vint_runcount+3).w,d0 andi.w #$1C,d0 lsr.w #1,d0 + moveq #0,d2 move.b byte_F950+1(pc,d0.w),d2 swap d2 move.b byte_F950(pc,d0.w),d2 moveq #0,d0 tst.w (Sidekick+x_vel).w bne.s + move.b (Vint_runcount+3).w,d0 andi.w #$1C,d0 lsr.w #1,d0 + moveq #0,d6 move.b byte_F950+1(pc,d0.w),d6 swap d6 move.b byte_F950(pc,d0.w),d6 bra.s + ; =========================================================================== byte_F950: dc.b 1, 2 dc.b 1, 2 ; 2 dc.b 1, 2 ; 4 dc.b 1, 2 ; 6 dc.b 0, 1 ; 8 dc.b 0, 0 ; 10 dc.b 0, 0 ; 12 dc.b 0, 1 ; 14 ; =========================================================================== + moveq #-2,d3 moveq #-2,d4 move.b status(a0),d0 andi.b #p1_standing,d0 beq.s + move.b objoff_3F(a0),d3 + move.b status(a0),d0 andi.b #p2_standing,d0 beq.s + move.b objoff_3B(a0),d4 + movea.l Obj11_child1(a0),a1 lea sub9_mapframe+next_subspr(a1),a2 lea sub2_mapframe(a1),a1 moveq #0,d1 move.b subtype(a0),d1 subq.b #1,d1 moveq #0,d5 - moveq #0,d0 subq.w #1,d3 cmp.b d3,d5 bne.s + move.w d2,d0 + addq.w #2,d3 cmp.b d3,d5 bne.s + move.w d2,d0 + subq.w #1,d3 subq.w #1,d4 cmp.b d4,d5 bne.s + move.w d6,d0 + addq.w #2,d4 cmp.b d4,d5 bne.s + move.w d6,d0 + subq.w #1,d4 cmp.b d3,d5 bne.s + swap d2 move.w d2,d0 swap d2 + cmp.b d4,d5 bne.s + swap d6 move.w d6,d0 swap d6 + move.b d0,(a1) addq.w #1,d5 addq.w #6,a1 cmpa.w a2,a1 bne.s + movea.l Obj11_child2(a0),a1 ; a1=object lea sub2_mapframe(a1),a1 + dbf d1,- rts ; End of function sub_F912 ; =========================================================================== ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; subroutine to make the bridge push down where Sonic or Tails walks over ; loc_F9E8: Obj11_Depress: move.b objoff_3E(a0),d0 jsrto (CalcSine).l, JmpTo_CalcSine move.w d0,d4 lea (byte_FB28).l,a4 moveq #0,d0 move.b subtype(a0),d0 lsl.w #4,d0 moveq #0,d3 move.b objoff_3F(a0),d3 move.w d3,d2 add.w d0,d3 moveq #0,d5 lea (Obj11_DepressionOffsets-$80).l,a5 move.b (a5,d3.w),d5 andi.w #$F,d3 lsl.w #4,d3 lea (a4,d3.w),a3 movea.l Obj11_child1(a0),a1 lea sub9_y_pos+next_subspr(a1),a2 lea sub2_y_pos(a1),a1 - moveq #0,d0 move.b (a3)+,d0 addq.w #1,d0 mulu.w d5,d0 mulu.w d4,d0 swap d0 add.w objoff_3C(a0),d0 move.w d0,(a1) addq.w #6,a1 cmpa.w a2,a1 bne.s + movea.l Obj11_child2(a0),a1 ; a1=object lea sub2_y_pos(a1),a1 + dbf d2,- moveq #0,d0 move.b subtype(a0),d0 moveq #0,d3 move.b objoff_3F(a0),d3 addq.b #1,d3 sub.b d0,d3 neg.b d3 bmi.s ++ ; rts move.w d3,d2 lsl.w #4,d3 lea (a4,d3.w),a3 adda.w d2,a3 subq.w #1,d2 bcs.s ++ ; rts - moveq #0,d0 move.b -(a3),d0 addq.w #1,d0 mulu.w d5,d0 mulu.w d4,d0 swap d0 add.w objoff_3C(a0),d0 move.w d0,(a1) addq.w #6,a1 cmpa.w a2,a1 bne.s + movea.l Obj11_child2(a0),a1 ; a1=object lea sub2_y_pos(a1),a1 + dbf d2,- + rts ; =========================================================================== ; seems to be bridge piece vertical position offset data Obj11_DepressionOffsets: ; byte_FA98: dc.b 2, 4, 6, 8, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0; 16 dc.b 2, 4, 6, 8, $A, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0; 32 dc.b 2, 4, 6, 8, $A, $A, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0; 48 dc.b 2, 4, 6, 8, $A, $C, $A, 8, 6, 4, 2, 0, 0, 0, 0, 0; 64 dc.b 2, 4, 6, 8, $A, $C, $C, $A, 8, 6, 4, 2, 0, 0, 0, 0; 80 dc.b 2, 4, 6, 8, $A, $C, $E, $C, $A, 8, 6, 4, 2, 0, 0, 0; 96 dc.b 2, 4, 6, 8, $A, $C, $E, $E, $C, $A, 8, 6, 4, 2, 0, 0; 112 dc.b 2, 4, 6, 8, $A, $C, $E,$10, $E, $C, $A, 8, 6, 4, 2, 0; 128 dc.b 2, 4, 6, 8, $A, $C, $E,$10,$10, $E, $C, $A, 8, 6, 4, 2; 144 ; something else important for bridge depression to work (phase? bridge size adjustment?) byte_FB28: dc.b $FF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 16 dc.b $B5,$FF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 32 dc.b $7E,$DB,$FF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 48 dc.b $61,$B5,$EC,$FF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 64 dc.b $4A,$93,$CD,$F3,$FF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 80 dc.b $3E,$7E,$B0,$DB,$F6,$FF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 96 dc.b $38,$6D,$9D,$C5,$E4,$F8,$FF, 0, 0, 0, 0, 0, 0, 0, 0, 0; 112 dc.b $31,$61,$8E,$B5,$D4,$EC,$FB,$FF, 0, 0, 0, 0, 0, 0, 0, 0; 128 dc.b $2B,$56,$7E,$A2,$C1,$DB,$EE,$FB,$FF, 0, 0, 0, 0, 0, 0, 0; 144 dc.b $25,$4A,$73,$93,$B0,$CD,$E1,$F3,$FC,$FF, 0, 0, 0, 0, 0, 0; 160 dc.b $1F,$44,$67,$88,$A7,$BD,$D4,$E7,$F4,$FD,$FF, 0, 0, 0, 0, 0; 176 dc.b $1F,$3E,$5C,$7E,$98,$B0,$C9,$DB,$EA,$F6,$FD,$FF, 0, 0, 0, 0; 192 dc.b $19,$38,$56,$73,$8E,$A7,$BD,$D1,$E1,$EE,$F8,$FE,$FF, 0, 0, 0; 208 dc.b $19,$38,$50,$6D,$83,$9D,$B0,$C5,$D8,$E4,$F1,$F8,$FE,$FF, 0, 0; 224 dc.b $19,$31,$4A,$67,$7E,$93,$A7,$BD,$CD,$DB,$E7,$F3,$F9,$FE,$FF, 0; 240 dc.b $19,$31,$4A,$61,$78,$8E,$A2,$B5,$C5,$D4,$E1,$EC,$F4,$FB,$FE,$FF; 256 ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj11_MapUnc_FC28: BINCLUDE "mappings/sprite/obj11_a.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj11_MapUnc_FC70: BINCLUDE "mappings/sprite/obj11_b.bin" ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| if ~~removeJmpTos ; sub_FC88: JmpTo_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo_PlatformObject11_cont jmp (PlatformObject11_cont).l ; sub_FC94: JmpTo_CalcSine jmp (CalcSine).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 15 - Swinging platform from Aquatic Ruin Zone ; ---------------------------------------------------------------------------- ; Sprite_FC9C: Obj15: btst #6,render_flags(a0) bne.w + moveq #0,d0 move.b routine(a0),d0 move.w Obj15_Index(pc,d0.w),d1 jmp Obj15_Index(pc,d1.w) ; --------------------------------------------------------------------------- + move.w #$200,d0 bra.w DisplaySprite3 ; =========================================================================== ; off_FCBC: Obj15_States: Obj15_Index: offsetTable offsetTableEntry.w Obj15_Init ; 0 offsetTableEntry.w Obj15_State2 ; 2 offsetTableEntry.w Obj15_Display ; 4 offsetTableEntry.w Obj15_State4 ; 6 offsetTableEntry.w Obj15_State5 ; 8 offsetTableEntry.w Obj15_State6 ; $A offsetTableEntry.w Obj15_State7 ; $C ; =========================================================================== ; loc_FCCA: Obj15_Init: addq.b #2,routine(a0) move.l #Obj15_MapUnc_101E8,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_OOZSwingPlat,2,0),art_tile(a0) move.b #4,render_flags(a0) move.b #3,priority(a0) move.b #$20,width_pixels(a0) move.b #$10,y_radius(a0) move.w y_pos(a0),objoff_38(a0) move.w x_pos(a0),objoff_3A(a0) cmpi.b #mystic_cave_zone,(Current_Zone).w bne.s + move.l #Obj15_Obj7A_MapUnc_10256,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0) move.b #$18,width_pixels(a0) move.b #8,y_radius(a0) + cmpi.b #aquatic_ruin_zone,(Current_Zone).w bne.s + move.l #Obj15_Obj83_MapUnc_1021E,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0) move.b #$20,width_pixels(a0) move.b #8,y_radius(a0) + bsr.w Adjust2PArtPointer moveq #0,d1 move.b subtype(a0),d1 bpl.s + addq.b #4,routine(a0) + move.b d1,d4 andi.b #$70,d4 andi.w #$F,d1 move.w x_pos(a0),d2 move.w y_pos(a0),d3 jsrto (SingleObjLoad2).l, JmpTo2_SingleObjLoad2 bne.w +++ _move.b id(a0),id(a1) ; load obj15 move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) move.b #4,render_flags(a1) cmpi.b #$20,d4 bne.s + move.b #4,routine(a1) move.b #4,priority(a1) move.b #$10,width_pixels(a1) move.b #$50,y_radius(a1) bset #4,render_flags(a1) move.b #3,mapping_frame(a1) move.w d2,x_pos(a1) addi.w #$40,d3 move.w d3,y_pos(a1) addi.w #$48,d3 move.w d3,y_pos(a0) bra.s ++ ; =========================================================================== + bset #6,render_flags(a1) move.b #$48,mainspr_width(a1) move.b d1,mainspr_childsprites(a1) subq.b #1,d1 lea sub2_x_pos(a1),a2 - move.w d2,(a2)+ ; sub?_x_pos move.w d3,(a2)+ ; sub?_y_pos move.w #1,(a2)+ ; sub2_mapframe addi.w #$10,d3 dbf d1,- move.b #2,sub2_mapframe(a1) move.w sub6_x_pos(a1),x_pos(a1) move.w sub6_y_pos(a1),y_pos(a1) move.w d2,sub6_x_pos(a1) move.w d3,sub6_y_pos(a1) move.b #1,mainspr_mapframe(a1) addi_.w #8,d3 move.w d3,y_pos(a0) move.b #$50,mainspr_height(a1) bset #4,render_flags(a1) + move.l a1,objoff_30(a0) + move.w #$8000,angle(a0) move.w #0,objoff_3E(a0) move.b subtype(a0),d1 andi.w #$70,d1 move.b d1,subtype(a0) cmpi.b #$40,d1 bne.s Obj15_State2 move.l #Obj15_MapUnc_102DE,mappings(a0) move.b #$A7,collision_flags(a0) ; loc_FE50: Obj15_State2: move.w x_pos(a0),-(sp) bsr.w sub_FE70 moveq #0,d1 move.b width_pixels(a0),d1 moveq #0,d3 move.b y_radius(a0),d3 addq.b #1,d3 move.w (sp)+,d4 jsrto (PlatformObject2).l, JmpTo_PlatformObject2 bra.w loc_1000C ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_FE70: moveq #0,d0 moveq #0,d1 move.b (Oscillating_Data+$18).w,d0 move.b subtype(a0),d1 beq.s loc_FEC2 cmpi.b #$10,d1 bne.s ++ cmpi.b #$3F,d0 beq.s + bhs.s loc_FEC2 moveq #$40,d0 bra.s loc_FEC2 ; =========================================================================== / move.w #SndID_PlatformKnock,d0 jsr (PlaySoundLocal).l moveq #$40,d0 bra.s loc_FEC2 ; =========================================================================== + cmpi.b #$20,d1 beq.w +++ ; rts cmpi.b #$30,d1 bne.s + cmpi.b #$41,d0 beq.s - blo.s loc_FEC2 moveq #$40,d0 bra.s loc_FEC2 ; =========================================================================== + cmpi.b #$40,d1 bne.s loc_FEC2 bsr.w loc_FF6E loc_FEC2: move.b objoff_2E(a0),d1 cmp.b d0,d1 beq.w ++ ; rts move.b d0,objoff_2E(a0) move.w #$80,d1 btst #0,status(a0) beq.s + neg.w d0 add.w d1,d0 + jsrto (CalcSine).l, JmpTo2_CalcSine move.w objoff_38(a0),d2 move.w objoff_3A(a0),d3 moveq #0,d6 movea.l objoff_30(a0),a1 move.b mainspr_childsprites(a1),d6 subq.w #1,d6 bcs.s + ; rts swap d0 swap d1 asr.l #4,d0 asr.l #4,d1 moveq #0,d4 moveq #0,d5 lea sub2_x_pos(a1),a2 - movem.l d4-d5,-(sp) swap d4 swap d5 add.w d2,d4 add.w d3,d5 move.w d5,(a2)+ ; sub?_x_pos move.w d4,(a2)+ ; sub?_y_pos movem.l (sp)+,d4-d5 add.l d0,d4 add.l d1,d5 addq.w #next_subspr-4,a2 dbf d6,- movem.l d4-d5,-(sp) swap d4 swap d5 add.w d2,d4 add.w d3,d5 move.w sub6_x_pos(a1),d2 move.w sub6_y_pos(a1),d3 move.w d5,sub6_x_pos(a1) move.w d4,sub6_y_pos(a1) move.w d2,x_pos(a1) move.w d3,y_pos(a1) movem.l (sp)+,d4-d5 asr.l #1,d0 asr.l #1,d1 add.l d0,d4 add.l d1,d5 swap d4 swap d5 add.w objoff_38(a0),d4 add.w objoff_3A(a0),d5 move.w d4,y_pos(a0) move.w d5,x_pos(a0) + rts ; End of function sub_FE70 ; =========================================================================== loc_FF6E: tst.w objoff_36(a0) beq.s + subq.w #1,objoff_36(a0) bra.w loc_10006 ; =========================================================================== + tst.b objoff_34(a0) bne.s + move.w (MainCharacter+x_pos).w,d0 sub.w objoff_3A(a0),d0 addi.w #$20,d0 cmpi.w #$40,d0 bhs.s loc_10006 tst.w (Debug_placement_mode).w bne.w loc_10006 move.b #1,objoff_34(a0) + tst.b objoff_3D(a0) beq.s + move.w objoff_3E(a0),d0 addi_.w #8,d0 move.w d0,objoff_3E(a0) add.w d0,angle(a0) cmpi.w #$200,d0 bne.s loc_10006 move.w #0,objoff_3E(a0) move.w #$8000,angle(a0) move.b #0,objoff_3D(a0) move.w #$3C,objoff_36(a0) bra.s loc_10006 ; =========================================================================== + move.w objoff_3E(a0),d0 subi_.w #8,d0 move.w d0,objoff_3E(a0) add.w d0,angle(a0) cmpi.w #$FE00,d0 bne.s loc_10006 move.w #0,objoff_3E(a0) move.w #$4000,angle(a0) move.b #1,objoff_3D(a0) ; loc_10000: move.w #$3C,objoff_36(a0) loc_10006: move.b angle(a0),d0 rts ; =========================================================================== loc_1000C: tst.w (Two_player_mode).w beq.s + bra.w DisplaySprite ; =========================================================================== + move.w objoff_3A(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w + bra.w DisplaySprite ; =========================================================================== + movea.l objoff_30(a0),a1 bsr.w DeleteObject2 bra.w DeleteObject ; =========================================================================== Obj15_Display: ;; bra.w DisplaySprite ; =========================================================================== ; loc_1003E: Obj15_State4: move.w x_pos(a0),-(sp) bsr.w sub_FE70 moveq #0,d1 move.b width_pixels(a0),d1 moveq #0,d3 move.b y_radius(a0),d3 addq.b #1,d3 move.w (sp)+,d4 jsrto (PlatformObject2).l, JmpTo_PlatformObject2 move.b status(a0),d0 andi.b #standing_mask,d0 beq.w BranchTo_loc_1000C tst.b (Oscillating_Data+$18).w bne.w BranchTo_loc_1000C jsrto (SingleObjLoad2).l, JmpTo2_SingleObjLoad2 bne.s loc_100E4 moveq #0,d0 move.w #bytesToLcnt(object_size),d1 - move.l (a0,d0.w),(a1,d0.w) addq.w #4,d0 dbf d1,- if object_size&3 move.w (a0,d0.w),(a1,d0.w) endif move.b #$A,routine(a1) cmpi.b #aquatic_ruin_zone,(Current_Zone).w bne.s + addq.b #2,routine(a1) + move.w #$200,x_vel(a1) btst #0,status(a0) beq.s + neg.w x_vel(a1) + bset #1,status(a1) move.w a0,d0 subi.w #Object_RAM,d0 if object_size=$40 lsr.w #6,d0 else divu.w #object_size,d0 endif andi.w #$7F,d0 move.w a1,d1 subi.w #Object_RAM,d1 if object_size=$40 lsr.w #6,d1 else divu.w #object_size,d1 endif andi.w #$7F,d1 lea (MainCharacter).w,a1 ; a1=character cmp.b interact(a1),d0 bne.s + move.b d1,interact(a1) + lea (Sidekick).w,a1 ; a1=character cmp.b interact(a1),d0 bne.s loc_100E4 move.b d1,interact(a1) loc_100E4: move.b #3,mapping_frame(a0) addq.b #2,routine(a0) andi.b #$E7,status(a0) BranchTo_loc_1000C bra.w loc_1000C ; =========================================================================== ; loc_100F8: Obj15_State5: bsr.w sub_FE70 bra.w loc_1000C ; =========================================================================== ; loc_10100: Obj15_State6: move.w x_pos(a0),-(sp) btst #1,status(a0) beq.s + bsr.w ObjectMove addi.w #$18,y_vel(a0) cmpi.w #$720,y_pos(a0) blo.s ++ move.w #$720,y_pos(a0) bclr #1,status(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) move.w y_pos(a0),objoff_38(a0) bra.s ++ ; =========================================================================== + moveq #0,d0 move.b (Oscillating_Data+$14).w,d0 lsr.w #1,d0 add.w objoff_38(a0),d0 move.w d0,y_pos(a0) + moveq #0,d1 move.b width_pixels(a0),d1 moveq #0,d3 move.b y_radius(a0),d3 addq.b #1,d3 move.w (sp)+,d4 jsrto (PlatformObject2).l, JmpTo_PlatformObject2 bra.w MarkObjGone ; =========================================================================== ; loc_10166: Obj15_State7: move.w x_pos(a0),-(sp) bsr.w ObjectMove btst #1,status(a0) beq.s + addi.w #$18,y_vel(a0) move.w (Water_Level_2).w,d0 cmp.w y_pos(a0),d0 bhi.s ++ move.w d0,y_pos(a0) move.w d0,objoff_38(a0) bclr #1,status(a0) move.w #$100,x_vel(a0) move.w #0,y_vel(a0) bra.s ++ ; =========================================================================== + moveq #0,d0 move.b (Oscillating_Data+$14).w,d0 lsr.w #1,d0 add.w objoff_38(a0),d0 move.w d0,y_pos(a0) tst.w x_vel(a0) beq.s + moveq #0,d3 move.b width_pixels(a0),d3 jsrto (ObjCheckRightWallDist).l, JmpTo_ObjCheckRightWallDist tst.w d1 bpl.s + add.w d1,x_pos(a0) move.w #0,x_vel(a0) + moveq #0,d1 move.b width_pixels(a0),d1 moveq #0,d3 move.b y_radius(a0),d3 addq.b #1,d3 move.w (sp)+,d4 jsrto (PlatformObject2).l, JmpTo_PlatformObject2 bra.w MarkObjGone ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj15_MapUnc_101E8: BINCLUDE "mappings/sprite/obj15_a.bin" ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj15_Obj83_MapUnc_1021E: BINCLUDE "mappings/sprite/obj83.bin" ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj15_Obj7A_MapUnc_10256: offsetTable offsetTableEntry.w word_1025E offsetTableEntry.w word_10270 offsetTableEntry.w word_1027A offsetTableEntry.w word_1028C word_1025E: dc.w 2 dc.w $F809, $6060, $6030, $FFE8 dc.w $F809, $6860, $6830, 0 word_10270: dc.w 1 dc.w $F805, $6066, $6033, $FFF8 word_1027A: dc.w 2 dc.w $E805, $406A, $4035, $FFF4 dc.w $F80B, $406E, $4037, $FFF4 word_1028C: dc.w $A dc.w $A805, $406A, $4035, $FFF4 dc.w $B80B, $406E, $4037, $FFF4 dc.w $C805, $6066, $6033, $FFF8 dc.w $D805, $6066, $6033, $FFF8 dc.w $E805, $6066, $6033, $FFF8 dc.w $F805, $6066, $6033, $FFF8 dc.w $805, $6066, $6033, $FFF8 dc.w $1805, $6066, $6033, $FFF8 dc.w $2805, $6066, $6033, $FFF8 dc.w $3805, $6066, $6033, $FFF8 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj15_MapUnc_102DE: offsetTable offsetTableEntry.w word_102E4 offsetTableEntry.w word_10270 offsetTableEntry.w word_1027A word_102E4: dc.w 2 dc.w $F80D, $6058, $602C, $FFE0 dc.w $F80D, $6858, $682C, 0 ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo_PlatformObject2 jmp (PlatformObject2).l JmpTo2_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo2_CalcSine jmp (CalcSine).l JmpTo_ObjCheckRightWallDist jmp (ObjCheckRightWallDist).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 17 - GHZ rotating log helix spikes (from Sonic 1, unused) ; the programming of this was modified somewhat between Sonic 1 and Sonic 2 ; ---------------------------------------------------------------------------- ; Sprite_10310: Obj17: moveq #0,d0 move.b routine(a0),d0 move.w Obj17_Index(pc,d0.w),d1 jmp Obj17_Index(pc,d1.w) ; =========================================================================== ; off_1031E: Obj17_Index: offsetTable offsetTableEntry.w Obj17_Init ; 0 offsetTableEntry.w Obj17_Main ; 2 offsetTableEntry.w Obj17_Display ; 4 ; =========================================================================== ; loc_10324: Obj17_Main: Obj17_Init: addq.b #2,routine(a0) move.l #Obj17_MapUnc_10452,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_GHZ_Spiked_Log,2,0),art_tile(a0) bsr.w Adjust2PArtPointer move.b #4,render_flags(a0) move.b #3,priority(a0) move.b #8,width_pixels(a0) move.w y_pos(a0),d2 move.w x_pos(a0),d3 _move.b id(a0),d4 lea subtype(a0),a2 ; move helix length to a2 moveq #0,d1 move.b (a2),d1 ; move a2 to d1 move.b #0,(a2)+ move.w d1,d0 lsr.w #1,d0 lsl.w #4,d0 sub.w d0,d3 subq.b #2,d1 bcs.s Obj17_Main moveq #0,d6 ; loc_10372: Obj17_MakeHelix: bsr.w SingleObjLoad2 bne.s Obj17_Main addq.b #1,subtype(a0) move.w a1,d5 subi.w #Object_RAM,d5 if object_size=$40 lsr.w #6,d5 else divu.w #object_size,d5 endif andi.w #$7F,d5 move.b d5,(a2)+ move.b #4,routine(a1) _move.b d4,id(a1) ; load obj17 move.w d2,y_pos(a1) move.w d3,x_pos(a1) move.l mappings(a0),mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_GHZ_Spiked_Log,2,0),art_tile(a1) bsr.w Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #3,priority(a1) move.b #8,width_pixels(a1) move.b d6,objoff_3E(a1) addq.b #1,d6 andi.b #7,d6 addi.w #$10,d3 cmp.w x_pos(a0),d3 bne.s + move.b d6,objoff_3E(a0) addq.b #1,d6 andi.b #7,d6 addi.w #$10,d3 addq.b #1,subtype(a0) + dbf d1,Obj17_MakeHelix ; repeat d1 times (helix length) ; loc_103E8: Obj17_Action: Obj17_Main: bsr.w Obj17_RotateSpike move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w Obj17_DelAll bra.w DisplaySprite ; =========================================================================== ; loc_10404: Obj17_DelAll: moveq #0,d2 lea subtype(a0),a2 ; move helix length to a2 move.b (a2)+,d2 ; move a2 to d2 subq.b #2,d2 bcs.s BranchTo2_DeleteObject ; loc_10410: Obj17_DelLoop: moveq #0,d0 move.b (a2)+,d0 if object_size=$40 lsl.w #6,d0 else mulu.w #object_size,d0 endif addi.l #Object_RAM,d0 movea.l d0,a1 ; a1=object bsr.w DeleteObject2 ; delete object dbf d2,Obj17_DelLoop ; repeat d2 times (helix length) ; loc_10426: BranchTo2_DeleteObject bra.w DeleteObject ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_1042A: Obj17_RotateSpike: move.b (Logspike_anim_frame).w,d0 move.b #0,collision_flags(a0) ; make object harmless add.b objoff_3E(a0),d0 andi.b #7,d0 move.b d0,mapping_frame(a0) ; change current frame bne.s + ; rts move.b #%10000100,collision_flags(a0) ; make object harmful + rts ; End of function Obj17_RotateSpike ; =========================================================================== ; loc_1044A: Obj17_Display: bsr.w Obj17_RotateSpike bra.w DisplaySprite ; =========================================================================== ; ----------------------------------------------------------------------------- ; sprite mappings - helix of spikes on a pole (GHZ) (unused) ; ----------------------------------------------------------------------------- Obj17_MapUnc_10452: BINCLUDE "mappings/sprite/obj17.bin" ; =========================================================================== if gameRevision<2 nop endif ; ---------------------------------------------------------------------------- ; Object 18 - Stationary floating platform from ARZ, EHZ and HTZ ; ---------------------------------------------------------------------------- ; Sprite_104AC: Obj18: moveq #0,d0 move.b routine(a0),d0 move.w Obj18_Index(pc,d0.w),d1 jmp Obj18_Index(pc,d1.w) ; =========================================================================== ; off_104BA: Obj18_Index: offsetTable offsetTableEntry.w Obj18_Init ; 0 offsetTableEntry.w loc_1056A ; 2 offsetTableEntry.w BranchTo3_DeleteObject ; 4 offsetTableEntry.w loc_105A8 ; 6 offsetTableEntry.w loc_105D4 ; 8 ; =========================================================================== ;word_104C4: Obj18_InitData: ; width_pixels ; frame dc.b $20, 0 dc.b $20, 1 dc.b $20, 2 dc.b $40, 3 dc.b $30, 4 ; =========================================================================== ; loc_104CE: Obj18_Init: addq.b #2,routine(a0) moveq #0,d0 move.b subtype(a0),d0 lsr.w #3,d0 andi.w #$E,d0 lea Obj18_InitData(pc,d0.w),a2 move.b (a2)+,width_pixels(a0) move.b (a2)+,mapping_frame(a0) move.l #Obj18_MapUnc_107F6,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,2,0),art_tile(a0) cmpi.b #aquatic_ruin_zone,(Current_Zone).w bne.s + move.l #Obj18_MapUnc_1084E,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,2,0),art_tile(a0) + bsr.w Adjust2PArtPointer move.b #4,render_flags(a0) move.b #4,priority(a0) move.w y_pos(a0),objoff_2C(a0) move.w y_pos(a0),objoff_34(a0) move.w x_pos(a0),objoff_32(a0) move.w #$80,angle(a0) tst.b subtype(a0) bpl.s ++ addq.b #6,routine(a0) andi.b #$F,subtype(a0) move.b #$30,y_radius(a0) cmpi.b #aquatic_ruin_zone,(Current_Zone).w bne.s + move.b #$28,y_radius(a0) + bset #4,render_flags(a0) bra.w loc_105D4 ; =========================================================================== + andi.b #$F,subtype(a0) loc_1056A: move.b status(a0),d0 andi.b #standing_mask,d0 bne.s + tst.b objoff_38(a0) beq.s ++ subq.b #4,objoff_38(a0) bra.s ++ ; =========================================================================== + cmpi.b #$40,objoff_38(a0) beq.s + addq.b #4,objoff_38(a0) + move.w x_pos(a0),-(sp) bsr.w sub_10638 bsr.w sub_1061E moveq #0,d1 move.b width_pixels(a0),d1 moveq #8,d3 move.w (sp)+,d4 jsrto (PlatformObject).l, JmpTo_PlatformObject bra.s loc_105B0 ; =========================================================================== loc_105A8: bsr.w sub_10638 bsr.w sub_1061E loc_105B0: tst.w (Two_player_mode).w beq.s + bra.w DisplaySprite ; =========================================================================== + move.w objoff_32(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.s BranchTo3_DeleteObject bra.w DisplaySprite ; =========================================================================== BranchTo3_DeleteObject bra.w DeleteObject ; =========================================================================== loc_105D4: move.b status(a0),d0 andi.b #standing_mask,d0 bne.s + tst.b objoff_38(a0) beq.s ++ subq.b #4,objoff_38(a0) bra.s ++ ; =========================================================================== + cmpi.b #$40,objoff_38(a0) beq.s + addq.b #4,objoff_38(a0) + move.w x_pos(a0),-(sp) bsr.w sub_10638 bsr.w sub_1061E moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 move.w (sp)+,d4 jsrto (SolidObject).l, JmpTo_SolidObject bra.s loc_105B0 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_1061E: move.b objoff_38(a0),d0 jsrto (CalcSine).l, JmpTo3_CalcSine move.w #$400,d1 muls.w d1,d0 swap d0 add.w objoff_2C(a0),d0 move.w d0,y_pos(a0) rts ; End of function sub_1061E ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_10638: moveq #0,d0 move.b subtype(a0),d0 andi.w #$F,d0 add.w d0,d0 move.w Obj18_Behaviours(pc,d0.w),d1 jmp Obj18_Behaviours(pc,d1.w) ; End of function sub_10638 ; =========================================================================== ; off_1064C: Obj18_Behaviours: offsetTable offsetTableEntry.w return_10668 ; 0 offsetTableEntry.w loc_1067A ; 1 offsetTableEntry.w loc_106C0 ; 2 offsetTableEntry.w loc_106D8 ; 3 offsetTableEntry.w loc_10702 ; 4 offsetTableEntry.w loc_1066A ; 5 offsetTableEntry.w loc_106B0 ; 6 offsetTableEntry.w loc_10778 ; 7 offsetTableEntry.w loc_107A4 ; 8 offsetTableEntry.w return_10668 ; 9 offsetTableEntry.w loc_107BC ; $A offsetTableEntry.w loc_107D6 ; $B offsetTableEntry.w loc_106A2 ; $C offsetTableEntry.w loc_10692 ; $D ; =========================================================================== return_10668: rts ; =========================================================================== loc_1066A: move.w objoff_32(a0),d0 move.b angle(a0),d1 neg.b d1 addi.b #$40,d1 bra.s loc_10686 ; =========================================================================== loc_1067A: move.w objoff_32(a0),d0 move.b angle(a0),d1 subi.b #$40,d1 loc_10686: ext.w d1 add.w d1,d0 move.w d0,x_pos(a0) bra.w loc_107EE ; =========================================================================== loc_10692: move.w objoff_34(a0),d0 move.b (Oscillating_Data+$C).w,d1 neg.b d1 addi.b #$30,d1 bra.s loc_106CC ; =========================================================================== loc_106A2: move.w objoff_34(a0),d0 move.b (Oscillating_Data+$C).w,d1 subi.b #$30,d1 bra.s loc_106CC ; =========================================================================== loc_106B0: move.w objoff_34(a0),d0 move.b angle(a0),d1 neg.b d1 addi.b #$40,d1 bra.s loc_106CC ; =========================================================================== loc_106C0: move.w objoff_34(a0),d0 move.b angle(a0),d1 subi.b #$40,d1 loc_106CC: ext.w d1 add.w d1,d0 move.w d0,objoff_2C(a0) bra.w loc_107EE ; =========================================================================== loc_106D8: tst.w objoff_3A(a0) bne.s loc_106F0 move.b status(a0),d0 andi.b #standing_mask,d0 beq.s + ; rts move.w #$1E,objoff_3A(a0) / rts ; =========================================================================== loc_106F0: subq.w #1,objoff_3A(a0) bne.s - ; rts move.w #$20,objoff_3A(a0) addq.b #1,subtype(a0) rts ; =========================================================================== loc_10702: tst.w objoff_3A(a0) beq.s loc_10730 subq.w #1,objoff_3A(a0) bne.s loc_10730 bclr #p1_standing_bit,status(a0) beq.s + lea (MainCharacter).w,a1 ; a1=character bsr.s sub_1075E + bclr #p2_standing_bit,status(a0) beq.s + lea (Sidekick).w,a1 ; a1=character bsr.s sub_1075E + move.b #6,routine(a0) loc_10730: move.l objoff_2C(a0),d3 move.w y_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d3 move.l d3,objoff_2C(a0) addi.w #$38,y_vel(a0) move.w (Camera_Max_Y_pos_now).w,d0 addi.w #$120,d0 cmp.w objoff_2C(a0),d0 bhs.s + ; rts move.b #4,routine(a0) + rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_1075E: bset #1,status(a1) bclr #3,status(a1) move.b #2,routine(a1) move.w y_vel(a0),y_vel(a1) rts ; End of function sub_1075E ; =========================================================================== loc_10778: tst.w objoff_3A(a0) bne.s loc_10798 lea (ButtonVine_Trigger).w,a2 moveq #0,d0 move.b subtype(a0),d0 lsr.w #4,d0 tst.b (a2,d0.w) beq.s + ; rts move.w #$3C,objoff_3A(a0) / rts ; =========================================================================== loc_10798: subq.w #1,objoff_3A(a0) bne.s - ; rts addq.b #1,subtype(a0) rts ; =========================================================================== loc_107A4: subq.w #2,objoff_2C(a0) move.w objoff_34(a0),d0 subi.w #$200,d0 cmp.w objoff_2C(a0),d0 bne.s + ; rts clr.b subtype(a0) + rts ; =========================================================================== loc_107BC: move.w objoff_34(a0),d0 move.b angle(a0),d1 subi.b #$40,d1 ext.w d1 asr.w #1,d1 add.w d1,d0 move.w d0,objoff_2C(a0) bra.w loc_107EE ; =========================================================================== loc_107D6: move.w objoff_34(a0),d0 move.b angle(a0),d1 neg.b d1 addi.b #$40,d1 ext.w d1 asr.w #1,d1 add.w d1,d0 move.w d0,objoff_2C(a0) loc_107EE: move.b (Oscillating_Data+$18).w,angle(a0) rts ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj18_MapUnc_107F6: BINCLUDE "mappings/sprite/obj18_a.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj18_MapUnc_1084E: BINCLUDE "mappings/sprite/obj18_b.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo3_CalcSine jmp (CalcSine).l JmpTo_PlatformObject jmp (PlatformObject).l JmpTo_SolidObject jmp (SolidObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 1A - Collapsing platform from HPZ (and GHZ) ; also supports OOZ, but never made use of ; ; Unlike Object 1F, this supports sloped platforms and subtype-dependant ; mappings. Both are used by GHZ, the latter to allow different shading ; on right-facing ledges. ; ---------------------------------------------------------------------------- ; Sprite_108BC: Obj1A: moveq #0,d0 move.b routine(a0),d0 move.w Obj1A_Index(pc,d0.w),d1 jmp Obj1A_Index(pc,d1.w) ; =========================================================================== ; off_108CA: Obj1A_Index: offsetTable offsetTableEntry.w Obj1A_Init ; 0 offsetTableEntry.w Obj1A_Main ; 2 offsetTableEntry.w Obj1A_Fragment ; 4 ; =========================================================================== collapsing_platform_delay_pointer = objoff_34 collapsing_platform_delay_counter = objoff_38 collapsing_platform_stood_on_flag = objoff_3A collapsing_platform_slope_pointer = objoff_3C ; loc_108D0: Obj1A_Init: addq.b #2,routine(a0) move.l #Obj1A_MapUnc_10C6C,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,2,0),art_tile(a0) bsr.w Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #4,priority(a0) move.b #7,collapsing_platform_delay_counter(a0) move.b subtype(a0),mapping_frame(a0) move.l #Obj1A_DelayData,collapsing_platform_delay_pointer(a0) cmpi.b #hidden_palace_zone,(Current_Zone).w bne.s + move.l #Obj1A_MapUnc_1101C,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_HPZPlatform,2,0),art_tile(a0) bsr.w Adjust2PArtPointer move.b #$30,width_pixels(a0) move.l #Obj1A_HPZ_SlopeData,collapsing_platform_slope_pointer(a0) move.l #Obj1A_HPZ_DelayData,collapsing_platform_delay_pointer(a0) bra.s Obj1A_Main ; =========================================================================== + cmpi.b #oil_ocean_zone,(Current_Zone).w bne.s + move.l #Obj1F_MapUnc_110C6,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_OOZPlatform,3,0),art_tile(a0) bsr.w Adjust2PArtPointer move.b #$40,width_pixels(a0) move.l #Obj1A_OOZ_SlopeData,collapsing_platform_slope_pointer(a0) bra.s Obj1A_Main ; =========================================================================== + move.l #Obj1A_GHZ_SlopeData,collapsing_platform_slope_pointer(a0) move.b #$34,width_pixels(a0) move.b #$38,y_radius(a0) bset #4,render_flags(a0) ; loc_1097C: Obj1A_Main: tst.b collapsing_platform_stood_on_flag(a0) beq.s + tst.b collapsing_platform_delay_counter(a0) beq.w Obj1A_CreateFragments ; time up; collapse subq.b #1,collapsing_platform_delay_counter(a0) + move.b status(a0),d0 andi.b #standing_mask,d0 beq.s sub_1099E move.b #1,collapsing_platform_stood_on_flag(a0) ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_1099E: moveq #0,d1 move.b width_pixels(a0),d1 movea.l collapsing_platform_slope_pointer(a0),a2 ; a2=object move.w x_pos(a0),d4 jsrto (SlopedPlatform).l, JmpTo_SlopedPlatform bra.w MarkObjGone ; End of function sub_1099E ; =========================================================================== ; loc_109B4: Obj1A_Fragment: tst.b collapsing_platform_delay_counter(a0) beq.s Obj1A_FragmentFall ; time up; collapse tst.b collapsing_platform_stood_on_flag(a0) bne.s + subq.b #1,collapsing_platform_delay_counter(a0) bra.w DisplaySprite ; =========================================================================== + bsr.w sub_1099E subq.b #1,collapsing_platform_delay_counter(a0) bne.s + lea (MainCharacter).w,a1 ; a1=character bsr.s sub_109DC lea (Sidekick).w,a1 ; a1=character sub_109DC: btst #3,status(a1) beq.s + bclr #3,status(a1) bclr #5,status(a1) move.b #AniIDSonAni_Run,next_anim(a1) + rts ; End of function sub_109DC ; =========================================================================== ; loc_109F8: Obj1A_FragmentFall: bsr.w ObjectMoveAndFall tst.b render_flags(a0) bpl.w DeleteObject bra.w DisplaySprite ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 1F - Collapsing platform from ARZ, MCZ and OOZ (and MZ, SLZ and SBZ) ; ---------------------------------------------------------------------------- ; Sprite_10A08: Obj1F: moveq #0,d0 move.b routine(a0),d0 move.w Obj1F_Index(pc,d0.w),d1 jmp Obj1F_Index(pc,d1.w) ; =========================================================================== ; off_10A16: Obj1F_Index: offsetTable offsetTableEntry.w Obj1F_Init ; 0 offsetTableEntry.w Obj1F_Main ; 2 offsetTableEntry.w Obj1F_Fragment ; 4 ; =========================================================================== ; loc_10A1C: Obj1F_Init: addq.b #2,routine(a0) move.l #Obj1F_MapUnc_10F0C,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_MZ_Platform,2,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #4,priority(a0) move.b #7,collapsing_platform_delay_counter(a0) move.b #$44,width_pixels(a0) lea (Obj1F_DelayData_EvenSubtype).l,a4 btst #0,subtype(a0) beq.s + lea (Obj1F_DelayData_OddSubtype).l,a4 + move.l a4,collapsing_platform_delay_pointer(a0) cmpi.b #oil_ocean_zone,(Current_Zone).w bne.s + move.l #Obj1F_MapUnc_110C6,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_OOZPlatform,3,0),art_tile(a0) bsr.w Adjust2PArtPointer move.b #$40,width_pixels(a0) move.l #Obj1F_OOZ_DelayData,collapsing_platform_delay_pointer(a0) + cmpi.b #mystic_cave_zone,(Current_Zone).w bne.s + move.l #Obj1F_MapUnc_11106,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_MCZCollapsePlat,3,0),art_tile(a0) bsr.w Adjust2PArtPointer move.b #$20,width_pixels(a0) move.l #Obj1F_MCZ_DelayData,collapsing_platform_delay_pointer(a0) + cmpi.b #aquatic_ruin_zone,(Current_Zone).w bne.s Obj1F_Main move.l #Obj1F_MapUnc_1115E,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,2,0),art_tile(a0) bsr.w Adjust2PArtPointer move.b #$20,width_pixels(a0) move.l #Obj1F_ARZ_DelayData,collapsing_platform_delay_pointer(a0) ; loc_10AD6: Obj1F_Main: tst.b collapsing_platform_stood_on_flag(a0) beq.s + tst.b collapsing_platform_delay_counter(a0) beq.w Obj1F_CreateFragments ; time up; collapse subq.b #1,collapsing_platform_delay_counter(a0) + move.b status(a0),d0 andi.b #standing_mask,d0 beq.s sub_10AF8 move.b #1,collapsing_platform_stood_on_flag(a0) ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_10AF8: moveq #0,d1 move.b width_pixels(a0),d1 move.w #$10,d3 move.w x_pos(a0),d4 jsrto (PlatformObject).l, JmpTo2_PlatformObject bra.w MarkObjGone ; End of function sub_10AF8 ; =========================================================================== ; loc_10B0E: Obj1F_Fragment: tst.b collapsing_platform_delay_counter(a0) beq.s Obj1F_FragmentFall ; time up; collapse tst.b collapsing_platform_stood_on_flag(a0) bne.s + subq.b #1,collapsing_platform_delay_counter(a0) bra.w DisplaySprite ; =========================================================================== + bsr.w sub_10AF8 subq.b #1,collapsing_platform_delay_counter(a0) bne.s + ; rts lea (MainCharacter).w,a1 ; a1=character bsr.s sub_10B36 lea (Sidekick).w,a1 ; a1=character sub_10B36: btst #3,status(a1) beq.s + ; rts bclr #3,status(a1) bclr #5,status(a1) move.b #AniIDSonAni_Run,next_anim(a1) + rts ; End of function sub_10B36 ; =========================================================================== ; loc_10B52: Obj1F_FragmentFall: bsr.w ObjectMoveAndFall tst.b render_flags(a0) bpl.w DeleteObject bra.w DisplaySprite ; =========================================================================== ; loc_10B62: Obj1F_CreateFragments: addq.b #1,mapping_frame(a0) bra.s + ; =========================================================================== ; loc_10B68: Obj1A_CreateFragments: addq.b #2,mapping_frame(a0) + movea.l collapsing_platform_delay_pointer(a0),a4 moveq #0,d0 move.b mapping_frame(a0),d0 add.w d0,d0 movea.l mappings(a0),a3 adda.w (a3,d0.w),a3 move.w (a3)+,d1 subq.w #1,d1 bset #5,render_flags(a0) _move.b id(a0),d4 move.b render_flags(a0),d5 movea.l a0,a1 bra.s + ; =========================================================================== - bsr.w SingleObjLoad bne.s +++ addq.w #8,a3 + move.b #4,routine(a1) _move.b d4,id(a1) ; load obj1F move.l a3,mappings(a1) move.b d5,render_flags(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w art_tile(a0),art_tile(a1) move.b priority(a0),priority(a1) move.b width_pixels(a0),width_pixels(a1) move.b y_radius(a0),y_radius(a1) move.b (a4)+,collapsing_platform_delay_counter(a1) cmpa.l a0,a1 bhs.s + bsr.w DisplaySprite2 + dbf d1,- + bsr.w DisplaySprite move.w #SndID_Smash,d0 jmp (PlaySound).l ; =========================================================================== ; Delay data for obj1A in all but HPZ: ;byte_10BF2: Obj1A_DelayData: dc.b $1C,$18,$14,$10,$1A,$16,$12, $E, $A, 6,$18,$14,$10, $C, 8, 4 dc.b $16,$12, $E, $A, 6, 2,$14,$10, $C; 16 rev02even ; Delay data for obj1A in HPZ: ;byte_10C0B: Obj1A_HPZ_DelayData: dc.b $18,$1C,$20,$1E,$1A,$16, 6, $E,$14,$12, $A, 2 rev02even ; Delay data for obj1F even subtypes in all levels without more specific data: ;byte_10C17: Obj1F_DelayData_EvenSubtype: dc.b $1E,$16, $E, 6,$1A,$12, $A, 2 rev02even ; Delay data for obj1F odd subtypes in all levels without more specific data: ;byte_10C1F: Obj1F_DelayData_OddSubtype: dc.b $16,$1E,$1A,$12, 6, $E, $A, 2 rev02even ; Delay data for obj1F in OOZ: ;byte_10C27: Obj1F_OOZ_DelayData: dc.b $1A,$12, $A, 2,$16, $E, 6 rev02even ; Delay data for obj1F in MCZ: ;byte_10C2E: Obj1F_MCZ_DelayData: dc.b $1A,$16,$12, $E, $A, 2 rev02even ; Delay data for obj1F in ARZ: ;byte_10C34: Obj1F_ARZ_DelayData: dc.b $16,$1A,$18,$12, 6, $E, $A, 2 rev02even ; S1 remnant: Height data for GHZ collapsing platform (unused): ;byte_10C3C: Obj1A_GHZ_SlopeData: dc.b $20,$20,$20,$20,$20,$20,$20,$20,$21,$21,$22,$22,$23,$23,$24,$24 dc.b $25,$25,$26,$26,$27,$27,$28,$28,$29,$29,$2A,$2A,$2B,$2B,$2C,$2C; 16 dc.b $2D,$2D,$2E,$2E,$2F,$2F,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30; 32 even ; ------------------------------------------------------------------------------- ; unused sprite mappings (GHZ) ; ------------------------------------------------------------------------------- Obj1A_MapUnc_10C6C: BINCLUDE "mappings/sprite/obj1A_a.bin" ; ---------------------------------------------------------------------------- ; unused sprite mappings (MZ, SLZ, SBZ) ; ---------------------------------------------------------------------------- Obj1F_MapUnc_10F0C: BINCLUDE "mappings/sprite/obj1F_a.bin" ; Slope data for platforms. ;byte_10FDC: Obj1A_OOZ_SlopeData: dc.b $10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10 ;byte_10FEC: Obj1A_HPZ_SlopeData dc.b $10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10 dc.b $10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10 dc.b $10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10 ; ---------------------------------------------------------------------------- ; sprite mappings (HPZ) ; ---------------------------------------------------------------------------- Obj1A_MapUnc_1101C: BINCLUDE "mappings/sprite/obj1A_b.bin" ; ---------------------------------------------------------------------------- ; sprite mappings (OOZ) ; ---------------------------------------------------------------------------- Obj1F_MapUnc_110C6: BINCLUDE "mappings/sprite/obj1F_b.bin" ; ------------------------------------------------------------------------------- ; sprite mappings (MCZ) ; ------------------------------------------------------------------------------- Obj1F_MapUnc_11106: BINCLUDE "mappings/sprite/obj1F_c.bin" ; ------------------------------------------------------------------------------- ; sprite mappings (ARZ) ; ------------------------------------------------------------------------------- Obj1F_MapUnc_1115E: BINCLUDE "mappings/sprite/obj1F_d.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo_SlopedPlatform jmp (SlopedPlatform).l JmpTo2_PlatformObject jmp (PlatformObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 1C - Bridge stake in Emerald Hill Zone and Hill Top Zone, falling oil in Oil Ocean Zone ; ---------------------------------------------------------------------------- ; Sprite_111D4: Obj1C: moveq #0,d0 move.b routine(a0),d0 move.w Obj1C_Index(pc,d0.w),d1 jmp Obj1C_Index(pc,d1.w) ; =========================================================================== ; off_111E2: Obj1C_Index: offsetTable offsetTableEntry.w Obj1C_Init ; 0 offsetTableEntry.w BranchTo_MarkObjGone ; 2 ; =========================================================================== objsubdecl macro frame, mapaddr,artaddr,width,priority dc.l frame<<24|mapaddr dc.w artaddr dc.b width, priority endm ; dword_111E6: Obj1C_InitData: objsubdecl 0, Obj1C_MapUnc_11552, make_art_tile(ArtTile_ArtNem_BoltEnd_Rope,2,0), 4, 6 objsubdecl 1, Obj1C_MapUnc_11552, make_art_tile(ArtTile_ArtNem_BoltEnd_Rope,2,0), 4, 6 objsubdecl 1, Obj11_MapUnc_FC70, make_art_tile(ArtTile_ArtNem_EHZ_Bridge,2,0), 4, 1 objsubdecl 2, Obj1C_MapUnc_11552, make_art_tile(ArtTile_ArtNem_BoltEnd_Rope,1,0), $10, 6 objsubdecl 3, Obj16_MapUnc_21F14, make_art_tile(ArtTile_ArtNem_HtzZipline,2,0), 8, 4 objsubdecl 4, Obj16_MapUnc_21F14, make_art_tile(ArtTile_ArtNem_HtzZipline,2,0), 8, 4 objsubdecl 1, Obj16_MapUnc_21F14, make_art_tile(ArtTile_ArtNem_HtzZipline,2,0), $20, 1 objsubdecl 0, Obj1C_MapUnc_113D6, make_art_tile(ArtTile_ArtKos_LevelArt,2,0), 8, 1 objsubdecl 1, Obj1C_MapUnc_113D6, make_art_tile(ArtTile_ArtKos_LevelArt,2,0), 8, 1 objsubdecl 0, Obj1C_MapUnc_113EE, make_art_tile(ArtTile_ArtUnc_Waterfall3,2,0), 4, 4 objsubdecl 0, Obj1C_MapUnc_11406, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 4, 4 objsubdecl 1, Obj1C_MapUnc_11406, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 4, 4 objsubdecl 2, Obj1C_MapUnc_11406, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 4, 4 objsubdecl 3, Obj1C_MapUnc_11406, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 4, 4 objsubdecl 4, Obj1C_MapUnc_11406, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 4, 4 objsubdecl 5, Obj1C_MapUnc_11406, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 4, 4 objsubdecl 0, Obj1C_MapUnc_114AE, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), $18, 4 objsubdecl 1, Obj1C_MapUnc_114AE, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), $18, 4 objsubdecl 2, Obj1C_MapUnc_114AE, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 8, 4 objsubdecl 3, Obj1C_MapUnc_114AE, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 8, 4 objsubdecl 4, Obj1C_MapUnc_114AE, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 8, 4 ; byte_1128E: Obj1C_Radii: dc.b 0 dc.b 0 ; 1 dc.b 0 ; 2 dc.b 0 ; 3 dc.b 0 ; 4 dc.b 0 ; 5 dc.b 0 ; 6 dc.b 0 ; 7 dc.b 0 ; 8 dc.b 0 ; 9 dc.b 0 ; 10 dc.b 0 ; 11 dc.b 0 ; 12 dc.b $30 ; 13 dc.b $40 ; 14 dc.b $60 ; 15 dc.b 0 ; 16 dc.b 0 ; 17 dc.b $30 ; 18 dc.b $40 ; 19 dc.b $50 ; 20 dc.b 0 ; 21 ; =========================================================================== ; loc_112A4: Obj1C_Init: addq.b #2,routine(a0) moveq #0,d0 move.b subtype(a0),d0 move.w d0,d1 lsl.w #3,d0 lea Obj1C_InitData(pc),a1 lea (a1,d0.w),a1 move.b (a1),mapping_frame(a0) move.l (a1)+,mappings(a0) move.w (a1)+,art_tile(a0) bsr.w Adjust2PArtPointer ori.b #4,render_flags(a0) move.b (a1)+,width_pixels(a0) move.b (a1)+,priority(a0) lea Obj1C_Radii(pc),a1 move.b (a1,d1.w),d1 beq.s BranchTo_MarkObjGone ; if the radius is zero, branch move.b d1,y_radius(a0) bset #4,render_flags(a0) BranchTo_MarkObjGone bra.w MarkObjGone ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 71 - Bridge stake and pulsing orb from Hidden Palace Zone ; ---------------------------------------------------------------------------- ; Sprite_112F0: Obj71: moveq #0,d0 move.b routine(a0),d0 move.w Obj71_Index(pc,d0.w),d1 jmp Obj71_Index(pc,d1.w) ; =========================================================================== ; off_112FE: Obj71_Index: offsetTable offsetTableEntry.w Obj71_Init ; 0 offsetTableEntry.w Obj71_Main ; 2 ; --------------------------------------------------------------------------- ; dword_11302: Obj71_InitData: objsubdecl 3, Obj11_MapUnc_FC28, make_art_tile(ArtTile_ArtNem_HPZ_Bridge,3,0), 4, 1 ; Hidden Palace bridge objsubdecl 0, Obj71_MapUnc_11396, make_art_tile(ArtTile_ArtNem_HPZOrb,3,1), $10, 1 ; Hidden Palace pulsing orb objsubdecl 0, Obj71_MapUnc_11576, make_art_tile(ArtTile_ArtNem_MtzLavaBubble,2,0), $10, 1 ; MTZ lava bubble ; =========================================================================== ; loc_1131A: Obj71_Init: addq.b #2,routine(a0) move.b subtype(a0),d0 andi.w #$F,d0 lsl.w #3,d0 lea Obj71_InitData(pc),a1 lea (a1,d0.w),a1 move.b (a1),mapping_frame(a0) move.l (a1)+,mappings(a0) move.w (a1)+,art_tile(a0) bsr.w Adjust2PArtPointer ori.b #4,render_flags(a0) move.b (a1)+,width_pixels(a0) move.b (a1)+,priority(a0) move.b subtype(a0),d0 andi.w #$F0,d0 lsr.b #4,d0 move.b d0,anim(a0) ; loc_1135C: Obj71_Main: lea (Ani_obj71).l,a1 bsr.w AnimateSprite bra.w MarkObjGone ; =========================================================================== ; off_1136A: Ani_obj71: offsetTable offsetTableEntry.w byte_11372 ; 0 offsetTableEntry.w byte_1137A ; 1 offsetTableEntry.w byte_11389 ; 2 offsetTableEntry.w byte_11392 ; 3 byte_11372: dc.b 8, 3, 3, 4, 5, 5, 4,$FF rev02even byte_1137A: dc.b 5, 0, 0, 0, 1, 2, 3, 3, 2, 1, 2, 3, 3, 1,$FF rev02even byte_11389: dc.b $B, 0, 1, 2, 3, 4, 5,$FD, 3 rev02even byte_11392: dc.b $7F, 6,$FD, 2 even ; -------------------------------------------------------------------------------- ; sprite mappings ; -------------------------------------------------------------------------------- Obj71_MapUnc_11396: BINCLUDE "mappings/sprite/obj71_a.bin" ; ---------------------------------------------------------------------------------------- ; Unknown sprite mappings ; ---------------------------------------------------------------------------------------- Obj1C_MapUnc_113D6: BINCLUDE "mappings/sprite/obj1C_a.bin" ; -------------------------------------------------------------------------------- ; Unknown sprite mappings ; -------------------------------------------------------------------------------- Obj1C_MapUnc_113EE: BINCLUDE "mappings/sprite/obj1C_b.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj1C_MapUnc_11406: BINCLUDE "mappings/sprite/obj1C_c.bin" ; -------------------------------------------------------------------------------- ; sprite mappings ; -------------------------------------------------------------------------------- Obj1C_MapUnc_114AE: BINCLUDE "mappings/sprite/obj1C_d.bin" ; -------------------------------------------------------------------------------- ; sprite mappings ; -------------------------------------------------------------------------------- Obj1C_MapUnc_11552: BINCLUDE "mappings/sprite/obj1C_e.bin" ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj71_MapUnc_11576: BINCLUDE "mappings/sprite/obj71_b.bin" ; =========================================================================== if gameRevision<2 nop endif ; ---------------------------------------------------------------------------- ; Object 2A - Stomper from MCZ ; ---------------------------------------------------------------------------- ; Sprite_115C4: Obj2A: moveq #0,d0 move.b routine(a0),d0 move.w Obj2A_Index(pc,d0.w),d1 jmp Obj2A_Index(pc,d1.w) ; =========================================================================== ; off_115D2: Obj2A_Index: offsetTable offsetTableEntry.w Obj2A_Init ; 0 offsetTableEntry.w Obj2A_Main ; 2 ; =========================================================================== ; loc_115D6: Obj2A_Init: addq.b #2,routine(a0) move.l #Obj2A_MapUnc_11666,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,2,0),art_tile(a0) bsr.w Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #4,priority(a0) move.w y_pos(a0),objoff_32(a0) move.b #$50,y_radius(a0) bset #4,render_flags(a0) ; loc_11610: Obj2A_Main: tst.b routine_secondary(a0) bne.s + addq.w #1,objoff_30(a0) cmpi.w #$60,objoff_30(a0) bne.s ++ move.b #2,routine_secondary(a0) bra.s ++ ; =========================================================================== + subq.w #8,objoff_30(a0) bhi.s + move.w #0,objoff_30(a0) move.b #0,routine_secondary(a0) + move.w objoff_32(a0),d0 sub.w objoff_30(a0),d0 move.w d0,y_pos(a0) moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 move.w #$40,d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsrto (SolidObject).l, JmpTo2_SolidObject bra.w MarkObjGone ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj2A_MapUnc_11666: BINCLUDE "mappings/sprite/obj2A.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 2D - One way barrier from CPZ and DEZ ; ---------------------------------------------------------------------------- ; Sprite_1169A: Obj2D: moveq #0,d0 move.b routine(a0),d0 move.w Obj2D_Index(pc,d0.w),d1 jmp Obj2D_Index(pc,d1.w) ; =========================================================================== ; off_116A8: Obj2D_Index: offsetTable offsetTableEntry.w Obj2D_Init ; 0 offsetTableEntry.w Obj2D_Main ; 2 ; =========================================================================== ; loc_116AC: Obj2D_Init: addq.b #2,routine(a0) move.l #Obj2D_MapUnc_11822,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_HtzValveBarrier,1,0),art_tile(a0) move.b #8,width_pixels(a0) cmpi.b #metropolis_zone,(Current_Zone).w beq.s + cmpi.b #metropolis_zone_2,(Current_Zone).w bne.s ++ + move.w #make_art_tile(ArtTile_ArtKos_LevelArt,3,0),art_tile(a0) move.b #$C,width_pixels(a0) + cmpi.b #chemical_plant_zone,(Current_Zone).w bne.s + move.w #make_art_tile(ArtTile_ArtNem_ConstructionStripes_2,1,0),art_tile(a0) move.b #8,width_pixels(a0) + cmpi.b #death_egg_zone,(Current_Zone).w bne.s + move.w #make_art_tile(ArtTile_ArtNem_ConstructionStripes_1,1,0),art_tile(a0) move.b #8,width_pixels(a0) + cmpi.b #aquatic_ruin_zone,(Current_Zone).w bne.s + move.w #make_art_tile(ArtTile_ArtNem_ARZBarrierThing,1,0),art_tile(a0) move.b #8,width_pixels(a0) + bsr.w Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #4,priority(a0) move.w y_pos(a0),objoff_32(a0) move.b subtype(a0),mapping_frame(a0) move.w x_pos(a0),d2 move.w d2,d3 subi.w #$200,d2 addi.w #$18,d3 btst #0,status(a0) beq.s + subi.w #-$1E8,d2 addi.w #$1E8,d3 + move.w d2,objoff_38(a0) move.w d3,objoff_3A(a0) ; loc_1175E: Obj2D_Main: btst #0,status(a0) bne.s + move.w objoff_38(a0),d2 move.w x_pos(a0),d3 tst.b routine_secondary(a0) ; check if barrier is moving up beq.s ++ move.w objoff_3A(a0),d3 bra.s ++ ; =========================================================================== + move.w x_pos(a0),d2 move.w objoff_3A(a0),d3 tst.b routine_secondary(a0) ; check if barrier is moving up beq.s + move.w objoff_38(a0),d2 + move.w objoff_32(a0),d4 move.w d4,d5 subi.w #$20,d4 addi.w #$20,d5 move.b #0,routine_secondary(a0) ; set barrier to move down, check if characters are in area lea (MainCharacter).w,a1 ; a1=character bsr.s Obj2D_CheckCharacter lea (Sidekick).w,a1 ; a1=character bsr.s Obj2D_CheckCharacter tst.b routine_secondary(a0) ; check if barrier is moving up beq.s + cmpi.w #$40,objoff_30(a0) ; check if barrier is high enough beq.s +++ addq.w #8,objoff_30(a0) ; move barrier up bra.s ++ ; =========================================================================== + tst.w objoff_30(a0) ; check if barrier is not in original position beq.s ++ subq.w #8,objoff_30(a0) ; move barrier down + move.w objoff_32(a0),d0 ; set the barrier y position sub.w objoff_30(a0),d0 move.w d0,y_pos(a0) + moveq #0,d1 ; perform solid object collision move.b width_pixels(a0),d1 addi.w #$B,d1 move.w #$20,d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsrto (SolidObject).l, JmpTo2_SolidObject bra.w MarkObjGone ; delete object if off screen ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_117F4 Obj2D_CheckCharacter: ; rect ltrb (d2, d4, d3, d5) move.w x_pos(a1),d0 cmp.w d2,d0 blt.w return_11820 cmp.w d3,d0 bhs.w return_11820 move.w y_pos(a1),d0 cmp.w d4,d0 blo.w return_11820 cmp.w d5,d0 bhs.w return_11820 tst.b obj_control(a1) bmi.s return_11820 move.b #2,routine_secondary(a0) ; set barrier to move up return_11820: rts ; End of function Obj2D_CheckCharacter ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj2D_MapUnc_11822: BINCLUDE "mappings/sprite/obj2D.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo2_SolidObject jmp (SolidObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 28 - Animal and the 100 points from a badnik ; ---------------------------------------------------------------------------- animal_ground_routine_base = objoff_30 animal_ground_x_vel = objoff_32 animal_ground_y_vel = objoff_34 ; Sprite_1188C: Obj28: moveq #0,d0 move.b routine(a0),d0 move.w Obj28_Index(pc,d0.w),d1 jmp Obj28_Index(pc,d1.w) ; =========================================================================== ; off_1189A: Obj28_Index: offsetTable offsetTableEntry.w Obj28_Init ; 0 offsetTableEntry.w Obj28_Main ; 2 offsetTableEntry.w Obj28_Walk ; 4 offsetTableEntry.w Obj28_Fly ; 6 offsetTableEntry.w Obj28_Walk ; 8 offsetTableEntry.w Obj28_Walk ; $A offsetTableEntry.w Obj28_Walk ; $C offsetTableEntry.w Obj28_Fly ; $E offsetTableEntry.w Obj28_Walk ; $10 offsetTableEntry.w Obj28_Fly ; $12 offsetTableEntry.w Obj28_Walk ; $14 offsetTableEntry.w Obj28_Walk ; $16 offsetTableEntry.w Obj28_Walk ; $18 offsetTableEntry.w Obj28_Walk ; $1A offsetTableEntry.w Obj28_Prison ; $1C ; These are the S1 ending actions: offsetTableEntry.w Obj28_FlickyWait ; $1E offsetTableEntry.w Obj28_FlickyWait ; $20 offsetTableEntry.w Obj28_FlickyJump ; $22 offsetTableEntry.w Obj28_RabbitWait ; $24 offsetTableEntry.w Obj28_LandJump ; $26 offsetTableEntry.w Obj28_SingleBounce ; $28 offsetTableEntry.w Obj28_LandJump ; $2A offsetTableEntry.w Obj28_SingleBounce ; $2C offsetTableEntry.w Obj28_LandJump ; $2E offsetTableEntry.w Obj28_FlyBounce ; $30 offsetTableEntry.w Obj28_DoubleBounce ; $32 ; byte_118CE: Obj28_ZoneAnimals: zoneOrderedTable 1,2 zoneAnimals macro first,second zoneTableEntry.b (Obj28_Properties_first - Obj28_Properties) / 8 zoneTableEntry.b (Obj28_Properties_second - Obj28_Properties) / 8 endm ; This table declares what animals will appear in the zone. ; When an enemy is destroyed, a random animal is chosen from the 2 selected animals. ; Note: you must also load the corresponding art in the PLCs. zoneAnimals.b Squirrel, Bird ; EHZ zoneAnimals.b Squirrel, Bird ; Zone 1 zoneAnimals.b Squirrel, Bird ; WZ zoneAnimals.b Squirrel, Bird ; Zone 3 zoneAnimals.b Beaver, Eagle ; MTZ zoneAnimals.b Beaver, Eagle ; MTZ zoneAnimals.b Beaver, Eagle ; WFZ zoneAnimals.b Beaver, Eagle ; HTZ zoneAnimals.b Mouse, Seal ; HPZ zoneAnimals.b Mouse, Seal ; Zone 9 zoneAnimals.b Penguin, Seal ; OOZ zoneAnimals.b Mouse, Chicken ; MCZ zoneAnimals.b Bear, Bird ; CNZ zoneAnimals.b Rabbit, Eagle ; CPZ zoneAnimals.b Pig, Chicken ; DEZ zoneAnimals.b Penguin, Bird ; ARZ zoneAnimals.b Turtle, Chicken ; SCZ zoneTableEnd ; word_118F0: Obj28_Properties: obj28decl macro xvel,yvel,mappings,{INTLABEL} Obj28_Properties___LABEL__: label * dc.w xvel dc.w yvel dc.l mappings endm ; This table declares the speed and mappings of each animal. Rabbit: obj28decl -$200,-$400,Obj28_MapUnc_11EAC Chicken: obj28decl -$200,-$300,Obj28_MapUnc_11E1C Penguin: obj28decl -$180,-$300,Obj28_MapUnc_11EAC Seal: obj28decl -$140,-$180,Obj28_MapUnc_11E88 Pig: obj28decl -$1C0,-$300,Obj28_MapUnc_11E64 Bird: obj28decl -$300,-$400,Obj28_MapUnc_11E1C Squirrel: obj28decl -$280,-$380,Obj28_MapUnc_11E40 Eagle: obj28decl -$280,-$300,Obj28_MapUnc_11E1C Mouse: obj28decl -$200,-$380,Obj28_MapUnc_11E40 Beaver: obj28decl -$2C0,-$300,Obj28_MapUnc_11E40 Turtle: obj28decl -$140,-$200,Obj28_MapUnc_11E40 Bear: obj28decl -$200,-$300,Obj28_MapUnc_11E40 ; The following tables tell the properties of animals based on their subtype. ; word_11950: Obj28_Speeds: dc.w -$440, -$400 dc.w -$440, -$400 ; 2 dc.w -$440, -$400 ; 4 dc.w -$300, -$400 ; 6 dc.w -$300, -$400 ; 8 dc.w -$180, -$300 ; 10 dc.w -$180, -$300 ; 12 dc.w -$140, -$180 ; 14 dc.w -$1C0, -$300 ; 16 dc.w -$200, -$300 ; 18 dc.w -$280, -$380 ; 20 ; off_1197C: Obj28_Mappings: dc.l Obj28_MapUnc_11E1C dc.l Obj28_MapUnc_11E1C ; 1 dc.l Obj28_MapUnc_11E1C ; 2 dc.l Obj28_MapUnc_11EAC ; 3 dc.l Obj28_MapUnc_11EAC ; 4 dc.l Obj28_MapUnc_11EAC ; 5 dc.l Obj28_MapUnc_11EAC ; 6 dc.l Obj28_MapUnc_11E88 ; 7 dc.l Obj28_MapUnc_11E64 ; 8 dc.l Obj28_MapUnc_11E1C ; 9 dc.l Obj28_MapUnc_11E40 ; 10 ; word_119A8: Obj28_ArtLocations: dc.w ArtTile_ArtNem_S1EndFlicky ; 0 Flicky dc.w ArtTile_ArtNem_S1EndFlicky ; 1 Flicky dc.w ArtTile_ArtNem_S1EndFlicky ; 2 Flicky dc.w ArtTile_ArtNem_S1EndRabbit ; 3 Rabbit dc.w ArtTile_ArtNem_S1EndRabbit ; 4 Rabbit dc.w ArtTile_ArtNem_S1EndPenguin ; 5 Penguin dc.w ArtTile_ArtNem_S1EndPenguin ; 6 Penguin dc.w ArtTile_ArtNem_S1EndSeal ; 7 Seal dc.w ArtTile_ArtNem_S1EndPig ; 8 Pig dc.w ArtTile_ArtNem_S1EndChicken ; 9 Chicken dc.w ArtTile_ArtNem_S1EndSquirrel ; 10 Squirrel ; =========================================================================== ; loc_119BE: Obj28_Init: tst.b subtype(a0) beq.w Obj28_InitRandom moveq #0,d0 move.b subtype(a0),d0 add.w d0,d0 move.b d0,routine(a0) subi.w #$14,d0 move.w Obj28_ArtLocations(pc,d0.w),art_tile(a0) add.w d0,d0 move.l Obj28_Mappings(pc,d0.w),mappings(a0) lea Obj28_Speeds(pc),a1 move.w (a1,d0.w),animal_ground_x_vel(a0) move.w (a1,d0.w),x_vel(a0) move.w 2(a1,d0.w),animal_ground_y_vel(a0) move.w 2(a1,d0.w),y_vel(a0) bsr.w Adjust2PArtPointer move.b #$C,y_radius(a0) move.b #4,render_flags(a0) bset #0,render_flags(a0) move.b #6,priority(a0) move.b #8,width_pixels(a0) move.b #7,anim_frame_duration(a0) bra.w DisplaySprite ; =========================================================================== ; loc_11A2C: Obj28_InitRandom: addq.b #2,routine(a0) jsrto (RandomNumber).l, JmpTo_RandomNumber move.w #make_art_tile(ArtTile_ArtNem_Animal_1,0,0),art_tile(a0) andi.w #1,d0 beq.s + move.w #make_art_tile(ArtTile_ArtNem_Animal_2,0,0),art_tile(a0) + moveq #0,d1 move.b (Current_Zone).w,d1 add.w d1,d1 add.w d0,d1 lea Obj28_ZoneAnimals(pc),a1 move.b (a1,d1.w),d0 move.b d0,animal_ground_routine_base(a0) lsl.w #3,d0 lea Obj28_Properties(pc),a1 adda.w d0,a1 move.w (a1)+,animal_ground_x_vel(a0) move.w (a1)+,animal_ground_y_vel(a0) move.l (a1)+,mappings(a0) bsr.w Adjust2PArtPointer move.b #$C,y_radius(a0) move.b #4,render_flags(a0) bset #0,render_flags(a0) move.b #6,priority(a0) move.b #8,width_pixels(a0) move.b #7,anim_frame_duration(a0) move.b #2,mapping_frame(a0) move.w #-$400,y_vel(a0) tst.b objoff_38(a0) bne.s ++ bsr.w SingleObjLoad bne.s + _move.b #ObjID_Points,id(a1) ; load obj29 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w objoff_3E(a0),d0 lsr.w #1,d0 move.b d0,mapping_frame(a1) + bra.w DisplaySprite ; =========================================================================== + move.b #$1C,routine(a0) clr.w x_vel(a0) bra.w DisplaySprite ; =========================================================================== ;loc_11ADE Obj28_Main: tst.b render_flags(a0) bpl.w DeleteObject bsr.w ObjectMoveAndFall tst.w y_vel(a0) bmi.s + jsr (ObjCheckFloorDist).l tst.w d1 bpl.s + add.w d1,y_pos(a0) move.w animal_ground_x_vel(a0),x_vel(a0) move.w animal_ground_y_vel(a0),y_vel(a0) move.b #1,mapping_frame(a0) move.b animal_ground_routine_base(a0),d0 add.b d0,d0 addq.b #4,d0 move.b d0,routine(a0) tst.b objoff_38(a0) beq.s + btst #4,(Vint_runcount+3).w beq.s + neg.w x_vel(a0) bchg #0,render_flags(a0) + bra.w DisplaySprite ; =========================================================================== ;loc_11B38 Obj28_Walk: bsr.w ObjectMoveAndFall move.b #1,mapping_frame(a0) tst.w y_vel(a0) bmi.s + move.b #0,mapping_frame(a0) jsr (ObjCheckFloorDist).l tst.w d1 bpl.s + add.w d1,y_pos(a0) move.w animal_ground_y_vel(a0),y_vel(a0) + tst.b subtype(a0) bne.s Obj28_ChkDel tst.b render_flags(a0) bpl.w DeleteObject bra.w DisplaySprite ; =========================================================================== ;loc_11B74 Obj28_Fly: bsr.w ObjectMove addi.w #$18,y_vel(a0) tst.w y_vel(a0) bmi.s + jsr (ObjCheckFloorDist).l tst.w d1 bpl.s + add.w d1,y_pos(a0) move.w animal_ground_y_vel(a0),y_vel(a0) tst.b subtype(a0) beq.s + cmpi.b #$A,subtype(a0) beq.s + neg.w x_vel(a0) bchg #0,render_flags(a0) + subq.b #1,anim_frame_duration(a0) bpl.s + move.b #1,anim_frame_duration(a0) addq.b #1,mapping_frame(a0) andi.b #1,mapping_frame(a0) + tst.b subtype(a0) bne.s Obj28_ChkDel tst.b render_flags(a0) bpl.w DeleteObject bra.w DisplaySprite ; =========================================================================== ;loc_11BD8 Obj28_ChkDel: move.w x_pos(a0),d0 sub.w (MainCharacter+x_pos).w,d0 bcs.s + subi.w #$180,d0 bpl.s + tst.b render_flags(a0) bpl.w DeleteObject + bra.w DisplaySprite ; =========================================================================== ;loc_11BF4 Obj28_Prison: tst.b render_flags(a0) bpl.w DeleteObject subq.w #1,objoff_36(a0) bne.w + move.b #2,routine(a0) move.b #1,priority(a0) + bra.w DisplaySprite ; =========================================================================== ;loc_11C14 Obj28_FlickyWait: bsr.w ChkAnimalInRange bcc.s + move.w animal_ground_x_vel(a0),x_vel(a0) move.w animal_ground_y_vel(a0),y_vel(a0) move.b #$E,routine(a0) bra.w Obj28_Fly ; =========================================================================== + bra.w Obj28_ChkDel ; =========================================================================== ;loc_11C34 Obj28_FlickyJump: bsr.w ChkAnimalInRange bpl.s + clr.w x_vel(a0) clr.w animal_ground_x_vel(a0) bsr.w ObjectMove addi.w #$18,y_vel(a0) bsr.w AnimalJump bsr.w AnimalFaceSonic subq.b #1,anim_frame_duration(a0) bpl.s + move.b #1,anim_frame_duration(a0) addq.b #1,mapping_frame(a0) andi.b #1,mapping_frame(a0) + bra.w Obj28_ChkDel ; =========================================================================== ;loc_11C6E Obj28_RabbitWait: bsr.w ChkAnimalInRange bpl.s ++ move.w animal_ground_x_vel(a0),x_vel(a0) move.w animal_ground_y_vel(a0),y_vel(a0) move.b #4,routine(a0) bra.w Obj28_Walk ; =========================================================================== ;loc_11C8A Obj28_DoubleBounce: bsr.w ObjectMoveAndFall move.b #1,mapping_frame(a0) tst.w y_vel(a0) bmi.s ++ move.b #0,mapping_frame(a0) jsr (ObjCheckFloorDist).l tst.w d1 bpl.s ++ not.b objoff_29(a0) bne.s + neg.w x_vel(a0) bchg #0,render_flags(a0) + add.w d1,y_pos(a0) move.w animal_ground_y_vel(a0),y_vel(a0) + bra.w Obj28_ChkDel ; =========================================================================== ;loc_11CC8 Obj28_LandJump: bsr.w ChkAnimalInRange bpl.s + clr.w x_vel(a0) clr.w animal_ground_x_vel(a0) bsr.w ObjectMoveAndFall bsr.w AnimalJump bsr.w AnimalFaceSonic + bra.w Obj28_ChkDel ; =========================================================================== ;loc_11CE6 Obj28_SingleBounce: bsr.w ChkAnimalInRange bpl.s + bsr.w ObjectMoveAndFall move.b #1,mapping_frame(a0) tst.w y_vel(a0) bmi.s + move.b #0,mapping_frame(a0) jsr (ObjCheckFloorDist).l tst.w d1 bpl.s + neg.w x_vel(a0) bchg #0,render_flags(a0) add.w d1,y_pos(a0) move.w animal_ground_y_vel(a0),y_vel(a0) + bra.w Obj28_ChkDel ; =========================================================================== ;loc_11D24 Obj28_FlyBounce: bsr.w ChkAnimalInRange bpl.s +++ bsr.w ObjectMove addi.w #$18,y_vel(a0) tst.w y_vel(a0) bmi.s ++ jsr (ObjCheckFloorDist).l tst.w d1 bpl.s ++ not.b objoff_29(a0) bne.s + neg.w x_vel(a0) bchg #0,render_flags(a0) + add.w d1,y_pos(a0) move.w animal_ground_y_vel(a0),y_vel(a0) + subq.b #1,anim_frame_duration(a0) bpl.s + move.b #1,anim_frame_duration(a0) addq.b #1,mapping_frame(a0) andi.b #1,mapping_frame(a0) + bra.w Obj28_ChkDel ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_11D78 AnimalJump: move.b #1,mapping_frame(a0) tst.w y_vel(a0) bmi.s + ; rts move.b #0,mapping_frame(a0) jsr (ObjCheckFloorDist).l tst.w d1 bpl.s + ; rts add.w d1,y_pos(a0) move.w animal_ground_y_vel(a0),y_vel(a0) + rts ; End of function AnimalJump ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_11DA0 AnimalFaceSonic: bset #0,render_flags(a0) move.w x_pos(a0),d0 sub.w (MainCharacter+x_pos).w,d0 bcc.s + ; rts bclr #0,render_flags(a0) + rts ; End of function AnimalFaceSonic ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_11DB8 ChkAnimalInRange: move.w (MainCharacter+x_pos).w,d0 sub.w x_pos(a0),d0 subi.w #$B8,d0 rts ; End of function ChkAnimalInRange ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 29 - "100 points" text ; ---------------------------------------------------------------------------- ; Sprite_11DC6: Obj29: moveq #0,d0 move.b routine(a0),d0 move.w Obj29_Index(pc,d0.w),d1 jmp Obj29_Index(pc,d1.w) ; =========================================================================== ; off_11DD4: Obj29_Index: offsetTable offsetTableEntry.w Obj29_Init ; 0 offsetTableEntry.w Obj29_Main ; 2 ; =========================================================================== Obj29_Init: addq.b #2,routine(a0) move.l #Obj29_MapUnc_11ED0,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Numbers,0,1),art_tile(a0) bsr.w Adjust2PArtPointer move.b #4,render_flags(a0) move.b #1,priority(a0) move.b #8,width_pixels(a0) move.w #-$300,y_vel(a0) ; set initial speed (upwards) Obj29_Main: tst.w y_vel(a0) ; test speed bpl.w DeleteObject ; if it's positive (>= 0), delete the object bsr.w ObjectMove ; move the points addi.w #$18,y_vel(a0) ; slow down bra.w DisplaySprite ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj28_MapUnc_11E1C: BINCLUDE "mappings/sprite/obj28_a.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj28_MapUnc_11E40: BINCLUDE "mappings/sprite/obj28_b.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj28_MapUnc_11E64: BINCLUDE "mappings/sprite/obj28_c.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj28_MapUnc_11E88: BINCLUDE "mappings/sprite/obj28_d.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj28_MapUnc_11EAC: BINCLUDE "mappings/sprite/obj28_e.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj29_MapUnc_11ED0: BINCLUDE "mappings/sprite/obj29.bin" if ~~removeJmpTos JmpTo_RandomNumber jmp (RandomNumber).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 25 - A ring (usually only placed through placement mode) ; ---------------------------------------------------------------------------- ; Obj_Ring: Obj25: moveq #0,d0 move.b routine(a0),d0 move.w Obj25_Index(pc,d0.w),d1 jmp Obj25_Index(pc,d1.w) ; =========================================================================== ; Obj_25_subtbl: Obj25_Index: offsetTable offsetTableEntry.w Obj25_Init ; 0 offsetTableEntry.w Obj25_Animate ; 2 offsetTableEntry.w Obj25_Collect ; 4 offsetTableEntry.w Obj25_Sparkle ; 6 offsetTableEntry.w Obj25_Delete ; 8 ; =========================================================================== ; Obj_25_sub_0: Obj25_Init: addq.b #2,routine(a0) move.w x_pos(a0),objoff_32(a0) move.l #Obj25_MapUnc_12382,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Ring,1,0),art_tile(a0) bsr.w Adjust2PArtPointer move.b #4,render_flags(a0) move.b #2,priority(a0) move.b #$47,collision_flags(a0) move.b #8,width_pixels(a0) ; Obj_25_sub_2: Obj25_Animate: move.b (Rings_anim_frame).w,mapping_frame(a0) move.w objoff_32(a0),d0 bra.w MarkObjGone2 ; =========================================================================== ; Obj_25_sub_4: Obj25_Collect: addq.b #2,routine(a0) move.b #0,collision_flags(a0) move.b #1,priority(a0) bsr.s CollectRing ; Obj_25_sub_6: Obj25_Sparkle: lea (Ani_Ring).l,a1 bsr.w AnimateSprite bra.w DisplaySprite ; =========================================================================== ; BranchTo4_DeleteObject Obj25_Delete: bra.w DeleteObject ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_11FC2: CollectRing: tst.b parent+1(a0) ; did Tails collect the ring? bne.s CollectRing_Tails ; if yes, branch CollectRing_Sonic: cmpi.w #999,(Rings_Collected).w ; did Sonic collect 999 or more rings? bhs.s CollectRing_1P ; if yes, branch addq.w #1,(Rings_Collected).w ; add 1 to the number of collected rings CollectRing_1P: if gameRevision=0 cmpi.w #999,(Ring_count).w ; does the player 1 have 999 or more rings? bhs.s + ; if yes, skip the increment addq.w #1,(Ring_count).w ; add 1 to the ring count + ori.b #1,(Update_HUD_rings).w ; set flag to update the ring counter in the HUD move.w #SndID_Ring,d0 ; prepare to play the ring sound else move.w #SndID_Ring,d0 ; prepare to play the ring sound cmpi.w #999,(Ring_count).w ; does the player 1 have 999 or more rings? bhs.s JmpTo_PlaySoundStereo ; if yes, play the ring sound addq.w #1,(Ring_count).w ; add 1 to the ring count ori.b #1,(Update_HUD_rings).w ; set flag to update the ring counter in the HUD endif cmpi.w #100,(Ring_count).w ; does the player 1 have less than 100 rings? blo.s JmpTo_PlaySoundStereo ; if yes, play the ring sound bset #1,(Extra_life_flags).w ; test and set the flag for the first extra life beq.s + ; if it was clear before, branch cmpi.w #200,(Ring_count).w ; does the player 1 have less than 200 rings? blo.s JmpTo_PlaySoundStereo ; if yes, play the ring sound bset #2,(Extra_life_flags).w ; test and set the flag for the second extra life bne.s JmpTo_PlaySoundStereo ; if it was set before, play the ring sound + addq.b #1,(Life_count).w ; add 1 to the life count addq.b #1,(Update_HUD_lives).w ; add 1 to the displayed life count move.w #MusID_ExtraLife,d0 ; prepare to play the extra life jingle JmpTo_PlaySoundStereo jmp (PlaySoundStereo).l ; =========================================================================== rts ; =========================================================================== CollectRing_Tails: cmpi.w #999,(Rings_Collected_2P).w ; did Tails collect 999 or more rings? bhs.s + ; if yes, branch addq.w #1,(Rings_Collected_2P).w ; add 1 to the number of collected rings + cmpi.w #999,(Ring_count_2P).w ; does Tails have 999 or more rings? bhs.s + ; if yes, branch addq.w #1,(Ring_count_2P).w ; add 1 to the ring count + tst.w (Two_player_mode).w ; are we in a 2P game? beq.s CollectRing_1P ; if not, branch ; CollectRing_2P: ori.b #1,(Update_HUD_rings_2P).w ; set flag to update the ring counter in the second player's HUD move.w #SndID_Ring,d0 ; prepare to play the ring sound cmpi.w #100,(Ring_count_2P).w ; does the player 2 have less than 100 rings? blo.s JmpTo2_PlaySoundStereo ; if yes, play the ring sound bset #1,(Extra_life_flags_2P).w ; test and set the flag for the first extra life beq.s + ; if it was clear before, branch cmpi.w #200,(Ring_count_2P).w ; does the player 2 have less than 200 rings? blo.s JmpTo2_PlaySoundStereo ; if yes, play the ring sound bset #2,(Extra_life_flags_2P).w ; test and set the flag for the second extra life bne.s JmpTo2_PlaySoundStereo ; if it was set before, play the ring sound + addq.b #1,(Life_count_2P).w ; add 1 to the life count addq.b #1,(Update_HUD_lives_2P).w ; add 1 to the displayed life count move.w #MusID_ExtraLife,d0 ; prepare to play the extra life jingle JmpTo2_PlaySoundStereo jmp (PlaySoundStereo).l ; End of function CollectRing ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 37 - Scattering rings (generated when Sonic is hurt and has rings) ; ---------------------------------------------------------------------------- ; Sprite_12078: Obj37: moveq #0,d0 move.b routine(a0),d0 move.w Obj37_Index(pc,d0.w),d1 jmp Obj37_Index(pc,d1.w) ; =========================================================================== ; Obj_37_subtbl: Obj37_Index: offsetTable offsetTableEntry.w Obj37_Init ; 0 offsetTableEntry.w Obj37_Main ; 2 offsetTableEntry.w Obj37_Collect ; 4 offsetTableEntry.w Obj37_Sparkle ; 6 offsetTableEntry.w Obj37_Delete ; 8 ; =========================================================================== ; Obj_37_sub_0: Obj37_Init: movea.l a0,a1 moveq #0,d5 move.w (Ring_count).w,d5 tst.b parent+1(a0) beq.s + move.w (Ring_count_2P).w,d5 + moveq #$20,d0 cmp.w d0,d5 blo.s + move.w d0,d5 + subq.w #1,d5 move.w #$288,d4 bra.s + ; =========================================================================== - bsr.w SingleObjLoad bne.w +++ + _move.b #ObjID_LostRings,id(a1) ; load obj37 addq.b #2,routine(a1) move.b #8,y_radius(a1) move.b #8,x_radius(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.l #Obj25_MapUnc_12382,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_Ring,1,0),art_tile(a1) bsr.w Adjust2PArtPointer2 move.b #$84,render_flags(a1) move.b #3,priority(a1) move.b #$47,collision_flags(a1) move.b #8,width_pixels(a1) move.b #-1,(Ring_spill_anim_counter).w tst.w d4 bmi.s + move.w d4,d0 jsrto (CalcSine).l, JmpTo4_CalcSine move.w d4,d2 lsr.w #8,d2 asl.w d2,d0 asl.w d2,d1 move.w d0,d2 move.w d1,d3 addi.b #$10,d4 bcc.s + subi.w #$80,d4 bcc.s + move.w #$288,d4 + move.w d2,x_vel(a1) move.w d3,y_vel(a1) neg.w d2 neg.w d4 dbf d5,- + move.w #SndID_RingSpill,d0 jsr (PlaySoundStereo).l tst.b parent+1(a0) bne.s + move.w #0,(Ring_count).w move.b #$80,(Update_HUD_rings).w move.b #0,(Extra_life_flags).w bra.s Obj37_Main ; =========================================================================== + move.w #0,(Ring_count_2P).w move.b #$80,(Update_HUD_rings_2P).w move.b #0,(Extra_life_flags_2P).w ; Obj_37_sub_2: Obj37_Main: move.b (Ring_spill_anim_frame).w,mapping_frame(a0) bsr.w ObjectMove addi.w #$18,y_vel(a0) bmi.s loc_121B8 move.b (Vint_runcount+3).w,d0 add.b d7,d0 andi.b #7,d0 bne.s loc_121B8 tst.b render_flags(a0) bpl.s loc_121D0 jsr (RingCheckFloorDist).l tst.w d1 bpl.s loc_121B8 add.w d1,y_pos(a0) move.w y_vel(a0),d0 asr.w #2,d0 sub.w d0,y_vel(a0) neg.w y_vel(a0) loc_121B8: tst.b (Ring_spill_anim_counter).w beq.s Obj37_Delete move.w (Camera_Max_Y_pos_now).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 blo.s Obj37_Delete bra.w DisplaySprite ; =========================================================================== loc_121D0: tst.w (Two_player_mode).w bne.w Obj37_Delete bra.s loc_121B8 ; =========================================================================== ; Obj_37_sub_4: Obj37_Collect: addq.b #2,routine(a0) move.b #0,collision_flags(a0) move.b #1,priority(a0) bsr.w CollectRing ; Obj_37_sub_6: Obj37_Sparkle: lea (Ani_Ring).l,a1 bsr.w AnimateSprite bra.w DisplaySprite ; =========================================================================== ; BranchTo5_DeleteObject Obj37_Delete: bra.w DeleteObject ; Unused - dead code/data S1 big ring: ; =========================================================================== ; BigRing: ; a0=object moveq #0,d0 move.b routine(a0),d0 move.w BigRing_States(pc,d0.w),d1 jmp BigRing_States(pc,d1.w) ; =========================================================================== BigRing_States: offsetTable offsetTableEntry.w BigRing_Init ; 0 offsetTableEntry.w BigRing_Main ; 2 offsetTableEntry.w BigRing_Enter ; 4 offsetTableEntry.w BigRing_Delete ; 6 ; =========================================================================== ; loc_12216: BigRing_Init: move.l #Obj37_MapUnc_123E6,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_BigRing,1,0),art_tile(a0) bsr.w Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$40,width_pixels(a0) tst.b render_flags(a0) bpl.s BigRing_Main cmpi.b #6,(Got_Emerald).w beq.w BigRing_Delete cmpi.w #50,(Ring_count).w bhs.s + rts ; =========================================================================== + addq.b #2,routine(a0) move.b #2,priority(a0) move.b #$52,collision_flags(a0) move.w #$C40,(BigRingGraphics).w ; loc_12264: BigRing_Main: move.b (Rings_anim_frame).w,mapping_frame(a0) move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w DeleteObject bra.w DisplaySprite ; =========================================================================== ; loc_12282: BigRing_Enter: subq.b #2,routine(a0) move.b #0,collision_flags(a0) bsr.w SingleObjLoad bne.w + ; Note: the object ID is not set ; If you want to restore the big ring object, you'll also have to ; restore the ring flash object (right after this) and assign its ID to ; the created object here (a1). ;move.b #ObjID_BigRingFlash,id(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.l a0,objoff_3C(a1) move.w (MainCharacter+x_pos).w,d0 cmp.w x_pos(a0),d0 blo.s + bset #0,render_flags(a1) + move.w #SndID_EnterGiantRing,d0 jsr (PlaySoundStereo).l bra.s BigRing_Main ; =========================================================================== ; BranchTo6_DeleteObject BigRing_Delete: bra.w DeleteObject ; Unused - dead code/data S1 ring flash: ; =========================================================================== ; BigRingFlash: ; a0=object moveq #0,d0 move.b routine(a0),d0 move.w BigRingFlash_States(pc,d0.w),d1 jmp BigRingFlash_States(pc,d1.w) ; =========================================================================== BigRingFlash_States: offsetTable offsetTableEntry.w BigRingFlash_Init ; 0 offsetTableEntry.w BigRingFlash_Main ; 2 offsetTableEntry.w BigRingFlash_Delete ; 4 ; =========================================================================== ; loc_122D8: BigRingFlash_Init: addq.b #2,routine(a0) move.l #Obj37_MapUnc_124E6,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_BigRing_Flash,1,0),art_tile(a0) bsr.w Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #0,priority(a0) move.b #$20,width_pixels(a0) move.b #-1,mapping_frame(a0) ; loc_12306: BigRingFlash_Main: bsr.s BigRingFlash_Animate move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w DeleteObject bra.w DisplaySprite ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_12320: BigRingFlash_Animate: subq.b #1,anim_frame_duration(a0) ; subtract 1 from frame duration bpl.s + ; rts move.b #1,anim_frame_duration(a0) ; reset frame duration (2 frames) addq.b #1,mapping_frame(a0) ; use next animation frame cmpi.b #8,mapping_frame(a0) ; have we reached the end of the animation frames? bhs.s ++ ; if yes, branch cmpi.b #3,mapping_frame(a0) ; have we reached the 4th animation frame? bne.s + ; rts ; if not, return movea.l objoff_3C(a0),a1 ; a1=object ; get the parent big ring object move.b #6,routine(a1) ; set its routine to "delete" move.b #AniIDSonAni_Blank,(MainCharacter+anim).w ; change the character's animation move.b #1,(SpecialStage_flag_2P).w lea (MainCharacter).w,a1 ; a1=character bclr #status_sec_isInvincible,status_secondary(a1) bclr #status_sec_hasShield,status_secondary(a1) + rts ; =========================================================================== + addq.b #2,routine(a0) move.w #0,(MainCharacter).w ; delete the player object addq.l #4,sp rts ; End of function BigRingFlash_Animate ; =========================================================================== ; BranchTo7_DeleteObject BigRingFlash_Delete: bra.w DeleteObject ; end of dead code/data ; =========================================================================== ; animation script ; byte_1237A: Ani_Ring: offsetTable offsetTableEntry.w + ; 0 + dc.b 5, 4, 5, 6, 7,$FC ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj25_MapUnc_12382: BINCLUDE "mappings/sprite/obj37_a.bin" ; ------------------------------------------------------------------------------- ; Unused sprite mappings ; ------------------------------------------------------------------------------- Obj37_MapUnc_123E6: BINCLUDE "mappings/sprite/obj37_b.bin" ; ------------------------------------------------------------------------------- ; Unused sprite mappings ; ------------------------------------------------------------------------------- Obj37_MapUnc_124E6: BINCLUDE "mappings/sprite/obj37_c.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object DC - Ring prize from Casino Night Zone ; ---------------------------------------------------------------------------- casino_prize_x_pos = objoff_30 ; X position of the ring with greater precision casino_prize_y_pos = objoff_34 ; Y position of the ring with greater precision casino_prize_machine_x_pos = objoff_38 ; X position of the slot machine that generated the ring casino_prize_machine_y_pos = objoff_3A ; Y position of the slot machine that generated the ring casino_prize_display_delay = objoff_3C ; number of frames before which the ring is displayed ; Sprite_125E6: ObjDC: moveq #0,d0 move.b routine(a0),d0 move.w ObjDC_Index(pc,d0.w),d1 jmp ObjDC_Index(pc,d1.w) ; =========================================================================== ; off_125F4: ObjDC_Index: offsetTable offsetTableEntry.w ObjDC_Main ; 0 offsetTableEntry.w ObjDC_Animate ; 2 offsetTableEntry.w ObjDC_Delete ; 4 ; =========================================================================== ; loc_125FA: ObjDC_Main: moveq #0,d1 move.w casino_prize_machine_x_pos(a0),d1 swap d1 move.l casino_prize_x_pos(a0),d0 sub.l d1,d0 asr.l #4,d0 sub.l d0,casino_prize_x_pos(a0) move.w casino_prize_x_pos(a0),x_pos(a0) moveq #0,d1 move.w casino_prize_machine_y_pos(a0),d1 swap d1 move.l casino_prize_y_pos(a0),d0 sub.l d1,d0 asr.l #4,d0 sub.l d0,casino_prize_y_pos(a0) move.w casino_prize_y_pos(a0),y_pos(a0) lea Ani_objDC(pc),a1 bsr.w AnimateSprite subq.w #1,casino_prize_display_delay(a0) bne.w DisplaySprite movea.l objoff_2A(a0),a1 subq.w #1,(a1) bsr.w CollectRing addi_.b #2,routine(a0) ; loc_1264E: ObjDC_Animate: lea Ani_Ring(pc),a1 bsr.w AnimateSprite bra.w DisplaySprite ; =========================================================================== ; BranchTo8_DeleteObject ObjDC_Delete: bra.w DeleteObject ; =========================================================================== ; animation script ; byte_1265E Ani_objDC: offsetTable offsetTableEntry.w + ; 0 + dc.b 1, 0, 1, 2, 3,$FF ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo4_CalcSine jmp (CalcSine).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 26 - Monitor ; ; The power-ups themselves are handled by the next object. This just does the ; monitor collision and graphics. ; ---------------------------------------------------------------------------- ; Obj_Monitor: Obj26: moveq #0,d0 move.b routine(a0),d0 move.w Obj26_Index(pc,d0.w),d1 jmp Obj26_Index(pc,d1.w) ; =========================================================================== ; obj_26_subtbl: Obj26_Index: offsetTable offsetTableEntry.w Obj26_Init ; 0 offsetTableEntry.w Obj26_Main ; 2 offsetTableEntry.w Obj26_Break ; 4 offsetTableEntry.w Obj26_Animate ; 6 offsetTableEntry.w BranchTo2_MarkObjGone ; 8 ; =========================================================================== ; obj_26_sub_0: Obj_26_Init: Obj26_Init: addq.b #2,routine(a0) move.b #$E,y_radius(a0) move.b #$E,x_radius(a0) move.l #Obj26_MapUnc_12D36,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Powerups,0,0),art_tile(a0) bsr.w Adjust2PArtPointer move.b #4,render_flags(a0) move.b #3,priority(a0) move.b #$F,width_pixels(a0) lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 bclr #7,2(a2,d0.w) btst #0,2(a2,d0.w) ; if this bit is set it means the monitor is already broken beq.s + move.b #8,routine(a0) ; set monitor to 'broken' state move.b #$B,mapping_frame(a0) rts ; --------------------------------------------------------------------------- + move.b #$46,collision_flags(a0) move.b subtype(a0),anim(a0) ; subtype = icon to display tst.w (Two_player_mode).w ; is it two player mode? beq.s Obj26_Main ; if not, branch move.b #9,anim(a0) ; use '?' icon ;obj_26_sub_2: Obj26_Main: move.b routine_secondary(a0),d0 beq.s SolidObject_Monitor ; only when secondary routine isn't 0 ; make monitor fall bsr.w ObjectMoveAndFall jsr (ObjCheckFloorDist).l tst.w d1 ; is monitor in the ground? bpl.w SolidObject_Monitor ; if not, branch add.w d1,y_pos(a0) ; move monitor out of the ground clr.w y_vel(a0) clr.b routine_secondary(a0) ; stop monitor from falling ; loc_1271C: SolidObject_Monitor: move.w #$1A,d1 ; monitor's width move.w #$F,d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w SolidObject_Monitor_Sonic movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 bsr.w SolidObject_Monitor_Tails Obj26_Animate: lea (Ani_obj26).l,a1 bsr.w AnimateSprite BranchTo2_MarkObjGone bra.w MarkObjGone ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_12756: SolidObject_Monitor_Sonic: btst d6,status(a0) ; is Sonic standing on the monitor? bne.s Obj26_ChkOverEdge ; if yes, branch cmpi.b #AniIDSonAni_Roll,anim(a1) ; is Sonic spinning? bne.w SolidObject_cont ; if not, branch rts ; End of function SolidObject_Monitor_Sonic ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_12768: SolidObject_Monitor_Tails: btst d6,status(a0) ; is Tails standing on the monitor? bne.s Obj26_ChkOverEdge ; if yes, branch tst.w (Two_player_mode).w ; is it two player mode? beq.w SolidObject_cont ; if not, branch ; in one player mode monitors always behave as solid for Tails cmpi.b #2,anim(a1) ; is Tails spinning? bne.w SolidObject_cont ; if not, branch rts ; End of function SolidObject_Monitor_Tails ; --------------------------------------------------------------------------- ; Checks if the player has walked over the edge of the monitor. ; --------------------------------------------------------------------------- ;loc_12782: Obj26_ChkOverEdge: move.w d1,d2 add.w d2,d2 btst #1,status(a1) ; is the character in the air? bne.s + ; if yes, branch ; check, if character is standing on move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s + ; branch, if character is behind the left edge of the monitor cmp.w d2,d0 blo.s Obj26_CharStandOn ; branch, if character is not beyond the right edge of the monitor + ; if the character isn't standing on the monitor bclr #3,status(a1) ; clear 'on object' bit bset #1,status(a1) ; set 'in air' bit bclr d6,status(a0) ; clear 'standing on' bit for the current character moveq #0,d4 rts ; --------------------------------------------------------------------------- ;loc_127B2: Obj26_CharStandOn: move.w d4,d2 bsr.w MvSonicOnPtfm moveq #0,d4 rts ; =========================================================================== ;obj_26_sub_4: Obj26_Break: move.b status(a0),d0 andi.b #standing_mask|pushing_mask,d0 ; is someone touching the monitor? beq.s Obj26_SpawnIcon ; if not, branch move.b d0,d1 andi.b #p1_standing|p1_pushing,d1 ; is it the main character? beq.s + ; if not, branch andi.b #$D7,(MainCharacter+status).w ori.b #2,(MainCharacter+status).w ; prevent Sonic from walking in the air + andi.b #p2_standing|p2_pushing,d0 ; is it the sidekick? beq.s Obj26_SpawnIcon ; if not, branch andi.b #$D7,(Sidekick+status).w ori.b #2,(Sidekick+status).w ; prevent Tails from walking in the air ;loc_127EC: Obj26_SpawnIcon: clr.b status(a0) addq.b #2,routine(a0) move.b #0,collision_flags(a0) bsr.w SingleObjLoad bne.s Obj26_SpawnSmoke _move.b #ObjID_MonitorContents,id(a1) ; load obj2E move.w x_pos(a0),x_pos(a1) ; set icon's position move.w y_pos(a0),y_pos(a1) move.b anim(a0),anim(a1) move.w parent(a0),parent(a1) ; parent gets the item ;loc_1281E: Obj26_SpawnSmoke: bsr.w SingleObjLoad bne.s + _move.b #ObjID_Explosion,id(a1) ; load obj27 addq.b #2,routine(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) + lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 bset #0,2(a2,d0.w) ; mark monitor as destroyed move.b #$A,anim(a0) bra.w DisplaySprite ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 2E - Monitor contents (code for power-up behavior and rising image) ; ---------------------------------------------------------------------------- Obj2E: moveq #0,d0 move.b routine(a0),d0 move.w Obj2E_Index(pc,d0.w),d1 jmp Obj2E_Index(pc,d1.w) ; =========================================================================== ; off_12862: Obj2E_Index: offsetTable offsetTableEntry.w Obj2E_Init ; 0 offsetTableEntry.w Obj2E_Raise ; 2 offsetTableEntry.w Obj2E_Wait ; 4 ; =========================================================================== ; Object initialization. Called if routine counter == 0. ; loc_12868: Obj2E_Init: addq.b #2,routine(a0) move.w #make_art_tile(ArtTile_ArtNem_Powerups,0,1),art_tile(a0) bsr.w Adjust2PArtPointer move.b #$24,render_flags(a0) move.b #3,priority(a0) move.b #8,width_pixels(a0) move.w #-$300,y_vel(a0) moveq #0,d0 move.b anim(a0),d0 tst.w (Two_player_mode).w ; is it two player mode? beq.s loc_128C6 ; if not, branch ; give 'random' item in two player mode move.w (Timer_frames).w,d0 ; use the timer to determine which item andi.w #7,d0 ; and 7 means there are 8 different items addq.w #1,d0 ; add 1 to prevent getting the static monitor tst.w (Two_player_items).w ; are monitors set to 'teleport only'? beq.s + ; if not, branch moveq #8,d0 ; force contents to be teleport + ; keep teleport monitor from causing unwanted effects cmpi.w #8,d0 ; teleport? bne.s + ; if not, branch move.b (Update_HUD_timer).w,d1 add.b (Update_HUD_timer_2P).w,d1 cmpi.b #2,d1 ; is either player done with the act? beq.s + ; if not, branch moveq #7,d0 ; give invincibility, instead + move.b d0,anim(a0) ;loc_128C6: loc_128C6: ; Determine correct mappings offset. addq.b #1,d0 move.b d0,mapping_frame(a0) movea.l #Obj26_MapUnc_12D36,a1 add.b d0,d0 adda.w (a1,d0.w),a1 addq.w #2,a1 move.l a1,mappings(a0) ; loc_128DE: Obj2E_Raise: bsr.s + bra.w DisplaySprite ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| + tst.w y_vel(a0) ; is icon still floating up? bpl.w + ; if not, branch bsr.w ObjectMove ; update position addi.w #$18,y_vel(a0) ; reduce upward speed rts ; --------------------------------------------------------------------------- + addq.b #2,routine(a0) move.w #$1D,anim_frame_duration(a0) movea.w parent(a0),a1 ; a1=character lea (Monitors_Broken).w,a2 cmpa.w #MainCharacter,a1 ; did Sonic break the monitor? beq.s + ; if yes, branch lea (Monitors_Broken_2P).w,a2 + moveq #0,d0 move.b anim(a0),d0 add.w d0,d0 move.w Obj2E_Types(pc,d0.w),d0 jmp Obj2E_Types(pc,d0.w) ; End of function ; =========================================================================== Obj2E_Types: offsetTable offsetTableEntry.w robotnik_monitor ; 0 - Static offsetTableEntry.w sonic_1up ; 1 - Sonic 1-up offsetTableEntry.w tails_1up ; 2 - Tails 1-up offsetTableEntry.w robotnik_monitor ; 3 - Robotnik offsetTableEntry.w super_ring ; 4 - Super Ring offsetTableEntry.w super_shoes ; 5 - Speed Shoes offsetTableEntry.w shield_monitor ; 6 - Shield offsetTableEntry.w invincible_monitor ; 7 - Invincibility offsetTableEntry.w teleport_monitor ; 8 - Teleport offsetTableEntry.w qmark_monitor ; 9 - Question mark ; =========================================================================== ; --------------------------------------------------------------------------- ; Robotnik Monitor ; hurts the player ; --------------------------------------------------------------------------- ; badnik_monitor: robotnik_monitor: addq.w #1,(a2) bra.w Touch_ChkHurt2 ; =========================================================================== ; --------------------------------------------------------------------------- ; Sonic 1up Monitor ; gives Sonic an extra life, or Tails in a 'Tails alone' game ; --------------------------------------------------------------------------- sonic_1up: addq.w #1,(Monitors_Broken).w addq.b #1,(Life_count).w addq.b #1,(Update_HUD_lives).w move.w #MusID_ExtraLife,d0 jmp (PlayMusic).l ; Play extra life music ; =========================================================================== ; --------------------------------------------------------------------------- ; Tails 1up Monitor ; gives Tails an extra life in two player mode ; --------------------------------------------------------------------------- tails_1up: addq.w #1,(Monitors_Broken_2P).w addq.b #1,(Life_count_2P).w addq.b #1,(Update_HUD_lives_2P).w move.w #MusID_ExtraLife,d0 jmp (PlayMusic).l ; Play extra life music ; =========================================================================== ; --------------------------------------------------------------------------- ; Super Ring Monitor ; gives the player 10 rings ; --------------------------------------------------------------------------- super_ring: addq.w #1,(a2) if gameRevision=0 lea (Ring_count).w,a2 lea (Update_HUD_rings).w,a3 lea (Extra_life_flags).w,a4 cmpa.w #MainCharacter,a1 beq.s + lea (Ring_count_2P).w,a2 lea (Update_HUD_rings_2P).w,a3 lea (Extra_life_flags_2P).w,a4 + ; give player 10 rings addi.w #10,(a2) else lea (Ring_count).w,a2 lea (Update_HUD_rings).w,a3 lea (Extra_life_flags).w,a4 lea (Rings_Collected).w,a5 cmpa.w #MainCharacter,a1 beq.s + lea (Ring_count_2P).w,a2 lea (Update_HUD_rings_2P).w,a3 lea (Extra_life_flags_2P).w,a4 lea (Rings_Collected_2P).w,a5 + addi.w #10,(a5) cmpi.w #999,(a5) blo.s + move.w #999,(a5) + ; give player 10 rings and max out at 999 addi.w #10,(a2) cmpi.w #999,(a2) blo.s + move.w #999,(a2) endif + ori.b #1,(a3) cmpi.w #100,(a2) blo.s + ; branch, if player has less than 100 rings bset #1,(a4) ; set flag for first 1up beq.s ChkPlayer_1up ; branch, if not yet set cmpi.w #200,(a2) blo.s + ; branch, if player has less than 200 rings bset #2,(a4) ; set flag for second 1up beq.s ChkPlayer_1up ; branch, if not yet set + move.w #SndID_Ring,d0 jmp (PlayMusic).l ; --------------------------------------------------------------------------- ;loc_129D4: ChkPlayer_1up: ; give 1up to correct player cmpa.w #MainCharacter,a1 beq.w sonic_1up bra.w tails_1up ; =========================================================================== ; --------------------------------------------------------------------------- ; Super Sneakers Monitor ; speeds the player up temporarily ; --------------------------------------------------------------------------- super_shoes: addq.w #1,(a2) bset #status_sec_hasSpeedShoes,status_secondary(a1) ; give super sneakers status move.w #$4B0,speedshoes_time(a1) cmpa.w #MainCharacter,a1 ; did the main character break the monitor? bne.s super_shoes_Tails ; if not, branch cmpi.w #2,(Player_mode).w ; is player using Tails? beq.s super_shoes_Tails ; if yes, branch move.w #$C00,(Sonic_top_speed).w ; set stats move.w #$18,(Sonic_acceleration).w move.w #$80,(Sonic_deceleration).w bra.s + ; --------------------------------------------------------------------------- ;loc_12A10: super_shoes_Tails: move.w #$C00,(Tails_top_speed).w move.w #$18,(Tails_acceleration).w move.w #$80,(Tails_deceleration).w + move.w #MusID_SpeedUp,d0 jmp (PlayMusic).l ; Speed up tempo ; =========================================================================== ; --------------------------------------------------------------------------- ; Shield Monitor ; gives the player a shield that absorbs one hit ; --------------------------------------------------------------------------- shield_monitor: addq.w #1,(a2) bset #status_sec_hasShield,status_secondary(a1) ; give shield status move.w #SndID_Shield,d0 jsr (PlayMusic).l tst.b parent+1(a0) bne.s + move.b #ObjID_Shield,(Sonic_Shield+id).w ; load Obj38 (shield) at $FFFFD180 move.w a1,(Sonic_Shield+parent).w rts ; --------------------------------------------------------------------------- + ; give shield to sidekick move.b #ObjID_Shield,(Tails_Shield+id).w ; load Obj38 (shield) at $FFFFD1C0 move.w a1,(Tails_Shield+parent).w rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Invincibility Monitor ; makes the player temporarily invincible ; --------------------------------------------------------------------------- invincible_monitor: addq.w #1,(a2) tst.b (Super_Sonic_flag).w ; is Sonic super? bne.s +++ ; rts ; if yes, branch bset #status_sec_isInvincible,status_secondary(a1) ; give invincibility status move.w #20*60,invincibility_time(a1) ; 20 seconds tst.b (Current_Boss_ID).w ; don't change music during boss battles bne.s + cmpi.b #$C,air_left(a1) ; or when drowning bls.s + move.w #MusID_Invincible,d0 jsr (PlayMusic).l + tst.b parent+1(a0) bne.s + move.b #ObjID_InvStars,(Sonic_InvincibilityStars+id).w ; load Obj35 (invincibility stars) at $FFFFD200 move.w a1,(Sonic_InvincibilityStars+parent).w rts ; --------------------------------------------------------------------------- + ; give invincibility to sidekick move.b #ObjID_InvStars,(Tails_InvincibilityStars+id).w ; load Obj35 (invincibility stars) at $FFFFD300 move.w a1,(Tails_InvincibilityStars+parent).w + rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Teleport Monitor ; swaps both players around ; --------------------------------------------------------------------------- ;loc_12AA6: teleport_monitor: addq.w #1,(a2) cmpi.b #6,(MainCharacter+routine).w ; is player 1 dead or respawning? bhs.s + ; if yes, branch cmpi.b #6,(Sidekick+routine).w ; is player 2 dead or respawning? blo.s swap_players ; if not, branch + ; can't teleport if either player is dead rts ; --------------------------------------------------------------------------- ; Routine to make both players swap positions ; and handle anything else that needs to be done ; --------------------------------------------------------------------------- swap_players: lea (teleport_swap_table).l,a3 moveq #(teleport_swap_table_end-teleport_swap_table)/6-1,d2 ; amount of entries in table - 1 process_swap_table: movea.w (a3)+,a1 ; address for main character movea.w (a3)+,a2 ; address for sidekick move.w (a3)+,d1 ; amount of word length data to be swapped - ; swap data between the main character and the sidekick d1 times move.w (a1),d0 move.w (a2),(a1)+ move.w d0,(a2)+ dbf d1,- dbf d2,process_swap_table ; process remaining entries in the list move.b #1,(MainCharacter+next_anim).w move.b #1,(Sidekick+next_anim).w if gameRevision>0 move.b #0,(MainCharacter+mapping_frame).w move.b #0,(Sidekick+mapping_frame).w endif move.b #-1,(Sonic_LastLoadedDPLC).w move.b #-1,(Tails_LastLoadedDPLC).w move.b #-1,(TailsTails_LastLoadedDPLC).w lea (unk_F786).w,a1 lea (unk_F789).w,a2 moveq #2,d1 - move.b (a1),d0 move.b (a2),(a1)+ move.b d0,(a2)+ dbf d1,- subi.w #$180,(Camera_Y_pos).w subi.w #$180,(Camera_Y_pos_P2).w move.w (MainCharacter+art_tile).w,d0 andi.w #drawing_mask,(MainCharacter+art_tile).w tst.w (Sidekick+art_tile).w bpl.s + ori.w #high_priority,(MainCharacter+art_tile).w + andi.w #drawing_mask,(Sidekick+art_tile).w tst.w d0 bpl.s + ori.w #high_priority,(Sidekick+art_tile).w + move.b #1,(Camera_Max_Y_Pos_Changing).w lea (Dynamic_Object_RAM).w,a1 moveq #(Dynamic_Object_RAM_End-Dynamic_Object_RAM)/object_size-1,d1 ; process objects: swap_loop_objects: cmpi.b #ObjID_PinballMode,id(a1) ; is it obj84 (pinball mode switcher)? beq.s + ; if yes, branch cmpi.b #ObjID_PlaneSwitcher,id(a1) ; is it obj03 (collision plane switcher)? bne.s ++ ; if not, branch further + move.b objoff_34(a1),d0 move.b objoff_35(a1),objoff_34(a1) move.b d0,objoff_35(a1) + cmpi.b #ObjID_PointPokey,id(a1) ; is it objD6 (CNZ point giver)? bne.s + ; if not, branch move.l objoff_30(a1),d0 move.l objoff_34(a1),objoff_30(a1) move.l d0,objoff_34(a1) + cmpi.b #ObjID_LauncherSpring,id(a1) ; is it obj85 (CNZ pressure spring)? bne.s + ; if not, branch move.b objoff_36(a1),d0 move.b objoff_37(a1),objoff_36(a1) move.b d0,objoff_37(a1) + lea next_object(a1),a1 ; look at next object ; a1=object dbf d1,swap_loop_objects ; loop lea (MainCharacter).w,a1 ; a1=character move.b #ObjID_Shield,(Sonic_Shield+id).w ; load Obj38 (shield) at $FFFFD180 move.w a1,(Sonic_Shield+parent).w move.b #ObjID_InvStars,(Sonic_InvincibilityStars+id).w ; load Obj35 (invincibility stars) at $FFFFD200 move.w a1,(Sonic_InvincibilityStars+parent).w btst #2,status(a1) ; is Sonic spinning? bne.s + ; if yes, branch move.b #$13,y_radius(a1) ; set to standing height move.b #9,x_radius(a1) + btst #3,status(a1) ; is Sonic on an object? beq.s + ; if not, branch moveq #0,d0 move.b interact(a1),d0 if object_size=$40 lsl.w #6,d0 else mulu.w #object_size,d0 endif addi.l #Object_RAM,d0 movea.l d0,a2 ; a2=object bclr #4,status(a2) bset #3,status(a2) + lea (Sidekick).w,a1 ; a1=character move.b #ObjID_Shield,(Tails_Shield+id).w ; load Obj38 (shield) at $FFFFD1C0 move.w a1,(Tails_Shield+parent).w move.b #ObjID_InvStars,(Tails_InvincibilityStars+id).w ; load Obj35 (invincibility) at $FFFFD300 move.w a1,(Tails_InvincibilityStars+parent).w btst #2,status(a1) ; is Tails spinning? bne.s + ; if yes, branch move.b #$F,y_radius(a1) ; set to standing height move.b #9,x_radius(a1) + btst #3,status(a1) ; is Tails on an object? beq.s + ; if not, branch moveq #0,d0 move.b interact(a1),d0 if object_size=$40 lsl.w #6,d0 else mulu.w #object_size,d0 endif addi.l #Object_RAM,d0 movea.l d0,a2 ; a2=object bclr #3,status(a2) bset #4,status(a2) + move.b #$40,(Teleport_timer).w move.b #1,(Teleport_flag).w move.w #SndID_Teleport,d0 jmp (PlayMusic).l ; =========================================================================== ; Table listing all the addresses for players 1 and 2 that need to be swapped ; when a teleport monitor is destroyed ;byte_12C52: teleport_swap_table: dc.w MainCharacter+x_pos, Sidekick+x_pos, $1B dc.w Camera_X_pos_last, Camera_X_pos_last_P2, 0 dc.w Obj_respawn_index, Obj_respawn_index_P2, 0 dc.w Obj_load_addr_right, Obj_load_addr_2, 3 dc.w Sonic_top_speed, Tails_top_speed, 2 dc.w Ring_start_addr, Ring_start_addr_P2, 1 dc.w CNZ_Visible_bumpers_start, CNZ_Visible_bumpers_start_P2, 3 dc.w Camera_X_pos, Camera_X_pos_P2, $F dc.w Camera_X_pos_coarse, Camera_X_pos_coarse_P2, 0 dc.w Camera_Min_X_pos, Tails_Min_X_pos, 3 dc.w Horiz_scroll_delay_val, Horiz_scroll_delay_val_P2, 1 dc.w Camera_Y_pos_bias, Camera_Y_pos_bias_P2, 0 dc.w Horiz_block_crossed_flag, Horiz_block_crossed_flag_P2, 3 dc.w Scroll_flags, Scroll_flags_P2, 3 dc.w Camera_RAM_copy, Camera_P2_copy, $F dc.w Scroll_flags_copy, Scroll_flags_copy_P2, 3 dc.w Camera_X_pos_diff, Camera_X_pos_diff_P2, 1 dc.w Sonic_Pos_Record_Buf, Tails_Pos_Record_Buf, $7F teleport_swap_table_end: ; =========================================================================== ; --------------------------------------------------------------------------- ; '?' Monitor ; doesn't actually do anything other than increase the player's monitor score ; --------------------------------------------------------------------------- qmark_monitor: addq.w #1,(a2) rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Holds icon in place for a while, then destroys it ; --------------------------------------------------------------------------- ;loc_12CC2: Obj2E_Wait: subq.w #1,anim_frame_duration(a0) bmi.w DeleteObject bra.w DisplaySprite ; =========================================================================== ; animation script ; off_12CCE: Ani_obj26: offsetTable offsetTableEntry.w Ani_obj26_Static ; 0 offsetTableEntry.w Ani_obj26_Sonic ; 1 offsetTableEntry.w Ani_obj26_Tails ; 2 offsetTableEntry.w Ani_obj26_Eggman ; 3 offsetTableEntry.w Ani_obj26_Ring ; 4 offsetTableEntry.w Ani_obj26_Shoes ; 5 offsetTableEntry.w Ani_obj26_Shield ; 6 offsetTableEntry.w Ani_obj26_Invincibility ; 7 offsetTableEntry.w Ani_obj26_Teleport ; 8 offsetTableEntry.w Ani_obj26_QuestionMark ; 9 offsetTableEntry.w Ani_obj26_Broken ; $A ; byte_12CE4: Ani_obj26_Static: dc.b $01 ; duration dc.b $00 ; frame number (which sprite table to use) dc.b $01 ; frame number dc.b $FF ; terminator ; byte_12CE8: Ani_obj26_Sonic: dc.b 1, 0, 2, 2, 1, 2, 2,$FF ; byte_12CF0: Ani_obj26_Tails: dc.b 1, 0, 3, 3, 1, 3, 3,$FF ; byte_12CF8: Ani_obj26_Eggman: dc.b 1, 0, 4, 4, 1, 4, 4,$FF ; byte_12D00: Ani_obj26_Ring: dc.b 1, 0, 5, 5, 1, 5, 5,$FF ; byte_12D08: Ani_obj26_Shoes: dc.b 1, 0, 6, 6, 1, 6, 6,$FF ; byte_12D10: Ani_obj26_Shield: dc.b 1, 0, 7, 7, 1, 7, 7,$FF ; byte_12D18: Ani_obj26_Invincibility: dc.b 1, 0, 8, 8, 1, 8, 8,$FF ; byte_12D20: Ani_obj26_Teleport: dc.b 1, 0, 9, 9, 1, 9, 9,$FF ; byte_12D28: Ani_obj26_QuestionMark: dc.b 1, 0, $A, $A, 1, $A, $A,$FF ; byte_12D30: Ani_obj26_Broken: dc.b 2, 0, 1, $B,$FE, 1 even ; --------------------------------------------------------------------------------- ; Sprite Mappings - Sprite table for monitor and monitor contents (26, ??) ; --------------------------------------------------------------------------------- ; MapUnc_12D36: MapUnc_obj26: Obj26_MapUnc_12D36: BINCLUDE "mappings/sprite/obj26.bin" ; =========================================================================== if gameRevision<2 nop endif ; ---------------------------------------------------------------------------- ; Object 0E - Flashing stars from intro ; ---------------------------------------------------------------------------- ; Sprite_12E18: Obj0E: moveq #0,d0 move.b routine(a0),d0 move.w Obj0E_Index(pc,d0.w),d1 jmp Obj0E_Index(pc,d1.w) ; =========================================================================== ; off_12E26: Obj0E_States: Obj0E_Index: offsetTable offsetTableEntry.w Obj0E_Init ; 0 offsetTableEntry.w Obj0E_Sonic ; 2 offsetTableEntry.w Obj0E_Tails ; 4 offsetTableEntry.w Obj0E_LogoTop ; 6 offsetTableEntry.w Obj0E_LargeStar ; 8 offsetTableEntry.w Obj0E_SonicHand ; $A offsetTableEntry.w Obj0E_SmallStar ; $C offsetTableEntry.w Obj0E_SkyPiece ; $E offsetTableEntry.w Obj0E_TailsHand ; $10 ; =========================================================================== ; loc_12E38: Obj0E_Init: addq.b #2,routine(a0) ; useless, because it's overwritten with the subtype below move.l #Obj0E_MapUnc_136A8,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_TitleSprites,0,0),art_tile(a0) move.b #4,priority(a0) move.b subtype(a0),routine(a0) bra.s Obj0E ; =========================================================================== Obj0E_Sonic: addq.w #1,objoff_34(a0) cmpi.w #$120,objoff_34(a0) bhs.s + bsr.w TitleScreen_SetFinalState + moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_12E76(pc,d0.w),d1 jmp off_12E76(pc,d1.w) ; =========================================================================== off_12E76: offsetTable offsetTableEntry.w Obj0E_Sonic_Init ; 0 offsetTableEntry.w loc_12EC2 ; 2 offsetTableEntry.w loc_12EE8 ; 4 offsetTableEntry.w loc_12F18 ; 6 offsetTableEntry.w loc_12F52 ; 8 offsetTableEntry.w Obj0E_Sonic_LastFrame ; $A offsetTableEntry.w loc_12F7C ; $C offsetTableEntry.w loc_12F9A ; $E offsetTableEntry.w loc_12FD6 ; $10 offsetTableEntry.w loc_13014 ; $12 ; =========================================================================== ; spawn more stars Obj0E_Sonic_Init: addq.b #2,routine_secondary(a0) move.b #5,mapping_frame(a0) move.w #$110,x_pixel(a0) move.w #$E0,y_pixel(a0) lea (IntroLargeStar).w,a1 move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro stars) at $FFFFB0C0 move.b #8,subtype(a1) ; large star lea (IntroEmblemTop).w,a1 move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro stars) at $FFFFD140 move.b #6,subtype(a1) ; logo top moveq #SndID_Sparkle,d0 jmpto (PlaySound).l, JmpTo4_PlaySound ; =========================================================================== loc_12EC2: cmpi.w #$38,objoff_34(a0) bhs.s + rts ; =========================================================================== + addq.b #2,routine_secondary(a0) lea (TitleScreenPaletteChanger3).w,a1 move.b #ObjID_TtlScrPalChanger,id(a1) ; load objC9 (palette change) move.b #0,subtype(a1) st.b objoff_30(a0) moveq #MusID_Title,d0 ; title music jmpto (PlayMusic).l, JmpTo4_PlayMusic ; =========================================================================== loc_12EE8: cmpi.w #$80,objoff_34(a0) bhs.s + rts ; =========================================================================== + addq.b #2,routine_secondary(a0) lea (Pal_133EC).l,a1 lea (Normal_palette).w,a2 moveq #$F,d6 - move.w (a1)+,(a2)+ dbf d6,- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_12F08: lea (IntroSmallStar1).w,a1 move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro star) at $FFFFB180 move.b #$E,subtype(a1) ; piece of sky rts ; End of function sub_12F08 ; =========================================================================== loc_12F18: moveq #word_13046_end-word_13046+4,d2 lea (word_13046).l,a1 loc_12F20: move.w objoff_2A(a0),d0 addq.w #1,d0 move.w d0,objoff_2A(a0) andi.w #3,d0 bne.s + move.w objoff_2C(a0),d1 addq.w #4,d1 cmp.w d2,d1 bhs.w loc_1310A move.w d1,objoff_2C(a0) move.l -4(a1,d1.w),d0 move.w d0,y_pixel(a0) swap d0 move.w d0,x_pixel(a0) + bra.w DisplaySprite ; =========================================================================== loc_12F52: lea (Ani_obj0E).l,a1 bsr.w AnimateSprite bra.w DisplaySprite ; =========================================================================== Obj0E_Sonic_LastFrame: addq.b #2,routine_secondary(a0) move.b #$12,mapping_frame(a0) lea (IntroSonicHand).w,a1 move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro star) at $FFFFB1C0 move.b #$A,subtype(a1) ; Sonic's hand bra.w DisplaySprite ; =========================================================================== loc_12F7C: cmpi.w #$C0,objoff_34(a0) blo.s + addq.b #2,routine_secondary(a0) lea (IntroTails).w,a1 move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro star) at $FFFFB080 move.b #4,subtype(a1) ; Tails + bra.w DisplaySprite ; =========================================================================== loc_12F9A: cmpi.w #$120,objoff_34(a0) blo.s + addq.b #2,routine_secondary(a0) clr.w objoff_2C(a0) st objoff_2F(a0) lea (Normal_palette_line3).w,a1 move.w #$EEE,d0 moveq #$F,d6 - move.w d0,(a1)+ dbf d6,- lea (TitleScreenPaletteChanger2).w,a1 move.b #ObjID_TtlScrPalChanger,id(a1) ; load objC9 (palette change handler) at $FFFFB240 move.b #2,subtype(a1) move.b #ObjID_TitleMenu,(TitleScreenMenu+id).w ; load Obj0F (title screen menu) at $FFFFB400 + bra.w DisplaySprite ; =========================================================================== loc_12FD6: btst #6,(Graphics_Flags).w beq.s + cmpi.w #$190,objoff_34(a0) beq.s ++ bra.w DisplaySprite ; =========================================================================== + cmpi.w #$1D0,objoff_34(a0) beq.s + bra.w DisplaySprite ; =========================================================================== + lea (IntroSmallStar2).w,a1 move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro star) at $FFFFB440 move.b #$C,subtype(a1) ; small star addq.b #2,routine_secondary(a0) lea (IntroSmallStar1).w,a1 bsr.w DeleteObject2 ; delete object at $FFFFB180 bra.w DisplaySprite ; =========================================================================== loc_13014: move.b (Vint_runcount+3).w,d0 andi.b #7,d0 bne.s ++ move.w objoff_2C(a0),d0 addq.w #2,d0 cmpi.w #CyclingPal_TitleStar_End-CyclingPal_TitleStar,d0 blo.s + moveq #0,d0 + move.w d0,objoff_2C(a0) move.w CyclingPal_TitleStar(pc,d0.w),(Normal_palette_line3+$A).w + bra.w DisplaySprite ; =========================================================================== ; word_1303A: CyclingPal_TitleStar: binclude "art/palettes/Title Star Cycle.bin" CyclingPal_TitleStar_End word_13046: dc.w $108, $D0 dc.w $100, $C0 ; 2 dc.w $F8, $B0 ; 4 dc.w $F6, $A6 ; 6 dc.w $FA, $9E ; 8 dc.w $100, $9A ; $A dc.w $104, $99 ; $C dc.w $108, $98 ; $E word_13046_end ; =========================================================================== Obj0E_Tails: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_13074(pc,d0.w),d1 jmp off_13074(pc,d1.w) ; =========================================================================== off_13074: offsetTable offsetTableEntry.w Obj0E_Tails_Init ; 0 offsetTableEntry.w loc_13096 ; 2 offsetTableEntry.w loc_12F52 ; 4 offsetTableEntry.w loc_130A2 ; 6 offsetTableEntry.w BranchTo10_DisplaySprite ; 8 ; =========================================================================== Obj0E_Tails_Init: addq.b #2,routine_secondary(a0) move.w #$D8,x_pixel(a0) move.w #$D8,y_pixel(a0) move.b #1,anim(a0) rts ; =========================================================================== loc_13096: moveq #word_130B8_end-word_130B8+4,d2 lea (word_130B8).l,a1 bra.w loc_12F20 ; =========================================================================== loc_130A2: addq.b #2,routine_secondary(a0) lea (IntroTailsHand).w,a1 move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro star) at $FFFFB200 move.b #$10,subtype(a1) ; Tails' hand BranchTo10_DisplaySprite bra.w DisplaySprite ; =========================================================================== word_130B8: dc.w $D7,$C8 dc.w $D3,$B8 ; 2 dc.w $CE,$AC ; 4 dc.w $CC,$A6 ; 6 dc.w $CA,$A2 ; 8 dc.w $C9,$A1 ; $A dc.w $C8,$A0 ; $C word_130B8_end ; =========================================================================== Obj0E_LogoTop: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_130E2(pc,d0.w),d1 jmp off_130E2(pc,d1.w) ; =========================================================================== off_130E2: offsetTable offsetTableEntry.w Obj0E_LogoTop_Init ; 0 offsetTableEntry.w BranchTo11_DisplaySprite ; 2 ; =========================================================================== Obj0E_LogoTop_Init: move.b #$B,mapping_frame(a0) tst.b (Graphics_Flags).w bmi.s + move.b #$A,mapping_frame(a0) + move.b #2,priority(a0) move.w #$120,x_pixel(a0) move.w #$E8,y_pixel(a0) loc_1310A: addq.b #2,routine_secondary(a0) BranchTo11_DisplaySprite bra.w DisplaySprite ; =========================================================================== Obj0E_SkyPiece: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_13120(pc,d0.w),d1 jmp off_13120(pc,d1.w) ; =========================================================================== off_13120: offsetTable offsetTableEntry.w Obj0E_SkyPiece_Init ; 0 offsetTableEntry.w BranchTo12_DisplaySprite ; 2 ; =========================================================================== Obj0E_SkyPiece_Init: addq.b #2,routine_secondary(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0) move.b #$11,mapping_frame(a0) move.b #2,priority(a0) move.w #$100,x_pixel(a0) move.w #$F0,y_pixel(a0) BranchTo12_DisplaySprite bra.w DisplaySprite ; =========================================================================== Obj0E_LargeStar: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_13158(pc,d0.w),d1 jmp off_13158(pc,d1.w) ; =========================================================================== off_13158: offsetTable offsetTableEntry.w Obj0E_LargeStar_Init ; 0 offsetTableEntry.w loc_12F52 ; 2 offsetTableEntry.w loc_13190 ; 4 offsetTableEntry.w loc_1319E ; 6 ; =========================================================================== Obj0E_LargeStar_Init: addq.b #2,routine_secondary(a0) move.b #$C,mapping_frame(a0) ori.w #high_priority,art_tile(a0) move.b #2,anim(a0) move.b #1,priority(a0) move.w #$100,x_pixel(a0) move.w #$A8,y_pixel(a0) move.w #4,objoff_2A(a0) rts ; =========================================================================== loc_13190: subq.w #1,objoff_2A(a0) bmi.s + rts ; =========================================================================== + addq.b #2,routine_secondary(a0) rts ; =========================================================================== loc_1319E: move.b #2,routine_secondary(a0) move.b #0,anim_frame(a0) move.b #0,anim_frame_duration(a0) move.w #6,objoff_2A(a0) move.w objoff_2C(a0),d0 addq.w #4,d0 cmpi.w #word_131DC_end-word_131DC+4,d0 bhs.w DeleteObject move.w d0,objoff_2C(a0) move.l word_131DC-4(pc,d0.w),d0 move.w d0,y_pixel(a0) swap d0 move.w d0,x_pixel(a0) moveq #SndID_Sparkle,d0 ; play intro sparkle sound jmpto (PlaySound).l, JmpTo4_PlaySound ; =========================================================================== ; unknown word_131DC: dc.w $DA, $F2 dc.w $170, $F8 ; 2 dc.w $132,$131 ; 4 dc.w $19E, $A2 ; 6 dc.w $C0, $E3 ; 8 dc.w $180, $E0 ; $A dc.w $10D,$13B ; $C dc.w $C0, $AB ; $E dc.w $165, $107 ; $10 word_131DC_end ; =========================================================================== Obj0E_SonicHand: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_1320E(pc,d0.w),d1 jmp off_1320E(pc,d1.w) ; =========================================================================== off_1320E: offsetTable offsetTableEntry.w Obj0E_SonicHand_Init ; 0 offsetTableEntry.w loc_13234 ; 2 offsetTableEntry.w BranchTo13_DisplaySprite ; 4 ; =========================================================================== Obj0E_SonicHand_Init: addq.b #2,routine_secondary(a0) move.b #9,mapping_frame(a0) move.b #3,priority(a0) move.w #$145,x_pixel(a0) move.w #$BF,y_pixel(a0) BranchTo13_DisplaySprite bra.w DisplaySprite ; =========================================================================== loc_13234: moveq #word_13240_end-word_13240+4,d2 lea (word_13240).l,a1 bra.w loc_12F20 ; =========================================================================== word_13240: dc.w $143, $C1 dc.w $140, $C2 ; 2 dc.w $141, $C1 ; 4 word_13240_end ; =========================================================================== Obj0E_TailsHand: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_1325A(pc,d0.w),d1 jmp off_1325A(pc,d1.w) ; =========================================================================== off_1325A: offsetTable offsetTableEntry.w Obj0E_TailsHand_Init ; 0 offsetTableEntry.w loc_13280 ; 2 offsetTableEntry.w BranchTo14_DisplaySprite ; 4 ; =========================================================================== Obj0E_TailsHand_Init: addq.b #2,routine_secondary(a0) move.b #$13,mapping_frame(a0) move.b #3,priority(a0) move.w #$10F,x_pixel(a0) move.w #$D5,y_pixel(a0) BranchTo14_DisplaySprite bra.w DisplaySprite ; =========================================================================== loc_13280: moveq #word_1328C_end-word_1328C+4,d2 lea (word_1328C).l,a1 bra.w loc_12F20 ; =========================================================================== word_1328C: dc.w $10C, $D0 dc.w $10D, $D1 ; 2 word_1328C_end ; =========================================================================== Obj0E_SmallStar: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_132A2(pc,d0.w),d1 jmp off_132A2(pc,d1.w) ; =========================================================================== off_132A2: offsetTable offsetTableEntry.w Obj0E_SmallStar_Init ; 0 offsetTableEntry.w loc_132D2 ; 2 ; =========================================================================== Obj0E_SmallStar_Init: addq.b #2,routine_secondary(a0) move.b #$C,mapping_frame(a0) move.b #5,priority(a0) move.w #$170,x_pixel(a0) move.w #$80,y_pixel(a0) move.b #3,anim(a0) move.w #$8C,objoff_2A(a0) bra.w DisplaySprite ; =========================================================================== loc_132D2: subq.w #1,objoff_2A(a0) bmi.w DeleteObject subq.w #2,x_pixel(a0) addq.w #1,y_pixel(a0) lea (Ani_obj0E).l,a1 bsr.w AnimateSprite bra.w DisplaySprite ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object C9 - "Palette changing handler" from title screen ; ---------------------------------------------------------------------------- ttlscrpalchanger_fadein_time_left = objoff_30 ttlscrpalchanger_fadein_time = objoff_31 ttlscrpalchanger_fadein_amount = objoff_32 ttlscrpalchanger_start_offset = objoff_34 ttlscrpalchanger_length = objoff_36 ttlscrpalchanger_codeptr = objoff_3A ; Sprite_132F0: ObjC9: moveq #0,d0 move.b routine(a0),d0 move.w ObjC9_Index(pc,d0.w),d1 jmp ObjC9_Index(pc,d1.w) ; =========================================================================== ObjC9_Index: offsetTable offsetTableEntry.w ObjC9_Init ; 0 offsetTableEntry.w ObjC9_Main ; 2 ; =========================================================================== ObjC9_Init: addq.b #2,routine(a0) moveq #0,d0 move.b subtype(a0),d0 lea (PaletteChangerDataIndex).l,a1 adda.w (a1,d0.w),a1 move.l (a1)+,ttlscrpalchanger_codeptr(a0) movea.l (a1)+,a2 move.b (a1)+,d0 move.w d0,ttlscrpalchanger_start_offset(a0) lea (Target_palette).w,a3 adda.w d0,a3 move.b (a1)+,d0 move.w d0,ttlscrpalchanger_length(a0) - move.w (a2)+,(a3)+ dbf d0,- move.b (a1)+,d0 move.b d0,ttlscrpalchanger_fadein_time_left(a0) move.b d0,ttlscrpalchanger_fadein_time(a0) move.b (a1)+,ttlscrpalchanger_fadein_amount(a0) rts ; =========================================================================== ObjC9_Main: subq.b #1,ttlscrpalchanger_fadein_time_left(a0) bpl.s + move.b ttlscrpalchanger_fadein_time(a0),ttlscrpalchanger_fadein_time_left(a0) subq.b #1,ttlscrpalchanger_fadein_amount(a0) bmi.w DeleteObject movea.l ttlscrpalchanger_codeptr(a0),a2 movea.l a0,a3 move.w ttlscrpalchanger_length(a0),d0 move.w ttlscrpalchanger_start_offset(a0),d1 lea (Normal_palette).w,a0 adda.w d1,a0 lea (Target_palette).w,a1 adda.w d1,a1 - jsr (a2) ; dynamic call! to Pal_FadeFromBlack.UpdateColour, loc_1344C, or loc_1348A, assuming the PaletteChangerData pointers haven't been changed dbf d0,- movea.l a3,a0 + rts ; =========================================================================== ; off_1337C: PaletteChangerDataIndex: offsetTable offsetTableEntry.w off_1338C ; 0 offsetTableEntry.w off_13398 ; 2 offsetTableEntry.w off_133A4 ; 4 offsetTableEntry.w off_133B0 ; 6 offsetTableEntry.w off_133BC ; 8 offsetTableEntry.w off_133C8 ; $A offsetTableEntry.w off_133D4 ; $C offsetTableEntry.w off_133E0 ; $E C9PalInfo macro codeptr,dataptr,loadtoOffset,length,fadeinTime,fadeinAmount dc.l codeptr, dataptr dc.b loadtoOffset, length, fadeinTime, fadeinAmount endm off_1338C: C9PalInfo Pal_FadeFromBlack.UpdateColour, Pal_1342C, $60, $F,2,$15 off_13398: C9PalInfo loc_1344C, Pal_1340C, $40, $F,4,7 off_133A4: C9PalInfo loc_1344C, Pal_AD1E, 0, $F,8,7 off_133B0: C9PalInfo loc_1348A, Pal_AD1E, 0, $F,8,7 off_133BC: C9PalInfo loc_1344C, Pal_AC7E, 0,$1F,4,7 off_133C8: C9PalInfo loc_1344C, Pal_ACDE, $40,$1F,4,7 off_133D4: C9PalInfo loc_1344C, Pal_AD3E, 0, $F,4,7 off_133E0: C9PalInfo loc_1344C, Pal_AC9E, 0,$1F,4,7 Pal_133EC: BINCLUDE "art/palettes/Title Sonic.bin" Pal_1340C: BINCLUDE "art/palettes/Title Background.bin" Pal_1342C: BINCLUDE "art/palettes/Title Emblem.bin" ; =========================================================================== loc_1344C: move.b (a1)+,d2 andi.b #$E,d2 move.b (a0),d3 cmp.b d2,d3 bls.s loc_1345C subq.b #2,d3 move.b d3,(a0) loc_1345C: addq.w #1,a0 move.b (a1)+,d2 move.b d2,d3 andi.b #$E0,d2 andi.b #$E,d3 move.b (a0),d4 move.b d4,d5 andi.b #$E0,d4 andi.b #$E,d5 cmp.b d2,d4 bls.s loc_1347E subi.b #$20,d4 loc_1347E: cmp.b d3,d5 bls.s loc_13484 subq.b #2,d5 loc_13484: or.b d4,d5 move.b d5,(a0)+ rts ; =========================================================================== loc_1348A: moveq #$E,d2 move.b (a0),d3 and.b d2,d3 cmp.b d2,d3 bhs.s loc_13498 addq.b #2,d3 move.b d3,(a0) loc_13498: addq.w #1,a0 move.b (a0),d3 move.b d3,d4 andi.b #$E0,d3 andi.b #$E,d4 cmpi.b #-$20,d3 bhs.s loc_134B0 addi.b #$20,d3 loc_134B0: cmp.b d2,d4 bhs.s loc_134B6 addq.b #2,d4 loc_134B6: or.b d3,d4 move.b d4,(a0)+ rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| TitleScreen_SetFinalState: tst.b objoff_2F(a0) bne.w + ; rts move.b (Ctrl_1_Press).w,d0 or.b (Ctrl_2_Press).w,d0 andi.b #button_up_mask|button_down_mask|button_left_mask|button_right_mask|button_B_mask|button_C_mask|button_A_mask,(Ctrl_1_Press).w andi.b #button_up_mask|button_down_mask|button_left_mask|button_right_mask|button_B_mask|button_C_mask|button_A_mask,(Ctrl_2_Press).w andi.b #button_start_mask,d0 beq.w + ; rts st.b objoff_2F(a0) move.b #$10,routine_secondary(a0) move.b #$12,mapping_frame(a0) move.w #$108,x_pixel(a0) move.w #$98,y_pixel(a0) lea (IntroSonicHand).w,a1 bsr.w TitleScreen_InitSprite move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro star) at $FFFFB1C0 move.b #$A,routine(a1) ; Sonic's hand move.b #2,priority(a1) move.b #9,mapping_frame(a1) move.b #4,routine_secondary(a1) move.w #$141,x_pixel(a1) move.w #$C1,y_pixel(a1) lea (IntroTails).w,a1 bsr.w TitleScreen_InitSprite move.b #ObjID_IntroStars,id(a1) ; load obj0E move.b #4,routine(a1) ; Tails move.b #4,mapping_frame(a1) move.b #6,routine_secondary(a1) move.b #3,priority(a1) move.w #$C8,x_pixel(a1) move.w #$A0,y_pixel(a1) lea (IntroTailsHand).w,a1 bsr.w TitleScreen_InitSprite move.b #ObjID_IntroStars,id(a1) ; load obj0E move.b #$10,routine(a1) ; Tails' hand move.b #2,priority(a1) move.b #$13,mapping_frame(a1) move.b #4,routine_secondary(a1) move.w #$10D,x_pixel(a1) move.w #$D1,y_pixel(a1) lea (IntroEmblemTop).w,a1 move.b #ObjID_IntroStars,id(a1) ; load obj0E move.b #6,subtype(a1) ; logo top bsr.w sub_12F08 move.b #ObjID_TitleMenu,(TitleScreenMenu+id).w ; load Obj0F (title screen menu) at $FFFFB400 lea (TitleScreenPaletteChanger).w,a1 bsr.w DeleteObject2 lea_ Pal_1342C,a1 lea (Normal_palette_line4).w,a2 moveq #7,d6 - move.l (a1)+,(a2)+ dbf d6,- lea_ Pal_1340C,a1 lea (Normal_palette_line3).w,a2 moveq #7,d6 - move.l (a1)+,(a2)+ dbf d6,- lea_ Pal_133EC,a1 lea (Normal_palette).w,a2 moveq #7,d6 - move.l (a1)+,(a2)+ dbf d6,- tst.b objoff_30(a0) bne.s + ; rts moveq #MusID_Title,d0 ; title music jsrto (PlayMusic).l, JmpTo4_PlayMusic + rts ; End of function sub_134BC ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;sub_135EA: TitleScreen_InitSprite: move.l #Obj0E_MapUnc_136A8,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_TitleSprites,0,0),art_tile(a1) move.b #4,priority(a1) rts ; End of function TitleScreen_InitSprite ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 0F - Title screen menu ; ---------------------------------------------------------------------------- ; Sprite_13600: Obj0F: moveq #0,d0 move.b routine(a0),d0 move.w Obj0F_Index(pc,d0.w),d1 jsr Obj0F_Index(pc,d1.w) bra.w DisplaySprite ; =========================================================================== ; off_13612: Obj0F_States: Obj0F_Index: offsetTable offsetTableEntry.w Obj0F_Init ; 0 offsetTableEntry.w Obj0F_Main ; 2 ; =========================================================================== ; loc_13616: Obj0F_Init: addq.b #2,routine(a0) ; => Obj0F_Main move.w #$128,x_pixel(a0) move.w #$14C,y_pixel(a0) move.l #Obj0F_MapUnc_13B70,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0) bsr.w Adjust2PArtPointer andi.b #1,(Title_screen_option).w move.b (Title_screen_option).w,mapping_frame(a0) ; loc_13644: Obj0F_Main: moveq #0,d2 move.b (Title_screen_option).w,d2 move.b (Ctrl_1_Press).w,d0 or.b (Ctrl_2_Press).w,d0 btst #button_up,d0 beq.s + subq.b #1,d2 bcc.s + move.b #2,d2 + btst #button_down,d0 beq.s + addq.b #1,d2 cmpi.b #3,d2 blo.s + moveq #0,d2 + move.b d2,mapping_frame(a0) move.b d2,(Title_screen_option).w andi.b #button_up_mask|button_down_mask,d0 beq.s + ; rts moveq #SndID_Blip,d0 ; selection blip sound jsrto (PlaySound).l, JmpTo4_PlaySound + rts ; =========================================================================== ; animation script ; off_13686: Ani_obj0E: offsetTable offsetTableEntry.w byte_1368E ; 0 offsetTableEntry.w byte_13694 ; 1 offsetTableEntry.w byte_1369C ; 2 offsetTableEntry.w byte_136A4 ; 3 byte_1368E: dc.b 1 dc.b 5 ; 1 dc.b 6 ; 2 dc.b 7 ; 3 dc.b 8 ; 4 dc.b $FA ; 5 even byte_13694: dc.b 1 dc.b 0 ; 1 dc.b 1 ; 2 dc.b 2 ; 3 dc.b 3 ; 4 dc.b 4 ; 5 dc.b $FA ; 6 even byte_1369C: dc.b 1 dc.b $C ; 1 dc.b $D ; 2 dc.b $E ; 3 dc.b $D ; 4 dc.b $C ; 5 dc.b $FA ; 6 even byte_136A4: dc.b 3 dc.b $C ; 1 dc.b $F ; 2 dc.b $FF ; 3 even ; ----------------------------------------------------------------------------- ; Sprite Mappings - Flashing stars from intro (Obj0E) ; ----------------------------------------------------------------------------- Obj0E_MapUnc_136A8: BINCLUDE "mappings/sprite/obj0E.bin" ; ----------------------------------------------------------------------------- ; sprite mappings ; ----------------------------------------------------------------------------- Obj0F_MapUnc_13B70: BINCLUDE "mappings/sprite/obj0F.bin" if ~~removeJmpTos JmpTo4_PlaySound jmp (PlaySound).l JmpTo4_PlayMusic jmp (PlayMusic).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 34 - level title card (screen with red, yellow, and blue) ; ---------------------------------------------------------------------------- titlecard_x_target = objoff_30 ; the X position the object will reach titlecard_x_source = objoff_32 ; the X position the object starts from and will end at titlecard_location = objoff_34 ; point up to which titlecard is drawn titlecard_vram_dest = objoff_36 ; target of VRAM write titlecard_vram_dest_2P = objoff_38 ; target of VRAM write titlecard_split_point = objoff_3A ; point to split drawing for yellow and red portions titlecard_leaveflag = objoff_3E ; whether or not titlecard is leaving screen ; Sprite_13C48: Obj34: ; (note: screen-space obj) moveq #0,d0 move.b routine(a0),d0 move.w Obj34_Index(pc,d0.w),d1 jmp Obj34_Index(pc,d1.w) ; =========================================================================== Obj34_Index: offsetTable offsetTableEntry.w Obj34_Init ; 0 - create all the title card objects offsetTableEntry.w Obj34_BackgroundIn ; 2 - the background, coming in offsetTableEntry.w Obj34_BottomPartIn ; 4 - the yellow part at the bottom, coming in offsetTableEntry.w Obj34_LeftPartIn ; 6 - the red part on the left, coming in offsetTableEntry.w Obj34_ZoneName ; 8 - the name of the zone, coming in offsetTableEntry.w Obj34_Zone ; $A - the word "ZONE", coming in offsetTableEntry.w Obj34_ActNumber ; $C - the act number, coming in offsetTableEntry.w Obj34_LeftPartOut ; $E - red part on the left, going out offsetTableEntry.w Obj34_BottomPartOut ; $10 - yellow part at the bottom, going out offsetTableEntry.w Obj34_BackgroundOutInit ; $12 - the background, going out (first frame) offsetTableEntry.w Obj34_BackgroundOut ; $14 - the background, going out offsetTableEntry.w Obj34_WaitAndGoAway ; $16 - wait and go away, used by the zone name, "ZONE" and the act number ; =========================================================================== ; loc_13C6E: Obj34_Init: lea (a0),a1 lea Obj34_TitleCardData(pc),a2 moveq #(Obj34_TitleCardData_End-Obj34_TitleCardData)/$A-1,d1 - _move.b #ObjID_TitleCard,id(a1) ; load obj34 move.b (a2)+,routine(a1) move.l #Obj34_MapUnc_147BA,mappings(a1) move.b (a2)+,mapping_frame(a1) move.b (a2)+,width_pixels(a1) move.b (a2)+,anim_frame_duration(a1) move.w (a2),x_pixel(a1) move.w (a2)+,titlecard_x_source(a1) move.w (a2)+,titlecard_x_target(a1) move.w (a2)+,y_pixel(a1) move.b #0,render_flags(a1) lea next_object(a1),a1 ; a1=object dbf d1,- move.w #$26,(TitleCard_Bottom+titlecard_location).w clr.w (Vscroll_Factor_FG).w move.w #-$E0,(Vscroll_Factor_P2_FG).w clearRAM Horiz_Scroll_Buf,Horiz_Scroll_Buf_End rts ; =========================================================================== ; This macro declares data for an object. The data includes: ; - the initial routine counter (byte) ; - the initial mapping frame (byte) ; - the width of the object (byte) ; - the number of frames before it appears on screen (byte) ; - the X position where it starts and where it will go back (word) ; - the X position to reach (word) ; - the Y position (word) titlecardobjdata macro routine,frame,width,duration,xstart,xstop,y dc.b routine,frame,width,duration dc.w xstart,xstop,y endm ; word_13CD4: Obj34_TitleCardData: titlecardobjdata 8, 0, $80, $1B, $240, $120, $B8 ; zone name titlecardobjdata $A, $11, $40, $1C, $28, $148, $D0 ; "ZONE" titlecardobjdata $C, $12, $18, $1C, $68, $188, $D0 ; act number titlecardobjdata 2, 0, 0, 0, 0, 0, 0 ; blue background titlecardobjdata 4, $15, $48, 8, $2A8, $168,$120 ; bottom yellow part titlecardobjdata 6, $16, 8, $15, $80, $F0, $F0 ; left red part Obj34_TitleCardData_End: ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_13D10: Obj34_Wait: subq.b #1,anim_frame_duration(a0) ; subtract 1 bne.s + ; if it's not 0, branch move.b #1,anim_frame_duration(a0) ; reset to 1 rts ; --------------------------------------------------------------------------- + addq.w #4,sp ; don't run the code after the call to this routine rts ; End of function Obj34_Wait ; =========================================================================== ; loc_13D22: Obj34_BackgroundIn: ; the blue background (green when playing as Knuckles), coming in moveq #$10,d0 moveq #8,d1 tst.w (Two_player_mode).w ; if two-player mode is on (1) sne d6 ; then set d6 to $FF, else set d6 to $00 beq.s + moveq #$20,d0 moveq #7,d1 + move.w titlecard_location(a0),d2 cmp.w d0,d2 beq.s ++ ; rts lsl.w d1,d2 move.w #VRAM_Plane_A_Name_Table,d0 add.w d2,d0 move.w d0,titlecard_vram_dest(a0) tst.b d6 beq.s + addi.w #VRAM_Plane_A_Name_Table_2P,d2 move.w d2,titlecard_vram_dest_2P(a0) + addq.w #1,titlecard_location(a0) + rts ; =========================================================================== ; loc_13D58: Obj34_BottomPartIn: ; the yellow part at the bottom, coming in jsr Obj34_Wait(pc) move.w titlecard_location(a0),d0 bmi.w Obj34_MoveTowardsTargetPosition add.w d0,d0 move.w #$80*$14/2,d1 ; $14 half-cells down (for 2P mode) tst.w (Two_player_mode).w sne d6 bne.s + add.w d1,d1 ; double distance down for 1P mode + move.w #VRAM_Plane_A_Name_Table,d2 add.w d0,d2 add.w d1,d2 move.w d2,titlecard_vram_dest(a0) tst.b d6 beq.s + addi.w #VRAM_Plane_A_Name_Table_2P,d1 add.w d0,d1 move.w d1,titlecard_vram_dest_2P(a0) + subq.w #2,titlecard_location(a0) move.w titlecard_location(a0),titlecard_split_point(a0) cmpi.w #6,titlecard_location(a0) ; if titlecard_location(a0) is 6, seq titlecard_location(a0) ; then set it to $FF, else set it to $00 bra.w Obj34_MoveTowardsTargetPosition ; =========================================================================== ; loc_13DA6: Obj34_LeftPartIn: ; the red part on the left, coming in jsr Obj34_Wait(pc) tst.w titlecard_location(a0) bmi.w Obj34_MoveTowardsTargetPosition move.w #VRAM_Plane_A_Name_Table,titlecard_vram_dest(a0) tst.w (Two_player_mode).w beq.s + move.w #VRAM_Plane_A_Name_Table_2P,titlecard_vram_dest_2P(a0) + addq.w #2,titlecard_location(a0) move.w titlecard_location(a0),titlecard_split_point(a0) cmpi.w #$E,titlecard_location(a0) seq titlecard_location(a0) bra.w Obj34_MoveTowardsTargetPosition ; =========================================================================== ; loc_13DDC: Obj34_ZoneName: ; the name of the zone, coming in jsr Obj34_Wait(pc) move.b (Current_Zone).w,mapping_frame(a0) bra.s Obj34_MoveTowardsTargetPosition ; =========================================================================== ; loc_13DE8: Obj34_Zone: ; the word "ZONE", coming in jsr Obj34_Wait(pc) bra.s Obj34_MoveTowardsTargetPosition ; =========================================================================== ; loc_13DEE: Obj34_ActNumber: ; the act number, coming in jsr Obj34_Wait(pc) move.b (Current_Zone).w,d0 ; get the current zone cmpi.b #sky_chase_zone,d0 ; is it Sky Chase? beq.s BranchTo9_DeleteObject ; if yes, branch cmpi.b #wing_fortress_zone,d0 ; is it Wing Fortress? beq.s BranchTo9_DeleteObject ; if yes, branch cmpi.b #death_egg_zone,d0 ; is it Death Egg Zone? beq.s BranchTo9_DeleteObject ; if yes, branch move.b (Current_Act).w,d1 ; get the current act addi.b #$12,d1 ; add $12 to it (this is the index of the "1" frame in the mappings) cmpi.b #metropolis_zone_2,d0 ; are we in Metropolis Zone Act 3? bne.s + ; if not, branch moveq #$14,d1 ; use the "3" frame instead + move.b d1,mapping_frame(a0) ; set the mapping frame ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_13E1C: Obj34_MoveTowardsTargetPosition: moveq #$10,d0 ; set speed move.w x_pixel(a0),d1 ; get the X position cmp.w titlecard_x_target(a0),d1 ; compare with target position beq.s ++ ; if it reached its target position, branch bhi.s + ; if it's beyond the target position, branch neg.w d0 ; negate the speed + sub.w d0,x_pixel(a0) ; move the object cmpi.w #$200,x_pixel(a0) ; is it beyond $200? bhi.s ++ ; if yes, return + bra.w DisplaySprite ; --------------------------------------------------------------------------- + rts ; End of function Obj34_MoveTowardsTargetPosition ; =========================================================================== BranchTo9_DeleteObject bra.w DeleteObject ; =========================================================================== ; loc_13E42: Obj34_LeftPartOut: ; red part on the left, going out move.w titlecard_location(a0),d0 bpl.s + move.b #$10,TitleCard_Bottom-TitleCard_Left+routine(a0) clr.w TitleCard_Bottom-TitleCard_Left+titlecard_location(a0) bra.s BranchTo9_DeleteObject ; =========================================================================== + add.w d0,d0 move.w #VRAM_Plane_A_Name_Table,titlecard_vram_dest(a0) add.w d0,titlecard_vram_dest(a0) tst.w (Two_player_mode).w beq.s + move.w #VRAM_Plane_A_Name_Table_2P,titlecard_vram_dest_2P(a0) add.w d0,titlecard_vram_dest_2P(a0) + subq.w #4,titlecard_location(a0) cmpi.w #-2,titlecard_location(a0) bne.s + clr.w titlecard_location(a0) + bra.w loc_13EC4 ; =========================================================================== ; loc_13E84: Obj34_BottomPartOut: ; yellow part at the bottom, going out move.w titlecard_location(a0),d0 cmpi.w #$28,d0 bne.s + move.b #$12,TitleCard_Background-TitleCard_Bottom+routine(a0) bra.s BranchTo9_DeleteObject ; --------------------------------------------------------------------------- + add.w d0,d0 move.w #$80*$14/2,d1 ; $14 half-cells down (for 2P mode) tst.w (Two_player_mode).w sne d6 bne.s + add.w d1,d1 ; double distance down for 1P mode + move.w #VRAM_Plane_A_Name_Table,d2 add.w d0,d2 add.w d1,d2 move.w d2,titlecard_vram_dest(a0) tst.b d6 beq.s + addi.w #VRAM_Plane_A_Name_Table_2P,d1 add.w d0,d1 move.w d1,titlecard_vram_dest_2P(a0) + addq.w #4,titlecard_location(a0) loc_13EC4: moveq #$20,d0 move.w x_pixel(a0),d1 cmp.w titlecard_x_source(a0),d1 beq.s ++ ; rts bhi.s + neg.w d0 + sub.w d0,x_pixel(a0) cmpi.w #$200,x_pixel(a0) bhi.s + ; rts bra.w DisplaySprite ; --------------------------------------------------------------------------- + rts ; =========================================================================== ; loc_13EE6: Obj34_BackgroundOutInit: ; the background, going out move.l a0,-(sp) move.l d7,-(sp) bsr.w DeformBgLayer move.l (sp)+,d7 movea.l (sp)+,a0 ; load 0bj address addi_.b #2,routine(a0) move.w #$F0,titlecard_location(a0) ; loc_13EFE: Obj34_BackgroundOut: move.w titlecard_location(a0),d0 subi.w #$20,d0 cmpi.w #-$30,d0 beq.w BranchTo9_DeleteObject move.w d0,titlecard_location(a0) move.w d0,titlecard_vram_dest(a0) rts ; =========================================================================== ; loc_13F18: Obj34_WaitAndGoAway: tst.w anim_frame_duration(a0) beq.s + subq.w #1,anim_frame_duration(a0) bra.s +++ ; DisplaySprite ; --------------------------------------------------------------------------- + moveq #$20,d0 move.w x_pixel(a0),d1 cmp.w titlecard_x_source(a0),d1 beq.s Obj34_LoadStandardWaterAndAnimalArt bhi.s + neg.w d0 + sub.w d0,x_pixel(a0) cmpi.w #$200,x_pixel(a0) bhi.s Obj34_LoadStandardWaterAndAnimalArt + bra.w DisplaySprite ; =========================================================================== ; loc_13F44: Obj34_LoadStandardWaterAndAnimalArt: cmpa.w #TitleCard_ZoneName,a0 ; is this the zone name object? bne.s + ; if not, just delete the title card moveq #PLCID_StdWtr,d0 ; load the standard water graphics jsrto (LoadPLC).l, JmpTo3_LoadPLC moveq #0,d0 move.b (Current_Zone).w,d0 move.b Animal_PLCTable(pc,d0.w),d0 ; load the animal graphics for the current zone jsrto (LoadPLC).l, JmpTo3_LoadPLC + bra.w DeleteObject ; delete the title card object ; =========================================================================== ;byte_13F62: Animal_PLCTable: zoneOrderedTable 1,1 zoneTableEntry.b PLCID_EhzAnimals ; $0 zoneTableEntry.b PLCID_EhzAnimals ; $1 zoneTableEntry.b PLCID_EhzAnimals ; $2 zoneTableEntry.b PLCID_EhzAnimals ; $3 zoneTableEntry.b PLCID_MtzAnimals ; $4 zoneTableEntry.b PLCID_MtzAnimals ; $5 zoneTableEntry.b PLCID_WfzAnimals ; $6 zoneTableEntry.b PLCID_HtzAnimals ; $7 zoneTableEntry.b PLCID_HpzAnimals ; $8 zoneTableEntry.b PLCID_HpzAnimals ; $9 zoneTableEntry.b PLCID_OozAnimals ; $A zoneTableEntry.b PLCID_MczAnimals ; $B zoneTableEntry.b PLCID_CnzAnimals ; $C zoneTableEntry.b PLCID_CpzAnimals ; $D zoneTableEntry.b PLCID_DezAnimals ; $E zoneTableEntry.b PLCID_ArzAnimals ; $F zoneTableEntry.b PLCID_SczAnimals ; $10 zoneTableEnd dc.b PLCID_SczAnimals ; level slot $11 (non-existent), not part of main table even ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 39 - Game/Time Over text ; ---------------------------------------------------------------------------- ; Sprite_13F74: Obj39: ; (screen-space obj) moveq #0,d0 move.b routine(a0),d0 move.w Obj39_Index(pc,d0.w),d1 jmp Obj39_Index(pc,d1.w) ; =========================================================================== Obj39_Index: offsetTable offsetTableEntry.w Obj39_Init ; 0 offsetTableEntry.w Obj39_SlideIn ; 2 offsetTableEntry.w Obj39_Wait ; 4 ; =========================================================================== ; loc_13F88: Obj39_Init: tst.l (Plc_Buffer).w beq.s + rts ; wait until the art is loaded ; --------------------------------------------------------------------------- + addq.b #2,routine(a0) move.w #$50,x_pixel(a0) btst #0,mapping_frame(a0) beq.s + move.w #$1F0,x_pixel(a0) + move.w #$F0,y_pixel(a0) move.l #Obj39_MapUnc_14C6C,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Game_Over,0,1),art_tile(a0) bsr.w Adjust2PArtPointer move.b #0,render_flags(a0) move.b #0,priority(a0) ; loc_13FCC: Obj39_SlideIn: moveq #$10,d1 cmpi.w #$120,x_pixel(a0) beq.s Obj39_SetTimer blo.s + neg.w d1 + add.w d1,x_pixel(a0) bra.w DisplaySprite ; =========================================================================== ; loc_13FE2: Obj39_SetTimer: move.w #$2D0,anim_frame_duration(a0) addq.b #2,routine(a0) rts ; =========================================================================== ; loc_13FEE: Obj39_Wait: btst #0,mapping_frame(a0) bne.w Obj39_Display move.b (Ctrl_1_Press).w,d0 or.b (Ctrl_2_Press).w,d0 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 bne.s Obj39_Dismiss tst.w anim_frame_duration(a0) beq.s Obj39_Dismiss subq.w #1,anim_frame_duration(a0) bra.w DisplaySprite ; =========================================================================== ; loc_14014: Obj39_Dismiss: tst.b (Time_Over_flag).w bne.s Obj39_TimeOver tst.b (Time_Over_flag_2P).w bne.s Obj39_TimeOver move.b #GameModeID_ContinueScreen,(Game_Mode).w ; => ContinueScreen tst.b (Continue_count).w bne.s Obj39_Check2PMode move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen bra.s Obj39_Check2PMode ; =========================================================================== ; loc_14034: Obj39_TimeOver: clr.l (Saved_Timer).w move.w #1,(Level_Inactive_flag).w ; loc_1403E: Obj39_Check2PMode: tst.w (Two_player_mode).w beq.s Obj39_Display move.w #0,(Level_Inactive_flag).w move.b #GameModeID_2PResults,(Game_Mode).w ; => TwoPlayerResults move.w #VsRSID_Act,(Results_Screen_2P).w tst.b (Time_Over_flag).w bne.s Obj39_Display tst.b (Time_Over_flag_2P).w bne.s Obj39_Display move.w #1,(Game_Over_2P).w move.w #VsRSID_Zone,(Results_Screen_2P).w jsrto (sub_8476).l, JmpTo_sub_8476 move.w #-1,(a4) tst.b parent+1(a0) beq.s + addq.w #1,a4 + move.b #-2,(a4) ; BranchTo17_DisplaySprite Obj39_Display: bra.w DisplaySprite ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 3A - End of level results screen ; ---------------------------------------------------------------------------- ; Sprite_14086: Obj3A: ; (screen-space obj) moveq #0,d0 move.b routine(a0),d0 move.w Obj3A_Index(pc,d0.w),d1 jmp Obj3A_Index(pc,d1.w) ; =========================================================================== ; off_14094: Obj3A_Index: offsetTable offsetTableEntry.w loc_140AC ; 0 offsetTableEntry.w loc_14102 ; 2 offsetTableEntry.w BranchTo_Obj34_MoveTowardsTargetPosition ; 4 offsetTableEntry.w loc_14146 ; 6 offsetTableEntry.w loc_14168 ; 8 offsetTableEntry.w loc_1419C ; $A offsetTableEntry.w loc_141AA ; $C offsetTableEntry.w loc_1419C ; $E offsetTableEntry.w loc_14270 ; $10 offsetTableEntry.w loc_142B0 ; $12 offsetTableEntry.w loc_142CC ; $14 offsetTableEntry.w loc_1413A ; $16 ; =========================================================================== loc_140AC: tst.l (Plc_Buffer).w beq.s + rts ; --------------------------------------------------------------------------- + movea.l a0,a1 lea byte_14380(pc),a2 moveq #7,d1 loc_140BC: _move.b id(a1),d0 beq.s loc_140CE cmpi.b #ObjID_Results,d0 beq.s loc_140CE lea next_object(a1),a1 ; a1=object bra.s loc_140BC ; =========================================================================== loc_140CE: _move.b #ObjID_Results,id(a1) ; load obj3A move.w (a2)+,x_pixel(a1) move.w (a2)+,objoff_30(a1) move.w (a2)+,y_pixel(a1) move.b (a2)+,routine(a1) move.b (a2)+,mapping_frame(a1) move.l #Obj3A_MapUnc_14CBC,mappings(a1) bsr.w Adjust2PArtPointer2 move.b #0,render_flags(a1) lea next_object(a1),a1 ; a1=object dbf d1,loc_140BC loc_14102: moveq #0,d0 cmpi.w #2,(Player_mode).w bne.s loc_14118 addq.w #1,d0 btst #7,(Graphics_Flags).w beq.s loc_14118 addq.w #1,d0 loc_14118: move.b d0,mapping_frame(a0) bsr.w Obj34_MoveTowardsTargetPosition move.w x_pixel(a0),d0 cmp.w objoff_30(a0),d0 bne.w return_14138 move.b #$A,routine(a0) move.w #$B4,anim_frame_duration(a0) return_14138: rts ; =========================================================================== loc_1413A: tst.w (Perfect_rings_left).w bne.w DeleteObject BranchTo_Obj34_MoveTowardsTargetPosition bra.w Obj34_MoveTowardsTargetPosition ; =========================================================================== loc_14146: move.b (Current_Zone).w,d0 cmpi.b #sky_chase_zone,d0 beq.s loc_1415E cmpi.b #wing_fortress_zone,d0 beq.s loc_1415E cmpi.b #death_egg_zone,d0 bne.w Obj34_MoveTowardsTargetPosition loc_1415E: move.b #5,mapping_frame(a0) bra.w Obj34_MoveTowardsTargetPosition ; =========================================================================== loc_14168: move.b (Current_Zone).w,d0 cmpi.b #sky_chase_zone,d0 beq.w BranchTo9_DeleteObject cmpi.b #wing_fortress_zone,d0 beq.w BranchTo9_DeleteObject cmpi.b #death_egg_zone,d0 beq.w BranchTo9_DeleteObject cmpi.b #metropolis_zone_2,d0 bne.s loc_1418E moveq #8,d0 bra.s loc_14194 ; =========================================================================== loc_1418E: move.b (Current_Act).w,d0 addq.b #6,d0 loc_14194: move.b d0,mapping_frame(a0) bra.w Obj34_MoveTowardsTargetPosition ; =========================================================================== loc_1419C: subq.w #1,anim_frame_duration(a0) bne.s BranchTo18_DisplaySprite addq.b #2,routine(a0) BranchTo18_DisplaySprite bra.w DisplaySprite ; =========================================================================== loc_141AA: bsr.w DisplaySprite move.b #1,(Update_Bonus_score).w moveq #0,d0 tst.w (Bonus_Countdown_1).w beq.s loc_141C6 addi.w #10,d0 subi.w #10,(Bonus_Countdown_1).w loc_141C6: tst.w (Bonus_Countdown_2).w beq.s loc_141D6 addi.w #10,d0 subi.w #10,(Bonus_Countdown_2).w loc_141D6: tst.w (Bonus_Countdown_3).w beq.s loc_141E6 addi.w #10,d0 subi.w #10,(Bonus_Countdown_3).w loc_141E6: add.w d0,(Total_Bonus_Countdown).w tst.w d0 bne.s loc_14256 move.w #SndID_TallyEnd,d0 jsr (PlaySound).l addq.b #2,routine(a0) move.w #$B4,anim_frame_duration(a0) cmpi.w #1000,(Total_Bonus_Countdown).w blo.s return_14254 move.w #$12C,anim_frame_duration(a0) lea next_object(a0),a1 ; a1=object loc_14214: _tst.b id(a1) beq.s loc_14220 lea next_object(a1),a1 ; a1=object bra.s loc_14214 ; =========================================================================== loc_14220: _move.b #ObjID_Results,id(a1) ; load obj3A (uses screen-space) move.b #$12,routine(a1) move.w #$188,x_pixel(a1) move.w #$118,y_pixel(a1) move.l #Obj3A_MapUnc_14CBC,mappings(a1) bsr.w Adjust2PArtPointer2 move.b #0,render_flags(a1) move.w #$3C,anim_frame_duration(a1) addq.b #1,(Continue_count).w return_14254: rts ; =========================================================================== loc_14256: jsr (AddPoints).l move.b (Vint_runcount+3).w,d0 andi.b #3,d0 bne.s return_14254 move.w #SndID_Blip,d0 jmp (PlaySound).l ; =========================================================================== loc_14270: moveq #0,d0 move.b (Current_Zone).w,d0 add.w d0,d0 add.b (Current_Act).w,d0 add.w d0,d0 lea LevelOrder(pc),a1 tst.w (Two_player_mode).w beq.s loc_1428C lea LevelOrder_2P(pc),a1 loc_1428C: move.w (a1,d0.w),d0 tst.w d0 bpl.s loc_1429C move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen rts ; =========================================================================== loc_1429C: move.w d0,(Current_ZoneAndAct).w clr.b (Last_star_pole_hit).w clr.b (Last_star_pole_hit_2P).w move.w #1,(Level_Inactive_flag).w rts ; =========================================================================== loc_142B0: tst.w anim_frame_duration(a0) beq.s loc_142BC subq.w #1,anim_frame_duration(a0) rts ; =========================================================================== loc_142BC: addi_.b #2,routine(a0) move.w #SndID_ContinueJingle,d0 jsr (PlaySound).l loc_142CC: subq.w #1,anim_frame_duration(a0) bpl.s loc_142E2 move.w #$13,anim_frame_duration(a0) addq.b #1,anim_frame(a0) andi.b #1,anim_frame(a0) loc_142E2: moveq #$C,d0 add.b anim_frame(a0),d0 move.b d0,mapping_frame(a0) btst #4,(Timer_frames+1).w bne.w DisplaySprite rts ; =========================================================================== ; ------------------------------------------------------------------------------- ; Main game level order ; One value per act. That value is the level/act number of the level to load when ; that act finishes. ; ------------------------------------------------------------------------------- ;word_142F8: LevelOrder: zoneOrderedTable 2,2 ; WrdArr_LevelOrder zoneTableEntry.w emerald_hill_zone_act_2 zoneTableEntry.w chemical_plant_zone_act_1 ; 1 zoneTableEntry.w emerald_hill_zone_act_1 ; 2 zoneTableEntry.w emerald_hill_zone_act_1 ; 3 zoneTableEntry.w wood_zone_act_2 ; 4 zoneTableEntry.w metropolis_zone_act_1 ; 5 zoneTableEntry.w emerald_hill_zone_act_1 ; 6 zoneTableEntry.w emerald_hill_zone_act_1 ; 7 zoneTableEntry.w metropolis_zone_act_2 ; 8 zoneTableEntry.w metropolis_zone_act_3 ; 9 zoneTableEntry.w sky_chase_zone_act_1 ; 10 zoneTableEntry.w emerald_hill_zone_act_1 ; 11 zoneTableEntry.w death_egg_zone_act_1 ; 12 zoneTableEntry.w emerald_hill_zone_act_1 ; 13 zoneTableEntry.w hill_top_zone_act_2 ; 14 zoneTableEntry.w mystic_cave_zone_act_1 ; 15 zoneTableEntry.w hidden_palace_zone_act_2 ; 16 zoneTableEntry.w oil_ocean_zone_act_1 ; 17 zoneTableEntry.w emerald_hill_zone_act_1 ; 18 zoneTableEntry.w emerald_hill_zone_act_1 ; 19 zoneTableEntry.w oil_ocean_zone_act_2 ; 20 zoneTableEntry.w metropolis_zone_act_1 ; 21 zoneTableEntry.w mystic_cave_zone_act_2 ; 22 zoneTableEntry.w oil_ocean_zone_act_1 ; 23 zoneTableEntry.w casino_night_zone_act_2 ; 24 zoneTableEntry.w hill_top_zone_act_1 ; 25 zoneTableEntry.w chemical_plant_zone_act_2 ; 26 zoneTableEntry.w aquatic_ruin_zone_act_1 ; 27 zoneTableEntry.w $FFFF ; 28 zoneTableEntry.w emerald_hill_zone_act_1 ; 29 zoneTableEntry.w aquatic_ruin_zone_act_2 ; 30 zoneTableEntry.w casino_night_zone_act_1 ; 31 zoneTableEntry.w wing_fortress_zone_act_1 ; 32 zoneTableEntry.w emerald_hill_zone_act_1 ; 33 zoneTableEnd ;word_1433C: LevelOrder_2P: zoneOrderedTable 2,2 ; WrdArr_LevelOrder_2P zoneTableEntry.w emerald_hill_zone_act_2 zoneTableEntry.w casino_night_zone_act_1 ; 1 zoneTableEntry.w emerald_hill_zone_act_1 ; 2 zoneTableEntry.w emerald_hill_zone_act_1 ; 3 zoneTableEntry.w wood_zone_act_2 ; 4 zoneTableEntry.w metropolis_zone_act_1 ; 5 zoneTableEntry.w emerald_hill_zone_act_1 ; 6 zoneTableEntry.w emerald_hill_zone_act_1 ; 7 zoneTableEntry.w metropolis_zone_act_2 ; 8 zoneTableEntry.w metropolis_zone_act_3 ; 9 zoneTableEntry.w sky_chase_zone_act_1 ; 10 zoneTableEntry.w emerald_hill_zone_act_1 ; 11 zoneTableEntry.w death_egg_zone_act_1 ; 12 zoneTableEntry.w emerald_hill_zone_act_1 ; 13 zoneTableEntry.w hill_top_zone_act_2 ; 14 zoneTableEntry.w mystic_cave_zone_act_1 ; 15 zoneTableEntry.w hidden_palace_zone_act_2 ; 16 zoneTableEntry.w oil_ocean_zone_act_1 ; 17 zoneTableEntry.w emerald_hill_zone_act_1 ; 18 zoneTableEntry.w emerald_hill_zone_act_1 ; 19 zoneTableEntry.w oil_ocean_zone_act_2 ; 20 zoneTableEntry.w metropolis_zone_act_1 ; 21 zoneTableEntry.w mystic_cave_zone_act_2 ; 22 zoneTableEntry.w $FFFF ; 23 zoneTableEntry.w casino_night_zone_act_2 ; 24 zoneTableEntry.w mystic_cave_zone_act_1 ; 25 zoneTableEntry.w chemical_plant_zone_act_2 ; 26 zoneTableEntry.w aquatic_ruin_zone_act_1 ; 27 zoneTableEntry.w $FFFF ; 28 zoneTableEntry.w emerald_hill_zone_act_1 ; 29 zoneTableEntry.w aquatic_ruin_zone_act_2 ; 30 zoneTableEntry.w casino_night_zone_act_1 ; 31 zoneTableEntry.w wing_fortress_zone_act_1 ; 32 zoneTableEntry.w emerald_hill_zone_act_1 ; 33 zoneTableEnd byte_14380: results_screen_object macro startx, targetx, y, routine, frame dc.w startx, targetx, y dc.b routine, frame endm results_screen_object $20, $120, $B8, 2, 0 results_screen_object $200, $100, $CA, 4, 3 results_screen_object $240, $140, $CA, 6, 4 results_screen_object $278, $178, $BE, 8, 6 results_screen_object $350, $120, $120, 4, 9 results_screen_object $320, $120, $F0, 4, $A results_screen_object $330, $120, $100, 4, $B results_screen_object $340, $120, $110, $16, $E ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 6F - End of special stage results screen ; ---------------------------------------------------------------------------- ; Sprite_143C0: Obj6F: ; (note: screen-space obj) moveq #0,d0 moveq #0,d6 move.b routine(a0),d0 move.w Obj6F_Index(pc,d0.w),d1 jmp Obj6F_Index(pc,d1.w) ; =========================================================================== ; off_143D0: Obj6F_Index: offsetTable offsetTableEntry.w Obj6F_Init ; 0 offsetTableEntry.w Obj6F_InitEmeraldText ; 2 offsetTableEntry.w Obj6F_InitResultTitle ; 4 offsetTableEntry.w Obj6F_Emerald0 ; 6 offsetTableEntry.w Obj6F_Emerald1 ; 8 offsetTableEntry.w Obj6F_Emerald2 ; $A offsetTableEntry.w Obj6F_Emerald3 ; $C offsetTableEntry.w Obj6F_Emerald4 ; $E offsetTableEntry.w Obj6F_Emerald5 ; $10 offsetTableEntry.w Obj6F_Emerald6 ; $12 offsetTableEntry.w BranchTo3_Obj34_MoveTowardsTargetPosition ; $14 offsetTableEntry.w Obj6F_P1Rings ; $16 offsetTableEntry.w Obj6F_P2Rings ; $18 offsetTableEntry.w Obj6F_DeleteIfNotEmerald ; $1A offsetTableEntry.w Obj6F_TimedDisplay ; $1C offsetTableEntry.w Obj6F_TallyScore ; $1E offsetTableEntry.w Obj6F_TimedDisplay ; $20 offsetTableEntry.w Obj6F_DisplayOnly ; $22 offsetTableEntry.w Obj6F_TimedDisplay ; $24 offsetTableEntry.w Obj6F_TimedDisplay ; $26 offsetTableEntry.w Obj6F_TallyPerfect ; $28 offsetTableEntry.w Obj6F_PerfectBonus ; $2A offsetTableEntry.w Obj6F_TimedDisplay ; $2C offsetTableEntry.w Obj6F_DisplayOnly ; $2E offsetTableEntry.w Obj6F_InitAndMoveSuperMsg ; $30 offsetTableEntry.w Obj6F_MoveToTargetPos ; $32 offsetTableEntry.w Obj6F_MoveAndDisplay ; $34 ; =========================================================================== ;loc_14406 Obj6F_Init: tst.l (Plc_Buffer).w beq.s + rts ; =========================================================================== + movea.l a0,a1 lea byte_14752(pc),a2 moveq #$C,d1 - _move.b id(a0),id(a1) ; load obj6F move.w (a2),x_pixel(a1) move.w (a2)+,objoff_32(a1) move.w (a2)+,objoff_30(a1) move.w (a2)+,y_pixel(a1) move.b (a2)+,routine(a1) move.b (a2)+,mapping_frame(a1) move.l #Obj6F_MapUnc_14ED0,mappings(a1) move.b #$78,width_pixels(a1) move.b #0,render_flags(a1) lea next_object(a1),a1 ; go to next object ; a1=object dbf d1,- ; loop ;loc_14450 Obj6F_InitEmeraldText: tst.b (Got_Emerald).w beq.s + move.b #4,mapping_frame(a0) ; "Chaos Emerald" + cmpi.b #7,(Emerald_count).w bne.s + move.b #$19,mapping_frame(a0) ; "Chaos Emeralds" + move.w objoff_30(a0),d0 cmp.w x_pixel(a0),d0 bne.s BranchTo2_Obj34_MoveTowardsTargetPosition move.b #$1C,routine(a0) ; => Obj6F_TimedDisplay move.w #$B4,anim_frame_duration(a0) BranchTo2_Obj34_MoveTowardsTargetPosition bra.w Obj34_MoveTowardsTargetPosition ; =========================================================================== ;loc_14484 Obj6F_InitResultTitle: cmpi.b #7,(Emerald_count).w bne.s + moveq #$16,d0 ; "Sonic has all the" bra.s ++ ; =========================================================================== + tst.b (Got_Emerald).w beq.w DeleteObject moveq #1,d0 ; "Sonic got a" + cmpi.w #2,(Player_mode).w bne.s + addq.w #1,d0 ; "Miles got a" or "Miles has all the" btst #7,(Graphics_Flags).w beq.s + addq.w #1,d0 ; "Tails got a" or "Tails has all the" + move.b d0,mapping_frame(a0) bra.w Obj34_MoveTowardsTargetPosition ; =========================================================================== ;loc_144B6 Obj6F_Emerald6: addq.w #1,d6 ;loc_144B8 Obj6F_Emerald5: addq.w #1,d6 ;loc_144BA Obj6F_Emerald4: addq.w #1,d6 ;loc_144BC Obj6F_Emerald3: addq.w #1,d6 ;loc_144BE Obj6F_Emerald2: addq.w #1,d6 ;loc_144C0 Obj6F_Emerald1: addq.w #1,d6 ;loc_144C2 Obj6F_Emerald0: lea (Got_Emeralds_array).w,a1 tst.b (a1,d6.w) beq.w DeleteObject btst #0,(Vint_runcount+3).w beq.s + bsr.w DisplaySprite + rts ; =========================================================================== ;loc_144DC Obj6F_P2Rings: tst.w (Player_mode).w bne.w DeleteObject cmpi.b #$26,(SpecialStageResults+routine).w ; Do we need space for perfect countdown? beq.w DeleteObject ; Branch if yes moveq #$E,d0 ; "Miles rings" btst #7,(Graphics_Flags).w beq.s + addq.w #1,d0 ; "Tails rings" + lea (Bonus_Countdown_2).w,a1 bra.s loc_1455A ; =========================================================================== ;loc_14500 Obj6F_P1Rings: cmpi.b #$26,(SpecialStageResults+routine).w ; Do we need space for perfect countdown? bne.s + ; Branch if not move.w #5000,(Bonus_Countdown_1).w ; Perfect bonus move.b #$2A,routine(a0) ; => Obj6F_PerfectBonus move.w #$120,y_pixel(a0) st.b (Update_Bonus_score).w ; set to -1 (update) move.w #SndID_Signpost,d0 jsr (PlaySound).l move.w #$5A,(SpecialStageResults+anim_frame_duration).w bra.w Obj6F_PerfectBonus ; =========================================================================== + move.w (Player_mode).w,d0 beq.s ++ move.w #$120,y_pixel(a0) subq.w #1,d0 beq.s ++ moveq #$E,d0 ; "Miles rings" btst #7,(Graphics_Flags).w beq.s + addq.w #1,d0 ; "Tails rings" + lea (Bonus_Countdown_2).w,a1 bra.s loc_1455A ; =========================================================================== + moveq #$D,d0 ; "Sonic rings" lea (Bonus_Countdown_1).w,a1 loc_1455A: tst.w (a1) bne.s + addq.w #5,d0 ; Rings text with zero points + move.b d0,mapping_frame(a0) BranchTo3_Obj34_MoveTowardsTargetPosition bra.w Obj34_MoveTowardsTargetPosition ; =========================================================================== ;loc_14568 Obj6F_DeleteIfNotEmerald: tst.b (Got_Emerald).w beq.w DeleteObject bra.s BranchTo3_Obj34_MoveTowardsTargetPosition ; =========================================================================== ;loc_14572 Obj6F_TimedDisplay: subq.w #1,anim_frame_duration(a0) bne.s BranchTo19_DisplaySprite addq.b #2,routine(a0) BranchTo19_DisplaySprite bra.w DisplaySprite ; =========================================================================== ;loc_14580 Obj6F_TallyScore: bsr.w DisplaySprite move.b #1,(Update_Bonus_score).w moveq #0,d0 tst.w (Bonus_Countdown_1).w beq.s + addi.w #10,d0 subq.w #1,(Bonus_Countdown_1).w + tst.w (Bonus_Countdown_2).w beq.s + addi.w #10,d0 subq.w #1,(Bonus_Countdown_2).w + tst.w (Total_Bonus_Countdown).w beq.s + addi.w #10,d0 subi.w #10,(Total_Bonus_Countdown).w + tst.w d0 bne.s +++ move.w #SndID_TallyEnd,d0 jsr (PlaySound).l addq.b #2,routine(a0) ; => Obj6F_TimedDisplay move.w #$78,anim_frame_duration(a0) tst.w (Perfect_rings_flag).w bne.s + cmpi.w #2,(Player_mode).w beq.s ++ ; rts tst.b (Got_Emerald).w beq.s ++ ; rts cmpi.b #7,(Emerald_count).w bne.s ++ ; rts move.b #$30,routine(a0) ; => Obj6F_InitAndMoveSuperMsg rts ; =========================================================================== + move.b #$24,routine(a0) ; => Obj6F_TimedDisplay move.w #$5A,anim_frame_duration(a0) / rts ; =========================================================================== + jsr (AddPoints).l move.b (Vint_runcount+3).w,d0 andi.b #3,d0 bne.s - ; rts move.w #SndID_Blip,d0 jmp (PlaySound).l ; =========================================================================== ;loc_1461C Obj6F_DisplayOnly: move.w #1,(Level_Inactive_flag).w bra.w DisplaySprite ; =========================================================================== ;loc_14626 Obj6F_TallyPerfect: bsr.w DisplaySprite move.b #1,(Update_Bonus_score).w moveq #0,d0 tst.w (Bonus_Countdown_1).w beq.s + addi.w #20,d0 subi.w #20,(Bonus_Countdown_1).w + tst.w d0 beq.s + jsr (AddPoints).l move.b (Vint_runcount+3).w,d0 andi.b #3,d0 bne.s ++ ; rts move.w #SndID_Blip,d0 jmp (PlaySound).l ; =========================================================================== + move.w #SndID_TallyEnd,d0 jsr (PlaySound).l addq.b #4,routine(a0) move.w #$78,anim_frame_duration(a0) cmpi.w #2,(Player_mode).w beq.s + ; rts tst.b (Got_Emerald).w beq.s + ; rts cmpi.b #7,(Emerald_count).w bne.s + ; rts move.b #$30,routine(a0) ; => Obj6F_InitAndMoveSuperMsg + rts ; =========================================================================== ;loc_14692 Obj6F_PerfectBonus: moveq #$11,d0 ; "Perfect bonus" btst #3,(Vint_runcount+3).w beq.s + moveq #$15,d0 ; null text + move.b d0,mapping_frame(a0) bra.w DisplaySprite ; =========================================================================== ;loc_146A6 Obj6F_InitAndMoveSuperMsg: move.b #$32,next_object+routine(a0) ; => Obj6F_MoveToTargetPos move.w x_pos(a0),d0 cmp.w objoff_32(a0),d0 bne.s Obj6F_MoveToTargetPos move.b #$14,next_object+routine(a0) ; => BranchTo3_Obj34_MoveTowardsTargetPosition subq.w #8,next_object+y_pixel(a0) move.b #$1A,next_object+mapping_frame(a0) ; "Now Sonic can" move.b #$34,routine(a0) ; => Obj6F_MoveAndDisplay subq.w #8,y_pixel(a0) move.b #$1B,mapping_frame(a0) ; "Change into" lea (SpecialStageResults2).w,a1 _move.b id(a0),id(a1) ; load obj6F; (uses screen-space) clr.w x_pixel(a1) move.w #$120,objoff_30(a1) move.w #$B4,y_pixel(a1) move.b #$14,routine(a1) ; => BranchTo3_Obj34_MoveTowardsTargetPosition move.b #$1C,mapping_frame(a1) ; "Super Sonic" move.l #Obj6F_MapUnc_14ED0,mappings(a1) move.b #$78,width_pixels(a1) move.b #0,render_flags(a1) bra.w DisplaySprite ; =========================================================================== ;loc_14714 Obj6F_MoveToTargetPos: moveq #$20,d0 move.w x_pos(a0),d1 cmp.w objoff_32(a0),d1 beq.s BranchTo20_DisplaySprite bhi.s + neg.w d0 + sub.w d0,x_pos(a0) cmpi.w #$200,x_pos(a0) bhi.s + BranchTo20_DisplaySprite bra.w DisplaySprite ; =========================================================================== + rts ; =========================================================================== ;loc_14736 Obj6F_MoveAndDisplay: move.w x_pos(a0),d0 cmp.w objoff_30(a0),d0 bne.w Obj34_MoveTowardsTargetPosition move.w #$B4,anim_frame_duration(a0) move.b #$20,routine(a0) ; => Obj6F_TimedDisplay bra.w DisplaySprite ; =========================================================================== byte_14752: ; startx targx starty routine map frame results_screen_object $240, $120, $AA, 2, 0 ; "Special Stage" results_screen_object 0, $120, $98, 4, 1 ; "Sonic got a" results_screen_object $118, 0, $C4, 6, 5 ; Emerald 0 results_screen_object $130, 0, $D0, 8, 6 ; Emerald 1 results_screen_object $130, 0, $E8, $A, 7 ; Emerald 2 results_screen_object $118, 0, $F4, $C, 8 ; Emerald 3 results_screen_object $100, 0, $E8, $E, 9 ; Emerald 4 results_screen_object $100, 0, $D0, $10, $A ; Emerald 5 results_screen_object $118, 0, $DC, $12, $B ; Emerald 6 results_screen_object $330, $120, $108, $14, $C ; Score results_screen_object $340, $120, $118, $16, $D ; Sonic Rings results_screen_object $350, $120, $128, $18, $E ; Miles Rings results_screen_object $360, $120, $138, $1A, $10 ; Gems Bonus ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj34_MapUnc_147BA: offsetTable offsetTableEntry.w word_147E8 offsetTableEntry.w word_147E8 offsetTableEntry.w word_147E8 offsetTableEntry.w word_147E8 offsetTableEntry.w word_14842 offsetTableEntry.w word_14842 offsetTableEntry.w word_14B24 offsetTableEntry.w word_14894 offsetTableEntry.w word_148CE offsetTableEntry.w word_147E8 offsetTableEntry.w word_14930 offsetTableEntry.w word_14972 offsetTableEntry.w word_149C4 offsetTableEntry.w word_14A1E offsetTableEntry.w word_14B86 offsetTableEntry.w word_14A88 offsetTableEntry.w word_14AE2 offsetTableEntry.w word_14BC8 offsetTableEntry.w word_14BEA offsetTableEntry.w word_14BF4 offsetTableEntry.w word_14BFE offsetTableEntry.w word_14C08 offsetTableEntry.w word_14C32 word_147E8: dc.w $B dc.w 5, $8580, $82C0, $FFC3 dc.w 9, $85DE, $82EF, $FFD0 dc.w 5, $8580, $82C0, $FFE8 dc.w 5, $85E4, $82F2, $FFF8 dc.w 5, $85E8, $82F4, 8 dc.w 5, $85EC, $82F6, $18 dc.w 5, $85F0, $82F8, $28 dc.w 5, $85F4, $82FA, $48 dc.w 1, $85F8, $82FC, $58 dc.w 5, $85EC, $82F6, $60 dc.w 5, $85EC, $82F6, $70 word_14842: dc.w $A dc.w 9, $85DE, $82EF, $FFE0 dc.w 5, $8580, $82C0, $FFF8 dc.w 5, $85E4, $82F2, 8 dc.w 5, $85E8, $82F4, $18 dc.w 5, $8588, $82C4, $28 dc.w 5, $85EC, $82F6, $38 dc.w 5, $8588, $82C4, $48 dc.w 5, $85F0, $82F8, $58 dc.w 1, $85F4, $82FA, $68 dc.w 5, $85F6, $82FB, $70 word_14894: dc.w 7 dc.w 5, $85DE, $82EF, 8 dc.w 1, $85E2, $82F1, $18 dc.w 5, $85E4, $82F2, $20 dc.w 5, $85E4, $82F2, $30 dc.w 5, $85E8, $82F4, $51 dc.w 5, $8588, $82C4, $60 dc.w 5, $85EC, $82F6, $70 word_148CE: dc.w $C dc.w 5, $85DE, $82EF, $FFB8 dc.w 1, $85E2, $82F1, $FFC8 dc.w 5, $85E4, $82F2, $FFD0 dc.w 5, $85E4, $82F2, $FFE0 dc.w 5, $8580, $82C0, $FFF0 dc.w 5, $8584, $82C2, 0 dc.w 5, $85E8, $82F4, $20 dc.w 5, $85EC, $82F6, $30 dc.w 5, $85F0, $82F8, $40 dc.w 5, $85EC, $82F6, $50 dc.w 5, $85F4, $82FA, $60 dc.w 5, $8580, $82C0, $70 word_14930: dc.w 8 dc.w 5, $8588, $82C4, $FFFB dc.w 1, $85DE, $82EF, $B dc.w 5, $85E0, $82F0, $13 dc.w 5, $8588, $82C4, $33 dc.w 5, $85E4, $82F2, $43 dc.w 5, $8580, $82C0, $53 dc.w 5, $85E8, $82F4, $60 dc.w 5, $8584, $82C2, $70 word_14972: dc.w $A dc.w 9, $85DE, $82EF, $FFD0 dc.w 5, $85E4, $82F2, $FFE8 dc.w 5, $85E8, $82F4, $FFF8 dc.w 5, $85EC, $82F6, 8 dc.w 1, $85F0, $82F8, $18 dc.w 5, $85F2, $82F9, $20 dc.w 5, $85F2, $82F9, $41 dc.w 5, $85F6, $82FB, $50 dc.w 5, $85FA, $82FD, $60 dc.w 5, $8580, $82C0, $70 word_149C4: dc.w $B dc.w 5, $85DE, $82EF, $FFD1 dc.w 5, $85E2, $82F1, $FFE0 dc.w 5, $85E6, $82F3, $FFF0 dc.w 1, $85EA, $82F5, 0 dc.w 5, $8584, $82C2, 8 dc.w 5, $8588, $82C4, $18 dc.w 5, $8584, $82C2, $38 dc.w 1, $85EA, $82F5, $48 dc.w 5, $85EC, $82F6, $50 dc.w 5, $85F0, $82F8, $60 dc.w 5, $85F4, $82FA, $70 word_14A1E: dc.w $D dc.w 5, $85DE, $82EF, $FFA4 dc.w 5, $85E2, $82F1, $FFB4 dc.w 5, $8580, $82C0, $FFC4 dc.w 9, $85E6, $82F3, $FFD1 dc.w 1, $85EC, $82F6, $FFE9 dc.w 5, $85DE, $82EF, $FFF1 dc.w 5, $85EE, $82F7, 0 dc.w 5, $85F2, $82F9, $10 dc.w 5, $85F6, $82FB, $31 dc.w 5, $85F2, $82F9, $41 dc.w 5, $85EE, $82F7, $50 dc.w 5, $8584, $82C2, $60 dc.w 5, $85FA, $82FD, $70 word_14A88: dc.w $B dc.w 5, $85DE, $82EF, $FFD2 dc.w 5, $85E2, $82F1, $FFE2 dc.w 5, $85E6, $82F3, $FFF2 dc.w 5, $85DE, $82EF, 0 dc.w 5, $85EA, $82F5, $10 dc.w 1, $85EE, $82F7, $20 dc.w 5, $85F0, $82F8, $28 dc.w 5, $85F4, $82FA, $48 dc.w 5, $85E6, $82F3, $58 dc.w 1, $85EE, $82F7, $68 dc.w 5, $8584, $82C2, $70 word_14AE2: dc.w 8 dc.w 5, $85DE, $82EF, $FFF0 dc.w 5, $85E2, $82F1, 0 dc.w 5, $85E6, $82F3, $10 dc.w 5, $85EA, $82F5, $30 dc.w 5, $85EE, $82F7, $40 dc.w 5, $85F2, $82F9, $50 dc.w 5, $85DE, $82EF, $60 dc.w 5, $8580, $82C0, $70 word_14B24: dc.w $C dc.w 9, $85DE, $82EF, $FFB1 dc.w 1, $85E4, $82F2, $FFC8 dc.w 5, $8584, $82C2, $FFD0 dc.w 5, $85E6, $82F3, $FFE0 dc.w 5, $85EA, $82F5, 1 dc.w 5, $8588, $82C4, $10 dc.w 5, $85EE, $82F7, $20 dc.w 5, $85F2, $82F9, $30 dc.w 5, $85EE, $82F7, $40 dc.w 5, $8580, $82C0, $50 dc.w 5, $85F6, $82FB, $5F dc.w 5, $85F6, $82FB, $6F word_14B86: dc.w 8 dc.w 5, $85DE, $82EF, $FFF2 dc.w 5, $8580, $82C0, 2 dc.w 5, $85E2, $82F1, $10 dc.w 5, $85E6, $82F3, $20 dc.w 5, $85EA, $82F5, $30 dc.w 5, $8580, $82C0, $51 dc.w 5, $85EE, $82F7, $60 dc.w 5, $85EE, $82F7, $70 word_14BC8: dc.w 4 dc.w 5, $858C, $82C6, 1 dc.w 5, $8588, $82C4, $10 dc.w 5, $8584, $82C2, $20 dc.w 5, $8580, $82C0, $30 word_14BEA: dc.w 1 dc.w 7, $A590, $A2C8, 0 word_14BF4: dc.w 1 dc.w $B, $A598, $A2CC, 0 word_14BFE: dc.w 1 dc.w $B, $A5A4, $A2D2, 0 word_14C08: dc.w 5 dc.w $D, $85B0, $82D8, $FFB8 dc.w $D, $85B8, $82DC, $FFD8 dc.w $D, $85C0, $82E0, $FFF8 dc.w $D, $85C8, $82E4, $18 dc.w 5, $85D0, $82E8, $38 word_14C32: dc.w 7 dc.w $9003, $85D4, $82EA, 0 dc.w $B003, $85D4, $82EA, 0 dc.w $D003, $85D4, $82EA, 0 dc.w $F003, $85D4, $82EA, 0 dc.w $1003, $85D4, $82EA, 0 dc.w $3003, $85D4, $82EA, 0 dc.w $5003, $85D4, $82EA, 0 ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj39_MapUnc_14C6C: BINCLUDE "mappings/sprite/obj39.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj3A_MapUnc_14CBC: offsetTable offsetTableEntry.w word_14CDA offsetTableEntry.w word_14D1C offsetTableEntry.w word_14D5E offsetTableEntry.w word_14DA0 offsetTableEntry.w word_14DDA offsetTableEntry.w word_14BC8 offsetTableEntry.w word_14BEA offsetTableEntry.w word_14BF4 offsetTableEntry.w word_14BFE offsetTableEntry.w word_14DF4 offsetTableEntry.w word_14E1E offsetTableEntry.w word_14E50 offsetTableEntry.w word_14E82 offsetTableEntry.w word_14E8C offsetTableEntry.w word_14E96 word_14CDA: dc.w 8 dc.w 5, $85D0, $82E8, $FFC0 dc.w 5, $8588, $82C4, $FFD0 dc.w 5, $8584, $82C2, $FFE0 dc.w 1, $85C0, $82E0, $FFF0 dc.w 5, $85B4, $82DA, $FFF8 dc.w 5, $85B8, $82DC, $10 dc.w 5, $8588, $82C4, $20 dc.w 5, $85D4, $82EA, $2F word_14D1C: dc.w 8 dc.w 9, $85C6, $82E3, $FFBC dc.w 1, $85C0, $82E0, $FFD4 dc.w 5, $85C2, $82E1, $FFDC dc.w 5, $8580, $82C0, $FFEC dc.w 5, $85D0, $82E8, $FFFC dc.w 5, $85B8, $82DC, $14 dc.w 5, $8588, $82C4, $24 dc.w 5, $85D4, $82EA, $33 word_14D5E: dc.w 8 dc.w 5, $85D4, $82EA, $FFC3 dc.w 5, $85B0, $82D8, $FFD0 dc.w 1, $85C0, $82E0, $FFE0 dc.w 5, $85C2, $82E1, $FFE8 dc.w 5, $85D0, $82E8, $FFF8 dc.w 5, $85B8, $82DC, $10 dc.w 5, $8588, $82C4, $20 dc.w 5, $85D4, $82EA, $2F word_14DA0: dc.w 7 dc.w 5, $85D4, $82EA, $FFC8 dc.w 5, $85BC, $82DE, $FFD8 dc.w 5, $85CC, $82E6, $FFE8 dc.w 5, $8588, $82C4, $FFF8 dc.w 5, $85D8, $82EC, 8 dc.w 5, $85B8, $82DC, $18 dc.w 5, $85BC, $82DE, $28 word_14DDA: dc.w 3 dc.w 5, $85B0, $82D8, 0 dc.w 5, $85B4, $82DA, $10 dc.w 5, $85D4, $82EA, $1F word_14DF4: dc.w 5 dc.w 9, $A5E6, $A2F3, $FFB8 dc.w 5, $A5EC, $A2F6, $FFD0 dc.w 5, $85F0, $82F8, $FFD4 dc.w $D, $8520, $8290, $38 dc.w 1, $86F0, $8378, $58 word_14E1E: dc.w 6 dc.w $D, $A6DA, $A36D, $FFA4 dc.w $D, $A5DE, $A2EF, $FFCC dc.w 1, $A6CA, $A365, $FFEC dc.w 5, $85F0, $82F8, $FFE8 dc.w $D, $8528, $8294, $38 dc.w 1, $86F0, $8378, $58 word_14E50: dc.w 6 dc.w $D, $A6D2, $A369, $FFA4 dc.w $D, $A5DE, $A2EF, $FFCC dc.w 1, $A6CA, $A365, $FFEC dc.w 5, $85F0, $82F8, $FFE8 dc.w $D, $8530, $8298, $38 dc.w 1, $86F0, $8378, $58 word_14E82: dc.w 1 dc.w 6, $85F4, $82FA, 0 word_14E8C: dc.w 1 dc.w 6, $85FA, $82FD, 0 word_14E96: dc.w 7 dc.w $D, $A540, $A2A0, $FF98 dc.w 9, $A548, $A2A4, $FFB8 dc.w $D, $A5DE, $A2EF, $FFD8 dc.w 1, $A6CA, $A365, $FFF8 dc.w 5, $85F0, $82F8, $FFF4 dc.w $D, $8538, $829C, $38 dc.w 1, $86F0, $8378, $58 ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj6F_MapUnc_14ED0: BINCLUDE "mappings/sprite/obj6F.bin" ; =========================================================================== ;loc_15584: ; level title card drawing function called from Vint DrawLevelTitleCard: lea (VDP_data_port).l,a6 tst.w (TitleCard_ZoneName+titlecard_leaveflag).w bne.w loc_15670 moveq #$3F,d5 move.l #make_block_tile_pair(ArtTile_ArtNem_TitleCard+$5A,0,0,0,1),d6 tst.w (Two_player_mode).w beq.s loc_155A8 moveq #$1F,d5 move.l #make_block_tile_pair_2p(ArtTile_ArtNem_TitleCard+$5A,0,0,0,1),d6 loc_155A8: lea (TitleCard_Background+titlecard_vram_dest).w,a0 moveq #1,d7 ; Once for P1, once for P2 (if in 2p mode) loc_155AE: move.w (a0)+,d0 beq.s loc_155C6 clr.w -2(a0) jsr sub_15792(pc) move.l d0,VDP_control_port-VDP_data_port(a6) move.w d5,d4 loc_155C0: move.l d6,(a6) dbf d4,loc_155C0 loc_155C6: dbf d7,loc_155AE moveq #$26,d1 sub.w (TitleCard_Bottom+titlecard_split_point).w,d1 lsr.w #1,d1 subq.w #1,d1 moveq #7,d5 move.l #make_block_tile_pair(ArtTile_ArtNem_TitleCard+$5C,0,0,1,1),d6 tst.w (Two_player_mode).w beq.s loc_155EA moveq #3,d5 move.l #make_block_tile_pair_2p(ArtTile_ArtNem_TitleCard+$5C,0,0,1,1),d6 loc_155EA: lea (TitleCard_Bottom+titlecard_vram_dest).w,a0 moveq #1,d7 ; Once for P1, once for P2 (if in 2p mode) loc_155F0: move.w (a0)+,d0 beq.s loc_15614 clr.w -2(a0) jsr sub_15792(pc) move.w d5,d4 loc_155FE: move.l d0,VDP_control_port-VDP_data_port(a6) move.w d1,d3 loc_15604: move.l d6,(a6) dbf d3,loc_15604 addi.l #vdpCommDelta($0080),d0 dbf d4,loc_155FE loc_15614: dbf d7,loc_155F0 move.w (TitleCard_Left+titlecard_split_point).w,d1 ; horizontal draw from left until this position subq.w #1,d1 moveq #$D,d5 move.l #make_block_tile_pair(ArtTile_ArtNem_TitleCard+$58,0,0,0,1),d6 ; VRAM location of graphic to fill on left side tst.w (Two_player_mode).w beq.s loc_15634 moveq #6,d5 move.l #make_block_tile_pair_2p(ArtTile_ArtNem_TitleCard+$58,0,0,0,1),d6 ; VRAM location of graphic to fill on left side (2p) loc_15634: lea (TitleCard_Left+titlecard_vram_dest).w,a0 ; obj34 red title card left side part moveq #1,d7 ; Once for P1, once for P2 (if in 2p mode) move.w #$8F80,VDP_control_port-VDP_data_port(a6) ; VRAM pointer increment: $0080 loc_15640: move.w (a0)+,d0 beq.s loc_15664 clr.w -2(a0) jsr sub_15792(pc) move.w d1,d4 loc_1564E: move.l d0,VDP_control_port-VDP_data_port(a6) move.w d5,d3 loc_15654: move.l d6,(a6) dbf d3,loc_15654 addi.l #vdpCommDelta($0002),d0 dbf d4,loc_1564E loc_15664: dbf d7,loc_15640 move.w #$8F02,VDP_control_port-VDP_data_port(a6) ; VRAM pointer increment: $0002 rts ; =========================================================================== loc_15670: moveq #9,d3 moveq #3,d4 move.l #make_block_tile_pair(ArtTile_ArtNem_TitleCard+$5A,0,0,0,1),d5 move.l #make_block_tile_pair(ArtTile_ArtNem_TitleCard+$5C,0,0,1,1),d6 tst.w (Two_player_mode).w beq.s + moveq #4,d3 moveq #1,d4 move.l #make_block_tile_pair_2p(ArtTile_ArtNem_TitleCard+$5A,0,0,0,1),d5 move.l #make_block_tile_pair_2p(ArtTile_ArtNem_TitleCard+$5C,0,0,1,1),d6 + lea (TitleCard_Left+titlecard_vram_dest).w,a0 moveq #1,d7 ; Once for P1, once for P2 (if in 2p mode) move.w #$8F80,VDP_control_port-VDP_data_port(a6) ; VRAM pointer increment: $0080 loc_156A2: move.w (a0)+,d0 beq.s loc_156CE clr.w -2(a0) jsr sub_15792(pc) moveq #3,d2 loc_156B0: move.l d0,VDP_control_port-VDP_data_port(a6) move.w d3,d1 - move.l d5,(a6) dbf d1,- move.w d4,d1 - move.l d6,(a6) dbf d1,- addi.l #vdpCommDelta($0002),d0 dbf d2,loc_156B0 loc_156CE: dbf d7,loc_156A2 move.w #$8F02,VDP_control_port-VDP_data_port(a6) ; VRAM pointer increment: $0002 moveq #7,d5 move.l #make_block_tile_pair(ArtTile_ArtNem_TitleCard+$5A,0,0,0,1),d6 tst.w (Two_player_mode).w beq.s + moveq #3,d5 move.l #make_block_tile_pair_2p(ArtTile_ArtNem_TitleCard+$5A,0,0,0,1),d6 + lea (TitleCard_Bottom+titlecard_vram_dest).w,a0 moveq #1,d7 ; Once for P1, once for P2 (if in 2p mode) loc_156F4: move.w (a0)+,d0 beq.s loc_15714 clr.w -2(a0) jsr sub_15792(pc) move.w d5,d4 - move.l d0,VDP_control_port-VDP_data_port(a6) move.l d6,(a6) move.l d6,(a6) addi.l #vdpCommDelta($0080),d0 dbf d4,- loc_15714: dbf d7,loc_156F4 move.w (TitleCard_Background+titlecard_vram_dest).w,d4 beq.s loc_1578C lea VDP_control_port-VDP_data_port(a6),a5 tst.w (Two_player_mode).w beq.s loc_15758 lea (Camera_X_pos_P2).w,a3 lea (Level_Layout).w,a4 move.w #vdpComm(VRAM_Plane_A_Name_Table_2P,VRAM,WRITE)>>16,d2 moveq #1,d6 - movem.l d4-d6,-(sp) moveq #-$10,d5 move.w d4,d1 bsr.w CalcBlockVRAMPosB move.w d1,d4 moveq #-$10,d5 moveq #$1F,d6 bsr.w DrawBlockRow movem.l (sp)+,d4-d6 addi.w #$10,d4 dbf d6,- loc_15758: lea (Camera_X_pos).w,a3 lea (Level_Layout).w,a4 move.w #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE)>>16,d2 move.w (TitleCard_Background+titlecard_vram_dest).w,d4 moveq #1,d6 - movem.l d4-d6,-(sp) moveq #-$10,d5 move.w d4,d1 bsr.w CalcBlockVRAMPos move.w d1,d4 moveq #-$10,d5 moveq #$1F,d6 bsr.w DrawBlockRow movem.l (sp)+,d4-d6 addi.w #$10,d4 dbf d6,- loc_1578C: clr.w (TitleCard_Background+titlecard_vram_dest).w rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to convert a VRAM address into a 32-bit VRAM write command word ; Input: ; d0 VRAM address (word) ; Output: ; d0 32-bit VDP command word for a VRAM write to specified address. ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_15792: andi.l #$FFFF,d0 lsl.l #2,d0 lsr.w #2,d0 ori.w #vdpComm($0000,VRAM,WRITE)>>16,d0 swap d0 rts ; End of function sub_15792 ; =========================================================================== ;loc_157A4 LoadTitleCardSS: movem.l d0/a0,-(sp) bsr.s LoadTitleCard0 movem.l (sp)+,d0/a0 bra.s loc_157EC ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_157B0: LoadTitleCard0: move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_TitleCard),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_TitleCard).l,a0 jsrto (NemDec).l, JmpTo2_NemDec lea (Level_Layout).w,a4 lea (ArtNem_TitleCard2).l,a0 jmpto (NemDecToRAM).l, JmpTo_NemDecToRAM ; =========================================================================== ; loc_157D2: LoadTitleCard: bsr.s LoadTitleCard0 moveq #0,d0 move.b (Current_Zone).w,d0 move.b Off_TitleCardLetters(pc,d0.w),d0 lea TitleCardLetters(pc),a0 lea (a0,d0.w),a0 move.l #vdpComm(tiles_to_bytes(ArtTile_LevelName),VRAM,WRITE),d0 loc_157EC: move #$2700,sr lea (Level_Layout).w,a1 lea (VDP_data_port).l,a6 move.l d0,4(a6) loc_157FE: moveq #0,d0 move.b (a0)+,d0 bmi.s loc_1581A lsl.w #5,d0 lea (a1,d0.w),a2 moveq #0,d1 move.b (a0)+,d1 lsl.w #3,d1 subq.w #1,d1 loc_15812: move.l (a2)+,(a6) dbf d1,loc_15812 bra.s loc_157FE ; =========================================================================== loc_1581A: move #$2300,sr rts ; =========================================================================== ; byte_15820: Off_TitleCardLetters: dc.b TitleCardLetters_EHZ - TitleCardLetters ; 0 dc.b TitleCardLetters_EHZ - TitleCardLetters ; 1 dc.b TitleCardLetters_EHZ - TitleCardLetters ; 2 dc.b TitleCardLetters_EHZ - TitleCardLetters ; 3 dc.b TitleCardLetters_MTZ - TitleCardLetters ; 4 dc.b TitleCardLetters_MTZ - TitleCardLetters ; 5 dc.b TitleCardLetters_WFZ - TitleCardLetters ; 6 dc.b TitleCardLetters_HTZ - TitleCardLetters ; 7 dc.b TitleCardLetters_HPZ - TitleCardLetters ; 8 dc.b TitleCardLetters_EHZ - TitleCardLetters ; 9 dc.b TitleCardLetters_OOZ - TitleCardLetters ; A dc.b TitleCardLetters_MCZ - TitleCardLetters ; B dc.b TitleCardLetters_CNZ - TitleCardLetters ; C dc.b TitleCardLetters_CPZ - TitleCardLetters ; D dc.b TitleCardLetters_DEZ - TitleCardLetters ; E dc.b TitleCardLetters_ARZ - TitleCardLetters ; F dc.b TitleCardLetters_SCZ - TitleCardLetters ; 10 even ; temporarily remap characters to title card letter format ; Characters are encoded as Aa, Bb, Cc, etc. through a macro charset 'A',0 ; can't have an embedded 0 in a string charset 'B',"\4\8\xC\4\x10\x14\x18\x1C\x1E\x22\x26\x2A\4\4\x30\x34\x38\x3C\x40\x44\x48\x4C\x52\x56\4" charset 'a',"\4\4\4\4\4\4\4\4\2\4\4\4\6\4\4\4\4\4\4\4\4\4\6\4\4" charset '.',"\x5A" ; Defines which letters load for the continue screen ; Each letter occurs only once, and the letters ENOZ (i.e. ZONE) aren't loaded here ; However, this is hidden by the titleLetters macro, and normal titles can be used ; (the macro is defined near SpecialStage_ResultsLetters, which uses it before here) ; word_15832: TitleCardLetters: TitleCardLetters_EHZ: titleLetters "EMERALD HILL" TitleCardLetters_MTZ: titleLetters "METROPOLIS" TitleCardLetters_HTZ: titleLetters "HILL TOP" TitleCardLetters_HPZ: titleLetters "HIDDEN PALACE" TitleCardLetters_OOZ: titleLetters "OIL OCEAN" TitleCardLetters_MCZ: titleLetters "MYSTIC CAVE" TitleCardLetters_CNZ: titleLetters "CASINO NIGHT" TitleCardLetters_CPZ: titleLetters "CHEMICAL PLANT" TitleCardLetters_ARZ: titleLetters "AQUATIC RUIN" TitleCardLetters_SCZ: titleLetters "SKY CHASE" TitleCardLetters_WFZ: titleLetters "WING FORTRESS" TitleCardLetters_DEZ: titleLetters "DEATH EGG" charset ; revert character set ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo2_NemDec jmp (NemDec).l JmpTo_NemDecToRAM jmp (NemDecToRAM).l JmpTo3_LoadPLC jmp (LoadPLC).l JmpTo_sub_8476 jmp (sub_8476).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 36 - Spikes ; ---------------------------------------------------------------------------- ; OST Variables: spikes_base_x_pos = objoff_30 ; original x-position spikes_base_y_pos = objoff_32 ; original y-position spikes_retract_offset = objoff_34 ; actual position relative to base position spikes_retract_state = objoff_36 ; 0 = positive offset, 1 = original position spikes_retract_timer = objoff_38 ; delay, before spikes move again ; Sprite_15900: Obj36: moveq #0,d0 move.b routine(a0),d0 move.w Obj36_Index(pc,d0.w),d1 jmp Obj36_Index(pc,d1.w) ; =========================================================================== ; off_1590E: Obj36_Index: offsetTable offsetTableEntry.w Obj36_Init ; 0 offsetTableEntry.w Obj36_Upright ; 2 offsetTableEntry.w Obj36_Sideways ; 4 offsetTableEntry.w Obj36_Upsidedown ; 6 ; =========================================================================== ; byte_15916: Obj36_InitData: ; width_pixels ; y_radius dc.b $10,$10 ; 0 - Upright or ceiling spikes dc.b $20,$10 ; 2 dc.b $30,$10 ; 4 dc.b $40,$10 ; 6 dc.b $10,$10 ; 8 - Sideways spikes dc.b $10,$20 ; 10 dc.b $10,$30 ; 12 dc.b $10,$40 ; 14 ; =========================================================================== ; loc_15926: Obj36_Init: addq.b #2,routine(a0) ; => Obj36_Upright move.l #Obj36_MapUnc_15B68,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Spikes,1,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #4,priority(a0) move.b subtype(a0),d0 andi.b #$F,subtype(a0) ; lower 4 bits determine behavior, upper bits need to be removed andi.w #$F0,d0 lea_ Obj36_InitData,a1 ; upper 4 bits determine size and orientation lsr.w #3,d0 ; use upper 4 bits * 2 as offset adda.w d0,a1 move.b (a1)+,width_pixels(a0) move.b (a1)+,y_radius(a0) lsr.w #1,d0 ; use upper 4 bits to determine mappings frame move.b d0,mapping_frame(a0) cmpi.b #4,d0 ; do spikes face sideways? blo.s + ; if not, branch addq.b #2,routine(a0) ; => Obj36_Sideways move.w #make_art_tile(ArtTile_ArtNem_HorizSpike,1,0),art_tile(a0) + btst #1,status(a0) ; are spikes upsiede-down? beq.s + ; if not, branch move.b #6,routine(a0) ; => Obj36_Upsidedown + move.w x_pos(a0),spikes_base_x_pos(a0) move.w y_pos(a0),spikes_base_y_pos(a0) bra.w Adjust2PArtPointer ; =========================================================================== ; loc_15996: Obj36_Upright: bsr.w MoveSpikes moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObject move.b status(a0),d6 andi.b #standing_mask,d6 ; are Sonic or Tails standing on the object? beq.s Obj36_UprightEnd ; if not, branch move.b d6,d0 andi.b #p1_standing,d0 ; is Sonic standing on the object? beq.s + ; if not, branch lea (MainCharacter).w,a1 ; a1=character bsr.w Touch_ChkHurt2 + andi.b #p2_standing,d6 ; is Tails standing on the object? beq.s Obj36_UprightEnd ; if not, branch lea (Sidekick).w,a1 ; a1=character bsr.w Touch_ChkHurt2 ; loc_159DE: Obj36_UprightEnd: move.w spikes_base_x_pos(a0),d0 bra.w MarkObjGone2 ; =========================================================================== ; loc_159E6: Obj36_Sideways: move.w x_pos(a0),-(sp) bsr.w MoveSpikes moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 move.w (sp)+,d4 bsr.w SolidObject swap d6 andi.w #touch_side_mask,d6 ; are Sonic or Tails pushing against the side? beq.s Obj36_SidewaysEnd ; if not, branch move.b d6,d0 andi.b #p1_touch_side,d0 ; is Sonic pushing against the side? beq.s + ; if not, branch lea (MainCharacter).w,a1 ; a1=character bsr.w Touch_ChkHurt2 bclr #p1_pushing_bit,status(a0) + andi.b #p2_touch_side,d6 ; is Tails pushing against the side? beq.s Obj36_SidewaysEnd ; if not, branch lea (Sidekick).w,a1 ; a1=character bsr.w Touch_ChkHurt2 bclr #p2_pushing_bit,status(a0) ; loc_15A3A: Obj36_SidewaysEnd: move.w spikes_base_x_pos(a0),d0 bra.w MarkObjGone2 ; =========================================================================== ; loc_15A42: Obj36_Upsidedown: bsr.w MoveSpikes moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObject swap d6 andi.w #touch_bottom_mask,d6 ; are Sonic or Tails touching the bottom? beq.s Obj36_UpsidedownEnd ; if not, branch move.b d6,d0 andi.b #p1_touch_bottom,d0 ; is Sonic touching the bottom? beq.s + ; if not, branch lea (MainCharacter).w,a1 ; a1=character bsr.w Touch_ChkHurt2 + andi.b #p2_touch_bottom,d6 ; is Tails touching the bottom? beq.s Obj36_UpsidedownEnd ; if not, branch lea (Sidekick).w,a1 ; a1=character bsr.w Touch_ChkHurt2 ; loc_15A88: Obj36_UpsidedownEnd: move.w spikes_base_x_pos(a0),d0 bra.w MarkObjGone2 ; --------------------------------------------------------------------------- ; Subroutine for checking if Sonic/Tails should be hurt and hurting them if so ; unlike Touch_ChkHurt, the character is at a1 instead of a0 ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| Touch_ChkHurt2: btst #status_sec_isInvincible,status_secondary(a1) ; is character invincible? bne.s + ; rts ; if yes, branch tst.w invulnerable_time(a1) ; is character invulnerable? bne.s + ; rts ; if yes, branch cmpi.b #4,routine(a1) ; is the character hurt, dieing, etc. ? bhs.s + ; rts ; if yes, branch move.l y_pos(a1),d3 move.w y_vel(a1),d0 ext.l d0 asl.l #8,d0 sub.l d0,d3 move.l d3,y_pos(a1) movea.l a0,a2 movea.l a1,a0 jsr (HurtCharacter).l movea.l a2,a0 + rts ; End of function Touch_ChkHurt2 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; handles direction, timing and movement of moving spikes ; sub_15AC6: MoveSpikes: moveq #0,d0 move.b subtype(a0),d0 add.w d0,d0 move.w MoveSpikes_Behaviors(pc,d0.w),d1 jmp MoveSpikes_Behaviors(pc,d1.w) ; End of function MoveSpikes ; =========================================================================== ; off_15AD6: MoveSpikes_Behaviors: offsetTable offsetTableEntry.w MoveSpikes_Still ; 0 offsetTableEntry.w MoveSpikes_Vertical ; 1 offsetTableEntry.w MoveSpikes_Horizontal ; 2 ; =========================================================================== ; return_15ADC: MoveSpikes_Still: rts ; =========================================================================== ; loc_15ADE: MoveSpikes_Vertical: bsr.w MoveSpikes_Delay moveq #0,d0 move.b spikes_retract_offset(a0),d0 add.w spikes_base_y_pos(a0),d0 ; apply offset to y-position move.w d0,y_pos(a0) rts ; =========================================================================== ; loc_15AF2: MoveSpikes_Horizontal: bsr.w MoveSpikes_Delay moveq #0,d0 move.b spikes_retract_offset(a0),d0 add.w spikes_base_x_pos(a0),d0 ; apply offset to x-position move.w d0,x_pos(a0) rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_15B06: MoveSpikes_Delay: tst.w spikes_retract_timer(a0) ; is it time for spikes to move again? beq.s MoveSpikes_ChkDir ; if yes, branch subq.w #1,spikes_retract_timer(a0) ; else, decrement timer bne.s + ; rts ; branch, if timer didn't reach 0 tst.b render_flags(a0) ; are spikes on screen? bpl.s + ; rts ; if not, branch move.w #SndID_SpikesMove,d0 ; play spike movement sount jsr (PlaySound).l bra.s + ; rts ; =========================================================================== ; loc_15B24: MoveSpikes_ChkDir: tst.w spikes_retract_state(a0) ; do spikes need to move away from initial position? beq.s MoveSpikes_Retract ; if yes, branch subi.w #$800,spikes_retract_offset(a0) ; subtract 8 pixels from offset bhs.s + ; rts ; branch, if offset is not yet 0 move.w #0,spikes_retract_offset(a0) move.w #0,spikes_retract_state(a0) ; switch state move.w #$3C,spikes_retract_timer(a0) ; reset timer bra.s + ; rts ; =========================================================================== ; loc_15B46: MoveSpikes_Retract: addi.w #$800,spikes_retract_offset(a0) ; add 8 pixels to offset cmpi.w #$2000,spikes_retract_offset(a0) ; is offset the width of one spike block (32 pixels)? blo.s + ; rts ; if not, branch move.w #$2000,spikes_retract_offset(a0) move.w #1,spikes_retract_state(a0) ; switch state move.w #$3C,spikes_retract_timer(a0) ; reset timer + rts ; End of function MoveSpikes_Delay ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj36_MapUnc_15B68: BINCLUDE "mappings/sprite/obj36.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 3B - Purple rock (leftover from S1) ; ---------------------------------------------------------------------------- ; Sprite_15CC8: Obj3B: moveq #0,d0 move.b routine(a0),d0 move.w Obj3B_Index(pc,d0.w),d1 jmp Obj3B_Index(pc,d1.w) ; =========================================================================== ; off_15CD6: Obj3B_Index: offsetTable offsetTableEntry.w Obj3B_Init ; 0 offsetTableEntry.w Obj3B_Main ; 2 ; =========================================================================== ; loc_15CDA: Obj3B_Init: addq.b #2,routine(a0) move.l #Obj3B_MapUnc_15D2E,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_GHZ_Purple_Rock,3,0),art_tile(a0) bsr.w Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$13,width_pixels(a0) move.b #4,priority(a0) ; loc_15D02: Obj3B_Main: move.w #$1B,d1 move.w #$10,d2 move.w #$10,d3 move.w x_pos(a0),d4 bsr.w SolidObject move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w DeleteObject bra.w DisplaySprite ; =========================================================================== ; ------------------------------------------------------------------------------- ; Unused sprite mappings ; ------------------------------------------------------------------------------- Obj3B_MapUnc_15D2E: BINCLUDE "mappings/sprite/obj3B.bin" if ~~removeJmpTos align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 3C - Breakable wall (leftover from S1) (mostly unused) ; ---------------------------------------------------------------------------- ; Sprite_15D44: Obj3C: moveq #0,d0 move.b routine(a0),d0 move.w Obj3C_Index(pc,d0.w),d1 jsr Obj3C_Index(pc,d1.w) bra.w MarkObjGone ; =========================================================================== ; off_15D56: Obj3C_Index: offsetTable offsetTableEntry.w Obj3C_Init ; 0 offsetTableEntry.w Obj3C_Main ; 2 offsetTableEntry.w Obj3C_Fragment ; 4 ; =========================================================================== ; loc_15D5C: Obj3C_Init: addq.b #2,routine(a0) move.l #Obj3C_MapUnc_15ECC,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_BreakWall,2,0),art_tile(a0) bsr.w Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #4,priority(a0) move.b subtype(a0),mapping_frame(a0) ; loc_15D8A: Obj3C_Main: move.w (MainCharacter+x_vel).w,objoff_30(a0) move.w #$1B,d1 move.w #$20,d2 move.w #$20,d3 move.w x_pos(a0),d4 bsr.w SolidObject btst #5,status(a0) bne.s + - rts ; =========================================================================== + lea (MainCharacter).w,a1 ; a1=character cmpi.b #2,anim(a1) bne.s - ; rts mvabs.w objoff_30(a0),d0 cmpi.w #$480,d0 blo.s - ; rts move.w objoff_30(a0),x_vel(a1) addq.w #4,x_pos(a1) lea (Obj3C_FragmentSpeeds_LeftToRight).l,a4 move.w x_pos(a0),d0 cmp.w x_pos(a1),d0 blo.s + subi_.w #8,x_pos(a1) lea (Obj3C_FragmentSpeeds_RightToLeft).l,a4 + move.w x_vel(a1),inertia(a1) bclr #5,status(a0) bclr #5,status(a1) bsr.s BreakObjectToPieces ; loc_15E02: Obj3C_Fragment: bsr.w ObjectMove addi.w #$70,y_vel(a0) tst.b render_flags(a0) bpl.w DeleteObject bra.w DisplaySprite ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_15E18: BreakObjectToPieces: ; splits up one object into its current mapping frame pieces moveq #0,d0 move.b mapping_frame(a0),d0 add.w d0,d0 movea.l mappings(a0),a3 adda.w (a3,d0.w),a3 ; put address of appropriate frame to a3 move.w (a3)+,d1 ; amount of pieces the frame consists of subq.w #1,d1 bset #5,render_flags(a0) _move.b id(a0),d4 move.b render_flags(a0),d5 movea.l a0,a1 bra.s BreakObjectToPieces_InitObject ; =========================================================================== ; loc_15E3E: BreakObjectToPieces_Loop: bsr.w SingleObjLoad2 bne.s loc_15E82 addq.w #8,a3 ; next mapping piece ; loc_15E46: BreakObjectToPieces_InitObject: move.b #4,routine(a1) _move.b d4,id(a1) ; load object with ID of parent object and routine 4 move.l a3,mappings(a1) move.b d5,render_flags(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w art_tile(a0),art_tile(a1) move.b priority(a0),priority(a1) move.b width_pixels(a0),width_pixels(a1) move.w (a4)+,x_vel(a1) move.w (a4)+,y_vel(a1) dbf d1,BreakObjectToPieces_Loop loc_15E82: move.w #SndID_SlowSmash,d0 jmp (PlaySound).l ; End of function BreakObjectToPieces ; =========================================================================== ; word_15E8C: Obj3C_FragmentSpeeds_LeftToRight: ; x_vel,y_vel dc.w $400,-$500 ; 0 dc.w $600,-$100 ; 2 dc.w $600, $100 ; 4 dc.w $400, $500 ; 6 dc.w $600,-$600 ; 8 dc.w $800,-$200 ; 10 dc.w $800, $200 ; 12 dc.w $600, $600 ; 14 ; word_15EAC: Obj3C_FragmentSpeeds_RightToLeft: dc.w -$600,-$600 ; 0 dc.w -$800,-$200 ; 2 dc.w -$800, $200 ; 4 dc.w -$600, $600 ; 6 dc.w -$400,-$500 ; 8 dc.w -$600,-$100 ; 10 dc.w -$600, $100 ; 12 dc.w -$400, $500 ; 14 ; ------------------------------------------------------------------------------- ; Unused sprite mappings ; ------------------------------------------------------------------------------- Obj3C_MapUnc_15ECC: BINCLUDE "mappings/sprite/obj3C.bin" ; =========================================================================== bra.w ObjNull ; ------------------------------------------------------------------------------- ; This runs the code of all the objects that are in Object_RAM ; ------------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_15F9C: ObjectsLoad: RunObjects: tst.b (Teleport_flag).w bne.s RunObjects_End ; rts lea (Object_RAM).w,a0 ; a0=object moveq #(Dynamic_Object_RAM_End-Object_RAM)/object_size-1,d7 ; run the first $80 objects out of levels moveq #0,d0 cmpi.b #GameModeID_Demo,(Game_Mode).w ; demo mode? beq.s + ; if in a level in a demo, branch cmpi.b #GameModeID_Level,(Game_Mode).w ; regular level mode? bne.s RunObject ; if not in a level, branch to RunObject + move.w #(Object_RAM_End-Object_RAM)/object_size-1,d7 ; run the first $90 objects in levels tst.w (Two_player_mode).w bne.s RunObject ; if in 2 player competition mode, branch to RunObject cmpi.b #6,(MainCharacter+routine).w bhs.s RunObjectsWhenPlayerIsDead ; if dead, branch ; continue straight to RunObject ; --------------------------------------------------------------------------- ; ------------------------------------------------------------------------------- ; This is THE place where each individual object's code gets called from ; ------------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_15FCC: RunObject: move.b id(a0),d0 ; get the object's ID beq.s RunNextObject ; if it's obj00, skip it add.w d0,d0 add.w d0,d0 ; d0 = object ID * 4 movea.l Obj_Index-4(pc,d0.w),a1 ; load the address of the object's code jsr (a1) ; dynamic call! to one of the the entries in Obj_Index moveq #0,d0 ; loc_15FDC: RunNextObject: lea next_object(a0),a0 ; load 0bj address dbf d7,RunObject ; return_15FE4: RunObjects_End: rts ; --------------------------------------------------------------------------- ; this skips certain objects to make enemies and things pause when Sonic dies ; loc_15FE6: RunObjectsWhenPlayerIsDead: moveq #(Reserved_Object_RAM_End-Reserved_Object_RAM)/object_size-1,d7 bsr.s RunObject ; run the first $10 objects normally moveq #(Dynamic_Object_RAM_End-Dynamic_Object_RAM)/object_size-1,d7 bsr.s RunObjectDisplayOnly ; all objects in this range are paused moveq #(LevelOnly_Object_RAM_End-LevelOnly_Object_RAM)/object_size-1,d7 bra.s RunObject ; run the last $10 objects normally ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_15FF2: RunObjectDisplayOnly: moveq #0,d0 move.b id(a0),d0 ; get the object's ID beq.s + ; if it's obj00, skip it tst.b render_flags(a0) ; should we render it? bpl.s + ; if not, skip it bsr.w DisplaySprite + lea next_object(a0),a0 ; load 0bj address dbf d7,RunObjectDisplayOnly rts ; End of function RunObjectDisplayOnly ; =========================================================================== ; --------------------------------------------------------------------------- ; OBJECT POINTER ARRAY ; object pointers ; sprite pointers ; object list ; sprite list ; ; This array contains the pointers to all the objects used in the game. ; --------------------------------------------------------------------------- Obj_Index: ; ObjPtrs: ; loc_1600C: ObjPtr_Sonic: dc.l Obj01 ; Sonic ObjPtr_Tails: dc.l Obj02 ; Tails ObjPtr_PlaneSwitcher: dc.l Obj03 ; Collision plane/layer switcher ObjPtr_WaterSurface: dc.l Obj04 ; Surface of the water ObjPtr_TailsTails: dc.l Obj05 ; Tails' tails ObjPtr_Spiral: dc.l Obj06 ; Rotating cylinder in MTZ, twisting spiral pathway in EHZ ObjPtr_Oil: dc.l Obj07 ; Oil in OOZ ObjPtr_SpindashDust: ObjPtr_Splash: dc.l Obj08 ; Water splash in Aquatic Ruin Zone, Spindash dust ObjPtr_SonicSS: dc.l Obj09 ; Sonic in Special Stage ObjPtr_SmallBubbles: dc.l Obj0A ; Small bubbles from Sonic's face while underwater ObjPtr_TippingFloor: dc.l Obj0B ; Section of pipe that tips you off from CPZ dc.l Obj0C ; Small floating platform (unused) ObjPtr_Signpost: dc.l Obj0D ; End of level signpost ObjPtr_IntroStars: dc.l Obj0E ; Flashing stars from intro ObjPtr_TitleMenu: dc.l Obj0F ; Title screen menu ObjPtr_TailsSS: dc.l Obj10 ; Tails in Special Stage ObjPtr_Bridge: dc.l Obj11 ; Bridge in Emerald Hill Zone and Hidden Palace Zone ObjPtr_HPZEmerald: dc.l Obj12 ; Emerald from Hidden Palace Zone (unused) ObjPtr_HPZWaterfall: dc.l Obj13 ; Waterfall in Hidden Palace Zone (unused) ObjPtr_Seesaw: dc.l Obj14 ; Seesaw from Hill Top Zone ObjPtr_SwingingPlatform:dc.l Obj15 ; Swinging platform from Aquatic Ruin Zone ObjPtr_HTZLift: dc.l Obj16 ; Diagonally moving lift from HTZ dc.l Obj17 ; GHZ rotating log helix spikes (from Sonic 1, unused) ObjPtr_ARZPlatform: ObjPtr_EHZPlatform: dc.l Obj18 ; Stationary floating platform from ARZ and EHZ ObjPtr_CPZPlatform: ObjPtr_OOZMovingPform: ObjPtr_WFZPlatform: dc.l Obj19 ; Platform from CPZ, OOZ and WFZ ObjPtr_HPZCollapsPform: dc.l Obj1A ; Collapsing platform from HPZ (and GHZ) ObjPtr_SpeedBooster: dc.l Obj1B ; Speed booster from from CPZ ObjPtr_Scenery: ObjPtr_BridgeStake: ObjPtr_FallingOil: dc.l Obj1C ; Bridge stake in Emerald Hill Zone and Hill Top Zone, falling oil in Oil Ocean Zone ObjPtr_BlueBalls: dc.l Obj1D ; Blue balls in CPZ (jumping droplets hazard) ObjPtr_CPZSpinTube: dc.l Obj1E ; Spin tube from CPZ ObjPtr_CollapsPform: dc.l Obj1F ; Collapsing platform from ARZ, MCZ and OOZ (and MZ, SLZ and SBZ) ObjPtr_LavaBubble: dc.l Obj20 ; Lava bubble from Hill Top Zone (boss weapon) ObjPtr_HUD: dc.l Obj21 ; Score/Rings/Time display (HUD) ObjPtr_ArrowShooter: dc.l Obj22 ; Arrow shooter from ARZ ObjPtr_FallingPillar: dc.l Obj23 ; Pillar that drops its lower part from ARZ ObjPtr_ARZBubbles: dc.l Obj24 ; Bubbles in Aquatic Ruin Zone ObjPtr_Ring: dc.l Obj25 ; A ring ObjPtr_Monitor: dc.l Obj26 ; Monitor ObjPtr_Explosion: dc.l Obj27 ; An explosion, giving off an animal and 100 points ObjPtr_Animal: dc.l Obj28 ; Animal and the 100 points from a badnik ObjPtr_Points: dc.l Obj29 ; "100 points" text ObjPtr_Stomper: dc.l Obj2A ; Stomper from MCZ ObjPtr_RisingPillar: dc.l Obj2B ; Rising pillar from ARZ ObjPtr_LeavesGenerator: dc.l Obj2C ; Sprite that makes leaves fly off when you hit it from ARZ ObjPtr_Barrier: dc.l Obj2D ; One way barrier from CPZ and DEZ ObjPtr_MonitorContents: dc.l Obj2E ; Monitor contents (code for power-up behavior and rising image) ObjPtr_SmashableGround: dc.l Obj2F ; Smashable ground in Hill Top Zone ObjPtr_RisingLava: dc.l Obj30 ; Large rising lava during earthquake in HTZ ObjPtr_LavaMarker: dc.l Obj31 ; Lava collision marker ObjPtr_BreakableBlock: ObjPtr_BreakableRock: dc.l Obj32 ; Breakable block/rock from CPZ and HTZ ObjPtr_OOZPoppingPform: dc.l Obj33 ; Green platform from OOZ ObjPtr_TitleCard: dc.l Obj34 ; level title card (screen with red, yellow, and blue) ObjPtr_InvStars: dc.l Obj35 ; Invincibility Stars ObjPtr_Spikes: dc.l Obj36 ; Vertical spikes ObjPtr_LostRings: dc.l Obj37 ; Scattering rings (generated when Sonic is hurt and has rings) ObjPtr_Shield: dc.l Obj38 ; Shield ObjPtr_GameOver: ObjPtr_TimeOver: dc.l Obj39 ; Game/Time Over text ObjPtr_Results: dc.l Obj3A ; End of level results screen dc.l Obj3B ; Purple rock (from Sonic 1, unused) dc.l Obj3C ; Breakable wall (leftover from S1) (mostly unused) ObjPtr_OOZLauncher: dc.l Obj3D ; Block thingy in OOZ that launches you into the round ball things ObjPtr_EggPrison: dc.l Obj3E ; Egg prison ObjPtr_Fan: dc.l Obj3F ; Fan from OOZ ObjPtr_Springboard: dc.l Obj40 ; Pressure spring from CPZ, ARZ, and MCZ (the red "diving board" springboard) ObjPtr_Spring: dc.l Obj41 ; Spring ObjPtr_SteamSpring: dc.l Obj42 ; Steam Spring from MTZ ObjPtr_SlidingSpike: dc.l Obj43 ; Sliding spike obstacle thing from OOZ ObjPtr_RoundBumper: dc.l Obj44 ; Round bumper from Casino Night Zone ObjPtr_OOZSpring: dc.l Obj45 ; Pressure spring from OOZ ObjPtr_OOZBall: dc.l Obj46 ; Ball from OOZ (unused, beta leftover) ObjPtr_Button: dc.l Obj47 ; Button ObjPtr_LauncherBall: dc.l Obj48 ; Round ball thing from OOZ that fires you off in a different direction ObjPtr_EHZWaterfall: dc.l Obj49 ; Waterfall from EHZ ObjPtr_Octus: dc.l Obj4A ; Octus (octopus badnik) from OOZ ObjPtr_Buzzer: dc.l Obj4B ; Buzzer (Buzz bomber) from EHZ dc.l ObjNull ; Obj4C dc.l ObjNull ; Obj4D dc.l ObjNull ; Obj4E dc.l ObjNull ; Obj4F ObjPtr_Aquis: dc.l Obj50 ; Aquis (seahorse badnik) from OOZ ObjPtr_CNZBoss: dc.l Obj51 ; CNZ boss ObjPtr_HTZBoss: dc.l Obj52 ; HTZ boss ObjPtr_MTZBossOrb: dc.l Obj53 ; Shield orbs that surround MTZ boss ObjPtr_MTZBoss: dc.l Obj54 ; MTZ boss ObjPtr_OOZBoss: dc.l Obj55 ; OOZ boss ObjPtr_EHZBoss: dc.l Obj56 ; EHZ boss ObjPtr_MCZBoss: dc.l Obj57 ; MCZ boss ObjPtr_BossExplosion: dc.l Obj58 ; Boss explosion ObjPtr_SSEmerald: dc.l Obj59 ; Emerald from Special Stage ObjPtr_SSMessage: dc.l Obj5A ; Messages/checkpoint from Special Stage ObjPtr_SSRingSpill: dc.l Obj5B ; Ring spray/spill in Special Stage ObjPtr_Masher: dc.l Obj5C ; Masher (jumping piranha fish badnik) from EHZ ObjPtr_CPZBoss: dc.l Obj5D ; CPZ boss ObjPtr_SSHUD: dc.l Obj5E ; HUD from Special Stage ObjPtr_StartBanner: ObjPtr_EndingController:dc.l Obj5F ; Start banner/"Ending controller" from Special Stage ObjPtr_SSRing: dc.l Obj60 ; Rings from Special Stage ObjPtr_SSBomb: dc.l Obj61 ; Bombs from Special Stage dc.l ObjNull ; Obj62 ObjPtr_SSShadow: dc.l Obj63 ; Character shadow from Special Stage ObjPtr_MTZTwinStompers: dc.l Obj64 ; Twin stompers from MTZ ObjPtr_MTZLongPlatform: dc.l Obj65 ; Long moving platform from MTZ ObjPtr_MTZSpringWall: dc.l Obj66 ; Yellow spring walls from MTZ ObjPtr_MTZSpinTube: dc.l Obj67 ; Spin tube from MTZ ObjPtr_SpikyBlock: dc.l Obj68 ; Block with a spike that comes out of each side sequentially from MTZ ObjPtr_Nut: dc.l Obj69 ; Nut from MTZ ObjPtr_MCZRotPforms: ObjPtr_MTZMovingPforms: dc.l Obj6A ; Platform that moves when you walk off of it, from MTZ ObjPtr_MTZPlatform: ObjPtr_CPZSquarePform: dc.l Obj6B ; Immobile platform from MTZ ObjPtr_Conveyor: dc.l Obj6C ; Small platform on pulleys (like at the start of MTZ2) ObjPtr_FloorSpike: dc.l Obj6D ; Floor spike from MTZ ObjPtr_LargeRotPform: dc.l Obj6E ; Platform moving in a circle (like at the start of MTZ3) ObjPtr_SSResults: dc.l Obj6F ; End of special stage results screen ObjPtr_Cog: dc.l Obj70 ; Giant rotating cog from MTZ ObjPtr_MTZLavaBubble: ObjPtr_HPZBridgeStake: ObjPtr_PulsingOrb: dc.l Obj71 ; Bridge stake and pulsing orb from Hidden Palace Zone ObjPtr_CNZConveyorBelt: dc.l Obj72 ; Conveyor belt from CNZ ObjPtr_RotatingRings: dc.l Obj73 ; Solid rotating ring thing from Mystic Cave Zone (mostly unused) ObjPtr_InvisibleBlock: dc.l Obj74 ; Invisible solid block ObjPtr_MCZBrick: dc.l Obj75 ; Brick from MCZ ObjPtr_SlidingSpikes: dc.l Obj76 ; Spike block that slides out of the wall from MCZ ObjPtr_MCZBridge: dc.l Obj77 ; Bridge from MCZ ObjPtr_CPZStaircase: dc.l Obj78 ; Stairs from CPZ that move down to open the way ObjPtr_Starpost: dc.l Obj79 ; Star pole / starpost / checkpoint ObjPtr_SidewaysPform: dc.l Obj7A ; Platform that moves back and fourth on top of water in CPZ ObjPtr_PipeExitSpring: dc.l Obj7B ; Warp pipe exit spring from CPZ ObjPtr_CPZPylon: dc.l Obj7C ; Big pylon in foreground of CPZ dc.l Obj7D ; Points that can be gotten at the end of an act (unused leftover from S1) ObjPtr_SuperSonicStars: dc.l Obj7E ; Super Sonic's stars ObjPtr_VineSwitch: dc.l Obj7F ; Vine switch that you hang off in MCZ ObjPtr_MovingVine: dc.l Obj80 ; Vine that you hang off and it moves down from MCZ ObjPtr_MCZDrawbridge: dc.l Obj81 ; Long invisible vertical barrier ObjPtr_SwingingPform: dc.l Obj82 ; Platform that is usually swinging, from ARZ ObjPtr_ARZRotPforms: dc.l Obj83 ; 3 adjoined platforms from ARZ that rotate in a circle ObjPtr_ForcedSpin: ObjPtr_PinballMode: dc.l Obj84 ; Pinball mode enable/disable (CNZ) ObjPtr_LauncherSpring: dc.l Obj85 ; Spring from CNZ that you hold jump on to pull back further ObjPtr_Flipper: dc.l Obj86 ; Flipper from CNZ ObjPtr_SSNumberOfRings: dc.l Obj87 ; Number of rings in Special Stage ObjPtr_SSTailsTails: dc.l Obj88 ; Tails' tails in Special Stage ObjPtr_ARZBoss: dc.l Obj89 ; ARZ boss dc.l Obj8A ; Sonic Team Presents/Credits (seemingly unused leftover from S1) ObjPtr_WFZPalSwitcher: dc.l Obj8B ; Cycling palette switcher from Wing Fortress Zone ObjPtr_Whisp: dc.l Obj8C ; Whisp (blowfly badnik) from ARZ ObjPtr_GrounderInWall: dc.l Obj8D ; Grounder in wall, from ARZ ObjPtr_GrounderInWall2: dc.l Obj8D ; Obj8E = Obj8D ObjPtr_GrounderWall: dc.l Obj8F ; Wall behind which Grounder hides, from ARZ ObjPtr_GrounderRocks: dc.l Obj90 ; Rocks thrown by Grounder behind wall, from ARZ ObjPtr_ChopChop: dc.l Obj91 ; Chop Chop (piranha/shark badnik) from ARZ ObjPtr_Spiker: dc.l Obj92 ; Spiker (drill badnik) from HTZ ObjPtr_SpikerDrill: dc.l Obj93 ; Drill thrown by Spiker from HTZ ObjPtr_Rexon: dc.l Obj94 ; Rexon (lava snake badnik), from HTZ ObjPtr_Sol: dc.l Obj95 ; Sol (fireball-throwing orbit badnik) from HTZ ObjPtr_Rexon2: dc.l Obj94 ; Obj96 = Obj94 ObjPtr_RexonHead: dc.l Obj97 ; Rexon's head, from HTZ ObjPtr_Projectile: dc.l Obj98 ; Projectile with optional gravity (EHZ coconut, CPZ spiny, etc.) ObjPtr_Nebula: dc.l Obj99 ; Nebula (bomber badnik) from SCZ ObjPtr_Turtloid: dc.l Obj9A ; Turtloid (turtle badnik) from Sky Chase Zone ObjPtr_TurtloidRider: dc.l Obj9B ; Turtloid rider from Sky Chase Zone ObjPtr_BalkiryJet: dc.l Obj9C ; Balkiry's jet from Sky Chase Zone ObjPtr_Coconuts: dc.l Obj9D ; Coconuts (monkey badnik) from EHZ ObjPtr_Crawlton: dc.l Obj9E ; Crawlton (snake badnik) from MCZ ObjPtr_Shellcracker: dc.l Obj9F ; Shellcraker (crab badnik) from MTZ ObjPtr_ShellcrackerClaw:dc.l ObjA0 ; Shellcracker's claw from MTZ ObjPtr_Slicer: dc.l ObjA1 ; Slicer (praying mantis dude) from MTZ ObjPtr_SlicerPincers: dc.l ObjA2 ; Slicer's pincers from MTZ ObjPtr_Flasher: dc.l ObjA3 ; Flasher (firefly/glowbug badnik) from MCZ ObjPtr_Asteron: dc.l ObjA4 ; Asteron (exploding starfish badnik) from MTZ ObjPtr_Spiny: dc.l ObjA5 ; Spiny (crawling badnik) from CPZ ObjPtr_SpinyOnWall: dc.l ObjA6 ; Spiny (on wall) from CPZ ObjPtr_Grabber: dc.l ObjA7 ; Grabber (spider badnik) from CPZ ObjPtr_GrabberLegs: dc.l ObjA8 ; Grabber's legs from CPZ ObjPtr_GrabberBox: dc.l ObjA9 ; The little hanger box thing a Grabber's string comes out of ObjPtr_GrabberString: dc.l ObjAA ; The thin white string a Grabber hangs from dc.l ObjAB ; Unknown (maybe unused?) ObjPtr_Balkiry: dc.l ObjAC ; Balkiry (jet badnik) from SCZ ObjPtr_CluckerBase: dc.l ObjAD ; Clucker's base from WFZ ObjPtr_Clucker: dc.l ObjAE ; Clucker (chicken badnik) from WFZ ObjPtr_MechaSonic: dc.l ObjAF ; Mecha Sonic / Silver Sonic from DEZ ObjPtr_SonicOnSegaScr: dc.l ObjB0 ; Sonic on the Sega screen ObjPtr_SegaHideTM: dc.l ObjB1 ; Object that hides TM symbol on JP region ObjPtr_Tornado: dc.l ObjB2 ; The Tornado (Tails' plane) ObjPtr_Cloud: dc.l ObjB3 ; Clouds (placeable object) from SCZ ObjPtr_VPropeller: dc.l ObjB4 ; Vertical propeller from WFZ ObjPtr_HPropeller: dc.l ObjB5 ; Horizontal propeller from WFZ ObjPtr_TiltingPlatform: dc.l ObjB6 ; Tilting platform from WFZ ObjPtr_VerticalLaser: dc.l ObjB7 ; Unused huge vertical laser from WFZ ObjPtr_WallTurret: dc.l ObjB8 ; Wall turret from WFZ ObjPtr_Laser: dc.l ObjB9 ; Laser from WFZ that shoots down the Tornado ObjPtr_WFZWheel: dc.l ObjBA ; Wheel from WFZ dc.l ObjBB ; Unknown ObjPtr_WFZShipFire: dc.l ObjBC ; Fire coming out of Robotnik's ship in WFZ ObjPtr_SmallMetalPform: dc.l ObjBD ; Ascending/descending metal platforms from WFZ ObjPtr_LateralCannon: dc.l ObjBE ; Lateral cannon (temporary platform that pops in/out) from WFZ ObjPtr_WFZStick: dc.l ObjBF ; Rotaty-stick badnik from WFZ ObjPtr_SpeedLauncher: dc.l ObjC0 ; Speed launcher from WFZ ObjPtr_BreakablePlating:dc.l ObjC1 ; Breakable plating from WFZ / what sonic hangs onto on the back of Robotnic's getaway ship ObjPtr_Rivet: dc.l ObjC2 ; Rivet thing you bust to get into ship at the end of WFZ ObjPtr_TornadoSmoke: dc.l ObjC3 ; Plane's smoke from WFZ ObjPtr_TornadoSmoke2: dc.l ObjC3 ; ObjC4 = ObjC3 ObjPtr_WFZBoss: dc.l ObjC5 ; WFZ boss ObjPtr_Eggman: dc.l ObjC6 ; Eggman ObjPtr_Eggrobo: dc.l ObjC7 ; Eggrobo (final boss) from Death Egg ObjPtr_Crawl: dc.l ObjC8 ; Crawl (shield badnik) from CNZ ObjPtr_TtlScrPalChanger:dc.l ObjC9 ; "Palette changing handler" from title screen ObjPtr_CutScene: dc.l ObjCA ; Cut scene at end of game ObjPtr_EndingSeqClouds: dc.l ObjCB ; Background clouds from ending sequence ObjPtr_EndingSeqTrigger:dc.l ObjCC ; Trigger for rescue plane and birds from ending sequence ObjPtr_EndingSeqBird: dc.l ObjCD ; Birds from ending sequence ObjPtr_EndingSeqSonic: ObjPtr_EndingSeqTails: dc.l ObjCE ; Sonic and Tails jumping off the plane from ending sequence ObjPtr_TornadoHelixes: dc.l ObjCF ;"Plane's helixes" from ending sequence dc.l ObjNull ; ObjD0 dc.l ObjNull ; ObjD1 ObjPtr_CNZRectBlocks: dc.l ObjD2 ; Flashing blocks that appear and disappear in a rectangular shape that you can walk across, from CNZ ObjPtr_BombPrize: dc.l ObjD3 ; Bomb prize from CNZ ObjPtr_CNZBigBlock: dc.l ObjD4 ; Big block from CNZ that moves back and fourth ObjPtr_Elevator: dc.l ObjD5 ; Elevator from CNZ ObjPtr_PointPokey: dc.l ObjD6 ; Pokey that gives out points from CNZ ObjPtr_Bumper: dc.l ObjD7 ; Bumper from Casino Night Zone ObjPtr_BonusBlock: dc.l ObjD8 ; Block thingy from CNZ that disappears after 3 hits ObjPtr_Grab: dc.l ObjD9 ; Invisible sprite that you can hang on to, like the blocks in WFZ ObjPtr_ContinueText: ObjPtr_ContinueIcons: dc.l ObjDA ; Continue text ObjPtr_ContinueChars: dc.l ObjDB ; Sonic lying down or Tails nagging (continue screen) ObjPtr_RingPrize: dc.l ObjDC ; Ring prize from Casino Night Zone ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 4C, 4D, 4E, 4F, 62, D0, and D1 ; Object removed from the game. All it does is deallocate its array. ; ---------------------------------------------------------------------------- ObjNull: ;; bra.w DeleteObject ; --------------------------------------------------------------------------- ; Subroutine to make an object move and fall downward increasingly fast ; This moves the object horizontally and vertically ; and also applies gravity to its speed ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_16380: ObjectFall: ObjectMoveAndFall: move.l x_pos(a0),d2 ; load x position move.l y_pos(a0),d3 ; load y position move.w x_vel(a0),d0 ; load x speed ext.l d0 asl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position add.l d0,d2 ; add x speed to x position ; note this affects the subpixel position x_sub(a0) = 2+x_pos(a0) move.w y_vel(a0),d0 ; load y speed addi.w #$38,y_vel(a0) ; increase vertical speed (apply gravity) ext.l d0 asl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position add.l d0,d3 ; add old y speed to y position ; note this affects the subpixel position y_sub(a0) = 2+y_pos(a0) move.l d2,x_pos(a0) ; store new x position move.l d3,y_pos(a0) ; store new y position rts ; End of function ObjectMoveAndFall ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; --------------------------------------------------------------------------- ; Subroutine translating object speed to update object position ; This moves the object horizontally and vertically ; but does not apply gravity to it ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_163AC: SpeedToPos: ObjectMove: move.l x_pos(a0),d2 ; load x position move.l y_pos(a0),d3 ; load y position move.w x_vel(a0),d0 ; load horizontal speed ext.l d0 asl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position add.l d0,d2 ; add to x-axis position ; note this affects the subpixel position x_sub(a0) = 2+x_pos(a0) move.w y_vel(a0),d0 ; load vertical speed ext.l d0 asl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position add.l d0,d3 ; add to y-axis position ; note this affects the subpixel position y_sub(a0) = 2+y_pos(a0) move.l d2,x_pos(a0) ; update x-axis position move.l d3,y_pos(a0) ; update y-axis position rts ; End of function ObjectMove ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; --------------------------------------------------------------------------- ; Routines to mark an enemy/monitor/ring/platform as destroyed ; --------------------------------------------------------------------------- ; =========================================================================== ; input: a0 = the object ; loc_163D2: MarkObjGone: tst.w (Two_player_mode).w ; is it two player mode? beq.s + ; if not, branch bra.w DisplaySprite + move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$80+320+$40+$80,d0 ; This gives an object $80 pixels of room offscreen before being unloaded (the $40 is there to round up 320 to a multiple of $80) bhi.w + bra.w DisplaySprite + lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s + bclr #7,2(a2,d0.w) + bra.w DeleteObject ; =========================================================================== ; input: d0 = the object's x position ; loc_1640A: MarkObjGone2: tst.w (Two_player_mode).w beq.s + bra.w DisplaySprite + andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$80+320+$40+$80,d0 ; This gives an object $80 pixels of room offscreen before being unloaded (the $40 is there to round up 320 to a multiple of $80) bhi.w + bra.w DisplaySprite + lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s + bclr #7,2(a2,d0.w) + bra.w DeleteObject ; =========================================================================== ; input: a0 = the object ; does nothing instead of calling DisplaySprite in the case of no deletion ; loc_1643E: MarkObjGone3: tst.w (Two_player_mode).w beq.s + rts + move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$80+320+$40+$80,d0 ; This gives an object $80 pixels of room offscreen before being unloaded (the $40 is there to round up 320 to a multiple of $80) bhi.w + rts + lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s + bclr #7,2(a2,d0.w) + bra.w DeleteObject ; =========================================================================== ; input: a0 = the object ; loc_16472: MarkObjGone_P1: tst.w (Two_player_mode).w bne.s MarkObjGone_P2 move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$80+320+$40+$80,d0 ; This gives an object $80 pixels of room offscreen before being unloaded (the $40 is there to round up 320 to a multiple of $80) bhi.w + bra.w DisplaySprite + lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s + bclr #7,2(a2,d0.w) + bra.w DeleteObject ; --------------------------------------------------------------------------- ; input: a0 = the object ; loc_164A6: MarkObjGone_P2: move.w x_pos(a0),d0 andi.w #$FF00,d0 move.w d0,d1 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$300,d0 bhi.w + bra.w DisplaySprite + sub.w (Camera_X_pos_coarse_P2).w,d1 cmpi.w #$300,d1 bhi.w + bra.w DisplaySprite + lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s + bclr #7,2(a2,d0.w) + bra.w DeleteObject ; useless branch... ; --------------------------------------------------------------------------- ; Subroutine to delete an object ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; freeObject: DeleteObject: movea.l a0,a1 ; sub_164E8: DeleteObject2: moveq #0,d1 moveq #bytesToLcnt(next_object),d0 ; we want to clear up to the next object ; delete the object by setting all of its bytes to 0 - move.l d1,(a1)+ dbf d0,- if object_size&3 move.w d1,(a1)+ endif rts ; End of function DeleteObject2 ; --------------------------------------------------------------------------- ; Subroutine to display a sprite/object, when a0 is the object RAM ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_164F4: DisplaySprite: lea (Sprite_Table_Input).w,a1 move.w priority(a0),d0 lsr.w #1,d0 andi.w #$380,d0 adda.w d0,a1 cmpi.w #$7E,(a1) bhs.s return_16510 addq.w #2,(a1) adda.w (a1),a1 move.w a0,(a1) return_16510: rts ; End of function DisplaySprite ; --------------------------------------------------------------------------- ; Subroutine to display a sprite/object, when a1 is the object RAM ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_16512: DisplaySprite2: lea (Sprite_Table_Input).w,a2 move.w priority(a1),d0 lsr.w #1,d0 andi.w #$380,d0 adda.w d0,a2 cmpi.w #$7E,(a2) bhs.s return_1652E addq.w #2,(a2) adda.w (a2),a2 move.w a1,(a2) return_1652E: rts ; End of function DisplaySprite2 ; --------------------------------------------------------------------------- ; Subroutine to display a sprite/object, when a0 is the object RAM ; and d0 is already (priority/2)&$380 ; --------------------------------------------------------------------------- ; loc_16530: DisplaySprite3: lea (Sprite_Table_Input).w,a1 adda.w d0,a1 cmpi.w #$7E,(a1) bhs.s return_16542 addq.w #2,(a1) adda.w (a1),a1 move.w a0,(a1) return_16542: rts ; --------------------------------------------------------------------------- ; Subroutine to animate a sprite using an animation script ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_16544: AnimateSprite: moveq #0,d0 move.b anim(a0),d0 ; move animation number to d0 cmp.b next_anim(a0),d0 ; is animation set to change? beq.s Anim_Run ; if not, branch move.b d0,next_anim(a0) ; set next anim to current current move.b #0,anim_frame(a0) ; reset animation move.b #0,anim_frame_duration(a0) ; reset frame duration ; loc_16560: Anim_Run: subq.b #1,anim_frame_duration(a0) ; subtract 1 from frame duration bpl.s Anim_Wait ; if time remains, branch add.w d0,d0 adda.w (a1,d0.w),a1 ; calculate address of appropriate animation script move.b (a1),anim_frame_duration(a0) ; load frame duration moveq #0,d1 move.b anim_frame(a0),d1 ; load current frame number move.b 1(a1,d1.w),d0 ; read sprite number from script bmi.s Anim_End_FF ; if animation is complete, branch ; loc_1657C: Anim_Next: andi.b #$7F,d0 ; clear sign bit move.b d0,mapping_frame(a0) ; load sprite number move.b status(a0),d1 ;* match the orientaion dictated by the object andi.b #3,d1 ;* with the orientation used by the object engine andi.b #$FC,render_flags(a0) ;* or.b d1,render_flags(a0) ;* addq.b #1,anim_frame(a0) ; next frame number ; return_1659A: Anim_Wait: rts ; =========================================================================== ; loc_1659C: Anim_End_FF: addq.b #1,d0 ; is the end flag = $FF ? bne.s Anim_End_FE ; if not, branch move.b #0,anim_frame(a0) ; restart the animation move.b 1(a1),d0 ; read sprite number bra.s Anim_Next ; =========================================================================== ; loc_165AC: Anim_End_FE: addq.b #1,d0 ; is the end flag = $FE ? bne.s Anim_End_FD ; if not, branch move.b 2(a1,d1.w),d0 ; read the next byte in the script sub.b d0,anim_frame(a0) ; jump back d0 bytes in the script sub.b d0,d1 move.b 1(a1,d1.w),d0 ; read sprite number bra.s Anim_Next ; =========================================================================== ; loc_165C0: Anim_End_FD: addq.b #1,d0 ; is the end flag = $FD ? bne.s Anim_End_FC ; if not, branch move.b 2(a1,d1.w),anim(a0) ; read next byte, run that animation rts ; =========================================================================== ; loc_165CC: Anim_End_FC: addq.b #1,d0 ; is the end flag = $FC ? bne.s Anim_End_FB ; if not, branch addq.b #2,routine(a0) ; jump to next routine move.b #0,anim_frame_duration(a0) addq.b #1,anim_frame(a0) rts ; =========================================================================== ; loc_165E0: Anim_End_FB: addq.b #1,d0 ; is the end flag = $FB ? bne.s Anim_End_FA ; if not, branch move.b #0,anim_frame(a0) ; reset animation clr.b routine_secondary(a0) ; reset 2nd routine counter rts ; =========================================================================== ; loc_165F0: Anim_End_FA: addq.b #1,d0 ; is the end flag = $FA ? bne.s Anim_End_F9 ; if not, branch addq.b #2,routine_secondary(a0) ; jump to next routine rts ; =========================================================================== ; loc_165FA: Anim_End_F9: addq.b #1,d0 ; is the end flag = $F9 ? bne.s Anim_End ; if not, branch addq.b #2,objoff_2A(a0) ; return_16602: Anim_End: rts ; End of function AnimateSprite ; --------------------------------------------------------------------------- ; Subroutine to convert mappings (etc) to proper Megadrive sprites ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_16604: BuildSprites: tst.w (Two_player_mode).w bne.w BuildSprites_2P lea (Sprite_Table).w,a2 moveq #0,d5 moveq #0,d4 tst.b (Level_started_flag).w beq.s + jsrto (BuildHUD).l, JmpTo_BuildHUD bsr.w BuildRings + lea (Sprite_Table_Input).w,a4 moveq #7,d7 ; 8 priority levels ; loc_16628: BuildSprites_LevelLoop: tst.w (a4) ; does this level have any objects? beq.w BuildSprites_NextLevel ; if not, check the next one moveq #2,d6 ; loc_16630: BuildSprites_ObjLoop: movea.w (a4,d6.w),a0 ; a0=object if gameRevision=0 ; the additional check prevents a crash triggered by placing an object in debug mode while dead ; unfortunately, the code it branches *to* causes a crash of its own tst.b id(a0) ; is this object slot occupied? beq.w BuildSprites_Unknown ; if not, branch tst.l mappings(a0) ; does this object have any mappings? beq.w BuildSprites_Unknown ; if not, branch else ; REV01 uses a better branch, but removed the useful check tst.b id(a0) ; is this object slot occupied? beq.w BuildSprites_NextObj ; if not, check next one endif andi.b #$7F,render_flags(a0) ; clear on-screen flag move.b render_flags(a0),d0 move.b d0,d4 btst #6,d0 ; is the multi-draw flag set? bne.w BuildSprites_MultiDraw ; if it is, branch andi.w #$C,d0 ; is this to be positioned by screen coordinates? beq.s BuildSprites_ScreenSpaceObj ; if it is, branch lea (Camera_X_pos_copy).w,a1 moveq #0,d0 move.b width_pixels(a0),d0 move.w x_pos(a0),d3 sub.w (a1),d3 move.w d3,d1 add.w d0,d1 ; is the object right edge to the left of the screen? bmi.w BuildSprites_NextObj ; if it is, branch move.w d3,d1 sub.w d0,d1 cmpi.w #320,d1 ; is the object left edge to the right of the screen? bge.w BuildSprites_NextObj ; if it is, branch addi.w #128,d3 btst #4,d4 ; is the accurate Y check flag set? beq.s BuildSprites_ApproxYCheck ; if not, branch moveq #0,d0 move.b y_radius(a0),d0 move.w y_pos(a0),d2 sub.w 4(a1),d2 move.w d2,d1 add.w d0,d1 bmi.s BuildSprites_NextObj ; if the object is above the screen move.w d2,d1 sub.w d0,d1 cmpi.w #224,d1 bge.s BuildSprites_NextObj ; if the object is below the screen addi.w #128,d2 bra.s BuildSprites_DrawSprite ; =========================================================================== ; loc_166A6: BuildSprites_ScreenSpaceObj: move.w y_pixel(a0),d2 move.w x_pixel(a0),d3 bra.s BuildSprites_DrawSprite ; =========================================================================== ; loc_166B0: BuildSprites_ApproxYCheck: move.w y_pos(a0),d2 sub.w 4(a1),d2 addi.w #128,d2 andi.w #$7FF,d2 cmpi.w #-32+128,d2 ; assume Y radius to be 32 pixels blo.s BuildSprites_NextObj cmpi.w #32+128+224,d2 bhs.s BuildSprites_NextObj ; loc_166CC: BuildSprites_DrawSprite: movea.l mappings(a0),a1 moveq #0,d1 btst #5,d4 ; is the static mappings flag set? bne.s + ; if it is, branch move.b mapping_frame(a0),d1 add.w d1,d1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 ; get number of pieces bmi.s ++ ; if there are 0 pieces, branch + bsr.w DrawSprite ; draw the sprite + ori.b #$80,render_flags(a0) ; set on-screen flag ; loc_166F2: BuildSprites_NextObj: addq.w #2,d6 ; load next object subq.w #2,(a4) ; decrement object count bne.w BuildSprites_ObjLoop ; if there are objects left, repeat ; loc_166FA: BuildSprites_NextLevel: lea $80(a4),a4 ; load next priority level dbf d7,BuildSprites_LevelLoop ; loop move.b d5,(Sprite_count).w cmpi.b #80,d5 ; was the sprite limit reached? beq.s + ; if it was, branch move.l #0,(a2) ; set link field to 0 rts + move.b #0,-5(a2) ; set link field to 0 rts ; =========================================================================== if gameRevision=0 BuildSprites_Unknown: ; in the Simon Wai beta, this was a simple BranchTo, but later builds have this mystery line move.w (1).w,d0 ; causes a crash on hardware because of the word operation at an odd address bra.s BuildSprites_NextObj endif ; loc_1671C: BuildSprites_MultiDraw: move.l a4,-(sp) lea (Camera_X_pos).w,a4 movea.w art_tile(a0),a3 movea.l mappings(a0),a5 moveq #0,d0 ; check if object is within X bounds move.b mainspr_width(a0),d0 ; load pixel width move.w x_pos(a0),d3 sub.w (a4),d3 move.w d3,d1 add.w d0,d1 bmi.w BuildSprites_MultiDraw_NextObj move.w d3,d1 sub.w d0,d1 cmpi.w #320,d1 bge.w BuildSprites_MultiDraw_NextObj addi.w #128,d3 ; check if object is within Y bounds btst #4,d4 beq.s + moveq #0,d0 move.b mainspr_height(a0),d0 ; load pixel height move.w y_pos(a0),d2 sub.w 4(a4),d2 move.w d2,d1 add.w d0,d1 bmi.w BuildSprites_MultiDraw_NextObj move.w d2,d1 sub.w d0,d1 cmpi.w #224,d1 bge.w BuildSprites_MultiDraw_NextObj addi.w #128,d2 bra.s ++ + move.w y_pos(a0),d2 sub.w 4(a4),d2 addi.w #128,d2 andi.w #$7FF,d2 cmpi.w #-32+128,d2 blo.s BuildSprites_MultiDraw_NextObj cmpi.w #32+128+224,d2 bhs.s BuildSprites_MultiDraw_NextObj + moveq #0,d1 move.b mainspr_mapframe(a0),d1 ; get current frame beq.s + add.w d1,d1 movea.l a5,a1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 bmi.s + move.w d4,-(sp) bsr.w ChkDrawSprite ; draw the sprite move.w (sp)+,d4 + ori.b #$80,render_flags(a0) ; set onscreen flag lea sub2_x_pos(a0),a6 moveq #0,d0 move.b mainspr_childsprites(a0),d0 ; get child sprite count subq.w #1,d0 ; if there are 0, go to next object bcs.s BuildSprites_MultiDraw_NextObj - swap d0 move.w (a6)+,d3 ; get X pos sub.w (a4),d3 addi.w #128,d3 move.w (a6)+,d2 ; get Y pos sub.w 4(a4),d2 addi.w #128,d2 andi.w #$7FF,d2 addq.w #1,a6 moveq #0,d1 move.b (a6)+,d1 ; get mapping frame add.w d1,d1 movea.l a5,a1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 bmi.s + move.w d4,-(sp) bsr.w ChkDrawSprite move.w (sp)+,d4 + swap d0 dbf d0,- ; repeat for number of child sprites ; loc_16804: BuildSprites_MultiDraw_NextObj: movea.l (sp)+,a4 bra.w BuildSprites_NextObj ; End of function BuildSprites ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_1680A: ChkDrawSprite: cmpi.b #80,d5 ; has the sprite limit been reached? blo.s DrawSprite_Cont ; if it hasn't, branch rts ; otherwise, return ; End of function ChkDrawSprite ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_16812: DrawSprite: movea.w art_tile(a0),a3 cmpi.b #80,d5 bhs.s DrawSprite_Done ; loc_1681C: DrawSprite_Cont: btst #0,d4 ; is the sprite to be X-flipped? bne.s DrawSprite_FlipX ; if it is, branch btst #1,d4 ; is the sprite to be Y-flipped? bne.w DrawSprite_FlipY ; if it is, branch ; loc__1682A: DrawSprite_Loop: move.b (a1)+,d0 ext.w d0 add.w d2,d0 move.w d0,(a2)+ ; set Y pos move.b (a1)+,(a2)+ ; set sprite size addq.b #1,d5 move.b d5,(a2)+ ; set link field move.w (a1)+,d0 add.w a3,d0 move.w d0,(a2)+ ; set art tile and flags addq.w #2,a1 move.w (a1)+,d0 add.w d3,d0 andi.w #$1FF,d0 bne.s + addq.w #1,d0 ; avoid activating sprite masking + move.w d0,(a2)+ ; set X pos dbf d1,DrawSprite_Loop ; repeat for next sprite ; return_16852: DrawSprite_Done: rts ; =========================================================================== ; loc_16854: DrawSprite_FlipX: btst #1,d4 ; is it to be Y-flipped as well? bne.w DrawSprite_FlipXY ; if it is, branch - move.b (a1)+,d0 ext.w d0 add.w d2,d0 move.w d0,(a2)+ move.b (a1)+,d4 ; store size for later use move.b d4,(a2)+ addq.b #1,d5 move.b d5,(a2)+ move.w (a1)+,d0 add.w a3,d0 eori.w #$800,d0 ; toggle X flip flag move.w d0,(a2)+ addq.w #2,a1 move.w (a1)+,d0 neg.w d0 ; negate X offset move.b CellOffsets_XFlip(pc,d4.w),d4 sub.w d4,d0 ; subtract sprite size add.w d3,d0 andi.w #$1FF,d0 bne.s + addq.w #1,d0 + move.w d0,(a2)+ dbf d1,- rts ; =========================================================================== ; offsets for horizontally mirrored sprite pieces CellOffsets_XFlip: dc.b 8, 8, 8, 8 ; 4 dc.b $10,$10,$10,$10 ; 8 dc.b $18,$18,$18,$18 ; 12 dc.b $20,$20,$20,$20 ; 16 ; offsets for vertically mirrored sprite pieces CellOffsets_YFlip: dc.b 8,$10,$18,$20 ; 4 dc.b 8,$10,$18,$20 ; 8 dc.b 8,$10,$18,$20 ; 12 dc.b 8,$10,$18,$20 ; 16 ; =========================================================================== ; loc_168B4: DrawSprite_FlipY: move.b (a1)+,d0 move.b (a1),d4 ext.w d0 neg.w d0 move.b CellOffsets_YFlip(pc,d4.w),d4 sub.w d4,d0 add.w d2,d0 move.w d0,(a2)+ ; set Y pos move.b (a1)+,(a2)+ ; set size addq.b #1,d5 move.b d5,(a2)+ ; set link field move.w (a1)+,d0 add.w a3,d0 eori.w #$1000,d0 ; toggle Y flip flag move.w d0,(a2)+ ; set art tile and flags addq.w #2,a1 move.w (a1)+,d0 add.w d3,d0 andi.w #$1FF,d0 bne.s + addq.w #1,d0 + move.w d0,(a2)+ ; set X pos dbf d1,DrawSprite_FlipY rts ; =========================================================================== ; offsets for vertically mirrored sprite pieces CellOffsets_YFlip2: dc.b 8,$10,$18,$20 ; 4 dc.b 8,$10,$18,$20 ; 8 dc.b 8,$10,$18,$20 ; 12 dc.b 8,$10,$18,$20 ; 16 ; =========================================================================== ; loc_168FC: DrawSprite_FlipXY: move.b (a1)+,d0 move.b (a1),d4 ext.w d0 neg.w d0 move.b CellOffsets_YFlip2(pc,d4.w),d4 sub.w d4,d0 add.w d2,d0 move.w d0,(a2)+ move.b (a1)+,d4 move.b d4,(a2)+ addq.b #1,d5 move.b d5,(a2)+ move.w (a1)+,d0 add.w a3,d0 eori.w #$1800,d0 ; toggle X and Y flip flags move.w d0,(a2)+ addq.w #2,a1 move.w (a1)+,d0 neg.w d0 move.b CellOffsets_XFlip2(pc,d4.w),d4 sub.w d4,d0 add.w d3,d0 andi.w #$1FF,d0 bne.s + addq.w #1,d0 + move.w d0,(a2)+ dbf d1,DrawSprite_FlipXY rts ; End of function DrawSprite ; =========================================================================== ; offsets for horizontally mirrored sprite pieces CellOffsets_XFlip2: dc.b 8, 8, 8, 8 ; 4 dc.b $10,$10,$10,$10 ; 8 dc.b $18,$18,$18,$18 ; 12 dc.b $20,$20,$20,$20 ; 16 ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to convert mappings (etc) to proper Megadrive sprites ; for 2-player (split screen) mode ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1694E: BuildSprites_2P: lea (Sprite_Table).w,a2 moveq #2,d5 moveq #0,d4 move.l #$1D80F01,(a2)+ ; mask all sprites move.l #1,(a2)+ move.l #$1D80F02,(a2)+ ; from 216px to 248px move.l #0,(a2)+ tst.b (Level_started_flag).w beq.s + jsrto (BuildHUD_P1).l, JmpTo_BuildHUD_P1 bsr.w BuildRings_P1 + lea (Sprite_Table_Input).w,a4 moveq #7,d7 ; loc_16982: BuildSprites_P1_LevelLoop: move.w (a4),d0 ; does this priority level have any objects? beq.w BuildSprites_P1_NextLevel ; if not, check next one move.w d0,-(sp) moveq #2,d6 ; loc_1698C: BuildSprites_P1_ObjLoop: movea.w (a4,d6.w),a0 ; a0=object tst.b id(a0) beq.w BuildSprites_P1_NextObj andi.b #$7F,render_flags(a0) move.b render_flags(a0),d0 move.b d0,d4 btst #6,d0 bne.w BuildSprites_P1_MultiDraw andi.w #$C,d0 beq.s BuildSprites_P1_ScreenSpaceObj lea (Camera_X_pos).w,a1 moveq #0,d0 move.b width_pixels(a0),d0 move.w x_pos(a0),d3 sub.w (a1),d3 move.w d3,d1 add.w d0,d1 bmi.w BuildSprites_P1_NextObj move.w d3,d1 sub.w d0,d1 cmpi.w #320,d1 bge.s BuildSprites_P1_NextObj addi.w #128,d3 btst #4,d4 beq.s BuildSprites_P1_ApproxYCheck moveq #0,d0 move.b y_radius(a0),d0 move.w y_pos(a0),d2 sub.w 4(a1),d2 move.w d2,d1 add.w d0,d1 bmi.s BuildSprites_P1_NextObj move.w d2,d1 sub.w d0,d1 cmpi.w #224,d1 bge.s BuildSprites_P1_NextObj addi.w #256,d2 bra.s BuildSprites_P1_DrawSprite ; =========================================================================== ; loc_16A00: BuildSprites_P1_ScreenSpaceObj: move.w y_pixel(a0),d2 move.w x_pixel(a0),d3 addi.w #128,d2 bra.s BuildSprites_P1_DrawSprite ; =========================================================================== ; loc_16A0E: BuildSprites_P1_ApproxYCheck: move.w y_pos(a0),d2 sub.w 4(a1),d2 addi.w #128,d2 cmpi.w #-32+128,d2 blo.s BuildSprites_P1_NextObj cmpi.w #32+128+224,d2 bhs.s BuildSprites_P1_NextObj addi.w #128,d2 ; loc_16A2A: BuildSprites_P1_DrawSprite: movea.l mappings(a0),a1 moveq #0,d1 btst #5,d4 bne.s + move.b mapping_frame(a0),d1 add.w d1,d1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 bmi.s ++ + bsr.w DrawSprite_2P + ori.b #$80,render_flags(a0) ; loc_16A50: BuildSprites_P1_NextObj: addq.w #2,d6 subq.w #2,(sp) bne.w BuildSprites_P1_ObjLoop addq.w #2,sp ; loc_16A5A: BuildSprites_P1_NextLevel: lea $80(a4),a4 dbf d7,BuildSprites_P1_LevelLoop move.b d5,(Sprite_count).w cmpi.b #80,d5 bhs.s + move.l #0,(a2) bra.s BuildSprites_P2 + move.b #0,-5(a2) ; build sprites for player 2 ; loc_16A7A: BuildSprites_P2: tst.w (Hint_flag).w ; has H-int occured yet? bne.s BuildSprites_P2 ; if not, wait lea (Sprite_Table_2).w,a2 moveq #0,d5 moveq #0,d4 tst.b (Level_started_flag).w beq.s + jsrto (BuildHUD_P2).l, JmpTo_BuildHUD_P2 bsr.w BuildRings_P2 + lea (Sprite_Table_Input).w,a4 moveq #7,d7 ; loc_16A9C: BuildSprites_P2_LevelLoop: move.w (a4),d0 beq.w BuildSprites_P2_NextLevel move.w d0,-(sp) moveq #2,d6 ; loc_16AA6: BuildSprites_P2_ObjLoop: movea.w (a4,d6.w),a0 ; a0=object tst.b id(a0) beq.w BuildSprites_P2_NextObj move.b render_flags(a0),d0 move.b d0,d4 btst #6,d0 bne.w BuildSprites_P2_MultiDraw andi.w #$C,d0 beq.s BuildSprites_P2_ScreenSpaceObj lea (Camera_X_pos_P2).w,a1 moveq #0,d0 move.b width_pixels(a0),d0 move.w x_pos(a0),d3 sub.w (a1),d3 move.w d3,d1 add.w d0,d1 bmi.w BuildSprites_P2_NextObj move.w d3,d1 sub.w d0,d1 cmpi.w #320,d1 bge.s BuildSprites_P2_NextObj addi.w #128,d3 btst #4,d4 beq.s BuildSprites_P2_ApproxYCheck moveq #0,d0 move.b y_radius(a0),d0 move.w y_pos(a0),d2 sub.w 4(a1),d2 move.w d2,d1 add.w d0,d1 bmi.s BuildSprites_P2_NextObj move.w d2,d1 sub.w d0,d1 cmpi.w #224,d1 bge.s BuildSprites_P2_NextObj addi.w #256+224,d2 bra.s BuildSprites_P2_DrawSprite ; =========================================================================== ; loc_16B14: BuildSprites_P2_ScreenSpaceObj: move.w y_pixel(a0),d2 move.w x_pixel(a0),d3 addi.w #$160,d2 bra.s BuildSprites_P2_DrawSprite ; =========================================================================== ; loc_16B22: BuildSprites_P2_ApproxYCheck: move.w y_pos(a0),d2 sub.w 4(a1),d2 addi.w #128,d2 cmpi.w #-32+128,d2 blo.s BuildSprites_P2_NextObj cmpi.w #32+128+224,d2 bhs.s BuildSprites_P2_NextObj addi.w #128+224,d2 ; loc_16B3E: BuildSprites_P2_DrawSprite: movea.l mappings(a0),a1 moveq #0,d1 btst #5,d4 bne.s + move.b mapping_frame(a0),d1 add.w d1,d1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 bmi.s ++ + bsr.w DrawSprite_2P + ori.b #$80,render_flags(a0) ; loc_16B64: BuildSprites_P2_NextObj: addq.w #2,d6 subq.w #2,(sp) bne.w BuildSprites_P2_ObjLoop addq.w #2,sp tst.b (Teleport_flag).w bne.s BuildSprites_P2_NextLevel move.w #0,(a4) ; loc_16B78: BuildSprites_P2_NextLevel: lea $80(a4),a4 dbf d7,BuildSprites_P2_LevelLoop move.b d5,(Sprite_count).w cmpi.b #80,d5 beq.s + move.l #0,(a2) rts + move.b #0,-5(a2) rts ; =========================================================================== ; loc_16B9A: BuildSprites_P1_MultiDraw: move.l a4,-(sp) lea (Camera_X_pos).w,a4 movea.w art_tile(a0),a3 movea.l mappings(a0),a5 moveq #0,d0 move.b mainspr_width(a0),d0 move.w x_pos(a0),d3 sub.w (a4),d3 move.w d3,d1 add.w d0,d1 bmi.w BuildSprites_P1_MultiDraw_NextObj move.w d3,d1 sub.w d0,d1 cmpi.w #320,d1 bge.w BuildSprites_P1_MultiDraw_NextObj addi.w #128,d3 btst #4,d4 beq.s + moveq #0,d0 move.b mainspr_height(a0),d0 move.w y_pos(a0),d2 sub.w 4(a4),d2 move.w d2,d1 add.w d0,d1 bmi.w BuildSprites_P1_MultiDraw_NextObj move.w d2,d1 sub.w d0,d1 cmpi.w #224,d1 bge.w BuildSprites_P1_MultiDraw_NextObj addi.w #256,d2 bra.s ++ + move.w y_pos(a0),d2 sub.w 4(a4),d2 addi.w #128,d2 cmpi.w #-32+128,d2 blo.s BuildSprites_P1_MultiDraw_NextObj cmpi.w #32+128+224,d2 bhs.s BuildSprites_P1_MultiDraw_NextObj addi.w #128,d2 + moveq #0,d1 move.b mainspr_mapframe(a0),d1 beq.s + add.w d1,d1 movea.l a5,a1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 bmi.s + move.w d4,-(sp) bsr.w ChkDrawSprite_2P move.w (sp)+,d4 + ori.b #$80,render_flags(a0) lea sub2_x_pos(a0),a6 moveq #0,d0 move.b mainspr_childsprites(a0),d0 subq.w #1,d0 bcs.s BuildSprites_P1_MultiDraw_NextObj - swap d0 move.w (a6)+,d3 sub.w (a4),d3 addi.w #128,d3 move.w (a6)+,d2 sub.w 4(a4),d2 addi.w #256,d2 addq.w #1,a6 moveq #0,d1 move.b (a6)+,d1 add.w d1,d1 movea.l a5,a1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 bmi.s + move.w d4,-(sp) bsr.w ChkDrawSprite_2P move.w (sp)+,d4 + swap d0 dbf d0,- ; loc_16C7E: BuildSprites_P1_MultiDraw_NextObj: movea.l (sp)+,a4 bra.w BuildSprites_P1_NextObj ; =========================================================================== ; loc_16C84: BuildSprites_P2_MultiDraw: move.l a4,-(sp) lea (Camera_X_pos_P2).w,a4 movea.w art_tile(a0),a3 movea.l mappings(a0),a5 moveq #0,d0 move.b mainspr_width(a0),d0 move.w x_pos(a0),d3 sub.w (a4),d3 move.w d3,d1 add.w d0,d1 bmi.w BuildSprites_P2_MultiDraw_NextObj move.w d3,d1 sub.w d0,d1 cmpi.w #320,d1 bge.w BuildSprites_P2_MultiDraw_NextObj addi.w #128,d3 btst #4,d4 beq.s + moveq #0,d0 move.b mainspr_height(a0),d0 move.w y_pos(a0),d2 sub.w 4(a4),d2 move.w d2,d1 add.w d0,d1 bmi.w BuildSprites_P2_MultiDraw_NextObj move.w d2,d1 sub.w d0,d1 cmpi.w #224,d1 bge.w BuildSprites_P2_MultiDraw_NextObj addi.w #256+224,d2 bra.s ++ + move.w y_pos(a0),d2 sub.w 4(a4),d2 addi.w #128,d2 cmpi.w #-32+128,d2 blo.s BuildSprites_P2_MultiDraw_NextObj cmpi.w #32+128+224,d2 bhs.s BuildSprites_P2_MultiDraw_NextObj addi.w #128+224,d2 + moveq #0,d1 move.b mainspr_mapframe(a0),d1 beq.s + add.w d1,d1 movea.l a5,a1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 bmi.s + move.w d4,-(sp) bsr.w ChkDrawSprite_2P move.w (sp)+,d4 + ori.b #$80,render_flags(a0) lea sub2_x_pos(a0),a6 moveq #0,d0 move.b mainspr_childsprites(a0),d0 subq.w #1,d0 bcs.s BuildSprites_P2_MultiDraw_NextObj - swap d0 move.w (a6)+,d3 sub.w (a4),d3 addi.w #128,d3 move.w (a6)+,d2 sub.w 4(a4),d2 addi.w #256+224,d2 addq.w #1,a6 moveq #0,d1 move.b (a6)+,d1 add.w d1,d1 movea.l a5,a1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 bmi.s + move.w d4,-(sp) bsr.w ChkDrawSprite_2P move.w (sp)+,d4 + swap d0 dbf d0,- ; loc_16D68: BuildSprites_P2_MultiDraw_NextObj: movea.l (sp)+,a4 bra.w BuildSprites_P2_NextObj ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; adjust art pointer of object at a0 for 2-player mode ; sub_16D6E: Adjust2PArtPointer: tst.w (Two_player_mode).w beq.s + ; rts move.w art_tile(a0),d0 andi.w #tile_mask,d0 lsr.w #1,d0 andi.w #nontile_mask,art_tile(a0) add.w d0,art_tile(a0) + rts ; End of function Adjust2PArtPointer ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; adjust art pointer of object at a1 for 2-player mode ; sub_16D8A: Adjust2PArtPointer2: tst.w (Two_player_mode).w beq.s + ; rts move.w art_tile(a1),d0 andi.w #tile_mask,d0 lsr.w #1,d0 andi.w #nontile_mask,art_tile(a1) add.w d0,art_tile(a1) + rts ; End of function Adjust2PArtPointer2 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_16DA6: ChkDrawSprite_2P: cmpi.b #80,d5 blo.s DrawSprite_2P_Loop rts ; End of function ChkDrawSprite_2P ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; copy sprite art to VRAM, in 2-player mode ; sub_16DAE: DrawSprite_2P: movea.w art_tile(a0),a3 cmpi.b #80,d5 bhs.s DrawSprite_2P_Done btst #0,d4 bne.s DrawSprite_2P_FlipX btst #1,d4 bne.w DrawSprite_2P_FlipY ; loc_16DC6: DrawSprite_2P_Loop: move.b (a1)+,d0 ext.w d0 add.w d2,d0 move.w d0,(a2)+ move.b (a1)+,d4 move.b SpriteSizes_2P(pc,d4.w),(a2)+ addq.b #1,d5 move.b d5,(a2)+ addq.w #2,a1 move.w (a1)+,d0 add.w a3,d0 move.w d0,(a2)+ move.w (a1)+,d0 add.w d3,d0 andi.w #$1FF,d0 bne.s + addq.w #1,d0 + move.w d0,(a2)+ dbf d1,DrawSprite_2P_Loop ; return_16DF2: DrawSprite_2P_Done: rts ; =========================================================================== ; cells are double the height in 2P mode, so halve the number of rows ;byte_16DF4: SpriteSizes_2P: dc.b 0,0 dc.b 1,1 dc.b 4,4 dc.b 5,5 dc.b 8,8 dc.b 9,9 dc.b $C,$C dc.b $D,$D ; =========================================================================== ; loc_16E04: DrawSprite_2P_FlipX: btst #1,d4 bne.w DrawSprite_2P_FlipXY - move.b (a1)+,d0 ext.w d0 add.w d2,d0 move.w d0,(a2)+ move.b (a1)+,d4 move.b SpriteSizes_2P(pc,d4.w),(a2)+ addq.b #1,d5 move.b d5,(a2)+ addq.w #2,a1 move.w (a1)+,d0 add.w a3,d0 eori.w #$800,d0 move.w d0,(a2)+ move.w (a1)+,d0 neg.w d0 move.b byte_16E46(pc,d4.w),d4 sub.w d4,d0 add.w d3,d0 andi.w #$1FF,d0 bne.s + addq.w #1,d0 + move.w d0,(a2)+ dbf d1,- rts ; =========================================================================== ; offsets for horizontally mirrored sprite pieces (2P) byte_16E46: dc.b 8, 8, 8, 8 ; 4 dc.b $10,$10,$10,$10 ; 8 dc.b $18,$18,$18,$18 ; 12 dc.b $20,$20,$20,$20 ; 16 ; offsets for vertically mirrored sprite pieces (2P) byte_16E56: dc.b 8,$10,$18,$20 ; 4 dc.b 8,$10,$18,$20 ; 8 dc.b 8,$10,$18,$20 ; 12 dc.b 8,$10,$18,$20 ; 16 ; =========================================================================== ; loc_16E66: DrawSprite_2P_FlipY: move.b (a1)+,d0 move.b (a1),d4 ext.w d0 neg.w d0 move.b byte_16E56(pc,d4.w),d4 sub.w d4,d0 add.w d2,d0 move.w d0,(a2)+ move.b (a1)+,d4 move.b SpriteSizes_2P_2(pc,d4.w),(a2)+ addq.b #1,d5 move.b d5,(a2)+ addq.w #2,a1 move.w (a1)+,d0 add.w a3,d0 eori.w #$1000,d0 move.w d0,(a2)+ move.w (a1)+,d0 add.w d3,d0 andi.w #$1FF,d0 bne.s + addq.w #1,d0 + move.w d0,(a2)+ dbf d1,DrawSprite_2P_FlipY rts ; =========================================================================== ; cells are double the height in 2P mode, so halve the number of rows ; byte_16EA2: SpriteSizes_2P_2: dc.b 0,0 dc.b 1,1 ; 2 dc.b 4,4 ; 4 dc.b 5,5 ; 6 dc.b 8,8 ; 8 dc.b 9,9 ; 10 dc.b $C,$C ; 12 dc.b $D,$D ; 14 ; offsets for vertically mirrored sprite pieces (2P) byte_16EB2: dc.b 8,$10,$18,$20 ; 4 dc.b 8,$10,$18,$20 ; 8 dc.b 8,$10,$18,$20 ; 12 dc.b 8,$10,$18,$20 ; 16 ; =========================================================================== ; loc_16EC2: DrawSprite_2P_FlipXY: move.b (a1)+,d0 move.b (a1),d4 ext.w d0 neg.w d0 move.b byte_16EB2(pc,d4.w),d4 sub.w d4,d0 add.w d2,d0 move.w d0,(a2)+ move.b (a1)+,d4 move.b SpriteSizes_2P_2(pc,d4.w),(a2)+ addq.b #1,d5 move.b d5,(a2)+ addq.w #2,a1 move.w (a1)+,d0 add.w a3,d0 eori.w #$1800,d0 move.w d0,(a2)+ move.w (a1)+,d0 neg.w d0 move.b byte_16F06(pc,d4.w),d4 sub.w d4,d0 add.w d3,d0 andi.w #$1FF,d0 bne.s + addq.w #1,d0 + move.w d0,(a2)+ dbf d1,DrawSprite_2P_FlipXY rts ; End of function DrawSprite_2P ; =========================================================================== ; offsets for horizontally mirrored sprite pieces (2P) byte_16F06: dc.b 8, 8, 8, 8 ; 4 dc.b $10,$10,$10,$10 ; 8 dc.b $18,$18,$18,$18 ; 12 dc.b $20,$20,$20,$20 ; 16 ; =========================================================================== ; loc_16F16: ; unused/dead code? ; a0=object move.w x_pos(a0),d0 sub.w (Camera_X_pos).w,d0 bmi.s + cmpi.w #320,d0 bge.s + move.w y_pos(a0),d1 sub.w (Camera_Y_pos).w,d1 bmi.s + cmpi.w #$E0,d1 bge.s + moveq #0,d0 rts + moveq #1,d0 rts ; =========================================================================== ; loc_16F3E: ; unused/dead code? ; a0=object moveq #0,d1 move.b width_pixels(a0),d1 move.w x_pos(a0),d0 sub.w (Camera_X_pos).w,d0 add.w d1,d0 bmi.s + add.w d1,d1 sub.w d1,d0 cmpi.w #320,d0 bge.s + move.w y_pos(a0),d1 sub.w (Camera_Y_pos).w,d1 bmi.s + cmpi.w #$E0,d1 bge.s + moveq #0,d0 rts + moveq #1,d0 rts ; =========================================================================== if gameRevision=1 nop endif if ~~removeJmpTos JmpTo_BuildHUD jmp (BuildHUD).l JmpTo_BuildHUD_P1 jmp (BuildHUD_P1).l JmpTo_BuildHUD_P2 jmp (BuildHUD_P2).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Pseudo-object that manages where rings are placed onscreen ; as you move through the level, and otherwise updates them. ; ---------------------------------------------------------------------------- ; loc_16F88: RingsManager: moveq #0,d0 move.b (Rings_manager_routine).w,d0 move.w RingsManager_States(pc,d0.w),d0 jmp RingsManager_States(pc,d0.w) ; =========================================================================== ; off_16F96: RingsManager_States: offsetTable offsetTableEntry.w RingsManager_Init ; 0 offsetTableEntry.w RingsManager_Main ; 2 ; =========================================================================== ; loc_16F9A: RingsManager_Init: addq.b #2,(Rings_manager_routine).w ; => RingsManager_Main bsr.w RingsManager_Setup ; perform initial setup lea (Ring_Positions).w,a1 move.w (Camera_X_pos).w,d4 subq.w #8,d4 bhi.s + moveq #1,d4 ; no negative values allowed bra.s + - lea 6(a1),a1 ; load next ring + cmp.w 2(a1),d4 ; is the X pos of the ring < camera X pos? bhi.s - ; if it is, check next ring move.w a1,(Ring_start_addr).w ; set start addresses move.w a1,(Ring_start_addr_P2).w addi.w #320+16,d4 ; advance by a screen bra.s + - lea 6(a1),a1 ; load next ring + cmp.w 2(a1),d4 ; is the X pos of the ring < camera X + 336? bhi.s - ; if it is, check next ring move.w a1,(Ring_end_addr).w ; set end addresses move.w a1,(Ring_end_addr_P2).w rts ; =========================================================================== ; loc_16FDE: RingsManager_Main: lea (Ring_consumption_table).w,a2 move.w (a2)+,d1 subq.w #1,d1 ; are any rings currently being consumed? bcs.s ++ ; if not, branch - move.w (a2)+,d0 ; is there a ring in this slot? beq.s - ; if not, branch movea.w d0,a1 ; load ring address subq.b #1,(a1) ; decrement timer bne.s + ; if it's not 0 yet, branch move.b #6,(a1) ; reset timer addq.b #1,1(a1); increment frame cmpi.b #8,1(a1); is it destruction time yet? bne.s + ; if not, branch move.w #-1,(a1); destroy ring move.w #0,-2(a2) ; clear ring entry subq.w #1,(Ring_consumption_table).w ; subtract count + dbf d1,- ; repeat for all rings in table + ; update ring start and end addresses movea.w (Ring_start_addr).w,a1 move.w (Camera_X_pos).w,d4 subq.w #8,d4 bhi.s + moveq #1,d4 bra.s + - lea 6(a1),a1 + cmp.w 2(a1),d4 bhi.s - bra.s + - subq.w #6,a1 + cmp.w -4(a1),d4 bls.s - move.w a1,(Ring_start_addr).w ; update start address movea.w (Ring_end_addr).w,a2 addi.w #320+16,d4 bra.s + - lea 6(a2),a2 + cmp.w 2(a2),d4 bhi.s - bra.s + - subq.w #6,a2 + cmp.w -4(a2),d4 bls.s - move.w a2,(Ring_end_addr).w ; update end address tst.w (Two_player_mode).w ; are we in 2P mode? bne.s + ; if we are, update P2 addresses move.w a1,(Ring_start_addr_P2).w ; otherwise, copy over P1 addresses move.w a2,(Ring_end_addr_P2).w rts + ; update ring start and end addresses for P2 movea.w (Ring_start_addr_P2).w,a1 move.w (Camera_X_pos_P2).w,d4 subq.w #8,d4 bhi.s + moveq #1,d4 bra.s + - lea 6(a1),a1 + cmp.w 2(a1),d4 bhi.s - bra.s + - subq.w #6,a1 + cmp.w -4(a1),d4 bls.s - move.w a1,(Ring_start_addr_P2).w ; update start address movea.w (Ring_end_addr_P2).w,a2 addi.w #320+16,d4 bra.s + - lea 6(a2),a2 + cmp.w 2(a2),d4 bhi.s - bra.s + - subq.w #6,a2 + cmp.w -4(a2),d4 bls.s - move.w a2,(Ring_end_addr_P2).w ; update end address rts ; --------------------------------------------------------------------------- ; Subroutine to handle ring collision ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_170BA: Touch_Rings: movea.w (Ring_start_addr).w,a1 movea.w (Ring_end_addr).w,a2 cmpa.w #MainCharacter,a0 beq.s + movea.w (Ring_start_addr_P2).w,a1 movea.w (Ring_end_addr_P2).w,a2 + cmpa.l a1,a2 ; are there no rings in this area? beq.w Touch_Rings_Done ; if so, return cmpi.w #$5A,invulnerable_time(a0) bhs.w Touch_Rings_Done move.w x_pos(a0),d2 move.w y_pos(a0),d3 subi_.w #8,d2 ; assume X radius to be 8 moveq #0,d5 move.b y_radius(a0),d5 subq.b #3,d5 sub.w d5,d3 ; subtract (Y radius - 3) from Y pos cmpi.b #$4D,mapping_frame(a0) bne.s + ; if you're not ducking, branch addi.w #$C,d3 moveq #$A,d5 + move.w #6,d1 ; set ring radius move.w #12,d6 ; set ring diameter move.w #16,d4 ; set Sonic's X diameter add.w d5,d5 ; set Y diameter ; loc_17112: Touch_Rings_Loop: tst.w (a1) ; has this ring already been collided with? bne.w Touch_NextRing ; if it has, branch move.w 2(a1),d0 ; get ring X pos sub.w d1,d0 ; get ring left edge X pos sub.w d2,d0 ; subtract Sonic's left edge X pos bcc.s + ; if Sonic's to the left of the ring, branch add.w d6,d0 ; add ring diameter bcs.s ++ ; if Sonic's colliding, branch bra.w Touch_NextRing ; otherwise, test next ring + cmp.w d4,d0 ; has Sonic crossed the ring? bhi.w Touch_NextRing ; if he has, branch + move.w 4(a1),d0 ; get ring Y pos sub.w d1,d0 ; get ring top edge pos sub.w d3,d0 ; subtract Sonic's top edge pos bcc.s + ; if Sonic's above the ring, branch add.w d6,d0 ; add ring diameter bcs.s ++ ; if Sonic's colliding, branch bra.w Touch_NextRing ; otherwise, test next ring + cmp.w d5,d0 ; has Sonic crossed the ring? bhi.w Touch_NextRing ; if he has, branch + move.w #$604,(a1) ; set frame and destruction timer bsr.s Touch_ConsumeRing lea (Ring_consumption_table+2).w,a3 - tst.w (a3)+ ; is this slot free? bne.s - ; if not, repeat until you find one move.w a1,-(a3) ; set ring address addq.w #1,(Ring_consumption_table).w ; increase count ; loc_1715C: Touch_NextRing: lea 6(a1),a1 cmpa.l a1,a2 ; are we at the last ring for this area? bne.w Touch_Rings_Loop ; if not, branch ; return_17166: Touch_Rings_Done: rts ; =========================================================================== ; loc_17168: Touch_ConsumeRing: subq.w #1,(Perfect_rings_left).w cmpa.w #MainCharacter,a0 ; who collected the ring? beq.w CollectRing_Sonic ; if it was Sonic, branch here bra.w CollectRing_Tails ; if it was Tails, branch here ; --------------------------------------------------------------------------- ; Subroutine to draw on-screen rings ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_17178: BuildRings: movea.w (Ring_start_addr).w,a0 movea.w (Ring_end_addr).w,a4 cmpa.l a0,a4 ; are there any rings on-screen? bne.s + ; if there are, branch rts ; otherwise, return + lea (Camera_X_pos).w,a3 ; loc_1718A: BuildRings_Loop: tst.w (a0) ; has this ring been consumed? bmi.w BuildRings_NextRing ; if it has, branch move.w 2(a0),d3 ; get ring X pos sub.w (a3),d3 ; subtract camera X pos addi.w #128,d3 ; screen top is 128x128 not 0x0 move.w 4(a0),d2 ; get ring Y pos sub.w 4(a3),d2 ; subtract camera Y pos andi.w #$7FF,d2 addi_.w #8,d2 bmi.s BuildRings_NextRing ; dunno how this check is supposed to work cmpi.w #240,d2 bge.s BuildRings_NextRing ; if the ring is not on-screen, branch addi.w #128-8,d2 lea (MapUnc_Rings).l,a1 moveq #0,d1 move.b 1(a0),d1 ; get ring frame bne.s + ; if this ring is using a specific frame, branch move.b (Rings_anim_frame).w,d1 ; use global frame + add.w d1,d1 adda.w (a1,d1.w),a1 ; get frame data address move.b (a1)+,d0 ; get Y offset ext.w d0 add.w d2,d0 ; add Y offset to Y pos move.w d0,(a2)+ ; set Y pos move.b (a1)+,(a2)+ ; set size addq.b #1,d5 move.b d5,(a2)+ ; set link field move.w (a1)+,d0 ; get art tile addi.w #make_art_tile(ArtTile_ArtNem_Ring,1,0),d0 ; add base art tile move.w d0,(a2)+ ; set art tile and flags addq.w #2,a1 ; skip 2P art tile move.w (a1)+,d0 ; get X offset add.w d3,d0 ; add base X pos move.w d0,(a2)+ ; set X pos ; loc_171EC: BuildRings_NextRing: lea 6(a0),a0 cmpa.l a0,a4 bne.w BuildRings_Loop rts ; --------------------------------------------------------------------------- ; Subroutine to draw on-screen rings for player 1 in a 2P versus game ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_171F8: BuildRings_P1: lea (Camera_X_pos).w,a3 move.w #128-8,d6 movea.w (Ring_start_addr).w,a0 movea.w (Ring_end_addr).w,a4 cmpa.l a0,a4 ; are there rings on-screen? bne.s BuildRings_2P_Loop ; if there are, draw them rts ; otherwise, return ; --------------------------------------------------------------------------- ; Subroutine to draw on-screen rings for player 2 in a 2P versus game ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1720E: BuildRings_P2: lea (Camera_X_pos_P2).w,a3 move.w #224+128-8,d6 movea.w (Ring_start_addr_P2).w,a0 movea.w (Ring_end_addr_P2).w,a4 cmpa.l a0,a4 ; are there rings on-screen? bne.s BuildRings_2P_Loop ; if there are, draw them rts ; otherwise, return ; =========================================================================== ; loc_17224: BuildRings_2P_Loop: tst.w (a0) ; has this ring been consumed? bmi.w BuildRings_2P_NextRing ; if it has, branch move.w 2(a0),d3 ; get ring X pos sub.w (a3),d3 ; subtract camera X pos addi.w #128,d3 move.w 4(a0),d2 ; get ring Y pos sub.w 4(a3),d2 ; subtract camera Y pos andi.w #$7FF,d2 addi.w #128+8,d2 bmi.s BuildRings_2P_NextRing cmpi.w #240+128,d2 bge.s BuildRings_2P_NextRing add.w d6,d2 ; add base Y pos lea (MapUnc_Rings).l,a1 moveq #0,d1 move.b 1(a0),d1 ; use ring-specific frame bne.s + ; if there is one move.b (Rings_anim_frame).w,d1 ; otherwise use global frame + add.w d1,d1 adda.w (a1,d1.w),a1 move.b (a1)+,d0 ext.w d0 add.w d2,d0 move.w d0,(a2)+ ; set Y pos move.b (a1)+,d4 move.b SpriteSizes_2P_3(pc,d4.w),(a2)+ ; set size addq.b #1,d5 move.b d5,(a2)+ ; set link field addq.w #2,a1 move.w (a1)+,d0 addi.w #make_art_tile_2p(ArtTile_ArtNem_Ring,1,0),d0 move.w d0,(a2)+ ; set art tile and flags move.w (a1)+,d0 add.w d3,d0 move.w d0,(a2)+ ; set X pos BuildRings_2P_NextRing: lea 6(a0),a0 ; load next ring cmpa.l a0,a4 ; are there any rings left? bne.w BuildRings_2P_Loop ; if there are, loop rts ; =========================================================================== ; cells are double the height in 2P mode, so halve the number of rows ; byte_17294: SpriteSizes_2P_3: dc.b 0,0 ; 1 dc.b 1,1 ; 3 dc.b 4,4 ; 5 dc.b 5,5 ; 7 dc.b 8,8 ; 9 dc.b 9,9 ; 11 dc.b $C,$C ; 13 dc.b $D,$D ; 15 ; --------------------------------------------------------------------------- ; Subroutine to perform initial rings manager setup ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_172A4: RingsManager_Setup: clearRAM Ring_Positions,Ring_Positions_End ; d0 = 0 lea (Ring_consumption_table).w,a1 move.w #bytesToLcnt(Ring_consumption_table_End-Ring_consumption_table-$40),d1 ; coding error, that '-$40' shouldn't be there - move.l d0,(a1)+ ; only half of Ring_consumption_table is cleared dbf d1,- moveq #0,d5 moveq #0,d0 move.w (Current_ZoneAndAct).w,d0 ror.b #1,d0 lsr.w #6,d0 lea (Off_Rings).l,a1 move.w (a1,d0.w),d0 lea (a1,d0.w),a1 lea (Ring_Positions+6).w,a2 ; first ring is left blank ; loc_172E0: RingsMgr_NextRowOrCol: move.w (a1)+,d2 ; is this the last ring? bmi.s RingsMgr_SortRings ; if it is, sort the rings move.w (a1)+,d3 ; is this a column of rings? bmi.s RingsMgr_RingCol ; if it is, branch move.w d3,d0 rol.w #4,d0 andi.w #7,d0 ; store number of rings andi.w #$FFF,d3 ; store Y pos ; loc_172F4: RingsMgr_NextRingInRow: move.w #0,(a2)+ ; set initial status move.w d2,(a2)+ ; set X pos move.w d3,(a2)+ ; set Y pos addi.w #$18,d2 ; increment X pos addq.w #1,d5 ; increment perfect counter dbf d0,RingsMgr_NextRingInRow bra.s RingsMgr_NextRowOrCol ; =========================================================================== ; loc_17308: RingsMgr_RingCol: move.w d3,d0 rol.w #4,d0 andi.w #7,d0 ; store number of rings andi.w #$FFF,d3 ; store Y pos ; loc_17314: RingsMgr_NextRingInCol: move.w #0,(a2)+ ; set initial status move.w d2,(a2)+ ; set X pos move.w d3,(a2)+ ; set Y pos addi.w #$18,d3 ; increment Y pos addq.w #1,d5 ; increment perfect counter dbf d0,RingsMgr_NextRingInCol bra.s RingsMgr_NextRowOrCol ; =========================================================================== ; loc_17328: RingsMgr_SortRings: move.w d5,(Perfect_rings_left).w move.w #0,(Perfect_rings_flag).w ; no idea what this is moveq #-1,d0 move.l d0,(a2)+ ; set X pos of last ring to -1 lea (Ring_Positions+2).w,a1 ; X pos of first ring move.w #$FE,d3 ; sort 255 rings - move.w d3,d4 lea 6(a1),a2 ; load next ring for comparison move.w (a1),d0 ; get X pos of current ring - tst.w (a2) ; is the next ring blank? beq.s + ; if it is, branch cmp.w (a2),d0 ; is the X pos of current ring <= X pos of next ring? bls.s + ; if so, branch move.l (a1),d1 ; otherwise, swap the rings move.l (a2),d0 move.l d0,(a1) move.l d1,(a2) swap d0 + lea 6(a2),a2 ; load next comparison ring dbf d4,- ; repeat lea 6(a1),a1 ; load next ring dbf d3,-- ; repeat rts ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- ; off_1736A: MapUnc_Rings: BINCLUDE "mappings/sprite/Rings.bin" if ~~removeJmpTos align 4 endif ; --------------------------------------------------------------------------- ; Pseudo-object to do collision with (and initialize?) the special bumpers in CNZ. ; These are the bumpers that are part of the level layout but have object-like collision. ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_173BC: SpecialCNZBumpers: moveq #0,d0 move.b (CNZ_Bumper_routine).w,d0 move.w SpecialCNZBumpers_Index(pc,d0.w),d0 jmp SpecialCNZBumpers_Index(pc,d0.w) ; =========================================================================== ; off_173CA: SpecialCNZBumpers_Index: offsetTable offsetTableEntry.w SpecialCNZBumpers_Init ; 0 offsetTableEntry.w SpecialCNZBumpers_Main ; 2 ; =========================================================================== ; loc_173CE: SpecialCNZBumpers_Init: addq.b #2,(CNZ_Bumper_routine).w lea (SpecialCNZBumpers_Act1).l,a1 tst.b (Current_Act).w beq.s + lea (SpecialCNZBumpers_Act2).l,a1 + move.w (Camera_X_pos).w,d4 subq.w #8,d4 bhi.s + moveq #1,d4 bra.s + ; =========================================================================== - lea next_bumper(a1),a1 + cmp.w bumper_x(a1),d4 bhi.s - move.l a1,(CNZ_Visible_bumpers_start).w move.l a1,(CNZ_Visible_bumpers_start_P2).w addi.w #$150,d4 bra.s + ; =========================================================================== - lea next_bumper(a1),a1 + cmp.w bumper_x(a1),d4 bhi.s - move.l a1,(CNZ_Visible_bumpers_end).w move.l a1,(CNZ_Visible_bumpers_end_P2).w move.b #1,(CNZ_Bumper_UnkFlag).w rts ; =========================================================================== ; loc_17422: SpecialCNZBumpers_Main: movea.l (CNZ_Visible_bumpers_start).w,a1 move.w (Camera_X_pos).w,d4 subq.w #8,d4 bhi.s + moveq #1,d4 bra.s + ; =========================================================================== - lea next_bumper(a1),a1 + cmp.w bumper_x(a1),d4 bhi.s - bra.s + ; =========================================================================== - subq.w #next_bumper,a1 + cmp.w prev_bumper_x(a1),d4 bls.s - move.l a1,(CNZ_Visible_bumpers_start).w movea.l (CNZ_Visible_bumpers_end).w,a2 addi.w #$150,d4 bra.s + ; =========================================================================== - lea next_bumper(a2),a2 + cmp.w bumper_x(a2),d4 bhi.s - bra.s + ; =========================================================================== - subq.w #next_bumper,a2 + cmp.w prev_bumper_x(a2),d4 bls.s - move.l a2,(CNZ_Visible_bumpers_end).w tst.w (Two_player_mode).w bne.s + move.l a1,(CNZ_Visible_bumpers_start_P2).w move.l a2,(CNZ_Visible_bumpers_end_P2).w rts ; =========================================================================== + movea.l (CNZ_Visible_bumpers_start_P2).w,a1 move.w (Camera_X_pos_P2).w,d4 subq.w #8,d4 bhi.s + moveq #1,d4 bra.s + ; =========================================================================== - lea next_bumper(a1),a1 + cmp.w bumper_x(a1),d4 bhi.s - bra.s + ; =========================================================================== - subq.w #next_bumper,a1 + cmp.w prev_bumper_x(a1),d4 bls.s - move.l a1,(CNZ_Visible_bumpers_start_P2).w movea.l (CNZ_Visible_bumpers_end_P2).w,a2 addi.w #$150,d4 bra.s + ; =========================================================================== - lea next_bumper(a2),a2 + cmp.w bumper_x(a2),d4 bhi.s - bra.s + ; =========================================================================== - subq.w #next_bumper,a2 + cmp.w prev_bumper_x(a2),d4 bls.s - move.l a2,(CNZ_Visible_bumpers_end_P2).w rts ; =========================================================================== Check_CNZ_bumpers: movea.l (CNZ_Visible_bumpers_start).w,a1 movea.l (CNZ_Visible_bumpers_end).w,a2 cmpa.w #MainCharacter,a0 beq.s + movea.l (CNZ_Visible_bumpers_start_P2).w,a1 movea.l (CNZ_Visible_bumpers_end_P2).w,a2 + cmpa.l a1,a2 beq.w return_17578 move.w x_pos(a0),d2 move.w y_pos(a0),d3 subi.w #9,d2 moveq #0,d5 move.b y_radius(a0),d5 subq.b #3,d5 sub.w d5,d3 cmpi.b #$4D,mapping_frame(a0) bne.s + addi.w #$C,d3 moveq #$A,d5 + move.w #$12,d4 add.w d5,d5 CNZ_Bumper_loop: move.w bumper_id(a1),d0 andi.w #$E,d0 lea byte_17558(pc,d0.w),a3 moveq #0,d1 move.b (a3)+,d1 move.w bumper_x(a1),d0 sub.w d1,d0 sub.w d2,d0 bcc.s loc_17530 add.w d1,d1 add.w d1,d0 bcs.s loc_17536 bra.w CNZ_Bumper_next ; =========================================================================== loc_17530: cmp.w d4,d0 bhi.w CNZ_Bumper_next loc_17536: moveq #0,d1 move.b (a3)+,d1 move.w bumper_y(a1),d0 sub.w d1,d0 sub.w d3,d0 bcc.s loc_17550 add.w d1,d1 add.w d1,d0 bcs.w loc_17564 bra.w CNZ_Bumper_next ; =========================================================================== loc_17550: cmp.w d5,d0 bhi.w CNZ_Bumper_next bra.s loc_17564 ; =========================================================================== byte_17558: dc.b $20 dc.b $20 ; 1 dc.b $20 ; 2 dc.b $20 ; 3 dc.b $40 ; 4 dc.b 8 ; 5 dc.b $40 ; 6 dc.b 8 ; 7 dc.b 8 ; 8 dc.b $40 ; 9 dc.b 8 ; 10 dc.b $40 ; 11 ; =========================================================================== loc_17564: move.w (a1),d0 move.w off_1757A(pc,d0.w),d0 jmp off_1757A(pc,d0.w) ; =========================================================================== CNZ_Bumper_next: lea next_bumper(a1),a1 cmpa.l a1,a2 bne.w CNZ_Bumper_loop return_17578: rts ; =========================================================================== off_1757A: offsetTable offsetTableEntry.w loc_17586 ; 0 offsetTableEntry.w loc_17638 ; 2 offsetTableEntry.w loc_1769E ; 4 offsetTableEntry.w loc_176F6 ; 6 offsetTableEntry.w loc_1774C ; 8 offsetTableEntry.w loc_177A4 ; $A ; =========================================================================== loc_17586: move.w bumper_y(a1),d0 sub.w y_pos(a0),d0 neg.w d0 cmpi.w #$20,d0 blt.s loc_175A0 move.w #$A00,y_vel(a0) bra.w loc_177FA ; =========================================================================== loc_175A0: move.w bumper_x(a1),d0 sub.w x_pos(a0),d0 neg.w d0 cmpi.w #$20,d0 blt.s loc_175BA move.w #$A00,x_vel(a0) bra.w loc_177FA ; =========================================================================== loc_175BA: move.w bumper_x(a1),d0 sub.w x_pos(a0),d0 cmpi.w #$20,d0 blt.s loc_175CC move.w #$20,d0 loc_175CC: add.w bumper_y(a1),d0 subq.w #8,d0 move.w y_pos(a0),d1 addi.w #$E,d1 sub.w d1,d0 bcc.s return_175E8 move.w #$20,d3 bsr.s loc_175EA bra.w loc_177FA ; =========================================================================== return_175E8: rts ; =========================================================================== loc_175EA: move.w x_vel(a0),d1 move.w y_vel(a0),d2 jsr (CalcAngle).l move.b d0,(unk_FFDC).w sub.w d3,d0 mvabs.w d0,d1 neg.w d0 add.w d3,d0 move.b d0,(unk_FFDD).w move.b d1,(unk_FFDF).w cmpi.b #$38,d1 blo.s loc_17618 move.w d3,d0 loc_17618: move.b d0,(unk_FFDE).w jsr (CalcSine).l muls.w #-$A00,d1 asr.l #8,d1 move.w d1,x_vel(a0) muls.w #-$A00,d0 asr.l #8,d0 move.w d0,y_vel(a0) rts ; =========================================================================== loc_17638: move.w bumper_y(a1),d0 sub.w y_pos(a0),d0 neg.w d0 cmpi.w #$20,d0 blt.s loc_17652 move.w #$A00,y_vel(a0) bra.w loc_177FA ; =========================================================================== loc_17652: move.w bumper_x(a1),d0 sub.w x_pos(a0),d0 cmpi.w #$20,d0 blt.s loc_1766A move.w #-$A00,x_vel(a0) bra.w loc_177FA ; =========================================================================== loc_1766A: move.w bumper_x(a1),d0 sub.w x_pos(a0),d0 neg.w d0 cmpi.w #$20,d0 blt.s loc_1767E move.w #$20,d0 loc_1767E: add.w bumper_y(a1),d0 subq.w #8,d0 move.w y_pos(a0),d1 addi.w #$E,d1 sub.w d1,d0 bcc.s return_1769C move.w #$60,d3 bsr.w loc_175EA bra.w loc_177FA ; =========================================================================== return_1769C: rts ; =========================================================================== loc_1769E: move.w bumper_y(a1),d0 sub.w y_pos(a0),d0 neg.w d0 cmpi.w #8,d0 blt.s loc_176B8 move.w #$A00,y_vel(a0) bra.w loc_177FA ; =========================================================================== loc_176B8: move.w bumper_x(a1),d0 sub.w x_pos(a0),d0 cmpi.w #$40,d0 blt.s loc_176D0 move.w #-$A00,x_vel(a0) bra.w loc_177FA ; =========================================================================== loc_176D0: neg.w d0 cmpi.w #$40,d0 blt.s loc_176E2 move.w #$A00,x_vel(a0) bra.w loc_177FA ; =========================================================================== loc_176E2: move.w #$38,d3 tst.w d0 bmi.s loc_176EE move.w #$48,d3 loc_176EE: bsr.w loc_175EA bra.w loc_177FA ; =========================================================================== loc_176F6: move.w bumper_y(a1),d0 sub.w y_pos(a0),d0 cmpi.w #8,d0 blt.s loc_1770E move.w #-$A00,y_vel(a0) bra.w loc_177FA ; =========================================================================== loc_1770E: move.w bumper_x(a1),d0 sub.w x_pos(a0),d0 cmpi.w #$40,d0 blt.s loc_17726 move.w #-$A00,x_vel(a0) bra.w loc_177FA ; =========================================================================== loc_17726: neg.w d0 cmpi.w #$40,d0 blt.s loc_17738 move.w #$A00,x_vel(a0) bra.w loc_177FA ; =========================================================================== loc_17738: move.w #$C8,d3 tst.w d0 bmi.s loc_17744 move.w #$B8,d3 loc_17744: bsr.w loc_175EA bra.w loc_177FA ; =========================================================================== loc_1774C: move.w bumper_x(a1),d0 sub.w x_pos(a0),d0 neg.w d0 cmpi.w #8,d0 blt.s loc_17766 move.w #$A00,x_vel(a0) bra.w loc_177FA ; =========================================================================== loc_17766: move.w bumper_y(a1),d0 sub.w y_pos(a0),d0 cmpi.w #$40,d0 blt.s loc_1777E move.w #-$A00,y_vel(a0) bra.w loc_177FA ; =========================================================================== loc_1777E: neg.w d0 cmpi.w #$40,d0 blt.s loc_17790 move.w #$A00,x_vel(a0) bra.w loc_177FA ; =========================================================================== loc_17790: move.w #8,d3 tst.w d0 bmi.s loc_1779C move.w #$F8,d3 loc_1779C: bsr.w loc_175EA bra.w loc_177FA ; =========================================================================== loc_177A4: move.w bumper_x(a1),d0 sub.w x_pos(a0),d0 cmpi.w #8,d0 blt.s loc_177BC move.w #$A00,x_vel(a0) bra.w loc_177FA ; =========================================================================== loc_177BC: move.w bumper_y(a1),d0 sub.w y_pos(a0),d0 cmpi.w #$40,d0 blt.s loc_177D4 move.w #-$A00,y_vel(a0) bra.w loc_177FA ; =========================================================================== loc_177D4: neg.w d0 cmpi.w #$40,d0 blt.s loc_177E6 move.w #$A00,x_vel(a0) bra.w loc_177FA ; =========================================================================== loc_177E6: move.w #$78,d3 tst.w d0 bmi.s loc_177F2 move.w #$88,d3 loc_177F2: bsr.w loc_175EA bra.w loc_177FA loc_177FA: bset #1,status(a0) bclr #4,status(a0) bclr #5,status(a0) clr.b jumping(a0) move.w #SndID_LargeBumper,d0 jmp (PlaySound).l ; =========================================================================== SpecialCNZBumpers_Act1: BINCLUDE "level/objects/CNZ 1 bumpers.bin" ; byte_1781A SpecialCNZBumpers_Act2: BINCLUDE "level/objects/CNZ 2 bumpers.bin" ; byte_1795E ; =========================================================================== if gameRevision<2 nop endif ; =========================================================================== ; --------------------------------------------------------------------------- ; Objects Manager ; Subroutine that keeps track of any objects that need to remember ; their state, such as monitors or enemies. ; ; input variables: ; -none- ; ; writes: ; d0, d1 ; d2 = respawn index of object to load ; d6 = camera position ; ; a0 = address in object placement list ; a2 = respawn table ; --------------------------------------------------------------------------- ; loc_17AA4 ObjectsManager: moveq #0,d0 move.b (Obj_placement_routine).w,d0 move.w ObjectsManager_States(pc,d0.w),d0 jmp ObjectsManager_States(pc,d0.w) ; =========================================================================== ObjectsManager_States: offsetTable offsetTableEntry.w ObjectsManager_Init ; 0 offsetTableEntry.w ObjectsManager_Main ; 2 offsetTableEntry.w ObjectsManager_2P_Main ; 4 ; =========================================================================== ; loc_17AB8 ObjectsManager_Init: addq.b #2,(Obj_placement_routine).w move.w (Current_ZoneAndAct).w,d0 ; If level == $0F01 (ARZ 2)... ror.b #1,d0 ; then this yields $0F80... lsr.w #6,d0 ; and this yields $003E. lea (Off_Objects).l,a0 ; Next, we load the first pointer in the object layout list pointer index, movea.l a0,a1 ; then copy it for quicker use later. adda.w (a0,d0.w),a0 ; (Point1 * 2) + $003E tst.w (Two_player_mode).w ; skip if not in 2-player vs mode beq.s + cmpi.b #casino_night_zone,(Current_Zone).w ; skip if not Casino Night Zone bne.s + lea (Objects_CNZ1_2P).l,a0 ; CNZ 1 2-player object layout tst.b (Current_Act).w ; skip if not past act 1 beq.s + lea (Objects_CNZ2_2P).l,a0 ; CNZ 2 2-player object layout + ; initialize each object load address with the first object in the layout move.l a0,(Obj_load_addr_right).w move.l a0,(Obj_load_addr_left).w move.l a0,(Obj_load_addr_2).w move.l a0,(Obj_load_addr_3).w lea (Object_Respawn_Table).w,a2 move.w #$101,(a2)+ ; the first two bytes are not used as respawn values ; instead, they are used to keep track of the current respawn indexes ; Bug: The '+7E' shouldn't be here; this loop accidentally clears an additional $7E bytes move.w #bytesToLcnt(Obj_respawn_data_End-Obj_respawn_data+$7E),d0 ; set loop counter - clr.l (a2)+ ; loop clears all other respawn values dbf d0,- lea (Obj_respawn_index).w,a2 ; reset a2 moveq #0,d2 move.w (Camera_X_pos).w,d6 subi.w #$80,d6 ; look one chunk to the left bcc.s + ; if the result was negative, moveq #0,d6 ; cap at zero + andi.w #$FF80,d6 ; limit to increments of $80 (width of a chunk) movea.l (Obj_load_addr_right).w,a0 ; load address of object placement list - ; at the beginning of a level this gives respawn table entries to any object that is one chunk ; behind the left edge of the screen that needs to remember its state (Monitors, Badniks, etc.) cmp.w (a0),d6 ; is object's x position >= d6? bls.s loc_17B3E ; if yes, branch tst.b 2(a0) ; does the object get a respawn table entry? bpl.s + ; if not, branch move.b (a2),d2 addq.b #1,(a2) ; respawn index of next object to the right + addq.w #6,a0 ; next object bra.s - ; --------------------------------------------------------------------------- loc_17B3E: move.l a0,(Obj_load_addr_right).w ; remember rightmost object that has been processed, so far (we still need to look forward) move.l a0,(Obj_load_addr_2).w movea.l (Obj_load_addr_left).w,a0 ; reset a0 subi.w #$80,d6 ; look even farther left (any object behind this is out of range) bcs.s loc_17B62 ; branch, if camera position would be behind level's left boundary - ; count how many objects are behind the screen that are not in range and need to remember their state cmp.w (a0),d6 ; is object's x position >= d6? bls.s loc_17B62 ; if yes, branch tst.b 2(a0) ; does the object get a respawn table entry? bpl.s + ; if not, branch addq.b #1,1(a2) ; respawn index of current object to the left + addq.w #6,a0 bra.s - ; continue with next object ; --------------------------------------------------------------------------- loc_17B62: move.l a0,(Obj_load_addr_left).w ; remember current object from the left move.l a0,(Obj_load_addr_3).w move.w #-1,(Camera_X_pos_last).w ; make sure ObjectsManager_GoingForward is run move.w #-1,(Camera_X_pos_last_P2).w tst.w (Two_player_mode).w ; is it two player mode? beq.s ObjectsManager_Main ; if not, branch addq.b #2,(Obj_placement_routine).w bra.w ObjectsManager_2P_Init ; --------------------------------------------------------------------------- ; loc_17B84 ObjectsManager_Main: move.w (Camera_X_pos).w,d1 subi.w #$80,d1 andi.w #$FF80,d1 move.w d1,(Camera_X_pos_coarse).w lea (Obj_respawn_index).w,a2 moveq #0,d2 move.w (Camera_X_pos).w,d6 andi.w #$FF80,d6 cmp.w (Camera_X_pos_last).w,d6 ; is the X range the same as last time? beq.w ObjectsManager_SameXRange ; if yes, branch (rts) bge.s ObjectsManager_GoingForward ; if new pos is greater than old pos, branch ; if the player is moving back move.w d6,(Camera_X_pos_last).w ; remember current position for next time movea.l (Obj_load_addr_left).w,a0 ; get current object from the left subi.w #$80,d6 ; look one chunk to the left bcs.s loc_17BE6 ; branch, if camera position would be behind level's left boundary - ; load all objects left of the screen that are now in range cmp.w -6(a0),d6 ; is the previous object's X pos less than d6? bge.s loc_17BE6 ; if it is, branch subq.w #6,a0 ; get object's address tst.b 2(a0) ; does the object get a respawn table entry? bpl.s + ; if not, branch subq.b #1,1(a2) ; respawn index of this object move.b 1(a2),d2 + bsr.w ChkLoadObj ; load object bne.s + ; branch, if SST is full subq.w #6,a0 bra.s - ; continue with previous object ; --------------------------------------------------------------------------- + ; undo a few things, if the object couldn't load tst.b 2(a0) ; does the object get a respawn table entry? bpl.s + ; if not, branch addq.b #1,1(a2) ; since we didn't load the object, undo last change + addq.w #6,a0 ; go back to last object loc_17BE6: move.l a0,(Obj_load_addr_left).w ; remember current object from the left movea.l (Obj_load_addr_right).w,a0 ; get next object from the right addi.w #$300,d6 ; look two chunks beyond the right edge of the screen - ; subtract number of objects that have been moved out of range (from the right side) cmp.w -6(a0),d6 ; is the previous object's X pos less than d6? bgt.s loc_17C04 ; if it is, branch tst.b -4(a0) ; does the previous object get a respawn table entry? bpl.s + ; if not, branch subq.b #1,(a2) ; respawn index of next object to the right + subq.w #6,a0 bra.s - ; continue with previous object ; --------------------------------------------------------------------------- loc_17C04: move.l a0,(Obj_load_addr_right).w ; remember next object from the right rts ; --------------------------------------------------------------------------- ObjectsManager_GoingForward: move.w d6,(Camera_X_pos_last).w movea.l (Obj_load_addr_right).w,a0 ; get next object from the right addi.w #$280,d6 ; look two chunks forward - ; load all objects right of the screen that are now in range cmp.w (a0),d6 ; is object's x position >= d6? bls.s loc_17C2A ; if yes, branch tst.b 2(a0) ; does the object get a respawn table entry? bpl.s + ; if not, branch move.b (a2),d2 ; respawn index of this object addq.b #1,(a2) ; respawn index of next object to the right + bsr.w ChkLoadObj ; load object (and get address of next object) beq.s - ; continue loading objects, if the SST isn't full loc_17C2A: move.l a0,(Obj_load_addr_right).w ; remember next object from the right movea.l (Obj_load_addr_left).w,a0 ; get current object from the left subi.w #$300,d6 ; look one chunk behind the left edge of the screen bcs.s loc_17C4A ; branch, if camera position would be behind level's left boundary - ; subtract number of objects that have been moved out of range (from the left) cmp.w (a0),d6 ; is object's x position >= d6? bls.s loc_17C4A ; if yes, branch tst.b 2(a0) ; does the object get a respawn table entry? bpl.s + ; if not, branch addq.b #1,1(a2) ; respawn index of next object to the left + addq.w #6,a0 bra.s - ; continue with previous object ; --------------------------------------------------------------------------- loc_17C4A: move.l a0,(Obj_load_addr_left).w ; remember current object from the left ObjectsManager_SameXRange: rts ; --------------------------------------------------------------------------- ; loc_17C50 ObjectsManager_2P_Init: moveq #-1,d0 move.l d0,(unk_F780).w move.l d0,(unk_F780+4).w move.l d0,(unk_F780+8).w move.l d0,(Camera_X_pos_last_P2).w ; both words that this sets to -1 are overwritten directly underneath, so this line is rather pointless... move.w #0,(Camera_X_pos_last).w move.w #0,(Camera_X_pos_last_P2).w lea (Obj_respawn_index).w,a2 move.w (a2),(Obj_respawn_index_P2).w ; mirrior first two bytes (respawn indices) for player 2(?) moveq #0,d2 ; run initialization for player 1 lea (Obj_respawn_index).w,a5 lea (Obj_load_addr_right).w,a4 lea (unk_F786).w,a1 ; = -1, -1, -1 lea (unk_F789).w,a6 ; = -1, -1, -1 moveq #-2,d6 bsr.w ObjMan2P_GoingForward lea (unk_F786).w,a1 moveq #-1,d6 bsr.w ObjMan2P_GoingForward lea (unk_F786).w,a1 moveq #0,d6 bsr.w ObjMan2P_GoingForward ; run initialization for player 2 lea (Obj_respawn_index_P2).w,a5 lea (Obj_load_addr_2).w,a4 lea (unk_F789).w,a1 lea (unk_F786).w,a6 moveq #-2,d6 bsr.w ObjMan2P_GoingForward lea (unk_F789).w,a1 moveq #-1,d6 bsr.w ObjMan2P_GoingForward lea (unk_F789).w,a1 moveq #0,d6 bsr.w ObjMan2P_GoingForward ; loc_17CCC ObjectsManager_2P_Main: move.w (Camera_X_pos).w,d1 andi.w #$FF00,d1 move.w d1,(Camera_X_pos_coarse).w move.w (Camera_X_pos_P2).w,d1 andi.w #$FF00,d1 move.w d1,(Camera_X_pos_coarse_P2).w move.b (Camera_X_pos).w,d6 ; get upper byte of camera positon andi.w #$FF,d6 move.w (Camera_X_pos_last).w,d0 cmp.w (Camera_X_pos_last).w,d6 ; is the X range the same as last time? beq.s + ; if yes, branch move.w d6,(Camera_X_pos_last).w ; remember current position for next time lea (Obj_respawn_index).w,a5 lea (Obj_load_addr_right).w,a4 lea (unk_F786).w,a1 lea (unk_F789).w,a6 bsr.s ObjectsManager_2P_Run + move.b (Camera_X_pos_P2).w,d6 ; get upper byte of camera positon andi.w #$FF,d6 move.w (Camera_X_pos_last_P2).w,d0 cmp.w (Camera_X_pos_last_P2).w,d6 ; is the X range the same as last time? beq.s return_17D34 ; if yes, branch (rts) move.w d6,(Camera_X_pos_last_P2).w lea (Obj_respawn_index_P2).w,a5 lea (Obj_load_addr_2).w,a4 lea (unk_F789).w,a1 lea (unk_F786).w,a6 bsr.s ObjectsManager_2P_Run return_17D34: rts ; =========================================================================== ObjectsManager_2P_Run: lea (Obj_respawn_index).w,a2 moveq #0,d2 cmp.w d0,d6 ; is the X range the same as last time? beq.w ObjectsManager_SameXRange ; if yes, branch (rts) bge.w ObjMan2P_GoingForward ; if new pos is greater than old pos, branch ; if the player is moving back move.b 2(a1),d2 move.b 1(a1),2(a1) move.b (a1),1(a1) move.b d6,(a1) cmp.b (a6),d2 beq.s + cmp.b 1(a6),d2 beq.s + cmp.b 2(a6),d2 beq.s + bsr.w ObjectsManager_2P_UnkSub3 bra.s loc_17D70 ; --------------------------------------------------------------------------- + bsr.w ObjMan_2P_UnkSub2 loc_17D70: bsr.w ObjMan_2P_UnkSub1 bne.s loc_17D94 ; if whatever checks were just performed were all not equal, branch movea.l 4(a4),a0 - cmp.b -6(a0),d6 bne.s loc_17D8E tst.b -4(a0) bpl.s + subq.b #1,1(a5) + subq.w #6,a0 bra.s - ; --------------------------------------------------------------------------- loc_17D8E: move.l a0,4(a4) bra.s loc_17DCA ; --------------------------------------------------------------------------- loc_17D94: movea.l 4(a4),a0 move.b d6,(a1) - cmp.b -6(a0),d6 bne.s loc_17DC6 subq.w #6,a0 tst.b 2(a0) bpl.s + subq.b #1,1(a5) move.b 1(a5),d2 + bsr.w ChkLoadObj_2P bne.s loc_17DBA subq.w #6,a0 bra.s - ; --------------------------------------------------------------------------- loc_17DBA: tst.b 2(a0) bpl.s + addq.b #1,1(a5) + addq.w #6,a0 loc_17DC6: move.l a0,4(a4) loc_17DCA: movea.l (a4),a0 addq.w #3,d6 - cmp.b -6(a0),d6 bne.s loc_17DE0 tst.b -4(a0) bpl.s + subq.b #1,(a5) + subq.w #6,a0 bra.s - ; --------------------------------------------------------------------------- loc_17DE0: move.l a0,(a4) rts ; =========================================================================== ;loc_17DE4: ObjMan2P_GoingForward: addq.w #2,d6 ; look forward two chunks move.b (a1),d2 ; shift positions in array left once move.b 1(a1),(a1) ; nearest chunk to the right move.b 2(a1),1(a1) ; middle chunk to the right move.b d6,2(a1) ; farthest chunk to the right cmp.b (a6),d2 ; compare farthset distance beq.s + cmp.b 1(a6),d2 beq.s + cmp.b 2(a6),d2 beq.s + bsr.w ObjectsManager_2P_UnkSub3 ; if not, run this sub-routine bra.s loc_17E10 ; --------------------------------------------------------------------------- + bsr.w ObjMan_2P_UnkSub2 loc_17E10: bsr.w ObjMan_2P_UnkSub1 bne.s loc_17E2C ; if whatever checks were just performed were all not equal, branch movea.l (a4),a0 - cmp.b (a0),d6 bne.s loc_17E28 tst.b 2(a0) ; does the object get a respawn table entry? bpl.s + ; if not, branch addq.b #1,(a5) + addq.w #6,a0 bra.s - ; =========================================================================== loc_17E28: move.l a0,(a4) bra.s loc_17E46 ; =========================================================================== loc_17E2C: movea.l (a4),a0 move.b d6,(a1) - cmp.b (a0),d6 bne.s loc_17E44 tst.b 2(a0) ; does the object get a respawn table entry? bpl.s + ; if not, branch move.b (a5),d2 addq.b #1,(a5) + bsr.w ChkLoadObj_2P beq.s - loc_17E44: move.l a0,(a4) loc_17E46: movea.l 4(a4),a0 subq.w #3,d6 bcs.s loc_17E60 loc_17E4E: cmp.b (a0),d6 bne.s loc_17E60 tst.b 2(a0) bpl.s loc_17E5C addq.b #1,1(a5) loc_17E5C: addq.w #6,a0 bra.s loc_17E4E ; =========================================================================== loc_17E60: move.l a0,4(a4) rts ; =========================================================================== ;loc_17E66: ObjMan_2P_UnkSub1: move.l a1,-(sp) lea (unk_F780).w,a1 cmp.b (a1)+,d6 beq.s + cmp.b (a1)+,d6 beq.s + cmp.b (a1)+,d6 beq.s + cmp.b (a1)+,d6 beq.s + cmp.b (a1)+,d6 beq.s + cmp.b (a1)+,d6 beq.s + moveq #1,d0 + movea.l (sp)+,a1 rts ; =========================================================================== ;loc_17E8A: ObjMan_2P_UnkSub2: lea (unk_F780).w,a1 lea (Dynamic_Object_RAM_2P_End).w,a3 tst.b (a1)+ bmi.s + lea (Dynamic_Object_RAM_2P_End+$C*object_size).w,a3 tst.b (a1)+ bmi.s + lea (Dynamic_Object_RAM_2P_End+$18*object_size).w,a3 tst.b (a1)+ bmi.s + lea (Dynamic_Object_RAM_2P_End+$24*object_size).w,a3 tst.b (a1)+ bmi.s + lea (Dynamic_Object_RAM_2P_End+$30*object_size).w,a3 tst.b (a1)+ bmi.s + lea (Dynamic_Object_RAM_2P_End+$3C*object_size).w,a3 tst.b (a1)+ bmi.s + nop nop + subq.w #1,a1 rts ; =========================================================================== ; this sub-routine appears to determine which 12 byte block of object RAM ; corresponds to the current out-of-range camera positon (in d2) and deletes ; the objects in this block. This most likely takes over the functionality ; of markObjGone, as that routine isn't called in two player mode. ;loc_17EC6: ObjectsManager_2P_UnkSub3: lea (unk_F780).w,a1 lea (Dynamic_Object_RAM_2P_End).w,a3 cmp.b (a1)+,d2 beq.s + lea (Dynamic_Object_RAM_2P_End+$C*object_size).w,a3 cmp.b (a1)+,d2 beq.s + lea (Dynamic_Object_RAM_2P_End+$18*object_size).w,a3 cmp.b (a1)+,d2 beq.s + lea (Dynamic_Object_RAM_2P_End+$24*object_size).w,a3 cmp.b (a1)+,d2 beq.s + lea (Dynamic_Object_RAM_2P_End+$30*object_size).w,a3 cmp.b (a1)+,d2 beq.s + lea (Dynamic_Object_RAM_2P_End+$3C*object_size).w,a3 cmp.b (a1)+,d2 beq.s + nop nop + move.b #-1,-(a1) movem.l a1/a3,-(sp) moveq #0,d1 ; used later to delete objects moveq #$C-1,d2 ;loc_17F0A: ObjMan2P_UnkSub3_DeleteBlockLoop: tst.b (a3) beq.s ObjMan2P_UnkSub3_DeleteBlock_SkipObj ; branch if slot is empty movea.l a3,a1 moveq #0,d0 move.b respawn_index(a1),d0 ; does object remember its state? beq.s + ; if not, branch bclr #7,2(a2,d0.w) ; else, clear entry in respawn table ; inlined DeleteObject2: + moveq #bytesToLcnt(next_object),d0 ; we want to clear up to the next object ; note: d1 is already 0 ; delete the object by setting all of its bytes to 0 - move.l d1,(a1)+ dbf d0,- if object_size&3 move.w d1,(a1)+ endif ;loc_17F26: ObjMan2P_UnkSub3_DeleteBlock_SkipObj: lea next_object(a3),a3 ; a3=object dbf d2,ObjMan2P_UnkSub3_DeleteBlockLoop moveq #0,d2 movem.l (sp)+,a1/a3 rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to check if an object needs to be loaded. ; ; input variables: ; d2 = respawn index of object to be loaded ; ; a0 = address in object placement list ; a2 = object respawn table ; ; writes: ; d0, d1 ; a1 = object ; --------------------------------------------------------------------------- ;loc_17F36: ChkLoadObj: tst.b 2(a0) ; does the object get a respawn table entry? bpl.s + ; if not, branch bset #7,2(a2,d2.w) ; mark object as loaded beq.s + ; branch if it wasn't already loaded addq.w #6,a0 ; next object moveq #0,d0 ; let the objects manager know that it can keep going rts ; --------------------------------------------------------------------------- + bsr.w SingleObjLoad ; find empty slot bne.s return_17F7E ; branch, if there is no room left in the SST move.w (a0)+,x_pos(a1) move.w (a0)+,d0 ; there are three things stored in this word bpl.s + ; branch, if the object doesn't get a respawn table entry move.b d2,respawn_index(a1) + move.w d0,d1 ; copy for later andi.w #$FFF,d0 ; get y-position move.w d0,y_pos(a1) rol.w #3,d1 ; adjust bits andi.b #3,d1 ; get render flags move.b d1,render_flags(a1) move.b d1,status(a1) _move.b (a0)+,id(a1) ; load obj move.b (a0)+,subtype(a1) moveq #0,d0 return_17F7E: rts ; =========================================================================== ;loc_17F80: ChkLoadObj_2P: tst.b 2(a0) ; does the object get a respawn table entry? bpl.s + ; if not, branch bset #7,2(a2,d2.w) ; mark object as loaded beq.s + ; branch if it wasn't already loaded addq.w #6,a0 ; next object moveq #0,d0 ; let the objects manager know that it can keep going rts ; --------------------------------------------------------------------------- + btst #4,2(a0) ; the bit that's being tested for here should always be zero, beq.s + ; but assuming it weren't and this branch isn't taken, bsr.w SingleObjLoad ; then this object would not be loaded into one of the 12 bne.s return_17FD8 ; byte blocks after Dynamic_Object_RAM_2P_End and would most bra.s ChkLoadObj_2P_LoadData ; likely end up somwhere before this in Dynamic_Object_RAM ; --------------------------------------------------------------------------- + bsr.w SingleObjLoad3 ; find empty slot in current 12 object block bne.s return_17FD8 ; branch, if there is no room left in this block ;loc_17FAA: ChkLoadObj_2P_LoadData: move.w (a0)+,x_pos(a1) move.w (a0)+,d0 ; there are three things stored in this word bpl.s + ; branch, if the object doesn't get a respawn table entry move.b d2,respawn_index(a1) + move.w d0,d1 ; copy for later andi.w #$FFF,d0 ; get y-position move.w d0,y_pos(a1) rol.w #3,d1 ; adjust bits andi.b #3,d1 ; get render flags move.b d1,render_flags(a1) move.b d1,status(a1) _move.b (a0)+,id(a1) ; load obj move.b (a0)+,subtype(a1) moveq #0,d0 return_17FD8: rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Single object loading subroutine ; Find an empty object array ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_17FDA: ; allocObject: SingleObjLoad: lea (Dynamic_Object_RAM).w,a1 ; a1=object move.w #(Dynamic_Object_RAM_End-Dynamic_Object_RAM)/object_size-1,d0 ; search to end of table tst.w (Two_player_mode).w beq.s + move.w #(Dynamic_Object_RAM_2P_End-Dynamic_Object_RAM)/object_size-1,d0 ; search to $BF00 exclusive / tst.b id(a1) ; is object RAM slot empty? beq.s return_17FF8 ; if yes, branch lea next_object(a1),a1 ; load obj address ; goto next object RAM slot dbf d0,- ; repeat until end return_17FF8: rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Single object loading subroutine ; Find an empty object array AFTER the current one in the table ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_17FFA: ; allocObjectAfterCurrent: SingleObjLoad2: movea.l a0,a1 move.w #Dynamic_Object_RAM_End,d0 ; $D000 sub.w a0,d0 ; subtract current object location if object_size=$40 lsr.w #6,d0 ; divide by $40 else divu.w #object_size,d0 endif subq.w #1,d0 ; keep from going over the object zone bcs.s return_18014 - tst.b id(a1) ; is object RAM slot empty? beq.s return_18014 ; if yes, branch lea next_object(a1),a1 ; load obj address ; goto next object RAM slot dbf d0,- ; repeat until end return_18014: rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Single object loading subroutine ; Find an empty object at or within < 12 slots after a3 ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_18016: SingleObjLoad3: movea.l a3,a1 move.w #$B,d0 - tst.b id(a1) ; is object RAM slot empty? beq.s return_18028 ; if yes, branch lea next_object(a1),a1 ; load obj address ; goto next object RAM slot dbf d0,- ; repeat until end return_18028: rts ; =========================================================================== ;--------------------------------------------------------------------------------------- ; CNZ act 1 object layout for 2-player mode (various objects were deleted) ;--------------------------------------------------------------------------------------- ; byte_1802A; if gameRevision=0 Objects_CNZ1_2P: BINCLUDE "level/objects/CNZ_1_2P (REV00).bin" else ; a Crawl badnik was moved slightly further away from a ledge ; 2 flippers were moved closer to a wall Objects_CNZ1_2P: BINCLUDE "level/objects/CNZ_1_2P.bin" endif ;--------------------------------------------------------------------------------------- ; CNZ act 2 object layout for 2-player mode (various objects were deleted) ;--------------------------------------------------------------------------------------- ; byte_18492: if gameRevision=0 Objects_CNZ2_2P: BINCLUDE "level/objects/CNZ_2_2P (REV00).bin" else ; 4 Crawl badniks were slightly moved, placing them closer/farther away from ledges ; 2 flippers were moved away from a wall to keep players from getting stuck behind them Objects_CNZ2_2P: BINCLUDE "level/objects/CNZ_2_2P.bin" endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 41 - Spring ; ---------------------------------------------------------------------------- ; Sprite_18888: Obj41: moveq #0,d0 move.b routine(a0),d0 move.w Obj41_Index(pc,d0.w),d1 jsr Obj41_Index(pc,d1.w) jmp (MarkObjGone).l ; =========================================================================== ; off_1889C: Obj41_Index: offsetTable offsetTableEntry.w Obj41_Init ; 0 offsetTableEntry.w Obj41_Up ; 2 offsetTableEntry.w Obj41_Horizontal ; 4 offsetTableEntry.w Obj41_Down ; 6 offsetTableEntry.w Obj41_DiagonallyUp ; 8 offsetTableEntry.w Obj41_DiagonallyDown ; $A ; =========================================================================== ; loc_188A8: Obj41_Init: addq.b #2,routine(a0) move.l #Obj41_MapUnc_1901C,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #4,priority(a0) move.b subtype(a0),d0 lsr.w #3,d0 andi.w #$E,d0 move.w Obj41_Init_Subtypes(pc,d0.w),d0 jmp Obj41_Init_Subtypes(pc,d0.w) ; =========================================================================== ; off_188DE: Obj41_Init_Subtypes: offsetTable offsetTableEntry.w Obj41_Init_Up ; 0 offsetTableEntry.w Obj41_Init_Horizontal ; 2 offsetTableEntry.w Obj41_Init_Down ; 4 offsetTableEntry.w Obj41_Init_DiagonallyUp ; 6 offsetTableEntry.w Obj41_Init_DiagonallyDown ; 8 ; =========================================================================== ; loc_188E8: Obj41_Init_Horizontal: move.b #4,routine(a0) move.b #2,anim(a0) move.b #3,mapping_frame(a0) move.w #make_art_tile(ArtTile_ArtNem_HrzntlSprng,0,0),art_tile(a0) move.b #8,width_pixels(a0) bra.s Obj41_Init_Common ; =========================================================================== ; loc_18908: Obj41_Init_Down: move.b #6,routine(a0) move.b #6,mapping_frame(a0) bset #1,status(a0) bra.s Obj41_Init_Common ; =========================================================================== ; loc_1891C: Obj41_Init_DiagonallyUp: move.b #8,routine(a0) move.b #4,anim(a0) move.b #7,mapping_frame(a0) move.w #make_art_tile(ArtTile_ArtNem_DignlSprng,0,0),art_tile(a0) bra.s Obj41_Init_Common ; =========================================================================== ; loc_18936: Obj41_Init_DiagonallyDown: move.b #$A,routine(a0) move.b #4,anim(a0) move.b #$A,mapping_frame(a0) move.w #make_art_tile(ArtTile_ArtNem_DignlSprng,0,0),art_tile(a0) bset #1,status(a0) ; loc_18954: Obj41_Init_Up: Obj41_Init_Common: ; checks color of spring move.b subtype(a0),d0 andi.w #2,d0 move.w Obj41_Strengths(pc,d0.w),objoff_30(a0) btst #1,d0 beq.s + bset #palette_bit_0,art_tile(a0) move.l #Obj41_MapUnc_19032,mappings(a0) + bsr.w Adjust2PArtPointer rts ; =========================================================================== ; word_1897C: Obj41_Strengths: ; Speed applied on Sonic dc.w -$1000 dc.w -$A00 ; =========================================================================== ; loc_18980: Obj41_Up: move.w #$1B,d1 move.w #8,d2 move.w #$10,d3 move.w x_pos(a0),d4 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w SolidObject_Always_SingleCharacter btst #p1_standing_bit,status(a0) beq.s loc_189A8 bsr.s loc_189CA loc_189A8: movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 bsr.w SolidObject_Always_SingleCharacter btst #p2_standing_bit,status(a0) beq.s loc_189C0 bsr.s loc_189CA loc_189C0: lea (Ani_obj41).l,a1 bra.w AnimateSprite ; =========================================================================== loc_189CA: move.w #$100,anim(a0) addq.w #8,y_pos(a1) move.w objoff_30(a0),y_vel(a1) bset #1,status(a1) bclr #3,status(a1) move.b #AniIDSonAni_Spring,anim(a1) move.b #2,routine(a1) move.b subtype(a0),d0 bpl.s loc_189FE move.w #0,x_vel(a1) loc_189FE: btst #0,d0 beq.s loc_18A3E move.w #1,inertia(a1) move.b #1,flip_angle(a1) move.b #AniIDSonAni_Walk,anim(a1) move.b #0,flips_remaining(a1) move.b #4,flip_speed(a1) btst #1,d0 bne.s loc_18A2E move.b #1,flips_remaining(a1) loc_18A2E: btst #0,status(a1) beq.s loc_18A3E neg.b flip_angle(a1) neg.w inertia(a1) loc_18A3E: andi.b #$C,d0 cmpi.b #4,d0 bne.s loc_18A54 move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) loc_18A54: cmpi.b #8,d0 bne.s loc_18A66 move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_18A66: move.w #SndID_Spring,d0 jmp (PlaySound).l ; =========================================================================== ; loc_18A70: Obj41_Horizontal: move.w #$13,d1 move.w #$E,d2 move.w #$F,d3 move.w x_pos(a0),d4 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w SolidObject_Always_SingleCharacter btst #p1_pushing_bit,status(a0) beq.s loc_18AB0 move.b status(a0),d1 move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcs.s loc_18AA8 eori.b #1,d1 loc_18AA8: andi.b #1,d1 bne.s loc_18AB0 bsr.s loc_18AEE loc_18AB0: movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 bsr.w SolidObject_Always_SingleCharacter btst #p2_pushing_bit,status(a0) beq.s loc_18AE0 move.b status(a0),d1 move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcs.s loc_18AD8 eori.b #1,d1 loc_18AD8: andi.b #1,d1 bne.s loc_18AE0 bsr.s loc_18AEE loc_18AE0: bsr.w loc_18BC6 lea (Ani_obj41).l,a1 bra.w AnimateSprite ; =========================================================================== loc_18AEE: move.w #$300,anim(a0) move.w objoff_30(a0),x_vel(a1) addq.w #8,x_pos(a1) bset #0,status(a1) btst #0,status(a0) bne.s loc_18B1C bclr #0,status(a1) subi.w #$10,x_pos(a1) neg.w x_vel(a1) loc_18B1C: move.w #$F,move_lock(a1) move.w x_vel(a1),inertia(a1) btst #2,status(a1) bne.s loc_18B36 move.b #AniIDSonAni_Walk,anim(a1) loc_18B36: move.b subtype(a0),d0 bpl.s loc_18B42 move.w #0,y_vel(a1) loc_18B42: btst #0,d0 beq.s loc_18B82 move.w #1,inertia(a1) move.b #1,flip_angle(a1) move.b #AniIDSonAni_Walk,anim(a1) move.b #1,flips_remaining(a1) move.b #8,flip_speed(a1) btst #1,d0 bne.s loc_18B72 move.b #3,flips_remaining(a1) loc_18B72: btst #0,status(a1) beq.s loc_18B82 neg.b flip_angle(a1) neg.w inertia(a1) loc_18B82: andi.b #$C,d0 cmpi.b #4,d0 bne.s loc_18B98 move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) loc_18B98: cmpi.b #8,d0 bne.s loc_18BAA move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_18BAA: bclr #p1_pushing_bit,status(a0) bclr #p2_pushing_bit,status(a0) bclr #5,status(a1) move.w #SndID_Spring,d0 jmp (PlaySound).l ; =========================================================================== loc_18BC6: cmpi.b #3,anim(a0) beq.w return_18C7E move.w x_pos(a0),d0 move.w d0,d1 addi.w #$28,d1 btst #0,status(a0) beq.s loc_18BE8 move.w d0,d1 subi.w #$28,d0 loc_18BE8: move.w y_pos(a0),d2 move.w d2,d3 subi.w #$18,d2 addi.w #$18,d3 lea (MainCharacter).w,a1 ; a1=character btst #1,status(a1) bne.s loc_18C3C move.w inertia(a1),d4 btst #0,status(a0) beq.s loc_18C10 neg.w d4 loc_18C10: tst.w d4 bmi.s loc_18C3C move.w x_pos(a1),d4 cmp.w d0,d4 blo.w loc_18C3C cmp.w d1,d4 bhs.w loc_18C3C move.w y_pos(a1),d4 cmp.w d2,d4 blo.w loc_18C3C cmp.w d3,d4 bhs.w loc_18C3C move.w d0,-(sp) bsr.w loc_18AEE move.w (sp)+,d0 loc_18C3C: lea (Sidekick).w,a1 ; a1=character btst #1,status(a1) bne.s return_18C7E move.w inertia(a1),d4 btst #0,status(a0) beq.s loc_18C56 neg.w d4 loc_18C56: tst.w d4 bmi.s return_18C7E move.w x_pos(a1),d4 cmp.w d0,d4 blo.w return_18C7E cmp.w d1,d4 bhs.w return_18C7E move.w y_pos(a1),d4 cmp.w d2,d4 blo.w return_18C7E cmp.w d3,d4 bhs.w return_18C7E bsr.w loc_18AEE return_18C7E: rts ; =========================================================================== ; loc_18C80: Obj41_Down: move.w #$1B,d1 move.w #8,d2 move.w #$10,d3 move.w x_pos(a0),d4 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w SolidObject_Always_SingleCharacter cmpi.w #-2,d4 bne.s loc_18CA6 bsr.s loc_18CC6 loc_18CA6: movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 bsr.w SolidObject_Always_SingleCharacter cmpi.w #-2,d4 bne.s loc_18CBC bsr.s loc_18CC6 loc_18CBC: lea (Ani_obj41).l,a1 bra.w AnimateSprite ; =========================================================================== loc_18CC6: move.w #$100,anim(a0) subq.w #8,y_pos(a1) move.w objoff_30(a0),y_vel(a1) neg.w y_vel(a1) move.b subtype(a0),d0 bpl.s loc_18CE6 move.w #0,x_vel(a1) loc_18CE6: btst #0,d0 beq.s loc_18D26 move.w #1,inertia(a1) move.b #1,flip_angle(a1) move.b #AniIDSonAni_Walk,anim(a1) move.b #0,flips_remaining(a1) move.b #4,flip_speed(a1) btst #1,d0 bne.s loc_18D16 move.b #1,flips_remaining(a1) loc_18D16: btst #0,status(a1) beq.s loc_18D26 neg.b flip_angle(a1) neg.w inertia(a1) loc_18D26: andi.b #$C,d0 cmpi.b #4,d0 bne.s loc_18D3C move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) loc_18D3C: cmpi.b #8,d0 bne.s loc_18D4E move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_18D4E: bset #1,status(a1) bclr #3,status(a1) move.b #2,routine(a1) move.w #SndID_Spring,d0 jmp (PlaySound).l ; =========================================================================== ; loc_18D6A: Obj41_DiagonallyUp: move.w #$1B,d1 move.w #$10,d2 move.w x_pos(a0),d4 lea Obj41_SlopeData_DiagUp(pc),a2 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w SlopedSolid_SingleCharacter btst #p1_standing_bit,status(a0) beq.s loc_18D92 bsr.s loc_18DB4 loc_18D92: movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 bsr.w SlopedSolid_SingleCharacter btst #p2_standing_bit,status(a0) beq.s loc_18DAA bsr.s loc_18DB4 loc_18DAA: lea (Ani_obj41).l,a1 bra.w AnimateSprite ; =========================================================================== loc_18DB4: btst #0,status(a0) bne.s loc_18DCA move.w x_pos(a0),d0 subq.w #4,d0 cmp.w x_pos(a1),d0 blo.s loc_18DD8 rts ; =========================================================================== loc_18DCA: move.w x_pos(a0),d0 addq.w #4,d0 cmp.w x_pos(a1),d0 bhs.s loc_18DD8 rts ; =========================================================================== loc_18DD8: move.w #$500,anim(a0) move.w objoff_30(a0),y_vel(a1) move.w objoff_30(a0),x_vel(a1) addq.w #6,y_pos(a1) addq.w #6,x_pos(a1) bset #0,status(a1) btst #0,status(a0) bne.s loc_18E10 bclr #0,status(a1) subi.w #$C,x_pos(a1) neg.w x_vel(a1) loc_18E10: bset #1,status(a1) bclr #3,status(a1) move.b #AniIDSonAni_Spring,anim(a1) move.b #2,routine(a1) move.b subtype(a0),d0 btst #0,d0 beq.s loc_18E6C move.w #1,inertia(a1) move.b #1,flip_angle(a1) move.b #AniIDSonAni_Walk,anim(a1) move.b #1,flips_remaining(a1) move.b #8,flip_speed(a1) btst #1,d0 bne.s loc_18E5C move.b #3,flips_remaining(a1) loc_18E5C: btst #0,status(a1) beq.s loc_18E6C neg.b flip_angle(a1) neg.w inertia(a1) loc_18E6C: andi.b #$C,d0 cmpi.b #4,d0 bne.s loc_18E82 move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) loc_18E82: cmpi.b #8,d0 bne.s loc_18E94 move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_18E94: move.w #SndID_Spring,d0 jmp (PlaySound).l ; =========================================================================== ; loc_18E9E: Obj41_DiagonallyDown: move.w #$1B,d1 move.w #$10,d2 move.w x_pos(a0),d4 lea Obj41_SlopeData_DiagDown(pc),a2 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w SlopedSolid_SingleCharacter cmpi.w #-2,d4 bne.s loc_18EC4 bsr.s loc_18EE6 loc_18EC4: movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 bsr.w SlopedSolid_SingleCharacter cmpi.w #-2,d4 bne.s loc_18EDA bsr.s loc_18EE6 loc_18EDA: lea (Ani_obj41).l,a1 bra.w AnimateSprite ; =========================================================================== rts ; =========================================================================== loc_18EE6: move.w #$500,anim(a0) move.w objoff_30(a0),y_vel(a1) neg.w y_vel(a1) move.w objoff_30(a0),x_vel(a1) subq.w #6,y_pos(a1) addq.w #6,x_pos(a1) bset #0,status(a1) btst #0,status(a0) bne.s loc_18F22 bclr #0,status(a1) subi.w #$C,x_pos(a1) neg.w x_vel(a1) loc_18F22: bset #1,status(a1) bclr #3,status(a1) move.b #2,routine(a1) move.b subtype(a0),d0 btst #0,d0 beq.s loc_18F78 move.w #1,inertia(a1) move.b #1,flip_angle(a1) move.b #AniIDSonAni_Walk,anim(a1) move.b #1,flips_remaining(a1) move.b #8,flip_speed(a1) btst #1,d0 bne.s loc_18F68 move.b #3,flips_remaining(a1) loc_18F68: btst #0,status(a1) beq.s loc_18F78 neg.b flip_angle(a1) neg.w inertia(a1) loc_18F78: andi.b #$C,d0 cmpi.b #4,d0 bne.s loc_18F8E move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) loc_18F8E: cmpi.b #8,d0 bne.s loc_18FA0 move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_18FA0: move.w #SndID_Spring,d0 jmp (PlaySound).l ; =========================================================================== ;byte_18FAA: Obj41_SlopeData_DiagUp: dc.b $10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10, $E, $C, $A, 8 dc.b 6, 4, 2, 0,$FE,$FC,$FC,$FC,$FC,$FC,$FC,$FC; 16 ;byte_18FC6: Obj41_SlopeData_DiagDown: dc.b $F4,$F0,$F0,$F0,$F0,$F0,$F0,$F0,$F0,$F0,$F0,$F0,$F2,$F4,$F6,$F8 dc.b $FA,$FC,$FE, 0, 2, 4, 4, 4, 4, 4, 4, 4; 16 ; animation script ; off_18FE2: Ani_obj41: offsetTable offsetTableEntry.w byte_18FEE ; 0 offsetTableEntry.w byte_18FF1 ; 1 offsetTableEntry.w byte_18FFD ; 2 offsetTableEntry.w byte_19000 ; 3 offsetTableEntry.w byte_1900C ; 4 offsetTableEntry.w byte_1900F ; 5 byte_18FEE: dc.b $F dc.b 0 ; 1 dc.b $FF ; 2 rev02even byte_18FF1: dc.b 0 dc.b 1 ; 1 dc.b 0 ; 2 dc.b 0 ; 3 dc.b 2 ; 4 dc.b 2 ; 5 dc.b 2 ; 6 dc.b 2 ; 7 dc.b 2 ; 8 dc.b 2 ; 9 dc.b $FD ; 10 dc.b 0 ; 11 rev02even byte_18FFD: dc.b $F dc.b 3 ; 1 dc.b $FF ; 2 rev02even byte_19000: dc.b 0 dc.b 4 ; 1 dc.b 3 ; 2 dc.b 3 ; 3 dc.b 5 ; 4 dc.b 5 ; 5 dc.b 5 ; 6 dc.b 5 ; 7 dc.b 5 ; 8 dc.b 5 ; 9 dc.b $FD ; 10 dc.b 2 ; 11 rev02even byte_1900C: dc.b $F dc.b 7 ; 1 dc.b $FF ; 2 rev02even byte_1900F: dc.b 0 dc.b 8 ; 1 dc.b 7 ; 2 dc.b 7 ; 3 dc.b 9 ; 4 dc.b 9 ; 5 dc.b 9 ; 6 dc.b 9 ; 7 dc.b 9 ; 8 dc.b 9 ; 9 dc.b $FD ; 10 dc.b 4 ; 11 even ; ---------------------------------------------------------------------------- ; Primary sprite mappings for springs ; ---------------------------------------------------------------------------- Obj41_MapUnc_1901C: offsetTable offsetTableEntry.w word_19048 ; 0 offsetTableEntry.w word_1905A ; 1 offsetTableEntry.w word_19064 ; 2 offsetTableEntry.w word_19076 ; 3 offsetTableEntry.w word_19088 ; 4 offsetTableEntry.w word_19092 ; 5 offsetTableEntry.w word_190A4 ; 6 offsetTableEntry.w word_190B6 ; 7 offsetTableEntry.w word_190D8 ; 8 offsetTableEntry.w word_190F2 ; 9 offsetTableEntry.w word_19114 ; $A ; ------------------------------------------------------------------------------- ; Secondary sprite mappings for springs ; merged with the above mappings; can't split to file in a useful way... ; ------------------------------------------------------------------------------- Obj41_MapUnc_19032: offsetTable offsetTableEntry.w word_19048 ; 0 offsetTableEntry.w word_1905A ; 1 offsetTableEntry.w word_19064 ; 2 offsetTableEntry.w word_19076 ; 3 offsetTableEntry.w word_19088 ; 4 offsetTableEntry.w word_19092 ; 5 offsetTableEntry.w word_190A4 ; 6 offsetTableEntry.w word_19136 ; 7 offsetTableEntry.w word_19158 ; 8 offsetTableEntry.w word_19172 ; 9 offsetTableEntry.w word_19194 ; $A word_19048: dc.w 2 dc.w $F00D, 0, 0,$FFF0 dc.w 5, 8, 4,$FFF8; 4 word_1905A: dc.w 1 dc.w $F80D, 0, 0,$FFF0 word_19064: dc.w 2 dc.w $E00D, 0, 0,$FFF0 dc.w $F007, $C, 6,$FFF8; 4 word_19076: dc.w 2 dc.w $F003, 0, 0, 0 dc.w $F801, 4, 2,$FFF8; 4 word_19088: dc.w 1 dc.w $F003, 0, 0,$FFF8 word_19092: dc.w 2 dc.w $F003, 0, 0, $10 dc.w $F809, 6, 3,$FFF8; 4 word_190A4: dc.w 2 dc.w $D,$1000,$1000,$FFF0 dc.w $F005,$1008,$1004,$FFF8; 4 word_190B6: dc.w 4 dc.w $F00D, 0, 0,$FFF0 dc.w 5, 8, 4, 0; 4 dc.w $FB05, $C, 6,$FFF6; 8 dc.w 5,$201C,$200E,$FFF0; 12 word_190D8: dc.w 3 dc.w $F60D, 0, 0,$FFEA dc.w $605, 8, 4,$FFFA; 4 dc.w 5,$201C,$200E,$FFF0; 8 word_190F2: dc.w 4 dc.w $E60D, 0, 0,$FFFB dc.w $F605, 8, 4, $B; 4 dc.w $F30B, $10, 8,$FFF6; 8 dc.w 5,$201C,$200E,$FFF0; 12 word_19114: dc.w 4 dc.w $D,$1000,$1000,$FFF0 dc.w $F005,$1008,$1004, 0; 4 dc.w $F505,$100C,$1006,$FFF6; 8 dc.w $F005,$301C,$300E,$FFF0; 12 word_19136: dc.w 4 dc.w $F00D, 0, 0,$FFF0 dc.w 5, 8, 4, 0; 4 dc.w $FB05, $C, 6,$FFF6; 8 dc.w 5, $1C, $E,$FFF0; 12 word_19158: dc.w 3 dc.w $F60D, 0, 0,$FFEA dc.w $605, 8, 4,$FFFA; 4 dc.w 5, $1C, $E,$FFF0; 8 word_19172: dc.w 4 dc.w $E60D, 0, 0,$FFFB dc.w $F605, 8, 4, $B; 4 dc.w $F30B, $10, 8,$FFF6; 8 dc.w 5, $1C, $E,$FFF0; 12 word_19194: dc.w 4 dc.w $D,$1000,$1000,$FFF0 dc.w $F005,$1008,$1004, 0; 4 dc.w $F505,$100C,$1006,$FFF6; 8 dc.w $F005,$101C,$100E,$FFF0; 12 ; =========================================================================== if gameRevision<2 nop endif ; ---------------------------------------------------------------------------- ; Object 0D - End of level sign post ; ---------------------------------------------------------------------------- ; OST: obj0D_spinframe = objoff_30 ; $30(a0) obj0D_sparkleframe = objoff_34 ; $34(a0) obj0D_finalanim = objoff_36 ; $36(a0) ; 4 if Tails only, 3 otherwise (determines what character to show) ; ---------------------------------------------------------------------------- Obj0D: moveq #0,d0 move.b routine(a0),d0 move.w Obj0D_Index(pc,d0.w),d1 jsr Obj0D_Index(pc,d1.w) lea (Ani_obj0D).l,a1 bsr.w AnimateSprite bsr.w PLCLoad_Signpost bra.w MarkObjGone ; =========================================================================== ; off_191D8: Obj_0D_subtbl: Obj0D_States: Obj0D_Index: offsetTable offsetTableEntry.w Obj0D_Init ; 0 offsetTableEntry.w Obj0D_Main ; 2 ; =========================================================================== ; loc_191DC: Obj_0D_sub_0: Obj0D_Init: tst.w (Two_player_mode).w beq.s loc_19208 move.l #Obj0D_MapUnc_19656,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_2p_Signpost,0,0),art_tile(a0) move.b #-1,(Signpost_prev_frame).w moveq #0,d1 move.w #$1020,d1 move.w #-$80,d4 moveq #0,d5 bsr.w loc_19564 bra.s loc_1922C ; --------------------------------------------------------------------------- loc_19208: cmpi.w #metropolis_zone_act_2,(Current_ZoneAndAct).w beq.s loc_1921E tst.b (Current_Act).w beq.s loc_1921E move.w #0,x_pos(a0) rts ; --------------------------------------------------------------------------- loc_1921E: move.l #Obj0D_MapUnc_195BE,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Signpost,0,0),art_tile(a0) loc_1922C: addq.b #2,routine(a0) ; => Obj0D_Main bsr.w Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$18,width_pixels(a0) move.b #4,priority(a0) move.w #$3C3C,(Loser_Time_Left).w ; loc_1924C: Obj_0D_sub_2: Obj0D_Main: tst.b (Update_HUD_timer).w beq.w loc_192D6 lea (MainCharacter).w,a1 ; a1=character move.w x_pos(a1),d0 sub.w x_pos(a0),d0 bcs.s loc_192D6 cmpi.w #$20,d0 bhs.s loc_192D6 move.w #SndID_Signpost,d0 jsr (PlayMusic).l ; play spinning sound clr.b (Update_HUD_timer).w move.w #1,anim(a0) move.w #0,obj0D_spinframe(a0) move.w (Camera_Max_X_pos).w,(Camera_Min_X_pos).w ; lock screen move.b #2,routine_secondary(a0) ; => Obj0D_Main_State2 cmpi.b #$C,(Loser_Time_Left).w bhi.s loc_192A0 move.w (Level_Music).w,d0 jsr (PlayMusic).l ; play zone music loc_192A0: tst.b obj0D_finalanim(a0) bne.w loc_19350 move.b #3,obj0D_finalanim(a0) cmpi.w #2,(Player_mode).w bne.s loc_192BC move.b #4,obj0D_finalanim(a0) loc_192BC: tst.w (Two_player_mode).w beq.w loc_19350 move.w #$3C3C,(Loser_Time_Left).w move.w #SndID_Signpost2P,d0 ; play different spinning sound jsr (PlaySound).l bra.s loc_19350 ; --------------------------------------------------------------------------- loc_192D6: tst.w (Two_player_mode).w beq.s loc_19350 tst.b (Update_HUD_timer_2P).w beq.s loc_19350 lea (Sidekick).w,a1 ; a1=character move.w x_pos(a1),d0 sub.w x_pos(a0),d0 bcs.s loc_19350 cmpi.w #$20,d0 bhs.s loc_19350 move.w #SndID_Signpost,d0 jsr (PlayMusic).l clr.b (Update_HUD_timer_2P).w move.w #1,anim(a0) move.w #0,obj0D_spinframe(a0) move.w (Tails_Max_X_pos).w,(Tails_Min_X_pos).w move.b #2,routine_secondary(a0) ; => Obj0D_Main_State2 cmpi.b #$C,(Loser_Time_Left).w bhi.s loc_1932E move.w (Level_Music).w,d0 jsr (PlayMusic).l loc_1932E: tst.b obj0D_finalanim(a0) bne.s loc_19350 move.b #4,obj0D_finalanim(a0) tst.w (Two_player_mode).w beq.s loc_19350 move.w #$3C3C,(Loser_Time_Left).w move.w #SndID_Signpost2P,d0 jsr (PlaySound).l loc_19350: moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj0D_Main_States(pc,d0.w),d1 jmp Obj0D_Main_States(pc,d1.w) ; =========================================================================== Obj0D_Main_States: offsetTable offsetTableEntry.w Obj0D_Main_StateNull ; 0 offsetTableEntry.w Obj0D_Main_State2 ; 2 offsetTableEntry.w Obj0D_Main_State3 ; 4 offsetTableEntry.w Obj0D_Main_State4 ; 6 ; =========================================================================== ; return_19366: Obj0D_Main_StateNull: rts ; =========================================================================== ; loc_19368: Obj0D_Main_State2: subq.w #1,obj0D_spinframe(a0) bpl.s loc_19398 move.w #$3C,obj0D_spinframe(a0) addq.b #1,anim(a0) cmpi.b #3,anim(a0) bne.s loc_19398 move.b #4,routine_secondary(a0) ; => Obj0D_Main_State3 move.b obj0D_finalanim(a0),anim(a0) tst.w (Two_player_mode).w beq.s loc_19398 move.b #6,routine_secondary(a0) ; => Obj0D_Main_State4 loc_19398: subq.w #1,objoff_32(a0) bpl.s return_19406 move.w #$B,objoff_32(a0) moveq #0,d0 move.b obj0D_sparkleframe(a0),d0 addq.b #2,obj0D_sparkleframe(a0) andi.b #$E,obj0D_sparkleframe(a0) lea Obj0D_RingSparklePositions(pc,d0.w),a2 bsr.w SingleObjLoad bne.s return_19406 _move.b #ObjID_Ring,id(a1) ; load obj25 (a ring) for the sparkly effects over the signpost move.b #6,routine(a1) ; => Obj_25_sub_6 move.b (a2)+,d0 ext.w d0 add.w x_pos(a0),d0 move.w d0,x_pos(a1) move.b (a2)+,d0 ext.w d0 add.w y_pos(a0),d0 move.w d0,y_pos(a1) move.l #Obj25_MapUnc_12382,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_Ring,1,0),art_tile(a1) bsr.w Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #2,priority(a1) move.b #8,width_pixels(a1) return_19406: rts ; =========================================================================== ; byte_19408: Obj0D_RingSparklePositions: dc.b -24,-16 ; 1 dc.b 8, 8 ; 3 dc.b -16, 0 ; 5 dc.b 24, -8 ; 7 dc.b 0, -8 ; 9 dc.b 16, 0 ; 11 dc.b -24, 8 ; 13 dc.b 24, 16 ; 15 ; =========================================================================== ; loc_19418: Obj0D_Main_State3: tst.w (Debug_placement_mode).w bne.w return_194D0 btst #1,(MainCharacter+status).w bne.s loc_19434 move.b #1,(Control_Locked).w move.w #(button_right_mask<<8)|0,(Ctrl_1_Logical).w loc_19434: tst.b (MainCharacter).w beq.s loc_1944C move.w (MainCharacter+x_pos).w,d0 move.w (Camera_Max_X_pos).w,d1 addi.w #$128,d1 cmp.w d1,d0 blo.w return_194D0 loc_1944C: move.b #0,routine_secondary(a0) ; => Obj0D_Main_StateNull ;loc_19452: Load_EndOfAct: lea (MainCharacter).w,a1 ; a1=character clr.b status_secondary(a1) clr.b (Update_HUD_timer).w bsr.w SingleObjLoad bne.s + move.b #ObjID_Results,id(a1) ; load obj3A (end of level results screen) + moveq #PLCID_Results,d0 cmpi.w #2,(Player_mode).w bne.s + moveq #PLCID_ResultsTails,d0 + jsr (LoadPLC2).l move.b #1,(Update_Bonus_score).w moveq #0,d0 move.b (Timer_minute).w,d0 mulu.w #$3C,d0 moveq #0,d1 move.b (Timer_second).w,d1 add.w d1,d0 divu.w #$F,d0 moveq #$14,d1 cmp.w d1,d0 blo.s + move.w d1,d0 + add.w d0,d0 move.w TimeBonuses(pc,d0.w),(Bonus_Countdown_1).w move.w (Ring_count).w,d0 mulu.w #$A,d0 move.w d0,(Bonus_Countdown_2).w clr.w (Total_Bonus_Countdown).w clr.w (Bonus_Countdown_3).w tst.w (Perfect_rings_left).w bne.s + move.w #5000,(Bonus_Countdown_3).w + move.w #MusID_EndLevel,d0 jsr (PlayMusic).l return_194D0: rts ; =========================================================================== ; word_194D2: TimeBonuses: dc.w 5000, 5000, 1000, 500, 400, 400, 300, 300 dc.w 200, 200, 200, 200, 100, 100, 100, 100 dc.w 50, 50, 50, 50, 0 ; =========================================================================== ; loc_194FC: Obj0D_Main_State4: subq.w #1,obj0D_spinframe(a0) bpl.s return_19532 tst.b (Time_Over_flag).w bne.s return_19532 tst.b (Time_Over_flag_2P).w bne.s return_19532 tst.b (Update_HUD_timer).w bne.s return_19532 tst.b (Update_HUD_timer_2P).w bne.s return_19532 move.b #0,(Last_star_pole_hit).w move.b #0,(Last_star_pole_hit_2P).w move.b #GameModeID_2PResults,(Game_Mode).w ; => TwoPlayerResults move.w #VsRSID_Act,(Results_Screen_2P).w return_19532: rts ; =========================================================================== PLCLoad_Signpost: tst.w (Two_player_mode).w beq.s return_1958C moveq #0,d0 move.b mapping_frame(a0),d0 cmp.b (Signpost_prev_frame).w,d0 beq.s return_1958C move.b d0,(Signpost_prev_frame).w lea (Obj0D_MapRUnc_196EE).l,a2 add.w d0,d0 adda.w (a2,d0.w),a2 move.w (a2)+,d5 subq.w #1,d5 bmi.s return_1958C move.w #tiles_to_bytes(ArtTile_ArtUnc_Signpost),d4 loc_19560: moveq #0,d1 move.w (a2)+,d1 loc_19564: move.w d1,d3 lsr.w #8,d3 andi.w #$F0,d3 addi.w #$10,d3 andi.w #$FFF,d1 lsl.l #5,d1 addi.l #ArtUnc_Signpost,d1 move.w d4,d2 add.w d3,d4 add.w d3,d4 jsr (QueueDMATransfer).l dbf d5,loc_19560 return_1958C: rts ; =========================================================================== ; animation script ; off_1958E: Ani_obj0D: offsetTable offsetTableEntry.w byte_19598 ; 0 offsetTableEntry.w byte_1959B ; 1 offsetTableEntry.w byte_195A9 ; 2 offsetTableEntry.w byte_195B7 ; 3 offsetTableEntry.w byte_195BA ; 4 byte_19598: dc.b $0F, $02, $FF rev02even byte_1959B: dc.b $01, $02, $03, $04, $05, $01, $03, $04, $05, $00, $03, $04, $05, $FF rev02even byte_195A9: dc.b $01, $02, $03, $04, $05, $01, $03, $04, $05, $00, $03, $04, $05, $FF rev02even byte_195B7: dc.b $0F, $00, $FF rev02even byte_195BA: dc.b $0F, $01, $FF even ; ------------------------------------------------------------------------------- ; sprite mappings - Primary sprite table for object 0D (signpost) ; ------------------------------------------------------------------------------- ; SprTbl_0D_Primary: Obj0D_MapUnc_195BE: BINCLUDE "mappings/sprite/obj0D_a.bin" ; ------------------------------------------------------------------------------- ; sprite mappings - Secondary sprite table for object 0D (signpost) ; ------------------------------------------------------------------------------- ; SprTbl_0D_Scndary: Obj0D_MapUnc_19656: BINCLUDE "mappings/sprite/obj0D_b.bin" ; ------------------------------------------------------------------------------- ; dynamic pattern loading cues ; ------------------------------------------------------------------------------- Obj0D_MapRUnc_196EE: BINCLUDE "mappings/spriteDPLC/obj0D.bin" ; =========================================================================== if gameRevision<2 nop endif ; --------------------------------------------------------------------------- ; Solid object subroutines (includes spikes, blocks, rocks etc) ; These check collision of Sonic/Tails with objects on the screen ; ; input variables: ; d1 = object width ; d2 = object height / 2 (when jumping) ; d3 = object height / 2 (when walking) ; d4 = object x-axis position ; ; address registers: ; a0 = the object to check collision with ; a1 = sonic or tails (set inside these subroutines) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_19718: SolidObject: lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) ; store input registers bsr.s + ; first check collision with Sonic movem.l (sp)+,d1-d4 ; restore input registers lea (Sidekick).w,a1 ; a1=character ; now check collision with Tails tst.b render_flags(a1) bpl.w return_19776 ; return if no Tails addq.b #1,d6 + btst d6,status(a0) beq.w SolidObject_OnScreenTest move.w d1,d2 add.w d2,d2 btst #1,status(a1) bne.s loc_1975A move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_1975A cmp.w d2,d0 blo.s loc_1976E loc_1975A: bclr #3,status(a1) bset #1,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_1976E: move.w d4,d2 bsr.w MvSonicOnPtfm moveq #0,d4 return_19776: rts ; =========================================================================== ; there are a few slightly different SolidObject functions ; specialized for certain objects, in this case, obj74 and obj30 ; These check for solidity even if the object is off-screen ; loc_19778: SolidObject74_30: SolidObject_Always: lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s SolidObject_Always_SingleCharacter movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character addq.b #1,d6 ;loc_1978E: SolidObject_Always_SingleCharacter: btst d6,status(a0) beq.w SolidObject_cont move.w d1,d2 add.w d2,d2 btst #1,status(a1) bne.s loc_197B2 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_197B2 cmp.w d2,d0 blo.s loc_197C6 loc_197B2: bclr #3,status(a1) bset #1,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_197C6: move.w d4,d2 bsr.w MvSonicOnPtfm moveq #0,d4 rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to collide Sonic/Tails with the top of a sloped solid like diagonal springs ; --------------------------------------------------------------------------- ; ; input variables: ; d1 = object width ; d2 = object height / 2 (when jumping) ; d3 = object height / 2 (when walking) ; d4 = object x-axis position ; ; address registers: ; a0 = the object to check collision with ; a1 = sonic or tails (set inside these subroutines) ; a2 = height data for slope ; loc_197D0: SolidObject86_30: SlopedSolid: lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s SlopedSolid_SingleCharacter movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character addq.b #1,d6 ; this gets called from a few more places... ; loc_197E6: SolidObject_Simple: SlopedSolid_SingleCharacter: btst d6,status(a0) beq.w SlopedSolid_cont move.w d1,d2 add.w d2,d2 btst #1,status(a1) bne.s loc_1980A move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_1980A cmp.w d2,d0 blo.s loc_1981E loc_1980A: bclr #3,status(a1) bset #1,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_1981E: move.w d4,d2 bsr.w MvSonicOnSlope moveq #0,d4 rts ; =========================================================================== ; unused/dead code for some SolidObject check ; This is for a sloped object that is sloped at the top and at the bottom. ; SolidObject_Unk: loc_19828: ;DoubleSlopedSolid: ; a0=object lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s + movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character addq.b #1,d6 + btst d6,status(a0) beq.w DoubleSlopedSolid_cont move.w d1,d2 add.w d2,d2 btst #1,status(a1) bne.s loc_19862 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_19862 cmp.w d2,d0 blo.s loc_19876 loc_19862: bclr #3,status(a1) bset #1,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_19876: move.w d4,d2 bsr.w MvSonicOnDoubleSlope moveq #0,d4 rts ; =========================================================================== ; loc_19880: SolidObject45: lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s loc_19896 movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character addq.b #1,d6 loc_19896: btst d6,status(a0) beq.w SolidObject45_cont btst #1,status(a1) bne.s loc_198B8 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_198B8 add.w d1,d1 cmp.w d1,d0 blo.s loc_198CC loc_198B8: bclr #3,status(a1) bset #1,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_198CC: ; Inlined call to MvSonicOnPtfm move.w y_pos(a0),d0 sub.w d2,d0 add.w d3,d0 moveq #0,d1 move.b y_radius(a1),d1 sub.w d1,d0 move.w d0,y_pos(a1) sub.w x_pos(a0),d4 sub.w d4,x_pos(a1) moveq #0,d4 rts ; =========================================================================== ; loc_198EC: SolidObject45_alt: SolidObject45_cont: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.w SolidObject_TestClearPush move.w d1,d4 add.w d4,d4 cmp.w d4,d0 bhi.w SolidObject_TestClearPush move.w y_pos(a0),d5 add.w d3,d5 move.b y_radius(a1),d3 ext.w d3 add.w d3,d2 move.w y_pos(a1),d3 sub.w d5,d3 addq.w #4,d3 add.w d2,d3 bmi.w SolidObject_TestClearPush move.w d2,d4 add.w d4,d4 cmp.w d4,d3 bhs.w SolidObject_TestClearPush bra.w SolidObject_ChkBounds ; =========================================================================== ; loc_1992E: SolidObject86_30_alt: SlopedSolid_cont: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.w SolidObject_TestClearPush move.w d1,d3 add.w d3,d3 cmp.w d3,d0 bhi.w SolidObject_TestClearPush move.w d0,d5 btst #0,render_flags(a0) beq.s + not.w d5 add.w d3,d5 + lsr.w #1,d5 move.b (a2,d5.w),d3 sub.b (a2),d3 ext.w d3 move.w y_pos(a0),d5 sub.w d3,d5 move.b y_radius(a1),d3 ext.w d3 add.w d3,d2 move.w y_pos(a1),d3 sub.w d5,d3 addq.w #4,d3 add.w d2,d3 bmi.w SolidObject_TestClearPush move.w d2,d4 add.w d4,d4 cmp.w d4,d3 bhs.w SolidObject_TestClearPush bra.w SolidObject_ChkBounds ; =========================================================================== ; unused/dead code ; loc_19988: SolidObject_Unk_cont: DoubleSlopedSolid_cont: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.w SolidObject_TestClearPush move.w d1,d3 add.w d3,d3 cmp.w d3,d0 bhi.w SolidObject_TestClearPush move.w d0,d5 btst #0,render_flags(a0) beq.s + not.w d5 add.w d3,d5 + andi.w #$FFFE,d5 move.b (a2,d5.w),d3 move.b 1(a2,d5.w),d2 ext.w d2 ext.w d3 move.w y_pos(a0),d5 sub.w d3,d5 move.w y_pos(a1),d3 sub.w d5,d3 move.b y_radius(a1),d5 ext.w d5 add.w d5,d3 addq.w #4,d3 bmi.w SolidObject_TestClearPush add.w d5,d2 move.w d2,d4 add.w d5,d4 cmp.w d4,d3 bhs.w SolidObject_TestClearPush bra.w SolidObject_ChkBounds ; =========================================================================== ; loc_199E8: SolidObject_cont: SolidObject_OnScreenTest: tst.b render_flags(a0) bpl.w SolidObject_TestClearPush ;loc_199F0: SolidObject_cont: ; We now perform the x portion of a bounding box check. To do this, we assume a ; coordinate system where the x origin is at the object's left edge. move.w x_pos(a1),d0 ; load Sonic's x position... sub.w x_pos(a0),d0 ; ... and calculate his x position relative to the object add.w d1,d0 ; assume object's left edge is at (0,0). This is also Sonic's distance to the object's left edge. bmi.w SolidObject_TestClearPush ; branch, if Sonic is outside the object's left edge move.w d1,d3 add.w d3,d3 ; calculate object's width cmp.w d3,d0 bhi.w SolidObject_TestClearPush ; branch, if Sonic is outside the object's right edge ; We now perform the y portion of a bounding box check. To do this, we assume a ; coordinate system where the y origin is at the highest y position relative to the object ; at which Sonic would still collide with it. This point is ; y_pos(object) - width(object)/2 - y_radius(Sonic) - 4, ; where object is stored in (a0), Sonic in (a1), and height(object)/2 in d2. This way ; of doing it causes the object's hitbox to be vertically off-center by -4 pixels. move.b y_radius(a1),d3 ; load Sonic's y radius ext.w d3 add.w d3,d2 ; calculate maximum distance for a top collision move.w y_pos(a1),d3 ; load Sonic's y position... sub.w y_pos(a0),d3 ; ... and calculate his y position relative to the object addq.w #4,d3 ; assume a slightly lower position for Sonic add.w d2,d3 ; assume the highest position where Sonic would still be colliding with the object to be (0,0) bmi.w SolidObject_TestClearPush ; branch, if Sonic is above this point andi.w #$7FF,d3 move.w d2,d4 add.w d4,d4 ; calculate minimum distance for a bottom collision cmp.w d4,d3 bhs.w SolidObject_TestClearPush ; branch, if Sonic is below this point ;loc_19A2E: SolidObject_ChkBounds: tst.b obj_control(a1) bmi.w SolidObject_TestClearPush ; branch, if object collisions are disabled for Sonic cmpi.b #6,routine(a1) ; is Sonic dead? bhs.w loc_19AEA ; if yes, branch tst.w (Debug_placement_mode).w bne.w loc_19AEA ; branch, if in debug mode move.w d0,d5 cmp.w d0,d1 bhs.s + ; branch, if Sonic is to the object's left add.w d1,d1 sub.w d1,d0 move.w d0,d5 ; calculate Sonic's distance to the object's right edge... neg.w d5 ; ... and calculate the absolute value + move.w d3,d1 cmp.w d3,d2 bhs.s + subq.w #4,d3 sub.w d4,d3 move.w d3,d1 neg.w d1 + cmp.w d1,d5 bhi.w loc_19AEE ; branch, if horizontal distance is greater than vertical distance loc_19A6A: cmpi.w #4,d1 bls.s loc_19AB6 tst.w d0 beq.s loc_19A90 bmi.s loc_19A7E tst.w x_vel(a1) bmi.s loc_19A90 bra.s loc_19A84 ; =========================================================================== loc_19A7E: tst.w x_vel(a1) bpl.s loc_19A90 loc_19A84: move.w #0,inertia(a1) move.w #0,x_vel(a1) loc_19A90: sub.w d0,x_pos(a1) btst #1,status(a1) bne.s loc_19AB6 move.l d6,d4 addq.b #pushing_bit_delta,d4 ; Character is pushing, not standing bset d4,status(a0) bset #5,status(a1) move.w d6,d4 addi.b #($10-p1_standing_bit+p1_touch_side_bit),d4 bset d4,d6 ; This sets bits 0 (Sonic) or 1 (Tails) of high word of d6 moveq #1,d4 rts ; =========================================================================== loc_19AB6: bsr.s loc_19ADC move.w d6,d4 addi.b #($10-p1_standing_bit+p1_touch_side_bit),d4 bset d4,d6 ; This sets bits 0 (Sonic) or 1 (Tails) of high word of d6 moveq #1,d4 rts ; =========================================================================== ;loc_19AC4: SolidObject_TestClearPush: move.l d6,d4 addq.b #pushing_bit_delta,d4 btst d4,status(a0) beq.s loc_19AEA cmpi.b #AniIDSonAni_Roll,anim(a1) beq.s loc_19ADC move.w #AniIDSonAni_Run,anim(a1) loc_19ADC: move.l d6,d4 addq.b #pushing_bit_delta,d4 bclr d4,status(a0) bclr #5,status(a1) loc_19AEA: moveq #0,d4 rts ; =========================================================================== loc_19AEE: tst.w d3 bmi.s loc_19B06 cmpi.w #$10,d3 blo.s loc_19B56 cmpi.b #ObjID_LauncherSpring,id(a0) bne.s SolidObject_TestClearPush cmpi.w #$14,d3 blo.s loc_19B56 bra.s SolidObject_TestClearPush ; =========================================================================== loc_19B06: tst.w y_vel(a1) beq.s loc_19B28 bpl.s loc_19B1C tst.w d3 bpl.s loc_19B1C sub.w d3,y_pos(a1) move.w #0,y_vel(a1) loc_19B1C: move.w d6,d4 addi.b #($10-p1_standing_bit+p1_touch_bottom_bit),d4 bset d4,d6 ; This sets bits 2 (Sonic) or 3 (Tails) of high word of d6 moveq #-2,d4 rts ; =========================================================================== loc_19B28: btst #1,status(a1) bne.s loc_19B1C mvabs.w d0,d4 cmpi.w #$10,d4 blo.w loc_19A6A move.l a0,-(sp) movea.l a1,a0 jsr (KillCharacter).l movea.l (sp)+,a0 ; load 0bj address move.w d6,d4 addi.b #($10-p1_standing_bit+p1_touch_bottom_bit),d4 bset d4,d6 ; This sets bits 2 (Sonic) or 3 (Tails) of high word of d6 moveq #-2,d4 rts ; =========================================================================== loc_19B56: subq.w #4,d3 moveq #0,d1 move.b width_pixels(a0),d1 move.w d1,d2 add.w d2,d2 add.w x_pos(a1),d1 sub.w x_pos(a0),d1 bmi.s loc_19B8E cmp.w d2,d1 bhs.s loc_19B8E tst.w y_vel(a1) bmi.s loc_19B8E sub.w d3,y_pos(a1) subq.w #1,y_pos(a1) bsr.w RideObject_SetRide move.w d6,d4 addi.b #($10-p1_standing_bit+p1_touch_top_bit),d4 bset d4,d6 ; This sets bits 4 (Sonic) or 5 (Tails) of high word of d6 moveq #-1,d4 rts ; =========================================================================== loc_19B8E: moveq #0,d4 rts ; =========================================================================== ; Subroutine to change Sonic's position with a platform ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_19B92: MvSonicOnPtfm: move.w y_pos(a0),d0 sub.w d3,d0 bra.s loc_19BA2 ; =========================================================================== ; a couple lines of unused/leftover/dead code from Sonic 1 ; a0=object move.w y_pos(a0),d0 subi.w #9,d0 loc_19BA2: tst.b obj_control(a1) bmi.s return_19BCA cmpi.b #6,routine(a1) bhs.s return_19BCA tst.w (Debug_placement_mode).w bne.s return_19BCA moveq #0,d1 move.b y_radius(a1),d1 sub.w d1,d0 move.w d0,y_pos(a1) sub.w x_pos(a0),d2 sub.w d2,x_pos(a1) return_19BCA: rts ; =========================================================================== ;loc_19BCC: MvSonicOnSlope: btst #3,status(a1) beq.s return_19C0C move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 lsr.w #1,d0 btst #0,render_flags(a0) beq.s loc_19BEC not.w d0 add.w d1,d0 loc_19BEC: move.b (a2,d0.w),d1 ext.w d1 move.w y_pos(a0),d0 sub.w d1,d0 moveq #0,d1 move.b y_radius(a1),d1 sub.w d1,d0 move.w d0,y_pos(a1) sub.w x_pos(a0),d2 sub.w d2,x_pos(a1) return_19C0C: rts ; =========================================================================== ; unused/dead code. ; loc_19C0E: MvSonicOnDoubleSlope: btst #3,status(a1) beq.s return_19C0C move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 btst #0,render_flags(a0) beq.s loc_19C2C not.w d0 add.w d1,d0 loc_19C2C: andi.w #$FFFE,d0 bra.s loc_19BEC ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to collide Sonic/Tails with the top of a platform ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; ; input variables: ; d1 = object width ; d3 = object height / 2 ; d4 = object x-axis position ; ; address registers: ; a0 = the object to check collision with ; a1 = sonic or tails (set inside these subroutines) ; loc_19C32: PlatformObject: lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s PlatformObject_SingleCharacter movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character addq.b #1,d6 ; loc_19C48: PlatformObject_SingleCharacter: btst d6,status(a0) beq.w PlatformObject_cont move.w d1,d2 add.w d2,d2 btst #1,status(a1) bne.s + move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s + cmp.w d2,d0 blo.s loc_19C80 + bclr #3,status(a1) bset #1,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_19C80: move.w d4,d2 bsr.w MvSonicOnPtfm moveq #0,d4 rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to collide Sonic/Tails with the top of a sloped platform like a seesaw ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; ; input variables: ; d1 = object width ; d3 = object height ; d4 = object x-axis position ; ; address registers: ; a0 = the object to check collision with ; a1 = sonic or tails (set inside these subroutines) ; a2 = height data for slope ; loc_19C8A: SlopeObject: SlopedPlatform: lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s SlopedPlatform_SingleCharacter movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character addq.b #1,d6 ; loc_19CA0: SlopedPlatform_SingleCharacter: btst d6,status(a0) beq.w SlopedPlatform_cont move.w d1,d2 add.w d2,d2 btst #1,status(a1) bne.s loc_19CC4 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_19CC4 cmp.w d2,d0 blo.s loc_19CD8 loc_19CC4: bclr #3,status(a1) bset #1,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_19CD8: move.w d4,d2 bsr.w MvSonicOnSlope moveq #0,d4 rts ; =========================================================================== ; Identical to PlatformObject. ;loc_19CE2: PlatformObject2: lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s loc_19CF8 movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character addq.b #1,d6 loc_19CF8: btst d6,status(a0) beq.w PlatformObject2_cont move.w d1,d2 add.w d2,d2 btst #1,status(a1) bne.s loc_19D1C move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_19D1C cmp.w d2,d0 blo.s loc_19D30 loc_19D1C: bclr #3,status(a1) bset #1,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; =========================================================================== loc_19D30: move.w d4,d2 bsr.w MvSonicOnPtfm moveq #0,d4 rts ; =========================================================================== ; Almost identical to PlatformObject, except that this function does nothing if ; the character is already standing on a platform. Used only by the elevators ; in CNZ. ;loc_19D3A: PlatformObjectD5: lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s loc_19D50 movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character addq.b #1,d6 loc_19D50: btst d6,status(a0) bne.s loc_19D62 btst #3,status(a1) bne.s loc_19D8E bra.w PlatformObject_cont ; =========================================================================== loc_19D62: move.w d1,d2 add.w d2,d2 btst #1,status(a1) bne.s loc_19D7E move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_19D7E cmp.w d2,d0 blo.s loc_19D92 loc_19D7E: bclr #3,status(a1) bset #1,status(a1) bclr d6,status(a0) loc_19D8E: moveq #0,d4 rts ; =========================================================================== loc_19D92: move.w d4,d2 bsr.w MvSonicOnPtfm moveq #0,d4 rts ; =========================================================================== ; Used only by EHZ/HPZ log bridges. Very similar to PlatformObject_cont, but ; d2 already has the full width of the log. ;loc_19D9C: PlatformObject11_cont: tst.w y_vel(a1) bmi.w return_19E8E move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.w return_19E8E cmp.w d2,d0 bhs.w return_19E8E bra.s loc_19DD8 ; =========================================================================== ;loc_19DBA: PlatformObject_cont: tst.w y_vel(a1) bmi.w return_19E8E move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.w return_19E8E add.w d1,d1 cmp.w d1,d0 bhs.w return_19E8E loc_19DD8: move.w y_pos(a0),d0 sub.w d3,d0 ;loc_19DDE: PlatformObject_ChkYRange: move.w y_pos(a1),d2 move.b y_radius(a1),d1 ext.w d1 add.w d2,d1 addq.w #4,d1 sub.w d1,d0 bhi.w return_19E8E cmpi.w #-$10,d0 blo.w return_19E8E tst.b obj_control(a1) bmi.w return_19E8E cmpi.b #6,routine(a1) bhs.w return_19E8E add.w d0,d2 addq.w #3,d2 move.w d2,y_pos(a1) ;loc_19E14: RideObject_SetRide: btst #3,status(a1) beq.s loc_19E30 moveq #0,d0 move.b interact(a1),d0 if object_size=$40 lsl.w #6,d0 else mulu.w #object_size,d0 endif addi.l #Object_RAM,d0 movea.l d0,a3 ; a3=object bclr d6,status(a3) loc_19E30: move.w a0,d0 subi.w #Object_RAM,d0 if object_size=$40 lsr.w #6,d0 else divu.w #object_size,d0 endif andi.w #$7F,d0 move.b d0,interact(a1) move.b #0,angle(a1) move.w #0,y_vel(a1) move.w x_vel(a1),inertia(a1) btst #1,status(a1) beq.s loc_19E7E move.l a0,-(sp) movea.l a1,a0 move.w a0,d1 subi.w #Object_RAM,d1 bne.s loc_19E76 cmpi.w #2,(Player_mode).w beq.s loc_19E76 jsr (Sonic_ResetOnFloor_Part2).l bra.s loc_19E7C ; =========================================================================== loc_19E76: jsr (Tails_ResetOnFloor_Part2).l loc_19E7C: movea.l (sp)+,a0 ; a0=character loc_19E7E: bset #3,status(a1) bclr #1,status(a1) bset d6,status(a0) return_19E8E: rts ; =========================================================================== ;loc_19E90: SlopedPlatform_cont: tst.w y_vel(a1) bmi.w return_19E8E move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s return_19E8E add.w d1,d1 cmp.w d1,d0 bhs.s return_19E8E btst #0,render_flags(a0) beq.s loc_19EB6 not.w d0 add.w d1,d0 loc_19EB6: lsr.w #1,d0 move.b (a2,d0.w),d3 ext.w d3 move.w y_pos(a0),d0 sub.w d3,d0 bra.w PlatformObject_ChkYRange ; =========================================================================== ; Basically identical to PlatformObject_cont ;loc_19EC8: PlatformObject2_cont: tst.w y_vel(a1) bmi.w return_19E8E move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.w return_19E8E add.w d1,d1 cmp.w d1,d0 bhs.w return_19E8E move.w y_pos(a0),d0 sub.w d3,d0 bra.w PlatformObject_ChkYRange ; =========================================================================== ; If a character is being dragged through terrain by this object, drop the ; character on terrain instead. ;loc_19EF0: DropOnFloor: lea (MainCharacter).w,a1 ; a1=character btst #p1_standing_bit,status(a0) beq.s loc_19F1E jsr (ChkFloorEdge2).l tst.w d1 beq.s loc_19F08 bpl.s loc_19F1E loc_19F08: lea (MainCharacter).w,a1 ; a1=character bclr #3,status(a1) bset #1,status(a1) bclr #p1_standing_bit,status(a0) loc_19F1E: lea (Sidekick).w,a1 ; a1=character btst #p2_standing_bit,status(a0) beq.s loc_19F4C jsr (ChkFloorEdge2).l tst.w d1 beq.s loc_19F36 bpl.s loc_19F4C loc_19F36: lea (Sidekick).w,a1 ; a1=character bclr #3,status(a1) bset #1,status(a1) bclr #p2_standing_bit,status(a0) loc_19F4C: moveq #0,d4 rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 01 - Sonic ; ---------------------------------------------------------------------------- ; Sprite_19F50: Object_Sonic: Obj01: ; a0=character tst.w (Debug_placement_mode).w ; is debug mode being used? beq.s Obj01_Normal ; if not, branch jmp (DebugMode).l ; --------------------------------------------------------------------------- ; loc_19F5C: Obj01_Normal: moveq #0,d0 move.b routine(a0),d0 move.w Obj01_Index(pc,d0.w),d1 jmp Obj01_Index(pc,d1.w) ; =========================================================================== ; off_19F6A: Obj01_States: Obj01_Index: offsetTable offsetTableEntry.w Obj01_Init ; 0 offsetTableEntry.w Obj01_Control ; 2 offsetTableEntry.w Obj01_Hurt ; 4 offsetTableEntry.w Obj01_Dead ; 6 offsetTableEntry.w Obj01_Gone ; 8 offsetTableEntry.w Obj01_Respawning ; $A ; =========================================================================== ; loc_19F76: Obj_01_Sub_0: Obj01_Main: Obj01_Init: addq.b #2,routine(a0) ; => Obj01_Control move.b #$13,y_radius(a0) ; this sets Sonic's collision height (2*pixels) move.b #9,x_radius(a0) move.l #Mapunc_Sonic,mappings(a0) move.b #2,priority(a0) move.b #$18,width_pixels(a0) move.b #4,render_flags(a0) move.w #$600,(Sonic_top_speed).w ; set Sonic's top speed move.w #$C,(Sonic_acceleration).w ; set Sonic's acceleration move.w #$80,(Sonic_deceleration).w ; set Sonic's deceleration tst.b (Last_star_pole_hit).w bne.s Obj01_Init_Continued ; only happens when not starting at a checkpoint: move.w #make_art_tile(ArtTile_ArtUnc_Sonic,0,0),art_tile(a0) bsr.w Adjust2PArtPointer move.b #$C,top_solid_bit(a0) move.b #$D,lrb_solid_bit(a0) move.w x_pos(a0),(Saved_x_pos).w move.w y_pos(a0),(Saved_y_pos).w move.w art_tile(a0),(Saved_art_tile).w move.w top_solid_bit(a0),(Saved_Solid_bits).w Obj01_Init_Continued: move.b #0,flips_remaining(a0) move.b #4,flip_speed(a0) move.b #0,(Super_Sonic_flag).w move.b #$1E,air_left(a0) subi.w #$20,x_pos(a0) addi_.w #4,y_pos(a0) move.w #0,(Sonic_Pos_Record_Index).w move.w #$3F,d2 - bsr.w Sonic_RecordPos subq.w #4,a1 move.l #0,(a1) dbf d2,- addi.w #$20,x_pos(a0) subi_.w #4,y_pos(a0) ; --------------------------------------------------------------------------- ; Normal state for Sonic ; --------------------------------------------------------------------------- ; loc_1A030: Obj_01_Sub_2: Obj01_Control: tst.w (Debug_mode_flag).w ; is debug cheat enabled? beq.s + ; if not, branch btst #button_B,(Ctrl_1_Press).w ; is button B pressed? beq.s + ; if not, branch move.w #1,(Debug_placement_mode).w ; change Sonic into a ring/item clr.b (Control_Locked).w ; unlock control rts ; ----------------------------------------------------------------------- + tst.b (Control_Locked).w ; are controls locked? bne.s + ; if yes, branch move.w (Ctrl_1).w,(Ctrl_1_Logical).w ; copy new held buttons, to enable joypad control + btst #0,obj_control(a0) ; is Sonic interacting with another object that holds him in place or controls his movement somehow? bne.s + ; if yes, branch to skip Sonic's control moveq #0,d0 move.b status(a0),d0 andi.w #6,d0 ; %0000 %0110 move.w Obj01_Modes(pc,d0.w),d1 jsr Obj01_Modes(pc,d1.w) ; run Sonic's movement control code + cmpi.w #-$100,(Camera_Min_Y_pos).w ; is vertical wrapping enabled? bne.s + ; if not, branch andi.w #$7FF,y_pos(a0) ; perform wrapping of Sonic's y position + bsr.s Sonic_Display bsr.w Sonic_Super bsr.w Sonic_RecordPos bsr.w Sonic_Water move.b (Primary_Angle).w,next_tilt(a0) move.b (Secondary_Angle).w,tilt(a0) tst.b (WindTunnel_flag).w beq.s + tst.b anim(a0) bne.s + move.b next_anim(a0),anim(a0) + bsr.w Sonic_Animate tst.b obj_control(a0) bmi.s + jsr (TouchResponse).l + bra.w LoadSonicDynPLC ; =========================================================================== ; secondary states under state Obj01_Control ; off_1A0BE: Obj01_Modes: offsetTable offsetTableEntry.w Obj01_MdNormal_Checks ; 0 - not airborne or rolling offsetTableEntry.w Obj01_MdAir ; 2 - airborne offsetTableEntry.w Obj01_MdRoll ; 4 - rolling offsetTableEntry.w Obj01_MdJump ; 6 - jumping ; =========================================================================== ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1A0C6: Sonic_Display: move.w invulnerable_time(a0),d0 beq.s Obj01_Display subq.w #1,invulnerable_time(a0) lsr.w #3,d0 bcc.s Obj01_ChkInvin ; loc_1A0D4: Obj01_Display: jsr (DisplaySprite).l ; loc_1A0DA: Obj01_ChkInvin: ; Checks if invincibility has expired and disables it if it has. btst #status_sec_isInvincible,status_secondary(a0) beq.s Obj01_ChkShoes tst.w invincibility_time(a0) beq.s Obj01_ChkShoes ; If there wasn't any time left, that means we're in Super Sonic mode. subq.w #1,invincibility_time(a0) bne.s Obj01_ChkShoes tst.b (Current_Boss_ID).w ; Don't change music if in a boss fight bne.s Obj01_RmvInvin cmpi.b #$C,air_left(a0) ; Don't change music if drowning blo.s Obj01_RmvInvin move.w (Level_Music).w,d0 jsr (PlayMusic).l ;loc_1A106: Obj01_RmvInvin: bclr #status_sec_isInvincible,status_secondary(a0) ; loc_1A10C: Obj01_ChkShoes: ; Checks if Speed Shoes have expired and disables them if they have. btst #status_sec_hasSpeedShoes,status_secondary(a0) beq.s Obj01_ExitChk tst.w speedshoes_time(a0) beq.s Obj01_ExitChk subq.w #1,speedshoes_time(a0) bne.s Obj01_ExitChk move.w #$600,(Sonic_top_speed).w move.w #$C,(Sonic_acceleration).w move.w #$80,(Sonic_deceleration).w tst.b (Super_Sonic_flag).w beq.s Obj01_RmvSpeed move.w #$A00,(Sonic_top_speed).w move.w #$30,(Sonic_acceleration).w move.w #$100,(Sonic_deceleration).w ; loc_1A14A: Obj01_RmvSpeed: bclr #status_sec_hasSpeedShoes,status_secondary(a0) move.w #MusID_SlowDown,d0 ; Slow down tempo jmp (PlayMusic).l ; --------------------------------------------------------------------------- ; return_1A15A: Obj01_ExitChk: rts ; End of subroutine Sonic_Display ; --------------------------------------------------------------------------- ; Subroutine to record Sonic's previous positions for invincibility stars ; and input/status flags for Tails' AI to follow ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1A15C: Sonic_RecordPos: move.w (Sonic_Pos_Record_Index).w,d0 lea (Sonic_Pos_Record_Buf).w,a1 lea (a1,d0.w),a1 move.w x_pos(a0),(a1)+ move.w y_pos(a0),(a1)+ addq.b #4,(Sonic_Pos_Record_Index+1).w lea (Sonic_Stat_Record_Buf).w,a1 lea (a1,d0.w),a1 move.w (Ctrl_1_Logical).w,(a1)+ move.w status(a0),(a1)+ rts ; End of subroutine Sonic_RecordPos ; --------------------------------------------------------------------------- ; Subroutine for Sonic when he's underwater ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1A186: Sonic_Water: tst.b (Water_flag).w ; does level have water? bne.s Obj01_InWater ; if yes, branch return_1A18C: rts ; --------------------------------------------------------------------------- ; loc_1A18E: Obj01_InWater: move.w (Water_Level_1).w,d0 cmp.w y_pos(a0),d0 ; is Sonic above the water? bge.s Obj01_OutWater ; if yes, branch bset #6,status(a0) ; set underwater flag bne.s return_1A18C ; if already underwater, branch movea.l a0,a1 bsr.w ResumeMusic move.b #ObjID_SmallBubbles,(Sonic_BreathingBubbles+id).w ; load Obj0A (sonic's breathing bubbles) at $FFFFD080 move.b #$81,(Sonic_BreathingBubbles+subtype).w move.l a0,(Sonic_BreathingBubbles+$3C).w move.w #$300,(Sonic_top_speed).w move.w #6,(Sonic_acceleration).w move.w #$40,(Sonic_deceleration).w tst.b (Super_Sonic_flag).w beq.s + move.w #$500,(Sonic_top_speed).w move.w #$18,(Sonic_acceleration).w move.w #$80,(Sonic_deceleration).w + asr.w x_vel(a0) asr.w y_vel(a0) ; memory operands can only be shifted one bit at a time asr.w y_vel(a0) beq.s return_1A18C move.w #$100,(Sonic_Dust+anim).w ; splash animation move.w #SndID_Splash,d0 ; splash sound jmp (PlaySound).l ; --------------------------------------------------------------------------- ; loc_1A1FE: Obj01_OutWater: bclr #6,status(a0) ; unset underwater flag beq.s return_1A18C ; if already above water, branch movea.l a0,a1 bsr.w ResumeMusic move.w #$600,(Sonic_top_speed).w move.w #$C,(Sonic_acceleration).w move.w #$80,(Sonic_deceleration).w tst.b (Super_Sonic_flag).w beq.s + move.w #$A00,(Sonic_top_speed).w move.w #$30,(Sonic_acceleration).w move.w #$100,(Sonic_deceleration).w + cmpi.b #4,routine(a0) ; is Sonic falling back from getting hurt? beq.s + ; if yes, branch asl y_vel(a0) + tst.w y_vel(a0) beq.w return_1A18C move.w #$100,(Sonic_Dust+anim).w ; splash animation movea.l a0,a1 bsr.w ResumeMusic cmpi.w #-$1000,y_vel(a0) bgt.s + move.w #-$1000,y_vel(a0) ; limit upward y velocity exiting the water + move.w #SndID_Splash,d0 ; splash sound jmp (PlaySound).l ; End of subroutine Sonic_Water ; =========================================================================== ; --------------------------------------------------------------------------- ; Start of subroutine Obj01_MdNormal ; Called if Sonic is neither airborne nor rolling this frame ; --------------------------------------------------------------------------- ; loc_1A26E: Obj01_MdNormal_Checks: move.b (Ctrl_1_Press_Logical).w,d0 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 bne.s Obj01_MdNormal cmpi.b #$A,anim(a0) beq.s return_1A2DE cmpi.b #$B,anim(a0) beq.s return_1A2DE cmpi.b #5,anim(a0) bne.s Obj01_MdNormal cmpi.b #$1E,anim_frame(a0) blo.s Obj01_MdNormal move.b (Ctrl_1_Held_Logical).w,d0 andi.b #button_up_mask|button_down_mask|button_left_mask|button_right_mask|button_B_mask|button_C_mask|button_A_mask,d0 beq.s return_1A2DE move.b #$A,anim(a0) cmpi.b #$AC,anim_frame(a0) blo.s return_1A2DE move.b #$B,anim(a0) bra.s return_1A2DE ; --------------------------------------------------------------------------- ; loc_1A2B8: Obj01_MdNormal: bsr.w Sonic_CheckSpindash bsr.w Sonic_Jump bsr.w Sonic_SlopeResist bsr.w Sonic_Move bsr.w Sonic_Roll bsr.w Sonic_LevelBound jsr (ObjectMove).l bsr.w AnglePos bsr.w Sonic_SlopeRepel return_1A2DE: rts ; End of subroutine Obj01_MdNormal ; =========================================================================== ; Start of subroutine Obj01_MdAir ; Called if Sonic is airborne, but not in a ball (thus, probably not jumping) ; loc_1A2E0: Obj01_MdJump Obj01_MdAir: bsr.w Sonic_JumpHeight bsr.w Sonic_ChgJumpDir bsr.w Sonic_LevelBound jsr (ObjectMoveAndFall).l btst #6,status(a0) ; is Sonic underwater? beq.s + ; if not, branch subi.w #$28,y_vel(a0) ; reduce gravity by $28 ($38-$28=$10) + bsr.w Sonic_JumpAngle bsr.w Sonic_DoLevelCollision rts ; End of subroutine Obj01_MdAir ; =========================================================================== ; Start of subroutine Obj01_MdRoll ; Called if Sonic is in a ball, but not airborne (thus, probably rolling) ; loc_1A30A: Obj01_MdRoll: tst.b pinball_mode(a0) bne.s + bsr.w Sonic_Jump + bsr.w Sonic_RollRepel bsr.w Sonic_RollSpeed bsr.w Sonic_LevelBound jsr (ObjectMove).l bsr.w AnglePos bsr.w Sonic_SlopeRepel rts ; End of subroutine Obj01_MdRoll ; =========================================================================== ; Start of subroutine Obj01_MdJump ; Called if Sonic is in a ball and airborne (he could be jumping but not necessarily) ; Notes: This is identical to Obj01_MdAir, at least at this outer level. ; Why they gave it a separate copy of the code, I don't know. ; loc_1A330: Obj01_MdJump2: Obj01_MdJump: bsr.w Sonic_JumpHeight bsr.w Sonic_ChgJumpDir bsr.w Sonic_LevelBound jsr (ObjectMoveAndFall).l btst #6,status(a0) ; is Sonic underwater? beq.s + ; if not, branch subi.w #$28,y_vel(a0) ; reduce gravity by $28 ($38-$28=$10) + bsr.w Sonic_JumpAngle bsr.w Sonic_DoLevelCollision rts ; End of subroutine Obj01_MdJump ; --------------------------------------------------------------------------- ; Subroutine to make Sonic walk/run ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1A35A: Sonic_Move: move.w (Sonic_top_speed).w,d6 move.w (Sonic_acceleration).w,d5 move.w (Sonic_deceleration).w,d4 if status_sec_isSliding = 7 tst.b status_secondary(a0) bmi.w Obj01_Traction else btst #status_sec_isSliding,status_secondary(a0) bne.w Obj01_Traction endif tst.w move_lock(a0) bne.w Obj01_ResetScr btst #button_left,(Ctrl_1_Held_Logical).w ; is left being pressed? beq.s Obj01_NotLeft ; if not, branch bsr.w Sonic_MoveLeft ; loc_1A382: Obj01_NotLeft: btst #button_right,(Ctrl_1_Held_Logical).w ; is right being pressed? beq.s Obj01_NotRight ; if not, branch bsr.w Sonic_MoveRight ; loc_1A38E: Obj01_NotRight: move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 ; is Sonic on a slope? bne.w Obj01_ResetScr ; if yes, branch tst.w inertia(a0) ; is Sonic moving? bne.w Obj01_ResetScr ; if yes, branch bclr #5,status(a0) move.b #AniIDSonAni_Wait,anim(a0) ; use "standing" animation btst #3,status(a0) beq.w Sonic_Balance moveq #0,d0 move.b interact(a0),d0 if object_size=$40 lsl.w #6,d0 else mulu.w #object_size,d0 endif lea (Object_RAM).w,a1 ; a1=character lea (a1,d0.w),a1 ; a1=object tst.b status(a1) bmi.w Sonic_Lookup moveq #0,d1 move.b width_pixels(a1),d1 move.w d1,d2 add.w d2,d2 subq.w #2,d2 add.w x_pos(a0),d1 sub.w x_pos(a1),d1 tst.b (Super_Sonic_flag).w bne.w SuperSonic_Balance cmpi.w #2,d1 blt.s Sonic_BalanceOnObjLeft cmp.w d2,d1 bge.s Sonic_BalanceOnObjRight bra.w Sonic_Lookup ; --------------------------------------------------------------------------- ; loc_1A3FE: SuperSonic_Balance: cmpi.w #2,d1 blt.w SuperSonic_BalanceOnObjLeft cmp.w d2,d1 bge.w SuperSonic_BalanceOnObjRight bra.w Sonic_Lookup ; --------------------------------------------------------------------------- ; balancing checks for when you're on the right edge of an object ; loc_1A410: Sonic_BalanceOnObjRight: btst #0,status(a0) bne.s + move.b #AniIDSonAni_Balance,anim(a0) addq.w #6,d2 cmp.w d2,d1 blt.w Obj01_ResetScr move.b #AniIDSonAni_Balance2,anim(a0) bra.w Obj01_ResetScr ; on right edge of object but facing left: + move.b #AniIDSonAni_Balance3,anim(a0) addq.w #6,d2 cmp.w d2,d1 blt.w Obj01_ResetScr move.b #AniIDSonAni_Balance4,anim(a0) bclr #0,status(a0) bra.w Obj01_ResetScr ; --------------------------------------------------------------------------- ; balancing checks for when you're on the left edge of an object ; loc_1A44E: Sonic_BalanceOnObjLeft: btst #0,status(a0) beq.s + move.b #AniIDSonAni_Balance,anim(a0) cmpi.w #-4,d1 bge.w Obj01_ResetScr move.b #AniIDSonAni_Balance2,anim(a0) bra.w Obj01_ResetScr ; on left edge of object but facing right: + move.b #AniIDSonAni_Balance3,anim(a0) cmpi.w #-4,d1 bge.w Obj01_ResetScr move.b #AniIDSonAni_Balance4,anim(a0) bset #0,status(a0) bra.w Obj01_ResetScr ; --------------------------------------------------------------------------- ; balancing checks for when you're on the edge of part of the level ; loc_1A48C: Sonic_Balance: jsr (ChkFloorEdge).l cmpi.w #$C,d1 blt.w Sonic_Lookup tst.b (Super_Sonic_flag).w bne.w SuperSonic_Balance2 cmpi.b #3,next_tilt(a0) bne.s Sonic_BalanceLeft btst #0,status(a0) bne.s + move.b #AniIDSonAni_Balance,anim(a0) move.w x_pos(a0),d3 subq.w #6,d3 jsr (ChkFloorEdge_Part2).l cmpi.w #$C,d1 blt.w Obj01_ResetScr move.b #AniIDSonAni_Balance2,anim(a0) bra.w Obj01_ResetScr ; on right edge but facing left: + move.b #AniIDSonAni_Balance3,anim(a0) move.w x_pos(a0),d3 subq.w #6,d3 jsr (ChkFloorEdge_Part2).l cmpi.w #$C,d1 blt.w Obj01_ResetScr move.b #AniIDSonAni_Balance4,anim(a0) bclr #0,status(a0) bra.w Obj01_ResetScr ; --------------------------------------------------------------------------- Sonic_BalanceLeft: cmpi.b #3,tilt(a0) bne.s Sonic_Lookup btst #0,status(a0) beq.s + move.b #AniIDSonAni_Balance,anim(a0) move.w x_pos(a0),d3 addq.w #6,d3 jsr (ChkFloorEdge_Part2).l cmpi.w #$C,d1 blt.w Obj01_ResetScr move.b #AniIDSonAni_Balance2,anim(a0) bra.w Obj01_ResetScr ; on left edge but facing right: + move.b #AniIDSonAni_Balance3,anim(a0) move.w x_pos(a0),d3 addq.w #6,d3 jsr (ChkFloorEdge_Part2).l cmpi.w #$C,d1 blt.w Obj01_ResetScr move.b #AniIDSonAni_Balance4,anim(a0) bset #0,status(a0) bra.w Obj01_ResetScr ; --------------------------------------------------------------------------- ; loc_1A55E: SuperSonic_Balance2: cmpi.b #3,next_tilt(a0) bne.s loc_1A56E ; loc_1A566: SuperSonic_BalanceOnObjRight: bclr #0,status(a0) bra.s loc_1A57C ; --------------------------------------------------------------------------- loc_1A56E: cmpi.b #3,tilt(a0) bne.s Sonic_Lookup ; loc_1A576: SuperSonic_BalanceOnObjLeft: bset #0,status(a0) loc_1A57C: move.b #AniIDSonAni_Balance,anim(a0) bra.s Obj01_ResetScr ; --------------------------------------------------------------------------- ; loc_1A584: Sonic_Lookup: btst #button_up,(Ctrl_1_Held_Logical).w ; is up being pressed? beq.s Sonic_Duck ; if not, branch move.b #AniIDSonAni_LookUp,anim(a0) ; use "looking up" animation addq.w #1,(Sonic_Look_delay_counter).w cmpi.w #$78,(Sonic_Look_delay_counter).w blo.s Obj01_ResetScr_Part2 move.w #$78,(Sonic_Look_delay_counter).w cmpi.w #$C8,(Camera_Y_pos_bias).w beq.s Obj01_UpdateSpeedOnGround addq.w #2,(Camera_Y_pos_bias).w bra.s Obj01_UpdateSpeedOnGround ; --------------------------------------------------------------------------- ; loc_1A5B2: Sonic_Duck: btst #button_down,(Ctrl_1_Held_Logical).w ; is down being pressed? beq.s Obj01_ResetScr ; if not, branch move.b #AniIDSonAni_Duck,anim(a0) ; use "ducking" animation addq.w #1,(Sonic_Look_delay_counter).w cmpi.w #$78,(Sonic_Look_delay_counter).w blo.s Obj01_ResetScr_Part2 move.w #$78,(Sonic_Look_delay_counter).w cmpi.w #8,(Camera_Y_pos_bias).w beq.s Obj01_UpdateSpeedOnGround subq.w #2,(Camera_Y_pos_bias).w bra.s Obj01_UpdateSpeedOnGround ; =========================================================================== ; moves the screen back to its normal position after looking up or down ; loc_1A5E0: Obj01_ResetScr: move.w #0,(Sonic_Look_delay_counter).w ; loc_1A5E6: Obj01_ResetScr_Part2: cmpi.w #(224/2)-16,(Camera_Y_pos_bias).w ; is screen in its default position? beq.s Obj01_UpdateSpeedOnGround ; if yes, branch. bhs.s + ; depending on the sign of the difference, addq.w #4,(Camera_Y_pos_bias).w ; either add 2 + subq.w #2,(Camera_Y_pos_bias).w ; or subtract 2 ; --------------------------------------------------------------------------- ; updates Sonic's speed on the ground ; --------------------------------------------------------------------------- ; sub_1A5F8: Obj01_UpdateSpeedOnGround: tst.b (Super_Sonic_flag).w beq.w + move.w #$C,d5 + move.b (Ctrl_1_Held_Logical).w,d0 andi.b #button_left_mask|button_right_mask,d0 ; is left/right pressed? bne.s Obj01_Traction ; if yes, branch move.w inertia(a0),d0 beq.s Obj01_Traction bmi.s Obj01_SettleLeft ; slow down when facing right and not pressing a direction ; Obj01_SettleRight: sub.w d5,d0 bcc.s + move.w #0,d0 + move.w d0,inertia(a0) bra.s Obj01_Traction ; --------------------------------------------------------------------------- ; slow down when facing left and not pressing a direction ; loc_1A624: Obj01_SettleLeft: add.w d5,d0 bcc.s + move.w #0,d0 + move.w d0,inertia(a0) ; increase or decrease speed on the ground ; loc_1A630: Obj01_Traction: move.b angle(a0),d0 jsr (CalcSine).l muls.w inertia(a0),d1 asr.l #8,d1 move.w d1,x_vel(a0) muls.w inertia(a0),d0 asr.l #8,d0 move.w d0,y_vel(a0) ; stops Sonic from running through walls that meet the ground ; loc_1A64E: Obj01_CheckWallsOnGround: move.b angle(a0),d0 addi.b #$40,d0 bmi.s return_1A6BE move.b #$40,d1 ; Rotate 90 degrees clockwise tst.w inertia(a0) ; Check inertia beq.s return_1A6BE ; If not moving, don't do anything bmi.s + ; If negative, branch neg.w d1 ; Otherwise, we want to rotate counterclockwise + move.b angle(a0),d0 add.b d1,d0 move.w d0,-(sp) bsr.w CalcRoomInFront move.w (sp)+,d0 tst.w d1 bpl.s return_1A6BE asl.w #8,d1 addi.b #$20,d0 andi.b #$C0,d0 beq.s loc_1A6BA cmpi.b #$40,d0 beq.s loc_1A6A8 cmpi.b #$80,d0 beq.s loc_1A6A2 add.w d1,x_vel(a0) bset #5,status(a0) move.w #0,inertia(a0) rts ; --------------------------------------------------------------------------- loc_1A6A2: sub.w d1,y_vel(a0) rts ; --------------------------------------------------------------------------- loc_1A6A8: sub.w d1,x_vel(a0) bset #5,status(a0) move.w #0,inertia(a0) rts ; --------------------------------------------------------------------------- loc_1A6BA: add.w d1,y_vel(a0) return_1A6BE: rts ; End of subroutine Sonic_Move ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1A6C0: Sonic_MoveLeft: move.w inertia(a0),d0 beq.s + bpl.s Sonic_TurnLeft ; if Sonic is already moving to the right, branch + bset #0,status(a0) bne.s + bclr #5,status(a0) move.b #AniIDSonAni_Run,next_anim(a0) + sub.w d5,d0 ; add acceleration to the left move.w d6,d1 neg.w d1 cmp.w d1,d0 ; compare new speed with top speed bgt.s + ; if new speed is less than the maximum, branch add.w d5,d0 ; remove this frame's acceleration change cmp.w d1,d0 ; compare speed with top speed ble.s + ; if speed was already greater than the maximum, branch move.w d1,d0 ; limit speed on ground going left + move.w d0,inertia(a0) move.b #AniIDSonAni_Walk,anim(a0) ; use walking animation rts ; --------------------------------------------------------------------------- ; loc_1A6FA: Sonic_TurnLeft: sub.w d4,d0 bcc.s + move.w #-$80,d0 + move.w d0,inertia(a0) move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 bne.s return_1A744 cmpi.w #$400,d0 blt.s return_1A744 move.b #AniIDSonAni_Stop,anim(a0) ; use "stopping" animation bclr #0,status(a0) move.w #SndID_Skidding,d0 jsr (PlaySound).l cmpi.b #$C,air_left(a0) blo.s return_1A744 ; if he's drowning, branch to not make dust move.b #6,(Sonic_Dust+routine).w move.b #$15,(Sonic_Dust+mapping_frame).w return_1A744: rts ; End of subroutine Sonic_MoveLeft ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1A746: Sonic_MoveRight: move.w inertia(a0),d0 bmi.s Sonic_TurnRight ; if Sonic is already moving to the left, branch bclr #0,status(a0) beq.s + bclr #5,status(a0) move.b #AniIDSonAni_Run,next_anim(a0) + add.w d5,d0 ; add acceleration to the right cmp.w d6,d0 ; compare new speed with top speed blt.s + ; if new speed is less than the maximum, branch sub.w d5,d0 ; remove this frame's acceleration change cmp.w d6,d0 ; compare speed with top speed bge.s + ; if speed was already greater than the maximum, branch move.w d6,d0 ; limit speed on ground going right + move.w d0,inertia(a0) move.b #AniIDSonAni_Walk,anim(a0) ; use walking animation rts ; --------------------------------------------------------------------------- ; loc_1A77A: Sonic_TurnRight: add.w d4,d0 bcc.s + move.w #$80,d0 + move.w d0,inertia(a0) move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 bne.s return_1A7C4 cmpi.w #-$400,d0 bgt.s return_1A7C4 move.b #AniIDSonAni_Stop,anim(a0) ; use "stopping" animation bset #0,status(a0) move.w #SndID_Skidding,d0 ; use "stopping" sound jsr (PlaySound).l cmpi.b #$C,air_left(a0) blo.s return_1A7C4 ; if he's drowning, branch to not make dust move.b #6,(Sonic_Dust+routine).w move.b #$15,(Sonic_Dust+mapping_frame).w return_1A7C4: rts ; End of subroutine Sonic_MoveRight ; --------------------------------------------------------------------------- ; Subroutine to change Sonic's speed as he rolls ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1A7C6: Sonic_RollSpeed: move.w (Sonic_top_speed).w,d6 asl.w #1,d6 move.w (Sonic_acceleration).w,d5 asr.w #1,d5 ; natural roll deceleration = 1/2 normal acceleration move.w #$20,d4 ; controlled roll deceleration... interestingly, ; this should be Sonic_deceleration/4 according to Tails_RollSpeed, ; which means Sonic is much better than Tails at slowing down his rolling when he's underwater if status_sec_isSliding = 7 tst.b status_secondary(a0) bmi.w Obj01_Roll_ResetScr else btst #status_sec_isSliding,status_secondary(a0) bne.w Obj01_Roll_ResetScr endif tst.w move_lock(a0) bne.s Sonic_ApplyRollSpeed btst #button_left,(Ctrl_1_Held_Logical).w ; is left being pressed? beq.s + ; if not, branch bsr.w Sonic_RollLeft + btst #button_right,(Ctrl_1_Held_Logical).w ; is right being pressed? beq.s Sonic_ApplyRollSpeed ; if not, branch bsr.w Sonic_RollRight ; loc_1A7FC: Sonic_ApplyRollSpeed: move.w inertia(a0),d0 beq.s Sonic_CheckRollStop bmi.s Sonic_ApplyRollSpeedLeft ; Sonic_ApplyRollSpeedRight: sub.w d5,d0 bcc.s + move.w #0,d0 + move.w d0,inertia(a0) bra.s Sonic_CheckRollStop ; --------------------------------------------------------------------------- ; loc_1A812: Sonic_ApplyRollSpeedLeft: add.w d5,d0 bcc.s + move.w #0,d0 + move.w d0,inertia(a0) ; loc_1A81E: Sonic_CheckRollStop: tst.w inertia(a0) bne.s Obj01_Roll_ResetScr tst.b pinball_mode(a0) ; note: the spindash flag has a different meaning when Sonic's already rolling -- it's used to mean he's not allowed to stop rolling bne.s Sonic_KeepRolling bclr #2,status(a0) move.b #$13,y_radius(a0) move.b #9,x_radius(a0) move.b #AniIDSonAni_Wait,anim(a0) subq.w #5,y_pos(a0) bra.s Obj01_Roll_ResetScr ; --------------------------------------------------------------------------- ; magically gives Sonic an extra push if he's going to stop rolling where it's not allowed ; (such as in an S-curve in HTZ or a stopper chamber in CNZ) ; loc_1A848: Sonic_KeepRolling: move.w #$400,inertia(a0) btst #0,status(a0) beq.s Obj01_Roll_ResetScr neg.w inertia(a0) ; resets the screen to normal while rolling, like Obj01_ResetScr ; loc_1A85A: Obj01_Roll_ResetScr: cmpi.w #(224/2)-16,(Camera_Y_pos_bias).w ; is screen in its default position? beq.s Sonic_SetRollSpeeds ; if yes, branch bhs.s + ; depending on the sign of the difference, addq.w #4,(Camera_Y_pos_bias).w ; either add 2 + subq.w #2,(Camera_Y_pos_bias).w ; or subtract 2 ; loc_1A86C: Sonic_SetRollSpeeds: move.b angle(a0),d0 jsr (CalcSine).l muls.w inertia(a0),d0 asr.l #8,d0 move.w d0,y_vel(a0) ; set y velocity based on $14 and angle muls.w inertia(a0),d1 asr.l #8,d1 cmpi.w #$1000,d1 ble.s + move.w #$1000,d1 ; limit Sonic's speed rolling right + cmpi.w #-$1000,d1 bge.s + move.w #-$1000,d1 ; limit Sonic's speed rolling left + move.w d1,x_vel(a0) ; set x velocity based on $14 and angle bra.w Obj01_CheckWallsOnGround ; End of function Sonic_RollSpeed ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1A8A2: Sonic_RollLeft: move.w inertia(a0),d0 beq.s + bpl.s Sonic_BrakeRollingRight + bset #0,status(a0) move.b #AniIDSonAni_Roll,anim(a0) ; use "rolling" animation rts ; --------------------------------------------------------------------------- ; loc_1A8B8: Sonic_BrakeRollingRight: sub.w d4,d0 ; reduce rightward rolling speed bcc.s + move.w #-$80,d0 + move.w d0,inertia(a0) rts ; End of function Sonic_RollLeft ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1A8C6: Sonic_RollRight: move.w inertia(a0),d0 bmi.s Sonic_BrakeRollingLeft bclr #0,status(a0) move.b #AniIDSonAni_Roll,anim(a0) ; use "rolling" animation rts ; --------------------------------------------------------------------------- ; loc_1A8DA: Sonic_BrakeRollingLeft: add.w d4,d0 ; reduce leftward rolling speed bcc.s + move.w #$80,d0 + move.w d0,inertia(a0) rts ; End of subroutine Sonic_RollRight ; --------------------------------------------------------------------------- ; Subroutine for moving Sonic left or right when he's in the air ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1A8E8: Sonic_ChgJumpDir: move.w (Sonic_top_speed).w,d6 move.w (Sonic_acceleration).w,d5 asl.w #1,d5 btst #4,status(a0) ; did Sonic jump from rolling? bne.s Obj01_Jump_ResetScr ; if yes, branch to skip midair control move.w x_vel(a0),d0 btst #button_left,(Ctrl_1_Held_Logical).w beq.s + ; if not holding left, branch bset #0,status(a0) sub.w d5,d0 ; add acceleration to the left move.w d6,d1 neg.w d1 cmp.w d1,d0 ; compare new speed with top speed bgt.s + ; if new speed is less than the maximum, branch move.w d1,d0 ; limit speed in air going left, even if Sonic was already going faster (speed limit/cap) + btst #button_right,(Ctrl_1_Held_Logical).w beq.s + ; if not holding right, branch bclr #0,status(a0) add.w d5,d0 ; accelerate right in the air cmp.w d6,d0 ; compare new speed with top speed blt.s + ; if new speed is less than the maximum, branch move.w d6,d0 ; limit speed in air going right, even if Sonic was already going faster (speed limit/cap) ; Obj01_JumpMove: + move.w d0,x_vel(a0) ; loc_1A932: Obj01_ResetScr2: Obj01_Jump_ResetScr: cmpi.w #(224/2)-16,(Camera_Y_pos_bias).w ; is screen in its default position? beq.s Sonic_JumpPeakDecelerate ; if yes, branch bhs.s + ; depending on the sign of the difference, addq.w #4,(Camera_Y_pos_bias).w ; either add 2 + subq.w #2,(Camera_Y_pos_bias).w ; or subtract 2 ; loc_1A944: Sonic_JumpPeakDecelerate: cmpi.w #-$400,y_vel(a0) ; is Sonic moving faster than -$400 upwards? blo.s return_1A972 ; if yes, return move.w x_vel(a0),d0 move.w d0,d1 asr.w #5,d1 ; d1 = x_velocity / 32 beq.s return_1A972 ; return if d1 is 0 bmi.s Sonic_JumpPeakDecelerateLeft ; branch if moving left ; Sonic_JumpPeakDecelerateRight: sub.w d1,d0 ; reduce x velocity by d1 bcc.s + move.w #0,d0 + move.w d0,x_vel(a0) rts ;------------------------------------------------------------- ; loc_1A966: Sonic_JumpPeakDecelerateLeft: sub.w d1,d0 ; reduce x velocity by d1 bcs.s + move.w #0,d0 + move.w d0,x_vel(a0) return_1A972: rts ; End of subroutine Sonic_ChgJumpDir ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to prevent Sonic from leaving the boundaries of a level ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1A974: Sonic_LevelBound: move.l x_pos(a0),d1 move.w x_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d1 swap d1 move.w (Camera_Min_X_pos).w,d0 addi.w #$10,d0 cmp.w d1,d0 ; has Sonic touched the left boundary? bhi.s Sonic_Boundary_Sides ; if yes, branch move.w (Camera_Max_X_pos).w,d0 addi.w #$128,d0 tst.b (Current_Boss_ID).w bne.s + addi.w #$40,d0 + cmp.w d1,d0 ; has Sonic touched the right boundary? bls.s Sonic_Boundary_Sides ; if yes, branch ; loc_1A9A6: Sonic_Boundary_CheckBottom: move.w (Camera_Max_Y_pos_now).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 ; has Sonic touched the bottom boundary? blt.s Sonic_Boundary_Bottom ; if yes, branch rts ; --------------------------------------------------------------------------- Sonic_Boundary_Bottom: ;; jmpto (KillCharacter).l, JmpTo_KillCharacter ; =========================================================================== ; loc_1A9BA: Sonic_Boundary_Sides: move.w d0,x_pos(a0) move.w #0,2+x_pos(a0) ; subpixel x move.w #0,x_vel(a0) move.w #0,inertia(a0) bra.s Sonic_Boundary_CheckBottom ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine allowing Sonic to start rolling when he's moving ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1A9D2: Sonic_Roll: if status_sec_isSliding = 7 tst.b status_secondary(a0) bmi.s Obj01_NoRoll else btst #status_sec_isSliding,status_secondary(a0) bne.s Obj01_NoRoll endif mvabs.w inertia(a0),d0 cmpi.w #$80,d0 ; is Sonic moving at $80 speed or faster? blo.s Obj01_NoRoll ; if not, branch move.b (Ctrl_1_Held_Logical).w,d0 andi.b #button_left_mask|button_right_mask,d0 ; is left/right being pressed? bne.s Obj01_NoRoll ; if yes, branch btst #button_down,(Ctrl_1_Held_Logical).w ; is down being pressed? bne.s Obj01_ChkRoll ; if yes, branch ; return_1A9F8: Obj01_NoRoll: rts ; --------------------------------------------------------------------------- ; loc_1A9FA: Obj01_ChkRoll: btst #2,status(a0) ; is Sonic already rolling? beq.s Obj01_DoRoll ; if not, branch rts ; --------------------------------------------------------------------------- ; loc_1AA04: Obj01_DoRoll: bset #2,status(a0) move.b #$E,y_radius(a0) move.b #7,x_radius(a0) move.b #AniIDSonAni_Roll,anim(a0) ; use "rolling" animation addq.w #5,y_pos(a0) move.w #SndID_Roll,d0 jsr (PlaySound).l ; play rolling sound tst.w inertia(a0) bne.s return_1AA36 move.w #$200,inertia(a0) return_1AA36: rts ; End of function Sonic_Roll ; --------------------------------------------------------------------------- ; Subroutine allowing Sonic to jump ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1AA38: Sonic_Jump: move.b (Ctrl_1_Press_Logical).w,d0 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 ; is A, B or C pressed? beq.w return_1AAE6 ; if not, return moveq #0,d0 move.b angle(a0),d0 addi.b #$80,d0 bsr.w CalcRoomOverHead cmpi.w #6,d1 ; does Sonic have enough room to jump? blt.w return_1AAE6 ; if not, branch move.w #$680,d2 tst.b (Super_Sonic_flag).w beq.s + move.w #$800,d2 ; set higher jump speed if super + btst #6,status(a0) ; Test if underwater beq.s + move.w #$380,d2 ; set lower jump speed if under + moveq #0,d0 move.b angle(a0),d0 subi.b #$40,d0 jsr (CalcSine).l muls.w d2,d1 asr.l #8,d1 add.w d1,x_vel(a0) ; make Sonic jump (in X... this adds nothing on level ground) muls.w d2,d0 asr.l #8,d0 add.w d0,y_vel(a0) ; make Sonic jump (in Y) bset #1,status(a0) bclr #5,status(a0) addq.l #4,sp move.b #1,jumping(a0) clr.b stick_to_convex(a0) move.w #SndID_Jump,d0 jsr (PlaySound).l ; play jumping sound move.b #$13,y_radius(a0) move.b #9,x_radius(a0) btst #2,status(a0) bne.s Sonic_RollJump move.b #$E,y_radius(a0) move.b #7,x_radius(a0) move.b #AniIDSonAni_Roll,anim(a0) ; use "jumping" animation bset #2,status(a0) addq.w #5,y_pos(a0) return_1AAE6: rts ; --------------------------------------------------------------------------- ; loc_1AAE8: Sonic_RollJump: bset #4,status(a0) ; set the rolling+jumping flag rts ; End of function Sonic_Jump ; --------------------------------------------------------------------------- ; Subroutine letting Sonic control the height of the jump ; when the jump button is released ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; =========================================================================== ; loc_1AAF0: Sonic_JumpHeight: tst.b jumping(a0) ; is Sonic jumping? beq.s Sonic_UpVelCap ; if not, branch move.w #-$400,d1 btst #6,status(a0) ; is Sonic underwater? beq.s + ; if not, branch move.w #-$200,d1 + cmp.w y_vel(a0),d1 ; is Sonic going up faster than d1? ble.s + ; if not, branch move.b (Ctrl_1_Held_Logical).w,d0 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 ; is a jump button pressed? bne.s + ; if yes, branch move.w d1,y_vel(a0) ; immediately reduce Sonic's upward speed to d1 + tst.b y_vel(a0) ; is Sonic exactly at the height of his jump? beq.s Sonic_CheckGoSuper ; if yes, test for turning into Super Sonic rts ; --------------------------------------------------------------------------- ; loc_1AB22: Sonic_UpVelCap: tst.b pinball_mode(a0) ; is Sonic charging a spindash or in a rolling-only area? bne.s return_1AB36 ; if yes, return cmpi.w #-$FC0,y_vel(a0) ; is Sonic moving up really fast? bge.s return_1AB36 ; if not, return move.w #-$FC0,y_vel(a0) ; cap upward speed return_1AB36: rts ; End of subroutine Sonic_JumpHeight ; --------------------------------------------------------------------------- ; Subroutine called at the peak of a jump that transforms Sonic into Super Sonic ; if he has enough rings and emeralds ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1AB38: test_set_SS: Sonic_CheckGoSuper: tst.b (Super_Sonic_flag).w ; is Sonic already Super? bne.s return_1ABA4 ; if yes, branch cmpi.b #7,(Emerald_count).w ; does Sonic have exactly 7 emeralds? bne.s return_1ABA4 ; if not, branch cmpi.w #50,(Ring_count).w ; does Sonic have at least 50 rings? blo.s return_1ABA4 ; if not, branch if gameRevision=2 ; fixes a bug where the player can get stuck if transforming at the end of a level tst.b (Update_HUD_timer).w ; has Sonic reached the end of the act? beq.s return_1ABA4 ; if yes, branch endif move.b #1,(Super_Sonic_palette).w move.b #$F,(Palette_timer).w move.b #1,(Super_Sonic_flag).w move.b #$81,obj_control(a0) move.b #AniIDSupSonAni_Transform,anim(a0) ; use transformation animation move.b #ObjID_SuperSonicStars,(SuperSonicStars+id).w ; load Obj7E (super sonic stars object) at $FFFFD040 move.w #$A00,(Sonic_top_speed).w move.w #$30,(Sonic_acceleration).w move.w #$100,(Sonic_deceleration).w move.w #0,invincibility_time(a0) bset #status_sec_isInvincible,status_secondary(a0) ; make Sonic invincible move.w #SndID_SuperTransform,d0 jsr (PlaySound).l ; Play transformation sound effect. move.w #MusID_SuperSonic,d0 jmp (PlayMusic).l ; load the Super Sonic song and return ; --------------------------------------------------------------------------- return_1ABA4: rts ; End of subroutine Sonic_CheckGoSuper ; --------------------------------------------------------------------------- ; Subroutine doing the extra logic for Super Sonic ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1ABA6: Sonic_Super: tst.b (Super_Sonic_flag).w ; Ignore all this code if not Super Sonic beq.w return_1AC3C tst.b (Update_HUD_timer).w beq.s Sonic_RevertToNormal ; ? subq.w #1,(Super_Sonic_frame_count).w bpl.w return_1AC3C move.w #60,(Super_Sonic_frame_count).w ; Reset frame counter to 60 tst.w (Ring_count).w beq.s Sonic_RevertToNormal ori.b #1,(Update_HUD_rings).w cmpi.w #1,(Ring_count).w beq.s + cmpi.w #10,(Ring_count).w beq.s + cmpi.w #100,(Ring_count).w bne.s ++ + ori.b #$80,(Update_HUD_rings).w + subq.w #1,(Ring_count).w bne.s return_1AC3C ; loc_1ABF2: Sonic_RevertToNormal: move.b #2,(Super_Sonic_palette).w ; Remove rotating palette move.w #$28,(Palette_frame).w move.b #0,(Super_Sonic_flag).w move.b #1,next_anim(a0) ; Change animation back to normal ? move.w #1,invincibility_time(a0) ; Remove invincibility move.w #$600,(Sonic_top_speed).w move.w #$C,(Sonic_acceleration).w move.w #$80,(Sonic_deceleration).w btst #6,status(a0) ; Check if underwater, return if not beq.s return_1AC3C move.w #$300,(Sonic_top_speed).w move.w #6,(Sonic_acceleration).w move.w #$40,(Sonic_deceleration).w return_1AC3C: rts ; End of subroutine Sonic_Super ; --------------------------------------------------------------------------- ; Subroutine to check for starting to charge a spindash ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1AC3E: Sonic_CheckSpindash: tst.b spindash_flag(a0) bne.s Sonic_UpdateSpindash cmpi.b #AniIDSonAni_Duck,anim(a0) bne.s return_1AC8C move.b (Ctrl_1_Press_Logical).w,d0 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 beq.w return_1AC8C move.b #AniIDSonAni_Spindash,anim(a0) move.w #SndID_SpindashRev,d0 jsr (PlaySound).l addq.l #4,sp move.b #1,spindash_flag(a0) move.w #0,spindash_counter(a0) cmpi.b #$C,air_left(a0) ; if he's drowning, branch to not make dust blo.s + move.b #2,(Sonic_Dust+anim).w + bsr.w Sonic_LevelBound bsr.w AnglePos return_1AC8C: rts ; End of subroutine Sonic_CheckSpindash ; --------------------------------------------------------------------------- ; Subrouting to update an already-charging spindash ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1AC8E: Sonic_UpdateSpindash: move.b (Ctrl_1_Held_Logical).w,d0 btst #button_down,d0 bne.w Sonic_ChargingSpindash ; unleash the charged spindash and start rolling quickly: move.b #$E,y_radius(a0) move.b #7,x_radius(a0) move.b #AniIDSonAni_Roll,anim(a0) addq.w #5,y_pos(a0) ; add the difference between Sonic's rolling and standing heights move.b #0,spindash_flag(a0) moveq #0,d0 move.b spindash_counter(a0),d0 add.w d0,d0 move.w SpindashSpeeds(pc,d0.w),inertia(a0) tst.b (Super_Sonic_flag).w beq.s + move.w SpindashSpeedsSuper(pc,d0.w),inertia(a0) + move.w inertia(a0),d0 subi.w #$800,d0 add.w d0,d0 andi.w #$1F00,d0 neg.w d0 addi.w #$2000,d0 move.w d0,(Horiz_scroll_delay_val).w btst #0,status(a0) beq.s + neg.w inertia(a0) + bset #2,status(a0) move.b #0,(Sonic_Dust+anim).w move.w #SndID_SpindashRelease,d0 ; spindash zoom sound jsr (PlaySound).l bra.s Obj01_Spindash_ResetScr ; =========================================================================== ; word_1AD0C: SpindashSpeeds: dc.w $800 ; 0 dc.w $880 ; 1 dc.w $900 ; 2 dc.w $980 ; 3 dc.w $A00 ; 4 dc.w $A80 ; 5 dc.w $B00 ; 6 dc.w $B80 ; 7 dc.w $C00 ; 8 ; word_1AD1E: SpindashSpeedsSuper: dc.w $B00 ; 0 dc.w $B80 ; 1 dc.w $C00 ; 2 dc.w $C80 ; 3 dc.w $D00 ; 4 dc.w $D80 ; 5 dc.w $E00 ; 6 dc.w $E80 ; 7 dc.w $F00 ; 8 ; =========================================================================== ; loc_1AD30: Sonic_ChargingSpindash: ; If still charging the dash... tst.w spindash_counter(a0) beq.s + move.w spindash_counter(a0),d0 lsr.w #5,d0 sub.w d0,spindash_counter(a0) bcc.s + move.w #0,spindash_counter(a0) + move.b (Ctrl_1_Press_Logical).w,d0 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 beq.w Obj01_Spindash_ResetScr move.w #(AniIDSonAni_Spindash<<8),anim(a0) move.w #SndID_SpindashRev,d0 jsr (PlaySound).l addi.w #$200,spindash_counter(a0) cmpi.w #$800,spindash_counter(a0) blo.s Obj01_Spindash_ResetScr move.w #$800,spindash_counter(a0) ; loc_1AD78: Obj01_Spindash_ResetScr: addq.l #4,sp cmpi.w #(224/2)-16,(Camera_Y_pos_bias).w beq.s loc_1AD8C bhs.s + addq.w #4,(Camera_Y_pos_bias).w + subq.w #2,(Camera_Y_pos_bias).w loc_1AD8C: bsr.w Sonic_LevelBound bsr.w AnglePos rts ; End of subroutine Sonic_UpdateSpindash ; --------------------------------------------------------------------------- ; Subroutine to slow Sonic walking up a slope ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1AD96: Sonic_SlopeResist: move.b angle(a0),d0 addi.b #$60,d0 cmpi.b #$C0,d0 bhs.s return_1ADCA move.b angle(a0),d0 jsr (CalcSine).l muls.w #$20,d0 asr.l #8,d0 tst.w inertia(a0) beq.s return_1ADCA bmi.s loc_1ADC6 tst.w d0 beq.s + add.w d0,inertia(a0) ; change Sonic's $14 + rts ; --------------------------------------------------------------------------- loc_1ADC6: add.w d0,inertia(a0) return_1ADCA: rts ; End of subroutine Sonic_SlopeResist ; --------------------------------------------------------------------------- ; Subroutine to push Sonic down a slope while he's rolling ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1ADCC: Sonic_RollRepel: move.b angle(a0),d0 addi.b #$60,d0 cmpi.b #-$40,d0 bhs.s return_1AE06 move.b angle(a0),d0 jsr (CalcSine).l muls.w #$50,d0 asr.l #8,d0 tst.w inertia(a0) bmi.s loc_1ADFC tst.w d0 bpl.s loc_1ADF6 asr.l #2,d0 loc_1ADF6: add.w d0,inertia(a0) rts ; =========================================================================== loc_1ADFC: tst.w d0 bmi.s loc_1AE02 asr.l #2,d0 loc_1AE02: add.w d0,inertia(a0) return_1AE06: rts ; End of function Sonic_RollRepel ; --------------------------------------------------------------------------- ; Subroutine to push Sonic down a slope ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1AE08: Sonic_SlopeRepel: nop tst.b stick_to_convex(a0) bne.s return_1AE42 tst.w move_lock(a0) bne.s loc_1AE44 move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 beq.s return_1AE42 mvabs.w inertia(a0),d0 cmpi.w #$280,d0 bhs.s return_1AE42 clr.w inertia(a0) bset #1,status(a0) move.w #$1E,move_lock(a0) return_1AE42: rts ; =========================================================================== loc_1AE44: subq.w #1,move_lock(a0) rts ; End of function Sonic_SlopeRepel ; --------------------------------------------------------------------------- ; Subroutine to return Sonic's angle to 0 as he jumps ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1AE4A: Sonic_JumpAngle: move.b angle(a0),d0 ; get Sonic's angle beq.s Sonic_JumpFlip ; if already 0, branch bpl.s loc_1AE5A ; if higher than 0, branch addq.b #2,d0 ; increase angle bcc.s BranchTo_Sonic_JumpAngleSet moveq #0,d0 BranchTo_Sonic_JumpAngleSet bra.s Sonic_JumpAngleSet ; =========================================================================== loc_1AE5A: subq.b #2,d0 ; decrease angle bcc.s Sonic_JumpAngleSet moveq #0,d0 ; loc_1AE60: Sonic_JumpAngleSet: move.b d0,angle(a0) ; End of function Sonic_JumpAngle ; continue straight to Sonic_JumpFlip ; --------------------------------------------------------------------------- ; Updates Sonic's secondary angle if he's tumbling ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1AE64: Sonic_JumpFlip: move.b flip_angle(a0),d0 beq.s return_1AEA8 tst.w inertia(a0) bmi.s Sonic_JumpLeftFlip ; loc_1AE70: Sonic_JumpRightFlip: move.b flip_speed(a0),d1 add.b d1,d0 bcc.s BranchTo_Sonic_JumpFlipSet subq.b #1,flips_remaining(a0) bcc.s BranchTo_Sonic_JumpFlipSet move.b #0,flips_remaining(a0) moveq #0,d0 BranchTo_Sonic_JumpFlipSet bra.s Sonic_JumpFlipSet ; =========================================================================== ; loc_1AE88: Sonic_JumpLeftFlip: tst.b flip_turned(a0) bne.s Sonic_JumpRightFlip move.b flip_speed(a0),d1 sub.b d1,d0 bcc.s Sonic_JumpFlipSet subq.b #1,flips_remaining(a0) bcc.s Sonic_JumpFlipSet move.b #0,flips_remaining(a0) moveq #0,d0 ; loc_1AEA4: Sonic_JumpFlipSet: move.b d0,flip_angle(a0) return_1AEA8: rts ; End of function Sonic_JumpFlip ; --------------------------------------------------------------------------- ; Subroutine for Sonic to interact with the floor and walls when he's in the air ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1AEAA: Sonic_Floor: Sonic_DoLevelCollision: move.l #Primary_Collision,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s + move.l #Secondary_Collision,(Collision_addr).w + move.b lrb_solid_bit(a0),d5 move.w x_vel(a0),d1 move.w y_vel(a0),d2 jsr (CalcAngle).l subi.b #$20,d0 andi.b #$C0,d0 cmpi.b #$40,d0 beq.w Sonic_HitLeftWall cmpi.b #$80,d0 beq.w Sonic_HitCeilingAndWalls cmpi.b #$C0,d0 beq.w Sonic_HitRightWall bsr.w CheckLeftWallDist tst.w d1 bpl.s + sub.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Sonic since he hit a wall + bsr.w CheckRightWallDist tst.w d1 bpl.s + add.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Sonic since he hit a wall + bsr.w Sonic_CheckFloor tst.w d1 bpl.s return_1AF8A move.b y_vel(a0),d2 addq.b #8,d2 neg.b d2 cmp.b d2,d1 bge.s + cmp.b d2,d0 blt.s return_1AF8A + add.w d1,y_pos(a0) move.b d3,angle(a0) bsr.w Sonic_ResetOnFloor move.b d3,d0 addi.b #$20,d0 andi.b #$40,d0 bne.s loc_1AF68 move.b d3,d0 addi.b #$10,d0 andi.b #$20,d0 beq.s loc_1AF5A asr y_vel(a0) bra.s loc_1AF7C ; =========================================================================== loc_1AF5A: move.w #0,y_vel(a0) move.w x_vel(a0),inertia(a0) rts ; =========================================================================== loc_1AF68: move.w #0,x_vel(a0) ; stop Sonic since he hit a wall cmpi.w #$FC0,y_vel(a0) ble.s loc_1AF7C move.w #$FC0,y_vel(a0) loc_1AF7C: move.w y_vel(a0),inertia(a0) tst.b d3 bpl.s return_1AF8A neg.w inertia(a0) return_1AF8A: rts ; =========================================================================== ; loc_1AF8C: Sonic_HitLeftWall: bsr.w CheckLeftWallDist tst.w d1 bpl.s Sonic_HitCeiling ; branch if distance is positive (not inside wall) sub.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Sonic since he hit a wall move.w y_vel(a0),inertia(a0) rts ; =========================================================================== ; loc_1AFA6: Sonic_HitCeiling: bsr.w Sonic_CheckCeiling tst.w d1 bpl.s Sonic_HitFloor ; branch if distance is positive (not inside ceiling) sub.w d1,y_pos(a0) tst.w y_vel(a0) bpl.s return_1AFBE move.w #0,y_vel(a0) ; stop Sonic in y since he hit a ceiling return_1AFBE: rts ; =========================================================================== ; loc_1AFC0: Sonic_HitFloor: tst.w y_vel(a0) bmi.s return_1AFE6 bsr.w Sonic_CheckFloor tst.w d1 bpl.s return_1AFE6 add.w d1,y_pos(a0) move.b d3,angle(a0) bsr.w Sonic_ResetOnFloor move.w #0,y_vel(a0) move.w x_vel(a0),inertia(a0) return_1AFE6: rts ; =========================================================================== ; loc_1AFE8: Sonic_HitCeilingAndWalls: bsr.w CheckLeftWallDist tst.w d1 bpl.s + sub.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Sonic since he hit a wall + bsr.w CheckRightWallDist tst.w d1 bpl.s + add.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Sonic since he hit a wall + bsr.w Sonic_CheckCeiling tst.w d1 bpl.s return_1B042 sub.w d1,y_pos(a0) move.b d3,d0 addi.b #$20,d0 andi.b #$40,d0 bne.s loc_1B02C move.w #0,y_vel(a0) ; stop Sonic in y since he hit a ceiling rts ; =========================================================================== loc_1B02C: move.b d3,angle(a0) bsr.w Sonic_ResetOnFloor move.w y_vel(a0),inertia(a0) tst.b d3 bpl.s return_1B042 neg.w inertia(a0) return_1B042: rts ; =========================================================================== ; loc_1B044: Sonic_HitRightWall: bsr.w CheckRightWallDist tst.w d1 bpl.s Sonic_HitCeiling2 add.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Sonic since he hit a wall move.w y_vel(a0),inertia(a0) rts ; =========================================================================== ; identical to Sonic_HitCeiling... ; loc_1B05E: Sonic_HitCeiling2: bsr.w Sonic_CheckCeiling tst.w d1 bpl.s Sonic_HitFloor2 sub.w d1,y_pos(a0) tst.w y_vel(a0) bpl.s return_1B076 move.w #0,y_vel(a0) ; stop Sonic in y since he hit a ceiling return_1B076: rts ; =========================================================================== ; identical to Sonic_HitFloor... ; loc_1B078: Sonic_HitFloor2: tst.w y_vel(a0) bmi.s return_1B09E bsr.w Sonic_CheckFloor tst.w d1 bpl.s return_1B09E add.w d1,y_pos(a0) move.b d3,angle(a0) bsr.w Sonic_ResetOnFloor move.w #0,y_vel(a0) move.w x_vel(a0),inertia(a0) return_1B09E: rts ; End of function Sonic_DoLevelCollision ; --------------------------------------------------------------------------- ; Subroutine to reset Sonic's mode when he lands on the floor ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1B0A0: Sonic_ResetOnFloor: tst.b pinball_mode(a0) bne.s Sonic_ResetOnFloor_Part3 move.b #AniIDSonAni_Walk,anim(a0) ; loc_1B0AC: Sonic_ResetOnFloor_Part2: ; some routines outside of Tails' code can call Sonic_ResetOnFloor_Part2 ; when they mean to call Tails_ResetOnFloor_Part2, so fix that here _cmpi.b #ObjID_Sonic,id(a0) ; is this object ID Sonic (obj01)? bne.w Tails_ResetOnFloor_Part2 ; if not, branch to the Tails version of this code btst #2,status(a0) beq.s Sonic_ResetOnFloor_Part3 bclr #2,status(a0) move.b #$13,y_radius(a0) ; this increases Sonic's collision height to standing move.b #9,x_radius(a0) move.b #AniIDSonAni_Walk,anim(a0) ; use running/walking/standing animation subq.w #5,y_pos(a0) ; move Sonic up 5 pixels so the increased height doesn't push him into the ground ; loc_1B0DA: Sonic_ResetOnFloor_Part3: bclr #1,status(a0) bclr #5,status(a0) bclr #4,status(a0) move.b #0,jumping(a0) move.w #0,(Chain_Bonus_counter).w move.b #0,flip_angle(a0) move.b #0,flip_turned(a0) move.b #0,flips_remaining(a0) move.w #0,(Sonic_Look_delay_counter).w cmpi.b #AniIDSonAni_Hang2,anim(a0) bne.s return_1B11E move.b #AniIDSonAni_Walk,anim(a0) return_1B11E: rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Sonic when he gets hurt ; --------------------------------------------------------------------------- ; loc_1B120: Obj_01_Sub_4: Obj01_Hurt: tst.w (Debug_mode_flag).w beq.s Obj01_Hurt_Normal btst #button_B,(Ctrl_1_Press).w beq.s Obj01_Hurt_Normal move.w #1,(Debug_placement_mode).w clr.b (Control_Locked).w rts ; --------------------------------------------------------------------------- ; loc_1B13A: Obj01_Hurt_Normal: tst.b routine_secondary(a0) bmi.w Sonic_HurtInstantRecover jsr (ObjectMove).l addi.w #$30,y_vel(a0) btst #6,status(a0) beq.s + subi.w #$20,y_vel(a0) + cmpi.w #-$100,(Camera_Min_Y_pos).w bne.s + andi.w #$7FF,y_pos(a0) + bsr.w Sonic_HurtStop bsr.w Sonic_LevelBound bsr.w Sonic_RecordPos bsr.w Sonic_Animate bsr.w LoadSonicDynPLC jmp (DisplaySprite).l ; =========================================================================== ; loc_1B184: Sonic_HurtStop: move.w (Camera_Max_Y_pos_now).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 blt.w JmpTo_KillCharacter bsr.w Sonic_DoLevelCollision btst #1,status(a0) bne.s return_1B1C8 moveq #0,d0 move.w d0,y_vel(a0) move.w d0,x_vel(a0) move.w d0,inertia(a0) move.b d0,obj_control(a0) move.b #AniIDSonAni_Walk,anim(a0) subq.b #2,routine(a0) ; => Obj01_Control move.w #$78,invulnerable_time(a0) move.b #0,spindash_flag(a0) return_1B1C8: rts ; =========================================================================== ; makes Sonic recover control after being hurt before landing ; seems to be unused ; loc_1B1CA: Sonic_HurtInstantRecover: subq.b #2,routine(a0) ; => Obj01_Control move.b #0,routine_secondary(a0) bsr.w Sonic_RecordPos bsr.w Sonic_Animate bsr.w LoadSonicDynPLC jmp (DisplaySprite).l ; =========================================================================== ; --------------------------------------------------------------------------- ; Sonic when he dies ; ...poor Sonic ; --------------------------------------------------------------------------- ; loc_1B1E6: Obj_01_Sub_6: Obj01_Dead: tst.w (Debug_mode_flag).w beq.s + btst #button_B,(Ctrl_1_Press).w beq.s + move.w #1,(Debug_placement_mode).w clr.b (Control_Locked).w rts + bsr.w CheckGameOver jsr (ObjectMoveAndFall).l bsr.w Sonic_RecordPos bsr.w Sonic_Animate bsr.w LoadSonicDynPLC jmp (DisplaySprite).l ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1B21C: CheckGameOver: move.b #1,(Scroll_lock).w move.b #0,spindash_flag(a0) move.w (Camera_Max_Y_pos_now).w,d0 addi.w #$100,d0 cmp.w y_pos(a0),d0 bge.w return_1B31A move.b #8,routine(a0) ; => Obj01_Gone move.w #$3C,restart_countdown(a0) addq.b #1,(Update_HUD_lives).w ; update lives counter subq.b #1,(Life_count).w ; subtract 1 from number of lives bne.s Obj01_ResetLevel ; if it's not a game over, branch move.w #0,restart_countdown(a0) move.b #ObjID_GameOver,(GameOver_GameText+id).w ; load Obj39 (game over text) move.b #ObjID_GameOver,(GameOver_OverText+id).w ; load Obj39 (game over text) move.b #1,(GameOver_OverText+mapping_frame).w move.w a0,(GameOver_GameText+parent).w clr.b (Time_Over_flag).w ; loc_1B26E: Obj01_Finished: clr.b (Update_HUD_timer).w clr.b (Update_HUD_timer_2P).w move.b #8,routine(a0) ; => Obj01_Gone move.w #MusID_GameOver,d0 jsr (PlayMusic).l moveq #PLCID_GameOver,d0 jmp (LoadPLC).l ; End of function CheckGameOver ; =========================================================================== ; --------------------------------------------------------------------------- ; Sonic when the level is restarted ; --------------------------------------------------------------------------- ; loc_1B28E: Obj01_ResetLevel: tst.b (Time_Over_flag).w beq.s Obj01_ResetLevel_Part2 move.w #0,restart_countdown(a0) move.b #ObjID_TimeOver,(TimeOver_TimeText+id).w ; load Obj39 move.b #ObjID_TimeOver,(TimeOver_OverText+id).w ; load Obj39 move.b #2,(TimeOver_TimeText+mapping_frame).w move.b #3,(TimeOver_OverText+mapping_frame).w move.w a0,(TimeOver_TimeText+parent).w bra.s Obj01_Finished ; --------------------------------------------------------------------------- Obj01_ResetLevel_Part2: tst.w (Two_player_mode).w beq.s return_1B31A move.b #0,(Scroll_lock).w move.b #$A,routine(a0) ; => Obj01_Respawning move.w (Saved_x_pos).w,x_pos(a0) move.w (Saved_y_pos).w,y_pos(a0) move.w (Saved_art_tile).w,art_tile(a0) move.w (Saved_Solid_bits).w,top_solid_bit(a0) clr.w (Ring_count).w clr.b (Extra_life_flags).w move.b #0,obj_control(a0) move.b #5,anim(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) move.w #0,inertia(a0) move.b #2,status(a0) move.w #0,move_lock(a0) move.w #0,restart_countdown(a0) return_1B31A: rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Sonic when he's offscreen and waiting for the level to restart ; --------------------------------------------------------------------------- ; loc_1B31C: Obj_01_Sub_8: Obj01_Gone: tst.w restart_countdown(a0) beq.s + subq.w #1,restart_countdown(a0) bne.s + move.w #1,(Level_Inactive_flag).w + rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Sonic when he's waiting for the camera to scroll back to where he respawned ; --------------------------------------------------------------------------- ; loc_1B330: Obj_01_Sub_A: Obj01_Respawning: tst.w (Camera_X_pos_diff).w bne.s + tst.w (Camera_Y_pos_diff).w bne.s + move.b #2,routine(a0) ; => Obj01_Control + bsr.w Sonic_Animate bsr.w LoadSonicDynPLC jmp (DisplaySprite).l ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to animate Sonic's sprites ; See also: AnimateSprite ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1B350: Sonic_Animate: lea (SonicAniData).l,a1 tst.b (Super_Sonic_flag).w beq.s + lea (SuperSonicAniData).l,a1 + moveq #0,d0 move.b anim(a0),d0 cmp.b next_anim(a0),d0 ; has animation changed? beq.s SAnim_Do ; if not, branch move.b d0,next_anim(a0) ; set to next animation move.b #0,anim_frame(a0) ; reset animation frame move.b #0,anim_frame_duration(a0) ; reset frame duration bclr #5,status(a0) ; loc_1B384: SAnim_Do: add.w d0,d0 adda.w (a1,d0.w),a1 ; calculate address of appropriate animation script move.b (a1),d0 bmi.s SAnim_WalkRun ; if animation is walk/run/roll/jump, branch move.b status(a0),d1 andi.b #1,d1 andi.b #$FC,render_flags(a0) or.b d1,render_flags(a0) subq.b #1,anim_frame_duration(a0) ; subtract 1 from frame duration bpl.s SAnim_Delay ; if time remains, branch move.b d0,anim_frame_duration(a0) ; load frame duration ; loc_1B3AA: SAnim_Do2: moveq #0,d1 move.b anim_frame(a0),d1 ; load current frame number move.b 1(a1,d1.w),d0 ; read sprite number from script cmpi.b #$F0,d0 bhs.s SAnim_End_FF ; if animation is complete, branch ; loc_1B3BA: SAnim_Next: move.b d0,mapping_frame(a0) ; load sprite number addq.b #1,anim_frame(a0) ; go to next frame ; return_1B3C2: SAnim_Delay: rts ; =========================================================================== ; loc_1B3C4: SAnim_End_FF: addq.b #1,d0 ; is the end flag = $FF ? bne.s SAnim_End_FE ; if not, branch move.b #0,anim_frame(a0) ; restart the animation move.b 1(a1),d0 ; read sprite number bra.s SAnim_Next ; =========================================================================== ; loc_1B3D4: SAnim_End_FE: addq.b #1,d0 ; is the end flag = $FE ? bne.s SAnim_End_FD ; if not, branch move.b 2(a1,d1.w),d0 ; read the next byte in the script sub.b d0,anim_frame(a0) ; jump back d0 bytes in the script sub.b d0,d1 move.b 1(a1,d1.w),d0 ; read sprite number bra.s SAnim_Next ; =========================================================================== ; loc_1B3E8: SAnim_End_FD: addq.b #1,d0 ; is the end flag = $FD ? bne.s SAnim_End ; if not, branch move.b 2(a1,d1.w),anim(a0) ; read next byte, run that animation ; return_1B3F2: SAnim_End: rts ; =========================================================================== ; loc_1B3F4: SAnim_WalkRun: addq.b #1,d0 ; is the start flag = $FF ? bne.w SAnim_Roll ; if not, branch moveq #0,d0 ; is animation walking/running? move.b flip_angle(a0),d0 ; if not, branch bne.w SAnim_Tumble moveq #0,d1 move.b angle(a0),d0 ; get Sonic's angle bmi.s + beq.s + subq.b #1,d0 + move.b status(a0),d2 andi.b #1,d2 ; is Sonic mirrored horizontally? bne.s + ; if yes, branch not.b d0 ; reverse angle + addi.b #$10,d0 ; add $10 to angle bpl.s + ; if angle is $0-$7F, branch moveq #3,d1 + andi.b #$FC,render_flags(a0) eor.b d1,d2 or.b d2,render_flags(a0) btst #5,status(a0) bne.w SAnim_Push lsr.b #4,d0 ; divide angle by 16 andi.b #6,d0 ; angle must be 0, 2, 4 or 6 mvabs.w inertia(a0),d2 ; get Sonic's "speed" for animation purposes if status_sec_isSliding = 7 tst.b status_secondary(a0) bpl.w + else btst #status_sec_isSliding,status_secondary(a0) beq.w + endif add.w d2,d2 + tst.b (Super_Sonic_flag).w bne.s SAnim_Super lea (SonAni_Run).l,a1 ; use running animation cmpi.w #$600,d2 ; is Sonic at running speed? bhs.s + ; use running animation lea (SonAni_Walk).l,a1 ; if yes, branch add.b d0,d0 + add.b d0,d0 move.b d0,d3 moveq #0,d1 move.b anim_frame(a0),d1 move.b 1(a1,d1.w),d0 cmpi.b #-1,d0 bne.s + move.b #0,anim_frame(a0) move.b 1(a1),d0 + move.b d0,mapping_frame(a0) add.b d3,mapping_frame(a0) subq.b #1,anim_frame_duration(a0) bpl.s return_1B4AC neg.w d2 addi.w #$800,d2 bpl.s + moveq #0,d2 + lsr.w #8,d2 move.b d2,anim_frame_duration(a0) ; modify frame duration addq.b #1,anim_frame(a0) ; modify frame number return_1B4AC: rts ; =========================================================================== ; loc_1B4AE: SAnim_Super: lea (SupSonAni_Run).l,a1 ; use fast animation cmpi.w #$800,d2 ; is Sonic moving fast? bhs.s SAnim_SuperRun ; if yes, branch lea (SupSonAni_Walk).l,a1 ; use slower animation add.b d0,d0 add.b d0,d0 bra.s SAnim_SuperWalk ; --------------------------------------------------------------------------- ; loc_1B4C6: SAnim_SuperRun: lsr.b #1,d0 ; loc_1B4C8: SAnim_SuperWalk: move.b d0,d3 moveq #0,d1 move.b anim_frame(a0),d1 move.b 1(a1,d1.w),d0 cmpi.b #-1,d0 bne.s + move.b #0,anim_frame(a0) move.b 1(a1),d0 + move.b d0,mapping_frame(a0) add.b d3,mapping_frame(a0) move.b (Timer_frames+1).w,d1 andi.b #3,d1 bne.s + cmpi.b #$B5,mapping_frame(a0) bhs.s + addi.b #$20,mapping_frame(a0) + subq.b #1,anim_frame_duration(a0) bpl.s return_1B51E neg.w d2 addi.w #$800,d2 bpl.s + moveq #0,d2 + lsr.w #8,d2 move.b d2,anim_frame_duration(a0) addq.b #1,anim_frame(a0) return_1B51E: rts ; =========================================================================== ; loc_1B520: SAnim_Tumble: move.b flip_angle(a0),d0 moveq #0,d1 move.b status(a0),d2 andi.b #1,d2 bne.s SAnim_Tumble_Left andi.b #$FC,render_flags(a0) addi.b #$B,d0 divu.w #$16,d0 addi.b #$5F,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_duration(a0) rts ; =========================================================================== ; loc_1B54E: SAnim_Tumble_Left: andi.b #$FC,render_flags(a0) tst.b flip_turned(a0) beq.s loc_1B566 ori.b #1,render_flags(a0) addi.b #$B,d0 bra.s loc_1B572 ; =========================================================================== loc_1B566: ori.b #3,render_flags(a0) neg.b d0 addi.b #$8F,d0 loc_1B572: divu.w #$16,d0 addi.b #$5F,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_duration(a0) rts ; =========================================================================== ; loc_1B586: SAnim_Roll: subq.b #1,anim_frame_duration(a0) ; subtract 1 from frame duration bpl.w SAnim_Delay ; if time remains, branch addq.b #1,d0 ; is the start flag = $FE ? bne.s SAnim_Push ; if not, branch mvabs.w inertia(a0),d2 lea (SonAni_Roll2).l,a1 cmpi.w #$600,d2 bhs.s + lea (SonAni_Roll).l,a1 + neg.w d2 addi.w #$400,d2 bpl.s + moveq #0,d2 + lsr.w #8,d2 move.b d2,anim_frame_duration(a0) move.b status(a0),d1 andi.b #1,d1 andi.b #$FC,render_flags(a0) or.b d1,render_flags(a0) bra.w SAnim_Do2 ; =========================================================================== SAnim_Push: subq.b #1,anim_frame_duration(a0) ; subtract 1 from frame duration bpl.w SAnim_Delay ; if time remains, branch move.w inertia(a0),d2 bmi.s + neg.w d2 + addi.w #$800,d2 bpl.s + moveq #0,d2 + lsr.w #6,d2 move.b d2,anim_frame_duration(a0) lea (SonAni_Push).l,a1 tst.b (Super_Sonic_flag).w beq.s + lea (SupSonAni_Push).l,a1 + move.b status(a0),d1 andi.b #1,d1 andi.b #$FC,render_flags(a0) or.b d1,render_flags(a0) bra.w SAnim_Do2 ; =========================================================================== ; --------------------------------------------------------------------------- ; Animation script - Sonic ; --------------------------------------------------------------------------- ; off_1B618: SonicAniData: offsetTable SonAni_Walk_ptr: offsetTableEntry.w SonAni_Walk ; 0 ; 0 SonAni_Run_ptr: offsetTableEntry.w SonAni_Run ; 1 ; 1 SonAni_Roll_ptr: offsetTableEntry.w SonAni_Roll ; 2 ; 2 SonAni_Roll2_ptr: offsetTableEntry.w SonAni_Roll2 ; 3 ; 3 SonAni_Push_ptr: offsetTableEntry.w SonAni_Push ; 4 ; 4 SonAni_Wait_ptr: offsetTableEntry.w SonAni_Wait ; 5 ; 5 SonAni_Balance_ptr: offsetTableEntry.w SonAni_Balance ; 6 ; 6 SonAni_LookUp_ptr: offsetTableEntry.w SonAni_LookUp ; 7 ; 7 SonAni_Duck_ptr: offsetTableEntry.w SonAni_Duck ; 8 ; 8 SonAni_Spindash_ptr: offsetTableEntry.w SonAni_Spindash ; 9 ; 9 SonAni_Blink_ptr: offsetTableEntry.w SonAni_Blink ; 10 ; $A SonAni_GetUp_ptr: offsetTableEntry.w SonAni_GetUp ; 11 ; $B SonAni_Balance2_ptr: offsetTableEntry.w SonAni_Balance2 ; 12 ; $C SonAni_Stop_ptr: offsetTableEntry.w SonAni_Stop ; 13 ; $D SonAni_Float_ptr: offsetTableEntry.w SonAni_Float ; 14 ; $E SonAni_Float2_ptr: offsetTableEntry.w SonAni_Float2 ; 15 ; $F SonAni_Spring_ptr: offsetTableEntry.w SonAni_Spring ; 16 ; $10 SonAni_Hang_ptr: offsetTableEntry.w SonAni_Hang ; 17 ; $11 SonAni_Dash2_ptr: offsetTableEntry.w SonAni_Dash2 ; 18 ; $12 SonAni_Dash3_ptr: offsetTableEntry.w SonAni_Dash3 ; 19 ; $13 SonAni_Hang2_ptr: offsetTableEntry.w SonAni_Hang2 ; 20 ; $14 SonAni_Bubble_ptr: offsetTableEntry.w SonAni_Bubble ; 21 ; $15 SonAni_DeathBW_ptr: offsetTableEntry.w SonAni_DeathBW ; 22 ; $16 SonAni_Drown_ptr: offsetTableEntry.w SonAni_Drown ; 23 ; $17 SonAni_Death_ptr: offsetTableEntry.w SonAni_Death ; 24 ; $18 SonAni_Hurt_ptr: offsetTableEntry.w SonAni_Hurt ; 25 ; $19 SonAni_Hurt2_ptr: offsetTableEntry.w SonAni_Hurt ; 26 ; $1A SonAni_Slide_ptr: offsetTableEntry.w SonAni_Slide ; 27 ; $1B SonAni_Blank_ptr: offsetTableEntry.w SonAni_Blank ; 28 ; $1C SonAni_Balance3_ptr: offsetTableEntry.w SonAni_Balance3 ; 29 ; $1D SonAni_Balance4_ptr: offsetTableEntry.w SonAni_Balance4 ; 30 ; $1E SupSonAni_Transform_ptr: offsetTableEntry.w SupSonAni_Transform ; 31 ; $1F SonAni_Lying_ptr: offsetTableEntry.w SonAni_Lying ; 32 ; $20 SonAni_LieDown_ptr: offsetTableEntry.w SonAni_LieDown ; 33 ; $21 SonAni_Walk: dc.b $FF, $F,$10,$11,$12,$13,$14, $D, $E,$FF rev02even SonAni_Run: dc.b $FF,$2D,$2E,$2F,$30,$FF,$FF,$FF,$FF,$FF rev02even SonAni_Roll: dc.b $FE,$3D,$41,$3E,$41,$3F,$41,$40,$41,$FF rev02even SonAni_Roll2: dc.b $FE,$3D,$41,$3E,$41,$3F,$41,$40,$41,$FF rev02even SonAni_Push: dc.b $FD,$48,$49,$4A,$4B,$FF,$FF,$FF,$FF,$FF rev02even SonAni_Wait: dc.b 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 dc.b 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2 dc.b 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 4, 4, 4, 5, 5 dc.b 5, 4, 4, 4, 5, 5, 5, 4, 4, 4, 5, 5, 5, 6, 6, 6 dc.b 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 5, 5, 5, 4, 4, 4 dc.b 5, 5, 5, 4, 4, 4, 5, 5, 5, 4, 4, 4, 5, 5, 5, 6 dc.b 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 5, 5, 5, 4 dc.b 4, 4, 5, 5, 5, 4, 4, 4, 5, 5, 5, 4, 4, 4, 5, 5 dc.b 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 5, 5 dc.b 5, 4, 4, 4, 5, 5, 5, 4, 4, 4, 5, 5, 5, 4, 4, 4 dc.b 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 8, 8 dc.b 8, 9, 9, 9,$FE, 6 rev02even SonAni_Balance: dc.b 9,$CC,$CD,$CE,$CD,$FF rev02even SonAni_LookUp: dc.b 5, $B, $C,$FE, 1 rev02even SonAni_Duck: dc.b 5,$4C,$4D,$FE, 1 rev02even SonAni_Spindash:dc.b 0,$42,$43,$42,$44,$42,$45,$42,$46,$42,$47,$FF rev02even SonAni_Blink: dc.b 1, 2,$FD, 0 rev02even SonAni_GetUp: dc.b 3, $A,$FD, 0 rev02even SonAni_Balance2:dc.b 3,$C8,$C9,$CA,$CB,$FF rev02even SonAni_Stop: dc.b 5,$D2,$D3,$D4,$D5,$FD, 0 ; halt/skidding animation rev02even SonAni_Float: dc.b 7,$54,$59,$FF rev02even SonAni_Float2: dc.b 7,$54,$55,$56,$57,$58,$FF rev02even SonAni_Spring: dc.b $2F,$5B,$FD, 0 rev02even SonAni_Hang: dc.b 1,$50,$51,$FF rev02even SonAni_Dash2: dc.b $F,$43,$43,$43,$FE, 1 rev02even SonAni_Dash3: dc.b $F,$43,$44,$FE, 1 rev02even SonAni_Hang2: dc.b $13,$6B,$6C,$FF rev02even SonAni_Bubble: dc.b $B,$5A,$5A,$11,$12,$FD, 0 ; breathe rev02even SonAni_DeathBW: dc.b $20,$5E,$FF rev02even SonAni_Drown: dc.b $20,$5D,$FF rev02even SonAni_Death: dc.b $20,$5C,$FF rev02even SonAni_Hurt: dc.b $40,$4E,$FF rev02even SonAni_Slide: dc.b 9,$4E,$4F,$FF rev02even SonAni_Blank: dc.b $77, 0,$FD, 0 rev02even SonAni_Balance3:dc.b $13,$D0,$D1,$FF rev02even SonAni_Balance4:dc.b 3,$CF,$C8,$C9,$CA,$CB,$FE, 4 rev02even SonAni_Lying: dc.b 9, 8, 9,$FF rev02even SonAni_LieDown: dc.b 3, 7,$FD, 0 even ; --------------------------------------------------------------------------- ; Animation script - Super Sonic ; (many of these point to the data above this) ; --------------------------------------------------------------------------- SuperSonicAniData: offsetTable offsetTableEntry.w SupSonAni_Walk ; 0 ; 0 offsetTableEntry.w SupSonAni_Run ; 1 ; 1 offsetTableEntry.w SonAni_Roll ; 2 ; 2 offsetTableEntry.w SonAni_Roll2 ; 3 ; 3 offsetTableEntry.w SupSonAni_Push ; 4 ; 4 offsetTableEntry.w SupSonAni_Stand ; 5 ; 5 offsetTableEntry.w SupSonAni_Balance ; 6 ; 6 offsetTableEntry.w SonAni_LookUp ; 7 ; 7 offsetTableEntry.w SupSonAni_Duck ; 8 ; 8 offsetTableEntry.w SonAni_Spindash ; 9 ; 9 offsetTableEntry.w SonAni_Blink ; 10 ; $A offsetTableEntry.w SonAni_GetUp ; 11 ; $B offsetTableEntry.w SonAni_Balance2 ; 12 ; $C offsetTableEntry.w SonAni_Stop ; 13 ; $D offsetTableEntry.w SonAni_Float ; 14 ; $E offsetTableEntry.w SonAni_Float2 ; 15 ; $F offsetTableEntry.w SonAni_Spring ; 16 ; $10 offsetTableEntry.w SonAni_Hang ; 17 ; $11 offsetTableEntry.w SonAni_Dash2 ; 18 ; $12 offsetTableEntry.w SonAni_Dash3 ; 19 ; $13 offsetTableEntry.w SonAni_Hang2 ; 20 ; $14 offsetTableEntry.w SonAni_Bubble ; 21 ; $15 offsetTableEntry.w SonAni_DeathBW ; 22 ; $16 offsetTableEntry.w SonAni_Drown ; 23 ; $17 offsetTableEntry.w SonAni_Death ; 24 ; $18 offsetTableEntry.w SonAni_Hurt ; 25 ; $19 offsetTableEntry.w SonAni_Hurt ; 26 ; $1A offsetTableEntry.w SonAni_Slide ; 27 ; $1B offsetTableEntry.w SonAni_Blank ; 28 ; $1C offsetTableEntry.w SonAni_Balance3 ; 29 ; $1D offsetTableEntry.w SonAni_Balance4 ; 30 ; $1E offsetTableEntry.w SupSonAni_Transform ; 31 ; $1F SupSonAni_Walk: dc.b $FF,$77,$78,$79,$7A,$7B,$7C,$75,$76,$FF rev02even SupSonAni_Run: dc.b $FF,$B5,$B9,$FF,$FF,$FF,$FF,$FF,$FF,$FF rev02even SupSonAni_Push: dc.b $FD,$BD,$BE,$BF,$C0,$FF,$FF,$FF,$FF,$FF rev02even SupSonAni_Stand: dc.b 7,$72,$73,$74,$73,$FF rev02even SupSonAni_Balance: dc.b 9,$C2,$C3,$C4,$C3,$C5,$C6,$C7,$C6,$FF rev02even SupSonAni_Duck: dc.b 5,$C1,$FF rev02even SupSonAni_Transform: dc.b 2,$6D,$6D,$6E,$6E,$6F,$70,$71,$70,$71,$70,$71,$70,$71,$FD, 0 even ; --------------------------------------------------------------------------- ; Sonic pattern loading subroutine ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1B848: LoadSonicDynPLC: moveq #0,d0 move.b mapping_frame(a0),d0 ; load frame number ; loc_1B84E: LoadSonicDynPLC_Part2: cmp.b (Sonic_LastLoadedDPLC).w,d0 beq.s return_1B89A move.b d0,(Sonic_LastLoadedDPLC).w lea (MapRUnc_Sonic).l,a2 add.w d0,d0 adda.w (a2,d0.w),a2 move.w (a2)+,d5 subq.w #1,d5 bmi.s return_1B89A move.w #tiles_to_bytes(ArtTile_ArtUnc_Sonic),d4 ; loc_1B86E: SPLC_ReadEntry: moveq #0,d1 move.w (a2)+,d1 move.w d1,d3 lsr.w #8,d3 andi.w #$F0,d3 addi.w #$10,d3 andi.w #$FFF,d1 lsl.l #5,d1 addi.l #ArtUnc_Sonic,d1 move.w d4,d2 add.w d3,d4 add.w d3,d4 jsr (QueueDMATransfer).l dbf d5,SPLC_ReadEntry ; repeat for number of entries return_1B89A: rts ; =========================================================================== JmpTo_KillCharacter jmp (KillCharacter).l if ~~removeJmpTos align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 02 - Tails ; ---------------------------------------------------------------------------- ; Sprite_1B8A4: Object_Tails: Obj02: ; a0=character cmpi.w #2,(Player_mode).w bne.s + move.w (Camera_Min_X_pos).w,(Tails_Min_X_pos).w move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w move.w (Camera_Max_Y_pos_now).w,(Tails_Max_Y_pos).w + moveq #0,d0 move.b routine(a0),d0 move.w Obj02_Index(pc,d0.w),d1 jmp Obj02_Index(pc,d1.w) ; =========================================================================== ; off_1B8CC: Obj02_States: Obj02_Index: offsetTable offsetTableEntry.w Obj02_Init ; 0 offsetTableEntry.w Obj02_Control ; 2 offsetTableEntry.w Obj02_Hurt ; 4 offsetTableEntry.w Obj02_Dead ; 6 offsetTableEntry.w Obj02_Gone ; 8 offsetTableEntry.w Obj02_Respawning ; $A ; =========================================================================== ; loc_1B8D8: Obj02_Main: Obj02_Init: addq.b #2,routine(a0) ; => Obj02_Normal move.b #$F,y_radius(a0) ; this sets Tails' collision height (2*pixels) to less than Sonic's height move.b #9,x_radius(a0) move.l #MapUnc_Tails,mappings(a0) move.b #2,priority(a0) move.b #$18,width_pixels(a0) move.b #$84,render_flags(a0) ; render_flags(Tails) = $80 | initial render_flags(Sonic) move.w #$600,(Tails_top_speed).w ; set Tails' top speed move.w #$C,(Tails_acceleration).w ; set Tails' acceleration move.w #$80,(Tails_deceleration).w ; set Tails' deceleration cmpi.w #2,(Player_mode).w bne.s Obj02_Init_2Pmode tst.b (Last_star_pole_hit).w bne.s Obj02_Init_Continued ; only happens when not starting at a checkpoint: move.w #make_art_tile(ArtTile_ArtUnc_Tails,0,0),art_tile(a0) bsr.w Adjust2PArtPointer move.b #$C,top_solid_bit(a0) move.b #$D,lrb_solid_bit(a0) move.w x_pos(a0),(Saved_x_pos).w move.w y_pos(a0),(Saved_y_pos).w move.w art_tile(a0),(Saved_art_tile).w move.w top_solid_bit(a0),(Saved_Solid_bits).w bra.s Obj02_Init_Continued ; =========================================================================== ; loc_1B952: Obj02_Init_2Pmode: move.w #make_art_tile(ArtTile_ArtUnc_Tails,0,0),art_tile(a0) bsr.w Adjust2PArtPointer move.w (MainCharacter+top_solid_bit).w,top_solid_bit(a0) tst.w (MainCharacter+art_tile).w bpl.s Obj02_Init_Continued ori.w #high_priority,art_tile(a0) ; loc_1B96E: Obj02_Init_Continued: move.w x_pos(a0),(Saved_x_pos_2P).w move.w y_pos(a0),(Saved_y_pos_2P).w move.w art_tile(a0),(Saved_art_tile_2P).w move.w top_solid_bit(a0),(Saved_Solid_bits_2P).w move.b #0,flips_remaining(a0) move.b #4,flip_speed(a0) move.b #$1E,air_left(a0) move.w #0,(Tails_CPU_routine).w ; set AI state to TailsCPU_Init move.w #0,(Tails_control_counter).w move.w #0,(Tails_respawn_counter).w move.b #ObjID_TailsTails,(Tails_Tails+id).w ; load Obj05 (Tails' Tails) at $FFFFD000 move.w a0,(Tails_Tails+parent).w ; set its parent object to this ; --------------------------------------------------------------------------- ; Normal state for Tails ; --------------------------------------------------------------------------- ; loc_1B9B4: Obj02_Control: cmpa.w #MainCharacter,a0 bne.s Obj02_Control_Joypad2 move.w (Ctrl_1_Logical).w,(Ctrl_2_Logical).w tst.b (Control_Locked).w ; are controls locked? bne.s Obj02_Control_Part2 ; if yes, branch move.w (Ctrl_1).w,(Ctrl_2_Logical).w ; copy new held buttons, to enable joypad control move.w (Ctrl_1).w,(Ctrl_1_Logical).w bra.s Obj02_Control_Part2 ; --------------------------------------------------------------------------- ; loc_1B9D4: Obj02_Control_Joypad2: tst.b (Control_Locked_P2).w bne.s + move.w (Ctrl_2).w,(Ctrl_2_Logical).w + tst.w (Two_player_mode).w bne.s Obj02_Control_Part2 bsr.w TailsCPU_Control ; loc_1B9EA: Obj02_Control_Part2: btst #0,obj_control(a0) ; is Tails flying, or interacting with another object that holds him in place or controls his movement somehow? bne.s + ; if yes, branch to skip Tails' control moveq #0,d0 move.b status(a0),d0 andi.w #6,d0 ; %0000 %0110 move.w Obj02_Modes(pc,d0.w),d1 jsr Obj02_Modes(pc,d1.w) ; run Tails' movement control code + cmpi.w #-$100,(Camera_Min_Y_pos).w ; is vertical wrapping enabled? bne.s + ; if not, branch andi.w #$7FF,y_pos(a0) ; perform wrapping of Sonic's y position + bsr.s Tails_Display bsr.w Tails_RecordPos bsr.w Tails_Water move.b (Primary_Angle).w,next_tilt(a0) move.b (Secondary_Angle).w,tilt(a0) tst.b (WindTunnel_flag).w beq.s + tst.b anim(a0) bne.s + move.b next_anim(a0),anim(a0) + bsr.w Tails_Animate tst.b obj_control(a0) bmi.s + jsr (TouchResponse).l + bra.w LoadTailsDynPLC ; =========================================================================== ; secondary states under state Obj02_Normal ; off_1BA4E: Obj02_Modes: offsetTable offsetTableEntry.w Obj02_MdNormal ; 0 - not airborne or rolling offsetTableEntry.w Obj02_MdAir ; 2 - airborne offsetTableEntry.w Obj02_MdRoll ; 4 - rolling offsetTableEntry.w Obj02_MdJump ; 6 - jumping ; =========================================================================== ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1BA56: Tails_Display: move.w invulnerable_time(a0),d0 beq.s Obj02_Display subq.w #1,invulnerable_time(a0) lsr.w #3,d0 bcc.s Obj02_ChkInvinc ; loc_1BA64: Obj02_Display: jsr (DisplaySprite).l ; loc_1BA6A: Obj02_ChkInvinc: ; Checks if invincibility has expired and disables it if it has. btst #status_sec_isInvincible,status_secondary(a0) beq.s Obj02_ChkShoes tst.w invincibility_time(a0) beq.s Obj02_ChkShoes subq.w #1,invincibility_time(a0) bne.s Obj02_ChkShoes tst.b (Current_Boss_ID).w ; Don't change music if in a boss fight bne.s Obj02_RmvInvin cmpi.b #$C,air_left(a0) ; Don't change music if drowning blo.s Obj02_RmvInvin move.w (Level_Music).w,d0 jsr (PlayMusic).l ; loc_1BA96: Obj02_RmvInvin: bclr #status_sec_isInvincible,status_secondary(a0) ; loc_1BA9C: Obj02_ChkShoes: ; Checks if Speed Shoes have expired and disables them if they have. btst #status_sec_hasSpeedShoes,status_secondary(a0) beq.s Obj02_ExitChk tst.w speedshoes_time(a0) beq.s Obj02_ExitChk subq.w #1,speedshoes_time(a0) bne.s Obj02_ExitChk move.w #$600,(Tails_top_speed).w move.w #$C,(Tails_acceleration).w move.w #$80,(Tails_deceleration).w ; Obj02_RmvSpeed: bclr #status_sec_hasSpeedShoes,status_secondary(a0) move.w #MusID_SlowDown,d0 ; Slow down tempo jmp (PlayMusic).l ; =========================================================================== ; return_1BAD2: Obj02_ExitChk: rts ; End of subroutine Tails_Display ; --------------------------------------------------------------------------- ; Tails' AI code for the Sonic and Tails mode 1-player game ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1BAD4: TailsCPU_Control: ; a0=Tails move.b (Ctrl_2_Held).w,d0 ; did the real player 2 hit something? andi.b #button_up_mask|button_down_mask|button_left_mask|button_right_mask|button_B_mask|button_C_mask|button_A_mask,d0 beq.s + ; if not, branch move.w #600,(Tails_control_counter).w ; give player 2 control for 10 seconds (minimum) + lea (MainCharacter).w,a1 ; a1=character ; a1=Sonic move.w (Tails_CPU_routine).w,d0 move.w TailsCPU_States(pc,d0.w),d0 jmp TailsCPU_States(pc,d0.w) ; =========================================================================== ; off_1BAF4: TailsCPU_States: offsetTable offsetTableEntry.w TailsCPU_Init ; 0 offsetTableEntry.w TailsCPU_Spawning ; 2 offsetTableEntry.w TailsCPU_Flying ; 4 offsetTableEntry.w TailsCPU_Normal ; 6 offsetTableEntry.w TailsCPU_Panic ; 8 ; =========================================================================== ; initial AI State ; --------------------------------------------------------------------------- ; loc_1BAFE: TailsCPU_Init: move.w #6,(Tails_CPU_routine).w ; => TailsCPU_Normal move.b #0,obj_control(a0) move.b #AniIDTailsAni_Walk,anim(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) move.w #0,inertia(a0) move.b #0,status(a0) move.w #0,(Tails_respawn_counter).w rts ; =========================================================================== ; AI State where Tails is waiting to respawn ; --------------------------------------------------------------------------- ; loc_1BB30: TailsCPU_Spawning: move.b (Ctrl_2_Held_Logical).w,d0 andi.b #button_B_mask|button_C_mask|button_A_mask|button_start_mask,d0 bne.s TailsCPU_Respawn move.w (Timer_frames).w,d0 andi.w #$3F,d0 bne.s return_1BB88 tst.b obj_control(a1) bne.s return_1BB88 move.b status(a1),d0 andi.b #$D2,d0 bne.s return_1BB88 ; loc_1BB54: TailsCPU_Respawn: move.w #4,(Tails_CPU_routine).w ; => TailsCPU_Flying move.w x_pos(a1),d0 move.w d0,x_pos(a0) move.w d0,(Tails_CPU_target_x).w move.w y_pos(a1),d0 move.w d0,(Tails_CPU_target_y).w subi.w #$C0,d0 move.w d0,y_pos(a0) ori.w #high_priority,art_tile(a0) move.b #0,spindash_flag(a0) move.w #0,spindash_counter(a0) return_1BB88: rts ; =========================================================================== ; AI State where Tails pretends to be a helicopter ; --------------------------------------------------------------------------- ; loc_1BB8A: TailsCPU_Flying: tst.b render_flags(a0) bmi.s TailsCPU_FlyingOnscreen addq.w #1,(Tails_respawn_counter).w cmpi.w #$12C,(Tails_respawn_counter).w blo.s TailsCPU_Flying_Part2 move.w #0,(Tails_respawn_counter).w move.w #2,(Tails_CPU_routine).w ; => TailsCPU_Spawning move.b #$81,obj_control(a0) move.b #2,status(a0) move.w #0,x_pos(a0) move.w #0,y_pos(a0) move.b #AniIDTailsAni_Fly,anim(a0) rts ; --------------------------------------------------------------------------- ; loc_1BBC8: TailsCPU_FlyingOnscreen: move.w #0,(Tails_respawn_counter).w ; loc_1BBCE: TailsCPU_Flying_Part2: lea (Sonic_Pos_Record_Buf).w,a2 move.w #$10,d2 lsl.b #2,d2 addq.b #4,d2 move.w (Sonic_Pos_Record_Index).w,d3 sub.b d2,d3 move.w (a2,d3.w),(Tails_CPU_target_x).w move.w 2(a2,d3.w),(Tails_CPU_target_y).w tst.b (Water_flag).w beq.s + move.w (Water_Level_1).w,d0 subi.w #$10,d0 cmp.w (Tails_CPU_target_y).w,d0 bge.s + move.w d0,(Tails_CPU_target_y).w + move.w x_pos(a0),d0 sub.w (Tails_CPU_target_x).w,d0 beq.s loc_1BC54 mvabs.w d0,d2 lsr.w #4,d2 cmpi.w #$C,d2 blo.s + moveq #$C,d2 + mvabs.b x_vel(a1),d1 add.b d1,d2 addq.w #1,d2 tst.w d0 bmi.s loc_1BC40 bset #0,status(a0) cmp.w d0,d2 blo.s + move.w d0,d2 moveq #0,d0 + neg.w d2 bra.s loc_1BC50 ; --------------------------------------------------------------------------- loc_1BC40: bclr #0,status(a0) neg.w d0 cmp.w d0,d2 blo.s loc_1BC50 move.b d0,d2 moveq #0,d0 loc_1BC50: add.w d2,x_pos(a0) loc_1BC54: moveq #1,d2 move.w y_pos(a0),d1 sub.w (Tails_CPU_target_y).w,d1 beq.s loc_1BC68 bmi.s loc_1BC64 neg.w d2 loc_1BC64: add.w d2,y_pos(a0) loc_1BC68: lea (Sonic_Stat_Record_Buf).w,a2 move.b 2(a2,d3.w),d2 andi.b #$D2,d2 bne.s return_1BCDE or.w d0,d1 bne.s return_1BCDE move.w #6,(Tails_CPU_routine).w ; => TailsCPU_Normal move.b #0,obj_control(a0) move.b #AniIDTailsAni_Walk,anim(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) move.w #0,inertia(a0) move.b #2,status(a0) move.w #0,move_lock(a0) andi.w #drawing_mask,art_tile(a0) tst.b art_tile(a1) bpl.s + ori.w #high_priority,art_tile(a0) + move.b top_solid_bit(a1),top_solid_bit(a0) move.b lrb_solid_bit(a1),lrb_solid_bit(a0) cmpi.b #AniIDTailsAni_Spindash,anim(a1) beq.s return_1BCDE move.b spindash_flag(a0),d0 beq.s return_1BCDE move.b d0,spindash_flag(a1) bsr.w loc_212C4 return_1BCDE: rts ; =========================================================================== ; AI State where Tails follows the player normally ; --------------------------------------------------------------------------- ; loc_1BCE0: TailsCPU_Normal: cmpi.b #6,(MainCharacter+routine).w ; is Sonic dead? blo.s TailsCPU_Normal_SonicOK ; if not, branch ; Sonic's dead; fly down to his corpse move.w #4,(Tails_CPU_routine).w ; => TailsCPU_Flying move.b #0,spindash_flag(a0) move.w #0,spindash_counter(a0) move.b #$81,obj_control(a0) move.b #2,status(a0) move.b #AniIDTailsAni_Fly,anim(a0) rts ; --------------------------------------------------------------------------- ; loc_1BD0E: TailsCPU_Normal_SonicOK: bsr.w TailsCPU_CheckDespawn tst.w (Tails_control_counter).w ; if CPU has control bne.w TailsCPU_Normal_HumanControl ; (if not, branch) tst.b obj_control(a0) ; and Tails isn't fully object controlled (&$80) bmi.w TailsCPU_Normal_HumanControl ; (if not, branch) tst.w move_lock(a0) ; and Tails' movement is locked (usually because he just fell down a slope) beq.s + ; (if not, branch) tst.w inertia(a0) ; and Tails is stopped, then... bne.s + ; (if not, branch) move.w #8,(Tails_CPU_routine).w ; => TailsCPU_Panic + lea (Sonic_Pos_Record_Buf).w,a1 move.w #$10,d1 lsl.b #2,d1 addq.b #4,d1 move.w (Sonic_Pos_Record_Index).w,d0 sub.b d1,d0 move.w (a1,d0.w),d2 ; d2 = earlier x position of Sonic move.w 2(a1,d0.w),d3 ; d3 = earlier y position of Sonic lea (Sonic_Stat_Record_Buf).w,a1 move.w (a1,d0.w),d1 ; d1 = earlier input of Sonic move.b 2(a1,d0.w),d4 ; d4 = earlier status of Sonic move.w d1,d0 btst #5,status(a0) ; is Tails pushing against something? beq.s + ; if not, branch btst #5,d4 ; was Sonic pushing against something? beq.w TailsCPU_Normal_FilterAction_Part2 ; if not, branch elsewhere ; either Tails isn't pushing, or Tails and Sonic are both pushing + sub.w x_pos(a0),d2 beq.s TailsCPU_Normal_Stand ; branch if Tails is already lined up horizontally with Sonic bpl.s TailsCPU_Normal_FollowRight neg.w d2 ; Tails wants to go left because that's where Sonic is ; loc_1BD76: TailsCPU_Normal_FollowLeft: cmpi.w #$10,d2 blo.s + andi.w #~(((button_left_mask|button_right_mask)<<8)|(button_left_mask|button_right_mask)),d1 ; AND out Sonic's left/right input... ori.w #(button_left_mask<<8)|button_left_mask,d1 ; ...and give Tails his own + tst.w inertia(a0) beq.s TailsCPU_Normal_FilterAction btst #0,status(a0) beq.s TailsCPU_Normal_FilterAction subq.w #1,x_pos(a0) bra.s TailsCPU_Normal_FilterAction ; =========================================================================== ; Tails wants to go right because that's where Sonic is ; loc_1BD98: TailsCPU_Normal_FollowRight: cmpi.w #$10,d2 blo.s + andi.w #~(((button_left_mask|button_right_mask)<<8)|(button_left_mask|button_right_mask)),d1 ; AND out Sonic's left/right input ori.w #(button_right_mask<<8)|button_right_mask,d1 ; ...and give Tails his own + tst.w inertia(a0) beq.s TailsCPU_Normal_FilterAction btst #0,status(a0) bne.s TailsCPU_Normal_FilterAction addq.w #1,x_pos(a0) bra.s TailsCPU_Normal_FilterAction ; =========================================================================== ; Tails is happy where he is ; loc_1BDBA: TailsCPU_Normal_Stand: bclr #0,status(a0) move.b d4,d0 andi.b #1,d0 beq.s TailsCPU_Normal_FilterAction bset #0,status(a0) ; Filter the action we chose depending on a few things ; loc_1BDCE: TailsCPU_Normal_FilterAction: tst.b (Tails_CPU_jumping).w beq.s + ori.w #((button_B_mask|button_C_mask|button_A_mask)<<8),d1 btst #1,status(a0) bne.s TailsCPU_Normal_SendAction move.b #0,(Tails_CPU_jumping).w + move.w (Timer_frames).w,d0 andi.w #$FF,d0 beq.s + cmpi.w #$40,d2 bhs.s TailsCPU_Normal_SendAction + sub.w y_pos(a0),d3 beq.s TailsCPU_Normal_SendAction bpl.s TailsCPU_Normal_SendAction neg.w d3 cmpi.w #$20,d3 blo.s TailsCPU_Normal_SendAction ; loc_1BE06: TailsCPU_Normal_FilterAction_Part2: move.b (Timer_frames+1).w,d0 andi.b #$3F,d0 bne.s TailsCPU_Normal_SendAction cmpi.b #AniIDTailsAni_Duck,anim(a0) beq.s TailsCPU_Normal_SendAction ori.w #((button_B_mask|button_C_mask|button_A_mask)<<8)|(button_B_mask|button_C_mask|button_A_mask),d1 move.b #1,(Tails_CPU_jumping).w ; Send the action we chose by storing it into player 2's input ; loc_1BE22: TailsCPU_Normal_SendAction: move.w d1,(Ctrl_2_Logical).w rts ; =========================================================================== ; Follow orders from controller 2 ; and decrease the counter to when the CPU will regain control ; loc_1BE28: TailsCPU_Normal_HumanControl: tst.w (Tails_control_counter).w beq.s + ; don't decrease if it's already 0 subq.w #1,(Tails_control_counter).w + rts ; =========================================================================== ; loc_1BE34: TailsCPU_Despawn: move.w #0,(Tails_control_counter).w move.w #0,(Tails_respawn_counter).w move.w #2,(Tails_CPU_routine).w ; => TailsCPU_Spawning move.b #$81,obj_control(a0) move.b #2,status(a0) move.w #$4000,x_pos(a0) move.w #0,y_pos(a0) move.b #AniIDTailsAni_Fly,anim(a0) rts ; =========================================================================== ; sub_1BE66: TailsCPU_CheckDespawn: tst.b render_flags(a0) bmi.s TailsCPU_ResetRespawnTimer btst #3,status(a0) beq.s TailsCPU_TickRespawnTimer moveq #0,d0 move.b interact(a0),d0 if object_size=$40 lsl.w #6,d0 else mulu.w #object_size,d0 endif addi.l #Object_RAM,d0 movea.l d0,a3 ; a3=object move.b (Tails_interact_ID).w,d0 cmp.b (a3),d0 bne.s BranchTo_TailsCPU_Despawn ; loc_1BE8C: TailsCPU_TickRespawnTimer: addq.w #1,(Tails_respawn_counter).w cmpi.w #$12C,(Tails_respawn_counter).w blo.s TailsCPU_UpdateObjInteract BranchTo_TailsCPU_Despawn bra.w TailsCPU_Despawn ; =========================================================================== ; loc_1BE9C: TailsCPU_ResetRespawnTimer: move.w #0,(Tails_respawn_counter).w ; loc_1BEA2: TailsCPU_UpdateObjInteract: moveq #0,d0 move.b interact(a0),d0 if object_size=$40 lsl.w #6,d0 else mulu.w #object_size,d0 endif addi.l #Object_RAM,d0 movea.l d0,a3 ; a3=object move.b (a3),(Tails_interact_ID).w rts ; =========================================================================== ; AI State where Tails stops, drops, and spindashes in Sonic's direction ; --------------------------------------------------------------------------- ; loc_1BEB8: TailsCPU_Panic: bsr.w TailsCPU_CheckDespawn tst.w (Tails_control_counter).w bne.w return_1BF36 tst.w move_lock(a0) bne.s return_1BF36 tst.b spindash_flag(a0) bne.s TailsCPU_Panic_ChargingDash tst.w inertia(a0) bne.s return_1BF36 bclr #0,status(a0) move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcs.s + bset #0,status(a0) + move.w #(button_down_mask<<8)|button_down_mask,(Ctrl_2_Logical).w move.b (Timer_frames+1).w,d0 andi.b #$7F,d0 beq.s TailsCPU_Panic_ReleaseDash cmpi.b #AniIDTailsAni_Duck,anim(a0) bne.s return_1BF36 move.w #((button_down_mask|button_B_mask|button_C_mask|button_A_mask)<<8)|(button_down_mask|button_B_mask|button_C_mask|button_A_mask),(Ctrl_2_Logical).w rts ; --------------------------------------------------------------------------- ; loc_1BF0C: TailsCPU_Panic_ChargingDash: move.w #(button_down_mask<<8)|button_down_mask,(Ctrl_2_Logical).w move.b (Timer_frames+1).w,d0 andi.b #$7F,d0 bne.s TailsCPU_Panic_RevDash ; loc_1BF1C: TailsCPU_Panic_ReleaseDash: move.w #0,(Ctrl_2_Logical).w move.w #6,(Tails_CPU_routine).w ; => TailsCPU_Normal rts ; --------------------------------------------------------------------------- ; loc_1BF2A: TailsCPU_Panic_RevDash: andi.b #$1F,d0 bne.s return_1BF36 ori.w #((button_B_mask|button_C_mask|button_A_mask)<<8)|(button_B_mask|button_C_mask|button_A_mask),(Ctrl_2_Logical).w return_1BF36: rts ; End of function TailsCPU_Control ; --------------------------------------------------------------------------- ; Subroutine to record Tails' previous positions for invincibility stars ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1BF38: Tails_RecordPos: move.w (Tails_Pos_Record_Index).w,d0 lea (Tails_Pos_Record_Buf).w,a1 lea (a1,d0.w),a1 move.w x_pos(a0),(a1)+ move.w y_pos(a0),(a1)+ addq.b #4,(Tails_Pos_Record_Index+1).w rts ; End of subroutine Tails_RecordPos ; --------------------------------------------------------------------------- ; Subroutine for Tails when he's underwater ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1BF52: Tails_Water: tst.b (Water_flag).w ; does level have water? bne.s Obj02_InWater ; if yes, branch return_1BF58: rts ; --------------------------------------------------------------------------- ; loc_1BF5A: Obj02_InWater: move.w (Water_Level_1).w,d0 cmp.w y_pos(a0),d0 ; is Sonic above the water? bge.s Obj02_OutWater ; if yes, branch bset #6,status(a0) ; set underwater flag bne.s return_1BF58 ; if already underwater, branch movea.l a0,a1 bsr.w ResumeMusic move.b #ObjID_SmallBubbles,(Tails_BreathingBubbles+id).w ; load Obj0A (tail's breathing bubbles) at $FFFFD0C0 move.b #$81,(Tails_BreathingBubbles+subtype).w move.l a0,(Tails_BreathingBubbles+$3C).w ; set its parent to be this (obj0A uses $3C instead of $3E for some reason) move.w #$300,(Tails_top_speed).w move.w #6,(Tails_acceleration).w move.w #$40,(Tails_deceleration).w asr x_vel(a0) asr y_vel(a0) asr y_vel(a0) beq.s return_1BF58 move.w #$100,(Tails_Dust+anim).w ; splash animation move.w #SndID_Splash,d0 ; splash sound jmp (PlaySound).l ; --------------------------------------------------------------------------- ; loc_1BFB2: Obj02_OutWater: bclr #6,status(a0) ; unset underwater flag beq.s return_1BF58 ; if already above water, branch movea.l a0,a1 bsr.w ResumeMusic move.w #$600,(Tails_top_speed).w move.w #$C,(Tails_acceleration).w move.w #$80,(Tails_deceleration).w cmpi.b #4,routine(a0) ; is Tails falling back from getting hurt? beq.s + ; if yes, branch asl y_vel(a0) + tst.w y_vel(a0) beq.w return_1BF58 move.w #$100,(Tails_Dust+anim).w ; splash animation movea.l a0,a1 bsr.w ResumeMusic cmpi.w #-$1000,y_vel(a0) bgt.s + move.w #-$1000,y_vel(a0) ; limit upward y velocity exiting the water + move.w #SndID_Splash,d0 ; splash sound jmp (PlaySound).l ; End of subroutine Tails_Water ; =========================================================================== ; --------------------------------------------------------------------------- ; Start of subroutine Obj02_MdNormal ; Called if Tails is neither airborne nor rolling this frame ; --------------------------------------------------------------------------- ; loc_1C00A: Obj02_MdNormal: bsr.w Tails_CheckSpindash bsr.w Tails_Jump bsr.w Tails_SlopeResist bsr.w Tails_Move bsr.w Tails_Roll bsr.w Tails_LevelBound jsr (ObjectMove).l bsr.w AnglePos bsr.w Tails_SlopeRepel rts ; End of subroutine Obj02_MdNormal ; =========================================================================== ; Start of subroutine Obj02_MdAir ; Called if Tails is airborne, but not in a ball (thus, probably not jumping) ; loc_1C032: Obj02_MdJump Obj02_MdAir: bsr.w Tails_JumpHeight bsr.w Tails_ChgJumpDir bsr.w Tails_LevelBound jsr (ObjectMoveAndFall).l btst #6,status(a0) ; is Tails underwater? beq.s + ; if not, branch subi.w #$28,y_vel(a0) ; reduce gravity by $28 ($38-$28=$10) + bsr.w Tails_JumpAngle bsr.w Tails_DoLevelCollision rts ; End of subroutine Obj02_MdAir ; =========================================================================== ; Start of subroutine Obj02_MdRoll ; Called if Tails is in a ball, but not airborne (thus, probably rolling) ; loc_1C05C: Obj02_MdRoll: tst.b pinball_mode(a0) bne.s + bsr.w Tails_Jump + bsr.w Tails_RollRepel bsr.w Tails_RollSpeed bsr.w Tails_LevelBound jsr (ObjectMove).l bsr.w AnglePos bsr.w Tails_SlopeRepel rts ; End of subroutine Obj02_MdRoll ; =========================================================================== ; Start of subroutine Obj02_MdJump ; Called if Tails is in a ball and airborne (he could be jumping but not necessarily) ; Notes: This is identical to Obj02_MdAir, at least at this outer level. ; Why they gave it a separate copy of the code, I don't know. ; loc_1C082: Obj02_MdJump2: Obj02_MdJump: bsr.w Tails_JumpHeight bsr.w Tails_ChgJumpDir bsr.w Tails_LevelBound jsr (ObjectMoveAndFall).l btst #6,status(a0) ; is Tails underwater? beq.s + ; if not, branch subi.w #$28,y_vel(a0) ; reduce gravity by $28 ($38-$28=$10) + bsr.w Tails_JumpAngle bsr.w Tails_DoLevelCollision rts ; End of subroutine Obj02_MdJump ; --------------------------------------------------------------------------- ; Subroutine to make Tails walk/run ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C0AC: Tails_Move: move.w (Tails_top_speed).w,d6 move.w (Tails_acceleration).w,d5 move.w (Tails_deceleration).w,d4 if status_sec_isSliding = 7 tst.b status_secondary(a0) bmi.w Obj02_Traction else btst #status_sec_isSliding,status_secondary(a0) bne.w Obj02_Traction endif tst.w move_lock(a0) bne.w Obj02_ResetScr btst #button_left,(Ctrl_2_Held_Logical).w ; is left being pressed? beq.s Obj02_NotLeft ; if not, branch bsr.w Tails_MoveLeft ; loc_1C0D4: Obj02_NotLeft: btst #button_right,(Ctrl_2_Held_Logical).w ; is right being pressed? beq.s Obj02_NotRight ; if not, branch bsr.w Tails_MoveRight ; loc_1C0E0: Obj02_NotRight: move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 ; is Tails on a slope? bne.w Obj02_ResetScr ; if yes, branch tst.w inertia(a0) ; is Tails moving? bne.w Obj02_ResetScr ; if yes, branch bclr #5,status(a0) move.b #AniIDTailsAni_Wait,anim(a0) ; use "standing" animation btst #3,status(a0) beq.s Tails_Balance moveq #0,d0 move.b interact(a0),d0 if object_size=$40 lsl.w #6,d0 else mulu.w #object_size,d0 endif lea (Object_RAM).w,a1 ; a1=character lea (a1,d0.w),a1 ; a1=object tst.b status(a1) bmi.s Tails_Lookup moveq #0,d1 move.b width_pixels(a1),d1 move.w d1,d2 add.w d2,d2 subq.w #4,d2 add.w x_pos(a0),d1 sub.w x_pos(a1),d1 cmpi.w #4,d1 blt.s Tails_BalanceOnObjLeft cmp.w d2,d1 bge.s Tails_BalanceOnObjRight bra.s Tails_Lookup ; --------------------------------------------------------------------------- ; balancing checks for Tails ; loc_1C142: Tails_Balance: jsr (ChkFloorEdge).l cmpi.w #$C,d1 blt.s Tails_Lookup cmpi.b #3,next_tilt(a0) bne.s Tails_BalanceLeft ; loc_1C156: Tails_BalanceOnObjRight: bclr #0,status(a0) bra.s Tails_BalanceDone ; --------------------------------------------------------------------------- ; loc_1C15E: Tails_BalanceLeft: cmpi.b #3,tilt(a0) bne.s Tails_Lookup ; loc_1C166: Tails_BalanceOnObjLeft: bset #0,status(a0) ; loc_1C16C: Tails_BalanceDone: move.b #AniIDTailsAni_Balance,anim(a0) bra.s Obj02_ResetScr ; --------------------------------------------------------------------------- ; loc_1C174: Tails_Lookup: btst #button_up,(Ctrl_2_Held_Logical).w ; is up being pressed? beq.s Tails_Duck ; if not, branch move.b #AniIDTailsAni_LookUp,anim(a0) ; use "looking up" animation addq.w #1,(Tails_Look_delay_counter).w cmpi.w #$78,(Tails_Look_delay_counter).w blo.s Obj02_ResetScr_Part2 move.w #$78,(Tails_Look_delay_counter).w cmpi.w #$C8,(Camera_Y_pos_bias_P2).w beq.s Obj02_UpdateSpeedOnGround addq.w #2,(Camera_Y_pos_bias_P2).w bra.s Obj02_UpdateSpeedOnGround ; --------------------------------------------------------------------------- ; loc_1C1A2: Tails_Duck: btst #button_down,(Ctrl_2_Held_Logical).w ; is down being pressed? beq.s Obj02_ResetScr ; if not, branch move.b #AniIDTailsAni_Duck,anim(a0) ; use "ducking" animation addq.w #1,(Tails_Look_delay_counter).w cmpi.w #$78,(Tails_Look_delay_counter).w blo.s Obj02_ResetScr_Part2 move.w #$78,(Tails_Look_delay_counter).w cmpi.w #8,(Camera_Y_pos_bias_P2).w beq.s Obj02_UpdateSpeedOnGround subq.w #2,(Camera_Y_pos_bias_P2).w bra.s Obj02_UpdateSpeedOnGround ; =========================================================================== ; moves the screen back to its normal position after looking up or down ; loc_1C1D0: Obj02_ResetScr: move.w #0,(Tails_Look_delay_counter).w ; loc_1C1D6: Obj02_ResetScr_Part2: cmpi.w #(224/2)-16,(Camera_Y_pos_bias_P2).w ; is screen in its default position? beq.s Obj02_UpdateSpeedOnGround ; if yes, branch. bhs.s + ; depending on the sign of the difference, addq.w #4,(Camera_Y_pos_bias_P2).w ; either add 2 + subq.w #2,(Camera_Y_pos_bias_P2).w ; or subtract 2 ; --------------------------------------------------------------------------- ; updates Tails' speed on the ground ; --------------------------------------------------------------------------- ; loc_1C1E8: Obj02_UpdateSpeedOnGround: move.b (Ctrl_2_Held_Logical).w,d0 andi.b #button_left_mask|button_right_mask,d0 ; is left/right pressed? bne.s Obj02_Traction ; if yes, branch move.w inertia(a0),d0 beq.s Obj02_Traction bmi.s Obj02_SettleLeft ; slow down when facing right and not pressing a direction ; Obj02_SettleRight: sub.w d5,d0 bcc.s + move.w #0,d0 + move.w d0,inertia(a0) bra.s Obj02_Traction ; --------------------------------------------------------------------------- ; slow down when facing left and not pressing a direction ; loc_1C208: Obj02_SettleLeft: add.w d5,d0 bcc.s + move.w #0,d0 + move.w d0,inertia(a0) ; increase or decrease speed on the ground ; loc_1C214: Obj02_Traction: move.b angle(a0),d0 jsr (CalcSine).l muls.w inertia(a0),d1 asr.l #8,d1 move.w d1,x_vel(a0) muls.w inertia(a0),d0 asr.l #8,d0 move.w d0,y_vel(a0) ; stops Tails from running through walls that meet the ground ; loc_1C232: Obj02_CheckWallsOnGround: move.b angle(a0),d0 addi.b #$40,d0 bmi.s return_1C2A2 move.b #$40,d1 tst.w inertia(a0) beq.s return_1C2A2 bmi.s + neg.w d1 + move.b angle(a0),d0 add.b d1,d0 move.w d0,-(sp) bsr.w CalcRoomInFront move.w (sp)+,d0 tst.w d1 bpl.s return_1C2A2 asl.w #8,d1 addi.b #$20,d0 andi.b #$C0,d0 beq.s loc_1C29E cmpi.b #$40,d0 beq.s loc_1C28C cmpi.b #$80,d0 beq.s loc_1C286 add.w d1,x_vel(a0) bset #5,status(a0) move.w #0,inertia(a0) rts ; --------------------------------------------------------------------------- loc_1C286: sub.w d1,y_vel(a0) rts ; --------------------------------------------------------------------------- loc_1C28C: sub.w d1,x_vel(a0) bset #5,status(a0) move.w #0,inertia(a0) rts ; --------------------------------------------------------------------------- loc_1C29E: add.w d1,y_vel(a0) return_1C2A2: rts ; End of subroutine Tails_Move ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C2A4: Tails_MoveLeft: move.w inertia(a0),d0 beq.s + bpl.s Tails_TurnLeft ; if Tails is already moving to the right, branch + bset #0,status(a0) bne.s + bclr #5,status(a0) move.b #AniIDTailsAni_Run,next_anim(a0) + sub.w d5,d0 ; add acceleration to the left move.w d6,d1 neg.w d1 cmp.w d1,d0 ; compare new speed with top speed bgt.s + ; if new speed is less than the maximum, branch add.w d5,d0 ; remove this frame's acceleration change cmp.w d1,d0 ; compare speed with top speed ble.s + ; if speed was already greater than the maximum, branch move.w d1,d0 ; limit speed on ground going left + move.w d0,inertia(a0) move.b #AniIDTailsAni_Walk,anim(a0) ; use walking animation rts ; --------------------------------------------------------------------------- ; loc_1C2DE: Tails_TurnLeft: sub.w d4,d0 bcc.s + move.w #-$80,d0 + move.w d0,inertia(a0) move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 bne.s return_1C328 cmpi.w #$400,d0 blt.s return_1C328 move.b #AniIDTailsAni_Stop,anim(a0) ; use "stopping" animation bclr #0,status(a0) move.w #SndID_Skidding,d0 jsr (PlaySound).l cmpi.b #$C,air_left(a0) blo.s return_1C328 ; if he's drowning, branch to not make dust move.b #6,(Tails_Dust+routine).w move.b #$15,(Tails_Dust+mapping_frame).w return_1C328: rts ; End of subroutine Tails_MoveLeft ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C32A: Tails_MoveRight: move.w inertia(a0),d0 bmi.s Tails_TurnRight bclr #0,status(a0) beq.s + bclr #5,status(a0) move.b #AniIDTailsAni_Run,next_anim(a0) + add.w d5,d0 ; add acceleration to the right cmp.w d6,d0 ; compare new speed with top speed blt.s + ; if new speed is less than the maximum, branch sub.w d5,d0 ; remove this frame's acceleration change cmp.w d6,d0 ; compare speed with top speed bge.s + ; if speed was already greater than the maximum, branch move.w d6,d0 ; limit speed on ground going right + move.w d0,inertia(a0) move.b #AniIDTailsAni_Walk,anim(a0) ; use walking animation rts ; --------------------------------------------------------------------------- ; loc_1C35E: Tails_TurnRight: add.w d4,d0 bcc.s + move.w #$80,d0 + move.w d0,inertia(a0) move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 bne.s return_1C3A8 cmpi.w #-$400,d0 bgt.s return_1C3A8 move.b #AniIDTailsAni_Stop,anim(a0) ; use "stopping" animation bset #0,status(a0) move.w #SndID_Skidding,d0 ; use "stopping" sound jsr (PlaySound).l cmpi.b #$C,air_left(a0) blo.s return_1C3A8 ; if he's drowning, branch to not make dust move.b #6,(Tails_Dust+routine).w move.b #$15,(Tails_Dust+mapping_frame).w return_1C3A8: rts ; End of subroutine Tails_MoveRight ; --------------------------------------------------------------------------- ; Subroutine to change Tails' speed as he rolls ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C3AA: Tails_RollSpeed: move.w (Tails_top_speed).w,d6 asl.w #1,d6 move.w (Tails_acceleration).w,d5 asr.w #1,d5 ; natural roll deceleration = 1/2 normal acceleration move.w (Tails_deceleration).w,d4 asr.w #2,d4 ; controlled roll deceleration... ; interestingly, Tails is much worse at this than Sonic when underwater if status_sec_isSliding = 7 tst.b status_secondary(a0) bmi.w Obj02_Roll_ResetScr else btst #status_sec_isSliding,status_secondary(a0) bne.w Obj02_Roll_ResetScr endif tst.w move_lock(a0) bne.s Tails_ApplyRollSpeed btst #button_left,(Ctrl_2_Held_Logical).w ; is left being pressed? beq.s + ; if not, branch bsr.w Tails_RollLeft + btst #button_right,(Ctrl_2_Held_Logical).w ; is right being pressed? beq.s Tails_ApplyRollSpeed ; if not, branch bsr.w Tails_RollRight ; loc_1C3E2: Tails_ApplyRollSpeed: move.w inertia(a0),d0 beq.s Tails_CheckRollStop bmi.s Tails_ApplyRollSpeedLeft ; Tails_ApplyRollSpeedRight: sub.w d5,d0 bcc.s + move.w #0,d0 + move.w d0,inertia(a0) bra.s Tails_CheckRollStop ; --------------------------------------------------------------------------- ; loc_1C3F8: Tails_ApplyRollSpeedLeft: add.w d5,d0 bcc.s + move.w #0,d0 + move.w d0,inertia(a0) ; loc_1C404 Tails_CheckRollStop: tst.w inertia(a0) bne.s Obj02_Roll_ResetScr tst.b pinball_mode(a0) ; note: the spindash flag has a different meaning when Tails is already rolling -- it's used to mean he's not allowed to stop rolling bne.s Tails_KeepRolling bclr #2,status(a0) move.b #$F,y_radius(a0) ; sets standing height to only slightly higher than rolling height, unlike Sonic move.b #9,x_radius(a0) move.b #AniIDTailsAni_Wait,anim(a0) subq.w #1,y_pos(a0) bra.s Obj02_Roll_ResetScr ; --------------------------------------------------------------------------- ; magically gives Tails an extra push if he's going to stop rolling where it's not allowed ; (such as in an S-curve in HTZ or a stopper chamber in CNZ) ; loc_1C42E: Tails_KeepRolling: move.w #$400,inertia(a0) btst #0,status(a0) beq.s Obj02_Roll_ResetScr neg.w inertia(a0) ; resets the screen to normal while rolling, like Obj02_ResetScr ; loc_1C440: Obj02_Roll_ResetScr: cmpi.w #(224/2)-16,(Camera_Y_pos_bias_P2).w ; is screen in its default position? beq.s Tails_SetRollSpeed ; if yes, branch bhs.s + ; depending on the sign of the difference, addq.w #4,(Camera_Y_pos_bias_P2).w ; either add 2 + subq.w #2,(Camera_Y_pos_bias_P2).w ; or subtract 2 ; loc_1C452: Tails_SetRollSpeed: move.b angle(a0),d0 jsr (CalcSine).l muls.w inertia(a0),d0 asr.l #8,d0 move.w d0,y_vel(a0) ; set y velocity based on $14 and angle muls.w inertia(a0),d1 asr.l #8,d1 cmpi.w #$1000,d1 ble.s + move.w #$1000,d1 ; limit Tails' speed rolling right + cmpi.w #-$1000,d1 bge.s + move.w #-$1000,d1 ; limit Tails' speed rolling left + move.w d1,x_vel(a0) ; set x velocity based on $14 and angle bra.w Obj02_CheckWallsOnGround ; End of function Tails_RollSpeed ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C488: Tails_RollLeft: move.w inertia(a0),d0 beq.s + bpl.s Tails_BrakeRollingRight + bset #0,status(a0) move.b #AniIDTailsAni_Roll,anim(a0) ; use "rolling" animation rts ; --------------------------------------------------------------------------- ; loc_1C49E: Tails_BrakeRollingRight: sub.w d4,d0 ; reduce rightward rolling speed bcc.s + move.w #-$80,d0 + move.w d0,inertia(a0) rts ; End of function Tails_RollLeft ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C4AC: Tails_RollRight: move.w inertia(a0),d0 bmi.s Tails_BrakeRollingLeft bclr #0,status(a0) move.b #AniIDTailsAni_Roll,anim(a0) ; use "rolling" animation rts ; --------------------------------------------------------------------------- ; loc_1C4C0: Tails_BrakeRollingLeft: add.w d4,d0 ; reduce leftward rolling speed bcc.s + move.w #$80,d0 + move.w d0,inertia(a0) rts ; End of subroutine Tails_RollRight ; --------------------------------------------------------------------------- ; Subroutine for moving Tails left or right when he's in the air ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C4CE: Tails_ChgJumpDir: move.w (Tails_top_speed).w,d6 move.w (Tails_acceleration).w,d5 asl.w #1,d5 btst #4,status(a0) ; did Tails jump from rolling? bne.s Obj02_Jump_ResetScr ; if yes, branch to skip midair control move.w x_vel(a0),d0 btst #button_left,(Ctrl_2_Held_Logical).w beq.s + ; if not holding left, branch bset #0,status(a0) sub.w d5,d0 ; add acceleration to the left move.w d6,d1 neg.w d1 cmp.w d1,d0 ; compare new speed with top speed bgt.s + ; if new speed is less than the maximum, branch move.w d1,d0 ; limit speed in air going left, even if Tails was already going faster (speed limit/cap) + btst #button_right,(Ctrl_2_Held_Logical).w beq.s + ; if not holding right, branch bclr #0,status(a0) add.w d5,d0 ; accelerate right in the air cmp.w d6,d0 ; compare new speed with top speed blt.s + ; if new speed is less than the maximum, branch move.w d6,d0 ; limit speed in air going right, even if Tails was already going faster (speed limit/cap) ; Obj02_JumpMove: + move.w d0,x_vel(a0) ; loc_1C518: Obj02_ResetScr2: Obj02_Jump_ResetScr: cmpi.w #(224/2)-16,(Camera_Y_pos_bias_P2).w ; is screen in its default position? beq.s Tails_JumpPeakDecelerate ; if yes, branch bhs.s + ; depending on the sign of the difference, addq.w #4,(Camera_Y_pos_bias_P2).w ; either add 2 + subq.w #2,(Camera_Y_pos_bias_P2).w ; or subtract 2 ; loc_1C52A: Tails_JumpPeakDecelerate: cmpi.w #-$400,y_vel(a0) ; is Tails moving faster than -$400 upwards? blo.s return_1C558 ; if yes, return move.w x_vel(a0),d0 move.w d0,d1 asr.w #5,d1 ; d1 = x_velocity / 32 beq.s return_1C558 ; return if d1 is 0 bmi.s Tails_JumpPeakDecelerateLeft ; Tails_JumpPeakDecelerateRight: sub.w d1,d0 ; reduce x velocity by d1 bcc.s + move.w #0,d0 + move.w d0,x_vel(a0) rts ; --------------------------------------------------------------------------- ; loc_1C54C: Tails_JumpPeakDecelerateLeft: sub.w d1,d0 ; reduce x velocity by d1 bcs.s + move.w #0,d0 + move.w d0,x_vel(a0) return_1C558: rts ; End of subroutine Tails_ChgJumpDir ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to prevent Tails from leaving the boundaries of a level ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C55A: Tails_LevelBound: move.l x_pos(a0),d1 move.w x_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d1 swap d1 move.w (Tails_Min_X_pos).w,d0 addi.w #$10,d0 cmp.w d1,d0 ; has Tails touched the left boundary? bhi.s Tails_Boundary_Sides ; if yes, branch move.w (Tails_Max_X_pos).w,d0 addi.w #$128,d0 tst.b (Current_Boss_ID).w bne.s + addi.w #$40,d0 + cmp.w d1,d0 ; has Tails touched the right boundary? bls.s Tails_Boundary_Sides ; if yes, branch ; loc_1C58C: Tails_Boundary_CheckBottom: move.w (Tails_Max_Y_pos).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 ; has Tails touched the bottom boundary? blt.s Tails_Boundary_Bottom ; if yes, branch rts ; --------------------------------------------------------------------------- Tails_Boundary_Bottom: ;; jmpto (KillCharacter).l, JmpTo2_KillCharacter ; =========================================================================== ; loc_1C5A0: Tails_Boundary_Sides: move.w d0,x_pos(a0) move.w #0,2+x_pos(a0) ; subpixel x move.w #0,x_vel(a0) move.w #0,inertia(a0) bra.s Tails_Boundary_CheckBottom ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine allowing Tails to start rolling when he's moving ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C5B8: Tails_Roll: if status_sec_isSliding = 7 tst.b status_secondary(a0) bmi.s Obj02_NoRoll else btst #status_sec_isSliding,status_secondary(a0) bne.w Obj02_NoRoll endif mvabs.w inertia(a0),d0 cmpi.w #$80,d0 ; is Tails moving at $80 speed or faster? blo.s Obj02_NoRoll ; if not, branch move.b (Ctrl_2_Held_Logical).w,d0 andi.b #button_left_mask|button_right_mask,d0 ; is left/right being pressed? bne.s Obj02_NoRoll ; if yes, branch btst #button_down,(Ctrl_2_Held_Logical).w ; is down being pressed? bne.s Obj02_ChkRoll ; if yes, branch ; return_1C5DE: Obj02_NoRoll: rts ; --------------------------------------------------------------------------- ; loc_1C5E0: Obj02_ChkRoll: btst #2,status(a0) ; is Tails already rolling? beq.s Obj02_DoRoll ; if not, branch rts ; --------------------------------------------------------------------------- ; loc_1C5EA: Obj02_DoRoll: bset #2,status(a0) move.b #$E,y_radius(a0) move.b #7,x_radius(a0) move.b #AniIDTailsAni_Roll,anim(a0) ; use "rolling" animation addq.w #1,y_pos(a0) move.w #SndID_Roll,d0 jsr (PlaySound).l ; play rolling sound tst.w inertia(a0) bne.s return_1C61C move.w #$200,inertia(a0) return_1C61C: rts ; End of function Tails_Roll ; --------------------------------------------------------------------------- ; Subroutine allowing Tails to jump ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C61E: Tails_Jump: move.b (Ctrl_2_Press_Logical).w,d0 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 ; is A, B or C pressed? beq.w return_1C6C2 ; if not, return moveq #0,d0 move.b angle(a0),d0 addi.b #$80,d0 bsr.w CalcRoomOverHead cmpi.w #6,d1 ; does Tails have enough room to jump? blt.w return_1C6C2 ; if not, branch move.w #$680,d2 btst #6,status(a0) ; Test if underwater beq.s + move.w #$380,d2 ; set lower jump speed if underwater + moveq #0,d0 move.b angle(a0),d0 subi.b #$40,d0 jsr (CalcSine).l muls.w d2,d1 asr.l #8,d1 add.w d1,x_vel(a0) ; make Tails jump (in X... this adds nothing on level ground) muls.w d2,d0 asr.l #8,d0 add.w d0,y_vel(a0) ; make Tails jump (in Y) bset #1,status(a0) bclr #5,status(a0) addq.l #4,sp move.b #1,jumping(a0) clr.b stick_to_convex(a0) move.w #SndID_Jump,d0 jsr (PlaySound).l ; play jumping sound move.b #$F,y_radius(a0) move.b #9,x_radius(a0) btst #2,status(a0) bne.s Tails_RollJump move.b #$E,y_radius(a0) move.b #7,x_radius(a0) move.b #AniIDTailsAni_Roll,anim(a0) ; use "jumping" animation bset #2,status(a0) addq.w #1,y_pos(a0) return_1C6C2: rts ; --------------------------------------------------------------------------- ; loc_1C6C4: Tails_RollJump: bset #4,status(a0) ; set the rolling+jumping flag rts ; End of function Tails_Jump ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; =========================================================================== ; loc_1C6CC: Tails_JumpHeight: tst.b jumping(a0) ; is Tails jumping? beq.s Tails_UpVelCap ; if not, branch move.w #-$400,d1 btst #6,status(a0) ; is Tails underwater? beq.s + ; if not, branch move.w #-$200,d1 + cmp.w y_vel(a0),d1 ; is Tails going up faster than d1? ble.s + ; if not, branch move.b (Ctrl_2_Held_Logical).w,d0 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 ; is a jump button pressed? bne.s + ; if yes, branch move.w d1,y_vel(a0) ; immediately reduce Tails's upward speed to d1 + rts ; --------------------------------------------------------------------------- ; loc_1C6F8: Tails_UpVelCap: tst.b pinball_mode(a0) ; is Tails charging a spindash or in a rolling-only area? bne.s return_1C70C ; if yes, return cmpi.w #-$FC0,y_vel(a0) ; is Tails moving up really fast? bge.s return_1C70C ; if not, return move.w #-$FC0,y_vel(a0) ; cap upward speed return_1C70C: rts ; End of subroutine Tails_JumpHeight ; --------------------------------------------------------------------------- ; Subroutine to check for starting to charge a spindash ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C70E: Tails_CheckSpindash: tst.b spindash_flag(a0) bne.s Tails_UpdateSpindash cmpi.b #AniIDTailsAni_Duck,anim(a0) bne.s return_1C75C move.b (Ctrl_2_Press_Logical).w,d0 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 beq.w return_1C75C move.b #AniIDTailsAni_Spindash,anim(a0) move.w #SndID_SpindashRev,d0 jsr (PlaySound).l addq.l #4,sp move.b #1,spindash_flag(a0) move.w #0,spindash_counter(a0) cmpi.b #$C,air_left(a0) ; if he's drowning, branch to not make dust blo.s loc_1C754 move.b #2,(Tails_Dust+anim).w loc_1C754: bsr.w Tails_LevelBound bsr.w AnglePos return_1C75C: rts ; End of subroutine Tails_CheckSpindash ; --------------------------------------------------------------------------- ; Subrouting to update an already-charging spindash ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C75E: Tails_UpdateSpindash: move.b (Ctrl_2_Held_Logical).w,d0 btst #button_down,d0 bne.s Tails_ChargingSpindash ; unleash the charged spindash and start rolling quickly: move.b #$E,y_radius(a0) move.b #7,x_radius(a0) move.b #AniIDTailsAni_Roll,anim(a0) addq.w #1,y_pos(a0) ; add the difference between Tails' rolling and standing heights move.b #0,spindash_flag(a0) moveq #0,d0 move.b spindash_counter(a0),d0 add.w d0,d0 move.w Tails_SpindashSpeeds(pc,d0.w),inertia(a0) move.w inertia(a0),d0 subi.w #$800,d0 add.w d0,d0 andi.w #$1F00,d0 neg.w d0 addi.w #$2000,d0 move.w d0,(Horiz_scroll_delay_val_P2).w btst #0,status(a0) beq.s + neg.w inertia(a0) + bset #2,status(a0) move.b #0,(Tails_Dust+anim).w move.w #SndID_SpindashRelease,d0 ; spindash zoom sound jsr (PlaySound).l bra.s loc_1C828 ; =========================================================================== ; word_1C7CE: Tails_SpindashSpeeds: dc.w $800 ; 0 dc.w $880 ; 1 dc.w $900 ; 2 dc.w $980 ; 3 dc.w $A00 ; 4 dc.w $A80 ; 5 dc.w $B00 ; 6 dc.w $B80 ; 7 dc.w $C00 ; 8 ; =========================================================================== ; loc_1C7E0: Tails_ChargingSpindash: ; If still charging the dash... tst.w spindash_counter(a0) beq.s loc_1C7F8 move.w spindash_counter(a0),d0 lsr.w #5,d0 sub.w d0,spindash_counter(a0) bcc.s loc_1C7F8 move.w #0,spindash_counter(a0) loc_1C7F8: move.b (Ctrl_2_Press_Logical).w,d0 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 beq.w loc_1C828 move.w #(AniIDTailsAni_Spindash<<8),anim(a0) move.w #SndID_SpindashRev,d0 jsr (PlaySound).l addi.w #$200,spindash_counter(a0) cmpi.w #$800,spindash_counter(a0) blo.s loc_1C828 move.w #$800,spindash_counter(a0) loc_1C828: addq.l #4,sp cmpi.w #(224/2)-16,(Camera_Y_pos_bias_P2).w beq.s loc_1C83C bhs.s + addq.w #4,(Camera_Y_pos_bias_P2).w + subq.w #2,(Camera_Y_pos_bias_P2).w loc_1C83C: bsr.w Tails_LevelBound bsr.w AnglePos rts ; End of subroutine Tails_UpdateSpindash ; --------------------------------------------------------------------------- ; Subroutine to slow Tails walking up a slope ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C846: Tails_SlopeResist: move.b angle(a0),d0 addi.b #$60,d0 cmpi.b #$C0,d0 bhs.s return_1C87A move.b angle(a0),d0 jsr (CalcSine).l muls.w #$20,d0 asr.l #8,d0 tst.w inertia(a0) beq.s return_1C87A bmi.s loc_1C876 tst.w d0 beq.s + add.w d0,inertia(a0) ; change Tails' $14 + rts ; --------------------------------------------------------------------------- loc_1C876: add.w d0,inertia(a0) return_1C87A: rts ; End of subroutine Tails_SlopeResist ; --------------------------------------------------------------------------- ; Subroutine to push Tails down a slope while he's rolling ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C87C: Tails_RollRepel: move.b angle(a0),d0 addi.b #$60,d0 cmpi.b #-$40,d0 bhs.s return_1C8B6 move.b angle(a0),d0 jsr (CalcSine).l muls.w #$50,d0 asr.l #8,d0 tst.w inertia(a0) bmi.s loc_1C8AC tst.w d0 bpl.s loc_1C8A6 asr.l #2,d0 loc_1C8A6: add.w d0,inertia(a0) rts ; =========================================================================== loc_1C8AC: tst.w d0 bmi.s loc_1C8B2 asr.l #2,d0 loc_1C8B2: add.w d0,inertia(a0) return_1C8B6: rts ; End of function Tails_RollRepel ; --------------------------------------------------------------------------- ; Subroutine to push Tails down a slope ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C8B8: Tails_SlopeRepel: nop tst.b stick_to_convex(a0) bne.s return_1C8F2 tst.w move_lock(a0) bne.s loc_1C8F4 move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 beq.s return_1C8F2 mvabs.w inertia(a0),d0 cmpi.w #$280,d0 bhs.s return_1C8F2 clr.w inertia(a0) bset #1,status(a0) move.w #$1E,move_lock(a0) return_1C8F2: rts ; =========================================================================== loc_1C8F4: subq.w #1,move_lock(a0) rts ; End of function Tails_SlopeRepel ; --------------------------------------------------------------------------- ; Subroutine to return Tails' angle to 0 as he jumps ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C8FA: Tails_JumpAngle: move.b angle(a0),d0 ; get Tails' angle beq.s Tails_JumpFlip ; if already 0, branch bpl.s loc_1C90A ; if higher than 0, branch addq.b #2,d0 ; increase angle bcc.s BranchTo_Tails_JumpAngleSet moveq #0,d0 BranchTo_Tails_JumpAngleSet bra.s Tails_JumpAngleSet ; =========================================================================== loc_1C90A: subq.b #2,d0 ; decrease angle bcc.s Tails_JumpAngleSet moveq #0,d0 ; loc_1C910: Tails_JumpAngleSet: move.b d0,angle(a0) ; End of function Tails_JumpAngle ; continue straight to Tails_JumpFlip ; --------------------------------------------------------------------------- ; Updates Tails' secondary angle if he's tumbling ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C914: Tails_JumpFlip: move.b flip_angle(a0),d0 beq.s return_1C958 tst.w inertia(a0) bmi.s Tails_JumpLeftFlip ; loc_1C920: Tails_JumpRightFlip: move.b flip_speed(a0),d1 add.b d1,d0 bcc.s BranchTo_Tails_JumpFlipSet subq.b #1,flips_remaining(a0) bcc.s BranchTo_Tails_JumpFlipSet move.b #0,flips_remaining(a0) moveq #0,d0 BranchTo_Tails_JumpFlipSet bra.s Tails_JumpFlipSet ; =========================================================================== ; loc_1C938: Tails_JumpLeftFlip: tst.b flip_turned(a0) bne.s Tails_JumpRightFlip move.b flip_speed(a0),d1 sub.b d1,d0 bcc.s Tails_JumpFlipSet subq.b #1,flips_remaining(a0) bcc.s Tails_JumpFlipSet move.b #0,flips_remaining(a0) moveq #0,d0 ; loc_1C954: Tails_JumpFlipSet: move.b d0,flip_angle(a0) return_1C958: rts ; End of function Tails_JumpFlip ; --------------------------------------------------------------------------- ; Subroutine for Tails to interact with the floor and walls when he's in the air ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1C95A: Tails_Floor: Tails_DoLevelCollision: move.l #Primary_Collision,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s + move.l #Secondary_Collision,(Collision_addr).w + move.b lrb_solid_bit(a0),d5 move.w x_vel(a0),d1 move.w y_vel(a0),d2 jsr (CalcAngle).l subi.b #$20,d0 andi.b #$C0,d0 cmpi.b #$40,d0 beq.w Tails_HitLeftWall cmpi.b #$80,d0 beq.w Tails_HitCeilingAndWalls cmpi.b #$C0,d0 beq.w Tails_HitRightWall bsr.w CheckLeftWallDist tst.w d1 bpl.s + sub.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Tails since he hit a wall + bsr.w CheckRightWallDist tst.w d1 bpl.s + add.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Tails since he hit a wall + bsr.w Sonic_CheckFloor tst.w d1 bpl.s return_1CA3A move.b y_vel(a0),d2 addq.b #8,d2 neg.b d2 cmp.b d2,d1 bge.s + cmp.b d2,d0 blt.s return_1CA3A + add.w d1,y_pos(a0) move.b d3,angle(a0) bsr.w Tails_ResetOnFloor move.b d3,d0 addi.b #$20,d0 andi.b #$40,d0 bne.s loc_1CA18 move.b d3,d0 addi.b #$10,d0 andi.b #$20,d0 beq.s loc_1CA0A asr y_vel(a0) bra.s loc_1CA2C ; =========================================================================== loc_1CA0A: move.w #0,y_vel(a0) move.w x_vel(a0),inertia(a0) rts ; =========================================================================== loc_1CA18: move.w #0,x_vel(a0) ; stop Tails since he hit a wall cmpi.w #$FC0,y_vel(a0) ble.s loc_1CA2C move.w #$FC0,y_vel(a0) loc_1CA2C: move.w y_vel(a0),inertia(a0) tst.b d3 bpl.s return_1CA3A neg.w inertia(a0) return_1CA3A: rts ; =========================================================================== ; loc_1CA3C: Tails_HitLeftWall: bsr.w CheckLeftWallDist tst.w d1 bpl.s Tails_HitCeiling ; branch if distance is positive (not inside wall) sub.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Tails since he hit a wall move.w y_vel(a0),inertia(a0) rts ; =========================================================================== ; loc_1CA56: Tails_HitCeiling: bsr.w Sonic_CheckCeiling tst.w d1 bpl.s Tails_HitFloor ; branch if distance is positive (not inside ceiling) sub.w d1,y_pos(a0) tst.w y_vel(a0) bpl.s return_1CA6E move.w #0,y_vel(a0) ; stop Tails in y since he hit a ceiling return_1CA6E: rts ; =========================================================================== ; loc_1CA70: Tails_HitFloor: tst.w y_vel(a0) bmi.s return_1CA96 bsr.w Sonic_CheckFloor tst.w d1 bpl.s return_1CA96 add.w d1,y_pos(a0) move.b d3,angle(a0) bsr.w Tails_ResetOnFloor move.w #0,y_vel(a0) move.w x_vel(a0),inertia(a0) return_1CA96: rts ; =========================================================================== ; loc_1CA98: Tails_HitCeilingAndWalls: bsr.w CheckLeftWallDist tst.w d1 bpl.s + sub.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Tails since he hit a wall + bsr.w CheckRightWallDist tst.w d1 bpl.s + add.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Tails since he hit a wall + bsr.w Sonic_CheckCeiling tst.w d1 bpl.s return_1CAF2 sub.w d1,y_pos(a0) move.b d3,d0 addi.b #$20,d0 andi.b #$40,d0 bne.s loc_1CADC move.w #0,y_vel(a0) ; stop Tails in y since he hit a ceiling rts ; =========================================================================== loc_1CADC: move.b d3,angle(a0) bsr.w Tails_ResetOnFloor move.w y_vel(a0),inertia(a0) tst.b d3 bpl.s return_1CAF2 neg.w inertia(a0) return_1CAF2: rts ; =========================================================================== ; loc_1CAF4: Tails_HitRightWall: bsr.w CheckRightWallDist tst.w d1 bpl.s Tails_HitCeiling2 add.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Tails since he hit a wall move.w y_vel(a0),inertia(a0) rts ; =========================================================================== ; identical to Tails_HitCeiling... ; loc_1CB0E: Tails_HitCeiling2: bsr.w Sonic_CheckCeiling tst.w d1 bpl.s Tails_HitFloor2 sub.w d1,y_pos(a0) tst.w y_vel(a0) bpl.s return_1CB26 move.w #0,y_vel(a0) ; stop Tails in y since he hit a ceiling return_1CB26: rts ; =========================================================================== ; identical to Tails_HitFloor... ; loc_1CB28: Tails_HitFloor2: tst.w y_vel(a0) bmi.s return_1CB4E bsr.w Sonic_CheckFloor tst.w d1 bpl.s return_1CB4E add.w d1,y_pos(a0) move.b d3,angle(a0) bsr.w Tails_ResetOnFloor move.w #0,y_vel(a0) move.w x_vel(a0),inertia(a0) return_1CB4E: rts ; End of function Tails_DoLevelCollision ; --------------------------------------------------------------------------- ; Subroutine to reset Tails' mode when he lands on the floor ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1CB50: Tails_ResetOnFloor: tst.b pinball_mode(a0) bne.s Tails_ResetOnFloor_Part3 move.b #AniIDTailsAni_Walk,anim(a0) ; loc_1CB5C: Tails_ResetOnFloor_Part2: btst #2,status(a0) beq.s Tails_ResetOnFloor_Part3 bclr #2,status(a0) move.b #$F,y_radius(a0) ; this slightly increases Tails' collision height to standing move.b #9,x_radius(a0) move.b #AniIDTailsAni_Walk,anim(a0) ; use running/walking/standing animation subq.w #1,y_pos(a0) ; move Tails up 1 pixel so the increased height doesn't push him slightly into the ground ; loc_1CB80: Tails_ResetOnFloor_Part3: bclr #1,status(a0) bclr #5,status(a0) bclr #4,status(a0) move.b #0,jumping(a0) move.w #0,(Chain_Bonus_counter).w move.b #0,flip_angle(a0) move.b #0,flip_turned(a0) move.b #0,flips_remaining(a0) move.w #0,(Tails_Look_delay_counter).w cmpi.b #AniIDTailsAni_Hang2,anim(a0) bne.s return_1CBC4 move.b #AniIDTailsAni_Walk,anim(a0) return_1CBC4: rts ; End of subroutine Tails_ResetOnFloor ; =========================================================================== ; --------------------------------------------------------------------------- ; Tails when he gets hurt ; --------------------------------------------------------------------------- ; loc_1CBC6: Obj02_Hurt: jsr (ObjectMove).l addi.w #$30,y_vel(a0) btst #6,status(a0) beq.s + subi.w #$20,y_vel(a0) + cmpi.w #-$100,(Camera_Min_Y_pos).w bne.s + andi.w #$7FF,y_pos(a0) + bsr.w Tails_HurtStop bsr.w Tails_LevelBound bsr.w Tails_RecordPos bsr.w Tails_Animate bsr.w LoadTailsDynPLC jmp (DisplaySprite).l ; =========================================================================== ; loc_1CC08: Tails_HurtStop: move.w (Tails_Max_Y_pos).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 blt.w JmpTo2_KillCharacter bsr.w Tails_DoLevelCollision btst #1,status(a0) bne.s return_1CC4E moveq #0,d0 move.w d0,y_vel(a0) move.w d0,x_vel(a0) move.w d0,inertia(a0) move.b d0,obj_control(a0) move.b #AniIDTailsAni_Walk,anim(a0) move.b #2,routine(a0) ; => Obj02_Control move.w #$78,invulnerable_time(a0) move.b #0,spindash_flag(a0) return_1CC4E: rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Tails when he dies ; . ; --------------------------------------------------------------------------- ; loc_1CC50: Obj02_Dead: bsr.w Obj02_CheckGameOver jsr (ObjectMoveAndFall).l bsr.w Tails_RecordPos bsr.w Tails_Animate bsr.w LoadTailsDynPLC jmp (DisplaySprite).l ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1CC6C: Obj02_CheckGameOver: cmpi.w #2,(Player_mode).w ; is it a Tails Alone game? beq.w CheckGameOver ; if yes, branch... goodness, code reuse move.b #1,(Scroll_lock_P2).w move.b #0,spindash_flag(a0) move.w (Tails_Max_Y_pos).w,d0 addi.w #$100,d0 cmp.w y_pos(a0),d0 bge.w return_1CD8E move.b #2,routine(a0) tst.w (Two_player_mode).w bne.s Obj02_CheckGameOver_2Pmode bra.w TailsCPU_Despawn ; --------------------------------------------------------------------------- ; loc_1CCA2: Obj02_CheckGameOver_2Pmode: addq.b #1,(Update_HUD_lives_2P).w subq.b #1,(Life_count_2P).w bne.s Obj02_ResetLevel move.w #0,restart_countdown(a0) move.b #ObjID_GameOver,(GameOver_GameText+id).w ; load Obj39 move.b #ObjID_GameOver,(GameOver_OverText+id).w ; load Obj39 move.b #1,(GameOver_OverText+mapping_frame).w move.w a0,(GameOver_GameText+parent).w clr.b (Time_Over_flag_2P).w ; loc_1CCCC: Obj02_Finished: clr.b (Update_HUD_timer).w clr.b (Update_HUD_timer_2P).w move.b #8,routine(a0) move.w #MusID_GameOver,d0 jsr (PlayMusic).l moveq #PLCID_GameOver,d0 jmp (LoadPLC).l ; End of function Obj02_CheckGameOver ; =========================================================================== ; --------------------------------------------------------------------------- ; Tails when the level is restarted ; --------------------------------------------------------------------------- ; loc_1CCEC: Obj02_ResetLevel: tst.b (Time_Over_flag).w if gameRevision=0 bne.s Obj02_ResetLevel_Part3 else beq.s Obj02_ResetLevel_Part2 tst.b (Time_Over_flag_2P).w beq.s Obj02_ResetLevel_Part3 move.w #0,restart_countdown(a0) clr.b (Update_HUD_timer).w clr.b (Update_HUD_timer_2P).w move.b #8,routine(a0) rts endif ; --------------------------------------------------------------------------- Obj02_ResetLevel_Part2: tst.b (Time_Over_flag_2P).w beq.s Obj02_ResetLevel_Part3 move.w #0,restart_countdown(a0) move.b #ObjID_TimeOver,(TimeOver_TimeText+id).w ; load Obj39 move.b #ObjID_TimeOver,(TimeOver_OverText+id).w ; load Obj39 move.b #2,(TimeOver_TimeText+mapping_frame).w move.b #3,(TimeOver_OverText+mapping_frame).w move.w a0,(TimeOver_TimeText+parent).w bra.s Obj02_Finished ; --------------------------------------------------------------------------- Obj02_ResetLevel_Part3: move.b #0,(Scroll_lock_P2).w move.b #$A,routine(a0) ; => Obj02_Respawning move.w (Saved_x_pos_2P).w,x_pos(a0) move.w (Saved_y_pos_2P).w,y_pos(a0) move.w (Saved_art_tile_2P).w,art_tile(a0) move.w (Saved_Solid_bits_2P).w,top_solid_bit(a0) clr.w (Ring_count_2P).w clr.b (Extra_life_flags_2P).w move.b #0,obj_control(a0) move.b #5,anim(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) move.w #0,inertia(a0) move.b #2,status(a0) move.w #0,move_lock(a0) return_1CD8E: rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Tails when he's offscreen and waiting for the level to restart ; --------------------------------------------------------------------------- ; loc_1CD90: Obj02_Gone: tst.w restart_countdown(a0) beq.s + subq.w #1,restart_countdown(a0) bne.s + move.w #1,(Level_Inactive_flag).w + rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Tails when he's waiting for the camera to scroll back to where he respawned ; --------------------------------------------------------------------------- ; loc_1CDA4: Obj02_Respawning: tst.w (Camera_X_pos_diff_P2).w bne.s + tst.w (Camera_Y_pos_diff_P2).w bne.s + move.b #2,routine(a0) + bsr.w Tails_Animate bsr.w LoadTailsDynPLC jmp (DisplaySprite).l ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to animate Tails' sprites ; See also: AnimateSprite and Sonic_Animate ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1CDC4: Tails_Animate: lea (TailsAniData).l,a1 ; loc_1CDCA: Tails_Animate_Part2: moveq #0,d0 move.b anim(a0),d0 cmp.b next_anim(a0),d0 ; has animation changed? beq.s TAnim_Do ; if not, branch move.b d0,next_anim(a0) ; set to next animation move.b #0,anim_frame(a0) ; reset animation frame move.b #0,anim_frame_duration(a0) ; reset frame duration bclr #5,status(a0) ; loc_1CDEC: TAnim_Do: add.w d0,d0 adda.w (a1,d0.w),a1 ; calculate address of appropriate animation script move.b (a1),d0 bmi.s TAnim_WalkRunZoom ; if animation is walk/run/roll/jump, branch move.b status(a0),d1 andi.b #1,d1 andi.b #$FC,render_flags(a0) or.b d1,render_flags(a0) subq.b #1,anim_frame_duration(a0) ; subtract 1 from frame duration bpl.s TAnim_Delay ; if time remains, branch move.b d0,anim_frame_duration(a0) ; load frame duration ; loc_1CE12: TAnim_Do2: moveq #0,d1 move.b anim_frame(a0),d1 ; load current frame number move.b 1(a1,d1.w),d0 ; read sprite number from script cmpi.b #$F0,d0 bhs.s TAnim_End_FF ; if animation is complete, branch ; loc_1CE22: TAnim_Next: move.b d0,mapping_frame(a0) ; load sprite number addq.b #1,anim_frame(a0) ; go to next frame ; return_1CE2A: TAnim_Delay: rts ; =========================================================================== ; loc_1CE2C: TAnim_End_FF: addq.b #1,d0 ; is the end flag = $FF ? bne.s TAnim_End_FE ; if not, branch move.b #0,anim_frame(a0) ; restart the animation move.b 1(a1),d0 ; read sprite number bra.s TAnim_Next ; =========================================================================== ; loc_1CE3C: TAnim_End_FE: addq.b #1,d0 ; is the end flag = $FE ? bne.s TAnim_End_FD ; if not, branch move.b 2(a1,d1.w),d0 ; read the next byte in the script sub.b d0,anim_frame(a0) ; jump back d0 bytes in the script sub.b d0,d1 move.b 1(a1,d1.w),d0 ; read sprite number bra.s TAnim_Next ; =========================================================================== ; loc_1CE50: TAnim_End_FD: addq.b #1,d0 ; is the end flag = $FD ? bne.s TAnim_End ; if not, branch move.b 2(a1,d1.w),anim(a0) ; read next byte, run that animation ; return_1CE5A: TAnim_End: rts ; =========================================================================== ; loc_1CE5C: TAnim_WalkRunZoom: ; a0=character ; note: for some reason SAnim_WalkRun doesn't need to do this here... subq.b #1,anim_frame_duration(a0) ; subtract 1 from Tails' frame duration bpl.s TAnim_Delay ; if time remains, branch addq.b #1,d0 ; is the end flag = $FF ? bne.w TAnim_Roll ; if not, branch moveq #0,d0 ; is animation walking/running? move.b flip_angle(a0),d0 ; if not, branch bne.w TAnim_Tumble moveq #0,d1 move.b angle(a0),d0 ; get Tails' angle bmi.s + beq.s + subq.b #1,d0 + move.b status(a0),d2 andi.b #1,d2 ; is Tails mirrored horizontally? bne.s + ; if yes, branch not.b d0 ; reverse angle + addi.b #$10,d0 ; add $10 to angle bpl.s + ; if angle is $0-$7F, branch moveq #3,d1 + andi.b #$FC,render_flags(a0) eor.b d1,d2 or.b d2,render_flags(a0) btst #5,status(a0) bne.w TAnim_Push lsr.b #4,d0 ; divide angle by 16 andi.b #6,d0 ; angle must be 0, 2, 4 or 6 mvabs.w inertia(a0),d2 ; get Tails' "speed" for animation purposes if status_sec_isSliding = 7 tst.b status_secondary(a0) bpl.w + else btst #status_sec_isSliding,status_secondary(a0) beq.w + endif add.w d2,d2 + move.b d0,d3 add.b d3,d3 add.b d3,d3 lea (TailsAni_Walk).l,a1 cmpi.w #$600,d2 ; is Tails going pretty fast? blo.s TAnim_SpeedSelected ; if not, branch lea (TailsAni_Run).l,a1 move.b d0,d1 lsr.b #1,d1 add.b d1,d0 add.b d0,d0 move.b d0,d3 cmpi.w #$700,d2 ; is Tails going really fast? blo.s TAnim_SpeedSelected ; if not, branch lea (TailsAni_HaulAss).l,a1 ; loc_1CEEE: TAnim_SpeedSelected: neg.w d2 addi.w #$800,d2 bpl.s + moveq #0,d2 + lsr.w #8,d2 move.b d2,anim_frame_duration(a0) ; modify frame duration bsr.w TAnim_Do2 add.b d3,mapping_frame(a0) rts ; =========================================================================== ; loc_1CF08 TAnim_Tumble: move.b flip_angle(a0),d0 moveq #0,d1 move.b status(a0),d2 andi.b #1,d2 bne.s TAnim_Tumble_Left andi.b #$FC,render_flags(a0) addi.b #$B,d0 divu.w #$16,d0 addi.b #$75,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_duration(a0) rts ; =========================================================================== ; loc_1CF36 TAnim_Tumble_Left: andi.b #$FC,render_flags(a0) tst.b flip_turned(a0) beq.s + ori.b #1,render_flags(a0) addi.b #$B,d0 bra.s ++ ; =========================================================================== + ori.b #3,render_flags(a0) neg.b d0 addi.b #$8F,d0 + divu.w #$16,d0 addi.b #$75,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_duration(a0) rts ; =========================================================================== ; loc_1CF6E: TAnim_Roll: addq.b #1,d0 ; is the end flag = $FE ? bne.s TAnim_GetTailFrame ; if not, branch mvabs.w inertia(a0),d2 lea (TailsAni_Roll2).l,a1 cmpi.w #$600,d2 bhs.s + lea (TailsAni_Roll).l,a1 + neg.w d2 addi.w #$400,d2 bpl.s + moveq #0,d2 + lsr.w #8,d2 move.b d2,anim_frame_duration(a0) move.b status(a0),d1 andi.b #1,d1 andi.b #$FC,render_flags(a0) or.b d1,render_flags(a0) bra.w TAnim_Do2 ; =========================================================================== ; loc_1CFB2 TAnim_Push: move.w inertia(a0),d2 bmi.s + neg.w d2 + addi.w #$800,d2 bpl.s + moveq #0,d2 + lsr.w #6,d2 move.b d2,anim_frame_duration(a0) lea (TailsAni_Push).l,a1 move.b status(a0),d1 andi.b #1,d1 andi.b #$FC,render_flags(a0) or.b d1,render_flags(a0) bra.w TAnim_Do2 ; =========================================================================== ; loc_1CFE4: TAnim_GetTailFrame: move.w x_vel(a2),d1 move.w y_vel(a2),d2 jsr (CalcAngle).l moveq #0,d1 move.b status(a0),d2 andi.b #1,d2 bne.s loc_1D002 not.b d0 bra.s loc_1D006 ; =========================================================================== loc_1D002: addi.b #$80,d0 loc_1D006: addi.b #$10,d0 bpl.s + moveq #3,d1 + andi.b #$FC,render_flags(a0) eor.b d1,d2 or.b d2,render_flags(a0) lsr.b #3,d0 andi.b #$C,d0 move.b d0,d3 lea (Obj05Ani_Directional).l,a1 move.b #3,anim_frame_duration(a0) bsr.w TAnim_Do2 add.b d3,mapping_frame(a0) rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Animation script - Tails ; --------------------------------------------------------------------------- ; off_1D038: TailsAniData: offsetTable TailsAni_Walk_ptr: offsetTableEntry.w TailsAni_Walk ; 0 ; 0 TailsAni_Run_ptr: offsetTableEntry.w TailsAni_Run ; 1 ; 1 TailsAni_Roll_ptr: offsetTableEntry.w TailsAni_Roll ; 2 ; 2 TailsAni_Roll2_ptr: offsetTableEntry.w TailsAni_Roll2 ; 3 ; 3 TailsAni_Push_ptr: offsetTableEntry.w TailsAni_Push ; 4 ; 4 TailsAni_Wait_ptr: offsetTableEntry.w TailsAni_Wait ; 5 ; 5 TailsAni_Balance_ptr: offsetTableEntry.w TailsAni_Balance ; 6 ; 6 TailsAni_LookUp_ptr: offsetTableEntry.w TailsAni_LookUp ; 7 ; 7 TailsAni_Duck_ptr: offsetTableEntry.w TailsAni_Duck ; 8 ; 8 TailsAni_Spindash_ptr: offsetTableEntry.w TailsAni_Spindash ; 9 ; 9 TailsAni_Dummy1_ptr: offsetTableEntry.w TailsAni_Dummy1 ; 10 ; $A TailsAni_Dummy2_ptr: offsetTableEntry.w TailsAni_Dummy2 ; 11 ; $B TailsAni_Dummy3_ptr: offsetTableEntry.w TailsAni_Dummy3 ; 12 ; $C TailsAni_Stop_ptr: offsetTableEntry.w TailsAni_Stop ; 13 ; $D TailsAni_Float_ptr: offsetTableEntry.w TailsAni_Float ; 14 ; $E TailsAni_Float2_ptr: offsetTableEntry.w TailsAni_Float2 ; 15 ; $F TailsAni_Spring_ptr: offsetTableEntry.w TailsAni_Spring ; 16 ; $10 TailsAni_Hang_ptr: offsetTableEntry.w TailsAni_Hang ; 17 ; $11 TailsAni_Blink_ptr: offsetTableEntry.w TailsAni_Blink ; 18 ; $12 TailsAni_Blink2_ptr: offsetTableEntry.w TailsAni_Blink2 ; 19 ; $13 TailsAni_Hang2_ptr: offsetTableEntry.w TailsAni_Hang2 ; 20 ; $14 TailsAni_Bubble_ptr: offsetTableEntry.w TailsAni_Bubble ; 21 ; $15 TailsAni_DeathBW_ptr: offsetTableEntry.w TailsAni_DeathBW ; 22 ; $16 TailsAni_Drown_ptr: offsetTableEntry.w TailsAni_Drown ; 23 ; $17 TailsAni_Death_ptr: offsetTableEntry.w TailsAni_Death ; 24 ; $18 TailsAni_Hurt_ptr: offsetTableEntry.w TailsAni_Hurt ; 25 ; $19 TailsAni_Hurt2_ptr: offsetTableEntry.w TailsAni_Hurt2 ; 26 ; $1A TailsAni_Slide_ptr: offsetTableEntry.w TailsAni_Slide ; 27 ; $1B TailsAni_Blank_ptr: offsetTableEntry.w TailsAni_Blank ; 28 ; $1C TailsAni_Dummy4_ptr: offsetTableEntry.w TailsAni_Dummy4 ; 29 ; $1D TailsAni_Dummy5_ptr: offsetTableEntry.w TailsAni_Dummy5 ; 30 ; $1E TailsAni_HaulAss_ptr: offsetTableEntry.w TailsAni_HaulAss ; 31 ; $1F TailsAni_Fly_ptr: offsetTableEntry.w TailsAni_Fly ; 32 ; $20 TailsAni_Walk: dc.b $FF,$10,$11,$12,$13,$14,$15, $E, $F,$FF rev02even TailsAni_Run: dc.b $FF,$2E,$2F,$30,$31,$FF,$FF,$FF,$FF,$FF rev02even TailsAni_Roll: dc.b 1,$48,$47,$46,$FF rev02even TailsAni_Roll2: dc.b 1,$48,$47,$46,$FF rev02even TailsAni_Push: dc.b $FD,$63,$64,$65,$66,$FF,$FF,$FF,$FF,$FF rev02even TailsAni_Wait: dc.b 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1 dc.b 1, 1, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 dc.b 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 dc.b 6, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 6,$FE,$1C rev02even TailsAni_Balance: dc.b 9,$69,$69,$6A,$6A,$69,$69,$6A,$6A,$69,$69,$6A,$6A,$69,$69,$6A dc.b $6A,$69,$69,$6A,$6A,$69,$6A,$FF rev02even TailsAni_LookUp: dc.b $3F, 4,$FF rev02even TailsAni_Duck: dc.b $3F,$5B,$FF rev02even TailsAni_Spindash: dc.b 0,$60,$61,$62,$FF rev02even TailsAni_Dummy1: dc.b $3F,$82,$FF rev02even TailsAni_Dummy2: dc.b 7, 8, 8, 9,$FD, 5 rev02even TailsAni_Dummy3: dc.b 7, 9,$FD, 5 rev02even TailsAni_Stop: dc.b 7,$67,$68,$67,$68,$FD, 0 rev02even TailsAni_Float: dc.b 9,$6E,$73,$FF rev02even TailsAni_Float2: dc.b 9,$6E,$6F,$70,$71,$72,$FF rev02even TailsAni_Spring: dc.b 3,$59,$5A,$59,$5A,$59,$5A,$59,$5A,$59,$5A,$59,$5A,$FD, 0 rev02even TailsAni_Hang: dc.b 5,$6C,$6D,$FF rev02even TailsAni_Blink: dc.b $F, 1, 2, 3,$FE, 1 rev02even TailsAni_Blink2: dc.b $F, 1, 2,$FE, 1 rev02even TailsAni_Hang2: dc.b $13,$85,$86,$FF rev02even TailsAni_Bubble: dc.b $B,$74,$74,$12,$13,$FD, 0 rev02even TailsAni_DeathBW: dc.b $20,$5D,$FF rev02even TailsAni_Drown: dc.b $2F,$5D,$FF rev02even TailsAni_Death: dc.b 3,$5D,$FF rev02even TailsAni_Hurt: dc.b 3,$5D,$FF rev02even TailsAni_Hurt2: dc.b 3,$5C,$FF rev02even TailsAni_Slide: dc.b 9,$6B,$5C,$FF rev02even TailsAni_Blank: dc.b $77, 0,$FD, 0 rev02even TailsAni_Dummy4: dc.b 3, 1, 2, 3, 4, 5, 6, 7, 8,$FF rev02even TailsAni_Dummy5: dc.b 3, 1, 2, 3, 4, 5, 6, 7, 8,$FF rev02even TailsAni_HaulAss: dc.b $FF,$32,$33,$FF dc.b $FF,$FF,$FF,$FF,$FF,$FF rev02even TailsAni_Fly: dc.b 1,$5E,$5F,$FF even ; =========================================================================== ; --------------------------------------------------------------------------- ; Tails' Tails pattern loading subroutine ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1D184: LoadTailsTailsDynPLC: moveq #0,d0 move.b mapping_frame(a0),d0 cmp.b (TailsTails_LastLoadedDPLC).w,d0 beq.s return_1D1FE move.b d0,(TailsTails_LastLoadedDPLC).w lea (MapRUnc_Tails).l,a2 add.w d0,d0 adda.w (a2,d0.w),a2 move.w (a2)+,d5 subq.w #1,d5 bmi.s return_1D1FE move.w #tiles_to_bytes(ArtTile_ArtUnc_Tails_Tails),d4 bra.s TPLC_ReadEntry ; --------------------------------------------------------------------------- ; Tails pattern loading subroutine ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1D1AC: LoadTailsDynPLC: moveq #0,d0 move.b mapping_frame(a0),d0 ; load frame number ; loc_1D1B2: LoadTailsDynPLC_Part2: cmp.b (Tails_LastLoadedDPLC).w,d0 beq.s return_1D1FE move.b d0,(Tails_LastLoadedDPLC).w lea (MapRUnc_Tails).l,a2 add.w d0,d0 adda.w (a2,d0.w),a2 move.w (a2)+,d5 subq.w #1,d5 bmi.s return_1D1FE move.w #tiles_to_bytes(ArtTile_ArtUnc_Tails),d4 ; loc_1D1D2: TPLC_ReadEntry: moveq #0,d1 move.w (a2)+,d1 move.w d1,d3 lsr.w #8,d3 andi.w #$F0,d3 addi.w #$10,d3 andi.w #$FFF,d1 lsl.l #5,d1 addi.l #ArtUnc_Tails,d1 move.w d4,d2 add.w d3,d4 add.w d3,d4 jsr (QueueDMATransfer).l dbf d5,TPLC_ReadEntry ; repeat for number of entries return_1D1FE: rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 05 - Tails' tails ; ---------------------------------------------------------------------------- ; Sprite_1D200: Obj05: moveq #0,d0 move.b routine(a0),d0 move.w Obj05_Index(pc,d0.w),d1 jmp Obj05_Index(pc,d1.w) ; =========================================================================== ; off_1D20E: Obj05_States: Obj05_Index: offsetTable offsetTableEntry.w Obj05_Init ; 0 offsetTableEntry.w Obj05_Main ; 2 ; =========================================================================== Obj05_parent_prev_anim = objoff_30 ; loc_1D212 Obj05_Init: addq.b #2,routine(a0) ; => Obj05_Main move.l #MapUnc_Tails,mappings(a0) move.w #make_art_tile(ArtTile_ArtUnc_Tails_Tails,0,0),art_tile(a0) bsr.w Adjust2PArtPointer move.b #2,priority(a0) move.b #$18,width_pixels(a0) move.b #4,render_flags(a0) ; loc_1D23A: Obj05_Main: movea.w parent(a0),a2 ; a2=character move.b angle(a2),angle(a0) move.b status(a2),status(a0) move.w x_pos(a2),x_pos(a0) move.w y_pos(a2),y_pos(a0) andi.w #drawing_mask,art_tile(a0) tst.w art_tile(a2) bpl.s + ori.w #high_priority,art_tile(a0) + moveq #0,d0 move.b anim(a2),d0 btst #5,status(a2) beq.s + moveq #4,d0 + ; This is here so Obj05Ani_Flick works ; It changes anim(a0) itself, so we don't want the below code changing it as well cmp.b Obj05_parent_prev_anim(a0),d0 ; Did Tails' animation change? beq.s .display move.b d0,Obj05_parent_prev_anim(a0) move.b Obj05AniSelection(pc,d0.w),anim(a0) ; If so, update Tails' tails' animation ; loc_1D288: .display: lea (Obj05AniData).l,a1 bsr.w Tails_Animate_Part2 bsr.w LoadTailsTailsDynPLC jsr (DisplaySprite).l rts ; =========================================================================== ; animation master script table for the tails ; chooses which animation script to run depending on what Tails is doing ; byte_1D29E: Obj05AniSelection: dc.b 0,0 ; TailsAni_Walk,Run -> dc.b 3 ; TailsAni_Roll -> Directional dc.b 3 ; TailsAni_Roll2 -> Directional dc.b 9 ; TailsAni_Push -> Pushing dc.b 1 ; TailsAni_Wait -> Swish dc.b 0 ; TailsAni_Balance -> Blank dc.b 2 ; TailsAni_LookUp -> Flick dc.b 1 ; TailsAni_Duck -> Swish dc.b 7 ; TailsAni_Spindash -> Spindash dc.b 0,0,0 ; TailsAni_Dummy1,2,3 -> dc.b 8 ; TailsAni_Stop -> Skidding dc.b 0,0 ; TailsAni_Float,2 -> dc.b 0 ; TailsAni_Spring -> dc.b 0 ; TailsAni_Hang -> dc.b 0,0 ; TailsAni_Blink,2 -> dc.b $A ; TailsAni_Hang2 -> Hanging dc.b 0 ; TailsAni_Bubble -> dc.b 0,0,0,0 ; TailsAni_Death,2,3,4 -> dc.b 0,0 ; TailsAni_Hurt,Slide -> dc.b 0 ; TailsAni_Blank -> dc.b 0,0 ; TailsAni_Dummy4,5 -> dc.b 0 ; TailsAni_HaulAss -> dc.b 0 ; TailsAni_Fly -> even ; --------------------------------------------------------------------------- ; Animation script - Tails' tails ; --------------------------------------------------------------------------- ; off_1D2C0: Obj05AniData: offsetTable offsetTableEntry.w Obj05Ani_Blank ; 0 offsetTableEntry.w Obj05Ani_Swish ; 1 offsetTableEntry.w Obj05Ani_Flick ; 2 offsetTableEntry.w Obj05Ani_Directional ; 3 offsetTableEntry.w Obj05Ani_DownLeft ; 4 offsetTableEntry.w Obj05Ani_Down ; 5 offsetTableEntry.w Obj05Ani_DownRight ; 6 offsetTableEntry.w Obj05Ani_Spindash ; 7 offsetTableEntry.w Obj05Ani_Skidding ; 8 offsetTableEntry.w Obj05Ani_Pushing ; 9 offsetTableEntry.w Obj05Ani_Hanging ; $A Obj05Ani_Blank: dc.b $20, 0,$FF rev02even Obj05Ani_Swish: dc.b 7, 9, $A, $B, $C, $D,$FF rev02even Obj05Ani_Flick: dc.b 3, 9, $A, $B, $C, $D,$FD, 1 rev02even Obj05Ani_Directional: dc.b $FC,$49,$4A,$4B,$4C,$FF ; Tails is moving right rev02even Obj05Ani_DownLeft: dc.b 3,$4D,$4E,$4F,$50,$FF ; Tails is moving up-right rev02even Obj05Ani_Down: dc.b 3,$51,$52,$53,$54,$FF ; Tails is moving up rev02even Obj05Ani_DownRight: dc.b 3,$55,$56,$57,$58,$FF ; Tails is moving up-left rev02even Obj05Ani_Spindash: dc.b 2,$81,$82,$83,$84,$FF rev02even Obj05Ani_Skidding: dc.b 2,$87,$88,$89,$8A,$FF rev02even Obj05Ani_Pushing: dc.b 9,$87,$88,$89,$8A,$FF rev02even Obj05Ani_Hanging: dc.b 9,$81,$82,$83,$84,$FF even ; =========================================================================== JmpTo2_KillCharacter jmp (KillCharacter).l ; =========================================================================== align 4 ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 0A - Small bubbles from Sonic's face while underwater ; ---------------------------------------------------------------------------- ; Sprite_1D320: Obj0A: moveq #0,d0 move.b routine(a0),d0 move.w Obj0A_Index(pc,d0.w),d1 jmp Obj0A_Index(pc,d1.w) ; =========================================================================== ; off_1D32E: Obj0A_States: Obj0A_Index: offsetTable offsetTableEntry.w Obj0A_Init ; 0 offsetTableEntry.w Obj0A_Animate ; 2 offsetTableEntry.w Obj0A_ChkWater ; 4 offsetTableEntry.w Obj0A_Display ; 6 offsetTableEntry.w JmpTo5_DeleteObject ; 8 offsetTableEntry.w Obj0A_Countdown ; $A offsetTableEntry.w Obj0A_AirLeft ; $C offsetTableEntry.w Obj0A_DisplayNumber ; $E offsetTableEntry.w JmpTo5_DeleteObject ; $10 ; =========================================================================== ; loc_1D340: Obj0A_Main: Obj0A_Init: addq.b #2,routine(a0) move.l #Obj24_MapUnc_1FBF6,mappings(a0) tst.b parent+1(a0) beq.s + move.l #Obj24_MapUnc_1FC18,mappings(a0) + move.w #make_art_tile(ArtTile_ArtNem_BigBubbles,0,1),art_tile(a0) move.b #$84,render_flags(a0) move.b #$10,width_pixels(a0) move.b #1,priority(a0) move.b subtype(a0),d0 bpl.s loc_1D388 addq.b #8,routine(a0) andi.w #$7F,d0 move.b d0,objoff_33(a0) bra.w Obj0A_Countdown ; =========================================================================== loc_1D388: move.b d0,anim(a0) move.w x_pos(a0),objoff_30(a0) move.w #-$88,y_vel(a0) ; loc_1D398: Obj0A_Animate: lea (Ani_obj0A).l,a1 jsr (AnimateSprite).l ; loc_1D3A4: Obj0A_ChkWater: move.w (Water_Level_1).w,d0 cmp.w y_pos(a0),d0 ; has bubble reached the water surface? blo.s Obj0A_Wobble ; if not, branch ; pop the bubble: move.b #6,routine(a0) addq.b #7,anim(a0) cmpi.b #$D,anim(a0) beq.s Obj0A_Display blo.s Obj0A_Display move.b #$D,anim(a0) bra.s Obj0A_Display ; =========================================================================== ; loc_1D3CA: Obj0A_Wobble: tst.b (WindTunnel_flag).w beq.s + addq.w #4,objoff_30(a0) + move.b angle(a0),d0 addq.b #1,angle(a0) andi.w #$7F,d0 lea (Obj0A_WobbleData).l,a1 move.b (a1,d0.w),d0 ext.w d0 add.w objoff_30(a0),d0 move.w d0,x_pos(a0) bsr.s Obj0A_ShowNumber jsr (ObjectMove).l tst.b render_flags(a0) bpl.s JmpTo4_DeleteObject jmp (DisplaySprite).l ; =========================================================================== JmpTo4_DeleteObject jmp (DeleteObject).l ; =========================================================================== ; loc_1D40E: Obj0A_DisplayNumber: movea.l objoff_3C(a0),a2 ; a2=character cmpi.b #$C,air_left(a2) bhi.s JmpTo5_DeleteObject ; loc_1D41A: Obj0A_Display: bsr.s Obj0A_ShowNumber lea (Ani_obj0A).l,a1 jsr (AnimateSprite).l jmp (DisplaySprite).l ; =========================================================================== JmpTo5_DeleteObject jmp (DeleteObject).l ; =========================================================================== ; loc_1D434: Obj0A_AirLeft: movea.l objoff_3C(a0),a2 ; a2=character cmpi.b #$C,air_left(a2) ; check air remaining bhi.s JmpTo6_DeleteObject ; if higher than $C, branch subq.w #1,objoff_38(a0) bne.s Obj0A_Display2 move.b #$E,routine(a0) addq.b #7,anim(a0) bra.s Obj0A_Display ; =========================================================================== ; loc_1D452: Obj0A_Display2: lea (Ani_obj0A).l,a1 jsr (AnimateSprite).l bsr.w Obj0A_LoadCountdownArt tst.b render_flags(a0) bpl.s JmpTo6_DeleteObject jmp (DisplaySprite).l ; =========================================================================== JmpTo6_DeleteObject jmp (DeleteObject).l ; =========================================================================== ; loc_1D474: Obj0A_ShowNumber: tst.w objoff_38(a0) beq.s return_1D4BE subq.w #1,objoff_38(a0) bne.s return_1D4BE cmpi.b #7,anim(a0) bhs.s return_1D4BE move.w #$F,objoff_38(a0) clr.w y_vel(a0) move.b #$80,render_flags(a0) move.w x_pos(a0),d0 sub.w (Camera_X_pos).w,d0 addi.w #$80,d0 move.w d0,x_pixel(a0) move.w y_pos(a0),d0 sub.w (Camera_Y_pos).w,d0 addi.w #$80,d0 move.w d0,y_pixel(a0) move.b #$C,routine(a0) return_1D4BE: rts ; =========================================================================== ; byte_1D4C0: Obj0A_WobbleData: dc.b 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2;16 dc.b 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3;32 dc.b 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2;48 dc.b 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0;64 dc.b 0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2,-3,-3,-3,-3,-3;80 dc.b -3,-3,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4;96 dc.b -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-3;112 dc.b -3,-3,-3,-3,-3,-3,-2,-2,-2,-2,-2,-1,-1,-1,-1,-1;128 ; Unused S1 leftover ; This was used by LZ's water ripple effect in REV01 dc.b 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2;144 dc.b 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3;160 dc.b 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2;176 dc.b 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0;192 dc.b 0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2,-3,-3,-3,-3,-3;208 dc.b -3,-3,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4;224 dc.b -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-3;240 dc.b -3,-3,-3,-3,-3,-3,-2,-2,-2,-2,-2,-1,-1,-1,-1,-1;256 ; =========================================================================== ; the countdown numbers go over the dust and splash effect tiles in VRAM ; loc_1D5C0: Obj0A_LoadCountdownArt: moveq #0,d1 move.b mapping_frame(a0),d1 cmpi.b #8,d1 blo.s return_1D604 cmpi.b #$E,d1 bhs.s return_1D604 cmp.b objoff_2E(a0),d1 beq.s return_1D604 move.b d1,objoff_2E(a0) subq.w #8,d1 move.w d1,d0 add.w d1,d1 add.w d0,d1 lsl.w #6,d1 addi.l #ArtUnc_Countdown,d1 move.w #tiles_to_bytes(ArtTile_ArtNem_SonicDust),d2 tst.b parent+1(a0) beq.s + move.w #tiles_to_bytes(ArtTile_ArtNem_TailsDust),d2 + move.w #$60,d3 jsr (QueueDMATransfer).l return_1D604: rts ; =========================================================================== ; loc_1D606: Obj0A_Countdown: movea.l objoff_3C(a0),a2 ; a2=character tst.w objoff_2C(a0) bne.w loc_1D708 cmpi.b #6,routine(a2) bhs.w return_1D81C btst #6,status(a2) beq.w return_1D81C subq.w #1,objoff_38(a0) bpl.w loc_1D72C move.w #$3B,objoff_38(a0) move.w #1,objoff_36(a0) jsr (RandomNumber).l andi.w #1,d0 move.b d0,objoff_34(a0) moveq #0,d0 move.b air_left(a2),d0 ; check air remaining cmpi.w #$19,d0 beq.s Obj0A_WarnSound ; play ding sound if air is $19 cmpi.w #$14,d0 beq.s Obj0A_WarnSound ; play ding sound if air is $14 cmpi.w #$F,d0 beq.s Obj0A_WarnSound ; play ding sound if air is $F cmpi.w #$C,d0 bhi.s Obj0A_ReduceAir ; if air is above $C, branch bne.s + tst.b parent+1(a0) bne.s + move.w #MusID_Countdown,d0 jsr (PlayMusic).l ; play countdown music + subq.b #1,objoff_32(a0) bpl.s Obj0A_ReduceAir move.b objoff_33(a0),objoff_32(a0) bset #7,objoff_36(a0) bra.s Obj0A_ReduceAir ; =========================================================================== ; loc_1D68C: Obj0A_WarnSound: tst.b parent+1(a0) bne.s Obj0A_ReduceAir move.w #SndID_WaterWarning,d0 jsr (PlaySound).l ; play "ding-ding" warning sound ; loc_1D69C: Obj0A_ReduceAir: subq.b #1,air_left(a2) ; subtract 1 from air remaining bcc.w BranchTo_Obj0A_MakeItem ; if air is above 0, branch move.b #$81,obj_control(a2) ; lock controls move.w #SndID_Drown,d0 jsr (PlaySound).l ; play drowning sound move.b #$A,objoff_34(a0) move.w #1,objoff_36(a0) move.w #$78,objoff_2C(a0) movea.l a2,a1 bsr.w ResumeMusic move.l a0,-(sp) movea.l a2,a0 bsr.w Sonic_ResetOnFloor_Part2 move.b #$17,anim(a0) ; use Sonic's drowning animation bset #1,status(a0) bset #high_priority_bit,art_tile(a0) move.w #0,y_vel(a0) move.w #0,x_vel(a0) move.w #0,inertia(a0) movea.l (sp)+,a0 ; load 0bj address ; restore a0 = obj0A cmpa.w #MainCharacter,a2 bne.s + ; if it isn't player 1, branch move.b #1,(Deform_lock).w + rts ; =========================================================================== loc_1D708: subq.w #1,objoff_2C(a0) bne.s + move.b #6,routine(a2) rts ; --------------------------------------------------------------------------- + move.l a0,-(sp) movea.l a2,a0 jsr (ObjectMove).l addi.w #$10,y_vel(a0) movea.l (sp)+,a0 ; load 0bj address bra.s loc_1D72C ; =========================================================================== BranchTo_Obj0A_MakeItem bra.s Obj0A_MakeItem ; =========================================================================== loc_1D72C: tst.w objoff_36(a0) beq.w return_1D81C subq.w #1,objoff_3A(a0) bpl.w return_1D81C ; loc_1D73C: Obj0A_MakeItem: jsr (RandomNumber).l andi.w #$F,d0 addq.w #8,d0 move.w d0,objoff_3A(a0) jsr (SingleObjLoad).l bne.w return_1D81C _move.b id(a0),id(a1) ; load obj0A move.w x_pos(a2),x_pos(a1) ; match its X position to Sonic moveq #6,d0 btst #0,status(a2) beq.s + neg.w d0 move.b #$40,angle(a1) + add.w d0,x_pos(a1) move.w y_pos(a2),y_pos(a1) move.l objoff_3C(a0),objoff_3C(a1) move.b #6,subtype(a1) tst.w objoff_2C(a0) beq.w loc_1D7C6 andi.w #7,objoff_3A(a0) addi.w #0,objoff_3A(a0) move.w y_pos(a2),d0 subi.w #$C,d0 move.w d0,y_pos(a1) jsr (RandomNumber).l move.b d0,angle(a1) move.w (Timer_frames).w,d0 andi.b #3,d0 bne.s loc_1D812 move.b #$E,subtype(a1) bra.s loc_1D812 ; --------------------------------------------------------------------------- ; has something to do with making bubbles come out less regularly ; when Sonic is almost drowning loc_1D7C6: btst #7,objoff_36(a0) beq.s loc_1D812 moveq #0,d2 move.b air_left(a2),d2 cmpi.b #$C,d2 bhs.s loc_1D812 lsr.w #1,d2 jsr (RandomNumber).l andi.w #3,d0 bne.s + bset #6,objoff_36(a0) bne.s loc_1D812 move.b d2,subtype(a1) move.w #$1C,objoff_38(a1) + tst.b objoff_34(a0) bne.s loc_1D812 bset #6,objoff_36(a0) bne.s loc_1D812 move.b d2,subtype(a1) move.w #$1C,objoff_38(a1) loc_1D812: subq.b #1,objoff_34(a0) bpl.s return_1D81C clr.w objoff_36(a0) return_1D81C: rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to play music after a countdown (when Sonic leaves the water) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1D81E: ResumeMusic: cmpi.b #$C,air_left(a1) bhi.s ResumeMusic_Done ; branch if countdown hasn't started yet cmpa.w #MainCharacter,a1 bne.s ResumeMusic_Done ; branch if it isn't player 1 move.w (Level_Music).w,d0 ; prepare to play current level's music btst #status_sec_isInvincible,status_secondary(a1) beq.s + ; branch if Sonic is not invincible move.w #MusID_Invincible,d0 ; prepare to play invincibility music + tst.b (Super_Sonic_flag).w beq.w + ; branch if it isn't Super Sonic move.w #MusID_SuperSonic,d0 ; prepare to play super sonic music + tst.b (Current_Boss_ID).w beq.s + ; branch if not in a boss fight move.w #MusID_Boss,d0 ; prepare to play boss music + jsr (PlayMusic).l ; return_1D858: ResumeMusic_Done: move.b #$1E,air_left(a1) ; reset air to full rts ; =========================================================================== ; animation script for the bubbles ; off_1D860: Ani_obj0A: offsetTable offsetTableEntry.w byte_1D87E ; 0 offsetTableEntry.w byte_1D887 ; 1 offsetTableEntry.w byte_1D890 ; 2 offsetTableEntry.w byte_1D899 ; 3 offsetTableEntry.w byte_1D8A2 ; 4 offsetTableEntry.w byte_1D8AB ; 5 offsetTableEntry.w byte_1D8B4 ; 6 offsetTableEntry.w byte_1D8B9 ; 7 offsetTableEntry.w byte_1D8C1 ; 8 offsetTableEntry.w byte_1D8C9 ; 9 offsetTableEntry.w byte_1D8D1 ; $A offsetTableEntry.w byte_1D8D9 ; $B offsetTableEntry.w byte_1D8E1 ; $C offsetTableEntry.w byte_1D8E9 ; $D offsetTableEntry.w byte_1D8EB ; $E byte_1D87E: dc.b 5, 0, 1, 2, 3, 4, 8, 8,$FC rev02even byte_1D887: dc.b 5, 0, 1, 2, 3, 4, 9, 9,$FC rev02even byte_1D890: dc.b 5, 0, 1, 2, 3, 4, $A, $A,$FC rev02even byte_1D899: dc.b 5, 0, 1, 2, 3, 4, $B, $B,$FC rev02even byte_1D8A2: dc.b 5, 0, 1, 2, 3, 4, $C, $C,$FC rev02even byte_1D8AB: dc.b 5, 0, 1, 2, 3, 4, $D, $D,$FC rev02even byte_1D8B4: dc.b $E, 0, 1, 2,$FC rev02even byte_1D8B9: dc.b 7,$10, 8,$10, 8,$10, 8,$FC rev02even byte_1D8C1: dc.b 7,$10, 9,$10, 9,$10, 9,$FC rev02even byte_1D8C9: dc.b 7,$10, $A,$10, $A,$10, $A,$FC rev02even byte_1D8D1: dc.b 7,$10, $B,$10, $B,$10, $B,$FC rev02even byte_1D8D9: dc.b 7,$10, $C,$10, $C,$10, $C,$FC rev02even byte_1D8E1: dc.b 7,$10, $D,$10, $D,$10, $D,$FC rev02even byte_1D8E9: dc.b $E,$FC rev02even byte_1D8EB: dc.b $E, 1, 2, 3, 4,$FC even ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 38 - Shield ; ---------------------------------------------------------------------------- ; Sprite_1D8F2: Obj38: moveq #0,d0 move.b routine(a0),d0 move.w Obj38_Index(pc,d0.w),d1 jmp Obj38_Index(pc,d1.w) ; =========================================================================== ; off_1D900: Obj38_Index: offsetTable offsetTableEntry.w Obj38_Main ; 0 offsetTableEntry.w Obj38_Shield ; 2 ; =========================================================================== ; loc_1D904: Obj38_Main: addq.b #2,routine(a0) move.l #Obj38_MapUnc_1DBE4,mappings(a0) move.b #4,render_flags(a0) move.b #1,priority(a0) move.b #$18,width_pixels(a0) move.w #make_art_tile(ArtTile_ArtNem_Shield,0,0),art_tile(a0) bsr.w Adjust2PArtPointer ; loc_1D92C: Obj38_Shield: movea.w parent(a0),a2 ; a2=character btst #status_sec_isInvincible,status_secondary(a2) bne.s return_1D976 btst #status_sec_hasShield,status_secondary(a2) beq.s JmpTo7_DeleteObject move.w x_pos(a2),x_pos(a0) move.w y_pos(a2),y_pos(a0) move.b status(a2),status(a0) andi.w #drawing_mask,art_tile(a0) tst.w art_tile(a2) bpl.s Obj38_Display ori.w #high_priority,art_tile(a0) ; loc_1D964: Obj38_Display: lea (Ani_obj38).l,a1 jsr (AnimateSprite).l jmp (DisplaySprite).l ; =========================================================================== return_1D976: rts ; =========================================================================== JmpTo7_DeleteObject jmp (DeleteObject).l ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 35 - Invincibility Stars ; ---------------------------------------------------------------------------- ; Sprite_1D97E: Obj35: moveq #0,d0 move.b objoff_A(a0),d0 move.w Obj35_Index(pc,d0.w),d1 jmp Obj35_Index(pc,d1.w) ; =========================================================================== ; off_1D98C: Obj35_Index: offsetTable offsetTableEntry.w loc_1D9A4 ; 0 offsetTableEntry.w loc_1DA0C ; 2 offsetTableEntry.w loc_1DA80 ; 4 off_1D992: dc.l byte_1DB8F dc.w $B dc.l byte_1DBA4 dc.w $160D dc.l byte_1DBBD dc.w $2C0D ; =========================================================================== loc_1D9A4: moveq #0,d2 lea off_1D992-6(pc),a2 lea (a0),a1 moveq #3,d1 - _move.b id(a0),id(a1) ; load obj35 move.b #4,objoff_A(a1) ; => loc_1DA80 move.l #Obj35_MapUnc_1DCBC,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_Invincible_stars,0,0),art_tile(a1) bsr.w Adjust2PArtPointer2 move.b #4,render_flags(a1) bset #6,render_flags(a1) move.b #$10,mainspr_width(a1) move.b #2,mainspr_childsprites(a1) move.w parent(a0),parent(a1) move.b d2,objoff_36(a1) addq.w #1,d2 move.l (a2)+,objoff_30(a1) move.w (a2)+,objoff_34(a1) lea next_object(a1),a1 ; a1=object dbf d1,- move.b #2,objoff_A(a0) ; => loc_1DA0C move.b #4,objoff_34(a0) loc_1DA0C: movea.w parent(a0),a1 ; a1=character btst #status_sec_isInvincible,status_secondary(a1) beq.w DeleteObject move.w x_pos(a1),d0 move.w d0,x_pos(a0) move.w y_pos(a1),d1 move.w d1,y_pos(a0) lea sub2_x_pos(a0),a2 lea byte_1DB82(pc),a3 moveq #0,d5 loc_1DA34: move.w objoff_38(a0),d2 move.b (a3,d2.w),d5 bpl.s loc_1DA44 clr.w objoff_38(a0) bra.s loc_1DA34 ; =========================================================================== loc_1DA44: addq.w #1,objoff_38(a0) lea byte_1DB42(pc),a6 move.b objoff_34(a0),d6 jsr loc_1DB2C(pc) move.w d2,(a2)+ ; sub2_x_pos move.w d3,(a2)+ ; sub2_y_pos move.w d5,(a2)+ ; sub2_mapframe addi.w #$20,d6 jsr loc_1DB2C(pc) move.w d2,(a2)+ ; sub3_x_pos move.w d3,(a2)+ ; sub3_y_pos move.w d5,(a2)+ ; sub3_mapframe moveq #$12,d0 btst #0,status(a1) beq.s loc_1DA74 neg.w d0 loc_1DA74: add.b d0,objoff_34(a0) move.w #$80,d0 bra.w DisplaySprite3 ; =========================================================================== loc_1DA80: movea.w parent(a0),a1 ; a1=character btst #status_sec_isInvincible,status_secondary(a1) beq.w DeleteObject cmpi.w #2,(Player_mode).w beq.s loc_1DAA4 lea (Sonic_Pos_Record_Index).w,a5 lea (Sonic_Pos_Record_Buf).w,a6 tst.b parent+1(a0) beq.s loc_1DAAC loc_1DAA4: lea (Tails_Pos_Record_Index).w,a5 lea (Tails_Pos_Record_Buf).w,a6 loc_1DAAC: move.b objoff_36(a0),d1 lsl.b #2,d1 move.w d1,d2 add.w d1,d1 add.w d2,d1 move.w (a5),d0 sub.b d1,d0 lea (a6,d0.w),a2 move.w (a2)+,d0 move.w (a2)+,d1 move.w d0,x_pos(a0) move.w d1,y_pos(a0) lea sub2_x_pos(a0),a2 movea.l objoff_30(a0),a3 loc_1DAD4: move.w objoff_38(a0),d2 move.b (a3,d2.w),d5 bpl.s loc_1DAE4 clr.w objoff_38(a0) bra.s loc_1DAD4 ; =========================================================================== loc_1DAE4: swap d5 add.b objoff_35(a0),d2 move.b (a3,d2.w),d5 addq.w #1,objoff_38(a0) lea byte_1DB42(pc),a6 move.b objoff_34(a0),d6 jsr loc_1DB2C(pc) move.w d2,(a2)+ ; sub2_x_pos move.w d3,(a2)+ ; sub2_y_pos move.w d5,(a2)+ ; sub2_mapframe addi.w #$20,d6 swap d5 jsr loc_1DB2C(pc) move.w d2,(a2)+ ; sub3_x_pos move.w d3,(a2)+ ; sub3_y_pos move.w d5,(a2)+ ; sub3_mapframe moveq #2,d0 btst #0,status(a1) beq.s loc_1DB20 neg.w d0 loc_1DB20: add.b d0,objoff_34(a0) move.w #$80,d0 bra.w DisplaySprite3 ; =========================================================================== loc_1DB2C: andi.w #$3E,d6 move.b (a6,d6.w),d2 move.b 1(a6,d6.w),d3 ext.w d2 ext.w d3 add.w d0,d2 add.w d1,d3 rts ; =========================================================================== ; unknown byte_1DB42: dc.w $F00, $F03, $E06, $D08, $B0B, $80D, $60E, $30F dc.w $10, -$3F1, -$6F2, -$8F3, -$BF5, -$DF8, -$EFA, -$FFD dc.w $F000, -$F04, -$E07, -$D09, -$B0C, -$80E, -$60F, -$310 dc.w -$10, $3F0, $6F1, $8F2, $BF4, $DF7, $EF9, $FFC byte_1DB82: dc.b 8, 5, 7, 6, 6, 7, 5, 8, 6, 7, 7, 6,$FF rev02even byte_1DB8F: dc.b 8, 7, 6, 5, 4, 3, 4, 5, 6, 7,$FF dc.b 3, 4, 5, 6, 7, 8, 7, 6, 5, 4 rev02even byte_1DBA4: dc.b 8, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7,$FF dc.b 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3 rev02even byte_1DBBD: dc.b 7, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5, 6,$FF dc.b 1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2 even ; animation script ; byte_1DBD6 Ani_obj38: offsetTable offsetTableEntry.w + ; 0 + dc.b 0, 5, 0, 5, 1, 5, 2, 5, 3, 5, 4,$FF ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj38_MapUnc_1DBE4: BINCLUDE "mappings/sprite/obj38.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj35_MapUnc_1DCBC: BINCLUDE "mappings/sprite/obj35.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 08 - Water splash in Aquatic Ruin Zone, Spindash dust ; ---------------------------------------------------------------------------- ; Sprite_1DD20: Obj08: moveq #0,d0 move.b routine(a0),d0 move.w Obj08_Index(pc,d0.w),d1 jmp Obj08_Index(pc,d1.w) ; =========================================================================== ; off_1DD2E: Obj08_Index: offsetTable offsetTableEntry.w Obj08_Init ; 0 offsetTableEntry.w Obj08_Main ; 2 offsetTableEntry.w BranchTo16_DeleteObject ; 4 offsetTableEntry.w Obj08_CheckSkid ; 6 ; =========================================================================== ; loc_1DD36: Obj08_Init: addq.b #2,routine(a0) move.l #Obj08_MapUnc_1DF5E,mappings(a0) ori.b #4,render_flags(a0) move.b #1,priority(a0) move.b #$10,width_pixels(a0) move.w #make_art_tile(ArtTile_ArtNem_SonicDust,0,0),art_tile(a0) move.w #MainCharacter,parent(a0) move.w #tiles_to_bytes(ArtTile_ArtNem_SonicDust),objoff_3C(a0) cmpa.w #Sonic_Dust,a0 beq.s + move.b #1,objoff_34(a0) cmpi.w #2,(Player_mode).w beq.s + move.w #make_art_tile(ArtTile_ArtNem_TailsDust,0,0),art_tile(a0) move.w #Sidekick,parent(a0) move.w #tiles_to_bytes(ArtTile_ArtNem_TailsDust),objoff_3C(a0) + bsr.w Adjust2PArtPointer ; loc_1DD90: Obj08_Main: movea.w parent(a0),a2 ; a2=character moveq #0,d0 move.b anim(a0),d0 ; use current animation as a secondary routine counter add.w d0,d0 move.w Obj08_DisplayModes(pc,d0.w),d1 jmp Obj08_DisplayModes(pc,d1.w) ; =========================================================================== ; off_1DDA4: Obj08_DisplayModes: offsetTable offsetTableEntry.w Obj08_Display ; 0 offsetTableEntry.w Obj08_MdSplash ; 2 offsetTableEntry.w Obj08_MdSpindashDust ; 4 offsetTableEntry.w Obj08_MdSkidDust ; 6 ; =========================================================================== ; loc_1DDAC: Obj08_MdSplash: move.w (Water_Level_1).w,y_pos(a0) tst.b next_anim(a0) bne.s Obj08_Display move.w x_pos(a2),x_pos(a0) move.b #0,status(a0) andi.w #drawing_mask,art_tile(a0) bra.s Obj08_Display ; =========================================================================== ; loc_1DDCC: Obj08_MdSpindashDust: cmpi.b #$C,air_left(a2) blo.s Obj08_ResetDisplayMode cmpi.b #4,routine(a2) bhs.s Obj08_ResetDisplayMode tst.b spindash_flag(a2) beq.s Obj08_ResetDisplayMode move.w x_pos(a2),x_pos(a0) move.w y_pos(a2),y_pos(a0) move.b status(a2),status(a0) andi.b #1,status(a0) tst.b objoff_34(a0) beq.s + subi_.w #4,y_pos(a0) + tst.b next_anim(a0) bne.s Obj08_Display andi.w #drawing_mask,art_tile(a0) tst.w art_tile(a2) bpl.s Obj08_Display ori.w #high_priority,art_tile(a0) bra.s Obj08_Display ; =========================================================================== ; loc_1DE20: Obj08_MdSkidDust: cmpi.b #$C,air_left(a2) blo.s Obj08_ResetDisplayMode ; loc_1DE28: Obj08_Display: lea (Ani_obj08).l,a1 jsr (AnimateSprite).l bsr.w Obj08_LoadDustOrSplashArt jmp (DisplaySprite).l ; =========================================================================== ; loc_1DE3E: Obj08_ResetDisplayMode: move.b #0,anim(a0) rts ; =========================================================================== BranchTo16_DeleteObject bra.w DeleteObject ; =========================================================================== ; loc_1DE4A: Obj08_CheckSkid: movea.w parent(a0),a2 ; a2=character cmpi.b #AniIDSonAni_Stop,anim(a2) ; SonAni_Stop beq.s Obj08_SkidDust move.b #2,routine(a0) move.b #0,objoff_32(a0) rts ; =========================================================================== ; loc_1DE64: Obj08_SkidDust: subq.b #1,objoff_32(a0) bpl.s loc_1DEE0 move.b #3,objoff_32(a0) bsr.w SingleObjLoad bne.s loc_1DEE0 _move.b id(a0),id(a1) ; load obj08 move.w x_pos(a2),x_pos(a1) move.w y_pos(a2),y_pos(a1) addi.w #$10,y_pos(a1) tst.b objoff_34(a0) beq.s + subi_.w #4,y_pos(a1) + move.b #0,status(a1) move.b #3,anim(a1) addq.b #2,routine(a1) move.l mappings(a0),mappings(a1) move.b render_flags(a0),render_flags(a1) move.b #1,priority(a1) move.b #4,width_pixels(a1) move.w art_tile(a0),art_tile(a1) move.w parent(a0),parent(a1) andi.w #drawing_mask,art_tile(a1) tst.w art_tile(a2) bpl.s loc_1DEE0 ori.w #high_priority,art_tile(a1) loc_1DEE0: bsr.s Obj08_LoadDustOrSplashArt rts ; =========================================================================== ; loc_1DEE4: Obj08_LoadDustOrSplashArt: moveq #0,d0 move.b mapping_frame(a0),d0 cmp.b objoff_30(a0),d0 beq.s return_1DF36 move.b d0,objoff_30(a0) lea (Obj08_MapRUnc_1E074).l,a2 add.w d0,d0 adda.w (a2,d0.w),a2 move.w (a2)+,d5 subq.w #1,d5 bmi.s return_1DF36 move.w objoff_3C(a0),d4 - moveq #0,d1 move.w (a2)+,d1 move.w d1,d3 lsr.w #8,d3 andi.w #$F0,d3 addi.w #$10,d3 andi.w #$FFF,d1 lsl.l #5,d1 addi.l #ArtUnc_Splash,d1 move.w d4,d2 add.w d3,d4 add.w d3,d4 jsr (QueueDMATransfer).l dbf d5,- return_1DF36: rts ; =========================================================================== ; animation script ; off_1DF38: Ani_obj08: offsetTable offsetTableEntry.w Obj08Ani_Null ; 0 offsetTableEntry.w Obj08Ani_Splash ; 1 offsetTableEntry.w Obj08Ani_Dash ; 2 offsetTableEntry.w Obj08Ani_Skid ; 3 Obj08Ani_Null: dc.b $1F, 0,$FF rev02even Obj08Ani_Splash:dc.b 3, 1, 2, 3, 4, 5, 6, 7, 8, 9,$FD, 0 rev02even Obj08Ani_Dash: dc.b 1, $A, $B, $C, $D, $E, $F,$10,$FF rev02even Obj08Ani_Skid: dc.b 3,$11,$12,$13,$14,$FC even ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj08_MapUnc_1DF5E: BINCLUDE "mappings/sprite/obj08.bin" ; ------------------------------------------------------------------------------- ; dynamic pattern loading cues ; ------------------------------------------------------------------------------- Obj08_MapRUnc_1E074: BINCLUDE "mappings/spriteDPLC/obj08.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 7E - Super Sonic's stars ; ---------------------------------------------------------------------------- ; Sprite_1E0F0: Obj7E: moveq #0,d0 move.b routine(a0),d0 move.w Obj7E_Index(pc,d0.w),d1 jmp Obj7E_Index(pc,d1.w) ; =========================================================================== ; off_1E0FE: Obj7E_States: Obj7E_Index: offsetTable offsetTableEntry.w Obj7E_Init ; 0 offsetTableEntry.w Obj7E_Main ; 2 ; =========================================================================== ; loc_1E102: Obj7E_Init: addq.b #2,routine(a0) move.l #Obj7E_MapUnc_1E1BE,mappings(a0) move.b #4,render_flags(a0) move.b #1,priority(a0) move.b #$18,width_pixels(a0) move.w #make_art_tile(ArtTile_ArtNem_SuperSonic_stars,0,0),art_tile(a0) bsr.w Adjust2PArtPointer btst #high_priority_bit,(MainCharacter+art_tile).w beq.s Obj7E_Main bset #high_priority_bit,art_tile(a0) ; loc_1E138: Obj7E_Main: tst.b (Super_Sonic_flag).w beq.s JmpTo8_DeleteObject tst.b objoff_30(a0) beq.s loc_1E188 subq.b #1,anim_frame_duration(a0) bpl.s loc_1E170 move.b #1,anim_frame_duration(a0) addq.b #1,mapping_frame(a0) cmpi.b #6,mapping_frame(a0) blo.s loc_1E170 move.b #0,mapping_frame(a0) move.b #0,objoff_30(a0) move.b #1,objoff_31(a0) rts ; =========================================================================== loc_1E170: tst.b objoff_31(a0) bne.s JmpTo6_DisplaySprite loc_1E176: move.w (MainCharacter+x_pos).w,x_pos(a0) move.w (MainCharacter+y_pos).w,y_pos(a0) JmpTo6_DisplaySprite jmp (DisplaySprite).l ; =========================================================================== loc_1E188: tst.b (MainCharacter+obj_control).w bne.s loc_1E1AA mvabs.w (MainCharacter+inertia).w,d0 cmpi.w #$800,d0 blo.s loc_1E1AA move.b #0,mapping_frame(a0) move.b #1,objoff_30(a0) bra.s loc_1E176 ; =========================================================================== loc_1E1AA: move.b #0,objoff_30(a0) move.b #0,objoff_31(a0) rts ; =========================================================================== JmpTo8_DeleteObject jmp (DeleteObject).l ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj7E_MapUnc_1E1BE: BINCLUDE "mappings/sprite/obj7E.bin" ; =========================================================================== if gameRevision<2 nop endif ; --------------------------------------------------------------------------- ; Subroutine to change Sonic's angle & position as he walks along the floor ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1E234: Sonic_AnglePos: AnglePos: move.l #Primary_Collision,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s + move.l #Secondary_Collision,(Collision_addr).w + move.b top_solid_bit(a0),d5 btst #3,status(a0) beq.s + moveq #0,d0 move.b d0,(Primary_Angle).w move.b d0,(Secondary_Angle).w rts ; --------------------------------------------------------------------------- + moveq #3,d0 move.b d0,(Primary_Angle).w move.b d0,(Secondary_Angle).w move.b angle(a0),d0 addi.b #$20,d0 bpl.s loc_1E286 move.b angle(a0),d0 bpl.s + subq.b #1,d0 + addi.b #$20,d0 bra.s loc_1E292 ; --------------------------------------------------------------------------- loc_1E286: move.b angle(a0),d0 bpl.s loc_1E28E addq.b #1,d0 loc_1E28E: addi.b #$1F,d0 loc_1E292: andi.b #$C0,d0 cmpi.b #$40,d0 beq.w Sonic_WalkVertL cmpi.b #$80,d0 beq.w Sonic_WalkCeiling cmpi.b #$C0,d0 beq.w Sonic_WalkVertR move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b y_radius(a0),d0 ext.w d0 add.w d0,d2 move.b x_radius(a0),d0 ext.w d0 add.w d0,d3 lea (Primary_Angle).w,a4 movea.w #$10,a3 move.w #0,d6 bsr.w FindFloor move.w d1,-(sp) move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b y_radius(a0),d0 ext.w d0 add.w d0,d2 move.b x_radius(a0),d0 ext.w d0 neg.w d0 add.w d0,d3 lea (Secondary_Angle).w,a4 movea.w #$10,a3 move.w #0,d6 bsr.w FindFloor move.w (sp)+,d0 bsr.w Sonic_Angle tst.w d1 beq.s return_1E31C bpl.s loc_1E31E cmpi.w #-$E,d1 blt.s return_1E31C add.w d1,y_pos(a0) return_1E31C: rts ; =========================================================================== loc_1E31E: mvabs.b x_vel(a0),d0 addq.b #4,d0 cmpi.b #$E,d0 blo.s + move.b #$E,d0 + cmp.b d0,d1 bgt.s loc_1E33C loc_1E336: add.w d1,y_pos(a0) rts ; =========================================================================== loc_1E33C: tst.b stick_to_convex(a0) bne.s loc_1E336 bset #1,status(a0) bclr #5,status(a0) move.b #AniIDSonAni_Run,next_anim(a0) rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to change Sonic's angle as he walks along the floor ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1E356: Sonic_Angle: move.b (Secondary_Angle).w,d2 cmp.w d0,d1 ble.s + move.b (Primary_Angle).w,d2 move.w d0,d1 + btst #0,d2 bne.s loc_1E380 move.b d2,d0 sub.b angle(a0),d0 bpl.s + neg.b d0 + cmpi.b #$20,d0 bhs.s loc_1E380 move.b d2,angle(a0) rts ; =========================================================================== loc_1E380: move.b angle(a0),d2 addi.b #$20,d2 andi.b #$C0,d2 move.b d2,angle(a0) rts ; End of function Sonic_Angle ; --------------------------------------------------------------------------- ; Subroutine allowing Sonic to walk up a vertical slope/wall to his right ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1E392: Sonic_WalkVertR: move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b x_radius(a0),d0 ext.w d0 neg.w d0 add.w d0,d2 move.b y_radius(a0),d0 ext.w d0 add.w d0,d3 lea (Primary_Angle).w,a4 movea.w #$10,a3 move.w #0,d6 bsr.w FindWall move.w d1,-(sp) move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b x_radius(a0),d0 ext.w d0 add.w d0,d2 move.b y_radius(a0),d0 ext.w d0 add.w d0,d3 lea (Secondary_Angle).w,a4 movea.w #$10,a3 move.w #0,d6 bsr.w FindWall move.w (sp)+,d0 bsr.w Sonic_Angle tst.w d1 beq.s return_1E400 bpl.s loc_1E402 cmpi.w #-$E,d1 blt.s return_1E400 add.w d1,x_pos(a0) return_1E400: rts ; =========================================================================== loc_1E402: mvabs.b y_vel(a0),d0 addq.b #4,d0 cmpi.b #$E,d0 blo.s + move.b #$E,d0 + cmp.b d0,d1 bgt.s loc_1E420 loc_1E41A: add.w d1,x_pos(a0) rts ; =========================================================================== loc_1E420: tst.b stick_to_convex(a0) bne.s loc_1E41A bset #1,status(a0) bclr #5,status(a0) move.b #AniIDSonAni_Run,next_anim(a0) rts ; =========================================================================== ;loc_1E43A Sonic_WalkCeiling: move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b y_radius(a0),d0 ext.w d0 sub.w d0,d2 eori.w #$F,d2 move.b x_radius(a0),d0 ext.w d0 add.w d0,d3 lea (Primary_Angle).w,a4 movea.w #-$10,a3 move.w #$800,d6 bsr.w FindFloor move.w d1,-(sp) move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b y_radius(a0),d0 ext.w d0 sub.w d0,d2 eori.w #$F,d2 move.b x_radius(a0),d0 ext.w d0 sub.w d0,d3 lea (Secondary_Angle).w,a4 movea.w #-$10,a3 move.w #$800,d6 bsr.w FindFloor move.w (sp)+,d0 bsr.w Sonic_Angle tst.w d1 beq.s return_1E4AE bpl.s loc_1E4B0 cmpi.w #-$E,d1 blt.s return_1E4AE sub.w d1,y_pos(a0) return_1E4AE: rts ; =========================================================================== loc_1E4B0: mvabs.b x_vel(a0),d0 addq.b #4,d0 cmpi.b #$E,d0 blo.s + move.b #$E,d0 + cmp.b d0,d1 bgt.s loc_1E4CE loc_1E4C8: sub.w d1,y_pos(a0) rts ; =========================================================================== loc_1E4CE: tst.b stick_to_convex(a0) bne.s loc_1E4C8 bset #1,status(a0) bclr #5,status(a0) move.b #AniIDSonAni_Run,next_anim(a0) rts ; =========================================================================== ;loc_1E4E8 Sonic_WalkVertL: move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b x_radius(a0),d0 ext.w d0 sub.w d0,d2 move.b y_radius(a0),d0 ext.w d0 sub.w d0,d3 eori.w #$F,d3 lea (Primary_Angle).w,a4 movea.w #-$10,a3 move.w #$400,d6 bsr.w FindWall move.w d1,-(sp) move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b x_radius(a0),d0 ext.w d0 add.w d0,d2 move.b y_radius(a0),d0 ext.w d0 sub.w d0,d3 eori.w #$F,d3 lea (Secondary_Angle).w,a4 movea.w #-$10,a3 move.w #$400,d6 bsr.w FindWall move.w (sp)+,d0 bsr.w Sonic_Angle tst.w d1 beq.s return_1E55C bpl.s loc_1E55E cmpi.w #-$E,d1 blt.s return_1E55C sub.w d1,x_pos(a0) return_1E55C: rts ; =========================================================================== loc_1E55E: mvabs.b y_vel(a0),d0 addq.b #4,d0 cmpi.b #$E,d0 blo.s + move.b #$E,d0 + cmp.b d0,d1 bgt.s loc_1E57C loc_1E576: sub.w d1,x_pos(a0) rts ; =========================================================================== loc_1E57C: tst.b stick_to_convex(a0) bne.s loc_1E576 bset #1,status(a0) bclr #5,status(a0) move.b #AniIDSonAni_Run,next_anim(a0) rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to find which tile is in the specified location ; d2 = y_pos ; d3 = x_pos ; returns relevant block ID in (a1) ; a1 is pointer to block in chunk table ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1E596: Floor_ChkTile: Find_Tile: move.w d2,d0 ; y_pos add.w d0,d0 andi.w #$F00,d0 ; rounded 2*y_pos move.w d3,d1 ; x_pos lsr.w #3,d1 move.w d1,d4 lsr.w #4,d1 ; x_pos/128 = x_of_chunk andi.w #$7F,d1 add.w d1,d0 ; d0 is relevant chunk ID now moveq #-1,d1 clr.w d1 ; d1 is now $FFFF0000 = Chunk_Table lea (Level_Layout).w,a1 move.b (a1,d0.w),d1 ; move 128*128 chunk ID to d1 add.w d1,d1 move.w word_1E5D0(pc,d1.w),d1 move.w d2,d0 ; y_pos andi.w #$70,d0 add.w d0,d1 andi.w #$E,d4 ; x_pos/8 add.w d4,d1 movea.l d1,a1 ; address of block ID rts ; =========================================================================== ; precalculated values for Find_Tile ; (Sonic 1 calculated it every time instead of using a table) word_1E5D0: c := 0 rept 256 dc.w c c := c+$80 endm ; =========================================================================== ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Scans vertically for up to 2 16x16 blocks to find solid ground or ceiling. ; d2 = y_pos ; d3 = x_pos ; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top) ; d6 = $0000 for no flip, $0800 for vertical flip ; a3 = delta-y for next location to check if current one is empty ; a4 = pointer to angle buffer ; returns relevant block ID in (a1) ; returns distance in d1 ; returns angle in (a4) ; loc_1E7D0: FindFloor: bsr.w Find_Tile move.w (a1),d0 move.w d0,d4 andi.w #$3FF,d0 beq.s loc_1E7E2 btst d5,d4 bne.s loc_1E7F0 loc_1E7E2: add.w a3,d2 bsr.w FindFloor2 sub.w a3,d2 addi.w #$10,d1 rts ; =========================================================================== loc_1E7F0: ; block has some solidity movea.l (Collision_addr).w,a2 ; pointer to collision data, i.e. blockID -> collisionID array move.b (a2,d0.w),d0 ; get collisionID andi.w #$FF,d0 beq.s loc_1E7E2 lea (ColCurveMap).l,a2 move.b (a2,d0.w),(a4) ; get angle from AngleMap --> (a4) lsl.w #4,d0 move.w d3,d1 ; x_pos btst #$A,d4 ; adv.blockID in d4 - X flipping beq.s + not.w d1 neg.b (a4) + btst #$B,d4 ; Y flipping beq.s + addi.b #$40,(a4) neg.b (a4) subi.b #$40,(a4) + andi.w #$F,d1 ; x_pos (mod 16) add.w d0,d1 ; d0 = 16*blockID -> offset in ColArray to look up lea (ColArray).l,a2 move.b (a2,d1.w),d0 ; heigth from ColArray ext.w d0 eor.w d6,d4 btst #$B,d4 ; Y flipping beq.s + neg.w d0 + tst.w d0 beq.s loc_1E7E2 ; no collision bmi.s loc_1E85E cmpi.b #$10,d0 beq.s loc_1E86A move.w d2,d1 andi.w #$F,d1 add.w d1,d0 move.w #$F,d1 sub.w d0,d1 rts ; =========================================================================== loc_1E85E: move.w d2,d1 andi.w #$F,d1 add.w d1,d0 bpl.w loc_1E7E2 loc_1E86A: sub.w a3,d2 bsr.w FindFloor2 add.w a3,d2 subi.w #$10,d1 rts ; End of function FindFloor ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Checks a 16x16 block to find solid ground or ceiling. ; d2 = y_pos ; d3 = x_pos ; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top) ; d6 = $0000 for no flip, $0800 for vertical flip ; a4 = pointer to angle buffer ; returns relevant block ID in (a1) ; returns distance in d1 ; returns angle in (a4) ; loc_1E878: FindFloor2: bsr.w Find_Tile move.w (a1),d0 move.w d0,d4 andi.w #$3FF,d0 beq.s loc_1E88A btst d5,d4 bne.s loc_1E898 loc_1E88A: move.w #$F,d1 move.w d2,d0 andi.w #$F,d0 sub.w d0,d1 rts ; =========================================================================== loc_1E898: movea.l (Collision_addr).w,a2 move.b (a2,d0.w),d0 andi.w #$FF,d0 beq.s loc_1E88A lea (ColCurveMap).l,a2 move.b (a2,d0.w),(a4) lsl.w #4,d0 move.w d3,d1 btst #$A,d4 beq.s + not.w d1 neg.b (a4) + btst #$B,d4 beq.s + addi.b #$40,(a4) neg.b (a4) subi.b #$40,(a4) + andi.w #$F,d1 add.w d0,d1 lea (ColArray).l,a2 move.b (a2,d1.w),d0 ext.w d0 eor.w d6,d4 btst #$B,d4 beq.s + neg.w d0 + tst.w d0 beq.s loc_1E88A bmi.s loc_1E900 move.w d2,d1 andi.w #$F,d1 add.w d1,d0 move.w #$F,d1 sub.w d0,d1 rts ; =========================================================================== loc_1E900: move.w d2,d1 andi.w #$F,d1 add.w d1,d0 bpl.w loc_1E88A not.w d1 rts ; =========================================================================== ; Checks a 16x16 block to find solid ground or ceiling. May check an additional ; 16x16 block up for ceilings. ; d2 = y_pos ; d3 = x_pos ; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top) ; d6 = $0000 for no flip, $0800 for vertical flip ; a4 = pointer to angle buffer ; returns relevant block ID in (a1) ; returns distance in d1 ; returns angle in (a4) ; loc_1E910: Obj_CheckInFloor: Ring_FindFloor: bsr.w Find_Tile move.w (a1),d0 move.w d0,d4 andi.w #$3FF,d0 beq.s loc_1E922 btst d5,d4 bne.s loc_1E928 loc_1E922: move.w #$10,d1 rts ; =========================================================================== loc_1E928: movea.l (Collision_addr).w,a2 move.b (a2,d0.w),d0 andi.w #$FF,d0 beq.s loc_1E922 lea (ColCurveMap).l,a2 move.b (a2,d0.w),(a4) lsl.w #4,d0 move.w d3,d1 btst #$A,d4 beq.s + not.w d1 neg.b (a4) + btst #$B,d4 beq.s + addi.b #$40,(a4) neg.b (a4) subi.b #$40,(a4) + andi.w #$F,d1 add.w d0,d1 lea (ColArray).l,a2 move.b (a2,d1.w),d0 ext.w d0 eor.w d6,d4 btst #$B,d4 beq.s + neg.w d0 + tst.w d0 beq.s loc_1E922 bmi.s loc_1E996 cmpi.b #$10,d0 beq.s loc_1E9A2 move.w d2,d1 andi.w #$F,d1 add.w d1,d0 move.w #$F,d1 sub.w d0,d1 rts ; =========================================================================== loc_1E996: move.w d2,d1 andi.w #$F,d1 add.w d1,d0 bpl.w loc_1E922 loc_1E9A2: sub.w a3,d2 bsr.w FindFloor2 add.w a3,d2 subi.w #$10,d1 rts ; =========================================================================== ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Scans horizontally for up to 2 16x16 blocks to find solid walls. ; d2 = y_pos ; d3 = x_pos ; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top) ; d6 = $0000 for no flip, $0400 for horizontal flip ; a3 = delta-x for next location to check if current one is empty ; a4 = pointer to angle buffer ; returns relevant block ID in (a1) ; returns distance to left/right in d1 ; returns angle in (a4) ; loc_1E9B0: FindWall: bsr.w Find_Tile move.w (a1),d0 move.w d0,d4 andi.w #$3FF,d0 ; plain blockID beq.s loc_1E9C2 ; no collision btst d5,d4 bne.s loc_1E9D0 loc_1E9C2: add.w a3,d3 bsr.w FindWall2 sub.w a3,d3 addi.w #$10,d1 rts ; =========================================================================== loc_1E9D0: movea.l (Collision_addr).w,a2 move.b (a2,d0.w),d0 andi.w #$FF,d0 ; relevant collisionArrayEntry beq.s loc_1E9C2 lea (ColCurveMap).l,a2 move.b (a2,d0.w),(a4) lsl.w #4,d0 ; offset in collision array move.w d2,d1 ; y btst #$B,d4 ; y-mirror? beq.s + not.w d1 addi.b #$40,(a4) neg.b (a4) subi.b #$40,(a4) + btst #$A,d4 ; x-mirror? beq.s + neg.b (a4) + andi.w #$F,d1 ; y add.w d0,d1 ; line to look up lea (ColArray2).l,a2 ; rotated collision array move.b (a2,d1.w),d0 ; collision value ext.w d0 eor.w d6,d4 ; set x-flip flag if from the right btst #$A,d4 ; x-mirror? beq.s + neg.w d0 + tst.w d0 beq.s loc_1E9C2 bmi.s loc_1EA3E cmpi.b #$10,d0 beq.s loc_1EA4A move.w d3,d1 ; x andi.w #$F,d1 add.w d1,d0 move.w #$F,d1 sub.w d0,d1 rts ; =========================================================================== loc_1EA3E: move.w d3,d1 andi.w #$F,d1 add.w d1,d0 bpl.w loc_1E9C2 ; no collision loc_1EA4A: sub.w a3,d3 bsr.w FindWall2 add.w a3,d3 subi.w #$10,d1 rts ; End of function FindWall ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Checks a 16x16 blocks to find solid walls. ; d2 = y_pos ; d3 = x_pos ; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top) ; d6 = $0000 for no flip, $0400 for horizontal flip ; a4 = pointer to angle buffer ; returns relevant block ID in (a1) ; returns distance to left/right in d1 ; returns angle in (a4) ; loc_1EA58: FindWall2: bsr.w Find_Tile move.w (a1),d0 move.w d0,d4 andi.w #$3FF,d0 beq.s loc_1EA6A btst d5,d4 bne.s loc_1EA78 loc_1EA6A: move.w #$F,d1 move.w d3,d0 andi.w #$F,d0 sub.w d0,d1 rts ; =========================================================================== loc_1EA78: movea.l (Collision_addr).w,a2 move.b (a2,d0.w),d0 andi.w #$FF,d0 beq.s loc_1EA6A lea (ColCurveMap).l,a2 move.b (a2,d0.w),(a4) lsl.w #4,d0 move.w d2,d1 btst #$B,d4 beq.s + not.w d1 addi.b #$40,(a4) neg.b (a4) subi.b #$40,(a4) + btst #$A,d4 beq.s + neg.b (a4) + andi.w #$F,d1 add.w d0,d1 lea (ColArray2).l,a2 move.b (a2,d1.w),d0 ext.w d0 eor.w d6,d4 btst #$A,d4 beq.s + neg.w d0 + tst.w d0 beq.s loc_1EA6A bmi.s loc_1EAE0 move.w d3,d1 andi.w #$F,d1 add.w d1,d0 move.w #$F,d1 sub.w d0,d1 rts ; =========================================================================== loc_1EAE0: move.w d3,d1 andi.w #$F,d1 add.w d1,d0 bpl.w loc_1EA6A not.w d1 rts ; End of function FindWall2 ; --------------------------------------------------------------------------- ; Unused floor/wall subroutine - logs something to do with collision ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; return_1EAF0: FloorLog_Unk: rts ; --------------------------------------------------------------------------- lea (ColArray).l,a1 lea (ColArray).l,a2 ; for d3 from 255 to 0 move.w #$FF,d3 - moveq #$10,d5 ; for d2 from 15 to 0 move.w #$F,d2 - moveq #0,d4 ; for d1 from 15 to 0 move.w #$F,d1 - move.w (a1)+,d0 lsr.l d5,d0 addx.w d4,d4 dbf d1,- ; end for d1 move.w d4,(a2)+ suba.w #$20,a1 subq.w #1,d5 dbf d2,-- ; end for d2 adda.w #$20,a1 dbf d3,--- ; end for d3 lea (ColArray).l,a1 lea (ColArray2).l,a2 bsr.s FloorLog_Unk2 lea (ColArray).l,a1 lea (ColArray).l,a2 ; End of function FloorLog_Unk ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1EB46: FloorLog_Unk2: move.w #$FFF,d3 - moveq #0,d2 move.w #$F,d1 move.w (a1)+,d0 beq.s loc_1EB78 bmi.s ++ - lsr.w #1,d0 bcc.s + addq.b #1,d2 + dbf d1,- bra.s loc_1EB7A ; =========================================================================== + cmpi.w #-1,d0 beq.s ++ - lsl.w #1,d0 bcc.s + subq.b #1,d2 + dbf d1,- bra.s loc_1EB7A ; =========================================================================== + move.w #$10,d0 loc_1EB78: move.w d0,d2 loc_1EB7A: move.b d2,(a2)+ dbf d3,--- rts ; End of function FloorLog_Unk2 if gameRevision<2 nop endif ; --------------------------------------------------------------------------- ; Subroutine to calculate how much space is in front of Sonic or Tails on the ground ; d0 = some input angle ; d1 = output about how many pixels (up to some high enough amount) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1EB84: Sonic_WalkSpeed: CalcRoomInFront: move.l #Primary_Collision,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s + move.l #Secondary_Collision,(Collision_addr).w + move.b lrb_solid_bit(a0),d5 ; Want walls or ceilings move.l x_pos(a0),d3 move.l y_pos(a0),d2 move.w x_vel(a0),d1 ext.l d1 asl.l #8,d1 add.l d1,d3 move.w y_vel(a0),d1 ext.l d1 asl.l #8,d1 add.l d1,d2 swap d2 swap d3 move.b d0,(Primary_Angle).w move.b d0,(Secondary_Angle).w move.b d0,d1 addi.b #$20,d0 bpl.s loc_1EBDC move.b d1,d0 bpl.s + subq.b #1,d0 + addi.b #$20,d0 bra.s loc_1EBE6 ; --------------------------------------------------------------------------- loc_1EBDC: move.b d1,d0 bpl.s + addq.b #1,d0 + addi.b #$1F,d0 loc_1EBE6: andi.b #$C0,d0 beq.w CheckFloorDist_Part2 ; Player is going mostly down cmpi.b #$80,d0 beq.w CheckCeilingDist_Part2 ; Player is going mostly up andi.b #$38,d1 bne.s + addq.w #8,d2 + cmpi.b #$40,d0 beq.w CheckLeftWallDist_Part2 ; Player is going mostly left bra.w CheckRightWallDist_Part2 ; Player is going mostly right ; End of function CalcRoomInFront ; --------------------------------------------------------------------------- ; Subroutine to calculate how much space is empty above Sonic's/Tails' head ; d0 = input angle perpendicular to the spine ; d1 = output about how many pixels are overhead (up to some high enough amount) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_1EC0A: CalcRoomOverHead: move.l #Primary_Collision,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s + move.l #Secondary_Collision,(Collision_addr).w + move.b lrb_solid_bit(a0),d5 move.b d0,(Primary_Angle).w move.b d0,(Secondary_Angle).w addi.b #$20,d0 andi.b #$C0,d0 cmpi.b #$40,d0 beq.w CheckLeftCeilingDist cmpi.b #$80,d0 beq.w Sonic_CheckCeiling cmpi.b #$C0,d0 beq.w CheckRightCeilingDist ; End of function CalcRoomOverHead ; --------------------------------------------------------------------------- ; Subroutine to check if Sonic/Tails is near the floor ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1EC4E: Sonic_HitFloor: Sonic_CheckFloor: move.l #Primary_Collision,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s + move.l #Secondary_Collision,(Collision_addr).w + move.b top_solid_bit(a0),d5 move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b y_radius(a0),d0 ext.w d0 add.w d0,d2 move.b x_radius(a0),d0 ext.w d0 add.w d0,d3 lea (Primary_Angle).w,a4 movea.w #$10,a3 move.w #0,d6 bsr.w FindFloor move.w d1,-(sp) move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b y_radius(a0),d0 ext.w d0 add.w d0,d2 move.b x_radius(a0),d0 ext.w d0 sub.w d0,d3 lea (Secondary_Angle).w,a4 movea.w #$10,a3 move.w #0,d6 bsr.w FindFloor move.w (sp)+,d0 move.b #0,d2 loc_1ECC6: move.b (Secondary_Angle).w,d3 cmp.w d0,d1 ble.s loc_1ECD4 move.b (Primary_Angle).w,d3 exg d0,d1 loc_1ECD4: btst #0,d3 beq.s + move.b d2,d3 + rts ; =========================================================================== ; a bit of unused/dead code here ;CheckFloorDist: move.w y_pos(a0),d2 ; a0=character move.w x_pos(a0),d3 ; Checks a 16x16 block to find solid ground. May check an additional ; 16x16 block up for ceilings. ; d2 = y_pos ; d3 = x_pos ; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top) ; returns relevant block ID in (a1) ; returns distance in d1 ; returns angle in d3, or zero if angle was odd ;loc_1ECE6: CheckFloorDist_Part2: addi.w #$A,d2 lea (Primary_Angle).w,a4 movea.w #$10,a3 move.w #0,d6 bsr.w FindFloor move.b #0,d2 ; d2 what to use as angle if (Primary_Angle).w is odd ; returns angle in d3, or value in d2 if angle was odd loc_1ECFE: move.b (Primary_Angle).w,d3 btst #0,d3 beq.s + move.b d2,d3 + rts ; =========================================================================== ; Unused collision checking subroutine move.w x_pos(a0),d3 ; a0=character move.w y_pos(a0),d2 subq.w #4,d2 move.l #Primary_Collision,(Collision_addr).w cmpi.b #$D,lrb_solid_bit(a0) beq.s + move.l #Secondary_Collision,(Collision_addr).w + lea (Primary_Angle).w,a4 move.b #0,(a4) movea.w #$10,a3 move.w #0,d6 move.b lrb_solid_bit(a0),d5 bsr.w FindFloor move.b (Primary_Angle).w,d3 btst #0,d3 beq.s + move.b #0,d3 + rts ; =========================================================================== ; loc_1ED56: ChkFloorEdge: move.w x_pos(a0),d3 ; loc_1ED5A: ChkFloorEdge_Part2: move.w y_pos(a0),d2 moveq #0,d0 move.b y_radius(a0),d0 ext.w d0 add.w d0,d2 move.l #Primary_Collision,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s + move.l #Secondary_Collision,(Collision_addr).w + lea (Primary_Angle).w,a4 move.b #0,(a4) movea.w #$10,a3 move.w #0,d6 move.b top_solid_bit(a0),d5 bsr.w FindFloor move.b (Primary_Angle).w,d3 btst #0,d3 beq.s + move.b #0,d3 + rts ; =========================================================================== ; Identical to ChkFloorEdge except that this uses a1 instead of a0 ;loc_1EDA8: ChkFloorEdge2: move.w x_pos(a1),d3 move.w y_pos(a1),d2 moveq #0,d0 move.b y_radius(a1),d0 ext.w d0 add.w d0,d2 move.l #Primary_Collision,(Collision_addr).w cmpi.b #$C,top_solid_bit(a1) beq.s + move.l #Secondary_Collision,(Collision_addr).w + lea (Primary_Angle).w,a4 move.b #0,(a4) movea.w #$10,a3 move.w #0,d6 move.b top_solid_bit(a1),d5 bsr.w FindFloor move.b (Primary_Angle).w,d3 btst #0,d3 beq.s return_1EDF8 move.b #0,d3 return_1EDF8: rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine checking if an object should interact with the floor ; (objects such as a monitor Sonic bumps from underneath) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1EDFA: ObjHitFloor: ObjCheckFloorDist: move.w x_pos(a0),d3 move.w y_pos(a0),d2 move.b y_radius(a0),d0 ext.w d0 add.w d0,d2 lea (Primary_Angle).w,a4 move.b #0,(a4) movea.w #$10,a3 move.w #0,d6 moveq #$C,d5 bsr.w FindFloor move.b (Primary_Angle).w,d3 btst #0,d3 beq.s + move.b #0,d3 + rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Collision check used to let the HTZ boss fire attack to hit the ground ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1EE30: FireCheckFloorDist: move.w x_pos(a1),d3 move.w y_pos(a1),d2 move.b y_radius(a1),d0 ext.w d0 add.w d0,d2 lea (Primary_Angle).w,a4 move.b #0,(a4) movea.w #$10,a3 move.w #0,d6 moveq #$C,d5 bra.w FindFloor ; End of function FireCheckFloorDist ; --------------------------------------------------------------------------- ; Collision check used to let scattered rings bounce on the ground ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1EE56: RingCheckFloorDist: move.w x_pos(a0),d3 move.w y_pos(a0),d2 move.b y_radius(a0),d0 ext.w d0 add.w d0,d2 lea (Primary_Angle).w,a4 move.b #0,(a4) movea.w #$10,a3 move.w #0,d6 moveq #$C,d5 bra.w Ring_FindFloor ; End of function RingCheckFloorDist ; --------------------------------------------------------------------------- ; Stores a distance to the nearest wall above Sonic/Tails, ; where "above" = right, into d1 ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1EE7C: CheckRightCeilingDist: move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b x_radius(a0),d0 ext.w d0 sub.w d0,d2 move.b y_radius(a0),d0 ext.w d0 add.w d0,d3 lea (Primary_Angle).w,a4 movea.w #$10,a3 move.w #0,d6 bsr.w FindWall move.w d1,-(sp) move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b x_radius(a0),d0 ext.w d0 add.w d0,d2 move.b y_radius(a0),d0 ext.w d0 add.w d0,d3 lea (Secondary_Angle).w,a4 movea.w #$10,a3 move.w #0,d6 bsr.w FindWall move.w (sp)+,d0 move.b #-$40,d2 bra.w loc_1ECC6 ; End of function CheckRightCeilingDist ; --------------------------------------------------------------------------- ; Stores a distance to the nearest wall on the right of Sonic/Tails into d1 ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Checks a 16x16 block to find solid walls. May check an additional ; 16x16 block up for walls. ; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top) ; returns relevant block ID in (a1) ; returns distance in d1 ; returns angle in d3, or zero if angle was odd ; sub_1EEDC: CheckRightWallDist: move.w y_pos(a0),d2 move.w x_pos(a0),d3 ; loc_1EEE4: CheckRightWallDist_Part2: addi.w #$A,d3 lea (Primary_Angle).w,a4 movea.w #$10,a3 move.w #0,d6 bsr.w FindWall move.b #-$40,d2 bra.w loc_1ECFE ; End of function CheckRightWallDist ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1EF00: ObjCheckLeftWallDist: ObjCheckRightWallDist: add.w x_pos(a0),d3 move.w y_pos(a0),d2 lea (Primary_Angle).w,a4 move.b #0,(a4) movea.w #$10,a3 move.w #0,d6 moveq #$D,d5 bsr.w FindWall move.b (Primary_Angle).w,d3 btst #0,d3 beq.s + move.b #-$40,d3 + rts ; End of function ObjCheckRightWallDist ; --------------------------------------------------------------------------- ; Stores a distance from Sonic/Tails to the nearest ceiling into d1 ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1EF2E: Sonic_DontRunOnWalls: CheckCeilingDist: Sonic_CheckCeiling: move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b y_radius(a0),d0 ext.w d0 sub.w d0,d2 eori.w #$F,d2 ; flip position upside-down within the current 16x16 block? move.b x_radius(a0),d0 ext.w d0 add.w d0,d3 lea (Primary_Angle).w,a4 movea.w #-$10,a3 move.w #$800,d6 bsr.w FindFloor move.w d1,-(sp) move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b y_radius(a0),d0 ext.w d0 sub.w d0,d2 eori.w #$F,d2 move.b x_radius(a0),d0 ext.w d0 sub.w d0,d3 lea (Secondary_Angle).w,a4 movea.w #-$10,a3 move.w #$800,d6 bsr.w FindFloor move.w (sp)+,d0 move.b #$80,d2 bra.w loc_1ECC6 ; End of function Sonic_CheckCeiling ; =========================================================================== ; a bit of unused/dead code here ;CheckCeilingDist: move.w y_pos(a0),d2 ; a0=character move.w x_pos(a0),d3 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Checks a 16x16 block to find solid ceiling. May check an additional ; 16x16 block up for ceilings. ; d2 = y_pos ; d3 = x_pos ; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top) ; returns relevant block ID in (a1) ; returns distance in d1 ; returns angle in d3, or zero if angle was odd ; loc_1EF9E: CheckSlopeDist: CheckCeilingDist_Part2: subi.w #$A,d2 eori.w #$F,d2 lea (Primary_Angle).w,a4 movea.w #-$10,a3 move.w #$800,d6 bsr.w FindFloor move.b #$80,d2 bra.w loc_1ECFE ; End of function CheckCeilingDist ; --------------------------------------------------------------------------- ; Stores a distance to the nearest wall above the object into d1 ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1EFBE: ObjHitCeiling: ObjCheckCeilingDist: move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b y_radius(a0),d0 ext.w d0 sub.w d0,d2 eori.w #$F,d2 lea (Primary_Angle).w,a4 movea.w #-$10,a3 move.w #$800,d6 moveq #$D,d5 bsr.w FindFloor move.b (Primary_Angle).w,d3 btst #0,d3 beq.s + move.b #$80,d3 + rts ; End of function ObjCheckCeilingDist ; --------------------------------------------------------------------------- ; Stores a distance to the nearest wall above Sonic/Tails, ; where "above" = left, into d1 ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1EFF6: CheckLeftCeilingDist: move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b x_radius(a0),d0 ext.w d0 sub.w d0,d2 move.b y_radius(a0),d0 ext.w d0 sub.w d0,d3 eori.w #$F,d3 lea (Primary_Angle).w,a4 movea.w #-$10,a3 move.w #$400,d6 bsr.w FindWall move.w d1,-(sp) move.w y_pos(a0),d2 move.w x_pos(a0),d3 moveq #0,d0 move.b x_radius(a0),d0 ext.w d0 add.w d0,d2 move.b y_radius(a0),d0 ext.w d0 sub.w d0,d3 eori.w #$F,d3 lea (Secondary_Angle).w,a4 movea.w #-$10,a3 move.w #$400,d6 bsr.w FindWall move.w (sp)+,d0 move.b #$40,d2 bra.w loc_1ECC6 ; End of function CheckLeftCeilingDist ; --------------------------------------------------------------------------- ; Stores a distance to the nearest wall on the left of Sonic/Tails into d1 ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; Checks a 16x16 block to find solid walls. May check an additional ; 16x16 block up for walls. ; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top) ; returns relevant block ID in (a1) ; returns distance in d1 ; returns angle in d3, or zero if angle was odd ; loc_1F05E: Sonic_HitWall: CheckLeftWallDist: move.w y_pos(a0),d2 move.w x_pos(a0),d3 ; loc_1F066: CheckLeftWallDist_Part2: subi.w #$A,d3 eori.w #$F,d3 lea (Primary_Angle).w,a4 movea.w #-$10,a3 move.w #$400,d6 bsr.w FindWall move.b #$40,d2 bra.w loc_1ECFE ; End of function CheckLeftWallDist ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_1F086: ObjCheckRightWallDist: ObjCheckLeftWallDist: add.w x_pos(a0),d3 move.w y_pos(a0),d2 ; Engine bug: colliding with left walls is erratic with this function. ; The cause is this: a missing instruction to flip collision on the found ; 16x16 block; this one: ;eori.w #$F,d3 lea (Primary_Angle).w,a4 move.b #0,(a4) movea.w #-$10,a3 move.w #$400,d6 moveq #$D,d5 bsr.w FindWall move.b (Primary_Angle).w,d3 btst #0,d3 beq.s + move.b #$40,d3 + rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 79 - Star pole / starpost / checkpoint ; ---------------------------------------------------------------------------- ; Sprite_1F0B4: Obj79: moveq #0,d0 move.b routine(a0),d0 move.w Obj79_Index(pc,d0.w),d1 jmp Obj79_Index(pc,d1.w) ; =========================================================================== ; off_1F0C2: Obj79_States: Obj79_Index: offsetTable offsetTableEntry.w Obj79_Init ; 0 offsetTableEntry.w Obj79_Main ; 2 offsetTableEntry.w Obj79_Animate ; 4 offsetTableEntry.w Obj79_Dongle ; 6 offsetTableEntry.w Obj79_Star ; 8 ; =========================================================================== ; loc_1F0CC: Obj79_Init: addq.b #2,routine(a0) ; => Obj79_Main move.l #Obj79_MapUnc_1F424,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Checkpoint,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo3_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #8,width_pixels(a0) move.b #5,priority(a0) lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 bclr #7,2(a2,d0.w) btst #0,2(a2,d0.w) bne.s loc_1F120 move.b (Last_star_pole_hit).w,d1 andi.b #$7F,d1 move.b subtype(a0),d2 andi.b #$7F,d2 cmp.b d2,d1 blo.s Obj79_Main loc_1F120: bset #0,2(a2,d0.w) move.b #2,anim(a0) ; loc_1F12C: Obj79_Main: tst.w (Debug_placement_mode).w bne.w Obj79_Animate lea (MainCharacter).w,a3 ; a3=character move.b (Last_star_pole_hit).w,d1 bsr.s Obj79_CheckActivation tst.w (Two_player_mode).w beq.w Obj79_Animate lea (Sidekick).w,a3 ; a3=character move.b (Last_star_pole_hit_2P).w,d1 bsr.s Obj79_CheckActivation bra.w Obj79_Animate ; --------------------------------------------------------------------------- ; loc_1F154: Obj79_CheckActivation: andi.b #$7F,d1 move.b subtype(a0),d2 andi.b #$7F,d2 cmp.b d2,d1 bhs.w loc_1F222 move.w x_pos(a3),d0 sub.w x_pos(a0),d0 addi_.w #8,d0 cmpi.w #$10,d0 bhs.w return_1F220 move.w y_pos(a3),d0 sub.w y_pos(a0),d0 addi.w #$40,d0 cmpi.w #$68,d0 bhs.w return_1F220 move.w #SndID_Checkpoint,d0 ; checkpoint ding-dong sound jsr (PlaySound).l jsr (SingleObjLoad).l bne.s loc_1F206 _move.b #ObjID_Starpost,id(a1) ; load obj79 move.b #6,routine(a1) ; => Obj79_Dongle move.w x_pos(a0),objoff_30(a1) move.w y_pos(a0),objoff_32(a1) subi.w #$14,objoff_32(a1) move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) move.b #4,render_flags(a1) move.b #8,width_pixels(a1) move.b #4,priority(a1) move.b #2,mapping_frame(a1) move.w #$20,objoff_36(a1) move.w a0,parent(a1) tst.w (Two_player_mode).w bne.s loc_1F206 cmpi.b #7,(Emerald_count).w beq.s loc_1F206 cmpi.w #50,(Ring_count).w blo.s loc_1F206 bsr.w Obj79_MakeSpecialStars loc_1F206: move.b #1,anim(a0) bsr.w Obj79_SaveData lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 bset #0,2(a2,d0.w) return_1F220: rts ; =========================================================================== loc_1F222: tst.b anim(a0) bne.s return_1F22E move.b #2,anim(a0) return_1F22E: rts ; =========================================================================== ; loc_1F230: Obj79_Animate: lea (Ani_obj79).l,a1 jsrto (AnimateSprite).l, JmpTo2_AnimateSprite jmp (MarkObjGone).l ; =========================================================================== ; loc_1F240: Obj79_Dongle: subq.w #1,objoff_36(a0) bpl.s Obj79_MoveDonglyThing movea.w parent(a0),a1 ; a1=object cmpi.b #ObjID_Starpost,id(a1) bne.s + move.b #2,anim(a1) move.b #0,mapping_frame(a1) + jmp (DeleteObject).l ; =========================================================================== ; loc_1F262: Obj79_MoveDonglyThing: move.b angle(a0),d0 subi.b #$10,angle(a0) subi.b #$40,d0 jsr (CalcSine).l muls.w #$C00,d1 swap d1 add.w objoff_30(a0),d1 move.w d1,x_pos(a0) muls.w #$C00,d0 swap d0 add.w objoff_32(a0),d0 move.w d0,y_pos(a0) jmp (MarkObjGone).l ; =========================================================================== ; hit a starpost / save checkpoint ; loc_1F298: Obj79_SaveData: cmpa.w #MainCharacter,a3 ; is it player 1? bne.w Obj79_SaveDataPlayer2 ; if not, branch move.b subtype(a0),(Last_star_pole_hit).w move.b (Last_star_pole_hit).w,(Saved_Last_star_pole_hit).w move.w x_pos(a0),(Saved_x_pos).w move.w y_pos(a0),(Saved_y_pos).w move.w (MainCharacter+art_tile).w,(Saved_art_tile).w move.w (MainCharacter+top_solid_bit).w,(Saved_Solid_bits).w move.w (Ring_count).w,(Saved_Ring_count).w move.b (Extra_life_flags).w,(Saved_Extra_life_flags).w move.l (Timer).w,(Saved_Timer).w move.b (Dynamic_Resize_Routine).w,(Saved_Dynamic_Resize_Routine).w move.w (Camera_Max_Y_pos_now).w,(Saved_Camera_Max_Y_pos).w move.w (Camera_X_pos).w,(Saved_Camera_X_pos).w move.w (Camera_Y_pos).w,(Saved_Camera_Y_pos).w move.w (Camera_BG_X_pos).w,(Saved_Camera_BG_X_pos).w move.w (Camera_BG_Y_pos).w,(Saved_Camera_BG_Y_pos).w move.w (Camera_BG2_X_pos).w,(Saved_Camera_BG2_X_pos).w move.w (Camera_BG2_Y_pos).w,(Saved_Camera_BG2_Y_pos).w move.w (Camera_BG3_X_pos).w,(Saved_Camera_BG3_X_pos).w move.w (Camera_BG3_Y_pos).w,(Saved_Camera_BG3_Y_pos).w move.w (Water_Level_2).w,(Saved_Water_Level).w move.b (Water_routine).w,(Saved_Water_routine).w move.b (Water_fullscreen_flag).w,(Saved_Water_move).w rts ; =========================================================================== ; second player hit a checkpoint in 2-player mode ; loc_1F326: Obj79_SaveDataPlayer2: move.b subtype(a0),(Last_star_pole_hit_2P).w move.b (Last_star_pole_hit_2P).w,(Saved_Last_star_pole_hit_2P).w move.w x_pos(a0),(Saved_x_pos_2P).w move.w y_pos(a0),(Saved_y_pos_2P).w move.w (Sidekick+art_tile).w,(Saved_art_tile_2P).w move.w (Sidekick+top_solid_bit).w,(Saved_Solid_bits_2P).w move.w (Ring_count_2P).w,(Saved_Ring_count_2P).w move.b (Extra_life_flags_2P).w,(Saved_Extra_life_flags_2P).w move.l (Timer_2P).w,(Saved_Timer_2P).w rts ; =========================================================================== ; continue from a starpost / load checkpoint ; loc_1F35E: Obj79_LoadData: move.b (Saved_Last_star_pole_hit).w,(Last_star_pole_hit).w move.w (Saved_x_pos).w,(MainCharacter+x_pos).w move.w (Saved_y_pos).w,(MainCharacter+y_pos).w move.w (Saved_Ring_count).w,(Ring_count).w move.b (Saved_Extra_life_flags).w,(Extra_life_flags).w clr.w (Ring_count).w clr.b (Extra_life_flags).w move.l (Saved_Timer).w,(Timer).w move.b #59,(Timer_frame).w subq.b #1,(Timer_second).w move.w (Saved_art_tile).w,(MainCharacter+art_tile).w move.w (Saved_Solid_bits).w,(MainCharacter+top_solid_bit).w move.b (Saved_Dynamic_Resize_Routine).w,(Dynamic_Resize_Routine).w move.b (Saved_Water_routine).w,(Water_routine).w move.w (Saved_Camera_Max_Y_pos).w,(Camera_Max_Y_pos_now).w move.w (Saved_Camera_Max_Y_pos).w,(Camera_Max_Y_pos).w move.w (Saved_Camera_X_pos).w,(Camera_X_pos).w move.w (Saved_Camera_Y_pos).w,(Camera_Y_pos).w move.w (Saved_Camera_BG_X_pos).w,(Camera_BG_X_pos).w move.w (Saved_Camera_BG_Y_pos).w,(Camera_BG_Y_pos).w move.w (Saved_Camera_BG2_X_pos).w,(Camera_BG2_X_pos).w move.w (Saved_Camera_BG2_Y_pos).w,(Camera_BG2_Y_pos).w move.w (Saved_Camera_BG3_X_pos).w,(Camera_BG3_X_pos).w move.w (Saved_Camera_BG3_Y_pos).w,(Camera_BG3_Y_pos).w tst.b (Water_flag).w ; does the level have water? beq.s + ; if not, branch to skip loading water stuff move.w (Saved_Water_Level).w,(Water_Level_2).w move.b (Saved_Water_routine).w,(Water_routine).w move.b (Saved_Water_move).w,(Water_fullscreen_flag).w + tst.b (Last_star_pole_hit).w bpl.s return_1F412 move.w (Saved_x_pos).w,d0 subi.w #$A0,d0 move.w d0,(Camera_Min_X_pos).w return_1F412: rts ; =========================================================================== ; animation script ; off_1F414: Ani_obj79: offsetTable offsetTableEntry.w byte_1F41A ; 0 offsetTableEntry.w byte_1F41D ; 1 offsetTableEntry.w byte_1F420 ; 2 byte_1F41A: dc.b $F, 0,$FF rev02even byte_1F41D: dc.b $F, 1,$FF rev02even byte_1F420: dc.b 3, 0, 4,$FF even ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj79_MapUnc_1F424: BINCLUDE "mappings/sprite/obj79_a.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj79_MapUnc_1F4A0: BINCLUDE "mappings/sprite/obj79_b.bin" ; =========================================================================== ; loc_1F4C4: Obj79_MakeSpecialStars: moveq #4-1,d1 ; execute the loop 4 times (1 for each star) moveq #0,d2 - bsr.w SingleObjLoad2 bne.s + ; rts _move.b id(a0),id(a1) ; load obj79 move.l #Obj79_MapUnc_1F4A0,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_Checkpoint,0,0),art_tile(a1) move.b #4,render_flags(a1) move.b #8,routine(a1) ; => Obj79_Star move.w x_pos(a0),d0 move.w d0,x_pos(a1) move.w d0,objoff_30(a1) move.w y_pos(a0),d0 subi.w #$30,d0 move.w d0,y_pos(a1) move.w d0,objoff_32(a1) move.b priority(a0),priority(a1) move.b #8,width_pixels(a1) move.b #1,mapping_frame(a1) move.w #-$400,x_vel(a1) move.w #0,y_vel(a1) move.w d2,objoff_34(a1) ; set the angle addi.w #$40,d2 ; increase the angle for next time dbf d1,- ; loop + rts ; =========================================================================== ; loc_1F536: Obj79_Star: move.b collision_property(a0),d0 beq.w loc_1F554 andi.b #1,d0 beq.s + move.b #1,(SpecialStage_flag_2P).w move.b #GameModeID_SpecialStage,(Game_Mode).w ; => SpecialStage + clr.b collision_property(a0) loc_1F554: addi.w #$A,objoff_34(a0) move.w objoff_34(a0),d0 andi.w #$FF,d0 jsr (CalcSine).l asr.w #5,d0 asr.w #3,d1 move.w d1,d3 move.w objoff_34(a0),d2 andi.w #$3E0,d2 lsr.w #5,d2 moveq #2,d5 moveq #0,d4 cmpi.w #$10,d2 ble.s + neg.w d1 + andi.w #$F,d2 cmpi.w #8,d2 ble.s loc_1F594 neg.w d2 andi.w #7,d2 loc_1F594: lsr.w #1,d2 beq.s + add.w d1,d4 + asl.w #1,d1 dbf d5,loc_1F594 asr.w #4,d4 add.w d4,d0 addq.w #1,objoff_36(a0) move.w objoff_36(a0),d1 cmpi.w #$80,d1 beq.s loc_1F5BE bgt.s loc_1F5C4 loc_1F5B4: muls.w d1,d0 muls.w d1,d3 asr.w #7,d0 asr.w #7,d3 bra.s loc_1F5D6 ; =========================================================================== loc_1F5BE: move.b #$D8,collision_flags(a0) loc_1F5C4: cmpi.w #$180,d1 ble.s loc_1F5D6 neg.w d1 addi.w #$200,d1 bmi.w JmpTo10_DeleteObject bra.s loc_1F5B4 ; =========================================================================== loc_1F5D6: move.w objoff_30(a0),d2 add.w d3,d2 move.w d2,x_pos(a0) move.w objoff_32(a0),d2 add.w d0,d2 move.w d2,y_pos(a0) addq.b #1,anim_frame(a0) move.b anim_frame(a0),d0 andi.w #6,d0 lsr.w #1,d0 cmpi.b #3,d0 bne.s + moveq #1,d0 + move.b d0,mapping_frame(a0) jmpto (MarkObjGone).l, JmpTo_MarkObjGone ; =========================================================================== JmpTo10_DeleteObject jmp (DeleteObject).l ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo_MarkObjGone jmp (MarkObjGone).l JmpTo2_AnimateSprite jmp (AnimateSprite).l JmpTo3_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 7D - Points that can be gotten at the end of an act (leftover from S1) (unused) ; ---------------------------------------------------------------------------- ; Sprite_1F624: Obj7D: moveq #0,d0 move.b routine(a0),d0 move.w Obj7D_Index(pc,d0.w),d1 jmp Obj7D_Index(pc,d1.w) ; =========================================================================== ; off_1F632: Obj7D_States: Obj7D_Index: offsetTable offsetTableEntry.w Obj7D_Init ; 0 offsetTableEntry.w Obj7D_Main ; 2 ; =========================================================================== ; loc_1F636: Obj7D_Init: moveq #$10,d2 move.w d2,d3 add.w d3,d3 lea (MainCharacter).w,a1 ; a1=character move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d2,d0 cmp.w d3,d0 bhs.s Obj7D_NoAdd move.w y_pos(a1),d1 sub.w y_pos(a0),d1 add.w d2,d1 cmp.w d3,d1 bhs.s Obj7D_NoAdd tst.w (Debug_placement_mode).w bne.s Obj7D_NoAdd tst.b (SpecialStage_flag_2P).w bne.s Obj7D_NoAdd addq.b #2,routine(a0) move.l #Obj7D_MapUnc_1F6FE,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_EndPoints,0,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo4_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #0,priority(a0) move.b #$10,width_pixels(a0) move.b subtype(a0),mapping_frame(a0) move.w #$77,objoff_30(a0) move.w #SndID_Bonus,d0 jsr (PlaySound).l moveq #0,d0 move.b subtype(a0),d0 add.w d0,d0 move.w word_1F6D2(pc,d0.w),d0 jsr (AddPoints).l Obj7D_NoAdd: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.s JmpTo11_DeleteObject rts ; =========================================================================== JmpTo11_DeleteObject jmp (DeleteObject).l ; =========================================================================== word_1F6D2: dc.w 0 dc.w 1000 ; 1 dc.w 100 ; 2 dc.w 1 ; 3 ; =========================================================================== ; loc_1F6DA: Obj7D_Main: subq.w #1,objoff_30(a0) bmi.s JmpTo12_DeleteObject move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.s JmpTo12_DeleteObject jmp (DisplaySprite).l ; =========================================================================== JmpTo12_DeleteObject jmp (DeleteObject).l ; =========================================================================== ; ------------------------------------------------------------------------------- ; Unused sprite mappings ; ------------------------------------------------------------------------------- Obj7D_MapUnc_1F6FE: BINCLUDE "mappings/sprite/obj7D.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo4_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 44 - Round bumper from Casino Night Zone ; ---------------------------------------------------------------------------- ; Sprite_1F730: Obj44: moveq #0,d0 move.b routine(a0),d0 move.w Obj44_Index(pc,d0.w),d1 jmp Obj44_Index(pc,d1.w) ; =========================================================================== ; off_1F73E: Obj44_States: Obj44_Index: offsetTable offsetTableEntry.w Obj44_Init ; 0 offsetTableEntry.w Obj44_Main ; 2 ; =========================================================================== ; loc_1F742: Obj44_Init: addq.b #2,routine(a0) ; => Obj44_Main move.l #Obj44_MapUnc_1F85A,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CNZRoundBumper,2,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo5_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #1,priority(a0) move.b #$D7,collision_flags(a0) ; loc_1F770: Obj44_Main: move.b collision_property(a0),d0 beq.w loc_1F83E lea (MainCharacter).w,a1 ; a1=character bclr #0,collision_property(a0) beq.s + bsr.s Obj44_BumpCharacter + lea (Sidekick).w,a1 ; a1=character bclr #1,collision_property(a0) beq.s + bsr.s Obj44_BumpCharacter + clr.b collision_property(a0) bra.w loc_1F83E ; =========================================================================== ; loc_1F79C: Obj44_BumpCharacter: move.w x_pos(a0),d1 move.w y_pos(a0),d2 sub.w x_pos(a1),d1 sub.w y_pos(a1),d2 jsr (CalcAngle).l move.b (Timer_frames).w,d1 andi.w #3,d1 add.w d1,d0 jsr (CalcSine).l muls.w #-$700,d1 asr.l #8,d1 move.w d1,x_vel(a1) muls.w #-$700,d0 asr.l #8,d0 move.w d0,y_vel(a1) bset #1,status(a1) bclr #4,status(a1) bclr #5,status(a1) clr.b jumping(a1) move.b #1,anim(a0) move.w #SndID_Bumper,d0 jsr (PlaySound).l lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s + cmpi.b #$8A,2(a2,d0.w) bhs.s return_1F83C addq.b #1,2(a2,d0.w) + moveq #1,d0 movea.w a1,a3 jsr (AddPoints2).l bsr.w SingleObjLoad bne.s return_1F83C _move.b #ObjID_Points,id(a1) ; load obj29 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b #4,mapping_frame(a1) return_1F83C: rts ; =========================================================================== loc_1F83E: lea (Ani_obj44).l,a1 jsrto (AnimateSprite).l, JmpTo3_AnimateSprite jmpto (MarkObjGone).l, JmpTo2_MarkObjGone ; =========================================================================== ; animation script ; off_1F84C: Ani_obj44: offsetTable offsetTableEntry.w byte_1F850 ; 0 offsetTableEntry.w byte_1F853 ; 1 byte_1F850: dc.b $F, 0,$FF rev02even byte_1F853: dc.b 3, 1, 0, 1,$FD, 0 even ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj44_MapUnc_1F85A: BINCLUDE "mappings/sprite/obj44.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo2_MarkObjGone jmp (MarkObjGone).l JmpTo3_AnimateSprite jmp (AnimateSprite).l JmpTo5_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 24 - Bubbles in Aquatic Ruin Zone ; ---------------------------------------------------------------------------- ; Sprite_1F8A8: Obj24: moveq #0,d0 move.b routine(a0),d0 move.w Obj24_Index(pc,d0.w),d1 jmp Obj24_Index(pc,d1.w) ; =========================================================================== ; off_1F8B6: Obj24_Index: offsetTable offsetTableEntry.w Obj24_Init ; 0 offsetTableEntry.w loc_1F924 ; 2 offsetTableEntry.w loc_1F93E ; 4 offsetTableEntry.w loc_1F99E ; 6 offsetTableEntry.w BranchTo_JmpTo15_DeleteObject ; 8 offsetTableEntry.w loc_1F9C0 ; $A ; =========================================================================== ; loc_1F8C2: Obj24_Init: addq.b #2,routine(a0) move.l #Obj24_MapUnc_1FBF6,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_BigBubbles,0,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo6_Adjust2PArtPointer move.b #$84,render_flags(a0) move.b #$10,width_pixels(a0) move.b #1,priority(a0) move.b subtype(a0),d0 bpl.s loc_1F90A addq.b #8,routine(a0) andi.w #$7F,d0 move.b d0,objoff_32(a0) move.b d0,objoff_33(a0) move.b #6,anim(a0) bra.w loc_1F9C0 ; =========================================================================== loc_1F90A: move.b d0,anim(a0) move.w x_pos(a0),objoff_30(a0) move.w #-$88,y_vel(a0) jsr (RandomNumber).l move.b d0,angle(a0) loc_1F924: lea (Ani_obj24).l,a1 jsr (AnimateSprite).l cmpi.b #6,mapping_frame(a0) bne.s loc_1F93E move.b #1,objoff_2E(a0) loc_1F93E: move.w (Water_Level_1).w,d0 cmp.w y_pos(a0),d0 blo.s loc_1F956 move.b #6,routine(a0) addq.b #3,anim(a0) bra.w loc_1F99E ; =========================================================================== loc_1F956: move.b angle(a0),d0 addq.b #1,angle(a0) andi.w #$7F,d0 lea (Obj0A_WobbleData).l,a1 move.b (a1,d0.w),d0 ext.w d0 add.w objoff_30(a0),d0 move.w d0,x_pos(a0) tst.b objoff_2E(a0) beq.s loc_1F988 bsr.w loc_1FB02 cmpi.b #6,routine(a0) beq.s loc_1F99E loc_1F988: jsrto (ObjectMove).l, JmpTo3_ObjectMove tst.b render_flags(a0) bpl.s JmpTo13_DeleteObject jmp (DisplaySprite).l ; =========================================================================== JmpTo13_DeleteObject jmp (DeleteObject).l ; =========================================================================== loc_1F99E: lea (Ani_obj24).l,a1 jsr (AnimateSprite).l tst.b render_flags(a0) bpl.s JmpTo14_DeleteObject jmp (DisplaySprite).l ; =========================================================================== JmpTo14_DeleteObject jmp (DeleteObject).l ; =========================================================================== if removeJmpTos JmpTo15_DeleteObject endif BranchTo_JmpTo15_DeleteObject jmpto (DeleteObject).l, JmpTo15_DeleteObject ; =========================================================================== loc_1F9C0: tst.w objoff_36(a0) bne.s loc_1FA22 move.w (Water_Level_1).w,d0 cmp.w y_pos(a0),d0 bhs.w loc_1FACE tst.b render_flags(a0) bpl.w loc_1FACE subq.w #1,objoff_38(a0) bpl.w loc_1FAC2 move.w #1,objoff_36(a0) loc_1F9E8: jsr (RandomNumber).l move.w d0,d1 andi.w #7,d0 cmpi.w #6,d0 bhs.s loc_1F9E8 move.b d0,objoff_34(a0) andi.w #$C,d1 lea (byte_1FAF0).l,a1 adda.w d1,a1 move.l a1,objoff_3C(a0) subq.b #1,objoff_32(a0) bpl.s BranchTo_loc_1FA2A move.b objoff_33(a0),objoff_32(a0) bset #7,objoff_36(a0) BranchTo_loc_1FA2A bra.s loc_1FA2A ; =========================================================================== loc_1FA22: subq.w #1,objoff_38(a0) bpl.w loc_1FAC2 loc_1FA2A: jsr (RandomNumber).l andi.w #$1F,d0 move.w d0,objoff_38(a0) bsr.w SingleObjLoad bne.s loc_1FAA6 _move.b id(a0),id(a1) ; load obj24 move.w x_pos(a0),x_pos(a1) jsr (RandomNumber).l andi.w #$F,d0 subq.w #8,d0 add.w d0,x_pos(a1) move.w y_pos(a0),y_pos(a1) moveq #0,d0 move.b objoff_34(a0),d0 movea.l objoff_3C(a0),a2 ; a2=object move.b (a2,d0.w),subtype(a1) btst #7,objoff_36(a0) beq.s loc_1FAA6 jsr (RandomNumber).l andi.w #3,d0 bne.s loc_1FA92 bset #6,objoff_36(a0) bne.s loc_1FAA6 move.b #2,subtype(a1) loc_1FA92: tst.b objoff_34(a0) bne.s loc_1FAA6 bset #6,objoff_36(a0) bne.s loc_1FAA6 move.b #2,subtype(a1) loc_1FAA6: subq.b #1,objoff_34(a0) bpl.s loc_1FAC2 jsr (RandomNumber).l andi.w #$7F,d0 addi.w #$80,d0 add.w d0,objoff_38(a0) clr.w objoff_36(a0) loc_1FAC2: lea (Ani_obj24).l,a1 jsr (AnimateSprite).l loc_1FACE: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w JmpTo15_DeleteObject move.w (Water_Level_1).w,d0 cmp.w y_pos(a0),d0 blo.w JmpTo7_DisplaySprite rts if removeJmpTos JmpTo7_DisplaySprite jmp (DisplaySprite).l endif ; =========================================================================== byte_1FAF0: dc.b 0 dc.b 1 ; 1 dc.b 0 ; 2 dc.b 0 ; 3 dc.b 0 ; 4 dc.b 0 ; 5 dc.b 1 ; 6 dc.b 0 ; 7 dc.b 0 ; 8 dc.b 0 ; 9 dc.b 0 ; 10 dc.b 1 ; 11 dc.b 0 ; 12 dc.b 1 ; 13 dc.b 0 ; 14 dc.b 0 ; 15 dc.b 1 ; 16 dc.b 0 ; 17 ; =========================================================================== loc_1FB02: lea (MainCharacter).w,a1 ; a1=character bsr.s loc_1FB0C lea (Sidekick).w,a1 ; a1=character loc_1FB0C: tst.b obj_control(a1) bmi.w return_1FBCA move.w x_pos(a1),d0 move.w x_pos(a0),d1 subi.w #$10,d1 cmp.w d0,d1 bhs.w return_1FBCA addi.w #$20,d1 cmp.w d0,d1 blo.w return_1FBCA move.w y_pos(a1),d0 move.w y_pos(a0),d1 cmp.w d0,d1 bhs.w return_1FBCA addi.w #$10,d1 cmp.w d0,d1 blo.w return_1FBCA bsr.w ResumeMusic move.w #SndID_InhalingBubble,d0 jsr (PlaySound).l clr.w x_vel(a1) clr.w y_vel(a1) clr.w inertia(a1) move.b #AniIDSonAni_Bubble,anim(a1) move.w #$23,move_lock(a1) move.b #0,jumping(a1) bclr #5,status(a1) bclr #4,status(a1) btst #2,status(a1) beq.w loc_1FBB8 cmpi.b #1,(a1) bne.s loc_1FBA8 bclr #2,status(a1) move.b #$13,y_radius(a1) move.b #9,x_radius(a1) subq.w #5,y_pos(a1) bra.s loc_1FBB8 ; =========================================================================== loc_1FBA8: move.b #$F,y_radius(a1) move.b #9,x_radius(a1) subq.w #1,y_pos(a1) loc_1FBB8: cmpi.b #6,routine(a0) beq.s return_1FBCA move.b #6,routine(a0) addq.b #3,anim(a0) return_1FBCA: rts ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite animations ; ------------------------------------------------------------------------------- ; animation script ; off_1FBCC: Ani_obj24: offsetTable offsetTableEntry.w byte_1FBDA ; 0 offsetTableEntry.w byte_1FBDF ; 1 offsetTableEntry.w byte_1FBE5 ; 2 offsetTableEntry.w byte_1FBEC ; 3 offsetTableEntry.w byte_1FBEC ; 4 offsetTableEntry.w byte_1FBEE ; 5 offsetTableEntry.w byte_1FBF2 ; 6 byte_1FBDA: dc.b $E, 0, 1, 2,$FC rev02even byte_1FBDF: dc.b $E, 1, 2, 3, 4,$FC rev02even byte_1FBE5: dc.b $E, 2, 3, 4, 5, 6,$FC rev02even byte_1FBEC: dc.b 4,$FC rev02even byte_1FBEE: dc.b 4, 6, 7,$FC rev02even byte_1FBF2: dc.b $F, $E, $F,$FF even ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj24_MapUnc_1FBF6: offsetTable offsetTableEntry.w word_1FC3A ; 0 offsetTableEntry.w word_1FC44 ; 1 offsetTableEntry.w word_1FC44 ; 2 offsetTableEntry.w word_1FC4E ; 3 offsetTableEntry.w word_1FC58 ; 4 offsetTableEntry.w word_1FC62 ; 5 offsetTableEntry.w word_1FC6C ; 6 offsetTableEntry.w word_1FC76 ; 7 offsetTableEntry.w word_1FC98 ; 8 offsetTableEntry.w word_1FC98 ; 9 offsetTableEntry.w word_1FC98 ; $A offsetTableEntry.w word_1FC98 ; $B offsetTableEntry.w word_1FC98 ; $C offsetTableEntry.w word_1FC98 ; $D offsetTableEntry.w word_1FCA2 ; $E offsetTableEntry.w word_1FCAC ; $F offsetTableEntry.w word_1FCB6 ; $10 ; ------------------------------------------------------------------------------- ; sprite mappings ; merged with the above mappings, can't split to file in a useful way... ; ------------------------------------------------------------------------------- Obj24_MapUnc_1FC18: offsetTable offsetTableEntry.w word_1FC3A ; 0 offsetTableEntry.w word_1FC44 ; 1 offsetTableEntry.w word_1FC44 ; 2 offsetTableEntry.w word_1FC4E ; 3 offsetTableEntry.w word_1FC58 ; 4 offsetTableEntry.w word_1FC62 ; 5 offsetTableEntry.w word_1FC6C ; 6 offsetTableEntry.w word_1FC76 ; 7 offsetTableEntry.w word_1FCB8 ; 8 offsetTableEntry.w word_1FCB8 ; 9 offsetTableEntry.w word_1FCB8 ; $A offsetTableEntry.w word_1FCB8 ; $B offsetTableEntry.w word_1FCB8 ; $C offsetTableEntry.w word_1FCB8 ; $D offsetTableEntry.w word_1FCA2 ; $E offsetTableEntry.w word_1FCAC ; $F offsetTableEntry.w word_1FCB6 ; $10 word_1FC3A: dc.w 1 dc.w $FC00, $008D, $0046, $FFFC word_1FC44: dc.w 1 dc.w $FC00, $008E, $0047, $FFFC word_1FC4E: dc.w 1 dc.w $F805, $008F, $0047, $FFF8 word_1FC58: dc.w 1 dc.w $F805, $0093, $0049, $FFF8 word_1FC62: dc.w 1 dc.w $F40A, $001C, $000E, $FFF4 word_1FC6C: dc.w 1 dc.w $F00F, $0008, $0004, $FFF0 word_1FC76: dc.w 4 dc.w $F005, $0018, $000C, $FFF0 dc.w $F005, $0818, $080C, $0000 dc.w $0005, $1018, $100C, $FFF0 dc.w $0005, $1818, $180C, $0000 word_1FC98: dc.w 1 dc.w $F406, $1F41, $1BA0, $FFF8 word_1FCA2: dc.w 1 dc.w $F805, $0000, $0000, $FFF8 word_1FCAC: dc.w 1 dc.w $F805, $0004, $0002, $FFF8 word_1FCB6: dc.w 0 word_1FCB8: dc.w 1 dc.w $F406, $1F31, $1B98, $FFF8 ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo7_DisplaySprite jmp (DisplaySprite).l JmpTo15_DeleteObject jmp (DeleteObject).l JmpTo6_Adjust2PArtPointer jmp (Adjust2PArtPointer).l ; loc_1FCD6: JmpTo3_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 03 - Collision plane/layer switcher ; ---------------------------------------------------------------------------- ; Sprite_1FCDC: Obj03: moveq #0,d0 move.b routine(a0),d0 move.w Obj03_Index(pc,d0.w),d1 jsr Obj03_Index(pc,d1.w) jmp (MarkObjGone3).l ; =========================================================================== ; off_1FCF0: Obj03_Index: offsetTable offsetTableEntry.w Obj03_Init ; 0 offsetTableEntry.w Obj03_MainX ; 2 offsetTableEntry.w Obj03_MainY ; 4 ; =========================================================================== ; loc_1FCF6: Obj03_Init: addq.b #2,routine(a0) ; => Obj03_MainX move.l #Obj03_MapUnc_1FFB8,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Ring,1,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo7_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #5,priority(a0) move.b subtype(a0),d0 btst #2,d0 beq.s Obj03_Init_CheckX ;Obj03_Init_CheckY: addq.b #2,routine(a0) ; => Obj03_MainY andi.w #7,d0 move.b d0,mapping_frame(a0) andi.w #3,d0 add.w d0,d0 move.w word_1FD68(pc,d0.w),objoff_32(a0) move.w y_pos(a0),d1 lea (MainCharacter).w,a1 ; a1=character cmp.w y_pos(a1),d1 bhs.s + move.b #1,objoff_34(a0) + lea (Sidekick).w,a1 ; a1=character cmp.w y_pos(a1),d1 bhs.s + move.b #1,objoff_35(a0) + bra.w Obj03_MainY ; =========================================================================== word_1FD68: dc.w $20 dc.w $40 ; 1 dc.w $80 ; 2 dc.w $100 ; 3 ; =========================================================================== ; loc_1FD70: Obj03_Init_CheckX: andi.w #3,d0 move.b d0,mapping_frame(a0) add.w d0,d0 move.w word_1FD68(pc,d0.w),objoff_32(a0) move.w x_pos(a0),d1 lea (MainCharacter).w,a1 ; a1=character cmp.w x_pos(a1),d1 bhs.s + move.b #1,objoff_34(a0) + lea (Sidekick).w,a1 ; a1=character cmp.w x_pos(a1),d1 bhs.s + move.b #1,objoff_35(a0) + ; loc_1FDA4: Obj03_MainX: tst.w (Debug_placement_mode).w bne.w return_1FEAC move.w x_pos(a0),d1 lea objoff_34(a0),a2 lea (MainCharacter).w,a1 ; a1=character bsr.s + lea (Sidekick).w,a1 ; a1=character + tst.b (a2)+ bne.s Obj03_MainX_Alt cmp.w x_pos(a1),d1 bhi.w return_1FEAC move.b #1,-1(a2) move.w y_pos(a0),d2 move.w d2,d3 move.w objoff_32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w y_pos(a1),d4 cmp.w d2,d4 blt.w return_1FEAC cmp.w d3,d4 bge.w return_1FEAC move.b subtype(a0),d0 bpl.s + btst #1,status(a1) bne.w return_1FEAC + btst #0,render_flags(a0) bne.s + move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) btst #3,d0 beq.s + move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) + andi.w #drawing_mask,art_tile(a1) btst #5,d0 beq.s return_1FEAC ori.w #high_priority,art_tile(a1) bra.s return_1FEAC ; =========================================================================== ; loc_1FE38: Obj03_MainX_Alt: cmp.w x_pos(a1),d1 bls.w return_1FEAC move.b #0,-1(a2) move.w y_pos(a0),d2 move.w d2,d3 move.w objoff_32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w y_pos(a1),d4 cmp.w d2,d4 blt.w return_1FEAC cmp.w d3,d4 bge.w return_1FEAC move.b subtype(a0),d0 bpl.s + btst #1,status(a1) bne.w return_1FEAC + btst #0,render_flags(a0) bne.s + move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) btst #4,d0 beq.s + move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) + andi.w #drawing_mask,art_tile(a1) btst #6,d0 beq.s return_1FEAC ori.w #high_priority,art_tile(a1) return_1FEAC: rts ; =========================================================================== Obj03_MainY: tst.w (Debug_placement_mode).w bne.w return_1FFB6 move.w y_pos(a0),d1 lea objoff_34(a0),a2 lea (MainCharacter).w,a1 ; a1=character bsr.s + lea (Sidekick).w,a1 ; a1=character + tst.b (a2)+ bne.s Obj03_MainY_Alt cmp.w y_pos(a1),d1 bhi.w return_1FFB6 move.b #1,-1(a2) move.w x_pos(a0),d2 move.w d2,d3 move.w objoff_32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w x_pos(a1),d4 cmp.w d2,d4 blt.w return_1FFB6 cmp.w d3,d4 bge.w return_1FFB6 move.b subtype(a0),d0 bpl.s + btst #1,status(a1) bne.w return_1FFB6 + btst #0,render_flags(a0) bne.s + move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) btst #3,d0 beq.s + move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) + andi.w #drawing_mask,art_tile(a1) btst #5,d0 beq.s return_1FFB6 ori.w #high_priority,art_tile(a1) bra.s return_1FFB6 ; =========================================================================== ; loc_1FF42: Obj03_MainY_Alt: cmp.w y_pos(a1),d1 bls.w return_1FFB6 move.b #0,-1(a2) move.w x_pos(a0),d2 move.w d2,d3 move.w objoff_32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w x_pos(a1),d4 cmp.w d2,d4 blt.w return_1FFB6 cmp.w d3,d4 bge.w return_1FFB6 move.b subtype(a0),d0 bpl.s + btst #1,status(a1) bne.w return_1FFB6 + btst #0,render_flags(a0) bne.s + move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) btst #4,d0 beq.s + move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) + andi.w #drawing_mask,art_tile(a1) btst #6,d0 beq.s return_1FFB6 ori.w #high_priority,art_tile(a1) return_1FFB6: rts ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj03_MapUnc_1FFB8: BINCLUDE "mappings/sprite/obj03.bin" ; =========================================================================== if ~~removeJmpTos JmpTo7_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 0B - Section of pipe that tips you off from CPZ ; ---------------------------------------------------------------------------- ; Sprite_2009C: Obj0B: moveq #0,d0 move.b routine(a0),d0 move.w Obj0B_Index(pc,d0.w),d1 jmp Obj0B_Index(pc,d1.w) ; =========================================================================== ; off_200AA: Obj0B_Index: offsetTable offsetTableEntry.w Obj0B_Init ; 0 offsetTableEntry.w loc_20104 ; 2 offsetTableEntry.w loc_20112 ; 4 ; =========================================================================== obj0B_duration_current = objoff_30 obj0B_duration_initial = objoff_32 obj0B_delay = objoff_36 ; loc_200B0: Obj0B_Init: addq.b #2,routine(a0) move.l #Obj0B_MapUnc_201A0,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CPZAnimatedBits,3,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo8_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #4,priority(a0) moveq #0,d0 move.b subtype(a0),d0 andi.w #$F0,d0 addi.w #$10,d0 move.w d0,d1 subq.w #1,d0 move.w d0,obj0B_duration_current(a0) move.w d0,obj0B_duration_initial(a0) moveq #0,d0 move.b subtype(a0),d0 andi.w #$F,d0 addq.w #1,d0 lsl.w #4,d0 move.b d0,obj0B_delay(a0) loc_20104: move.b (Vint_runcount+3).w,d0 add.b obj0B_delay(a0),d0 bne.s loc_2013C addq.b #2,routine(a0) loc_20112: subq.w #1,obj0B_duration_current(a0) bpl.s loc_20130 move.w #$7F,obj0B_duration_current(a0) tst.b anim(a0) beq.s + move.w obj0B_duration_initial(a0),obj0B_duration_current(a0) + bchg #0,anim(a0) loc_20130: lea (Ani_obj0B).l,a1 jsr (AnimateSprite).l loc_2013C: tst.b mapping_frame(a0) bne.s + moveq #0,d1 move.b width_pixels(a0),d1 moveq #$11,d3 move.w x_pos(a0),d4 bsr.w PlatformObject jmpto (MarkObjGone).l, JmpTo3_MarkObjGone ; --------------------------------------------------------------------------- + move.b status(a0),d0 andi.b #standing_mask,d0 beq.s BranchTo_JmpTo3_MarkObjGone bclr #p1_standing_bit,status(a0) beq.s + bclr #3,(MainCharacter+status).w bset #1,(MainCharacter+status).w + bclr #p2_standing_bit,status(a0) beq.s BranchTo_JmpTo3_MarkObjGone bclr #3,(Sidekick+status).w bset #1,(Sidekick+status).w BranchTo_JmpTo3_MarkObjGone jmpto (MarkObjGone).l, JmpTo3_MarkObjGone ; =========================================================================== ; animation script ; off_2018C: Ani_obj0B: offsetTable offsetTableEntry.w byte_20190 ; 0 offsetTableEntry.w byte_20198 ; 1 byte_20190: dc.b 7, 0, 1, 2, 3, 4,$FE, 1 byte_20198: dc.b 7, 4, 3, 2, 1, 0,$FE, 1 even ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj0B_MapUnc_201A0: BINCLUDE "mappings/sprite/obj0B.bin" ; =========================================================================== if ~~removeJmpTos JmpTo3_MarkObjGone jmp (MarkObjGone).l JmpTo8_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 0C - Small floating platform (unused) ; (used in CPZ in the Nick Arcade prototype) ; ---------------------------------------------------------------------------- ; Sprite_20210: Obj0C: moveq #0,d0 move.b routine(a0),d0 move.w Obj0C_Index(pc,d0.w),d1 jmp Obj0C_Index(pc,d1.w) ; =========================================================================== ; off_2021E Obj0C_Index: offsetTable offsetTableEntry.w Obj0C_Init ; 0 offsetTableEntry.w Obj0C_Main ; 2 ; =========================================================================== ; loc_20222: Obj0C_Init: addq.b #2,routine(a0) move.l #Obj0C_MapUnc_202FA,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_FloatPlatform,3,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo9_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #4,priority(a0) move.w y_pos(a0),d0 subi.w #$10,d0 move.w d0,objoff_3A(a0) moveq #0,d0 move.b subtype(a0),d0 andi.w #$F0,d0 addi.w #$10,d0 move.w d0,d1 subq.w #1,d0 move.w d0,objoff_30(a0) move.w d0,objoff_32(a0) moveq #0,d0 move.b subtype(a0),d0 andi.w #$F,d0 move.b d0,objoff_3E(a0) move.b d0,objoff_3F(a0) ; loc_20282: Obj0C_Main: move.b objoff_3C(a0),d0 beq.s loc_202C0 cmpi.b #$80,d0 bne.s loc_202D0 move.b objoff_3D(a0),d1 bne.s loc_202A2 subq.b #1,objoff_3E(a0) bpl.s loc_202A2 move.b objoff_3F(a0),objoff_3E(a0) bra.s loc_202D0 ; =========================================================================== loc_202A2: addq.b #1,objoff_3D(a0) move.b d1,d0 jsrto (CalcSine).l, JmpTo5_CalcSine addi_.w #8,d0 asr.w #6,d0 subi.w #$10,d0 add.w objoff_3A(a0),d0 move.w d0,y_pos(a0) bra.s loc_202E6 ; =========================================================================== loc_202C0: move.w (Vint_runcount+2).w,d1 andi.w #$3FF,d1 bne.s loc_202D4 move.b #1,objoff_3D(a0) loc_202D0: addq.b #1,objoff_3C(a0) loc_202D4: jsrto (CalcSine).l, JmpTo5_CalcSine addi_.w #8,d1 asr.w #4,d1 add.w objoff_3A(a0),d1 move.w d1,y_pos(a0) loc_202E6: moveq #0,d1 move.b width_pixels(a0),d1 moveq #9,d3 move.w x_pos(a0),d4 bsr.w PlatformObject jmpto (MarkObjGone).l, JmpTo4_MarkObjGone ; =========================================================================== ; ---------------------------------------------------------------------------- ; Unused sprite mappings ; ---------------------------------------------------------------------------- Obj0C_MapUnc_202FA: BINCLUDE "mappings/sprite/obj0C.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo4_MarkObjGone jmp (MarkObjGone).l JmpTo9_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo5_CalcSine jmp (CalcSine).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 12 - Emerald from Hidden Palace Zone (unused) ; ---------------------------------------------------------------------------- ; Sprite_2031C: Obj12: moveq #0,d0 move.b routine(a0),d0 move.w Obj12_Index(pc,d0.w),d1 jmp Obj12_Index(pc,d1.w) ; =========================================================================== ; off_2032A Obj12_Index: offsetTable offsetTableEntry.w Obj12_Init ; 0 offsetTableEntry.w Obj12_Main ; 2 ; =========================================================================== ; loc_2032E: Obj12_Init: addq.b #2,routine(a0) move.l #Obj12_MapUnc_20382,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_HPZ_Emerald,3,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo10_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$20,width_pixels(a0) move.b #4,priority(a0) ; loc_20356: Obj12_Main: move.w #$20,d1 move.w #$10,d2 move.w #$10,d3 move.w x_pos(a0),d4 bsr.w SolidObject move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w JmpTo16_DeleteObject jmpto (DisplaySprite).l, JmpTo8_DisplaySprite ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings (unused) ; ------------------------------------------------------------------------------- Obj12_MapUnc_20382: BINCLUDE "mappings/sprite/obj12.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo8_DisplaySprite jmp (DisplaySprite).l JmpTo16_DeleteObject jmp (DeleteObject).l JmpTo10_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 else JmpTo16_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 13 - Waterfall in Hidden Palace Zone (unused) ; ---------------------------------------------------------------------------- ; Sprite_203AC: Obj13: moveq #0,d0 move.b routine(a0),d0 move.w Obj13_Index(pc,d0.w),d1 jmp Obj13_Index(pc,d1.w) ; =========================================================================== ; off_203BA Obj13_Index: offsetTable offsetTableEntry.w Obj13_Init ; 0 offsetTableEntry.w Obj13_Main ; 2 offsetTableEntry.w Obj13_ChkDel ; 4 ; =========================================================================== ; loc_203C0: Obj13_Init: addq.b #2,routine(a0) move.l #Obj13_MapUnc_20528,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_HPZ_Waterfall,3,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo11_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #1,priority(a0) move.b #$12,mapping_frame(a0) bsr.s Obj13_LoadSubObject move.b #$A0,y_radius(a1) bset #4,render_flags(a1) move.l a1,objoff_38(a0) move.w y_pos(a0),objoff_34(a0) move.w y_pos(a0),objoff_36(a0) cmpi.b #$10,subtype(a0) blo.s loc_2046C bsr.s Obj13_LoadSubObject move.l a1,objoff_3C(a0) move.w y_pos(a0),y_pos(a1) addi.w #$98,y_pos(a1) bra.s loc_2046C ; =========================================================================== ; loc_20428: Obj13_LoadSubObject: jsr (SingleObjLoad2).l bne.s + ; rts _move.b #ObjID_HPZWaterfall,id(a1) ; load obj13 addq.b #4,routine(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.l #Obj13_MapUnc_20528,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_HPZ_Waterfall,3,1),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo2_Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #$10,width_pixels(a1) move.b #1,priority(a1) + rts ; =========================================================================== loc_2046C: moveq #0,d1 move.b subtype(a0),d1 move.w objoff_34(a0),d0 subi.w #$78,d0 lsl.w #4,d1 add.w d1,d0 move.w d0,y_pos(a0) move.w d0,objoff_34(a0) ; loc_20486: Obj13_Main: movea.l objoff_38(a0),a1 ; a1=object move.b #$12,mapping_frame(a0) move.w objoff_34(a0),d0 move.w (Water_Level_1).w,d1 cmp.w d0,d1 bhs.s + move.w d1,d0 + move.w d0,y_pos(a0) sub.w objoff_36(a0),d0 addi.w #$80,d0 bmi.s loc_204F0 lsr.w #4,d0 move.w d0,d1 cmpi.w #$F,d0 blo.s + moveq #$F,d0 + move.b d0,mapping_frame(a1) cmpi.b #$10,subtype(a0) blo.s loc_204D8 movea.l objoff_3C(a0),a1 ; a1=object subi.w #$F,d1 bcc.s + moveq #0,d1 + addi.w #$13,d1 move.b d1,mapping_frame(a1) loc_204D8: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w JmpTo17_DeleteObject jmpto (DisplaySprite).l, JmpTo9_DisplaySprite ; =========================================================================== loc_204F0: moveq #$13,d0 move.b d0,mapping_frame(a0) move.b d0,mapping_frame(a1) move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w JmpTo17_DeleteObject rts ; =========================================================================== ; loc_20510: Obj13_ChkDel: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w JmpTo17_DeleteObject jmpto (DisplaySprite).l, JmpTo9_DisplaySprite ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings (unused) ; ------------------------------------------------------------------------------- Obj13_MapUnc_20528: BINCLUDE "mappings/sprite/obj13.bin" ; =========================================================================== if ~~removeJmpTos JmpTo9_DisplaySprite jmp (DisplaySprite).l JmpTo17_DeleteObject jmp (DeleteObject).l JmpTo2_Adjust2PArtPointer2 jmp (Adjust2PArtPointer2).l JmpTo11_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 else JmpTo17_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 04 - Surface of the water - water surface ; ---------------------------------------------------------------------------- Obj04: moveq #0,d0 move.b routine(a0),d0 move.w Obj04_Index(pc,d0.w),d1 jmp Obj04_Index(pc,d1.w) ; =========================================================================== ; off_208EA: Obj04_Index: offsetTable offsetTableEntry.w Obj04_Init ; 0 offsetTableEntry.w Obj04_Action ; 2 offsetTableEntry.w Obj04_Action2 ; 4 ; =========================================================================== ; loc_208F0: Obj04_Main: Obj04_Init: addq.b #2,routine(a0) ; => Obj04_Action move.l #Obj04_MapUnc_20A0E,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_WaterSurface,0,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo12_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$80,width_pixels(a0) move.w x_pos(a0),objoff_30(a0) cmpi.b #aquatic_ruin_zone,(Current_Zone).w bne.s Obj04_Action addq.b #2,routine(a0) ; Obj04_Action2 move.l #Obj04_MapUnc_20AFE,mappings(a0) bra.w Obj04_Action2 ; =========================================================================== ; loc_20930: Obj04_Action: move.w (Water_Level_1).w,d1 move.w d1,y_pos(a0) tst.b objoff_32(a0) bne.s Obj04_Animate btst #button_start,(Ctrl_1_Press).w ; is Start button pressed? beq.s loc_20962 ; if not, branch addq.b #3,mapping_frame(a0) ; use different frames move.b #1,objoff_32(a0) ; stop animation bra.s loc_20962 ; =========================================================================== ; loc_20952: Obj04_Animate: tst.w (Game_paused).w ; is the game paused? bne.s loc_20962 ; if yes, branch move.b #0,objoff_32(a0) ; resume animation subq.b #3,mapping_frame(a0) ; use normal frames loc_20962: lea (Anim_obj04).l,a1 moveq #0,d1 move.b anim_frame(a0),d1 move.b (a1,d1.w),mapping_frame(a0) addq.b #1,anim_frame(a0) andi.b #$3F,anim_frame(a0) jmpto (DisplaySprite).l, JmpTo10_DisplaySprite ; =========================================================================== ; water sprite animation 'script' (custom format for this object) ; byte_20982: Anim_obj04: dc.b 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1 dc.b 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2 dc.b 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1 dc.b 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0 ; =========================================================================== ; loc_209C2: Obj04_Action2: move.w (Water_Level_1).w,d1 move.w d1,y_pos(a0) tst.b objoff_32(a0) bne.s Obj04_Animate2 btst #button_start,(Ctrl_1_Press).w ; is Start button pressed? beq.s loc_209F4 ; if not, branch addq.b #2,mapping_frame(a0) ; use different frames move.b #1,objoff_32(a0) ; stop animation bra.s BranchTo_JmpTo10_DisplaySprite ; =========================================================================== ; loc_209E4: Obj04_Animate2: tst.w (Game_paused).w ; is the game paused? bne.s BranchTo_JmpTo10_DisplaySprite ; if yes, branch move.b #0,objoff_32(a0) ; resume animation subq.b #2,mapping_frame(a0) ; use normal frames loc_209F4: subq.b #1,anim_frame_duration(a0) bpl.s BranchTo_JmpTo10_DisplaySprite move.b #5,anim_frame_duration(a0) addq.b #1,mapping_frame(a0) andi.b #1,mapping_frame(a0) BranchTo_JmpTo10_DisplaySprite jmpto (DisplaySprite).l, JmpTo10_DisplaySprite ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj04_MapUnc_20A0E: BINCLUDE "mappings/sprite/obj04_a.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj04_MapUnc_20AFE: BINCLUDE "mappings/sprite/obj04_b.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 49 - Waterfall from EHZ ; ---------------------------------------------------------------------------- ; Sprite_20B9E: Obj49: moveq #0,d0 move.b routine(a0),d0 move.w Obj49_Index(pc,d0.w),d1 jmp Obj49_Index(pc,d1.w) ; =========================================================================== ; off_20BAC: Obj49_Index: offsetTable offsetTableEntry.w Obj49_Init ; 0 offsetTableEntry.w Obj49_ChkDel ; 2 ; =========================================================================== ; loc_20BB0: Obj49_Main: Obj49_Init: addq.b #2,routine(a0) move.l #Obj49_MapUnc_20C50,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Waterfall,1,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo12_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$20,width_pixels(a0) move.w x_pos(a0),objoff_30(a0) move.b #0,priority(a0) move.b #$80,y_radius(a0) bset #4,render_flags(a0) ; loc_20BEA: Obj49_ChkDel: tst.w (Two_player_mode).w bne.s + move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w JmpTo18_DeleteObject + move.w x_pos(a0),d1 move.w d1,d2 subi.w #$40,d1 addi.w #$40,d2 move.b subtype(a0),d3 move.b #0,mapping_frame(a0) move.w (MainCharacter+x_pos).w,d0 cmp.w d1,d0 blo.s loc_20C36 cmp.w d2,d0 bhs.s loc_20C36 move.b #1,mapping_frame(a0) add.b d3,mapping_frame(a0) jmpto (DisplaySprite).l, JmpTo10_DisplaySprite ; =========================================================================== loc_20C36: move.w (Sidekick+x_pos).w,d0 cmp.w d1,d0 blo.s Obj49_Display cmp.w d2,d0 bhs.s Obj49_Display move.b #1,mapping_frame(a0) ; loc_20C48: Obj49_Display: add.b d3,mapping_frame(a0) jmpto (DisplaySprite).l, JmpTo10_DisplaySprite ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj49_MapUnc_20C50: BINCLUDE "mappings/sprite/obj49.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 31 - Lava collision marker ; ---------------------------------------------------------------------------- ; Sprite_20DEC: Obj31: moveq #0,d0 move.b routine(a0),d0 move.w Obj31_Index(pc,d0.w),d1 jmp Obj31_Index(pc,d1.w) ; =========================================================================== ; off_20DFA: Obj31_States: Obj31_Index: offsetTable offsetTableEntry.w Obj31_Init ; 0 offsetTableEntry.w Obj31_Main ; 2 ; --------------------------------------------------------------------------- ; byte_20DFE: Obj31_CollisionFlagsBySubtype: dc.b $96 ; 0 dc.b $94 ; 1 dc.b $95 ; 2 dc.b 0 ; 3 ; =========================================================================== ; loc_20E02: Obj31_Init: addq.b #2,routine(a0) ; => Obj31_Main moveq #0,d0 move.b subtype(a0),d0 move.b Obj31_CollisionFlagsBySubtype(pc,d0.w),collision_flags(a0) move.l #Obj31_MapUnc_20E6C,mappings(a0) tst.w (Debug_placement_mode).w beq.s + move.l #Obj31_MapUnc_20E74,mappings(a0) + move.w #make_art_tile(ArtTile_ArtNem_Powerups,0,1),art_tile(a0) move.b #$84,render_flags(a0) move.b #$80,width_pixels(a0) move.b #4,priority(a0) move.b subtype(a0),mapping_frame(a0) ; loc_20E46: Obj31_Main: tst.w (Two_player_mode).w bne.s + move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w JmpTo18_DeleteObject + tst.w (Debug_placement_mode).w beq.s + ; rts jsrto (DisplaySprite).l, JmpTo10_DisplaySprite + rts ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite non-mappings ; ------------------------------------------------------------------------------- Obj31_MapUnc_20E6C: BINCLUDE "mappings/sprite/obj31_a.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj31_MapUnc_20E74: BINCLUDE "mappings/sprite/obj31_b.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 74 - Invisible solid block ; ---------------------------------------------------------------------------- ; Sprite_20EE0: Obj74: moveq #0,d0 move.b routine(a0),d0 move.w Obj74_Index(pc,d0.w),d1 jmp Obj74_Index(pc,d1.w) ; =========================================================================== ; off_20EEE: Obj74_States: Obj74_Index: offsetTable offsetTableEntry.w Obj74_Init ; 0 offsetTableEntry.w Obj74_Main ; 2 ; =========================================================================== ; loc_20EF2: Obj74_Init: addq.b #2,routine(a0) ; => Obj74_Main move.l #Obj74_MapUnc_20F66,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Powerups,0,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo12_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b subtype(a0),d0 move.b d0,d1 andi.w #$F0,d0 addi.w #$10,d0 lsr.w #1,d0 move.b d0,width_pixels(a0) andi.w #$F,d1 addq.w #1,d1 lsl.w #3,d1 move.b d1,y_radius(a0) ; loc_20F2E: Obj74_Main: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObject_Always tst.w (Two_player_mode).w bne.s + move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w JmpTo18_DeleteObject if gameRevision=0 ; this object was visible with debug mode in REV00 + tst.w (Debug_placement_mode).w beq.s + ; rts jmp (DisplaySprite).l endif + rts ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj74_MapUnc_20F66: BINCLUDE "mappings/sprite/obj74.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 7C - Big pylon in foreground of CPZ ; ---------------------------------------------------------------------------- ; Sprite_20FD2: Obj7C: moveq #0,d0 move.b routine(a0),d0 move.w Obj7C_Index(pc,d0.w),d1 jmp Obj7C_Index(pc,d1.w) ; =========================================================================== ; off_20FE0: Obj7C_States: Obj7C_Index: offsetTable offsetTableEntry.w Obj7C_Init ; 0 offsetTableEntry.w Obj7C_Main ; 2 ; =========================================================================== ; loc_20FE4: Obj7C_Init: addq.b #2,routine(a0) ; => Obj7C_Main move.l #Obj7C_MapUnc_2103C,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CPZMetalThings,2,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo12_Adjust2PArtPointer move.b #$10,width_pixels(a0) move.b #7,priority(a0) ; loc_21006: Obj7C_Main: move.w (Camera_X_pos).w,d1 andi.w #$3FF,d1 cmpi.w #$2E0,d1 bhs.s + ; rts asr.w #1,d1 move.w d1,d0 asr.w #1,d1 add.w d1,d0 neg.w d0 move.w d0,x_pixel(a0) move.w (Camera_Y_pos).w,d1 asr.w #1,d1 andi.w #$3F,d1 neg.w d1 addi.w #$100,d1 move.w d1,y_pixel(a0) jmpto (DisplaySprite).l, JmpTo10_DisplaySprite ; --------------------------------------------------------------------------- + rts ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj7C_MapUnc_2103C: BINCLUDE "mappings/sprite/obj7C.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 27 - An explosion, giving off an animal and 100 points ; ---------------------------------------------------------------------------- ; Sprite_21088: Obj27: moveq #0,d0 move.b routine(a0),d0 move.w Obj27_Index(pc,d0.w),d1 jmp Obj27_Index(pc,d1.w) ; =========================================================================== ; off_21096: Obj27_States: Obj27_Index: offsetTable offsetTableEntry.w Obj27_InitWithAnimal ; 0 offsetTableEntry.w Obj27_Init ; 2 offsetTableEntry.w Obj27_Main ; 4 ; =========================================================================== ; loc_2109C: Obj27_Init: Obj27_InitWithAnimal: addq.b #2,routine(a0) ; => Obj27_Init jsrto (SingleObjLoad).l, JmpTo2_SingleObjLoad bne.s Obj27_Init _move.b #ObjID_Animal,id(a1) ; load obj28 (Animal and 100 points) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w parent(a0),parent(a1) ; loc_210BE: Obj27_Init2: Obj27_Init: addq.b #2,routine(a0) ; => Obj27_Main move.l #Obj27_MapUnc_21120,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Explosion,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo12_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #1,priority(a0) move.b #0,collision_flags(a0) move.b #$C,width_pixels(a0) move.b #3,anim_frame_duration(a0) move.b #0,mapping_frame(a0) move.w #SndID_Explosion,d0 jsr (PlaySound).l ; loc_21102: Obj27_Main: subq.b #1,anim_frame_duration(a0) bpl.s + move.b #7,anim_frame_duration(a0) addq.b #1,mapping_frame(a0) cmpi.b #5,mapping_frame(a0) beq.w JmpTo18_DeleteObject + jmpto (DisplaySprite).l, JmpTo10_DisplaySprite ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj27_MapUnc_21120: BINCLUDE "mappings/sprite/obj27.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 84 - Pinball mode enable/disable ; (used in Casino Night Zone to determine when Sonic should stay in a ball) ; ---------------------------------------------------------------------------- ; Sprite_2115C: Obj84: moveq #0,d0 move.b routine(a0),d0 move.w Obj84_Index(pc,d0.w),d1 jsr Obj84_Index(pc,d1.w) jmp (MarkObjGone3).l ; =========================================================================== ; off_21170: Obj84_States: Obj84_Index: offsetTable offsetTableEntry.w Obj84_Init ; 0 offsetTableEntry.w Obj84_MainX ; 2 offsetTableEntry.w Obj84_MainY ; 4 ; =========================================================================== ; loc_21176: Obj84_Init: addq.b #2,routine(a0) ; => Obj84_MainX move.l #Obj03_MapUnc_1FFB8,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Ring,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo12_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #5,priority(a0) move.b subtype(a0),d0 btst #2,d0 beq.s Obj84_Init_CheckX addq.b #2,routine(a0) ; => Obj84_MainY andi.w #7,d0 move.b d0,mapping_frame(a0) andi.w #3,d0 add.w d0,d0 move.w word_211E8(pc,d0.w),objoff_32(a0) move.w y_pos(a0),d1 lea (MainCharacter).w,a1 ; a1=character cmp.w y_pos(a1),d1 bhs.s + move.b #1,objoff_34(a0) + lea (Sidekick).w,a1 ; a1=character cmp.w y_pos(a1),d1 bhs.s + move.b #1,objoff_35(a0) + bra.w Obj84_MainY ; =========================================================================== word_211E8: dc.w $20 dc.w $40 ; 1 dc.w $80 ; 2 dc.w $100 ; 3 ; =========================================================================== ; loc_211F0: Obj84_Init_CheckX: andi.w #3,d0 move.b d0,mapping_frame(a0) add.w d0,d0 move.w word_211E8(pc,d0.w),objoff_32(a0) move.w x_pos(a0),d1 lea (MainCharacter).w,a1 ; a1=character cmp.w x_pos(a1),d1 bhs.s + move.b #1,objoff_34(a0) + lea (Sidekick).w,a1 ; a1=character cmp.w x_pos(a1),d1 bhs.s Obj84_MainX move.b #1,objoff_35(a0) ; loc_21224: Obj84_MainX: tst.w (Debug_placement_mode).w bne.s return_21284 move.w x_pos(a0),d1 lea objoff_34(a0),a2 ; a2=object lea (MainCharacter).w,a1 ; a1=character bsr.s + lea (Sidekick).w,a1 ; a1=character cmpi.w #4,(Tails_CPU_routine).w ; TailsCPU_Flying beq.s return_21284 + tst.b (a2)+ bne.s Obj84_MainX_Alt cmp.w x_pos(a1),d1 bhi.s return_21284 move.b #1,-1(a2) move.w y_pos(a0),d2 move.w d2,d3 move.w objoff_32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w y_pos(a1),d4 cmp.w d2,d4 blo.s return_21284 cmp.w d3,d4 bhs.s return_21284 btst #0,render_flags(a0) bne.s + move.b #1,pinball_mode(a1) ; enable must-roll "pinball mode" bra.s loc_212C4 ; --------------------------------------------------------------------------- + move.b #0,pinball_mode(a1) ; disable pinball mode return_21284: rts ; =========================================================================== ; loc_21286: Obj84_MainX_Alt: cmp.w x_pos(a1),d1 bls.s return_21284 move.b #0,-1(a2) move.w y_pos(a0),d2 move.w d2,d3 move.w objoff_32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w y_pos(a1),d4 cmp.w d2,d4 blo.s return_21284 cmp.w d3,d4 bhs.s return_21284 btst #0,render_flags(a0) beq.s + move.b #1,pinball_mode(a1) bra.s loc_212C4 ; --------------------------------------------------------------------------- + move.b #0,pinball_mode(a1) rts ; =========================================================================== loc_212C4: btst #2,status(a1) beq.s + rts ; --------------------------------------------------------------------------- + bset #2,status(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #AniIDSonAni_Roll,anim(a1) addq.w #5,y_pos(a1) move.w #SndID_Roll,d0 jsr (PlaySound).l rts ; =========================================================================== ; loc_212F6: Obj84_MainY: tst.w (Debug_placement_mode).w bne.s return_21350 move.w y_pos(a0),d1 lea objoff_34(a0),a2 ; a2=object lea (MainCharacter).w,a1 ; a1=character bsr.s + lea (Sidekick).w,a1 ; a1=character + tst.b (a2)+ bne.s Obj84_MainY_Alt cmp.w y_pos(a1),d1 bhi.s return_21350 move.b #1,-1(a2) move.w x_pos(a0),d2 move.w d2,d3 move.w objoff_32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w x_pos(a1),d4 cmp.w d2,d4 blo.s return_21350 cmp.w d3,d4 bhs.s return_21350 btst #0,render_flags(a0) bne.s + move.b #1,pinball_mode(a1) bra.w loc_212C4 ; --------------------------------------------------------------------------- + move.b #0,pinball_mode(a1) return_21350: rts ; =========================================================================== ; loc_21352: Obj84_MainY_Alt: cmp.w y_pos(a1),d1 bls.s return_21350 move.b #0,-1(a2) move.w x_pos(a0),d2 move.w d2,d3 move.w objoff_32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w x_pos(a1),d4 cmp.w d2,d4 blo.s return_21350 cmp.w d3,d4 bhs.s return_21350 btst #0,render_flags(a0) beq.s + move.b #1,pinball_mode(a1) bra.w loc_212C4 ; --------------------------------------------------------------------------- + move.b #0,pinball_mode(a1) rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 8B - Cycling palette switcher from Wing Fortress Zone ; ---------------------------------------------------------------------------- ; Sprite_21392: Obj8B: moveq #0,d0 move.b routine(a0),d0 move.w Obj8B_Index(pc,d0.w),d1 jsr Obj8B_Index(pc,d1.w) jmp (MarkObjGone3).l ; =========================================================================== ; off_213A6: Obj8B_Index: offsetTable offsetTableEntry.w Obj8B_Init ; 0 offsetTableEntry.w Obj8B_Main ; 2 ; =========================================================================== word_213AA: dc.w $20 dc.w $40 ; 1 dc.w $80 ; 2 dc.w $100 ; 3 ; =========================================================================== ; loc_213B2: Obj8B_Init: addq.b #2,routine(a0) move.l #Obj03_MapUnc_1FFB8,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Ring,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo12_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #5,priority(a0) move.b subtype(a0),d0 andi.w #3,d0 move.b d0,mapping_frame(a0) add.w d0,d0 move.w word_213AA(pc,d0.w),objoff_32(a0) move.w x_pos(a0),d1 lea (MainCharacter).w,a1 ; a1=character cmp.w x_pos(a1),d1 bhs.s loc_21402 move.b #1,objoff_34(a0) loc_21402: lea (Sidekick).w,a1 ; a1=character cmp.w x_pos(a1),d1 bhs.s Obj8B_Main move.b #1,objoff_35(a0) ; loc_21412: Obj8B_Main: tst.w (Debug_placement_mode).w bne.s return_2146A move.w x_pos(a0),d1 lea objoff_34(a0),a2 ; a2=object lea (MainCharacter).w,a1 ; a1=character bsr.s loc_2142A lea (Sidekick).w,a1 ; a1=character loc_2142A: tst.b (a2)+ bne.s loc_2146C cmp.w x_pos(a1),d1 bhi.s return_2146A move.b #1,-1(a2) move.w y_pos(a0),d2 move.w d2,d3 move.w objoff_32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w y_pos(a1),d4 cmp.w d2,d4 blo.s return_2146A cmp.w d3,d4 bhs.s return_2146A btst #0,render_flags(a0) bne.s + move.b #1,(WFZ_SCZ_Fire_Toggle).w rts ; --------------------------------------------------------------------------- + move.b #0,(WFZ_SCZ_Fire_Toggle).w return_2146A: rts ; =========================================================================== loc_2146C: cmp.w x_pos(a1),d1 bls.s return_2146A move.b #0,-1(a2) move.w y_pos(a0),d2 move.w d2,d3 move.w objoff_32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w y_pos(a1),d4 cmp.w d2,d4 blo.s return_2146A cmp.w d3,d4 bhs.s return_2146A btst #0,render_flags(a0) beq.s + move.b #1,(WFZ_SCZ_Fire_Toggle).w rts ; --------------------------------------------------------------------------- + move.b #0,(WFZ_SCZ_Fire_Toggle).w rts ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos ; loc_214AC: JmpTo10_DisplaySprite jmp (DisplaySprite).l JmpTo18_DeleteObject jmp (DeleteObject).l JmpTo2_SingleObjLoad jmp (SingleObjLoad).l JmpTo12_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 else JmpTo18_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 06 - Rotating cylinder in MTZ, twisting spiral pathway in EHZ ; ---------------------------------------------------------------------------- ; Sprite_214C4: Obj06: moveq #0,d0 move.b routine(a0),d0 move.w Obj06_Index(pc,d0.w),d1 jsr Obj06_Index(pc,d1.w) tst.w (Two_player_mode).w beq.s Obj06_ChkDel rts ; --------------------------------------------------------------------------- ; seems to be an optimization to delete the object the instant it goes offscreen ; only in 1-player mode, because it would screw up the other player ; loc_214DA: Obj06_ChkDel: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.s JmpTo19_DeleteObject rts ; --------------------------------------------------------------------------- JmpTo19_DeleteObject jmp (DeleteObject).l ; =========================================================================== ; off_214F4: Obj06_Index: offsetTable offsetTableEntry.w Obj06_Init ; 0 offsetTableEntry.w Obj06_Spiral ; 2 offsetTableEntry.w Obj06_Cylinder ; 4 ; =========================================================================== ; loc_214FA: Obj06_Init: addq.b #2,routine(a0) ; => Obj06_Spiral move.b #$D0,width_pixels(a0) tst.b subtype(a0) bpl.s Obj06_Spiral addq.b #2,routine(a0) ; => Obj06_Cylinder bra.w Obj06_Cylinder ; =========================================================================== ; spiral pathway from EHZ ; loc_21512: Obj06_Spiral: lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 bsr.s + lea (Sidekick).w,a1 ; a1=character addq.b #1,d6 + btst d6,status(a0) bne.w loc_215C0 btst #1,status(a1) bne.w return_215BE btst #3,status(a1) bne.s loc_21580 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 tst.w x_vel(a1) bmi.s loc_21556 cmpi.w #-$C0,d0 bgt.s return_215BE cmpi.w #-$D0,d0 blt.s return_215BE bra.s loc_21562 ; --------------------------------------------------------------------------- loc_21556: cmpi.w #$C0,d0 blt.s return_215BE cmpi.w #$D0,d0 bgt.s return_215BE loc_21562: move.w y_pos(a1),d1 sub.w y_pos(a0),d1 subi.w #$10,d1 cmpi.w #$30,d1 bhs.s return_215BE tst.b obj_control(a1) bne.s return_215BE bsr.w RideObject_SetRide rts ; --------------------------------------------------------------------------- loc_21580: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 tst.w x_vel(a1) bmi.s loc_2159C cmpi.w #-$B0,d0 bgt.s return_215BE cmpi.w #-$C0,d0 blt.s return_215BE bra.s loc_215A8 ; --------------------------------------------------------------------------- loc_2159C: cmpi.w #$B0,d0 blt.s return_215BE cmpi.w #$C0,d0 bgt.s return_215BE loc_215A8: move.w y_pos(a1),d1 sub.w y_pos(a0),d1 subi.w #$10,d1 cmpi.w #$30,d1 bhs.s return_215BE bsr.w RideObject_SetRide return_215BE: rts ; --------------------------------------------------------------------------- loc_215C0: mvabs.w inertia(a1),d0 cmpi.w #$600,d0 blo.s Obj06_Spiral_CharacterFallsOff btst #1,status(a1) bne.s Obj06_Spiral_CharacterFallsOff move.w x_pos(a1),d0 sub.w x_pos(a0),d0 addi.w #$D0,d0 bmi.s Obj06_Spiral_CharacterFallsOff cmpi.w #$1A0,d0 blo.s Obj06_Spiral_MoveCharacter ; loc_215EA: Obj06_Spiral_CharacterFallsOff: bclr #3,status(a1) bclr d6,status(a0) move.b #0,flips_remaining(a1) move.b #4,flip_speed(a1) rts ; --------------------------------------------------------------------------- ; loc_21602: Obj06_Spiral_MoveCharacter: btst #3,status(a1) beq.s return_215BE move.b Obj06_CosineTable(pc,d0.w),d1 ext.w d1 move.w y_pos(a0),d2 add.w d1,d2 moveq #0,d1 move.b y_radius(a1),d1 subi.w #$13,d1 sub.w d1,d2 move.w d2,y_pos(a1) lsr.w #3,d0 andi.w #$3F,d0 move.b Obj06_FlipAngleTable(pc,d0.w),flip_angle(a1) rts ; =========================================================================== ; byte_21634: Obj06_FlipAngleTable: dc.b 0, 0, 1, 1; 4 dc.b $16, $16, $16, $16; 8 dc.b $2C, $2C, $2C, $2C; 12 dc.b $42, $42, $42, $42; 16 dc.b $58, $58, $58, $58; 20 dc.b $6E, $6E, $6E, $6E; 24 dc.b $84, $84, $84, $84; 28 dc.b $9A, $9A, $9A, $9A; 32 dc.b $B0, $B0, $B0, $B0; 36 dc.b $C6, $C6, $C6, $C6; 40 dc.b $DC, $DC, $DC, $DC; 44 dc.b $F2, $F2, $F2, $F2; 48 dc.b 1, 1, 0, 0; 52 ; byte_21668: Obj06_CosineTable: dc.b 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32; 16 dc.b 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 31, 31; 32 dc.b 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 30, 30; 48 dc.b 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 28, 28, 28, 28, 27; 64 dc.b 27, 27, 27, 26, 26, 26, 25, 25, 25, 24, 24, 24, 23, 23, 22, 22; 80 dc.b 21, 21, 20, 20, 19, 18, 18, 17, 16, 16, 15, 14, 14, 13, 12, 12; 96 dc.b 11, 10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1; 112 dc.b 0, -1, -2, -2, -3, -4, -4, -5, -6, -7, -7, -8, -9, -9,-10,-10; 128 dc.b -11,-11,-12,-12,-13,-14,-14,-15,-15,-16,-16,-17,-17,-18,-18,-19; 144 dc.b -19,-19,-20,-21,-21,-22,-22,-23,-23,-24,-24,-25,-25,-26,-26,-27; 160 dc.b -27,-28,-28,-28,-29,-29,-30,-30,-30,-31,-31,-31,-32,-32,-32,-33; 176 dc.b -33,-33,-33,-34,-34,-34,-35,-35,-35,-35,-35,-35,-35,-35,-36,-36; 192 dc.b -36,-36,-36,-36,-36,-36,-36,-37,-37,-37,-37,-37,-37,-37,-37,-37; 208 dc.b -37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37; 224 dc.b -37,-37,-37,-37,-36,-36,-36,-36,-36,-36,-36,-35,-35,-35,-35,-35; 240 dc.b -35,-35,-35,-34,-34,-34,-33,-33,-33,-33,-32,-32,-32,-31,-31,-31; 256 dc.b -30,-30,-30,-29,-29,-28,-28,-28,-27,-27,-26,-26,-25,-25,-24,-24; 272 dc.b -23,-23,-22,-22,-21,-21,-20,-19,-19,-18,-18,-17,-16,-16,-15,-14; 288 dc.b -14,-13,-12,-11,-11,-10, -9, -8, -7, -7, -6, -5, -4, -3, -2, -1; 304 dc.b 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 10, 11, 12, 13; 320 dc.b 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21; 336 dc.b 21, 22, 22, 23, 23, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26; 352 dc.b 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29; 368 dc.b 29, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31; 384 dc.b 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32; 400 dc.b 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32; 416 ; =========================================================================== ; rotating meshed cage from MTZ ; loc_21808: Obj06_Cylinder: lea (MainCharacter).w,a1 ; a1=character lea (MTZCylinder_Angle_Sonic).w,a2 moveq #p1_standing_bit,d6 bsr.s + lea (Sidekick).w,a1 ; a1=character lea (MTZCylinder_Angle_Tails).w,a2 addq.b #1,d6 + btst d6,status(a0) bne.w loc_2188C move.w x_pos(a1),d0 sub.w x_pos(a0),d0 cmpi.w #-$C0,d0 blt.s return_2188A cmpi.w #$C0,d0 bge.s return_2188A move.w y_pos(a0),d0 addi.w #$3C,d0 move.w y_pos(a1),d2 move.b y_radius(a1),d1 ext.w d1 add.w d2,d1 addq.w #4,d1 sub.w d1,d0 bhi.s return_2188A cmpi.w #-$10,d0 blo.s return_2188A cmpi.b #6,routine(a1) bhs.s return_2188A add.w d0,d2 addq.w #3,d2 move.w d2,y_pos(a1) move.b #1,flip_turned(a1) ; face the other way bsr.w RideObject_SetRide move.w #AniIDSonAni_Run,anim(a1) move.b #0,(a2) tst.w inertia(a1) bne.s return_2188A move.w #1,inertia(a1) return_2188A: rts ; =========================================================================== loc_2188C: btst #1,status(a1) bne.s loc_218C6 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 addi.w #$C0,d0 bmi.s loc_218A8 cmpi.w #$180,d0 blo.s loc_218E0 loc_218A8: bclr #3,status(a1) bclr d6,status(a0) move.b #0,flips_remaining(a1) move.b #4,flip_speed(a1) bset #1,status(a1) rts ; --------------------------------------------------------------------------- loc_218C6: move.b (a2),d0 addi.b #$20,d0 cmpi.b #$40,d0 bhs.s + asr y_vel(a1) bra.s loc_218A8 ; --------------------------------------------------------------------------- + move.w #0,y_vel(a1) bra.s loc_218A8 ; =========================================================================== loc_218E0: btst #3,status(a1) beq.s return_2188A move.b (a2),d0 jsrto (CalcSine).l, JmpTo6_CalcSine muls.w #$2800,d1 swap d1 move.w y_pos(a0),d2 add.w d1,d2 moveq #0,d1 move.b y_radius(a1),d1 subi.w #$13,d1 sub.w d1,d2 move.w d2,y_pos(a1) move.b (a2),d0 move.b d0,flip_angle(a1) addq.b #4,(a2) tst.w inertia(a1) bne.s return_2191E move.w #1,inertia(a1) return_2191E: rts ; =========================================================================== if ~~removeJmpTos JmpTo6_CalcSine jmp (CalcSine).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 14 - See saw from Hill Top Zone ; ---------------------------------------------------------------------------- ; Sprite_21928: Obj14: moveq #0,d0 move.b routine(a0),d0 move.w Obj14_Index(pc,d0.w),d1 jsr Obj14_Index(pc,d1.w) move.w objoff_30(a0),d0 jmpto (MarkObjGone2).l, JmpTo_MarkObjGone2 ; =========================================================================== ; off_2193E: Obj14_Index: offsetTable offsetTableEntry.w Obj14_Init ; 0 offsetTableEntry.w Obj14_Main ; 2 offsetTableEntry.w return_21A74 ; 4 offsetTableEntry.w Obj14_Ball_Init ; 6 offsetTableEntry.w Obj14_Ball_Main ; 8 offsetTableEntry.w Obj14_Ball_Fly ; $A ; =========================================================================== ; loc_2194A: Obj14_Init: addq.b #2,routine(a0) move.l #Obj14_MapUnc_21CF0,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_HtzSeeSaw,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo13_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #4,priority(a0) move.b #$30,width_pixels(a0) move.w x_pos(a0),objoff_30(a0) tst.b subtype(a0) bne.s loc_219A4 jsrto (SingleObjLoad2).l, JmpTo3_SingleObjLoad2 bne.s loc_219A4 _move.b #ObjID_Seesaw,id(a1) ; load obj14 addq.b #6,routine(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b status(a0),status(a1) move.l a0,objoff_3C(a1) loc_219A4: btst #0,status(a0) beq.s loc_219B2 move.b #2,mapping_frame(a0) loc_219B2: move.b mapping_frame(a0),objoff_3A(a0) Obj14_Main: move.b objoff_3A(a0),d1 btst #p1_standing_bit,status(a0) beq.s loc_21A12 moveq #2,d1 lea (MainCharacter).w,a1 ; a1=character move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcc.s + neg.w d0 moveq #0,d1 + cmpi.w #8,d0 bhs.s + moveq #1,d1 + btst #p2_standing_bit,status(a0) beq.s Obj14_UpdateMappingAndCollision moveq #2,d2 lea (Sidekick).w,a1 ; a1=character move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcc.s + neg.w d0 moveq #0,d2 + cmpi.w #8,d0 bhs.s + moveq #1,d2 + add.w d2,d1 cmpi.w #3,d1 bne.s + addq.w #1,d1 + lsr.w #1,d1 bra.s Obj14_UpdateMappingAndCollision ; =========================================================================== loc_21A12: btst #p2_standing_bit,status(a0) beq.s loc_21A38 moveq #2,d1 lea (Sidekick).w,a1 ; a1=character move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcc.s + neg.w d0 moveq #0,d1 + cmpi.w #8,d0 bhs.s Obj14_UpdateMappingAndCollision moveq #1,d1 bra.s Obj14_UpdateMappingAndCollision ; =========================================================================== loc_21A38: move.w (MainCharacter+y_vel).w,d0 move.w (Sidekick+y_vel).w,d2 cmp.w d0,d2 blt.s + move.w d2,d0 + move.w d0,objoff_38(a0) ; loc_21A4A: Obj14_UpdateMappingAndCollision: bsr.w Obj14_SetMapping lea (byte_21C8E).l,a2 btst #0,mapping_frame(a0) beq.s + lea (byte_21CBF).l,a2 + move.w x_pos(a0),-(sp) moveq #0,d1 move.b width_pixels(a0),d1 moveq #8,d3 move.w (sp)+,d4 bra.w SlopedPlatform ; =========================================================================== return_21A74: rts ; =========================================================================== ; loc_21A76: Obj14_SetMapping: move.b mapping_frame(a0),d0 cmp.b d1,d0 beq.s return_21AA0 bhs.s + addq.b #2,d0 + subq.b #1,d0 move.b d0,mapping_frame(a0) move.b d1,objoff_3A(a0) bclr #0,render_flags(a0) btst #1,mapping_frame(a0) beq.s return_21AA0 bset #0,render_flags(a0) return_21AA0: rts ; =========================================================================== ; loc_21AA2: Obj14_Ball_Init: addq.b #2,routine(a0) move.l #Obj14_MapUnc_21D7C,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Sol,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo13_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #4,priority(a0) move.b #$8B,collision_flags(a0) move.b #$C,width_pixels(a0) move.w x_pos(a0),objoff_30(a0) ; save seesaw x position addi.w #$28,x_pos(a0) addi.w #$10,y_pos(a0) move.w y_pos(a0),objoff_34(a0) ; save bottom of seesaw y position btst #0,status(a0) beq.s Obj14_Ball_Main subi.w #$50,x_pos(a0) move.b #2,objoff_3A(a0) ; loc_21AFC: Obj14_Ball_Main: bsr.w Obj14_Animate movea.l objoff_3C(a0),a1 ; a1=parent object (seesaw) moveq #0,d0 move.b objoff_3A(a0),d0 ; d0 = ball angle - seesaw angle sub.b objoff_3A(a1),d0 beq.s Obj14_SetBallToRestOnSeeSaw bcc.s + neg.b d0 + move.w #-$818,d1 move.w #-$114,d2 cmpi.b #1,d0 beq.s + move.w #-$AF0,d1 move.w #-$CC,d2 cmpi.w #$A00,objoff_38(a1) ; check if character y_vel that jumped on blt.s + ; seesaw > 2560 move.w #-$E00,d1 move.w #-$A0,d2 + move.w d1,y_vel(a0) move.w d2,x_vel(a0) move.w x_pos(a0),d0 sub.w objoff_30(a0),d0 bcc.s + neg.w x_vel(a0) + addq.b #2,routine(a0) bra.s Obj14_Ball_Fly ; =========================================================================== ; loc_21B56: Obj14_SetBallToRestOnSeeSaw: lea (Obj14_YOffsets).l,a2 moveq #0,d0 move.b mapping_frame(a1),d0 move.w #$28,d2 move.w x_pos(a0),d1 sub.w objoff_30(a0),d1 bcc.s + neg.w d2 addq.w #2,d0 + add.w d0,d0 move.w objoff_34(a0),d1 ; d1 = bottom of seesaw y position add.w (a2,d0.w),d1 ; + offset for current angle move.w d1,y_pos(a0) ; set y position so ball rests on seesaw add.w objoff_30(a0),d2 move.w d2,x_pos(a0) clr.w y_sub(a0) clr.w x_sub(a0) rts ; =========================================================================== Obj14_Ball_Fly: bsr.w Obj14_Animate tst.w y_vel(a0) bpl.s loc_21BB6 jsrto (ObjectMoveAndFall).l, JmpTo_ObjectMoveAndFall move.w objoff_34(a0),d0 ; d0 = bottom of seesaw y position subi.w #$2F,d0 cmp.w y_pos(a0),d0 bgt.s return_21BB4 jsrto (ObjectMoveAndFall).l, JmpTo_ObjectMoveAndFall return_21BB4: rts ; =========================================================================== loc_21BB6: jsrto (ObjectMoveAndFall).l, JmpTo_ObjectMoveAndFall movea.l objoff_3C(a0),a1 ; a1=parent object (seesaw) lea (Obj14_YOffsets).l,a2 moveq #0,d0 move.b mapping_frame(a1),d0 move.w x_pos(a0),d1 sub.w objoff_30(a0),d1 bcc.s + addq.w #2,d0 + add.w d0,d0 move.w objoff_34(a0),d1 ; d1 = bottom of seesaw y position add.w (a2,d0.w),d1 ; + offset for current angle cmp.w y_pos(a0),d1 ; return if y position < d1 bgt.s return_21C2A movea.l objoff_3C(a0),a1 ; a1=parent object (seesaw) moveq #2,d1 ; d1 = x_vel >= 0 ? 0 : 2 tst.w x_vel(a0) bmi.s + moveq #0,d1 + move.b d1,objoff_3A(a1) ; set seesaw angle to d1 move.b d1,objoff_3A(a0) ; set ball angle to d1 cmp.b mapping_frame(a1),d1 beq.s loc_21C1E ; launch main character if stood on seesaw lea (MainCharacter).w,a2 ; a2=character bclr #p1_standing_bit,status(a1) beq.s + bsr.s Obj14_LaunchCharacter + ; launch sidekick if stood on seesaw lea (Sidekick).w,a2 ; a2=character bclr #p2_standing_bit,status(a1) beq.s loc_21C1E bsr.s Obj14_LaunchCharacter loc_21C1E: clr.w x_vel(a0) ; clear ball velocity clr.w y_vel(a0) subq.b #2,routine(a0) ; set ball to main state return_21C2A: rts ; =========================================================================== ; loc_21C2C: Obj14_LaunchCharacter: move.w y_vel(a0),y_vel(a2) ; set character y velocity to inverse of sol neg.w y_vel(a2) ; y velocity bset #1,status(a2) ; set character airborne flag bclr #3,status(a2) ; clear character on object flag clr.b jumping(a2) ; clear character jumping flag move.b #AniIDSonAni_Spring,anim(a2) ; set character to spring animation move.b #2,routine(a2) ; set character to airborne state move.w #SndID_Spring,d0 ; play spring sound jmp (PlaySound).l ; =========================================================================== ; heights of the contact point of the ball on the seesaw ; word_21C5C: Obj14_YOffsets: dc.w -8, -28, -47, -28, -8 ; low, balanced, high, balanced, low ; =========================================================================== ; loc_21C66: Obj14_Animate: move.b (Timer_frames+1).w,d0 andi.b #3,d0 bne.s Obj14_SetSolToFaceMainCharacter bchg #palette_bit_0,art_tile(a0) Obj14_SetSolToFaceMainCharacter: andi.b #$FE,render_flags(a0) move.w (MainCharacter+x_pos).w,d0 sub.w x_pos(a0),d0 bcs.s return_21C8C ori.b #1,render_flags(a0) return_21C8C: rts ; =========================================================================== byte_21C8E: dc.b $14,$14,$16,$18,$1A,$1C,$1A,$18,$16,$14,$13,$12,$11,$10, $F, $E dc.b $D, $C, $B, $A, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,$FF,$FE; 16 dc.b $FD,$FC,$FB,$FA,$F9,$F8,$F7,$F6,$F5,$F4,$F3,$F2,$F2,$F2,$F2,$F2; 32 dc.b $F2 ; 48 rev02even byte_21CBF: dc.b 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 dc.b 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5; 16 dc.b 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5; 32 even ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj14_MapUnc_21CF0: BINCLUDE "mappings/sprite/obj14_a.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj14_MapUnc_21D7C: BINCLUDE "mappings/sprite/obj14_b.bin" ; =========================================================================== if ~~removeJmpTos JmpTo3_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo13_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo_ObjectMoveAndFall jmp (ObjectMoveAndFall).l JmpTo_MarkObjGone2 jmp (MarkObjGone2).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 16 - Diagonally moving lift from HTZ ; ---------------------------------------------------------------------------- ; Sprite_21DAC: Obj16: moveq #0,d0 move.b routine(a0),d0 move.w Obj16_Index(pc,d0.w),d1 jmp Obj16_Index(pc,d1.w) ; =========================================================================== ; off_21DBA: Obj16_Index: offsetTable offsetTableEntry.w Obj16_Init ; 0 offsetTableEntry.w Obj16_Main ; 2 ; =========================================================================== ; loc_21DBE: Obj16_Init: addq.b #2,routine(a0) move.l #Obj16_MapUnc_21F14,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_HtzZipline,2,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo14_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$20,width_pixels(a0) move.b #0,mapping_frame(a0) move.b #1,priority(a0) move.w x_pos(a0),objoff_30(a0) move.w y_pos(a0),objoff_32(a0) move.b #$40,y_radius(a0) bset #4,render_flags(a0) moveq #0,d0 move.b subtype(a0),d0 lsl.w #3,d0 move.w d0,objoff_34(a0) ; loc_21E10: Obj16_Main: move.w x_pos(a0),-(sp) bsr.w Obj16_RunSecondaryRoutine moveq #0,d1 move.b width_pixels(a0),d1 move.w #-$28,d3 move.w (sp)+,d4 jsrto (PlatformObject).l, JmpTo3_PlatformObject jmpto (MarkObjGone).l, JmpTo5_MarkObjGone ; =========================================================================== ; loc_21E2C: Obj16_RunSecondaryRoutine: moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj16_Main_States(pc,d0.w),d1 jmp Obj16_Main_States(pc,d1.w) ; =========================================================================== ; off_21E3A: Obj16_Main_States: offsetTable offsetTableEntry.w Obj16_Wait ; 0 offsetTableEntry.w Obj16_Slide ; 2 offsetTableEntry.w Obj16_Fall ; 4 ; =========================================================================== ; loc_21E40: Obj16_Wait: move.b status(a0),d0 ; get the status flags andi.b #standing_mask,d0 ; is one of the players standing on it? beq.s ++ ; if not, branch addq.b #2,routine_secondary(a0) move.w #$200,x_vel(a0) btst #0,status(a0) beq.s + neg.w x_vel(a0) + move.w #$100,y_vel(a0) + rts ; =========================================================================== ; loc_21E68: Obj16_Slide: move.w (Timer_frames).w,d0 andi.w #$F,d0 ; play the sound only every 16 frames bne.s + move.w #SndID_HTZLiftClick,d0 jsr (PlaySound).l + jsrto (ObjectMove).l, JmpTo4_ObjectMove subq.w #1,objoff_34(a0) bne.s + ; rts addq.b #2,routine_secondary(a0) move.b #2,mapping_frame(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) jsrto (SingleObjLoad2).l, JmpTo4_SingleObjLoad2 bne.s + ; rts _move.b #ObjID_Scenery,id(a1) ; load obj1C move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b render_flags(a0),render_flags(a1) move.b #6,subtype(a1) + rts ; =========================================================================== ; loc_21EC2: Obj16_Fall: jsrto (ObjectMove).l, JmpTo4_ObjectMove addi.w #$38,y_vel(a0) move.w (Camera_Max_Y_pos_now).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 bhs.s +++ ; rts move.b status(a0),d0 andi.b #standing_mask,d0 beq.s ++ bclr #p1_standing_bit,status(a0) beq.s + bclr #3,(MainCharacter+status).w bset #1,(MainCharacter+status).w + bclr #p2_standing_bit,status(a0) beq.s + bclr #3,(Sidekick+status).w bset #1,(Sidekick+status).w + move.w #$4000,x_pos(a0) + rts ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj16_MapUnc_21F14: BINCLUDE "mappings/sprite/obj16.bin" ; =========================================================================== if ~~removeJmpTos JmpTo5_MarkObjGone jmp (MarkObjGone).l JmpTo4_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo14_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo3_PlatformObject jmp (PlatformObject).l ; loc_22010: JmpTo4_ObjectMove jmp (ObjectMove).l align 4 else dc.b $01,$02,$1E,$42 ; ??? (unused) endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 19 - Platform from CPZ, OOZ and WFZ ; ---------------------------------------------------------------------------- ; Sprite_22018: Obj19: moveq #0,d0 move.b routine(a0),d0 move.w Obj19_Index(pc,d0.w),d1 jmp Obj19_Index(pc,d1.w) ; =========================================================================== ; off_22026: Obj19_States: Obj19_Index: offsetTable offsetTableEntry.w Obj19_Init ; 0 offsetTableEntry.w Obj19_Main ; 2 ; --------------------------------------------------------------------------- ; word_2202A: Obj19_SubtypeProperties: ; width_pixels ; mapping_frame dc.b $20, 0 dc.b $18, 1 dc.b $40, 2 dc.b $20, 3 ; =========================================================================== ; loc_22032: Obj19_Init: addq.b #2,routine(a0) ; => Obj19_Main move.l #Obj19_MapUnc_2222A,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CPZElevator,3,0),art_tile(a0) ; set default art cmpi.b #oil_ocean_zone,(Current_Zone).w ; are we in OOZ? bne.s + ; if not, branch move.w #make_art_tile(ArtTile_ArtNem_OOZElevator,3,0),art_tile(a0) ; set OOZ art + cmpi.b #wing_fortress_zone,(Current_Zone).w ; are we in WFZ? bne.s + ; if not, branch move.w #make_art_tile(ArtTile_ArtNem_WfzFloatingPlatform,1,1),art_tile(a0) ; set WTZ art + jsrto (Adjust2PArtPointer).l, JmpTo15_Adjust2PArtPointer move.b #4,render_flags(a0) moveq #0,d0 move.b subtype(a0),d0 lsr.w #3,d0 andi.w #$1E,d0 lea Obj19_SubtypeProperties(pc,d0.w),a2 move.b (a2)+,width_pixels(a0) move.b (a2)+,mapping_frame(a0) move.b #4,priority(a0) move.w x_pos(a0),objoff_30(a0) move.w y_pos(a0),objoff_32(a0) andi.b #$F,subtype(a0) cmpi.b #3,subtype(a0) bne.s loc_220AA btst #0,status(a0) bne.s loc_220B2 loc_220AA: cmpi.b #7,subtype(a0) bne.s Obj19_Main loc_220B2: subi.w #$C0,y_pos(a0) ; loc_220B8: Obj19_Main: move.w x_pos(a0),-(sp) bsr.w Obj19_Move moveq #0,d1 move.b width_pixels(a0),d1 move.w #$11,d3 move.w (sp)+,d4 jsrto (PlatformObject).l, JmpTo4_PlatformObject move.w objoff_30(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w JmpTo20_DeleteObject jmpto (DisplaySprite).l, JmpTo11_DisplaySprite ; --------------------------------------------------------------------------- ; loc_220E8: Obj19_Move: moveq #0,d0 move.b subtype(a0),d0 andi.w #$F,d0 add.w d0,d0 move.w Obj19_MoveTypes(pc,d0.w),d1 jmp Obj19_MoveTypes(pc,d1.w) ; =========================================================================== ; platform movement routine table ; off_220FC: Obj19_MoveTypes:offsetTable offsetTableEntry.w Obj19_MoveRoutine1 ; 0 offsetTableEntry.w Obj19_MoveRoutine2 ; 1 offsetTableEntry.w Obj19_MoveRoutine3 ; 2 offsetTableEntry.w Obj19_MoveRoutine4 ; 3 offsetTableEntry.w Obj19_MoveRoutine5 ; 4 offsetTableEntry.w Obj19_MoveRoutineNull ; 5 offsetTableEntry.w Obj19_MoveRoutine6 ; 6 offsetTableEntry.w Obj19_MoveRoutine6 ; 7 offsetTableEntry.w Obj19_MoveRoutine7 ; 8 offsetTableEntry.w Obj19_MoveRoutine7 ; 9 offsetTableEntry.w Obj19_MoveRoutine7 ; $A offsetTableEntry.w Obj19_MoveRoutine7 ; $B offsetTableEntry.w Obj19_MoveRoutine8 ; $C offsetTableEntry.w Obj19_MoveRoutine8 ; $D offsetTableEntry.w Obj19_MoveRoutine8 ; $E offsetTableEntry.w Obj19_MoveRoutine8 ; $F ; =========================================================================== ; loc_2211C: Obj19_MoveRoutine1: move.b (Oscillating_Data+8).w,d0 move.w #$40,d1 bra.s Obj19_MoveRoutine2_Part2 ; =========================================================================== ; loc_22126: Obj19_MoveRoutine2: move.b (Oscillating_Data+$C).w,d0 move.w #$60,d1 ; loc_2212E: Obj19_MoveRoutine2_Part2: btst #0,status(a0) beq.s + neg.w d0 add.w d1,d0 + move.w objoff_30(a0),d1 sub.w d0,d1 move.w d1,x_pos(a0) rts ; =========================================================================== ; loc_22146: Obj19_MoveRoutine3: move.b (Oscillating_Data+$1C).w,d0 move.w #$80,d1 btst #0,status(a0) beq.s + neg.w d0 add.w d1,d0 + move.w objoff_32(a0),d1 sub.w d0,d1 move.w d1,y_pos(a0) rts ; =========================================================================== ; loc_22166: Obj19_MoveRoutine4: move.b status(a0),d0 andi.b #standing_mask,d0 beq.s + ; rts addq.b #1,subtype(a0) + rts ; =========================================================================== ; loc_22176: Obj19_MoveRoutine5: jsrto (ObjectMove).l, JmpTo5_ObjectMove moveq #8,d1 move.w objoff_32(a0),d0 subi.w #$60,d0 cmp.w y_pos(a0),d0 bhs.s + neg.w d1 + add.w d1,y_vel(a0) bne.s Obj19_MoveRoutineNull addq.b #1,subtype(a0) ; return_22196: Obj19_MoveRoutineNull: rts ; =========================================================================== ; loc_22198: Obj19_MoveRoutine6: jsrto (ObjectMove).l, JmpTo5_ObjectMove moveq #8,d1 move.w objoff_32(a0),d0 subi.w #$60,d0 cmp.w y_pos(a0),d0 bhs.s + neg.w d1 + add.w d1,y_vel(a0) rts ; =========================================================================== ; loc_221B4: Obj19_MoveRoutine7: move.b (Oscillating_Data+$38).w,d1 subi.b #$40,d1 ext.w d1 move.b (Oscillating_Data+$3C).w,d2 subi.b #$40,d2 ext.w d2 btst #2,d0 beq.s + neg.w d1 neg.w d2 + btst #1,d0 beq.s + neg.w d1 exg d1,d2 + add.w objoff_30(a0),d1 move.w d1,x_pos(a0) add.w objoff_32(a0),d2 move.w d2,y_pos(a0) rts ; =========================================================================== ; loc_221EE: Obj19_MoveRoutine8: move.b (Oscillating_Data+$38).w,d1 subi.b #$40,d1 ext.w d1 move.b (Oscillating_Data+$3C).w,d2 subi.b #$40,d2 ext.w d2 btst #2,d0 beq.s + neg.w d1 neg.w d2 + btst #1,d0 beq.s + neg.w d1 exg d1,d2 + neg.w d1 add.w objoff_30(a0),d1 move.w d1,x_pos(a0) add.w objoff_32(a0),d2 move.w d2,y_pos(a0) rts ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj19_MapUnc_2222A: BINCLUDE "mappings/sprite/obj19.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo11_DisplaySprite jmp (DisplaySprite).l JmpTo20_DeleteObject jmp (DeleteObject).l JmpTo15_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo4_PlatformObject jmp (PlatformObject).l ; loc_222A4: JmpTo5_ObjectMove jmp (ObjectMove).l align 4 else JmpTo20_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 1B - Speed booster from CPZ ; ---------------------------------------------------------------------------- speedbooster_boostspeed = objoff_30 ; Sprite_222AC: Obj1B: moveq #0,d0 move.b routine(a0),d0 move.w Obj1B_Index(pc,d0.w),d1 jmp Obj1B_Index(pc,d1.w) ; =========================================================================== ; off_222BA: Obj1B_Index: offsetTable offsetTableEntry.w Obj1B_Init ; 0 offsetTableEntry.w Obj1B_Main ; 2 ; --------------------------------------------------------------------------- ; word_222BE: Obj1B_BoosterSpeeds: dc.w $1000 dc.w $A00 ; =========================================================================== ; loc_222C2: Obj1B_Init: addq.b #2,routine(a0) ; => Obj1B_Main move.l #Obj1B_MapUnc_223E2,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CPZBooster,3,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo16_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$20,width_pixels(a0) move.b #1,priority(a0) move.b subtype(a0),d0 andi.w #2,d0 move.w Obj1B_BoosterSpeeds(pc,d0.w),speedbooster_boostspeed(a0) ; loc_222F8: Obj1B_Main: move.b (Timer_frames+1).w,d0 andi.b #2,d0 move.b d0,mapping_frame(a0) move.w x_pos(a0),d0 move.w d0,d1 subi.w #$10,d0 addi.w #$10,d1 move.w y_pos(a0),d2 move.w d2,d3 subi.w #$10,d2 addi.w #$10,d3 lea (MainCharacter).w,a1 ; a1=character btst #1,status(a1) bne.s + move.w x_pos(a1),d4 cmp.w d0,d4 blo.w + cmp.w d1,d4 bhs.w + move.w y_pos(a1),d4 cmp.w d2,d4 blo.w + cmp.w d3,d4 bhs.w + move.w d0,-(sp) bsr.w Obj1B_GiveBoost move.w (sp)+,d0 + lea (Sidekick).w,a1 ; a1=character btst #1,status(a1) bne.s + move.w x_pos(a1),d4 cmp.w d0,d4 blo.w + cmp.w d1,d4 bhs.w + move.w y_pos(a1),d4 cmp.w d2,d4 blo.w + cmp.w d3,d4 bhs.w + bsr.w Obj1B_GiveBoost + jmpto (MarkObjGone).l, JmpTo6_MarkObjGone ; =========================================================================== ; sub_22388: Obj1B_GiveBoost: move.w x_vel(a1),d0 btst #0,status(a0) beq.s + neg.w d0 ; d0 = absolute value of character's x velocity + cmpi.w #$1000,d0 ; is the character already going super fast? bge.s Obj1B_GiveBoost_Done ; if yes, branch to not change the speed move.w speedbooster_boostspeed(a0),x_vel(a1) ; make the character go super fast bclr #0,status(a1) ; turn him right btst #0,status(a0) ; was that the correct direction? beq.s + ; if yes, branch bset #0,status(a1) ; turn him left neg.w x_vel(a1) ; make the boosting direction left + move.w #$F,move_lock(a1) ; don't let him turn around for a few frames move.w x_vel(a1),inertia(a1) ; update his inertia value bclr #5,status(a0) bclr #6,status(a0) bclr #5,status(a1) ; loc_223D8: Obj1B_GiveBoost_Done: move.w #SndID_Spring,d0 ; spring boing sound jmp (PlaySound).l ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj1B_MapUnc_223E2: BINCLUDE "mappings/sprite/obj1B.bin" ; =========================================================================== if ~~removeJmpTos JmpTo6_MarkObjGone jmp (MarkObjGone).l JmpTo16_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 1D - Blue balls in CPZ ; ---------------------------------------------------------------------------- ; Sprite_22408: Obj1D: moveq #0,d0 move.b routine(a0),d0 move.w Obj1D_Index(pc,d0.w),d1 jmp Obj1D_Index(pc,d1.w) ; =========================================================================== ; off_22416: Obj1D_States: Obj1D_Index: offsetTable offsetTableEntry.w Obj1D_Init ; 0 offsetTableEntry.w Obj1D_Wait ; 2 offsetTableEntry.w Obj1D_MoveArc ; 4 offsetTableEntry.w Obj1D_Wait ; 6 offsetTableEntry.w Obj1D_MoveStraight ; 8 ; --------------------------------------------------------------------------- ; unused table of speed values ; word_22420: dc.w -$480 dc.w -$500 dc.w -$600 dc.w -$700 ; =========================================================================== ; loc_22428: Obj1D_Init: addq.b #2,routine(a0) ; => Obj1D_Wait move.w #-$480,y_vel(a0) moveq #0,d1 move.b subtype(a0),d1 move.b d1,d0 andi.b #$F,d1 ; number of blue balls moveq #2,d5 ; routine number andi.b #$F0,d0 beq.s + moveq #6,d5 ; routine number + move.b status(a0),d4 moveq #0,d2 movea.l a0,a1 bra.s Obj1D_InitBall ; --------------------------------------------------------------------------- Obj1D_LoadBall: jsrto (SingleObjLoad2).l, JmpTo5_SingleObjLoad2 bne.s ++ ; loc_22458: Obj1D_InitBall: _move.b id(a0),id(a1) ; load obj1D move.b d5,routine(a1) ; => Obj1D_Wait (either one) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.l #Obj1D_MapUnc_22576,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_CPZDroplet,3,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo3_Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #3,priority(a1) move.b #%10001011,collision_flags(a1) move.w x_pos(a1),objoff_38(a1) move.w y_pos(a1),objoff_30(a1) move.w y_vel(a0),y_vel(a1) move.w y_vel(a1),objoff_34(a1) move.b #8,width_pixels(a1) move.w #$60,objoff_3A(a1) move.w #$B,objoff_36(a1) andi.b #1,d4 beq.s + neg.w objoff_36(a1) neg.w objoff_3A(a1) + move.w d2,objoff_32(a1) addq.w #3,d2 + dbf d1,Obj1D_LoadBall rts ; =========================================================================== ; loc_224D6: Obj1D_Wait: subq.w #1,objoff_32(a0) bpl.s BranchTo_JmpTo7_MarkObjGone addq.b #2,routine(a0) ; => Obj1D_MoveArc or Obj1D_MoveStraight move.w #$3B,objoff_32(a0) move.w #SndID_Gloop,d0 jsr (PlaySoundLocal).l BranchTo_JmpTo7_MarkObjGone jmpto (MarkObjGone).l, JmpTo7_MarkObjGone ; =========================================================================== ; loc_224F4: Obj1D_MoveArc: jsrto (ObjectMove).l, JmpTo6_ObjectMove move.w objoff_36(a0),d0 add.w d0,x_vel(a0) addi.w #$18,y_vel(a0) bne.s + neg.w objoff_36(a0) + move.w objoff_30(a0),d0 cmp.w y_pos(a0),d0 bhi.s BranchTo2_JmpTo7_MarkObjGone move.w objoff_34(a0),y_vel(a0) clr.w x_vel(a0) subq.b #2,routine(a0) ; => Obj1D_Wait BranchTo2_JmpTo7_MarkObjGone jmpto (MarkObjGone).l, JmpTo7_MarkObjGone ; =========================================================================== ; loc_22528: Obj1D_MoveStraight: jsrto (ObjectMove).l, JmpTo6_ObjectMove addi.w #$18,y_vel(a0) bne.s + move.w objoff_3A(a0),d0 add.w objoff_38(a0),d0 move.w d0,x_pos(a0) + cmpi.w #$180,y_vel(a0) bne.s + move.w #SndID_Gloop,d0 jsr (PlaySoundLocal).l + move.w objoff_30(a0),d0 cmp.w y_pos(a0),d0 bhi.s BranchTo3_JmpTo7_MarkObjGone move.w objoff_34(a0),y_vel(a0) move.w objoff_38(a0),x_pos(a0) move.w #SndID_Gloop,d0 jsr (PlaySoundLocal).l BranchTo3_JmpTo7_MarkObjGone jmpto (MarkObjGone).l, JmpTo7_MarkObjGone ; =========================================================================== ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj1D_MapUnc_22576: BINCLUDE "mappings/sprite/obj1D.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo7_MarkObjGone jmp (MarkObjGone).l JmpTo5_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo3_Adjust2PArtPointer2 jmp (Adjust2PArtPointer2).l ; loc_22596: JmpTo6_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 1E - Spin tube from CPZ ; ---------------------------------------------------------------------------- ; Sprite_2259C: Obj1E: moveq #0,d0 move.b routine(a0),d0 move.w Obj1E_Index(pc,d0.w),d1 jsr Obj1E_Index(pc,d1.w) move.b objoff_2C(a0),d0 add.b objoff_36(a0),d0 beq.w JmpTo_MarkObjGone3 rts if removeJmpTos JmpTo_MarkObjGone3 jmp (MarkObjGone3).l endif ; =========================================================================== ; JmpTbl_225B8: Obj1E_States: Obj1E_Index: offsetTable offsetTableEntry.w Obj1E_Init ; 0 offsetTableEntry.w Obj1E_Main ; 2 ; =========================================================================== word_225BC: dc.w $A0 ; 0 dc.w $100 ; 2 dc.w $120 ; 4 ; =========================================================================== ; loc_225C2: LoadSubtype_1E: Obj1E_Init: addq.b #2,routine(a0) move.b subtype(a0),d0 add.w d0,d0 andi.w #6,d0 move.w word_225BC(pc,d0.w),objoff_2A(a0) ; loc_225D6: Obj1E_Main: lea (MainCharacter).w,a1 ; a1=character lea objoff_2C(a0),a4 bsr.s + lea (Sidekick).w,a1 ; a1=character lea objoff_36(a0),a4 + moveq #0,d0 move.b (a4),d0 move.w Obj1E_Modes(pc,d0.w),d0 jmp Obj1E_Modes(pc,d0.w) ; =========================================================================== ; off_225F4: Obj1E_Modes: offsetTable offsetTableEntry.w loc_225FC ; 0 offsetTableEntry.w loc_2271A ; 2 offsetTableEntry.w loc_227FE ; 4 offsetTableEntry.w loc_2286A ; 6 ; =========================================================================== loc_225FC: tst.w (Debug_placement_mode).w bne.w return_22718 move.w objoff_2A(a0),d2 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 cmp.w d2,d0 bhs.w return_22718 move.w y_pos(a1),d1 sub.w y_pos(a0),d1 cmpi.w #$80,d1 bhs.w return_22718 cmpi.b #$20,anim(a1) beq.w return_22718 moveq #0,d3 cmpi.w #$A0,d2 beq.s + moveq #8,d3 cmpi.w #$120,d2 beq.s + moveq #4,d3 neg.w d0 addi.w #$100,d0 + cmpi.w #$80,d0 blo.s loc_2267E moveq #0,d2 move.b subtype(a0),d0 lsr.w #2,d0 andi.w #$F,d0 move.b byte_2266E(pc,d0.w),d2 cmpi.b #2,d2 bne.s loc_22688 move.b (Timer_second).w,d2 andi.b #1,d2 bra.s loc_22688 ; =========================================================================== byte_2266E: dc.b 2 dc.b 2 ; 1 dc.b 2 ; 2 dc.b 2 ; 3 dc.b 2 ; 4 dc.b 2 ; 5 dc.b 2 ; 6 dc.b 2 ; 7 dc.b 2 ; 8 dc.b 2 ; 9 dc.b 0 ; 10 dc.b 2 ; 11 dc.b 0 ; 12 dc.b 1 ; 13 dc.b 2 ; 14 dc.b 1 ; 15 ; =========================================================================== loc_2267E: moveq #2,d2 cmpi.w #$40,d1 bhs.s loc_22688 moveq #3,d2 loc_22688: move.b d2,1(a4) add.w d3,d2 add.w d2,d2 andi.w #$1E,d2 lea off_22980(pc),a2 adda.w (a2,d2.w),a2 move.w (a2)+,4(a4) subq.w #4,4(a4) move.w (a2)+,d4 add.w x_pos(a0),d4 move.w d4,x_pos(a1) move.w (a2)+,d5 add.w y_pos(a0),d5 move.w d5,y_pos(a1) move.l a2,6(a4) move.w (a2)+,d4 add.w x_pos(a0),d4 move.w (a2)+,d5 add.w y_pos(a0),d5 addq.b #2,(a4) move.b #$81,obj_control(a1) move.b #AniIDSonAni_Roll,anim(a1) move.w #$800,inertia(a1) move.w #0,x_vel(a1) move.w #0,y_vel(a1) bclr #5,status(a0) bclr #5,status(a1) bset #1,status(a1) move.b #0,jumping(a1) bclr #high_priority_bit,art_tile(a1) move.w #$800,d2 bsr.w loc_22902 move.w #SndID_Roll,d0 jsr (PlaySound).l return_22718: rts ; =========================================================================== loc_2271A: subq.b #1,2(a4) bpl.s Obj1E_MoveCharacter movea.l 6(a4),a2 move.w (a2)+,d4 add.w x_pos(a0),d4 move.w d4,x_pos(a1) move.w (a2)+,d5 add.w y_pos(a0),d5 move.w d5,y_pos(a1) tst.b 1(a4) bpl.s + subq.w #8,a2 + move.l a2,6(a4) subq.w #4,4(a4) beq.s loc_22784 move.w (a2)+,d4 add.w x_pos(a0),d4 move.w (a2)+,d5 add.w y_pos(a0),d5 move.w #$800,d2 bra.w loc_22902 ; =========================================================================== ; update the position of Sonic/Tails in the CPZ tube ; loc_2275E: Obj1E_MoveCharacter: move.l x_pos(a1),d2 move.l y_pos(a1),d3 move.w x_vel(a1),d0 ext.l d0 asl.l #8,d0 add.l d0,d2 move.w y_vel(a1),d0 ext.l d0 asl.l #8,d0 add.l d0,d3 move.l d2,x_pos(a1) move.l d3,y_pos(a1) rts ; =========================================================================== loc_22784: cmpi.b #4,1(a4) bhs.s loc_227A6 move.b subtype(a0),d0 andi.w #$FC,d0 add.b 1(a4),d0 move.b #4,1(a4) move.b byte_227BE(pc,d0.w),d0 bne.w loc_22892 loc_227A6: andi.w #$7FF,y_pos(a1) move.b #6,(a4) clr.b obj_control(a1) move.w #SndID_SpindashRelease,d0 jmp (PlaySound).l ; =========================================================================== byte_227BE: dc.b 2, 1, 0, 0 dc.b -1, 3, 0, 0 dc.b 4, -2, 0, 0 dc.b -3, -4, 0, 0 dc.b -5, -5, 0, 0 dc.b 7, 6, 0, 0 dc.b -7, -6, 0, 0 dc.b 8, 9, 0, 0 dc.b -8, -9, 0, 0 dc.b 11, 10, 0, 0 dc.b 12, 0, 0, 0 dc.b -11,-10, 0, 0 dc.b -12, 0, 0, 0 dc.b 0, 13, 0, 0 dc.b -13, 14, 0, 0 dc.b 0,-14, 0, 0 ; =========================================================================== loc_227FE: subq.b #1,2(a4) bpl.s Obj1E_MoveCharacter_2 movea.l 6(a4),a2 move.w (a2)+,d4 move.w d4,x_pos(a1) move.w (a2)+,d5 move.w d5,y_pos(a1) tst.b 1(a4) bpl.s loc_2281C subq.w #8,a2 loc_2281C: move.l a2,6(a4) subq.w #4,4(a4) beq.s loc_22858 move.w (a2)+,d4 move.w (a2)+,d5 move.w #$800,d2 bra.w loc_22902 ; =========================================================================== ; update the position of Sonic/Tails in the CPZ tube ; loc_22832: Obj1E_MoveCharacter_2: move.l x_pos(a1),d2 move.l y_pos(a1),d3 move.w x_vel(a1),d0 ext.l d0 asl.l #8,d0 add.l d0,d2 move.w y_vel(a1),d0 ext.l d0 asl.l #8,d0 add.l d0,d3 move.l d2,x_pos(a1) move.l d3,y_pos(a1) rts ; =========================================================================== loc_22858: andi.w #$7FF,y_pos(a1) clr.b (a4) move.w #SndID_SpindashRelease,d0 jmp (PlaySound).l ; =========================================================================== loc_2286A: move.w objoff_2A(a0),d2 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 cmp.w d2,d0 bhs.w loc_2288E move.w y_pos(a1),d1 sub.w y_pos(a0),d1 cmpi.w #$80,d1 bhs.w loc_2288E rts ; =========================================================================== loc_2288E: clr.b (a4) rts ; =========================================================================== loc_22892: bpl.s loc_228C4 neg.b d0 move.b #-4,1(a4) add.w d0,d0 lea (off_22E88).l,a2 adda.w (a2,d0.w),a2 move.w (a2)+,d0 subq.w #4,d0 move.w d0,4(a4) lea (a2,d0.w),a2 move.w (a2)+,d4 move.w d4,x_pos(a1) move.w (a2)+,d5 move.w d5,y_pos(a1) subq.w #8,a2 bra.s loc_228E4 ; =========================================================================== loc_228C4: add.w d0,d0 lea (off_22E88).l,a2 adda.w (a2,d0.w),a2 move.w (a2)+,4(a4) subq.w #4,4(a4) move.w (a2)+,d4 move.w d4,x_pos(a1) move.w (a2)+,d5 move.w d5,y_pos(a1) loc_228E4: move.l a2,6(a4) move.w (a2)+,d4 move.w (a2)+,d5 move.w #$800,d2 bsr.w loc_22902 move.w #SndID_Roll,d0 jsr (PlaySound).l addq.b #2,(a4) rts ; =========================================================================== loc_22902: moveq #0,d0 move.w d2,d3 move.w d4,d0 sub.w x_pos(a1),d0 bge.s + neg.w d0 neg.w d2 + moveq #0,d1 move.w d5,d1 sub.w y_pos(a1),d1 bge.s + neg.w d1 neg.w d3 + cmp.w d0,d1 blo.s loc_22952 moveq #0,d1 move.w d5,d1 sub.w y_pos(a1),d1 swap d1 divs.w d3,d1 moveq #0,d0 move.w d4,d0 sub.w x_pos(a1),d0 beq.s + swap d0 divs.w d1,d0 + move.w d0,x_vel(a1) move.w d3,y_vel(a1) abs.w d1 move.w d1,2(a4) rts ; =========================================================================== loc_22952: moveq #0,d0 move.w d4,d0 sub.w x_pos(a1),d0 swap d0 divs.w d2,d0 moveq #0,d1 move.w d5,d1 sub.w y_pos(a1),d1 beq.s + swap d1 divs.w d0,d1 + move.w d1,y_vel(a1) move.w d2,x_vel(a1) abs.w d0 move.w d0,2(a4) rts ; =========================================================================== obj1E67Size macro {INTLABEL} __LABEL__ label * dc.w __LABEL___End-__LABEL__-2 endm ; ------------------------------------------------------------------------------- ; spin tube data - entry/exit ; ------------------------------------------------------------------------------- ; off_22980: include "misc/obj1E_a.asm" ; ------------------------------------------------------------------------------- ; spin tube data - main tube ; ------------------------------------------------------------------------------- ; off_22E88: include "misc/obj1E_b.asm" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo_MarkObjGone3 jmp (MarkObjGone3).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 20 - Lava bubble from Hill Top Zone (boss weapon) ; ---------------------------------------------------------------------------- ; Sprite_22FF8: Obj20: moveq #0,d0 move.b routine(a0),d0 move.w Obj20_Index(pc,d0.w),d1 jmp Obj20_Index(pc,d1.w) ; =========================================================================== ; off_23006: Obj20_Index: offsetTable offsetTableEntry.w Obj20_Init ; 0 offsetTableEntry.w loc_23076 ; 2 offsetTableEntry.w loc_23084 ; 4 offsetTableEntry.w loc_2311E ; 6 offsetTableEntry.w loc_23144 ; 8 offsetTableEntry.w loc_231D2 ; $A offsetTableEntry.w BranchTo_JmpTo21_DeleteObject ; $C ; =========================================================================== ; loc_23014: Obj20_Init: addq.b #2,routine(a0) move.b #8,y_radius(a0) move.b #8,x_radius(a0) move.l #Obj20_MapUnc_23254,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_HtzFireball,0,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo17_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #3,priority(a0) move.b #8,width_pixels(a0) move.w y_pos(a0),objoff_30(a0) moveq #0,d0 move.b subtype(a0),d0 lsl.w #3,d0 andi.w #$780,d0 neg.w d0 move.w d0,x_vel(a0) move.w d0,y_vel(a0) move.b subtype(a0),d0 andi.w #$F,d0 lsl.w #4,d0 move.w d0,objoff_32(a0) move.w d0,objoff_34(a0) loc_23076: lea (Ani_obj20).l,a1 jsrto (AnimateSprite).l, JmpTo4_AnimateSprite jmpto (MarkObjGone).l, JmpTo8_MarkObjGone ; =========================================================================== loc_23084: cmpi.b #5,anim_frame_duration(a0) bne.s loc_230B4 jsrto (SingleObjLoad2).l, JmpTo6_SingleObjLoad2 bne.s loc_230A6 bsr.s loc_230C2 jsrto (SingleObjLoad2).l, JmpTo6_SingleObjLoad2 bne.s loc_230A6 bsr.s loc_230C2 neg.w x_vel(a1) bset #0,render_flags(a1) loc_230A6: move.w #SndID_ArrowFiring,d0 jsr (PlaySound).l addq.b #2,routine(a0) loc_230B4: lea (Ani_obj20).l,a1 jsrto (AnimateSprite).l, JmpTo4_AnimateSprite jmpto (MarkObjGone).l, JmpTo8_MarkObjGone ; =========================================================================== loc_230C2: _move.b #ObjID_LavaBubble,id(a1) ; load obj20 move.b #8,routine(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w x_vel(a0),x_vel(a1) move.w y_vel(a0),y_vel(a1) move.b #8,y_radius(a1) move.b #8,x_radius(a1) move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) ori.b #4,render_flags(a1) move.b #3,priority(a1) move.b #8,width_pixels(a1) move.b #$8B,collision_flags(a1) move.w y_pos(a1),objoff_30(a1) rts ; =========================================================================== loc_2311E: subq.w #1,objoff_32(a0) bpl.s loc_23136 move.w objoff_34(a0),objoff_32(a0) move.b #2,routine(a0) move.w #1,anim(a0) loc_23136: lea (Ani_obj20).l,a1 jsrto (AnimateSprite).l, JmpTo4_AnimateSprite jmpto (MarkObjGone).l, JmpTo8_MarkObjGone ; =========================================================================== loc_23144: subq.b #1,anim_frame_duration(a0) bpl.s loc_2315A move.b #7,anim_frame_duration(a0) addq.b #1,mapping_frame(a0) andi.b #1,mapping_frame(a0) loc_2315A: jsrto (ObjectMove).l, JmpTo7_ObjectMove addi.w #$18,y_vel(a0) move.w (Camera_Max_Y_pos_now).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 bhs.s loc_23176 jmpto (DeleteObject).l, JmpTo21_DeleteObject ; =========================================================================== loc_23176: bclr #1,render_flags(a0) tst.w y_vel(a0) bmi.s BranchTo_JmpTo8_MarkObjGone bset #1,render_flags(a0) bsr.w ObjCheckFloorDist tst.w d1 bpl.s BranchTo_JmpTo8_MarkObjGone add.w d1,y_pos(a0) addq.b #2,routine(a0) move.b #2,anim(a0) move.b #4,mapping_frame(a0) move.w #0,y_vel(a0) move.l #Obj20_MapUnc_23294,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Buzzer_Fireball_1,0,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo17_Adjust2PArtPointer move.b #0,mapping_frame(a0) move.w #9,objoff_32(a0) move.b #3,objoff_36(a0) BranchTo_JmpTo8_MarkObjGone jmpto (MarkObjGone).l, JmpTo8_MarkObjGone ; =========================================================================== loc_231D2: subq.w #1,objoff_32(a0) bpl.s loc_23224 move.w #$7F,objoff_32(a0) subq.b #1,objoff_36(a0) bmi.s loc_23224 jsrto (SingleObjLoad2).l, JmpTo6_SingleObjLoad2 bne.s loc_23224 moveq #0,d0 move.w #bytesToLcnt(object_size),d1 loc_231F0: move.l (a0,d0.w),(a1,d0.w) addq.w #4,d0 dbf d1,loc_231F0 if object_size&3 move.w (a0,d0.w),(a1,d0.w) endif move.w #9,objoff_32(a1) move.w #$200,anim(a1) move.w #$E,d0 tst.w x_vel(a1) bpl.s loc_23214 neg.w d0 loc_23214: add.w d0,x_pos(a1) move.l a1,-(sp) bsr.w FireCheckFloorDist movea.l (sp)+,a1 ; a1=object add.w d1,y_pos(a1) loc_23224: lea (Ani_obj20).l,a1 jsrto (AnimateSprite).l, JmpTo4_AnimateSprite jmpto (MarkObjGone).l, JmpTo8_MarkObjGone ; =========================================================================== BranchTo_JmpTo21_DeleteObject jmpto (DeleteObject).l, JmpTo21_DeleteObject ; =========================================================================== ; animation script ; off_23236: Ani_obj20: offsetTable offsetTableEntry.w byte_2323C ; 0 offsetTableEntry.w byte_23243 ; 1 offsetTableEntry.w byte_23246 ; 2 byte_2323C: dc.b $B, 2, 3,$FC, 4,$FD, 1 rev02even byte_23243: dc.b $7F, 5,$FF rev02even byte_23246: dc.b 5, 4, 5, 2, 3, 0, 1, 0, 1, 2, 3, 4, 5,$FC even ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj20_MapUnc_23254: BINCLUDE "mappings/sprite/obj20_a.bin" ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj20_MapUnc_23294: BINCLUDE "mappings/sprite/obj20_b.bin" ; =========================================================================== if ~~removeJmpTos JmpTo21_DeleteObject jmp (DeleteObject).l JmpTo8_MarkObjGone jmp (MarkObjGone).l JmpTo6_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo4_AnimateSprite jmp (AnimateSprite).l JmpTo17_Adjust2PArtPointer jmp (Adjust2PArtPointer).l ; loc_232FA: JmpTo7_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 2F - Smashable ground in Hill Top Zone ; ---------------------------------------------------------------------------- ; Sprite_23300: Obj2F: moveq #0,d0 move.b routine(a0),d0 move.w Obj2F_Index(pc,d0.w),d1 jmp Obj2F_Index(pc,d1.w) ; =========================================================================== ; off_2330E: Obj2F_Index: offsetTable offsetTableEntry.w Obj2F_Init ; 0 offsetTableEntry.w Obj2F_Main ; 2 offsetTableEntry.w Obj2F_Fragment ; 4 ; =========================================================================== ; byte_23314: Obj2F_Properties: ; y_radius ; mapping_frame dc.b $24, 0 ; 0 dc.b $20, 2 ; 2 dc.b $18, 4 ; 4 dc.b $10, 6 ; 6 dc.b 8, 8 ; 8 ; =========================================================================== ; loc_2331E: Obj2F_Init: addq.b #2,routine(a0) move.l #Obj2F_MapUnc_236FA,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,2,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo18_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #4,priority(a0) moveq #0,d0 move.b subtype(a0),d0 andi.w #$1E,d0 lea Obj2F_Properties(pc,d0.w),a2 move.b (a2)+,y_radius(a0) move.b (a2)+,mapping_frame(a0) move.b #$20,y_radius(a0) bset #4,render_flags(a0) ; loc_23368: Obj2F_Main: move.w (Chain_Bonus_counter).w,objoff_38(a0) move.b (MainCharacter+anim).w,objoff_32(a0) move.b (Sidekick+anim).w,objoff_33(a0) moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsrto (SolidObject).l, JmpTo3_SolidObject move.b status(a0),d0 andi.b #standing_mask,d0 bne.s + BranchTo_JmpTo9_MarkObjGone jmpto (MarkObjGone).l, JmpTo9_MarkObjGone ; =========================================================================== + cmpi.b #standing_mask,d0 bne.s loc_23408 cmpi.b #AniIDSonAni_Roll,objoff_32(a0) bne.s loc_233C0 tst.b subtype(a0) bmi.s loc_233F0 cmpi.b #$E,(MainCharacter+top_solid_bit).w beq.s loc_233F0 loc_233C0: move.b #$C,(MainCharacter+top_solid_bit).w move.b #$D,(MainCharacter+lrb_solid_bit).w cmpi.b #AniIDSonAni_Roll,objoff_33(a0) bne.s loc_233E2 tst.b subtype(a0) bmi.s loc_233F0 cmpi.b #$E,(Sidekick+top_solid_bit).w beq.s loc_233F0 loc_233E2: move.b #$C,(Sidekick+top_solid_bit).w move.b #$D,(Sidekick+lrb_solid_bit).w bra.s BranchTo_JmpTo9_MarkObjGone ; =========================================================================== loc_233F0: lea (MainCharacter).w,a1 ; a1=character move.b objoff_32(a0),d0 bsr.s loc_2343E lea (Sidekick).w,a1 ; a1=character move.b objoff_33(a0),d0 bsr.s loc_2343E bra.w loc_234A4 ; =========================================================================== loc_23408: move.b d0,d1 andi.b #p1_standing,d1 beq.s loc_23470 cmpi.b #AniIDSonAni_Roll,objoff_32(a0) bne.s loc_23426 tst.b subtype(a0) bmi.s loc_23436 cmpi.b #$E,(MainCharacter+top_solid_bit).w beq.s loc_23436 loc_23426: move.b #$C,(MainCharacter+top_solid_bit).w move.b #$D,(MainCharacter+lrb_solid_bit).w bra.w BranchTo_JmpTo9_MarkObjGone ; =========================================================================== loc_23436: lea (MainCharacter).w,a1 ; a1=character bsr.s loc_23444 bra.s loc_234A4 ; =========================================================================== loc_2343E: cmpi.b #AniIDSonAni_Roll,d0 bne.s loc_2345C loc_23444: bset #2,status(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #AniIDSonAni_Roll,anim(a1) loc_2345C: bset #1,status(a1) bclr #3,status(a1) move.b #2,routine(a1) rts ; =========================================================================== loc_23470: andi.b #p2_standing,d0 beq.w BranchTo_JmpTo9_MarkObjGone cmpi.b #AniIDSonAni_Roll,objoff_33(a0) bne.s loc_2348E tst.b subtype(a0) bmi.s loc_2349E cmpi.b #$E,(Sidekick+top_solid_bit).w beq.s loc_2349E loc_2348E: move.b #$C,(Sidekick+top_solid_bit).w move.b #$D,(Sidekick+lrb_solid_bit).w bra.w BranchTo_JmpTo9_MarkObjGone ; =========================================================================== loc_2349E: lea (Sidekick).w,a1 ; a1=character bsr.s loc_23444 loc_234A4: move.w objoff_38(a0),(Chain_Bonus_counter).w andi.b #~standing_mask,status(a0) lea (byte_234F2).l,a4 moveq #0,d0 move.b mapping_frame(a0),d0 addq.b #1,mapping_frame(a0) move.l d0,d1 add.w d0,d0 add.w d0,d0 lea (a4,d0.w),a4 neg.w d1 addi.w #9,d1 move.w #$18,d2 jsrto (BreakObjectToPieces).l, JmpTo_BreakObjectToPieces bsr.w SmashableObject_LoadPoints ; loc_234DC: Obj2F_Fragment: jsrto (ObjectMove).l, JmpTo8_ObjectMove addi.w #$18,y_vel(a0) tst.b render_flags(a0) bpl.w JmpTo22_DeleteObject jmpto (DisplaySprite).l, JmpTo12_DisplaySprite ; =========================================================================== byte_234F2: dc.b $FF dc.b 0 ; 1 dc.b $F8 ; 2 dc.b 0 ; 3 dc.b 1 ; 4 dc.b 0 ; 5 dc.b $F8 ; 6 dc.b 0 ; 7 dc.b $FF ; 8 dc.b $20 ; 9 dc.b $F9 ; 10 dc.b 0 ; 11 dc.b 0 ; 12 dc.b $E0 ; 13 dc.b $F9 ; 14 dc.b 0 ; 15 dc.b $FF ; 16 dc.b $40 ; 17 dc.b $FA ; 18 dc.b 0 ; 19 dc.b 0 ; 20 dc.b $C0 ; 21 dc.b $FA ; 22 dc.b 0 ; 23 dc.b $FF ; 24 dc.b $60 ; 25 dc.b $FB ; 26 dc.b 0 ; 27 dc.b 0 ; 28 dc.b $A0 ; 29 dc.b $FB ; 30 dc.b 0 ; 31 dc.b $FF ; 32 dc.b $80 ; 33 dc.b $FC ; 34 dc.b 0 ; 35 dc.b 0 ; 36 dc.b $80 ; 37 dc.b $FC ; 38 dc.b 0 ; 39 ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 32 - Breakable block/rock from CPZ and HTZ ; ---------------------------------------------------------------------------- breakableblock_mainchar_anim = objoff_32 breakableblock_sidekick_anim = objoff_33 ; Sprite_2351A: Obj32: moveq #0,d0 move.b routine(a0),d0 move.w Obj32_Index(pc,d0.w),d1 jmp Obj32_Index(pc,d1.w) ; =========================================================================== ; off_23528: Obj32_Index: offsetTable offsetTableEntry.w Obj32_Init ; 0 offsetTableEntry.w Obj32_Main ; 2 offsetTableEntry.w Obj32_Fragment ; 4 ; =========================================================================== ; loc_2352E: Obj32_Init: addq.b #2,routine(a0) move.l #Obj32_MapUnc_23852,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_HtzRock,2,0),art_tile(a0) move.b #$18,width_pixels(a0) move.l #Obj32_VelArray1,objoff_3C(a0) cmpi.b #chemical_plant_zone,(Current_Zone).w bne.s + move.l #Obj32_MapUnc_23886,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CPZMetalBlock,3,0),art_tile(a0) move.b #$10,width_pixels(a0) move.l #Obj32_VelArray2,objoff_3C(a0) + jsrto (Adjust2PArtPointer).l, JmpTo18_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #4,priority(a0) ; loc_23582: Obj32_Main: move.w (Chain_Bonus_counter).w,objoff_38(a0) move.b (MainCharacter+anim).w,breakableblock_mainchar_anim(a0) move.b (Sidekick+anim).w,breakableblock_sidekick_anim(a0) moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 move.w #$10,d2 move.w #$11,d3 move.w x_pos(a0),d4 jsrto (SolidObject).l, JmpTo3_SolidObject move.b status(a0),d0 andi.b #standing_mask,d0 ; is at least one player standing on the object? bne.s Obj32_SupportingSomeone BranchTo2_JmpTo9_MarkObjGone jmpto (MarkObjGone).l, JmpTo9_MarkObjGone ; =========================================================================== ; loc_235BC: Obj32_SupportingSomeone: cmpi.b #standing_mask,d0 ; are BOTH players standing on the object? bne.s Obj32_SupportingOnePlayerOnly ; if not, branch cmpi.b #AniIDSonAni_Roll,breakableblock_mainchar_anim(a0) beq.s + cmpi.b #AniIDSonAni_Roll,breakableblock_sidekick_anim(a0) bne.s BranchTo2_JmpTo9_MarkObjGone + lea (MainCharacter).w,a1 ; a1=character move.b breakableblock_mainchar_anim(a0),d0 bsr.s Obj32_SetCharacterOffBlock lea (Sidekick).w,a1 ; a1=character move.b breakableblock_sidekick_anim(a0),d0 bsr.s Obj32_SetCharacterOffBlock bra.w Obj32_Destroy ; =========================================================================== ; loc_235EA: Obj32_SupportingOnePlayerOnly: move.b d0,d1 andi.b #p1_standing,d1 ; is the main character standing on the object? beq.s Obj32_SupportingSidekick ; if not, branch cmpi.b #AniIDSonAni_Roll,breakableblock_mainchar_anim(a0) bne.s BranchTo2_JmpTo9_MarkObjGone lea (MainCharacter).w,a1 ; a1=character bsr.s Obj32_BouncePlayer bra.s Obj32_Destroy ; =========================================================================== ; loc_23602: Obj32_SetCharacterOffBlock: cmpi.b #AniIDSonAni_Roll,d0 bne.s + ; loc_23608: Obj32_BouncePlayer: bset #2,status(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #AniIDSonAni_Roll,anim(a1) move.w #-$300,y_vel(a1) + bset #1,status(a1) bclr #3,status(a1) move.b #2,routine(a1) rts ; =========================================================================== ; loc_2363A: Obj32_SupportingSidekick: andi.b #p2_standing,d0 ; is the sidekick standing on the object? (at this point, it should...) beq.w BranchTo2_JmpTo9_MarkObjGone ; if, by miracle, he's not, branch cmpi.b #2,breakableblock_sidekick_anim(a0) bne.w BranchTo2_JmpTo9_MarkObjGone lea (Sidekick).w,a1 ; a1=character bsr.s Obj32_BouncePlayer ; loc_23652: Obj32_Destroy: move.w objoff_38(a0),(Chain_Bonus_counter).w andi.b #~standing_mask,status(a0) movea.l objoff_3C(a0),a4 jsrto (BreakObjectToPieces).l, JmpTo_BreakObjectToPieces bsr.w SmashableObject_LoadPoints ; loc_2366A: Obj32_Fragment: jsrto (ObjectMove).l, JmpTo8_ObjectMove addi.w #$18,y_vel(a0) tst.b render_flags(a0) bpl.w JmpTo22_DeleteObject jmpto (DisplaySprite).l, JmpTo12_DisplaySprite ; =========================================================================== ; velocity array for smashed bits, two words for each fragment ; byte_23680: Obj32_VelArray1: ; x_vel y_vel dc.w -$200,-$200 dc.w 0,-$280 dc.w $200,-$200 dc.w -$1C0,-$1C0 dc.w 0,-$200 dc.w $1C0,-$1C0 ;byte_23698: Obj32_VelArray2: ; x_vel y_vel dc.w -$100,-$200 dc.w $100,-$200 dc.w -$C0,-$1C0 dc.w $C0,-$1C0 ; =========================================================================== ; loc_236A8: SmashableObject_LoadPoints: jsrto (SingleObjLoad).l, JmpTo3_SingleObjLoad bne.s +++ ; rts _move.b #ObjID_Points,id(a1) ; load obj29 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w (Chain_Bonus_counter).w,d2 addq.w #2,(Chain_Bonus_counter).w cmpi.w #6,d2 blo.s + moveq #6,d2 + moveq #0,d0 move.w SmashableObject_ScoreBonus(pc,d2.w),d0 cmpi.w #$20,(Chain_Bonus_counter).w blo.s + move.w #1000,d0 moveq #$A,d2 + jsr (AddPoints).l lsr.w #1,d2 move.b d2,mapping_frame(a1) + rts ; =========================================================================== ; word_236F2: SmashableObject_ScoreBonus: dc.w 10 dc.w 20 ; 1 dc.w 50 ; 2 dc.w 100 ; 3 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj2F_MapUnc_236FA: BINCLUDE "mappings/sprite/obj2F.bin" ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj32_MapUnc_23852: BINCLUDE "mappings/sprite/obj32_a.bin" ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj32_MapUnc_23886: BINCLUDE "mappings/sprite/obj32_b.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo12_DisplaySprite jmp (DisplaySprite).l JmpTo22_DeleteObject jmp (DeleteObject).l JmpTo3_SingleObjLoad jmp (SingleObjLoad).l JmpTo9_MarkObjGone jmp (MarkObjGone).l JmpTo18_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo_BreakObjectToPieces jmp (BreakObjectToPieces).l JmpTo3_SolidObject jmp (SolidObject).l ; loc_238D6: JmpTo8_ObjectMove jmp (ObjectMove).l align 4 else JmpTo22_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 30 - Large rising lava during earthquake in HTZ ; ---------------------------------------------------------------------------- ; Sprite_238DC: Obj30: moveq #0,d0 move.b routine(a0),d0 move.w Obj30_Index(pc,d0.w),d1 jmp Obj30_Index(pc,d1.w) ; =========================================================================== ; off_238EA: Obj30_Index: offsetTable offsetTableEntry.w Obj30_Init ; 0 offsetTableEntry.w Obj30_Main ; 2 ; =========================================================================== ; byte_238EE: Obj30_Widths: dc.b $C0 dc.b 0 ; 1 dc.b $C0 ; 2 dc.b 0 ; 3 dc.b $C0 ; 4 dc.b 0 ; 5 dc.b $E0 ; 6 dc.b 0 ; 7 dc.b $C0 ; 8 dc.b 0 ; 9 ; =========================================================================== ; loc_238F8: Obj30_Init: addq.b #2,routine(a0) move.w y_pos(a0),objoff_32(a0) move.w x_pos(a0),objoff_30(a0) moveq #0,d0 move.b subtype(a0),d0 move.b Obj30_Widths(pc,d0.w),width_pixels(a0) cmpi.b #6,d0 blo.s Obj30_Main bne.s + cmpi.w #$380,(Camera_Y_pos).w bhs.s Obj30_Main bra.s ++ ; =========================================================================== + cmpi.w #$380,(Camera_Y_pos).w blo.s Obj30_Main + lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s + bclr #7,2(a2,d0.w) + jmpto (DeleteObject).l, JmpTo23_DeleteObject ; =========================================================================== ; loc_23944: Obj30_Main: move.w objoff_32(a0),d0 add.w (Camera_BG_Y_offset).w,d0 move.w d0,y_pos(a0) moveq #0,d0 move.b subtype(a0),d0 move.w Obj30_Modes(pc,d0.w),d1 jsr Obj30_Modes(pc,d1.w) tst.b (Screen_Shaking_Flag_HTZ).w beq.w JmpTo2_MarkObjGone3 rts ; =========================================================================== ; off_23968: Obj30_Modes: offsetTable offsetTableEntry.w loc_23972 ; 0 offsetTableEntry.w loc_23972 ; 2 offsetTableEntry.w loc_2398A ; 4 offsetTableEntry.w loc_239D0 ; 6 offsetTableEntry.w loc_239EA ; 8 ; =========================================================================== loc_23972: move.w #$CB,d1 move.w #$80,d2 move.w #$81,d3 move.w x_pos(a0),d4 jsrto (SolidObject_Always).l, JmpTo_SolidObject_Always jmpto (DropOnFloor).l, JmpTo_DropOnFloor ; =========================================================================== loc_2398A: move.w #$CB,d1 move.w #$78,d2 move.w #$79,d3 move.w x_pos(a0),d4 jsrto (SolidObject_Always).l, JmpTo_SolidObject_Always jsrto (DropOnFloor).l, JmpTo_DropOnFloor ; loc_239A2: Obj30_HurtSupportedPlayers: btst #p1_standing_bit,status(a0) beq.s + move.l a0,-(sp) movea.l a0,a1 lea (MainCharacter).w,a0 ; a0=character jsrto (Touch_ChkHurt).l, JmpTo_Touch_ChkHurt movea.l (sp)+,a0 ; load 0bj address + btst #p2_standing_bit,status(a0) beq.s + move.l a0,-(sp) movea.l a0,a1 lea (Sidekick).w,a0 ; a0=character jsrto (Touch_ChkHurt).l, JmpTo_Touch_ChkHurt movea.l (sp)+,a0 ; load 0bj address + rts ; =========================================================================== loc_239D0: move.w #$EB,d1 move.w #$78,d2 move.w #$79,d3 move.w x_pos(a0),d4 jsrto (SolidObject_Always).l, JmpTo_SolidObject_Always jsrto (DropOnFloor).l, JmpTo_DropOnFloor bra.s Obj30_HurtSupportedPlayers ; =========================================================================== loc_239EA: move.w #$CB,d1 move.w #$2E,d2 move.w x_pos(a0),d4 lea (Obj30_SlopeData).l,a2 jsrto (SlopedSolid).l, JmpTo_SlopedSolid jmpto (DropOnFloor).l, JmpTo_DropOnFloor ; =========================================================================== ;byte_23A04: Obj30_SlopeData: dc.b $30,$30,$30,$30,$30,$30,$30,$30,$2F,$2F,$2E,$2E,$2D,$2D,$2C,$2C dc.b $2B,$2B,$2A,$2A,$29,$29,$28,$28,$27,$27,$26,$26,$25,$25,$24,$24; 16 dc.b $23,$23,$22,$22,$21,$21,$20,$20,$1F,$1F,$1E,$1E,$1D,$1D,$1C,$1C; 32 dc.b $1B,$1B,$1A,$1A,$19,$19,$18,$18,$17,$17,$16,$16,$15,$15,$14,$14; 48 dc.b $13,$13,$12,$12,$11,$11,$10,$10, $F, $F, $E, $E, $D, $D, $C, $C; 64 dc.b $B, $B, $A, $A, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4; 80 dc.b 3, 3, 2, 2, 1, 1, 0, 0,$FF,$FF,$FE,$FE,$FD,$FD,$FC,$FC; 96 dc.b $FB,$FB,$FA,$FA,$F9,$F9,$F8,$F8,$F7,$F7,$F6,$F6,$F5,$F5,$F4,$F4; 112 dc.b $F3,$F3,$F2,$F2,$F1,$F1,$F0,$F0,$EF,$EF,$EE,$EE,$ED,$ED,$EC,$EC; 128 dc.b $EB,$EB,$EA,$EA,$E9,$E9,$E8,$E8,$E7,$E7,$E6,$E6,$E5,$E5,$E4,$E4; 144 dc.b $E3,$E3,$E2,$E2,$E1,$E1,$E0,$E0,$DF,$DF,$DE,$DE,$DD,$DD,$DC,$DC; 160 dc.b $DB,$DB,$DA,$DA,$D9,$D9,$D8,$D8,$D7,$D7,$D6,$D6,$D5,$D5,$D4,$D4; 176 dc.b $D3,$D3,$D2,$D2,$D1,$D1,$D0,$D0,$D0,$D0,$D0,$D0; 192 ; =========================================================================== if ~~removeJmpTos JmpTo23_DeleteObject jmp (DeleteObject).l JmpTo_Touch_ChkHurt jmp (Touch_ChkHurt).l JmpTo2_MarkObjGone3 jmp (MarkObjGone3).l JmpTo_DropOnFloor jmp (DropOnFloor).l JmpTo_SolidObject_Always jmp (SolidObject_Always).l JmpTo_SlopedSolid jmp (SlopedSolid).l align 4 else JmpTo2_MarkObjGone3 jmp (MarkObjGone3).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 33 - Green platform from OOZ ; ---------------------------------------------------------------------------- ; Sprite_23AF4: Obj33: moveq #0,d0 move.b routine(a0),d0 move.w Obj33_Index(pc,d0.w),d1 jmp Obj33_Index(pc,d1.w) ; =========================================================================== ; off_23B02: Obj33_Index: offsetTable offsetTableEntry.w Obj33_Init ; 0 offsetTableEntry.w Obj33_Main ; 2 offsetTableEntry.w Obj33_Flame ; 4 ; =========================================================================== ; loc_23B08: Obj33_Init: addq.b #2,routine(a0) move.l #Obj33_MapUnc_23DDC,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_BurnerLid,3,0),art_tile(a0) move.b #4,render_flags(a0) move.b #3,priority(a0) move.b #$18,width_pixels(a0) move.w y_pos(a0),objoff_30(a0) addq.b #2,routine_secondary(a0) move.w #$78,objoff_36(a0) tst.b subtype(a0) beq.s + move.b #4,routine_secondary(a0) + jsrto (SingleObjLoad2).l, JmpTo7_SingleObjLoad2 bne.s Obj33_Main _move.b id(a0),id(a1) ; load obj33 move.b #4,routine(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) subi.w #$10,y_pos(a1) move.l #Obj33_MapUnc_23DF0,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_OOZBurn,3,0),art_tile(a1) move.b #4,render_flags(a1) move.b #4,priority(a1) move.b #$10,width_pixels(a1) move.l a0,objoff_3C(a1) ; loc_23B90: Obj33_Main: move.w x_pos(a0),-(sp) moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj33_Modes(pc,d0.w),d1 jsr Obj33_Modes(pc,d1.w) move.w (sp)+,d4 moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #8,d2 move.w d2,d3 addq.w #1,d3 jsrto (SolidObject).l, JmpTo4_SolidObject jmpto (MarkObjGone).l, JmpTo10_MarkObjGone ; =========================================================================== ; off_23BBC: Obj33_Modes: offsetTable offsetTableEntry.w loc_23BC6 ; 0 offsetTableEntry.w loc_23BEA ; 2 offsetTableEntry.w loc_23C26 ; 4 offsetTableEntry.w loc_23D20 ; 6 offsetTableEntry.w return_23D98 ; 8 ; =========================================================================== loc_23BC6: subq.w #1,objoff_36(a0) bpl.s + ; rts move.w #$78,objoff_36(a0) move.l #-$96800,objoff_32(a0) addq.b #2,routine_secondary(a0) move.w #SndID_OOZLidPop,d0 jsr (PlaySoundLocal).l + rts ; =========================================================================== loc_23BEA: move.l y_pos(a0),d1 add.l objoff_32(a0),d1 move.l d1,y_pos(a0) addi.l #$3800,objoff_32(a0) swap d1 cmp.w objoff_30(a0),d1 blo.s ++ ; rts move.l objoff_32(a0),d0 cmpi.l #$10000,d0 bhs.s + subq.b #2,routine_secondary(a0) + lsr.l #2,d0 neg.l d0 move.l d0,objoff_32(a0) move.w objoff_30(a0),y_pos(a0) + rts ; =========================================================================== loc_23C26: move.w x_pos(a0),d2 move.w d2,d3 subi.w #$10,d2 addi.w #$10,d3 move.b status(a0),d0 andi.b #standing_mask,d0 beq.s ++ ; rts cmpi.b #standing_mask,d0 beq.s loc_23CA0 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 bsr.s + lea (Sidekick).w,a1 ; a1=character addq.b #1,d6 + btst d6,status(a0) beq.s + ; rts move.w x_pos(a1),d0 cmp.w d2,d0 blo.s + ; rts cmp.w d3,d0 bhs.s + ; rts move.b #1,obj_control(a1) move.w #0,inertia(a1) move.w #0,x_vel(a1) move.w #0,y_vel(a1) bclr #5,status(a1) bclr #high_priority_bit,art_tile(a1) move.l #-$96800,objoff_32(a0) addq.b #2,routine_secondary(a0) move.w #SndID_OOZLidPop,d0 jsr (PlaySoundLocal).l + rts ; =========================================================================== loc_23CA0: lea (MainCharacter).w,a1 ; a1=character move.w x_pos(a1),d0 cmp.w d2,d0 blo.s + ; rts cmp.w d3,d0 bhs.s + ; rts lea (Sidekick).w,a2 ; a2=character move.w x_pos(a2),d0 cmp.w d2,d0 blo.s + ; rts cmp.w d3,d0 bhs.s + ; rts move.b #1,obj_control(a1) move.w #0,inertia(a1) move.w #0,x_vel(a1) move.w #0,y_vel(a1) bclr #5,status(a1) bclr #high_priority_bit,art_tile(a1) move.b #1,obj_control(a2) move.w #0,inertia(a2) move.w #0,x_vel(a2) move.w #0,y_vel(a2) bclr #5,status(a2) bclr #high_priority_bit,art_tile(a2) move.l #-$96800,objoff_32(a0) addq.b #2,routine_secondary(a0) move.w #SndID_OOZLidPop,d0 jsr (PlaySoundLocal).l + rts ; =========================================================================== loc_23D20: move.l y_pos(a0),d1 add.l objoff_32(a0),d1 move.l d1,y_pos(a0) addi.l #$3800,objoff_32(a0) swap d1 move.w objoff_30(a0),d0 subi.w #$7D,d0 cmp.w d0,d1 bne.s + ; rts addq.b #2,routine_secondary(a0) lea (MainCharacter).w,a1 ; a1=character move.b status(a0),d0 andi.b #p1_standing,d0 bsr.s loc_23D60 lea (Sidekick).w,a1 ; a1=character move.b status(a0),d0 andi.b #p2_standing,d0 loc_23D60: beq.s + ; rts move.w x_pos(a0),x_pos(a1) move.b #AniIDSonAni_Roll,anim(a1) move.w #$800,inertia(a1) bset #1,status(a1) move.w #-$1000,y_vel(a1) bclr #3,status(a1) move.b #0,obj_control(a1) move.w #SndID_Spring,d0 jsr (PlaySoundLocal).l + rts ; =========================================================================== return_23D98: rts ; =========================================================================== ; loc_23D9A: Obj33_Flame: movea.l objoff_3C(a0),a1 ; a1=object move.w y_pos(a0),d0 sub.w y_pos(a1),d0 cmpi.w #$14,d0 blt.s Obj33_FlameOff move.b #$9B,collision_flags(a0) lea (Ani_obj33).l,a1 jsr (AnimateSprite).l jmpto (MarkObjGone).l, JmpTo10_MarkObjGone ; =========================================================================== ; loc_23DC2: Obj33_FlameOff: move.b #0,collision_flags(a0) move.b #0,anim_frame(a0) rts ; =========================================================================== ; animation script ; off_23DD0: Ani_obj33: offsetTable offsetTableEntry.w + ; 0 + dc.b 2, 2, 0, 2, 0, 2, 0, 1,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj33_MapUnc_23DDC: BINCLUDE "mappings/sprite/obj33_a.bin" ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj33_MapUnc_23DF0: BINCLUDE "mappings/sprite/obj33_b.bin" ; =========================================================================== if ~~removeJmpTos JmpTo10_MarkObjGone jmp (MarkObjGone).l JmpTo7_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo4_SolidObject jmp (SolidObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 43 - Sliding spike obstacle thing from OOZ ; ---------------------------------------------------------------------------- ; Sprite_23E40: Obj43: moveq #0,d0 move.b routine(a0),d0 move.w Obj43_Index(pc,d0.w),d1 jmp Obj43_Index(pc,d1.w) ; =========================================================================== ; off_23E4E: Obj43_Index: offsetTable offsetTableEntry.w Obj43_Init ; 0 offsetTableEntry.w loc_23F0A ; 2 offsetTableEntry.w loc_23F5C ; 4 ; --------------------------------------------------------------------------- byte_23E54: dc.b 0 dc.b $68 ; 1 dc.b 0 ; 2 dc.b 0 ; 3 dc.b 0 ; 4 dc.b 0 ; 5 dc.b 1 ; 6 dc.b $E8 ; 7 dc.b $FF ; 8 dc.b $E8 ; 9 dc.b 0 ; 10 dc.b $18 ; 11 dc.b 1 ; 12 dc.b $A8 ; 13 dc.b $FF ; 14 dc.b $A8 ; 15 dc.b $FF ; 16 dc.b $D8 ; 17 ; =========================================================================== ; loc_23E66: Obj43_Init: addq.b #2,routine(a0) move.w #make_art_tile(ArtTile_ArtNem_SpikyThing,2,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo19_Adjust2PArtPointer moveq #0,d1 move.b subtype(a0),d1 lea byte_23E54(pc,d1.w),a2 move.b (a2)+,d1 movea.l a0,a1 bra.s loc_23EA8 ; =========================================================================== loc_23E84: jsrto (SingleObjLoad2).l, JmpTo8_SingleObjLoad2 bne.s loc_23ED4 _move.b id(a0),id(a1) ; load obj43 move.b #4,routine(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b #1,objoff_36(a1) loc_23EA8: move.l #Obj43_MapUnc_23FE0,mappings(a1) move.w art_tile(a0),art_tile(a1) move.b #4,render_flags(a1) move.b #4,priority(a1) move.b #$18,width_pixels(a1) move.b #$A5,collision_flags(a1) move.w x_pos(a1),objoff_30(a1) loc_23ED4: dbf d1,loc_23E84 move.l a0,objoff_3C(a1) move.l a1,objoff_3C(a0) moveq #0,d1 move.b (a2)+,d1 move.w objoff_30(a0),d0 sub.w d1,d0 move.w d0,objoff_32(a0) move.w d0,objoff_32(a1) add.w d1,d0 add.w d1,d0 move.w d0,objoff_34(a0) move.w d0,objoff_34(a1) move.w (a2)+,d0 add.w d0,x_pos(a0) move.w (a2)+,d0 add.w d0,x_pos(a1) loc_23F0A: bsr.s loc_23F66 move.w objoff_32(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bls.s JmpTo13_DisplaySprite move.w objoff_34(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.s loc_23F36 JmpTo13_DisplaySprite jmp (DisplaySprite).l ; =========================================================================== loc_23F36: movea.l objoff_3C(a0),a1 ; a1=object cmpa.l a0,a1 beq.s loc_23F44 jsr (DeleteObject2).l loc_23F44: lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s JmpTo24_DeleteObject bclr #7,2(a2,d0.w) JmpTo24_DeleteObject jmp (DeleteObject).l ; =========================================================================== loc_23F5C: bsr.s loc_23F66 bsr.s loc_23FB0 jmp (DisplaySprite).l ; =========================================================================== loc_23F66: tst.b objoff_36(a0) bne.s loc_23F8E move.w x_pos(a0),d1 subq.w #1,d1 cmp.w objoff_32(a0),d1 bne.s loc_23F88 move.b #1,objoff_36(a0) move.w #SndID_SlidingSpike,d0 jsr (PlaySoundLocal).l loc_23F88: move.w d1,x_pos(a0) rts ; =========================================================================== loc_23F8E: move.w x_pos(a0),d1 addq.w #1,d1 cmp.w objoff_34(a0),d1 bne.s loc_23FAA move.b #0,objoff_36(a0) move.w #SndID_SlidingSpike,d0 jsr (PlaySoundLocal).l loc_23FAA: move.w d1,x_pos(a0) rts ; =========================================================================== loc_23FB0: movea.l objoff_3C(a0),a1 ; a1=object move.w x_pos(a0),d0 subi.w #$18,d0 move.w x_pos(a1),d2 addi.w #$18,d2 cmp.w d0,d2 bne.s return_23FDE eori.b #1,objoff_36(a0) eori.b #1,objoff_36(a1) move.w #SndID_SlidingSpike,d0 jsr (PlaySoundLocal).l return_23FDE: rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj43_MapUnc_23FE0: BINCLUDE "mappings/sprite/obj43.bin" ; =========================================================================== if ~~removeJmpTos JmpTo8_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo19_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 07 - Oil Ocean in OOZ ; ---------------------------------------------------------------------------- ; OST: oil_char1submersion = objoff_38 ; $38(a0) oil_char2submersion = objoff_3A ; $3A(a0) ; ---------------------------------------------------------------------------- ; Sprite_24020: Obj07: moveq #0,d0 move.b routine(a0),d0 move.w Obj07_Index(pc,d0.w),d1 jmp Obj07_Index(pc,d1.w) ; =========================================================================== ; off_2402E: Obj07_States: Obj07_Index: offsetTable offsetTableEntry.w Obj07_Init ; 0 offsetTableEntry.w Obj07_Main ; 2 ; =========================================================================== ; loc_24032: Obj07_Init: addq.b #2,routine(a0) ; => Obj07_Main move.w #$758,y_pos(a0) move.b #$20,width_pixels(a0) move.w y_pos(a0),objoff_30(a0) move.b #$30,oil_char1submersion(a0) bset #7,status(a0) ; loc_24054: Obj07_Main: ; check player 1 tst.w (Debug_placement_mode).w bne.w Obj07_End lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing,d1 move.b status(a0),d0 and.b d1,d0 bne.s Obj07_CheckKillChar1 cmpi.b #$30,oil_char1submersion(a0) beq.s Obj07_CheckSupportChar1 addq.b #1,oil_char1submersion(a0) bra.s Obj07_CheckSupportChar1 ; --------------------------------------------------------------------------- ; loc_24078: Obj07_CheckKillChar1: tst.b oil_char1submersion(a0) beq.s Obj07_SuffocateCharacter subq.b #1,oil_char1submersion(a0) ; loc_24082: Obj07_CheckSupportChar1: moveq #$20,d1 moveq #0,d3 move.b oil_char1submersion(a0),d3 moveq #p1_standing_bit,d6 move.w x_pos(a1),d4 move.w d4,x_pos(a0) jsrto (PlatformObject_SingleCharacter).l, JmpTo_PlatformObject_SingleCharacter ; stop the character from falling past the oil ; check player 2 lea (Sidekick).w,a1 ; a1=character moveq #p2_standing,d1 move.b status(a0),d0 and.b d1,d0 bne.s Obj07_CheckKillChar2 cmpi.b #$30,oil_char2submersion(a0) beq.s Obj07_CheckSupportChar2 addq.b #1,oil_char2submersion(a0) bra.s Obj07_CheckSupportChar2 ; --------------------------------------------------------------------------- ; loc_240B4: Obj07_CheckKillChar2: tst.b oil_char2submersion(a0) beq.s Obj07_SuffocateCharacter subq.b #1,oil_char2submersion(a0) ; loc_240BE: Obj07_CheckSupportChar2: moveq #$20,d1 moveq #0,d3 move.b oil_char2submersion(a0),d3 moveq #p2_standing_bit,d6 move.w x_pos(a1),d4 move.w d4,x_pos(a0) jsrto (PlatformObject_SingleCharacter).l, JmpTo_PlatformObject_SingleCharacter ; stop the character from falling past the oil rts ; --------------------------------------------------------------------------- ; loc_240D6: Obj07_SuffocateCharacter: not.b d1 and.b d1,status(a0) move.l a0,-(sp) movea.l a0,a2 movea.l a1,a0 jsrto (KillCharacter).l, JmpTo3_KillCharacter movea.l (sp)+,a0 ; load 0bj address Obj07_End: rts ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo3_KillCharacter jmp (KillCharacter).l JmpTo_PlatformObject_SingleCharacter jmp (PlatformObject_SingleCharacter).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 45 - Pressure spring from OOZ ; ---------------------------------------------------------------------------- ; Sprite_240F8: Obj45: moveq #0,d0 move.b routine(a0),d0 move.w Obj45_Index(pc,d0.w),d1 jsr Obj45_Index(pc,d1.w) jmpto (MarkObjGone).l, JmpTo11_MarkObjGone ; =========================================================================== ; off_2410A: Obj45_Index: offsetTable offsetTableEntry.w Obj45_Init ; 0 offsetTableEntry.w loc_24186 ; 2 offsetTableEntry.w loc_2427A ; 4 ; =========================================================================== ; loc_24110: Obj45_Init: addq.b #2,routine(a0) move.l #Obj45_MapUnc_2451A,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_PushSpring,2,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #4,priority(a0) move.b subtype(a0),d0 lsr.w #3,d0 andi.w #$E,d0 move.w Obj45_InitRoutines(pc,d0.w),d0 jmp Obj45_InitRoutines(pc,d0.w) ; =========================================================================== ; off_24146: Obj45_InitRoutines: offsetTable offsetTableEntry.w loc_2416E ; 0 offsetTableEntry.w loc_2414A ; 2 ; =========================================================================== loc_2414A: move.b #4,routine(a0) move.b #1,anim(a0) move.b #$A,mapping_frame(a0) move.w #make_art_tile(ArtTile_ArtNem_PushSpring,2,0),art_tile(a0) move.b #$14,width_pixels(a0) move.w x_pos(a0),objoff_34(a0) loc_2416E: move.b subtype(a0),d0 andi.w #2,d0 move.w word_24182(pc,d0.w),objoff_30(a0) jsrto (Adjust2PArtPointer).l, JmpTo20_Adjust2PArtPointer rts ; =========================================================================== word_24182: dc.w $F000 dc.w $F600 ; 1 ; =========================================================================== loc_24186: move.b status(a0),d0 andi.b #standing_mask,d0 bne.s loc_2419C tst.b objoff_32(a0) beq.s loc_241A8 subq.b #1,objoff_32(a0) bra.s loc_241A8 ; =========================================================================== loc_2419C: cmpi.b #9,objoff_32(a0) beq.s loc_241C6 addq.b #1,objoff_32(a0) loc_241A8: moveq #0,d3 move.b objoff_32(a0),d3 move.b d3,mapping_frame(a0) add.w d3,d3 move.w #$1B,d1 move.w #$14,d2 move.w x_pos(a0),d4 jsrto (SolidObject45).l, JmpTo_SolidObject45 rts ; =========================================================================== loc_241C6: lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 bsr.s loc_241D4 lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 loc_241D4: bclr d6,status(a0) beq.w return_24278 move.w objoff_30(a0),y_vel(a1) bset #1,status(a1) bclr #3,status(a1) move.b #AniIDSonAni_Spring,anim(a1) move.b #2,routine(a1) move.b subtype(a0),d0 bpl.s loc_24206 move.w #0,x_vel(a1) loc_24206: btst #0,d0 beq.s loc_24246 move.w #1,inertia(a1) move.b #1,flip_angle(a1) move.b #AniIDSonAni_Walk,anim(a1) move.b #0,flips_remaining(a1) move.b #4,flip_speed(a1) btst #1,d0 bne.s loc_24236 move.b #1,flips_remaining(a1) loc_24236: btst #0,status(a1) beq.s loc_24246 neg.b flip_angle(a1) neg.w inertia(a1) loc_24246: andi.b #$C,d0 cmpi.b #4,d0 bne.s loc_2425C move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) loc_2425C: cmpi.b #8,d0 bne.s loc_2426E move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_2426E: move.w #SndID_Spring,d0 jmp (PlaySound).l ; =========================================================================== return_24278: rts ; =========================================================================== loc_2427A: move.b #0,objoff_36(a0) move.w #$1F,d1 move.w #$C,d2 move.w #$D,d3 move.w x_pos(a0),d4 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) jsrto (SolidObject_Always_SingleCharacter).l, JmpTo_SolidObject_Always_SingleCharacter cmpi.w #1,d4 bne.s loc_242C0 move.b status(a0),d1 move.w x_pos(a0),d2 sub.w x_pos(a1),d2 bcs.s loc_242B6 eori.b #1,d1 loc_242B6: andi.b #1,d1 bne.s loc_242C0 bsr.w loc_2433C loc_242C0: movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 jsrto (SolidObject_Always_SingleCharacter).l, JmpTo_SolidObject_Always_SingleCharacter cmpi.w #1,d4 bne.s loc_242EE move.b status(a0),d1 move.w x_pos(a0),d2 sub.w x_pos(a1),d2 bcs.s loc_242E6 eori.b #1,d1 loc_242E6: andi.b #1,d1 bne.s loc_242EE bsr.s loc_2433C loc_242EE: tst.b objoff_36(a0) bne.s return_2433A move.w objoff_34(a0),d0 cmp.w x_pos(a0),d0 beq.s return_2433A bhs.s loc_2431C subq.b #4,mapping_frame(a0) subq.w #4,x_pos(a0) cmp.w x_pos(a0),d0 blo.s loc_24336 move.b #$A,mapping_frame(a0) move.w objoff_34(a0),x_pos(a0) bra.s loc_24336 ; =========================================================================== loc_2431C: subq.b #4,mapping_frame(a0) addq.w #4,x_pos(a0) cmp.w x_pos(a0),d0 bhs.s loc_24336 move.b #$A,mapping_frame(a0) move.w objoff_34(a0),x_pos(a0) loc_24336: bsr.w loc_243D0 return_2433A: rts ; =========================================================================== loc_2433C: btst #0,status(a0) beq.s loc_24378 btst #0,status(a1) bne.w return_243CE tst.w d0 bne.w loc_2435E tst.w inertia(a1) beq.s return_243CE bpl.s loc_243C8 bra.s return_243CE ; =========================================================================== loc_2435E: move.w objoff_34(a0),d0 addi.w #$12,d0 cmp.w x_pos(a0),d0 beq.s loc_243C8 addq.w #1,x_pos(a0) moveq #1,d0 move.w #$40,d1 bra.s loc_243A6 ; =========================================================================== loc_24378: btst #0,status(a1) beq.s return_243CE tst.w d0 bne.w loc_2438E tst.w inertia(a1) bmi.s loc_243C8 bra.s return_243CE ; =========================================================================== loc_2438E: move.w objoff_34(a0),d0 subi.w #$12,d0 cmp.w x_pos(a0),d0 beq.s loc_243C8 subq.w #1,x_pos(a0) moveq #-1,d0 move.w #-$40,d1 loc_243A6: add.w d0,x_pos(a1) move.w d1,inertia(a1) move.w #0,x_vel(a1) move.w objoff_34(a0),d0 sub.w x_pos(a0),d0 bcc.s loc_243C0 neg.w d0 loc_243C0: addi.w #$A,d0 move.b d0,mapping_frame(a0) loc_243C8: move.b #1,objoff_36(a0) return_243CE: rts ; =========================================================================== loc_243D0: move.b status(a0),d0 andi.b #pushing_mask,d0 beq.w return_244D0 lea (MainCharacter).w,a1 ; a1=character moveq #p1_pushing_bit,d6 bsr.s loc_243EA lea (Sidekick).w,a1 ; a1=character moveq #p2_pushing_bit,d6 loc_243EA: bclr d6,status(a0) beq.w return_244D0 move.w objoff_34(a0),d0 sub.w x_pos(a0),d0 bcc.s loc_243FE neg.w d0 loc_243FE: addi.w #$A,d0 lsl.w #7,d0 neg.w d0 move.w d0,x_vel(a1) subq.w #4,x_pos(a1) bset #0,status(a1) btst #0,status(a0) bne.s loc_2442C bclr #0,status(a1) addi_.w #8,x_pos(a1) neg.w x_vel(a1) loc_2442C: move.w #$F,move_lock(a1) move.w x_vel(a1),inertia(a1) btst #2,status(a1) bne.s loc_24446 move.b #AniIDSonAni_Walk,anim(a1) loc_24446: move.b subtype(a0),d0 bpl.s loc_24452 move.w #0,y_vel(a1) loc_24452: btst #0,d0 beq.s loc_24492 move.w #1,inertia(a1) move.b #1,flip_angle(a1) move.b #AniIDSonAni_Walk,anim(a1) move.b #1,flips_remaining(a1) move.b #8,flip_speed(a1) btst #1,d0 bne.s loc_24482 move.b #3,flips_remaining(a1) loc_24482: btst #0,status(a1) beq.s loc_24492 neg.b flip_angle(a1) neg.w inertia(a1) loc_24492: andi.b #$C,d0 cmpi.b #4,d0 bne.s loc_244A8 move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) loc_244A8: cmpi.b #8,d0 bne.s loc_244BA move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_244BA: bclr #5,status(a1) move.b #AniIDSonAni_Run,next_anim(a1) move.w #SndID_Spring,d0 ; play spring bounce sound jmp (PlaySound).l ; =========================================================================== return_244D0: rts ; =========================================================================== ; off_244D2: ; Unused animation script Ani_obj45: offsetTable offsetTableEntry.w byte_244D6 ; 0 offsetTableEntry.w byte_244F8 ; 1 byte_244D6: dc.b 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9 dc.b 9, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0; 16 dc.b 0,$FF ; 32 byte_244F8: dc.b 0, $A, $B, $C, $D, $E, $F,$10,$11,$12,$13,$13,$13,$13,$13,$13 dc.b $13,$13,$12,$11,$10, $F, $E, $D, $C, $B, $A, $A, $A, $A, $A, $A; 16 dc.b $A,$FF ; 32 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj45_MapUnc_2451A: BINCLUDE "mappings/sprite/obj45.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 46 - Ball from OOZ (unused, beta leftover) ; ---------------------------------------------------------------------------- ; Sprite_24A16: Obj46: moveq #0,d0 move.b routine(a0),d0 move.w Obj46_Index(pc,d0.w),d1 jmp Obj46_Index(pc,d1.w) ; =========================================================================== ; off_24A24: Obj46_Index: offsetTable offsetTableEntry.w Obj46_Init ; 0 - Init offsetTableEntry.w Obj46_Inactive ; 2 - Ball inactive offsetTableEntry.w Obj46_Moving ; 4 - Ball moving offsetTableEntry.w Obj46_PressureSpring ; 6 - Pressure Spring ; =========================================================================== ; loc_24A2C: Obj46_Init: lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s + bclr #7,2(a2,d0.w) bset #0,2(a2,d0.w) bne.w JmpTo25_DeleteObject + ; loads the ball itself addq.b #2,routine(a0) move.b #$F,y_radius(a0) move.b #$F,x_radius(a0) move.l #Obj46_MapUnc_24C52,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_BallThing,3,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo20_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #3,priority(a0) move.w x_pos(a0),objoff_34(a0) move.w y_pos(a0),objoff_36(a0) move.b #$10,width_pixels(a0) move.b #0,mapping_frame(a0) move.w #0,objoff_14(a0) move.b #1,objoff_1F(a0) ; Obj46_InitPressureSpring: ; loads the spring under the ball jsrto (SingleObjLoad).l, JmpTo4_SingleObjLoad bne.s + _move.b #ObjID_OOZBall,id(a1) ; load obj46 addq.b #6,routine(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$12,y_pos(a1) move.l #Obj45_MapUnc_2451A,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_PushSpring,2,0),art_tile(a1) ori.b #4,render_flags(a1) move.b #$10,width_pixels(a1) move.b #4,priority(a1) move.b #9,mapping_frame(a1) move.l a0,objoff_3C(a1) + move.l a1,objoff_3C(a0) ; loc_24AEA: Obj46_Inactive: btst #button_A,(Ctrl_2_Press).w bne.s + lea (ButtonVine_Trigger).w,a2 moveq #0,d0 move.b subtype(a0),d0 lsr.w #4,d0 tst.b (a2,d0.w) beq.s ++ + addq.b #2,routine(a0) bset #1,status(a0) move.w #-$300,y_vel(a0) move.w #$100,objoff_14(a0) movea.l objoff_3C(a0),a1 ; a1=object move.b #1,objoff_30(a1) btst #0,status(a0) beq.s + neg.w objoff_14(a0) + bsr.w loc_24BF0 jmpto (MarkObjGone).l, JmpTo11_MarkObjGone ; =========================================================================== ; loc_24B38: Obj46_Moving: move.w x_pos(a0),-(sp) jsrto (ObjectMove).l, JmpTo9_ObjectMove btst #1,status(a0) beq.s loc_24B8C addi.w #$18,y_vel(a0) bmi.s + move.w (Camera_Max_Y_pos_now).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 blo.s loc_24BC4 jsr (ObjCheckFloorDist).l tst.w d1 bpl.w + add.w d1,y_pos(a0) clr.w y_vel(a0) bclr #1,status(a0) move.w #$100,x_vel(a0) btst #0,status(a0) beq.s + neg.w x_vel(a0) + bra.s loc_24BA4 ; =========================================================================== loc_24B8C: jsr (ObjCheckFloorDist).l cmpi.w #8,d1 blt.s loc_24BA0 bset #1,status(a0) bra.s loc_24BA4 ; =========================================================================== loc_24BA0: add.w d1,y_pos(a0) loc_24BA4: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 move.w #$10,d2 move.w #$11,d3 move.w (sp)+,d4 jsrto (SolidObject).l, JmpTo5_SolidObject bsr.w loc_24BF0 jmpto (MarkObjGone).l, JmpTo11_MarkObjGone ; =========================================================================== loc_24BC4: move.w (sp)+,d4 lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s BranchTo_JmpTo25_DeleteObject bclr #7,2(a2,d0.w) if removeJmpTos JmpTo25_DeleteObject endif BranchTo_JmpTo25_DeleteObject jmpto (DeleteObject).l, JmpTo25_DeleteObject ; =========================================================================== ; loc_24BDC: Obj46_PressureSpring: tst.b objoff_30(a0) beq.s + subq.b #1,mapping_frame(a0) bne.s + clr.b objoff_30(a0) + jmpto (MarkObjGone).l, JmpTo11_MarkObjGone ; =========================================================================== loc_24BF0: tst.b mapping_frame(a0) beq.s + move.b #0,mapping_frame(a0) rts ; =========================================================================== + move.b objoff_14(a0),d0 beq.s loc_24C2A bmi.s loc_24C32 subq.b #1,anim_frame_duration(a0) bpl.s loc_24C2A neg.b d0 addq.b #8,d0 bcs.s + moveq #0,d0 + move.b d0,anim_frame_duration(a0) move.b objoff_1F(a0),d0 addq.b #1,d0 cmpi.b #4,d0 bne.s + moveq #1,d0 + move.b d0,objoff_1F(a0) loc_24C2A: move.b objoff_1F(a0),mapping_frame(a0) rts ; =========================================================================== loc_24C32: subq.b #1,anim_frame_duration(a0) bpl.s loc_24C2A addq.b #8,d0 bcs.s + moveq #0,d0 + move.b d0,anim_frame_duration(a0) move.b objoff_1F(a0),d0 subq.b #1,d0 bne.s + moveq #3,d0 + move.b d0,objoff_1F(a0) bra.s loc_24C2A ; =========================================================================== ; ---------------------------------------------------------------------------- ; Unused sprite mappings ; ---------------------------------------------------------------------------- Obj46_MapUnc_24C52: BINCLUDE "mappings/sprite/obj46.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo25_DeleteObject jmp (DeleteObject).l JmpTo4_SingleObjLoad jmp (SingleObjLoad).l ; some of these are still used, for some reason: JmpTo11_MarkObjGone jmp (MarkObjGone).l JmpTo20_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo5_SolidObject jmp (SolidObject).l JmpTo_SolidObject_Always_SingleCharacter jmp (SolidObject_Always_SingleCharacter).l JmpTo_SolidObject45 jmp (SolidObject45).l ; loc_24CEE: JmpTo9_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 47 - Button ; ---------------------------------------------------------------------------- ; Sprite_24CF4: Obj47: moveq #0,d0 move.b routine(a0),d0 move.w Obj47_Index(pc,d0.w),d1 jmp Obj47_Index(pc,d1.w) ; =========================================================================== ; off_24D02: Obj47_Index: offsetTable offsetTableEntry.w Obj47_Init ; 0 offsetTableEntry.w Obj47_Main ; 2 ; =========================================================================== ; loc_24D06: Obj47_Init: addq.b #2,routine(a0) move.l #Obj47_MapUnc_24D96,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Button,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo21_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #4,priority(a0) addq.w #4,y_pos(a0) ; loc_24D32: Obj47_Main: tst.b render_flags(a0) bpl.s BranchTo_JmpTo12_MarkObjGone move.w #$1B,d1 move.w #4,d2 move.w #5,d3 move.w x_pos(a0),d4 jsrto (SolidObject).l, JmpTo6_SolidObject move.b #0,mapping_frame(a0) move.b subtype(a0),d0 andi.w #$F,d0 lea (ButtonVine_Trigger).w,a3 lea (a3,d0.w),a3 moveq #0,d3 btst #6,subtype(a0) beq.s + moveq #7,d3 + move.b status(a0),d0 andi.b #standing_mask,d0 bne.s + bclr d3,(a3) bra.s BranchTo_JmpTo12_MarkObjGone ; =========================================================================== + tst.b (a3) bne.s + move.w #SndID_Blip,d0 jsr (PlaySound).l + bset d3,(a3) move.b #1,mapping_frame(a0) BranchTo_JmpTo12_MarkObjGone jmpto (MarkObjGone).l, JmpTo12_MarkObjGone ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj47_MapUnc_24D96: BINCLUDE "mappings/sprite/obj47.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo12_MarkObjGone jmp (MarkObjGone).l JmpTo21_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo6_SolidObject jmp (SolidObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 3D - Block thingy in OOZ that launches you into the round ball things ; ---------------------------------------------------------------------------- ; Sprite_24DD0: Obj3D: moveq #0,d0 move.b routine(a0),d0 move.w Obj3D_Index(pc,d0.w),d1 jmp Obj3D_Index(pc,d1.w) ; =========================================================================== ; off_24DDE: Obj3D_Index: offsetTable offsetTableEntry.w Obj3D_Init ; 0 offsetTableEntry.w Obj3D_Main ; 2 offsetTableEntry.w Obj3D_Fragment ; 4 offsetTableEntry.w Obj3D_InvisibleLauncher ; 6 ; =========================================================================== ; loc_24DE6: Obj3D_Init: addq.b #2,routine(a0) move.l #Obj3D_MapUnc_250BA,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_StripedBlocksVert,3,0),art_tile(a0) tst.b subtype(a0) beq.s + move.w #make_art_tile(ArtTile_ArtNem_StripedBlocksHoriz,3,0),art_tile(a0) move.b #2,mapping_frame(a0) + jsrto (Adjust2PArtPointer).l, JmpTo22_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) bset #7,status(a0) move.b #4,priority(a0) ; loc_24E26: Obj3D_Main: move.b (MainCharacter+anim).w,objoff_32(a0) move.b (Sidekick+anim).w,objoff_33(a0) move.w (MainCharacter+y_vel).w,objoff_34(a0) move.w (Sidekick+y_vel).w,objoff_36(a0) move.w #$1B,d1 move.w #$10,d2 move.w #$11,d3 move.w x_pos(a0),d4 jsrto (SolidObject).l, JmpTo7_SolidObject move.b status(a0),d0 andi.b #standing_mask,d0 bne.s loc_24E60 BranchTo_JmpTo13_MarkObjGone jmpto (MarkObjGone).l, JmpTo13_MarkObjGone ; =========================================================================== loc_24E60: cmpi.b #standing_mask,d0 bne.s loc_24E96 cmpi.b #AniIDSonAni_Roll,objoff_32(a0) beq.s loc_24E76 cmpi.b #AniIDSonAni_Roll,objoff_33(a0) bne.s BranchTo_JmpTo13_MarkObjGone loc_24E76: lea (MainCharacter).w,a1 ; a1=character move.b objoff_32(a0),d0 move.w objoff_34(a0),d1 bsr.s loc_24EB2 lea (Sidekick).w,a1 ; a1=character move.b objoff_33(a0),d0 move.w objoff_36(a0),d1 bsr.s loc_24EB2 bra.w loc_24F04 ; =========================================================================== loc_24E96: move.b d0,d1 andi.b #p1_standing,d1 beq.s loc_24EE8 cmpi.b #AniIDSonAni_Roll,objoff_32(a0) bne.s BranchTo_JmpTo13_MarkObjGone lea (MainCharacter).w,a1 ; a1=character move.w objoff_34(a0),d1 bsr.s loc_24EB8 bra.s loc_24F04 ; =========================================================================== loc_24EB2: cmpi.b #AniIDSonAni_Roll,d0 bne.s loc_24ED4 loc_24EB8: bset #2,status(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #AniIDSonAni_Roll,anim(a1) move.w d1,y_vel(a1) loc_24ED4: bset #1,status(a1) bclr #3,status(a1) move.b #2,routine(a1) rts ; =========================================================================== loc_24EE8: andi.b #p2_standing,d0 beq.w BranchTo_JmpTo13_MarkObjGone cmpi.b #AniIDSonAni_Roll,objoff_33(a0) bne.w BranchTo_JmpTo13_MarkObjGone lea (Sidekick).w,a1 ; a1=character move.w objoff_36(a0),d1 bsr.s loc_24EB8 loc_24F04: andi.b #~standing_mask,status(a0) jsrto (SingleObjLoad2).l, JmpTo9_SingleObjLoad2 bne.s loc_24F28 moveq #0,d0 move.w #$A,d1 loc_24F16: move.l (a0,d0.w),(a1,d0.w) addq.w #4,d0 dbf d1,loc_24F16 move.b #6,routine(a1) loc_24F28: lea (word_2507A).l,a4 addq.b #1,mapping_frame(a0) moveq #$F,d1 move.w #$18,d2 jsrto (BreakObjectToPieces).l, JmpTo2_BreakObjectToPieces ; loc_24F3C: Obj3D_Fragment: jsrto (ObjectMove).l, JmpTo10_ObjectMove addi.w #$18,y_vel(a0) tst.b render_flags(a0) bpl.w JmpTo26_DeleteObject jmpto (DisplaySprite).l, JmpTo14_DisplaySprite ; =========================================================================== ; loc_24F52: Obj3D_InvisibleLauncher: lea (MainCharacter).w,a1 ; a1=character lea objoff_2C(a0),a4 bsr.s loc_24F74 lea (Sidekick).w,a1 ; a1=character lea objoff_36(a0),a4 bsr.s loc_24F74 move.b objoff_2C(a0),d0 add.b objoff_36(a0),d0 beq.w JmpTo3_MarkObjGone3 rts ; =========================================================================== loc_24F74: moveq #0,d0 move.b (a4),d0 move.w off_24F80(pc,d0.w),d0 jmp off_24F80(pc,d0.w) ; =========================================================================== off_24F80: offsetTable offsetTableEntry.w loc_24F84 ; 0 offsetTableEntry.w loc_25036 ; 2 ; =========================================================================== loc_24F84: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 addi.w #$10,d0 cmpi.w #$20,d0 bhs.w return_25034 move.w y_pos(a1),d1 sub.w y_pos(a0),d1 tst.b subtype(a0) beq.s loc_24FAA addi.w #$10,d1 loc_24FAA: cmpi.w #$10,d1 bhs.w return_25034 cmpa.w #Sidekick,a1 bne.s loc_24FC2 cmpi.w #4,(Tails_CPU_routine).w ; TailsCPU_Flying beq.w return_25034 loc_24FC2: addq.b #2,(a4) move.b #$81,obj_control(a1) move.b #AniIDSonAni_Roll,anim(a1) move.w #$800,inertia(a1) tst.b subtype(a0) beq.s loc_24FF0 move.w x_pos(a0),x_pos(a1) move.w #0,x_vel(a1) move.w #-$800,y_vel(a1) bra.s loc_25002 ; =========================================================================== loc_24FF0: move.w y_pos(a0),y_pos(a1) move.w #$800,x_vel(a1) move.w #0,y_vel(a1) loc_25002: bclr #5,status(a0) bclr #5,status(a1) bset #1,status(a1) bset #3,status(a1) move.w a0,d0 subi.w #Object_RAM,d0 if object_size=$40 lsr.w #6,d0 else divu.w #object_size,d0 endif andi.w #$7F,d0 move.b d0,interact(a1) move.w #SndID_Roll,d0 jsr (PlaySound).l return_25034: rts ; =========================================================================== loc_25036: tst.b render_flags(a1) bmi.s Obj3D_MoveCharacter move.b #0,obj_control(a1) bset #1,status(a1) bclr #3,status(a1) move.b #0,(a4) rts ; =========================================================================== ; update the position of Sonic/Tails from the block thing to the launcher ; loc_25054: Obj3D_MoveCharacter: move.l x_pos(a1),d2 move.l y_pos(a1),d3 move.w x_vel(a1),d0 ext.l d0 asl.l #8,d0 add.l d0,d2 move.w y_vel(a1),d0 ext.l d0 asl.l #8,d0 add.l d0,d3 move.l d2,x_pos(a1) move.l d3,y_pos(a1) rts ; =========================================================================== word_2507A: dc.w -$400,-$400 ; 0 dc.w -$200,-$400 ; 2 dc.w $200,-$400 ; 4 dc.w $400,-$400 ; 6 dc.w -$3C0,-$200 ; 8 dc.w -$1C0,-$200 ; 10 dc.w $1C0,-$200 ; 12 dc.w $3C0,-$200 ; 14 dc.w -$380, $200 ; 16 dc.w -$180, $200 ; 18 dc.w $180, $200 ; 20 dc.w $380, $200 ; 22 dc.w -$340, $400 ; 24 dc.w -$140, $400 ; 26 dc.w $140, $400 ; 28 dc.w $340, $400 ; 30 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj3D_MapUnc_250BA: BINCLUDE "mappings/sprite/obj3D.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo14_DisplaySprite jmp (DisplaySprite).l JmpTo26_DeleteObject jmp (DeleteObject).l JmpTo13_MarkObjGone jmp (MarkObjGone).l JmpTo9_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo3_MarkObjGone3 jmp (MarkObjGone3).l JmpTo22_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo2_BreakObjectToPieces jmp (BreakObjectToPieces).l JmpTo7_SolidObject jmp (SolidObject).l ; loc_2523C: JmpTo10_ObjectMove jmp (ObjectMove).l align 4 else JmpTo3_MarkObjGone3 jmp (MarkObjGone3).l JmpTo26_DeleteObject jmp (DeleteObject).l ; Unused ;JmpTo13_MarkObjGone jmp (MarkObjGone).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 48 - Round ball thing from OOZ that fires you off in a different direction (sphere) ; ---------------------------------------------------------------------------- ; Sprite_25244: Obj48: moveq #0,d0 move.b routine(a0),d0 move.w Obj48_Index(pc,d0.w),d1 jsr Obj48_Index(pc,d1.w) move.b objoff_2C(a0),d0 add.b objoff_36(a0),d0 beq.w JmpTo14_MarkObjGone jmpto (DisplaySprite).l, JmpTo15_DisplaySprite if removeJmpTos JmpTo14_MarkObjGone jmp (MarkObjGone).l endif ; =========================================================================== ; off_25262: Obj48_Index: offsetTable offsetTableEntry.w Obj48_Init ; 0 offsetTableEntry.w Obj48_Main ; 2 ; =========================================================================== ; byte_25266: Obj48_Properties: ; render_flags ; objoff_3F dc.b 4, 0 ; 0 dc.b 6, 7 ; 2 dc.b 7, 0 ; 4 dc.b 5, 7 ; 6 dc.b 5, 0 ; 8 dc.b 4, 7 ; 10 dc.b 6, 0 ; 12 dc.b 7, 7 ; 14 ; =========================================================================== ; loc_25276: Obj48_Init: addq.b #2,routine(a0) move.l #Obj48_MapUnc_254FE,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_LaunchBall,3,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo23_Adjust2PArtPointer move.b subtype(a0),d0 andi.w #$F,d0 btst #0,status(a0) beq.s + addq.w #4,d0 + add.w d0,d0 move.b Obj48_Properties(pc,d0.w),render_flags(a0) move.b Obj48_Properties+1(pc,d0.w),objoff_3F(a0) beq.s + move.b #1,objoff_3E(a0) + move.b objoff_3F(a0),mapping_frame(a0) move.b #$28,width_pixels(a0) move.b #1,priority(a0) ; loc_252C6: Obj48_Main: lea (MainCharacter).w,a1 ; a1=character lea objoff_2C(a0),a4 moveq #objoff_2C,d2 bsr.s loc_252DC lea (Sidekick).w,a1 ; a1=character lea objoff_36(a0),a4 moveq #objoff_36,d2 loc_252DC: moveq #0,d0 move.b (a4),d0 move.w Obj48_Modes(pc,d0.w),d0 jmp Obj48_Modes(pc,d0.w) ; =========================================================================== ; off_252E8: Obj48_Modes: offsetTable offsetTableEntry.w loc_252F0 ; 0 offsetTableEntry.w loc_253C6 ; 2 offsetTableEntry.w loc_25474 ; 4 offsetTableEntry.w loc_254F2 ; 6 ; =========================================================================== loc_252F0: tst.w (Debug_placement_mode).w bne.w return_253C4 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 addi.w #$10,d0 cmpi.w #$20,d0 bhs.w return_253C4 move.w y_pos(a1),d1 sub.w y_pos(a0),d1 addi.w #$10,d1 cmpi.w #$20,d1 bhs.w return_253C4 cmpa.w #Sidekick,a1 bne.s + cmpi.w #4,(Tails_CPU_routine).w ; TailsCPU_Flying beq.w return_253C4 + cmpi.b #6,routine(a1) bhs.w return_253C4 tst.w (Debug_placement_mode).w bne.w return_253C4 btst #3,status(a1) beq.s + moveq #0,d0 move.b interact(a1),d0 if object_size=$40 lsl.w #6,d0 else mulu.w #object_size,d0 endif addi.l #Object_RAM,d0 movea.l d0,a3 ; a3=object move.b #0,(a3,d2.w) + move.w a0,d0 subi.w #Object_RAM,d0 if object_size=$40 lsr.w #6,d0 else divu.w #object_size,d0 endif andi.w #$7F,d0 move.b d0,interact(a1) addq.b #2,(a4) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b #$81,obj_control(a1) move.b #2,anim(a1) move.w #$1000,inertia(a1) move.w #0,x_vel(a1) move.w #0,y_vel(a1) bclr #5,status(a0) bclr #5,status(a1) bset #1,status(a1) bset #3,status(a1) move.b objoff_3F(a0),mapping_frame(a0) move.w #SndID_Roll,d0 jsr (PlaySound).l return_253C4: rts ; =========================================================================== loc_253C6: tst.b objoff_3E(a0) bne.s loc_253EE cmpi.b #7,mapping_frame(a0) beq.s loc_25408 subq.w #1,anim_frame_duration(a0) bpl.s return_253EC move.w #7,anim_frame_duration(a0) addq.b #1,mapping_frame(a0) cmpi.b #7,mapping_frame(a0) beq.s loc_25408 return_253EC: rts ; =========================================================================== loc_253EE: tst.b mapping_frame(a0) beq.s loc_25408 subq.w #1,anim_frame_duration(a0) bpl.s return_253EC move.w #7,anim_frame_duration(a0) subq.b #1,mapping_frame(a0) beq.s loc_25408 rts ; =========================================================================== loc_25408: addq.b #2,(a4) move.b subtype(a0),d0 addq.b #1,d0 btst #0,status(a0) beq.s + subq.b #2,d0 + andi.w #3,d0 add.w d0,d0 add.w d0,d0 move.w word_25464(pc,d0.w),x_vel(a1) move.w word_25464+2(pc,d0.w),y_vel(a1) move.w #3,anim_frame_duration(a0) tst.b subtype(a0) bpl.s return_25462 move.b #0,obj_control(a1) bset #1,status(a1) bclr #3,status(a1) move.b #0,jumping(a1) move.b #2,routine(a1) move.b #6,(a4) move.w #7,objoff_3C(a0) return_25462: rts ; =========================================================================== word_25464: dc.w 0,-$1000 dc.w $1000, 0 ; 2 dc.w 0, $1000 ; 4 dc.w -$1000, 0 ; 6 ; =========================================================================== loc_25474: tst.b render_flags(a1) bmi.s loc_25492 move.b #0,obj_control(a1) bset #1,status(a1) bclr #3,status(a1) move.b #0,(a4) rts ; =========================================================================== loc_25492: cmpi.b #2,objoff_2C(a0) beq.s Obj48_MoveCharacter cmpi.b #2,objoff_36(a0) beq.s Obj48_MoveCharacter subq.w #1,anim_frame_duration(a0) bpl.s Obj48_MoveCharacter move.w #1,anim_frame_duration(a0) tst.b objoff_3E(a0) beq.s loc_254C2 cmpi.b #7,mapping_frame(a0) beq.s Obj48_MoveCharacter addq.b #1,mapping_frame(a0) bra.s Obj48_MoveCharacter ; =========================================================================== loc_254C2: tst.b mapping_frame(a0) beq.s Obj48_MoveCharacter subq.b #1,mapping_frame(a0) ; update the position of Sonic/Tails between launchers ; loc_254CC: Obj48_MoveCharacter: move.l x_pos(a1),d2 move.l y_pos(a1),d3 move.w x_vel(a1),d0 ext.l d0 asl.l #8,d0 add.l d0,d2 move.w y_vel(a1),d0 ext.l d0 asl.l #8,d0 add.l d0,d3 move.l d2,x_pos(a1) move.l d3,y_pos(a1) rts ; =========================================================================== loc_254F2: subq.w #1,objoff_3C(a0) bpl.s + ; rts move.b #0,(a4) + rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj48_MapUnc_254FE: BINCLUDE "mappings/sprite/obj48.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo15_DisplaySprite jmp (DisplaySprite).l JmpTo14_MarkObjGone jmp (MarkObjGone).l JmpTo23_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 22 - Arrow shooter from ARZ ; ---------------------------------------------------------------------------- ; Sprite_25694: Obj22: moveq #0,d0 move.b routine(a0),d0 move.w Obj22_Index(pc,d0.w),d1 jmp Obj22_Index(pc,d1.w) ; =========================================================================== ; off_256A2: Obj22_Index: offsetTable offsetTableEntry.w Obj22_Init ; 0 offsetTableEntry.w Obj22_Main ; 2 offsetTableEntry.w Obj22_ShootArrow ; 4 offsetTableEntry.w Obj22_Arrow_Init ; 6 offsetTableEntry.w Obj22_Arrow ; 8 ; =========================================================================== ; loc_256AC: Obj22_Init: addq.b #2,routine(a0) move.l #Obj22_MapUnc_25804,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_ArrowAndShooter,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo24_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #3,priority(a0) move.b #$10,width_pixels(a0) move.b #1,mapping_frame(a0) andi.b #$F,subtype(a0) ; loc_256E0: Obj22_Main: cmpi.b #2,anim(a0) beq.s Obj22_Animate moveq #0,d2 lea (MainCharacter).w,a1 ; a1=character bsr.s Obj22_DetectPlayer lea (Sidekick).w,a1 ; a1=character bsr.s Obj22_DetectPlayer tst.b d2 bne.s + tst.b anim(a0) beq.s + moveq #2,d2 + move.b d2,anim(a0) ; loc_25706: Obj22_Animate: lea (Ani_obj22).l,a1 jsrto (AnimateSprite).l, JmpTo5_AnimateSprite jmpto (MarkObjGone).l, JmpTo15_MarkObjGone ; =========================================================================== ; loc_25714: Obj22_DetectPlayer: move.w x_pos(a0),d0 sub.w x_pos(a1),d0 ; is the player on the left of the shooter? bcc.s + ; if yes, branch neg.w d0 + cmpi.w #$40,d0 ; is the player within $40 pixels of the shooter? bhs.s + ; if not, branch moveq #1,d2 ; change the shooter's animation + rts ; =========================================================================== ; loc_2572A: Obj22_ShootArrow: jsrto (SingleObjLoad).l, JmpTo5_SingleObjLoad bne.s + _move.b id(a0),id(a1) ; load obj22 addq.b #6,routine(a1) move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b render_flags(a0),render_flags(a1) move.b status(a0),status(a1) move.w #SndID_PreArrowFiring,d0 jsr (PlaySound).l + subq.b #2,routine(a0) lea (Ani_obj22).l,a1 jsrto (AnimateSprite).l, JmpTo5_AnimateSprite jmpto (MarkObjGone).l, JmpTo15_MarkObjGone ; =========================================================================== ; loc_2577A: Obj22_Arrow_Init: addq.b #2,routine(a0) move.b #8,y_radius(a0) move.b #$10,x_radius(a0) move.b #4,priority(a0) move.b #$9B,collision_flags(a0) move.b #8,width_pixels(a0) move.b #0,mapping_frame(a0) move.w #$400,x_vel(a0) btst #0,status(a0) beq.s + neg.w x_vel(a0) + move.w #SndID_ArrowFiring,d0 jsr (PlaySound).l ; loc_257BE: Obj22_Arrow: jsrto (ObjectMove).l, JmpTo11_ObjectMove btst #0,status(a0) bne.s loc_257DE moveq #-8,d3 bsr.w ObjCheckLeftWallDist tst.w d1 bmi.w BranchTo_JmpTo27_DeleteObject jmpto (MarkObjGone).l, JmpTo15_MarkObjGone ; =========================================================================== BranchTo_JmpTo27_DeleteObject jmpto (DeleteObject).l, JmpTo27_DeleteObject ; =========================================================================== loc_257DE: moveq #8,d3 bsr.w ObjCheckRightWallDist tst.w d1 bmi.w BranchTo_JmpTo27_DeleteObject jmpto (MarkObjGone).l, JmpTo15_MarkObjGone ; =========================================================================== ; animation script ; off_257EE: Ani_obj22: offsetTable offsetTableEntry.w byte_257F4 ; 0 offsetTableEntry.w byte_257F7 ; 1 offsetTableEntry.w byte_257FB ; 2 byte_257F4: dc.b $1F, 1,$FF rev02even byte_257F7: dc.b 3, 1, 2,$FF rev02even byte_257FB: dc.b 7, 3, 4,$FC, 4, 3, 1,$FD, 0 even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj22_MapUnc_25804: BINCLUDE "mappings/sprite/obj22.bin" ; =========================================================================== if ~~removeJmpTos JmpTo27_DeleteObject jmp (DeleteObject).l JmpTo5_SingleObjLoad jmp (SingleObjLoad).l JmpTo15_MarkObjGone jmp (MarkObjGone).l JmpTo5_AnimateSprite jmp (AnimateSprite).l JmpTo24_Adjust2PArtPointer jmp (Adjust2PArtPointer).l ; loc_25886: JmpTo11_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 23 - Pillar that drops its lower part from ARZ ; ---------------------------------------------------------------------------- ; Sprite_2588C: Obj23: moveq #0,d0 move.b routine(a0),d0 move.w Obj23_Index(pc,d0.w),d1 jmp Obj23_Index(pc,d1.w) ; =========================================================================== ; off_2589A: Obj23_Index: offsetTable offsetTableEntry.w Obj23_Init ; 0 offsetTableEntry.w Obj23_Main ; 2 ; =========================================================================== ; loc_2589E: Obj23_Init: addq.b #2,routine(a0) move.l #Obj23_MapUnc_259E6,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,1,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo25_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #$20,y_radius(a0) move.b #4,priority(a0) jsrto (SingleObjLoad2).l, JmpTo10_SingleObjLoad2 bne.s Obj23_Main _move.b id(a0),id(a1) ; load obj23 addq.b #2,routine(a1) addq.b #2,routine_secondary(a1) move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) move.w x_pos(a0),x_pos(a1) move.w x_pos(a0),objoff_30(a1) move.w y_pos(a0),y_pos(a1) addi.w #$30,y_pos(a1) move.b render_flags(a0),render_flags(a1) move.b #$10,width_pixels(a1) move.b #$10,y_radius(a1) move.b #4,priority(a1) move.b #1,mapping_frame(a1) ; loc_25922: Obj23_Main: move.w x_pos(a0),-(sp) bsr.w loc_25948 moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 move.w (sp)+,d4 jsrto (SolidObject).l, JmpTo8_SolidObject jmpto (MarkObjGone).l, JmpTo16_MarkObjGone ; =========================================================================== loc_25948: moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj23_Modes(pc,d0.w),d1 jmp Obj23_Modes(pc,d1.w) ; =========================================================================== ; off_25956: Obj23_Modes: offsetTable offsetTableEntry.w return_2598C ; 0 offsetTableEntry.w loc_2595E ; 2 offsetTableEntry.w loc_2598E ; 4 offsetTableEntry.w loc_259B8 ; 6 ; =========================================================================== loc_2595E: tst.w (Debug_placement_mode).w bne.s return_2598C lea (MainCharacter).w,a1 ; a1=character bsr.s loc_2596E lea (Sidekick).w,a1 ; a1=character loc_2596E: move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcc.s + neg.w d0 + cmpi.w #$80,d0 bhs.s return_2598C move.b #4,routine_secondary(a0) move.w #8,objoff_34(a0) return_2598C: rts ; =========================================================================== loc_2598E: move.w objoff_34(a0),d0 subq.w #1,d0 bcc.s loc_2599C addq.b #2,routine_secondary(a0) rts ; =========================================================================== loc_2599C: move.w d0,objoff_34(a0) move.b byte_259B0(pc,d0.w),d0 ext.w d0 add.w objoff_30(a0),d0 move.w d0,x_pos(a0) rts ; =========================================================================== byte_259B0: dc.b 0 ; 0 dc.b 1 ; 1 dc.b -1 ; 2 dc.b 1 ; 3 dc.b 0 ; 4 dc.b -1 ; 5 dc.b 0 ; 6 dc.b 1 ; 7 ; =========================================================================== loc_259B8: jsrto (ObjectMove).l, JmpTo12_ObjectMove addi.w #$38,y_vel(a0) bsr.w ObjCheckFloorDist tst.w d1 bpl.w + add.w d1,y_pos(a0) clr.w y_vel(a0) move.w y_pos(a0),objoff_32(a0) move.b #2,mapping_frame(a0) clr.b routine_secondary(a0) + rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj23_MapUnc_259E6: BINCLUDE "mappings/sprite/obj23.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 2B - Rising pillar from ARZ ; ---------------------------------------------------------------------------- ; Sprite_25A5A: Obj2B: moveq #0,d0 move.b routine(a0),d0 move.w Obj2B_Index(pc,d0.w),d1 jmp Obj2B_Index(pc,d1.w) ; =========================================================================== ; off_25A68: Obj2B_Index: offsetTable offsetTableEntry.w Obj2B_Init ; 0 offsetTableEntry.w Obj2B_Main ; 2 offsetTableEntry.w loc_25B8E ; 4 ; =========================================================================== ; loc_25A6E: Obj2B_Init: addq.b #2,routine(a0) move.l #Obj2B_MapUnc_25C6E,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,1,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo25_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #$18,y_radius(a0) move.b #4,priority(a0) ; loc_25A9C: Obj2B_Main: move.w x_pos(a0),-(sp) bsr.w loc_25B28 moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 move.w (sp)+,d4 jsrto (SolidObject).l, JmpTo8_SolidObject move.b status(a0),d0 andi.b #standing_mask,d0 bne.w loc_25ACE jmpto (MarkObjGone).l, JmpTo16_MarkObjGone ; =========================================================================== loc_25ACE: lea (word_25BBE).l,a4 lea (byte_25BB0).l,a2 addq.b #7,mapping_frame(a0) bsr.w loc_25BF6 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 bsr.s loc_25AF6 lea (Sidekick).w,a1 ; a1=character addq.b #1,d6 bsr.s loc_25AF6 bra.w loc_25B8E ; =========================================================================== loc_25AF6: bclr d6,status(a0) beq.s return_25B26 bset #2,status(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #AniIDSonAni_Roll,anim(a1) bset #1,status(a1) bclr #3,status(a1) move.b #2,routine(a1) return_25B26: rts ; =========================================================================== loc_25B28: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_25B36(pc,d0.w),d1 jmp off_25B36(pc,d1.w) ; =========================================================================== off_25B36: offsetTable offsetTableEntry.w loc_25B3C ; 0 offsetTableEntry.w loc_25B66 ; 2 offsetTableEntry.w return_25B64 ; 4 ; =========================================================================== loc_25B3C: tst.w (Debug_placement_mode).w bne.s return_25B64 lea (MainCharacter).w,a1 ; a1=character bsr.s loc_25B4C lea (Sidekick).w,a1 ; a1=character loc_25B4C: move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcc.s loc_25B58 neg.w d0 loc_25B58: cmpi.w #$40,d0 bhs.s return_25B64 move.b #2,routine_secondary(a0) return_25B64: rts ; =========================================================================== loc_25B66: subq.w #1,objoff_34(a0) bcc.s return_25B8C move.w #3,objoff_34(a0) subq.w #4,y_pos(a0) addq.b #4,y_radius(a0) addq.b #1,mapping_frame(a0) cmpi.b #6,mapping_frame(a0) bne.s return_25B8C move.b #4,routine_secondary(a0) return_25B8C: rts ; =========================================================================== loc_25B8E: tst.b objoff_3F(a0) beq.s loc_25B9A subq.b #1,objoff_3F(a0) bra.s loc_25BA4 ; =========================================================================== loc_25B9A: jsrto (ObjectMove).l, JmpTo12_ObjectMove addi.w #$18,y_vel(a0) loc_25BA4: tst.b render_flags(a0) bpl.w JmpTo28_DeleteObject jmpto (DisplaySprite).l, JmpTo16_DisplaySprite ; =========================================================================== byte_25BB0: dc.b 0 dc.b 0 ; 1 dc.b 0 ; 2 dc.b 0 ; 3 dc.b 4 ; 4 dc.b 4 ; 5 dc.b 8 ; 6 dc.b 8 ; 7 dc.b $C ; 8 dc.b $C ; 9 dc.b $10 ; 10 dc.b $10 ; 11 dc.b $14 ; 12 dc.b $14 ; 13 word_25BBE: dc.w -$200,-$200,$200,-$200 ; 0 dc.w -$1C0,-$1C0,$1C0,-$1C0 ; 4 dc.w -$180,-$180,$180,-$180 ; 8 dc.w -$140,-$140,$140,-$140 ; 12 dc.w -$100,-$100,$100,-$100 ; 16 dc.w -$C0, -$C0, $C0, -$C0 ; 20 dc.w -$80, -$80, $80, -$80 ; 24 ; =========================================================================== loc_25BF6: moveq #0,d0 move.b mapping_frame(a0),d0 add.w d0,d0 movea.l mappings(a0),a3 adda.w (a3,d0.w),a3 move.w (a3)+,d1 subq.w #1,d1 bset #5,render_flags(a0) _move.b id(a0),d4 move.b render_flags(a0),d5 movea.l a0,a1 bra.s loc_25C24 ; =========================================================================== loc_25C1C: jsrto (SingleObjLoad2).l, JmpTo10_SingleObjLoad2 bne.s loc_25C64 addq.w #8,a3 loc_25C24: move.b #4,routine(a1) _move.b d4,id(a1) ; load obj2B? move.l a3,mappings(a1) move.b d5,render_flags(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w art_tile(a0),art_tile(a1) move.b priority(a0),priority(a1) move.b width_pixels(a0),width_pixels(a1) move.w (a4)+,x_vel(a1) move.w (a4)+,y_vel(a1) move.b (a2)+,objoff_3F(a1) dbf d1,loc_25C1C loc_25C64: move.w #SndID_SlowSmash,d0 jmp (PlaySound).l ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj2B_MapUnc_25C6E: BINCLUDE "mappings/sprite/obj2B.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo16_DisplaySprite jmp (DisplaySprite).l JmpTo28_DeleteObject jmp (DeleteObject).l JmpTo16_MarkObjGone jmp (MarkObjGone).l JmpTo10_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo25_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo8_SolidObject jmp (SolidObject).l ; loc_260FC: JmpTo12_ObjectMove jmp (ObjectMove).l align 4 else JmpTo28_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 2C - Sprite that makes leaves fly off when you hit it from ARZ ; ---------------------------------------------------------------------------- ; Sprite_26104: Obj2C: moveq #0,d0 move.b routine(a0),d0 move.w Obj2C_Index(pc,d0.w),d1 jmp Obj2C_Index(pc,d1.w) ; =========================================================================== ; off_26112: Obj2C_Index: offsetTable offsetTableEntry.w Obj2C_Init ; 0 offsetTableEntry.w Obj2C_Main ; 2 offsetTableEntry.w loc_26296 ; 4 ; =========================================================================== ; byte_26118: Obj2C_CollisionFlags: dc.b $D6 dc.b $D4 ; 1 dc.b $D5 ; 2 dc.b 0 ; 3 ; =========================================================================== ; loc_2611C: Obj2C_Init: addq.b #2,routine(a0) moveq #0,d0 move.b subtype(a0),d0 move.b Obj2C_CollisionFlags(pc,d0.w),collision_flags(a0) move.l #Obj31_MapUnc_20E74,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Powerups,0,1),art_tile(a0) move.b #$84,render_flags(a0) move.b #$80,width_pixels(a0) move.b #4,priority(a0) move.b subtype(a0),mapping_frame(a0) ; loc_26152: Obj2C_Main: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w JmpTo29_DeleteObject move.b collision_property(a0),d0 beq.s loc_261C2 move.w objoff_2E(a0),d0 beq.s + add.b (Timer_frames+1).w,d0 andi.w #$F,d0 bne.s loc_26198 + lea (MainCharacter).w,a2 ; a2=character bclr #0,collision_property(a0) beq.s Obj2C_RemoveCollision bsr.s loc_261C8 tst.w objoff_2E(a0) bne.s Obj2C_RemoveCollision move.w (Timer_frames).w,objoff_2E(a0) bra.s Obj2C_RemoveCollision ; =========================================================================== loc_26198: addi_.w #8,d0 andi.w #$F,d0 bne.s Obj2C_RemoveCollision lea (Sidekick).w,a2 ; a2=character bclr #1,collision_property(a0) beq.s Obj2C_RemoveCollision bsr.s loc_261C8 tst.w objoff_2E(a0) bne.s Obj2C_RemoveCollision move.w (Timer_frames).w,objoff_2E(a0) ; loc_261BC: Obj2C_RemoveCollision: clr.b collision_property(a0) rts ; =========================================================================== loc_261C2: clr.w objoff_2E(a0) rts ; =========================================================================== loc_261C8: mvabs.w x_vel(a2),d0 cmpi.w #$200,d0 bhs.s loc_261E4 mvabs.w y_vel(a2),d0 cmpi.w #$200,d0 blo.s loc_261C2 loc_261E4: lea (Obj2C_Speeds).l,a3 moveq #3,d6 loc_261EC: jsrto (SingleObjLoad).l, JmpTo6_SingleObjLoad bne.w loc_26278 _move.b #ObjID_LeavesGenerator,id(a1) ; load obj2C move.b #4,routine(a1) move.w x_pos(a2),x_pos(a1) move.w y_pos(a2),y_pos(a1) jsrto (RandomNumber).l, JmpTo2_RandomNumber andi.w #$F,d0 subq.w #8,d0 add.w d0,x_pos(a1) swap d0 andi.w #$F,d0 subq.w #8,d0 add.w d0,y_pos(a1) move.w (a3)+,x_vel(a1) move.w (a3)+,y_vel(a1) btst #0,status(a2) beq.s + neg.w x_vel(a1) + move.w x_pos(a1),objoff_30(a1) move.w y_pos(a1),objoff_34(a1) andi.b #1,d0 move.b d0,mapping_frame(a1) move.l #Obj2C_MapUnc_2631E,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_Leaves,3,1),art_tile(a1) move.b #$84,render_flags(a1) move.b #8,width_pixels(a1) move.b #1,priority(a1) move.b #4,objoff_38(a1) move.b d1,angle(a0) loc_26278: dbf d6,loc_261EC move.w #SndID_Leaves,d0 jmp (PlaySound).l ; =========================================================================== ; byte_26286: word_26286: Obj2C_Speeds: dc.w -$80,-$80 ; 0 dc.w $C0,-$40 ; 1 dc.w -$C0, $40 ; 2 dc.w $80, $80 ; 3 ; =========================================================================== loc_26296: move.b objoff_38(a0),d0 add.b d0,angle(a0) add.b (Vint_runcount+3).w,d0 andi.w #$1F,d0 bne.s + add.b d7,d0 andi.b #1,d0 beq.s + neg.b objoff_38(a0) + move.l objoff_30(a0),d2 move.l objoff_34(a0),d3 move.w x_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d2 move.w y_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d3 move.l d2,objoff_30(a0) move.l d3,objoff_34(a0) swap d2 andi.w #3,d3 addq.w #4,d3 add.w d3,y_vel(a0) move.b angle(a0),d0 jsrto (CalcSine).l, JmpTo7_CalcSine asr.w #6,d0 add.w objoff_30(a0),d0 move.w d0,x_pos(a0) asr.w #6,d1 add.w objoff_34(a0),d1 move.w d1,y_pos(a0) subq.b #1,anim_frame_duration(a0) bpl.s + move.b #$B,anim_frame_duration(a0) bchg #1,mapping_frame(a0) + tst.b render_flags(a0) bpl.w JmpTo29_DeleteObject jmpto (DisplaySprite).l, JmpTo17_DisplaySprite if removeJmpTos JmpTo29_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj2C_MapUnc_2631E: BINCLUDE "mappings/sprite/obj2C.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo17_DisplaySprite jmp (DisplaySprite).l JmpTo29_DeleteObject jmp (DeleteObject).l JmpTo6_SingleObjLoad jmp (SingleObjLoad).l JmpTo2_RandomNumber jmp (RandomNumber).l JmpTo7_CalcSine jmp (CalcSine).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 40 - Pressure spring from CPZ, ARZ, and MCZ (the red "diving board" springboard) ; ---------------------------------------------------------------------------- ; Sprite_26370: Obj40: moveq #0,d0 move.b routine(a0),d0 move.w Obj40_Index(pc,d0.w),d1 jsr Obj40_Index(pc,d1.w) jmpto (MarkObjGone).l, JmpTo17_MarkObjGone ; =========================================================================== ; off_26382: Obj40_Index: offsetTable offsetTableEntry.w Obj40_Init ; 0 offsetTableEntry.w Obj40_Main ; 2 ; --------------------------------------------------------------------------- ; it seems this object's strength was once controlled by subtype ; these would be applied to the player's y_vel ; word_26386: Obj40_Strengths: dc.w -$400 ; 0 dc.w -$A00 ; 2 ; inaccessible dc.w -$800 ; 4 ; =========================================================================== ; loc_2638C: Obj40_Init: addq.b #2,routine(a0) move.l #Obj40_MapUnc_265F4,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_LeverSpring,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo26_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$1C,width_pixels(a0) move.b #4,priority(a0) bset #7,status(a0) move.b subtype(a0),d0 andi.w #2,d0 ; there is enough data for this to be capped at 4 move.w Obj40_Strengths(pc,d0.w),objoff_30(a0) ; this is never read ; loc_263C8: Obj40_Main: lea (Ani_obj40).l,a1 jsrto (AnimateSprite).l, JmpTo6_AnimateSprite move.w #$27,d1 move.w #8,d2 move.w x_pos(a0),d4 lea Obj40_SlopeData_DiagUp(pc),a2 tst.b mapping_frame(a0) beq.s + lea Obj40_SlopeData_Straight(pc),a2 + lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) jsrto (SlopedSolid_SingleCharacter).l, JmpTo_SlopedSolid_SingleCharacter btst #p1_standing_bit,status(a0) beq.s + bsr.s loc_2641E + movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 jsrto (SlopedSolid_SingleCharacter).l, JmpTo_SlopedSolid_SingleCharacter btst #p2_standing_bit,status(a0) beq.s + ; rts bsr.s loc_2641E + rts ; =========================================================================== loc_2641E: btst #0,status(a0) bne.s loc_26436 move.w x_pos(a0),d0 subi.w #$10,d0 cmp.w x_pos(a1),d0 blo.s loc_26446 rts ; =========================================================================== loc_26436: move.w x_pos(a0),d0 addi.w #$10,d0 cmp.w x_pos(a1),d0 bhs.s loc_26446 rts ; =========================================================================== loc_26446: cmpi.b #1,anim(a0) beq.s loc_26456 move.w #$100,anim(a0) rts ; =========================================================================== loc_26456: tst.b mapping_frame(a0) beq.s loc_2645E rts ; =========================================================================== loc_2645E: move.w x_pos(a0),d0 subi.w #$1C,d0 sub.w x_pos(a1),d0 neg.w d0 btst #0,status(a0) beq.s loc_2647A not.w d0 addi.w #$27,d0 loc_2647A: tst.w d0 bpl.s loc_26480 moveq #0,d0 loc_26480: lea (byte_26550).l,a3 move.b (a3,d0.w),d0 move.w #-$400,y_vel(a1) sub.b d0,y_vel(a1) bset #0,status(a1) btst #0,status(a0) bne.s loc_264AA bclr #0,status(a1) neg.b d0 loc_264AA: mvabs.w x_vel(a1),d1 cmpi.w #$400,d1 blo.s loc_264BC sub.b d0,x_vel(a1) loc_264BC: bset #1,status(a1) bclr #3,status(a1) move.b #AniIDSonAni_Spring,anim(a1) move.b #2,routine(a1) move.b #0,spindash_flag(a1) move.b subtype(a0),d0 btst #0,d0 beq.s loc_2651E move.w #1,inertia(a1) move.b #1,flip_angle(a1) move.b #AniIDSonAni_Walk,anim(a1) move.b #1,flips_remaining(a1) move.b #8,flip_speed(a1) btst #1,d0 bne.s loc_2650E move.b #3,flips_remaining(a1) loc_2650E: btst #0,status(a1) beq.s loc_2651E neg.b flip_angle(a1) neg.w inertia(a1) loc_2651E: andi.b #$C,d0 cmpi.b #4,d0 bne.s loc_26534 move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) loc_26534: cmpi.b #8,d0 bne.s loc_26546 move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_26546: move.w #SndID_Spring,d0 jmp (PlaySound).l ; =========================================================================== byte_26550: dc.b 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 dc.b 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1; 16 dc.b 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2; 32 dc.b 3, 3, 3, 3, 3, 3, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0; 48 dc.b 0, 0, 0, 0, 0, 0, 0, 0; 64 ;byte_26598: Obj40_SlopeData_DiagUp: dc.b 8, 8, 8, 8, 8, 8, 8, 9, $A, $B, $C, $D, $E, $F,$10,$10 dc.b $11,$12,$13,$14,$14,$15,$15,$16,$17,$18,$18,$18,$18,$18,$18,$18; 16 dc.b $18,$18,$18,$18,$18,$18,$18,$18; 32 ;byte_265C0: Obj40_SlopeData_Straight: dc.b 8, 8, 8, 8, 8, 8, 8, 9, $A, $B, $C, $C, $C, $C, $D, $D dc.b $D, $D, $D, $D, $E, $E, $F, $F,$10,$10,$10,$10, $F, $F, $E, $E; 16 dc.b $D, $D, $D, $D, $D, $D, $D, $D; 32 ; animation script ; off_265E8: Ani_obj40: offsetTable offsetTableEntry.w byte_265EC ; 0 offsetTableEntry.w byte_265EF ; 1 byte_265EC: dc.b $F, 0,$FF rev02even byte_265EF: dc.b 3, 1, 0,$FD, 0 even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj40_MapUnc_265F4: BINCLUDE "mappings/sprite/obj40.bin" ; =========================================================================== if ~~removeJmpTos JmpTo17_MarkObjGone jmp (MarkObjGone).l JmpTo6_AnimateSprite jmp (AnimateSprite).l JmpTo26_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo_SlopedSolid_SingleCharacter jmp (SlopedSolid_SingleCharacter).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 42 - Steam Spring from MTZ ; ---------------------------------------------------------------------------- ; Sprite_26634: Obj42: moveq #0,d0 move.b routine(a0),d0 move.w Obj42_Index(pc,d0.w),d1 jmp Obj42_Index(pc,d1.w) ; =========================================================================== ; off_26642: Obj42_Index: offsetTable offsetTableEntry.w Obj42_Init ; 0 offsetTableEntry.w loc_26688 ; 2 offsetTableEntry.w loc_2683A ; 4 ; =========================================================================== ; loc_26648: Obj42_Init: addq.b #2,routine(a0) move.l #Obj42_MapUnc_2686C,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,3,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #4,priority(a0) jsrto (Adjust2PArtPointer).l, JmpTo27_Adjust2PArtPointer move.b #7,mapping_frame(a0) move.w y_pos(a0),objoff_34(a0) move.w #$10,objoff_36(a0) addi.w #$10,y_pos(a0) loc_26688: move.w #$1B,d1 move.w #$10,d2 move.w #$10,d3 move.w x_pos(a0),d4 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) jsrto (SolidObject_Always_SingleCharacter).l, JmpTo2_SolidObject_Always_SingleCharacter btst #p1_standing_bit,status(a0) beq.s + bsr.w loc_2678E + movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 jsrto (SolidObject_Always_SingleCharacter).l, JmpTo2_SolidObject_Always_SingleCharacter btst #p2_standing_bit,status(a0) beq.s + bsr.w loc_2678E + move.b routine_secondary(a0),d0 bne.s loc_266E4 subq.w #1,objoff_32(a0) bpl.s BranchTo_JmpTo18_MarkObjGone move.w #$3B,objoff_32(a0) addq.b #2,routine_secondary(a0) bra.s BranchTo_JmpTo18_MarkObjGone ; =========================================================================== loc_266E4: subq.b #2,d0 bne.s loc_26716 subq.w #8,objoff_36(a0) bne.s loc_26708 addq.b #2,routine_secondary(a0) bsr.s loc_2674C addi.w #$28,x_pos(a1) bsr.s loc_2674C subi.w #$28,x_pos(a1) bset #0,render_flags(a1) loc_26708: move.w objoff_36(a0),d0 add.w objoff_34(a0),d0 move.w d0,y_pos(a0) bra.s BranchTo_JmpTo18_MarkObjGone ; =========================================================================== loc_26716: subq.b #2,d0 bne.s loc_2672C subq.w #1,objoff_32(a0) bpl.s BranchTo_JmpTo18_MarkObjGone move.w #$3B,objoff_32(a0) addq.b #2,routine_secondary(a0) bra.s BranchTo_JmpTo18_MarkObjGone ; =========================================================================== loc_2672C: addq.w #8,objoff_36(a0) cmpi.w #$10,objoff_36(a0) bne.s loc_2673C clr.b routine_secondary(a0) loc_2673C: move.w objoff_36(a0),d0 add.w objoff_34(a0),d0 move.w d0,y_pos(a0) BranchTo_JmpTo18_MarkObjGone jmpto (MarkObjGone).l, JmpTo18_MarkObjGone ; =========================================================================== loc_2674C: jsrto (SingleObjLoad).l, JmpTo7_SingleObjLoad bne.s + _move.b id(a0),id(a1) ; load obj42 addq.b #4,routine(a1) move.w x_pos(a0),x_pos(a1) move.w objoff_34(a0),y_pos(a1) move.b #7,anim_frame_duration(a1) move.l mappings(a0),mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_MtzSteam,1,0),art_tile(a1) ori.b #4,render_flags(a1) move.b #$18,width_pixels(a1) move.b #4,priority(a1) + rts ; =========================================================================== loc_2678E: cmpi.b #2,routine_secondary(a0) beq.s loc_26798 rts ; =========================================================================== loc_26798: move.w #-$A00,y_vel(a1) bset #1,status(a1) bclr #3,status(a1) move.b #AniIDSonAni_Spring,anim(a1) move.b #2,routine(a1) move.b #0,spindash_flag(a1) move.b subtype(a0),d0 bpl.s + move.w #0,x_vel(a1) + btst #0,d0 beq.s loc_26808 move.w #1,inertia(a1) move.b #1,flip_angle(a1) move.b #AniIDSonAni_Walk,anim(a1) move.b #0,flips_remaining(a1) move.b #4,flip_speed(a1) btst #1,d0 bne.s + move.b #1,flips_remaining(a1) + btst #0,status(a1) beq.s loc_26808 neg.b flip_angle(a1) neg.w inertia(a1) loc_26808: andi.b #$C,d0 cmpi.b #4,d0 bne.s + move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) + cmpi.b #8,d0 bne.s + move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) + move.w #SndID_Spring,d0 jmp (PlaySound).l ; =========================================================================== loc_2683A: subq.b #1,anim_frame_duration(a0) bpl.s ++ move.b #7,anim_frame_duration(a0) move.b #0,collision_flags(a0) addq.b #1,mapping_frame(a0) cmpi.b #3,mapping_frame(a0) bne.s + move.b #$A6,collision_flags(a0) + cmpi.b #7,mapping_frame(a0) beq.w JmpTo30_DeleteObject + jmpto (DisplaySprite).l, JmpTo18_DisplaySprite if removeJmpTos JmpTo30_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj42_MapUnc_2686C: BINCLUDE "mappings/sprite/obj42.bin" ; =========================================================================== if ~~removeJmpTos JmpTo18_DisplaySprite jmp (DisplaySprite).l JmpTo30_DeleteObject jmp (DeleteObject).l JmpTo7_SingleObjLoad jmp (SingleObjLoad).l JmpTo18_MarkObjGone jmp (MarkObjGone).l JmpTo27_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo2_SolidObject_Always_SingleCharacter jmp (SolidObject_Always_SingleCharacter).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 64 - Twin stompers from MTZ ; ---------------------------------------------------------------------------- ; Sprite_26920: Obj64: moveq #0,d0 move.b routine(a0),d0 move.w Obj64_Index(pc,d0.w),d1 jmp Obj64_Index(pc,d1.w) ; =========================================================================== ; off_2692E: Obj64_Index: offsetTable offsetTableEntry.w Obj64_Init ; 0 offsetTableEntry.w Obj64_Main ; 2 ; =========================================================================== ; byte_26932: Obj64_Properties: ; width_pixels ; objoff_2E dc.b $40, $C dc.b $40, 1 ; 2 dc.b $10,$20 ; 4 dc.b $40, 1 ; 6 ; =========================================================================== ; loc_2693A: Obj64_Init: addq.b #2,routine(a0) moveq #0,d0 move.b subtype(a0),d0 lsr.w #2,d0 andi.w #$1C,d0 lea Obj64_Properties(pc,d0.w),a3 move.b (a3)+,width_pixels(a0) move.b (a3)+,objoff_2E(a0) lsr.w #2,d0 move.b d0,mapping_frame(a0) bne.s + move.b #$6C,y_radius(a0) bset #4,render_flags(a0) + move.l #Obj64_MapUnc_26A5C,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,1,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo28_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #4,priority(a0) move.w x_pos(a0),objoff_34(a0) move.w y_pos(a0),objoff_30(a0) moveq #0,d0 move.b (a3)+,d0 move.w d0,objoff_3C(a0) andi.b #$F,subtype(a0) ; loc_269A2: Obj64_Main: move.w x_pos(a0),-(sp) moveq #0,d0 move.b subtype(a0),d0 add.w d0,d0 move.w Obj64_Modes(pc,d0.w),d1 jsr Obj64_Modes(pc,d1.w) move.w (sp)+,d4 tst.b render_flags(a0) bpl.s + moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b objoff_2E(a0),d2 move.w d2,d3 addq.w #1,d3 jsrto (SolidObject).l, JmpTo9_SolidObject + move.w objoff_34(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.s JmpTo31_DeleteObject jmp (DisplaySprite).l ; =========================================================================== JmpTo31_DeleteObject jmp (DeleteObject).l ; =========================================================================== ; off_269F4: Obj64_Modes: offsetTable offsetTableEntry.w return_269F8 ; 0 offsetTableEntry.w loc_269FA ; 2 ; =========================================================================== return_269F8: rts ; =========================================================================== loc_269FA: tst.b objoff_38(a0) bne.s loc_26A1E tst.w objoff_3A(a0) beq.s loc_26A0C subq.w #8,objoff_3A(a0) bra.s loc_26A3E ; =========================================================================== loc_26A0C: subq.w #1,objoff_36(a0) bpl.s loc_26A3E move.w #$5A,objoff_36(a0) move.b #1,objoff_38(a0) loc_26A1E: move.w objoff_3A(a0),d0 cmp.w objoff_3C(a0),d0 beq.s loc_26A2E addq.w #8,objoff_3A(a0) bra.s loc_26A3E ; =========================================================================== loc_26A2E: subq.w #1,objoff_36(a0) bpl.s loc_26A3E move.w #$5A,objoff_36(a0) clr.b objoff_38(a0) loc_26A3E: move.w objoff_3A(a0),d0 btst #0,status(a0) beq.s loc_26A50 neg.w d0 addi.w #$40,d0 loc_26A50: move.w objoff_30(a0),d1 add.w d0,d1 move.w d1,y_pos(a0) rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj64_MapUnc_26A5C: BINCLUDE "mappings/sprite/obj64.bin" ; =========================================================================== if ~~removeJmpTos JmpTo28_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo9_SolidObject jmp (SolidObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 65 - Long moving platform from MTZ ; ---------------------------------------------------------------------------- ; Sprite_26AE0: Obj65: moveq #0,d0 move.b routine(a0),d0 move.w Obj65_Index(pc,d0.w),d1 jmp Obj65_Index(pc,d1.w) ; =========================================================================== ; off_26AEE: Obj65_Index: offsetTable offsetTableEntry.w Obj65_Init ; 0 offsetTableEntry.w loc_26C1C ; 2 offsetTableEntry.w loc_26EA4 ; 4 offsetTableEntry.w loc_26EC2 ; 6 ; --------------------------------------------------------------------------- ; byte_26AF6: Obj65_Properties: ; width_pixels ; radius dc.b $40, $C dc.b $80, 1 ; 2 dc.b $20, $C ; 4 dc.b $40, 3 ; 6 dc.b $10,$10 ; 8 dc.b $20, 0 ; 10 dc.b $40, $C ; 12 dc.b $80, 7 ; 14 ; =========================================================================== ; loc_26B06: Obj65_Init: addq.b #2,routine(a0) move.l #Obj65_Obj6A_Obj6B_MapUnc_26EC8,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,3,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo29_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #4,priority(a0) moveq #0,d0 move.b subtype(a0),d0 lsr.w #2,d0 andi.w #$1C,d0 lea Obj65_Properties(pc,d0.w),a3 move.b (a3)+,width_pixels(a0) move.b (a3)+,y_radius(a0) lsr.w #2,d0 move.b d0,mapping_frame(a0) cmpi.b #1,d0 bne.s + bset #7,status(a0) + cmpi.b #2,d0 bne.s loc_26B6E addq.b #4,routine(a0) move.l #Obj65_MapUnc_26F04,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_MtzCog,3,0),art_tile(a0) bra.w loc_26EC2 ; =========================================================================== loc_26B6E: move.w x_pos(a0),objoff_34(a0) move.w y_pos(a0),objoff_30(a0) moveq #0,d0 move.b (a3)+,d0 move.w d0,objoff_3C(a0) moveq #0,d0 move.b subtype(a0),d0 bpl.w loc_26C16 andi.b #$F,d0 move.b d0,objoff_3E(a0) move.b (a3),subtype(a0) cmpi.b #7,(a3) bne.s + move.w objoff_3C(a0),objoff_3A(a0) + jsrto (SingleObjLoad2).l, JmpTo11_SingleObjLoad2 bne.s loc_26C04 _move.b id(a0),id(a1) ; load obj65 addq.b #4,routine(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #-$4C,x_pos(a1) addi.w #$14,y_pos(a1) btst #0,status(a0) bne.s + subi.w #-$18,x_pos(a1) bset #0,render_flags(a1) + move.l #Obj65_MapUnc_26F04,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_MtzCog,3,0),art_tile(a1) ori.b #4,render_flags(a1) move.b #$10,width_pixels(a1) move.b #4,priority(a1) move.l a0,objoff_3C(a1) loc_26C04: lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s loc_26C16 bclr #7,2(a2,d0.w) loc_26C16: andi.b #$F,subtype(a0) loc_26C1C: move.w x_pos(a0),objoff_2E(a0) moveq #0,d0 move.b subtype(a0),d0 add.w d0,d0 move.w off_26C7E(pc,d0.w),d1 jsr off_26C7E(pc,d1.w) move.w objoff_2E(a0),d4 moveq #0,d1 move.b width_pixels(a0),d1 addi_.w #5,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 jsrto (SolidObject).l, JmpTo10_SolidObject move.w objoff_34(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.s loc_26C66 jmp (DisplaySprite).l ; =========================================================================== loc_26C66: lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s + bclr #7,2(a2,d0.w) + jmp (DeleteObject).l ; =========================================================================== off_26C7E: offsetTable offsetTableEntry.w return_26C8E ; 0 offsetTableEntry.w loc_26CA4 ; 1 offsetTableEntry.w loc_26D34 ; 2 offsetTableEntry.w loc_26D94 ; 3 offsetTableEntry.w loc_26E3C ; 4 offsetTableEntry.w loc_26E4A ; 5 offsetTableEntry.w loc_26C90 ; 6 offsetTableEntry.w loc_26D14 ; 7 ; =========================================================================== return_26C8E: rts ; =========================================================================== loc_26C90: tst.b objoff_38(a0) bne.s BranchTo_loc_26CC2 subq.w #1,objoff_36(a0) bne.s loc_26CD0 move.b #1,objoff_38(a0) BranchTo_loc_26CC2 bra.s loc_26CC2 ; =========================================================================== loc_26CA4: tst.b objoff_38(a0) bne.s loc_26CC2 lea (ButtonVine_Trigger).w,a2 moveq #0,d0 move.b objoff_3E(a0),d0 btst #0,(a2,d0.w) beq.s loc_26CD0 move.b #1,objoff_38(a0) loc_26CC2: move.w objoff_3C(a0),d0 cmp.w objoff_3A(a0),d0 beq.s loc_26CF2 addq.w #2,objoff_3A(a0) loc_26CD0: move.w objoff_3A(a0),d0 btst #0,status(a0) beq.s + neg.w d0 addi.w #$80,d0 + move.w objoff_34(a0),d1 sub.w d0,d1 move.w d1,x_pos(a0) move.w d1,objoff_2E(a0) rts ; =========================================================================== loc_26CF2: addq.b #1,subtype(a0) move.w #$B4,objoff_36(a0) clr.b objoff_38(a0) lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s loc_26CD0 bset #0,2(a2,d0.w) bra.s loc_26CD0 ; =========================================================================== loc_26D14: tst.b objoff_38(a0) bne.s + lea (ButtonVine_Trigger).w,a2 moveq #0,d0 move.b objoff_3E(a0),d0 btst #0,(a2,d0.w) beq.s loc_26D50 move.b #1,objoff_38(a0) + bra.s loc_26D46 ; =========================================================================== loc_26D34: tst.b objoff_38(a0) bne.s loc_26D46 subq.w #1,objoff_36(a0) bne.s loc_26D50 move.b #1,objoff_38(a0) loc_26D46: tst.w objoff_3A(a0) beq.s loc_26D72 subq.w #2,objoff_3A(a0) loc_26D50: move.w objoff_3A(a0),d0 btst #0,status(a0) beq.s + neg.w d0 addi.w #$80,d0 + move.w objoff_34(a0),d1 sub.w d0,d1 move.w d1,x_pos(a0) move.w d1,objoff_2E(a0) rts ; =========================================================================== loc_26D72: subq.b #1,subtype(a0) move.w #$B4,objoff_36(a0) clr.b objoff_38(a0) lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s loc_26D50 bclr #0,2(a2,d0.w) bra.s loc_26D50 ; =========================================================================== loc_26D94: move.w objoff_34(a0),d4 move.w d4,d5 btst #0,status(a0) bne.s loc_26DAC subi.w #$20,d4 addi.w #$60,d5 bra.s loc_26DB4 ; =========================================================================== loc_26DAC: subi.w #$A0,d4 subi.w #$20,d5 loc_26DB4: move.w y_pos(a0),d2 move.w d2,d3 subi.w #$10,d2 addi.w #$40,d3 moveq #0,d1 move.w (MainCharacter+x_pos).w,d0 cmp.w d4,d0 blo.s + cmp.w d5,d0 bhs.s + move.w (MainCharacter+y_pos).w,d0 cmp.w d2,d0 blo.s + cmp.w d3,d0 bhs.s + moveq #1,d1 + move.w (Sidekick+x_pos).w,d0 cmp.w d4,d0 blo.s + cmp.w d5,d0 bhs.s + move.w (Sidekick+y_pos).w,d0 cmp.w d2,d0 blo.s + cmp.w d3,d0 bhs.s + moveq #1,d1 + tst.b d1 beq.s loc_26E0E move.w objoff_3C(a0),d0 cmp.w objoff_3A(a0),d0 beq.s return_26E3A addi.w #$10,objoff_3A(a0) bra.s loc_26E1A ; =========================================================================== loc_26E0E: tst.w objoff_3A(a0) beq.s loc_26E1A subi.w #$10,objoff_3A(a0) loc_26E1A: move.w objoff_3A(a0),d0 btst #0,status(a0) beq.s + neg.w d0 addi.w #$40,d0 + move.w objoff_34(a0),d1 sub.w d0,d1 move.w d1,x_pos(a0) move.w d1,objoff_2E(a0) return_26E3A: rts ; =========================================================================== loc_26E3C: btst #p1_standing_bit,status(a0) beq.s + addq.b #1,subtype(a0) + rts ; =========================================================================== loc_26E4A: tst.b objoff_38(a0) bne.s loc_26E84 addq.w #2,x_pos(a0) cmpi.b #metropolis_zone_2,(Current_Zone).w bne.s loc_26E74 cmpi.w #$1CC0,x_pos(a0) beq.s loc_26E6C cmpi.w #$2940,x_pos(a0) bne.s loc_26E96 loc_26E6C: move.b #0,subtype(a0) bra.s loc_26E96 ; =========================================================================== loc_26E74: cmpi.w #$1BC0,x_pos(a0) bne.s loc_26E96 move.b #1,objoff_38(a0) bra.s loc_26E96 ; =========================================================================== loc_26E84: subq.w #2,x_pos(a0) cmpi.w #$1880,x_pos(a0) bne.s loc_26E96 move.b #0,objoff_38(a0) loc_26E96: move.w x_pos(a0),objoff_34(a0) move.w x_pos(a0),(MTZ_Platform_Cog_X).w rts ; =========================================================================== loc_26EA4: movea.l objoff_3C(a0),a1 ; a1=object move.w objoff_3A(a1),d0 loc_26EAC: andi.w #7,d0 move.b byte_26EBA(pc,d0.w),mapping_frame(a0) jmpto (MarkObjGone).l, JmpTo19_MarkObjGone ; =========================================================================== byte_26EBA: dc.b 0 dc.b 0 ; 1 dc.b 2 ; 2 dc.b 2 ; 3 dc.b 2 ; 4 dc.b 1 ; 5 dc.b 1 ; 6 dc.b 1 ; 7 ; =========================================================================== loc_26EC2: move.w (MTZ_Platform_Cog_X).w,d0 bra.s loc_26EAC ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj65_Obj6A_Obj6B_MapUnc_26EC8: BINCLUDE "mappings/sprite/obj65_a.bin" ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj65_MapUnc_26F04: BINCLUDE "mappings/sprite/obj65_b.bin" ; =========================================================================== if ~~removeJmpTos JmpTo19_MarkObjGone jmp (MarkObjGone).l JmpTo11_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo29_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo10_SolidObject jmp (SolidObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 66 - Yellow spring walls from MTZ ; ---------------------------------------------------------------------------- ; Sprite_26F58: Obj66: moveq #0,d0 move.b routine(a0),d0 move.w Obj66_Index(pc,d0.w),d1 jmp Obj66_Index(pc,d1.w) ; =========================================================================== ; off_26F66: Obj66_Index: offsetTable offsetTableEntry.w Obj66_Init ; 0 offsetTableEntry.w Obj66_Main ; 2 ; =========================================================================== ; loc_26F6A: Obj66_Init: addq.b #2,routine(a0) move.l #Obj66_MapUnc_27120,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Powerups,0,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo30_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #8,width_pixels(a0) move.b #4,priority(a0) move.b #$40,y_radius(a0) move.b subtype(a0),d0 lsr.b #4,d0 andi.b #7,d0 move.b d0,mapping_frame(a0) beq.s Obj66_Main move.b #$80,y_radius(a0) ; loc_26FAE: Obj66_Main: move.w #$13,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) jsrto (SolidObject_Always_SingleCharacter).l, JmpTo3_SolidObject_Always_SingleCharacter cmpi.b #1,d4 bne.s loc_26FF6 btst #1,status(a1) beq.s loc_26FF6 move.b status(a0),d1 move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcs.s + eori.b #1,d1 + andi.b #1,d1 bne.s loc_26FF6 bsr.s loc_27042 loc_26FF6: movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 jsrto (SolidObject_Always_SingleCharacter).l, JmpTo3_SolidObject_Always_SingleCharacter cmpi.b #1,d4 bne.s loc_2702C btst #1,status(a1) beq.s loc_2702C move.b status(a0),d1 move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcs.s + eori.b #1,d1 + andi.b #1,d1 bne.s loc_2702C bsr.s loc_27042 loc_2702C: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w JmpTo33_DeleteObject if gameRevision=0 ; this object was visible with debug mode in REV00 tst.w (Debug_placement_mode).w beq.s + ; rts jsrto (DisplaySprite).l, JmpTo47_DisplaySprite + endif rts if removeJmpTos JmpTo33_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== loc_27042: if gameRevision>0 ; REV00 didn't prevent the player from bouncing if they were hurt or dead cmpi.b #4,routine(a1) blo.s loc_2704C rts endif ; =========================================================================== loc_2704C: move.w objoff_30(a0),x_vel(a1) move.w #-$800,x_vel(a1) move.w #-$800,y_vel(a1) bset #0,status(a1) btst #0,status(a0) bne.s + bclr #0,status(a1) neg.w x_vel(a1) + move.w #$F,move_lock(a1) move.w x_vel(a1),inertia(a1) btst #2,status(a1) bne.s + move.b #AniIDSonAni_Walk,anim(a1) + move.b subtype(a0),d0 bpl.s + move.w #0,y_vel(a1) + btst #0,d0 beq.s loc_270DC move.w #1,inertia(a1) move.b #1,flip_angle(a1) move.b #AniIDSonAni_Walk,anim(a1) move.b #1,flips_remaining(a1) move.b #8,flip_speed(a1) btst #1,d0 bne.s + move.b #3,flips_remaining(a1) + btst #0,status(a1) beq.s loc_270DC neg.b flip_angle(a1) neg.w inertia(a1) loc_270DC: andi.b #$C,d0 cmpi.b #4,d0 bne.s + move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) + cmpi.b #8,d0 bne.s + move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) + bclr #p1_pushing_bit,status(a0) bclr #p2_pushing_bit,status(a0) bclr #5,status(a1) move.w #SndID_Spring,d0 jmp (PlaySound).l ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj66_MapUnc_27120: BINCLUDE "mappings/sprite/obj66.bin" ; =========================================================================== if ~~removeJmpTos if gameRevision=0 JmpTo47_DisplaySprite jmp (DisplaySprite).l endif JmpTo33_DeleteObject jmp (DeleteObject).l JmpTo30_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo3_SolidObject_Always_SingleCharacter jmp (SolidObject_Always_SingleCharacter).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 67 - Spin tube from MTZ ; ---------------------------------------------------------------------------- ; Sprite_2715C: Obj67: moveq #0,d0 move.b routine(a0),d0 move.w Obj67_Index(pc,d0.w),d1 jsr Obj67_Index(pc,d1.w) move.b objoff_2C(a0),d0 add.b objoff_36(a0),d0 beq.w JmpTo4_MarkObjGone3 lea (Ani_obj67).l,a1 jsrto (AnimateSprite).l, JmpTo7_AnimateSprite jmpto (DisplaySprite).l, JmpTo19_DisplaySprite ; =========================================================================== ; off_27184: Obj67_Index: offsetTable offsetTableEntry.w Obj67_Init ; 0 offsetTableEntry.w Obj67_Main ; 2 ; =========================================================================== ; loc_27188: Obj67_Init: addq.b #2,routine(a0) move.l #Obj67_MapUnc_27548,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_MtzSpinTubeFlash,3,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #5,priority(a0) ; loc_271AC: Obj67_Main: lea (MainCharacter).w,a1 ; a1=character lea objoff_2C(a0),a4 bsr.s loc_271BE lea (Sidekick).w,a1 ; a1=character lea objoff_36(a0),a4 loc_271BE: moveq #0,d0 move.b (a4),d0 move.w off_271CA(pc,d0.w),d0 jmp off_271CA(pc,d0.w) ; =========================================================================== off_271CA: offsetTable offsetTableEntry.w loc_271D0 ; 0 offsetTableEntry.w loc_27260 ; 2 offsetTableEntry.w loc_27294 ; 4 ; =========================================================================== loc_271D0: tst.w (Debug_placement_mode).w bne.w return_2725E move.w x_pos(a1),d0 sub.w x_pos(a0),d0 addq.w #3,d0 btst #0,status(a0) beq.s + addi.w #$A,d0 + cmpi.w #$10,d0 bhs.s return_2725E move.w y_pos(a1),d1 sub.w y_pos(a0),d1 addi.w #$20,d1 cmpi.w #$40,d1 bhs.s return_2725E tst.b obj_control(a1) bne.s return_2725E addq.b #2,(a4) move.b #$81,obj_control(a1) move.b #AniIDSonAni_Roll,anim(a1) move.w #$800,inertia(a1) move.w #0,x_vel(a1) move.w #0,y_vel(a1) bclr #5,status(a0) bclr #5,status(a1) bset #1,status(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) clr.b 1(a4) move.w #SndID_Roll,d0 jsr (PlaySound).l move.w #$100,anim(a0) return_2725E: rts ; =========================================================================== loc_27260: move.b 1(a4),d0 addq.b #2,1(a4) jsr (CalcSine).l asr.w #5,d0 move.w y_pos(a0),d2 sub.w d0,d2 move.w d2,y_pos(a1) cmpi.b #$80,1(a4) bne.s + bsr.w loc_27310 addq.b #2,(a4) move.w #SndID_SpindashRelease,d0 jsr (PlaySound).l + rts ; =========================================================================== loc_27294: subq.b #1,2(a4) bpl.s Obj67_MoveCharacter movea.l 6(a4),a2 move.w (a2)+,d4 move.w d4,x_pos(a1) move.w (a2)+,d5 move.w d5,y_pos(a1) tst.b subtype(a0) bpl.s + subq.w #8,a2 + move.l a2,6(a4) subq.w #4,4(a4) beq.s loc_272EE move.w (a2)+,d4 move.w (a2)+,d5 move.w #$1000,d2 bra.w loc_27374 ; =========================================================================== ; update the position of Sonic/Tails in the MTZ tube ; loc_272C8: Obj67_MoveCharacter: move.l x_pos(a1),d2 move.l y_pos(a1),d3 move.w x_vel(a1),d0 ext.l d0 asl.l #8,d0 add.l d0,d2 move.w y_vel(a1),d0 ext.l d0 asl.l #8,d0 add.l d0,d3 move.l d2,x_pos(a1) move.l d3,y_pos(a1) rts ; =========================================================================== loc_272EE: andi.w #$7FF,y_pos(a1) clr.b (a4) clr.b obj_control(a1) btst #4,subtype(a0) bne.s + move.w #0,x_vel(a1) move.w #0,y_vel(a1) + rts ; =========================================================================== loc_27310: move.b subtype(a0),d0 bpl.s loc_27344 neg.b d0 andi.w #$F,d0 add.w d0,d0 lea (off_273F2).l,a2 adda.w (a2,d0.w),a2 move.w (a2)+,d0 subq.w #4,d0 move.w d0,4(a4) lea (a2,d0.w),a2 move.w (a2)+,d4 move.w d4,x_pos(a1) move.w (a2)+,d5 move.w d5,y_pos(a1) subq.w #8,a2 bra.s loc_27368 ; =========================================================================== loc_27344: andi.w #$F,d0 add.w d0,d0 lea (off_273F2).l,a2 adda.w (a2,d0.w),a2 move.w (a2)+,4(a4) subq.w #4,4(a4) move.w (a2)+,d4 move.w d4,x_pos(a1) move.w (a2)+,d5 move.w d5,y_pos(a1) loc_27368: move.l a2,6(a4) move.w (a2)+,d4 move.w (a2)+,d5 move.w #$1000,d2 loc_27374: moveq #0,d0 move.w d2,d3 move.w d4,d0 sub.w x_pos(a1),d0 bge.s loc_27384 neg.w d0 neg.w d2 loc_27384: moveq #0,d1 move.w d5,d1 sub.w y_pos(a1),d1 bge.s loc_27392 neg.w d1 neg.w d3 loc_27392: cmp.w d0,d1 blo.s loc_273C4 moveq #0,d1 move.w d5,d1 sub.w y_pos(a1),d1 swap d1 divs.w d3,d1 moveq #0,d0 move.w d4,d0 sub.w x_pos(a1),d0 beq.s loc_273B0 swap d0 divs.w d1,d0 loc_273B0: move.w d0,x_vel(a1) move.w d3,y_vel(a1) abs.w d1 move.w d1,2(a4) rts ; =========================================================================== loc_273C4: moveq #0,d0 move.w d4,d0 sub.w x_pos(a1),d0 swap d0 divs.w d2,d0 moveq #0,d1 move.w d5,d1 sub.w y_pos(a1),d1 beq.s loc_273DE swap d1 divs.w d0,d1 loc_273DE: move.w d1,y_vel(a1) move.w d2,x_vel(a1) abs.w d0 move.w d0,2(a4) rts ; =========================================================================== ; MTZ tube position data ; off_273F2: include "misc/obj67.asm" ; animation script ; byte_2752E: Ani_obj67: offsetTable offsetTableEntry.w byte_27532 ; 0 offsetTableEntry.w byte_27535 ; 1 byte_27532: dc.b $1F, 0,$FF rev02even byte_27535: dc.b 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0,$FE, 2 even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj67_MapUnc_27548: BINCLUDE "mappings/sprite/obj67.bin" ; =========================================================================== if ~~removeJmpTos JmpTo19_DisplaySprite jmp (DisplaySprite).l JmpTo7_AnimateSprite jmp (AnimateSprite).l JmpTo4_MarkObjGone3 jmp (MarkObjGone3).l align 4 else JmpTo4_MarkObjGone3 jmp (MarkObjGone3).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 68 - Block with a spike that comes out of each side sequentially from MTZ ; ---------------------------------------------------------------------------- spikearoundblock_initial_x_pos = objoff_30 spikearoundblock_initial_y_pos = objoff_32 spikearoundblock_offset = objoff_34 ; offset from the center spikearoundblock_position = objoff_36 ; 0 = retracted or expanding, 1 = expanded or retracting spikearoundblock_waiting = objoff_38 ; 0 = moving, 1 = waiting ; Sprite_27594: Obj68: moveq #0,d0 move.b routine(a0),d0 move.w Obj68_Index(pc,d0.w),d1 jmp Obj68_Index(pc,d1.w) ; =========================================================================== ; off_275A2: Obj68_Index: offsetTable offsetTableEntry.w Obj68_Init ; 0 offsetTableEntry.w Obj68_Block ; 2 offsetTableEntry.w Obj68_Spike ; 4 ; =========================================================================== ; loc_275A8: Obj68_Init: addq.b #2,routine(a0) move.l #Obj68_Obj6D_MapUnc_27750,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_MtzSpikeBlock,3,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo31_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #4,priority(a0) jsrto (SingleObjLoad2).l, JmpTo12_SingleObjLoad2 bne.s + _move.b id(a0),id(a1) ; load obj68 addq.b #4,routine(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w x_pos(a1),spikearoundblock_initial_x_pos(a1) move.w y_pos(a1),spikearoundblock_initial_y_pos(a1) move.l mappings(a0),mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_MtzSpike,1,0),art_tile(a1) ori.b #4,render_flags(a1) move.b #$10,width_pixels(a1) move.b #4,priority(a1) move.w (Timer_frames).w,d0 lsr.w #6,d0 move.w d0,d1 andi.w #1,d0 move.w d0,spikearoundblock_position(a1) lsr.w #1,d1 add.b subtype(a0),d1 andi.w #3,d1 move.b d1,routine_secondary(a1) move.b d1,mapping_frame(a1) lea (Obj68_CollisionFlags).l,a2 move.b (a2,d1.w),collision_flags(a1) + move.b #4,mapping_frame(a0) ; loc_2764A: Obj68_Block: move.w #$1B,d1 move.w #$10,d2 move.w #$11,d3 move.w x_pos(a0),d4 jsrto (SolidObject).l, JmpTo11_SolidObject jmpto (MarkObjGone).l, JmpTo20_MarkObjGone ; =========================================================================== ; loc_27662: Obj68_Spike: bsr.w Obj68_Spike_Action moveq #0,d0 move.b routine_secondary(a0),d0 add.w d0,d0 move.w Obj68_Spike_Directions(pc,d0.w),d1 jsr Obj68_Spike_Directions(pc,d1.w) move.w spikearoundblock_initial_x_pos(a0),d0 jmpto (MarkObjGone2).l, JmpTo2_MarkObjGone2 ; =========================================================================== ; off_2767E: Obj68_Spike_Directions: offsetTable offsetTableEntry.w Obj68_Spike_Up ; 0 offsetTableEntry.w Obj68_Spike_Right ; 1 offsetTableEntry.w Obj68_Spike_Down ; 2 offsetTableEntry.w Obj68_Spike_Left ; 3 ; =========================================================================== ; These routines update the position of the spike. ; =========================================================================== ; loc_27686: Obj68_Spike_Up: moveq #0,d0 move.b spikearoundblock_offset(a0),d0 neg.w d0 add.w spikearoundblock_initial_y_pos(a0),d0 move.w d0,y_pos(a0) rts ; =========================================================================== ; loc_27698: Obj68_Spike_Right: moveq #0,d0 move.b spikearoundblock_offset(a0),d0 add.w spikearoundblock_initial_x_pos(a0),d0 move.w d0,x_pos(a0) rts ; =========================================================================== ; loc_276A8: Obj68_Spike_Down: moveq #0,d0 move.b spikearoundblock_offset(a0),d0 add.w spikearoundblock_initial_y_pos(a0),d0 move.w d0,y_pos(a0) rts ; =========================================================================== ; loc_276B8: Obj68_Spike_Left: moveq #0,d0 move.b spikearoundblock_offset(a0),d0 neg.w d0 add.w spikearoundblock_initial_x_pos(a0),d0 move.w d0,x_pos(a0) rts ; =========================================================================== ; loc_276CA: Obj68_Spike_Action: tst.w spikearoundblock_waiting(a0) beq.s + move.b (Timer_frames+1).w,d0 andi.b #$3F,d0 bne.s Obj68_Spike_Action_End clr.w spikearoundblock_waiting(a0) tst.b render_flags(a0) ; is the spike on the screen? bpl.s + ; if not, branch move.w #SndID_SpikesMove,d0 jsr (PlaySound).l + tst.w spikearoundblock_position(a0) beq.s Obj68_Spike_Expanding ; Obj68_Spike_Retracting: subi.w #$800,spikearoundblock_offset(a0) ; retract the spike bcc.s Obj68_Spike_Action_End move.w #0,spikearoundblock_offset(a0) move.w #0,spikearoundblock_position(a0) move.w #1,spikearoundblock_waiting(a0) addq.b #1,routine_secondary(a0) andi.b #3,routine_secondary(a0) moveq #0,d0 move.b routine_secondary(a0),d0 move.b d0,mapping_frame(a0) move.b Obj68_CollisionFlags(pc,d0.w),collision_flags(a0) rts ; =========================================================================== ; loc_2772A: Obj68_Spike_Expanding: addi.w #$800,spikearoundblock_offset(a0) ; expand the spike cmpi.w #$2000,spikearoundblock_offset(a0) ; did it reach full expansion? blo.s Obj68_Spike_Action_End ; if not, return move.w #$2000,spikearoundblock_offset(a0) move.w #1,spikearoundblock_position(a0) move.w #1,spikearoundblock_waiting(a0) ; return_2774A: Obj68_Spike_Action_End: rts ; =========================================================================== ; byte_2774C: Obj68_CollisionFlags: dc.b $84 ; 0 dc.b $A6 ; 1 dc.b $84 ; 2 dc.b $A6 ; 3 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj68_Obj6D_MapUnc_27750: BINCLUDE "mappings/sprite/obj68.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 6D - Floor spike from MTZ ; ---------------------------------------------------------------------------- floorspike_initial_x_pos = objoff_30 floorspike_initial_y_pos = objoff_32 floorspike_offset = objoff_34 ; on the y axis floorspike_position = objoff_36 ; 0 = retracted or expanding, 1 = expanded or retracting floorspike_waiting = objoff_38 ; 0 = moving, 1 = waiting floorspike_delay = objoff_3A ; short delay before the spike retracts ; Sprite_27794: Obj6D: moveq #0,d0 move.b routine(a0),d0 move.w Obj6D_Index(pc,d0.w),d1 jmp Obj6D_Index(pc,d1.w) ; =========================================================================== ; off_277A2: Obj6D_Index: offsetTable offsetTableEntry.w Obj6D_Init ; 0 offsetTableEntry.w Obj6D_Main ; 2 ; =========================================================================== ; loc_277A6: Obj6D_Init: addq.b #2,routine(a0) move.l #Obj68_Obj6D_MapUnc_27750,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_MtzSpike,1,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo31_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #4,width_pixels(a0) move.b #4,priority(a0) move.w x_pos(a0),floorspike_initial_x_pos(a0) move.w y_pos(a0),floorspike_initial_y_pos(a0) move.b #$84,collision_flags(a0) ; loc_277E0: Obj6D_Main: bsr.w Obj6D_Action moveq #0,d0 move.b floorspike_offset(a0),d0 neg.w d0 add.w floorspike_initial_y_pos(a0),d0 move.w d0,y_pos(a0) move.w floorspike_initial_x_pos(a0),d0 jmpto (MarkObjGone2).l, JmpTo2_MarkObjGone2 ; =========================================================================== ; loc_277FC: Obj6D_Action: tst.w floorspike_delay(a0) beq.s + subq.w #1,floorspike_delay(a0) rts ; --------------------------------------------------------------------------- + tst.w floorspike_waiting(a0) beq.s + move.b (Timer_frames+1).w,d0 sub.b subtype(a0),d0 andi.b #$7F,d0 bne.s Obj6D_Action_End clr.w floorspike_waiting(a0) + tst.w floorspike_position(a0) beq.s Obj6D_Expanding ; Obj6D_Retracting: subi.w #$400,floorspike_offset(a0) bcc.s Obj6D_Action_End move.w #0,floorspike_offset(a0) move.w #0,floorspike_position(a0) move.w #1,floorspike_waiting(a0) rts ; =========================================================================== ; loc_27842: Obj6D_Expanding: addi.w #$400,floorspike_offset(a0) cmpi.w #$2000,floorspike_offset(a0) blo.s Obj6D_Action_End move.w #$2000,floorspike_offset(a0) move.w #1,floorspike_position(a0) move.w #3,floorspike_delay(a0) ; return_27862: Obj6D_Action_End: rts ; =========================================================================== if ~~removeJmpTos JmpTo20_MarkObjGone jmp (MarkObjGone).l JmpTo12_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo31_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo11_SolidObject jmp (SolidObject).l JmpTo2_MarkObjGone2 jmp (MarkObjGone2).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 69 - Nut from MTZ ; ---------------------------------------------------------------------------- ; Sprite_27884: Obj69: moveq #0,d0 move.b routine(a0),d0 move.w Obj69_Index(pc,d0.w),d1 jmp Obj69_Index(pc,d1.w) ; =========================================================================== ; off_27892: Obj69_Index: offsetTable offsetTableEntry.w Obj69_Init ; 0 offsetTableEntry.w Obj69_Main ; 2 offsetTableEntry.w loc_279FC ; 4 offsetTableEntry.w loc_278F4 ; 6 ; =========================================================================== ; loc_2789A: Obj69_Init: addq.b #2,routine(a0) move.l #Obj69_MapUnc_27A26,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_MtzAsstBlocks,1,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo32_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$20,width_pixels(a0) move.b #$B,y_radius(a0) move.b #4,priority(a0) move.w y_pos(a0),objoff_32(a0) move.b subtype(a0),d0 andi.w #$7F,d0 lsl.w #3,d0 move.w d0,objoff_36(a0) ; loc_278DC: Obj69_Main: lea (MainCharacter).w,a1 ; a1=character lea objoff_38(a0),a4 moveq #p1_standing_bit,d6 bsr.s Obj69_Action lea (Sidekick).w,a1 ; a1=character lea objoff_3C(a0),a4 moveq #p2_standing_bit,d6 bsr.s Obj69_Action loc_278F4: andi.w #$7FF,y_pos(a0) move.w #$2B,d1 move.w #$C,d2 move.w #$D,d3 move.w x_pos(a0),d4 jsrto (SolidObject).l, JmpTo12_SolidObject jmpto (MarkObjGone).l, JmpTo21_MarkObjGone ; =========================================================================== ; loc_27912: Obj69_Action: btst d6,status(a0) bne.s + clr.b (a4) + moveq #0,d0 move.b (a4),d0 move.w Obj69_Modes(pc,d0.w),d0 jmp Obj69_Modes(pc,d0.w) ; =========================================================================== ; off_27926: Obj69_Modes: offsetTable offsetTableEntry.w loc_2792C ; 0 offsetTableEntry.w loc_2794C ; 2 offsetTableEntry.w loc_2796E ; 4 ; =========================================================================== loc_2792C: btst d6,status(a0) bne.s + rts ; =========================================================================== + addq.b #2,(a4) move.b #0,1(a4) move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcc.s loc_2794C move.b #1,1(a4) loc_2794C: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 tst.b 1(a4) beq.s + addi.w #$F,d0 + cmpi.w #$10,d0 bhs.s + ; rts move.w x_pos(a0),x_pos(a1) addq.b #2,(a4) + rts ; =========================================================================== loc_2796E: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 bcc.s loc_279D4 add.w d0,objoff_34(a0) move.w x_pos(a0),x_pos(a1) move.w objoff_34(a0),d0 asr.w #3,d0 move.w d0,d1 asr.w #1,d0 andi.w #3,d0 move.b d0,mapping_frame(a0) neg.w d1 add.w objoff_32(a0),d1 move.w d1,y_pos(a0) sub.w objoff_32(a0),d1 move.w objoff_36(a0),d0 cmp.w d0,d1 blt.s return_279D2 move.w d0,d1 add.w objoff_32(a0),d1 move.w d1,y_pos(a0) lsl.w #3,d0 neg.w d0 move.w d0,objoff_34(a0) move.b #0,mapping_frame(a0) tst.b subtype(a0) bmi.s loc_279CC clr.b (a4) rts ; =========================================================================== loc_279CC: move.b #4,routine(a0) return_279D2: rts ; =========================================================================== loc_279D4: add.w d0,objoff_34(a0) move.w x_pos(a0),x_pos(a1) move.w objoff_34(a0),d0 asr.w #3,d0 move.w d0,d1 asr.w #1,d0 andi.w #3,d0 move.b d0,mapping_frame(a0) neg.w d1 add.w objoff_32(a0),d1 move.w d1,y_pos(a0) rts ; =========================================================================== loc_279FC: jsrto (ObjectMove).l, JmpTo13_ObjectMove addi.w #$38,y_vel(a0) jsrto (ObjCheckFloorDist).l, JmpTo_ObjCheckFloorDist tst.w d1 bpl.w + add.w d1,y_pos(a0) andi.w #$7FF,y_pos(a0) clr.w y_vel(a0) addq.b #2,routine(a0) + bra.w loc_278F4 ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj69_MapUnc_27A26: BINCLUDE "mappings/sprite/obj69.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo21_MarkObjGone jmp (MarkObjGone).l JmpTo_ObjCheckFloorDist jmp (ObjCheckFloorDist).l JmpTo32_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo12_SolidObject jmp (SolidObject).l ; loc_27AA8: JmpTo13_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 6A - Platform that moves when you walk off of it, from MTZ ; ---------------------------------------------------------------------------- ; Sprite_27AB0: Obj6A: moveq #0,d0 move.b routine(a0),d0 move.w Obj6A_Index(pc,d0.w),d1 jmp Obj6A_Index(pc,d1.w) ; =========================================================================== ; off_27ABE: Obj6A_Index: offsetTable offsetTableEntry.w Obj6A_Init ; 0 offsetTableEntry.w loc_27BDE ; 2 offsetTableEntry.w loc_27C66 ; 4 ; =========================================================================== ; loc_27AC4: Obj6A_Init: addq.b #2,routine(a0) move.l #Obj65_Obj6A_Obj6B_MapUnc_26EC8,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,3,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #4,priority(a0) move.b #$20,width_pixels(a0) move.b #$C,y_radius(a0) move.l #byte_27CDC,objoff_2C(a0) move.b #1,mapping_frame(a0) cmpi.b #mystic_cave_zone,(Current_Zone).w bne.w loc_27BC4 addq.b #2,routine(a0) move.l #Obj6A_MapUnc_27D30,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Crate,3,0),art_tile(a0) move.b #$20,width_pixels(a0) move.b #$20,y_radius(a0) move.l #byte_27CF4,objoff_2C(a0) btst #0,status(a0) beq.s + move.l #byte_27D12,objoff_2C(a0) + move.b #0,mapping_frame(a0) cmpi.b #$18,subtype(a0) bne.w loc_27BD0 jsrto (SingleObjLoad2).l, JmpTo13_SingleObjLoad2 bne.s ++ bsr.s Obj6A_InitSubObject addi.w #$40,x_pos(a1) addi.w #$40,y_pos(a1) move.b #6,subtype(a1) btst #0,status(a0) beq.s + move.b #$C,subtype(a1) + jsrto (SingleObjLoad2).l, JmpTo13_SingleObjLoad2 bne.s + bsr.s Obj6A_InitSubObject subi.w #$40,x_pos(a1) addi.w #$40,y_pos(a1) move.b #$C,subtype(a1) btst #0,status(a0) beq.s + move.b #6,subtype(a1) + bra.s loc_27BC4 ; =========================================================================== ; loc_27B9E: Obj6A_InitSubObject: _move.b id(a0),id(a1) ; load obj6A move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w x_pos(a0),objoff_32(a1) move.w y_pos(a0),objoff_30(a1) move.b status(a0),status(a1) rts ; =========================================================================== loc_27BC4: move.w x_pos(a0),objoff_32(a0) move.w y_pos(a0),objoff_30(a0) loc_27BD0: jsrto (Adjust2PArtPointer).l, JmpTo33_Adjust2PArtPointer move.b subtype(a0),objoff_38(a0) bra.w loc_27CA2 ; =========================================================================== loc_27BDE: move.w x_pos(a0),-(sp) tst.w objoff_36(a0) bne.s loc_27C2E move.b objoff_3C(a0),d1 move.b status(a0),d0 btst #p1_standing_bit,d0 bne.s loc_27C0A btst #p1_standing_bit,d1 beq.s loc_27C0E move.b #1,objoff_36(a0) move.b #0,objoff_3C(a0) bra.s loc_27C3E ; =========================================================================== loc_27C0A: move.b d0,objoff_3C(a0) loc_27C0E: btst #p2_standing_bit,d0 bne.s loc_27C28 btst #p2_standing_bit,d1 beq.s loc_27C3E move.b #1,objoff_36(a0) move.b #0,objoff_3C(a0) bra.s loc_27C3E ; =========================================================================== loc_27C28: move.b d0,objoff_3C(a0) bra.s loc_27C3E ; =========================================================================== loc_27C2E: jsr (ObjectMove).l subq.w #1,objoff_34(a0) bne.s loc_27C3E bsr.w loc_27CA2 loc_27C3E: move.w (sp)+,d4 tst.b render_flags(a0) bpl.s loc_27C5E moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 jsrto (SolidObject).l, JmpTo13_SolidObject loc_27C5E: move.w objoff_32(a0),d0 jmpto (MarkObjGone2).l, JmpTo3_MarkObjGone2 ; =========================================================================== loc_27C66: move.w x_pos(a0),-(sp) jsr (ObjectMove).l subq.w #1,objoff_34(a0) bne.s loc_27C7A bsr.w loc_27CA2 loc_27C7A: move.w (sp)+,d4 tst.b render_flags(a0) bpl.s loc_27C9A moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 jsrto (SolidObject).l, JmpTo13_SolidObject loc_27C9A: move.w objoff_32(a0),d0 jmpto (MarkObjGone2).l, JmpTo3_MarkObjGone2 ; =========================================================================== loc_27CA2: moveq #0,d0 move.b objoff_38(a0),d0 movea.l objoff_2C(a0),a1 ; a1=object lea (a1,d0.w),a1 move.w (a1)+,x_vel(a0) move.w (a1)+,y_vel(a0) move.w (a1)+,objoff_34(a0) move.w #7,objoff_3A(a0) move.b #0,objoff_36(a0) addq.b #6,objoff_38(a0) cmpi.b #$18,objoff_38(a0) blo.s return_27CDA move.b #0,objoff_38(a0) return_27CDA: rts ; =========================================================================== byte_27CDC: dc.b 0, 0, 4, 0, 0,$10, 4, 0,$FE, 0, 0,$20, 0, 0, 4, 0 dc.b 0,$10,$FC, 0,$FE, 0, 0,$20; 16 byte_27CF4: dc.b 0, 0, 1, 0, 0,$40,$FF, 0, 0, 0, 0,$80, 0, 0,$FF, 0 dc.b 0,$40, 1, 0, 0, 0, 0,$80, 1, 0, 0, 0, 0,$40; 16 byte_27D12: dc.b 0, 0, 1, 0, 0,$40, 1, 0, 0, 0, 0,$80, 0, 0,$FF, 0 dc.b 0,$40,$FF, 0, 0, 0, 0,$80,$FF, 0, 0, 0, 0,$40; 16 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj6A_MapUnc_27D30: BINCLUDE "mappings/sprite/obj6A.bin" ; =========================================================================== if ~~removeJmpTos JmpTo13_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo33_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo13_SolidObject jmp (SolidObject).l JmpTo3_MarkObjGone2 jmp (MarkObjGone2).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 6B - Immobile platform from MTZ ; ---------------------------------------------------------------------------- ; Sprite_27D6C: Obj6B: moveq #0,d0 move.b routine(a0),d0 move.w Obj6B_Index(pc,d0.w),d1 jmp Obj6B_Index(pc,d1.w) ; =========================================================================== ; off_27D7A: Obj6B_Index: offsetTable offsetTableEntry.w Obj6B_Init ; 0 offsetTableEntry.w Obj6B_Main ; 2 ; =========================================================================== byte_27D7E: dc.b $20 dc.b $C ; 1 dc.b 1 ; 2 dc.b 0 ; 3 dc.b $10 ; 4 dc.b $10 ; 5 dc.b 0 ; 6 dc.b 0 ; 7 ; =========================================================================== ; loc_27D86: Obj6B_Init: addq.b #2,routine(a0) move.l #Obj65_Obj6A_Obj6B_MapUnc_26EC8,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,3,0),art_tile(a0) cmpi.b #chemical_plant_zone,(Current_Zone).w bne.s + move.l #Obj6B_MapUnc_2800E,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CPZStairBlock,3,0),art_tile(a0) + jsrto (Adjust2PArtPointer).l, JmpTo34_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #3,priority(a0) moveq #0,d0 move.b subtype(a0),d0 lsr.w #2,d0 andi.w #$1C,d0 lea byte_27D7E(pc,d0.w),a2 move.b (a2)+,width_pixels(a0) move.b (a2)+,y_radius(a0) move.b (a2)+,mapping_frame(a0) move.w x_pos(a0),objoff_34(a0) move.w y_pos(a0),objoff_30(a0) move.b status(a0),objoff_2E(a0) moveq #0,d0 move.b subtype(a0),d0 andi.w #$F,d0 subq.w #8,d0 bcs.s Obj6B_Main lsl.w #2,d0 lea (Oscillating_Data+$2A).w,a2 lea (a2,d0.w),a2 tst.w (a2) bpl.s Obj6B_Main bchg #0,objoff_2E(a0) ; loc_27E0E: Obj6B_Main: move.w x_pos(a0),-(sp) moveq #0,d0 move.b subtype(a0),d0 andi.w #$F,d0 add.w d0,d0 move.w Obj6B_Types(pc,d0.w),d1 jsr Obj6B_Types(pc,d1.w) move.w (sp)+,d4 tst.b render_flags(a0) bpl.s + moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 jsrto (SolidObject).l, JmpTo14_SolidObject + move.w objoff_34(a0),d0 jmpto (MarkObjGone2).l, JmpTo4_MarkObjGone2 ; =========================================================================== ; off_27E4E: Obj6B_Types: offsetTable offsetTableEntry.w Obj6B_Type_Immobile ; 0 offsetTableEntry.w loc_27E68 ; 1 offsetTableEntry.w loc_27E74 ; 2 offsetTableEntry.w loc_27E96 ; 3 offsetTableEntry.w loc_27EA2 ; 4 offsetTableEntry.w loc_27EC4 ; 5 offsetTableEntry.w loc_27EE2 ; 6 offsetTableEntry.w loc_27F10 ; 7 offsetTableEntry.w loc_27F4E ; 8 offsetTableEntry.w loc_27F60 ; 9 offsetTableEntry.w loc_27F70 ; $A offsetTableEntry.w loc_27F80 ; $B ; =========================================================================== ; return_27E66: Obj6B_Type_Immobile: rts ; =========================================================================== loc_27E68: move.w #$40,d1 moveq #0,d0 move.b (Oscillating_Data+8).w,d0 bra.s + ; =========================================================================== loc_27E74: move.w #$80,d1 moveq #0,d0 move.b (Oscillating_Data+$1C).w,d0 + btst #0,status(a0) beq.s + neg.w d0 add.w d1,d0 + move.w objoff_34(a0),d1 sub.w d0,d1 move.w d1,x_pos(a0) rts ; =========================================================================== loc_27E96: move.w #$40,d1 moveq #0,d0 move.b (Oscillating_Data+8).w,d0 bra.s loc_27EAC ; =========================================================================== loc_27EA2: move.w #$80,d1 moveq #0,d0 move.b (Oscillating_Data+$1C).w,d0 loc_27EAC: btst #0,status(a0) beq.s loc_27EB8 neg.w d0 add.w d1,d0 loc_27EB8: move.w objoff_30(a0),d1 sub.w d0,d1 move.w d1,y_pos(a0) rts ; =========================================================================== loc_27EC4: move.b (Oscillating_Data).w,d0 lsr.w #1,d0 add.w objoff_30(a0),d0 move.w d0,y_pos(a0) move.b status(a0),d1 andi.b #standing_mask,d1 beq.s return_27EE0 addq.b #1,subtype(a0) return_27EE0: rts ; =========================================================================== loc_27EE2: move.l y_pos(a0),d3 move.w y_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d3 move.l d3,y_pos(a0) addi_.w #8,y_vel(a0) move.w (Camera_Max_Y_pos_now).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 bhs.s return_27F0E move.b #0,subtype(a0) return_27F0E: rts ; =========================================================================== loc_27F10: tst.b objoff_38(a0) bne.s loc_27F26 move.b status(a0),d0 andi.b #standing_mask,d0 beq.s return_27F4C move.b #8,objoff_38(a0) loc_27F26: jsrto (ObjectMove).l, JmpTo14_ObjectMove andi.w #$7FF,y_pos(a0) cmpi.w #$2A8,y_vel(a0) bne.s loc_27F3C neg.b objoff_38(a0) loc_27F3C: move.b objoff_38(a0),d1 ext.w d1 add.w d1,y_vel(a0) bne.s return_27F4C clr.b subtype(a0) return_27F4C: rts ; =========================================================================== loc_27F4E: move.w #$10,d1 moveq #0,d0 move.b (Oscillating_Data+$28).w,d0 lsr.w #1,d0 move.w (Oscillating_Data+$2A).w,d3 bra.s loc_27F8E ; =========================================================================== loc_27F60: move.w #$30,d1 moveq #0,d0 move.b (Oscillating_Data+$2C).w,d0 move.w (Oscillating_Data+$2E).w,d3 bra.s loc_27F8E ; =========================================================================== loc_27F70: move.w #$50,d1 moveq #0,d0 move.b (Oscillating_Data+$30).w,d0 move.w (Oscillating_Data+$32).w,d3 bra.s loc_27F8E ; =========================================================================== loc_27F80: move.w #$70,d1 moveq #0,d0 move.b (Oscillating_Data+$34).w,d0 move.w (Oscillating_Data+$36).w,d3 loc_27F8E: tst.w d3 bne.s loc_27F9C addq.b #1,objoff_2E(a0) andi.b #3,objoff_2E(a0) loc_27F9C: move.b objoff_2E(a0),d2 andi.b #3,d2 bne.s loc_27FBC sub.w d1,d0 add.w objoff_34(a0),d0 move.w d0,x_pos(a0) neg.w d1 add.w objoff_30(a0),d1 move.w d1,y_pos(a0) rts ; =========================================================================== loc_27FBC: subq.b #1,d2 bne.s loc_27FDA subq.w #1,d1 sub.w d1,d0 neg.w d0 add.w objoff_30(a0),d0 move.w d0,y_pos(a0) addq.w #1,d1 add.w objoff_34(a0),d1 move.w d1,x_pos(a0) rts ; =========================================================================== loc_27FDA: subq.b #1,d2 bne.s loc_27FF8 subq.w #1,d1 sub.w d1,d0 neg.w d0 add.w objoff_34(a0),d0 move.w d0,x_pos(a0) addq.w #1,d1 add.w objoff_30(a0),d1 move.w d1,y_pos(a0) rts ; =========================================================================== loc_27FF8: sub.w d1,d0 add.w objoff_30(a0),d0 move.w d0,y_pos(a0) neg.w d1 add.w objoff_34(a0),d1 move.w d1,x_pos(a0) rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj6B_MapUnc_2800E: BINCLUDE "mappings/sprite/obj6B.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo34_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo14_SolidObject jmp (SolidObject).l JmpTo4_MarkObjGone2 jmp (MarkObjGone2).l ; loc_2802E: JmpTo14_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 6C - Small platform on pulleys (like at the start of MTZ2) ; ---------------------------------------------------------------------------- ; Sprite_28034: Obj6C: moveq #0,d0 move.b routine(a0),d0 move.w Obj6C_Index(pc,d0.w),d1 jsr Obj6C_Index(pc,d1.w) move.w objoff_30(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.s + jmpto (DisplaySprite).l, JmpTo20_DisplaySprite ; =========================================================================== + jmpto (DeleteObject).l, JmpTo34_DeleteObject ; =========================================================================== ; off_2805C: Obj6C_Index: offsetTable offsetTableEntry.w Obj6C_Init ; 0 offsetTableEntry.w Obj6C_Main ; 2 ; =========================================================================== ; loc_28060: Obj6C_Init: move.b subtype(a0),d0 bmi.w loc_28112 addq.b #2,routine(a0) move.l #Obj6C_MapUnc_28372,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_LavaCup,3,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #4,priority(a0) jsrto (Adjust2PArtPointer).l, JmpTo35_Adjust2PArtPointer move.b #0,mapping_frame(a0) moveq #0,d0 move.b subtype(a0),d0 move.w d0,d1 lsr.w #3,d0 andi.w #$1E,d0 lea off_28252(pc),a2 adda.w (a2,d0.w),a2 move.w (a2)+,objoff_38(a0) move.l a2,objoff_3C(a0) andi.w #$F,d1 lsl.w #2,d1 move.b d1,objoff_38(a0) move.b #4,objoff_3A(a0) btst #0,status(a0) beq.s loc_280F2 neg.b objoff_3A(a0) moveq #0,d1 move.b objoff_38(a0),d1 add.b objoff_3A(a0),d1 cmp.b objoff_39(a0),d1 blo.s loc_280EE move.b d1,d0 moveq #0,d1 tst.b d0 bpl.s loc_280EE move.b objoff_39(a0),d1 subq.b #4,d1 loc_280EE: move.b d1,objoff_38(a0) loc_280F2: move.w (a2,d1.w),d0 add.w objoff_30(a0),d0 move.w d0,objoff_34(a0) move.w 2(a2,d1.w),d0 add.w objoff_32(a0),d0 move.w d0,objoff_36(a0) bsr.w loc_281DA bra.w Obj6C_Main ; =========================================================================== loc_28112: andi.w #$7F,d0 add.w d0,d0 lea (off_282D6).l,a2 adda.w (a2,d0.w),a2 move.w (a2)+,d1 movea.l a0,a1 move.w x_pos(a0),d2 move.w y_pos(a0),d3 bra.s Obj6C_LoadSubObject ; =========================================================================== ; loc_28130: Obj6C_SubObjectsLoop: jsrto (SingleObjLoad).l, JmpTo8_SingleObjLoad bne.s + ; loc_28136: Obj6C_LoadSubObject: _move.b #ObjID_Conveyor,id(a1) ; load obj6C move.w (a2)+,d0 add.w d2,d0 move.w d0,x_pos(a1) move.w (a2)+,d0 add.w d3,d0 move.w d0,y_pos(a1) move.w d2,objoff_30(a1) move.w d3,objoff_32(a1) move.w (a2)+,d0 move.b d0,subtype(a1) move.b status(a0),status(a1) + dbf d1,Obj6C_SubObjectsLoop addq.l #4,sp rts ; =========================================================================== ; loc_28168: Obj6C_Main: move.w x_pos(a0),-(sp) bsr.w loc_2817E moveq #0,d1 move.b width_pixels(a0),d1 moveq #8,d3 move.w (sp)+,d4 jmpto (PlatformObject).l, JmpTo5_PlatformObject ; =========================================================================== loc_2817E: move.w x_pos(a0),d0 cmp.w objoff_34(a0),d0 bne.s loc_281D4 move.w y_pos(a0),d0 cmp.w objoff_36(a0),d0 bne.s loc_281D4 moveq #0,d1 move.b objoff_38(a0),d1 add.b objoff_3A(a0),d1 cmp.b objoff_39(a0),d1 blo.s loc_281B0 move.b d1,d0 moveq #0,d1 tst.b d0 bpl.s loc_281B0 move.b objoff_39(a0),d1 subq.b #4,d1 loc_281B0: move.b d1,objoff_38(a0) movea.l objoff_3C(a0),a1 ; a1=object move.w (a1,d1.w),d0 add.w objoff_30(a0),d0 move.w d0,objoff_34(a0) move.w 2(a1,d1.w),d0 add.w objoff_32(a0),d0 move.w d0,objoff_36(a0) bsr.w loc_281DA loc_281D4: jsrto (ObjectMove).l, JmpTo15_ObjectMove rts ; =========================================================================== loc_281DA: moveq #0,d0 move.w #-$100,d2 move.w x_pos(a0),d0 sub.w objoff_34(a0),d0 bcc.s loc_281EE neg.w d0 neg.w d2 loc_281EE: moveq #0,d1 move.w #-$100,d3 move.w y_pos(a0),d1 sub.w objoff_36(a0),d1 bcc.s loc_28202 neg.w d1 neg.w d3 loc_28202: cmp.w d0,d1 blo.s loc_2822C move.w x_pos(a0),d0 sub.w objoff_34(a0),d0 beq.s loc_28218 ext.l d0 asl.l #8,d0 divs.w d1,d0 neg.w d0 loc_28218: move.w d0,x_vel(a0) move.w d3,y_vel(a0) swap d0 move.w d0,x_sub(a0) clr.w y_sub(a0) rts ; =========================================================================== loc_2822C: move.w y_pos(a0),d1 sub.w objoff_36(a0),d1 beq.s loc_2823E ext.l d1 asl.l #8,d1 divs.w d0,d1 neg.w d1 loc_2823E: move.w d1,y_vel(a0) move.w d2,x_vel(a0) swap d1 move.w d1,y_sub(a0) clr.w x_sub(a0) rts ; =========================================================================== off_28252: offsetTable offsetTableEntry.w byte_28258 ; 0 offsetTableEntry.w byte_28282 ; 1 offsetTableEntry.w byte_282AC ; 2 byte_28258: dc.b 0,$28, 0, 0, 0, 0,$FF,$EA, 0, $A,$FF,$E0, 0,$20,$FF,$E0 dc.b 0,$E0,$FF,$EA, 0,$F6, 0, 0, 1, 0, 0,$16, 0,$F6, 0,$20; 16 dc.b 0,$E0, 0,$20, 0,$20, 0,$16, 0, $A; 32 byte_28282: dc.b 0,$28, 0, 0, 0, 0,$FF,$EA, 0, $A,$FF,$E0, 0,$20,$FF,$E0 dc.b 1,$60,$FF,$EA, 1,$76, 0, 0, 1,$80, 0,$16, 1,$76, 0,$20; 16 dc.b 1,$60, 0,$20, 0,$20, 0,$16, 0, $A; 32 byte_282AC: dc.b 0,$28, 0, 0, 0, 0,$FF,$EA, 0, $A,$FF,$E0, 0,$20,$FF,$E0 dc.b 1,$E0,$FF,$EA, 1,$F6, 0, 0, 2, 0, 0,$16, 1,$F6, 0,$20; 16 dc.b 1,$E0, 0,$20, 0,$20, 0,$16, 0, $A; 32 ; --------------------------------------------------------------------------- off_282D6: offsetTable offsetTableEntry.w byte_282DC ; 0 offsetTableEntry.w byte_2830E ; 1 offsetTableEntry.w byte_28340 ; 2 byte_282DC: dc.b 0, 7, 0, 0, 0, 0, 0, 1,$FF,$E0, 0,$3A, 0, 3,$FF,$E0 dc.b 0,$80, 0, 3,$FF,$E0, 0,$C6, 0, 3, 0, 0, 1, 0, 0, 6; 16 dc.b 0,$20, 0,$C6, 0, 8, 0,$20, 0,$80, 0, 8, 0,$20, 0,$3A; 32 dc.b 0, 8 ; 48 byte_2830E: dc.b 0, 7, 0, 0, 0, 0, 0,$11,$FF,$E0, 0,$5A, 0,$13,$FF,$E0 dc.b 0,$C0, 0,$13,$FF,$E0, 1,$26, 0,$13, 0, 0, 1,$80, 0,$16; 16 dc.b 0,$20, 1,$26, 0,$18, 0,$20, 0,$C0, 0,$18, 0,$20, 0,$5A; 32 dc.b 0,$18 ; 48 byte_28340: dc.b 0, 7, 0, 0, 0, 0, 0,$21,$FF,$E0, 0,$7A, 0,$23,$FF,$E0 dc.b 1, 0, 0,$23,$FF,$E0, 1,$86, 0,$23, 0, 0, 2, 0, 0,$26; 16 dc.b 0,$20, 1,$86, 0,$28, 0,$20, 1, 0, 0,$28, 0,$20, 0,$7A; 32 dc.b 0,$28 ; 48 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj6C_MapUnc_28372: BINCLUDE "mappings/sprite/obj6C.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo20_DisplaySprite jmp (DisplaySprite).l JmpTo34_DeleteObject jmp (DeleteObject).l JmpTo8_SingleObjLoad jmp (SingleObjLoad).l JmpTo35_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo5_PlatformObject jmp (PlatformObject).l ; loc_283A6: JmpTo15_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 6E - Platform moving in a circle (like at the start of MTZ3) ; ---------------------------------------------------------------------------- ; Sprite_283AC: Obj6E: moveq #0,d0 move.b routine(a0),d0 move.w Obj6E_Index(pc,d0.w),d1 jmp Obj6E_Index(pc,d1.w) ; =========================================================================== ; off_283BA: Obj6E_Index: offsetTable offsetTableEntry.w Obj6E_Init ; 0 offsetTableEntry.w loc_28432 ; 2 offsetTableEntry.w loc_284BC ; 4 ; =========================================================================== byte_283C0: ; width_pixels ; radius dc.b $10, $C dc.b $28, 8 ; 2 dc.b $60,$18 ; 4 dc.b $C, $C ; 6 ; =========================================================================== ; loc_283C8: Obj6E_Init: addq.b #2,routine(a0) move.l #Obj6E_MapUnc_2852C,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,3,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo36_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #4,priority(a0) moveq #0,d0 move.b subtype(a0),d0 lsr.w #3,d0 andi.w #$E,d0 lea byte_283C0(pc,d0.w),a3 move.b (a3)+,width_pixels(a0) move.b (a3)+,y_radius(a0) lsr.w #1,d0 move.b d0,mapping_frame(a0) move.w x_pos(a0),objoff_34(a0) move.w y_pos(a0),objoff_30(a0) cmpi.b #3,d0 bne.s loc_28432 addq.b #2,routine(a0) move.w #make_art_tile(ArtTile_ArtNem_MtzWheelIndent,3,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo36_Adjust2PArtPointer move.b #5,priority(a0) bra.w loc_284BC ; =========================================================================== loc_28432: move.w x_pos(a0),-(sp) move.b (Oscillating_Data+$20).w,d1 subi.b #$38,d1 ext.w d1 move.b (Oscillating_Data+$24).w,d2 subi.b #$38,d2 ext.w d2 btst #0,subtype(a0) beq.s + neg.w d1 neg.w d2 + btst #1,subtype(a0) beq.s + neg.w d1 exg d1,d2 + add.w objoff_34(a0),d1 move.w d1,x_pos(a0) add.w objoff_30(a0),d2 move.w d2,y_pos(a0) move.w (sp)+,d4 moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 jsrto (SolidObject).l, JmpTo15_SolidObject move.w objoff_34(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.s + jmp (DisplaySprite).l ; =========================================================================== + lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s + bclr #7,2(a2,d0.w) + jmp (DeleteObject).l ; =========================================================================== loc_284BC: move.b (Oscillating_Data+$20).w,d1 lsr.b #1,d1 subi.b #$1C,d1 ext.w d1 move.b (Oscillating_Data+$24).w,d2 lsr.b #1,d2 subi.b #$1C,d2 ext.w d2 btst #0,subtype(a0) beq.s + neg.w d1 neg.w d2 + btst #1,subtype(a0) beq.s + neg.w d1 exg d1,d2 + add.w objoff_34(a0),d1 move.w d1,x_pos(a0) add.w objoff_30(a0),d2 move.w d2,y_pos(a0) move.w objoff_34(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.s + jmp (DisplaySprite).l ; =========================================================================== + lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s + bclr #7,2(a2,d0.w) + jmp (DeleteObject).l ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj6E_MapUnc_2852C: BINCLUDE "mappings/sprite/obj6E.bin" ; =========================================================================== if ~~removeJmpTos JmpTo36_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo15_SolidObject jmp (SolidObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 70 - Giant rotating cog from MTZ ; ---------------------------------------------------------------------------- ; Sprite_285C0: Obj70: moveq #0,d0 move.b routine(a0),d0 move.w Obj70_Index(pc,d0.w),d1 jmp Obj70_Index(pc,d1.w) ; =========================================================================== ; off_285CE: Obj70_Index: offsetTable offsetTableEntry.w Obj70_Init ; 0 offsetTableEntry.w Obj70_Main ; 2 ; =========================================================================== ; loc_285D2: Obj70_Init: moveq #7,d1 moveq #0,d4 lea (Obj70_Positions).l,a2 movea.l a0,a1 move.w x_pos(a0),d2 move.w y_pos(a0),d3 bset #7,status(a0) bra.s Obj70_LoadSubObject ; =========================================================================== ; loc_285EE: Obj70_SubObjectLoop: jsrto (SingleObjLoad2).l, JmpTo14_SingleObjLoad2 bne.s + ; loc_285F4: Obj70_LoadSubObject: _move.b id(a0),id(a1) ; load obj70 addq.b #2,routine(a1) move.l #Obj70_MapUnc_28786,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_MtzWheel,3,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo4_Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #4,priority(a1) move.b #$10,width_pixels(a1) move.w d2,objoff_32(a1) move.w d3,objoff_30(a1) move.b (a2)+,d0 ext.w d0 add.w d2,d0 move.w d0,x_pos(a1) move.b (a2)+,d0 ext.w d0 add.w d3,d0 move.w d0,y_pos(a1) move.b (a2)+,mapping_frame(a1) move.w d4,objoff_34(a1) addq.w #3,d4 move.b status(a0),status(a1) + dbf d1,Obj70_SubObjectLoop ; loc_28652: Obj70_Main: move.w x_pos(a0),-(sp) move.b (Timer_frames+1).w,d0 move.b d0,d1 andi.w #$F,d0 bne.s loc_286CA move.w objoff_36(a0),d1 btst #0,status(a0) beq.s loc_28684 subi.w #$18,d1 bcc.s loc_286A2 moveq #$48,d1 subq.w #3,objoff_34(a0) bcc.s loc_286A2 move.w #$15,objoff_34(a0) bra.s loc_286A2 ; =========================================================================== loc_28684: addi.w #$18,d1 cmpi.w #$60,d1 blo.s loc_286A2 moveq #0,d1 addq.w #3,objoff_34(a0) cmpi.w #$18,objoff_34(a0) blo.s loc_286A2 move.w #0,objoff_34(a0) loc_286A2: move.w d1,objoff_36(a0) add.w objoff_34(a0),d1 lea Obj70_Positions(pc,d1.w),a1 move.b (a1)+,d0 ext.w d0 add.w objoff_32(a0),d0 move.w d0,x_pos(a0) move.b (a1)+,d0 ext.w d0 add.w objoff_30(a0),d0 move.w d0,y_pos(a0) move.b (a1)+,mapping_frame(a0) loc_286CA: move.b mapping_frame(a0),d0 add.w d0,d0 andi.w #$1E,d0 moveq #0,d1 moveq #0,d2 move.b byte_28706(pc,d0.w),d1 move.b byte_28706+1(pc,d0.w),d2 move.w d2,d3 move.w (sp)+,d4 jsrto (SolidObject).l, JmpTo16_SolidObject move.w objoff_32(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.s + jmp (DisplaySprite).l ; =========================================================================== + jmp (DeleteObject).l ; =========================================================================== byte_28706: dc.b $10,$10 ; 0 dc.b $10,$10 ; 2 dc.b $10,$10 ; 4 dc.b $10,$10 ; 6 dc.b $10,$10 ; 8 dc.b $10,$10 ; 10 dc.b $10,$10 ; 12 dc.b $10, $C ; 14 dc.b $10, 8 ; 16 dc.b $10, $C ; 18 dc.b $10,$10 ; 20 dc.b $10,$10 ; 22 dc.b $10,$10 ; 24 dc.b $10,$10 ; 26 dc.b $10,$10 ; 28 dc.b $10,$10 ; 30 ; byte_28726: Obj70_Positions: ; initial positions ; x_pos, y_pos, mapping_frame dc.b 0,$B8, 0 dc.b $32,$CE, 4 dc.b $48, 0, 8 dc.b $32,$32, $C dc.b 0,$48,$10 dc.b $CE,$32,$14 dc.b $B8, 0,$18 dc.b $CE,$CE,$1C dc.b $D,$B8, 1 dc.b $3F,$DA, 5 dc.b $48, $C, 9 dc.b $27,$3C, $D dc.b $F3,$48,$11 dc.b $C1,$26,$15 dc.b $B8,$F4,$19 dc.b $D9,$C4,$1D dc.b $19,$BC, 2 dc.b $46,$E9, 6 dc.b $46,$17, $A dc.b $19,$44, $E dc.b $E7,$44,$12 dc.b $BA,$17,$16 dc.b $BA,$E9,$1A dc.b $E7,$BC,$1E dc.b $27,$C4, 3 dc.b $48,$F4, 7 dc.b $3F,$26, $B dc.b $D,$48, $F dc.b $D9,$3C,$13 dc.b $B8, $C,$17 dc.b $C1,$DA,$1B dc.b $F3,$B8,$1F ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj70_MapUnc_28786: BINCLUDE "mappings/sprite/obj70.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo14_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo4_Adjust2PArtPointer2 jmp (Adjust2PArtPointer2).l JmpTo16_SolidObject jmp (SolidObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 72 - Conveyor belt from CNZ ; ---------------------------------------------------------------------------- ; Sprite_2893C: Obj72: moveq #0,d0 move.b routine(a0),d0 move.w Obj72_Index(pc,d0.w),d1 jmp Obj72_Index(pc,d1.w) ; =========================================================================== ; off_2894A: Obj72_Index: offsetTable offsetTableEntry.w Obj72_Init ; 0 offsetTableEntry.w Obj72_Main ; 2 ; =========================================================================== ; loc_2894E: Obj72_Init: addq.b #2,routine(a0) move.w #$30,objoff_3C(a0) move.b subtype(a0),d0 bpl.s + move.w #$70,objoff_3C(a0) + andi.b #$7F,d0 lsl.b #4,d0 move.b d0,objoff_38(a0) move.w #2,objoff_36(a0) btst #0,status(a0) beq.s Obj72_Main neg.w objoff_36(a0) ; loc_28980: Obj72_Main: lea (MainCharacter).w,a1 ; a1=character bsr.s Obj72_Action lea (Sidekick).w,a1 ; a1=character bsr.s Obj72_Action jmpto (MarkObjGone3).l, JmpTo5_MarkObjGone3 ; =========================================================================== ; loc_28990: Obj72_Action: moveq #0,d2 move.b objoff_38(a0),d2 move.w d2,d3 add.w d3,d3 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d2,d0 cmp.w d3,d0 bhs.s + ; rts move.w y_pos(a1),d1 sub.w y_pos(a0),d1 move.w objoff_3C(a0),d0 add.w d0,d1 cmp.w d0,d1 bhs.s + ; rts btst #1,status(a1) bne.s + ; rts move.w objoff_36(a0),d0 add.w d0,x_pos(a1) + rts ; =========================================================================== if ~~removeJmpTos JmpTo5_MarkObjGone3 jmp (MarkObjGone3).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 73 - Solid rotating ring thing from Mystic Cave Zone ; (unused, but can be seen in debug mode) ; ---------------------------------------------------------------------------- ; Sprite_289D4: Obj73: moveq #0,d0 move.b routine(a0),d0 move.w Obj73_Index(pc,d0.w),d1 jmp Obj73_Index(pc,d1.w) ; =========================================================================== ; off_289E2: Obj73_Index: offsetTable offsetTableEntry.w Obj73_Init ; 0 offsetTableEntry.w Obj73_Main ; 2 offsetTableEntry.w Obj73_SubObject ; 4 ; =========================================================================== ; loc_289E8: Obj73_Init: addq.b #2,routine(a0) move.l #Obj73_MapUnc_28B9C,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Ring,1,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo37_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #4,priority(a0) move.b #8,width_pixels(a0) move.w x_pos(a0),objoff_3A(a0) move.w y_pos(a0),objoff_38(a0) move.b #0,collision_flags(a0) bset #7,status(a0) move.b subtype(a0),d1 andi.b #$F0,d1 ext.w d1 asl.w #3,d1 move.w d1,objoff_3E(a0) move.b status(a0),d0 ror.b #2,d0 andi.b #$C0,d0 move.b d0,angle(a0) lea objoff_29(a0),a2 move.b subtype(a0),d1 andi.w #7,d1 move.b #0,(a2)+ move.w d1,d3 lsl.w #4,d3 move.b d3,objoff_3C(a0) subq.w #1,d1 bcs.s Obj73_LoadSubObject_End btst #3,subtype(a0) beq.s Obj73_LoadSubObject subq.w #1,d1 bcs.s Obj73_LoadSubObject_End ; loc_28A6E: Obj73_LoadSubObject: jsrto (SingleObjLoad).l, JmpTo9_SingleObjLoad bne.s Obj73_LoadSubObject_End addq.b #1,objoff_29(a0) move.w a1,d5 subi.w #Object_RAM,d5 if object_size=$40 lsr.w #6,d5 else divu.w #object_size,d5 endif andi.w #$7F,d5 move.b d5,(a2)+ move.b #4,routine(a1) _move.b id(a0),id(a1) ; load obj73 move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) move.b render_flags(a0),render_flags(a1) move.b priority(a0),priority(a1) move.b width_pixels(a0),width_pixels(a1) move.b collision_flags(a0),collision_flags(a1) move.b status(a0),status(a1) subi.b #$10,d3 move.b d3,objoff_3C(a1) dbf d1,Obj73_LoadSubObject ; loc_28AC8: Obj73_LoadSubObject_End: move.w a0,d5 subi.w #Object_RAM,d5 if object_size=$40 lsr.w #6,d5 else divu.w #object_size,d5 endif andi.w #$7F,d5 move.b d5,(a2)+ ; loc_28AD6: Obj73_Main: move.w x_pos(a0),-(sp) bsr.w loc_28AF4 move.w #8,d1 move.w #8,d2 move.w d2,d3 addq.w #1,d3 move.w (sp)+,d4 jsrto (SolidObject).l, JmpTo17_SolidObject bra.w loc_28B46 ; =========================================================================== loc_28AF4: move.w objoff_3E(a0),d0 add.w d0,angle(a0) move.b angle(a0),d0 jsr (CalcSine).l move.w objoff_38(a0),d2 move.w objoff_3A(a0),d3 lea objoff_29(a0),a2 moveq #0,d6 move.b (a2)+,d6 loc_28B16: moveq #0,d4 move.b (a2)+,d4 if object_size=$40 lsl.w #6,d4 else mulu.w #object_size,d4 endif addi.l #Object_RAM,d4 movea.l d4,a1 ; a1=object moveq #0,d4 move.b objoff_3C(a1),d4 move.l d4,d5 muls.w d0,d4 asr.l #8,d4 muls.w d1,d5 asr.l #8,d5 add.w d2,d4 add.w d3,d5 move.w d4,y_pos(a1) move.w d5,x_pos(a1) dbf d6,loc_28B16 rts ; =========================================================================== loc_28B46: move.w objoff_3A(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w + jmpto (DisplaySprite).l, JmpTo21_DisplaySprite ; =========================================================================== + moveq #0,d2 lea objoff_29(a0),a2 move.b (a2)+,d2 - moveq #0,d0 move.b (a2)+,d0 if object_size=$40 lsl.w #6,d0 else mulu.w #object_size,d0 endif addi.l #Object_RAM,d0 movea.l d0,a1 ; a1=object jsrto (DeleteObject2).l, JmpTo_DeleteObject2 dbf d2,- rts ; =========================================================================== ; loc_28B7E: Obj73_SubObject: move.w #8,d1 move.w #8,d2 move.w d2,d3 addq.w #1,d3 move.w objoff_36(a0),d4 jsrto (SolidObject).l, JmpTo17_SolidObject move.w x_pos(a0),objoff_36(a0) jmpto (DisplaySprite).l, JmpTo21_DisplaySprite ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj73_MapUnc_28B9C: BINCLUDE "mappings/sprite/obj73.bin" ; =========================================================================== if ~~removeJmpTos JmpTo21_DisplaySprite jmp (DisplaySprite).l JmpTo9_SingleObjLoad jmp (SingleObjLoad).l JmpTo_DeleteObject2 jmp (DeleteObject2).l JmpTo37_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo17_SolidObject jmp (SolidObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 75 - Brick from MCZ ; ---------------------------------------------------------------------------- ; Sprite_28BC8: Obj75: btst #6,render_flags(a0) bne.w + moveq #0,d0 move.b routine(a0),d0 move.w Obj75_Index(pc,d0.w),d1 jmp Obj75_Index(pc,d1.w) ; =========================================================================== + move.w #$280,d0 jmpto (DisplaySprite3).l, JmpTo_DisplaySprite3 ; =========================================================================== ; off_28BE8: Obj75_Index: offsetTable offsetTableEntry.w Obj75_Init ; 0 offsetTableEntry.w Obj75_Main ; 2 offsetTableEntry.w loc_28D6C ; 4 ; =========================================================================== ; loc_28BEE: Obj75_Init: addq.b #2,routine(a0) move.l #Obj75_MapUnc_28D8A,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,1,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo38_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #5,priority(a0) move.b #$10,width_pixels(a0) move.w x_pos(a0),objoff_30(a0) move.w y_pos(a0),objoff_32(a0) move.b subtype(a0),d1 move.b d1,d0 andi.w #$F,d1 andi.b #$F0,d0 ext.w d0 asl.w #3,d0 move.w d0,objoff_34(a0) move.b status(a0),d0 ror.b #2,d0 andi.b #$C0,d0 move.b d0,angle(a0) cmpi.b #$F,d1 bne.s + addq.b #2,routine(a0) move.b #4,priority(a0) move.b #2,mapping_frame(a0) rts ; =========================================================================== + move.b #$9A,collision_flags(a0) jsrto (SingleObjLoad2).l, JmpTo15_SingleObjLoad2 bne.s Obj75_Main _move.b id(a0),id(a1) ; load obj75 move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) move.b #4,render_flags(a1) bset #6,render_flags(a1) move.b #$40,mainspr_width(a1) move.w x_pos(a0),d2 move.w y_pos(a0),d3 move.b d1,mainspr_childsprites(a1) subq.w #1,d1 lea sub2_x_pos(a1),a2 - move.w d2,(a2)+ ; sub?_x_pos move.w d3,(a2)+ ; sub?_y_pos move.w #1,(a2)+ ; sub?_mapframe dbf d1,- move.w d2,x_pos(a1) move.w d3,y_pos(a1) move.b #0,mainspr_mapframe(a1) move.l a1,objoff_3C(a0) move.b #$40,mainspr_height(a1) bset #4,render_flags(a1) ; loc_28CCA: Obj75_Main: moveq #0,d0 moveq #0,d1 move.w objoff_34(a0),d0 add.w d0,angle(a0) move.b angle(a0),d0 jsrto (CalcSine).l, JmpTo8_CalcSine move.w objoff_32(a0),d2 move.w objoff_30(a0),d3 moveq #0,d6 movea.l objoff_3C(a0),a1 ; a1=object move.b mainspr_childsprites(a1),d6 subq.w #1,d6 bcs.s loc_28D3E swap d0 swap d1 asr.l #4,d0 asr.l #4,d1 moveq #0,d4 moveq #0,d5 lea sub2_x_pos(a1),a2 - movem.l d4-d5,-(sp) swap d4 swap d5 add.w d2,d4 add.w d3,d5 move.w d5,(a2)+ ; sub?_x_pos move.w d4,(a2)+ ; sub?_y_pos movem.l (sp)+,d4-d5 add.l d0,d4 add.l d1,d5 addq.w #next_subspr-4,a2 dbf d6,- swap d4 swap d5 add.w d2,d4 add.w d3,d5 move.w d5,x_pos(a0) move.w d4,y_pos(a0) move.w sub6_x_pos(a1),x_pos(a1) move.w sub6_y_pos(a1),y_pos(a1) loc_28D3E: tst.w (Two_player_mode).w beq.s + jmpto (DisplaySprite).l, JmpTo22_DisplaySprite ; =========================================================================== + move.w objoff_30(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w + jmpto (DisplaySprite).l, JmpTo22_DisplaySprite ; =========================================================================== + movea.l objoff_3C(a0),a1 ; a1=object jsrto (DeleteObject2).l, JmpTo2_DeleteObject2 jmpto (DeleteObject).l, JmpTo38_DeleteObject ; =========================================================================== loc_28D6C: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 move.w #$10,d2 move.w #$11,d3 move.w x_pos(a0),d4 jsrto (SolidObject).l, JmpTo18_SolidObject jmpto (MarkObjGone).l, JmpTo22_MarkObjGone ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj75_MapUnc_28D8A: BINCLUDE "mappings/sprite/obj75.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo_DisplaySprite3 jmp (DisplaySprite3).l JmpTo22_DisplaySprite jmp (DisplaySprite).l JmpTo38_DeleteObject jmp (DeleteObject).l JmpTo22_MarkObjGone jmp (MarkObjGone).l JmpTo2_DeleteObject2 jmp (DeleteObject2).l JmpTo15_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo38_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo8_CalcSine jmp (CalcSine).l JmpTo18_SolidObject jmp (SolidObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 76 - Spike block that slides out of the wall from MCZ ; ---------------------------------------------------------------------------- sliding_spikes_remaining_movement = objoff_36 ; Sprite_28DF8: Obj76: moveq #0,d0 move.b routine(a0),d0 move.w Obj76_Index(pc,d0.w),d1 jmp Obj76_Index(pc,d1.w) ; =========================================================================== ; off_28E06: Obj76_Index: offsetTable offsetTableEntry.w Obj76_Init ; 0 offsetTableEntry.w Obj76_Main ; 2 ; =========================================================================== ; byte_28E0A: Obj76_InitData: dc.b $40 ; width_pixels dc.b $10 ; y_radius dc.b 0 ; mapping_frame even ; =========================================================================== ; loc_28E0E: Obj76_Init: addq.b #2,routine(a0) move.l #Obj76_MapUnc_28F3A,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo39_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #4,priority(a0) moveq #0,d0 move.b subtype(a0),d0 ; this is always 0 in the original layouts... lsr.w #2,d0 andi.w #$1C,d0 lea Obj76_InitData(pc,d0.w),a2 move.b (a2)+,width_pixels(a0) move.b (a2)+,y_radius(a0) move.b (a2)+,mapping_frame(a0) move.w x_pos(a0),objoff_34(a0) move.w y_pos(a0),objoff_30(a0) andi.w #$F,subtype(a0) ; loc_28E5E: Obj76_Main: move.w x_pos(a0),-(sp) moveq #0,d0 move.b subtype(a0),d0 move.w Obj76_Modes(pc,d0.w),d1 jsr Obj76_Modes(pc,d1.w) move.w (sp)+,d4 tst.b render_flags(a0) bpl.s loc_28EC2 moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 jsrto (SolidObject).l, JmpTo19_SolidObject swap d6 andi.w #touch_side_mask,d6 beq.s loc_28EC2 move.b d6,d0 andi.b #p1_touch_side,d0 beq.s + lea (MainCharacter).w,a1 ; a1=character jsrto (Touch_ChkHurt2).l, JmpTo_Touch_ChkHurt2 bclr #p1_pushing_bit,status(a0) + andi.b #p2_touch_side,d6 beq.s loc_28EC2 lea (Sidekick).w,a1 ; a1=character jsrto (Touch_ChkHurt2).l, JmpTo_Touch_ChkHurt2 bclr #p2_pushing_bit,status(a0) loc_28EC2: move.w objoff_34(a0),d0 jmpto (MarkObjGone2).l, JmpTo5_MarkObjGone2 ; =========================================================================== ; off_28ECA: Obj76_Modes: offsetTable offsetTableEntry.w Obj76_CheckPlayers ; 0 offsetTableEntry.w Obj76_SlideOut ; 2 ; =========================================================================== ; loc_28ECE: Obj76_CheckPlayers: lea (MainCharacter).w,a1 ; a1=character bsr.s Obj76_CheckPlayer lea (Sidekick).w,a1 ; a1=character ; loc_28ED8: Obj76_CheckPlayer: btst #1,status(a1) bne.s ++ ; rts move.w x_pos(a1),d0 sub.w x_pos(a0),d0 addi.w #$C0,d0 btst #0,status(a0) beq.s + subi.w #$100,d0 + cmpi.w #$80,d0 bhs.s + ; rts move.w y_pos(a1),d0 sub.w y_pos(a0),d0 addi.w #$10,d0 cmpi.w #$20,d0 bhs.s + ; rts move.b #2,subtype(a0) move.w #$80,sliding_spikes_remaining_movement(a0) + rts ; =========================================================================== ; loc_28F1E: Obj76_SlideOut: tst.w sliding_spikes_remaining_movement(a0) beq.s ++ ; rts subq.w #1,sliding_spikes_remaining_movement(a0) moveq #-1,d0 btst #0,status(a0) beq.s + neg.w d0 + add.w d0,x_pos(a0) + rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj76_MapUnc_28F3A: BINCLUDE "mappings/sprite/obj76.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo_Touch_ChkHurt2 jmp (Touch_ChkHurt2).l JmpTo39_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo19_SolidObject jmp (SolidObject).l JmpTo5_MarkObjGone2 jmp (MarkObjGone2).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 77 - Bridge from MCZ ; ---------------------------------------------------------------------------- ; Sprite_28F88: Obj77: moveq #0,d0 move.b routine(a0),d0 move.w Obj77_Index(pc,d0.w),d1 jmp Obj77_Index(pc,d1.w) ; =========================================================================== ; off_28F96: Obj77_Index: offsetTable offsetTableEntry.w Obj77_Init ; 0 offsetTableEntry.w Obj77_Main ; 2 ; =========================================================================== ; loc_28F9A: Obj77_Init: addq.b #2,routine(a0) move.l #Obj77_MapUnc_29064,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_MCZGateLog,3,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo40_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$80,width_pixels(a0) ; loc_28FBC: Obj77_Main: tst.b objoff_34(a0) bne.s + lea (ButtonVine_Trigger).w,a2 moveq #0,d0 move.b subtype(a0),d0 btst #0,(a2,d0.w) beq.s + move.b #1,objoff_34(a0) bchg #0,anim(a0) tst.b render_flags(a0) bpl.s + move.w #SndID_DoorSlam,d0 jsr (PlaySound).l + lea (Ani_obj77).l,a1 jsr (AnimateSprite).l tst.b mapping_frame(a0) bne.s Obj77_DropCharacters move.w #$4B,d1 move.w #8,d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsrto (SolidObject).l, JmpTo20_SolidObject jmpto (MarkObjGone).l, JmpTo23_MarkObjGone ; =========================================================================== ; Check if the characters are standing on it. If a character is standing on the ; bridge, the "standing on object" flag is cleared so that it falls. ; loc_2901A: Obj77_DropCharacters: move.b status(a0),d0 andi.b #standing_mask,d0 beq.s +++ move.b d0,d1 andi.b #p1_standing,d0 beq.s + lea (MainCharacter).w,a1 ; a1=character bclr #3,status(a1) + andi.b #p2_standing,d1 beq.s + lea (Sidekick).w,a1 ; a1=character bclr #3,status(a1) + andi.b #~standing_mask,status(a0) + jmpto (MarkObjGone).l, JmpTo23_MarkObjGone ; =========================================================================== ; ---------------------------------------------------------------------------- ; animation script ; ---------------------------------------------------------------------------- ; off_29050: Ani_obj77: offsetTable offsetTableEntry.w Ani_obj77_Close ; 0 offsetTableEntry.w Ani_obj77_Open ; 1 ; byte_29054: Ani_obj77_Close: dc.b 3, 4, 3, 2, 1, 0,$FE, 1 ; byte_2905C: Ani_obj77_Open: dc.b 3, 0, 1, 2, 3, 4,$FE, 1 even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj77_MapUnc_29064: BINCLUDE "mappings/sprite/obj77.bin" ; =========================================================================== if ~~removeJmpTos JmpTo23_MarkObjGone jmp (MarkObjGone).l JmpTo40_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo20_SolidObject jmp (SolidObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 78 - Stairs from CPZ that move down to open the way ; ---------------------------------------------------------------------------- ; Sprite_291CC: Obj78: moveq #0,d0 move.b routine(a0),d0 move.w Obj78_Index(pc,d0.w),d1 jsr Obj78_Index(pc,d1.w) move.w objoff_30(a0),d0 jmpto (MarkObjGone2).l, JmpTo6_MarkObjGone2 ; =========================================================================== ; off_291E2: Obj78_Index: offsetTable offsetTableEntry.w Obj78_Init ; 0 offsetTableEntry.w Obj78_Main ; 2 offsetTableEntry.w loc_29280 ; 4 ; =========================================================================== ; loc_291E8: Obj78_Init: addq.b #2,routine(a0) moveq #objoff_34,d3 moveq #2,d4 btst #0,status(a0) beq.s + moveq #objoff_3A,d3 moveq #-2,d4 + move.w x_pos(a0),d2 movea.l a0,a1 moveq #3,d1 bra.s Obj78_LoadSubObject ; =========================================================================== ; loc_29206: Obj78_SubObjectLoop: jsrto (SingleObjLoad2).l, JmpTo16_SingleObjLoad2 bne.w Obj78_Main move.b #4,routine(a1) ; loc_29214: Obj78_LoadSubObject: _move.b id(a0),id(a1) ; load obj78 move.l #Obj6B_MapUnc_2800E,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_CPZStairBlock,3,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo5_Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #3,priority(a1) move.b #$10,width_pixels(a1) move.b subtype(a0),subtype(a1) move.w d2,x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w x_pos(a0),objoff_30(a1) move.w y_pos(a1),objoff_32(a1) addi.w #$20,d2 move.b d3,objoff_2F(a1) move.l a0,objoff_3C(a1) add.b d4,d3 dbf d1,Obj78_SubObjectLoop ; loc_2926C: Obj78_Main: moveq #0,d0 move.b subtype(a0),d0 andi.w #7,d0 add.w d0,d0 move.w Obj78_Types(pc,d0.w),d1 jsr Obj78_Types(pc,d1.w) loc_29280: movea.l objoff_3C(a0),a2 ; a2=object moveq #0,d0 move.b objoff_2F(a0),d0 move.w (a2,d0.w),d0 add.w objoff_32(a0),d0 move.w d0,y_pos(a0) moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 move.w #$10,d2 move.w #$11,d3 move.w x_pos(a0),d4 jsrto (SolidObject).l, JmpTo21_SolidObject swap d6 or.b d6,objoff_2E(a2) rts ; =========================================================================== ; off_292B8: Obj78_Types: offsetTable offsetTableEntry.w loc_292C8 ; 0 offsetTableEntry.w loc_29334 ; 1 offsetTableEntry.w loc_292EC ; 2 offsetTableEntry.w loc_29334 ; 3 offsetTableEntry.w loc_292C8 ; 4 offsetTableEntry.w loc_2935E ; 5 offsetTableEntry.w loc_292EC ; 6 offsetTableEntry.w loc_2935E ; 7 ; =========================================================================== loc_292C8: tst.w objoff_2C(a0) bne.s loc_292E0 move.b objoff_2E(a0),d0 andi.b #touch_top_mask,d0 beq.s return_292DE move.w #$1E,objoff_2C(a0) return_292DE: rts ; =========================================================================== loc_292E0: subq.w #1,objoff_2C(a0) bne.s return_292DE addq.b #1,subtype(a0) rts ; =========================================================================== loc_292EC: tst.w objoff_2C(a0) bne.s loc_29304 move.b objoff_2E(a0),d0 andi.b #touch_bottom_mask,d0 beq.s return_29302 move.w #$3C,objoff_2C(a0) return_29302: rts ; =========================================================================== loc_29304: subq.w #1,objoff_2C(a0) bne.s loc_29310 addq.b #1,subtype(a0) rts ; =========================================================================== loc_29310: lea objoff_34(a0),a1 ; a1=object move.w objoff_2C(a0),d0 lsr.b #2,d0 andi.b #1,d0 move.w d0,(a1)+ eori.b #1,d0 move.w d0,(a1)+ eori.b #1,d0 move.w d0,(a1)+ eori.b #1,d0 move.w d0,(a1)+ rts ; =========================================================================== loc_29334: lea objoff_34(a0),a1 ; a1=object cmpi.w #$80,(a1) beq.s return_2935C addq.w #1,(a1) moveq #0,d1 move.w (a1)+,d1 swap d1 lsr.l #1,d1 move.l d1,d2 lsr.l #1,d1 move.l d1,d3 add.l d2,d3 swap d1 swap d2 swap d3 move.w d3,(a1)+ move.w d2,(a1)+ move.w d1,(a1)+ return_2935C: rts ; =========================================================================== loc_2935E: lea objoff_34(a0),a1 ; a1=object cmpi.w #-$80,(a1) beq.s return_29386 subq.w #1,(a1) moveq #0,d1 move.w (a1)+,d1 swap d1 asr.l #1,d1 move.l d1,d2 asr.l #1,d1 move.l d1,d3 add.l d2,d3 swap d1 swap d2 swap d3 move.w d3,(a1)+ move.w d2,(a1)+ move.w d1,(a1)+ return_29386: rts ; =========================================================================== if ~~removeJmpTos JmpTo16_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo5_Adjust2PArtPointer2 jmp (Adjust2PArtPointer2).l JmpTo21_SolidObject jmp (SolidObject).l JmpTo6_MarkObjGone2 jmp (MarkObjGone2).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 7A - Platform that moves back and forth on top of water in CPZ ; ---------------------------------------------------------------------------- ; Sprite_293A0: Obj7A: moveq #0,d0 move.b routine(a0),d0 move.w Obj7A_Index(pc,d0.w),d1 jmp Obj7A_Index(pc,d1.w) ; =========================================================================== ; off_293AE: Obj7A_Index: offsetTable offsetTableEntry.w Obj7A_Init ; 0 offsetTableEntry.w Obj7A_Main ; 2 offsetTableEntry.w Obj7A_SubObject ; 4 ; =========================================================================== byte_293B4: dc.b 0 dc.b $68 ; 1 dc.b $FF ; 2 dc.b $98 ; 3 dc.b 0 ; 4 dc.b 0 ; 5 dc.b 1 ; 6 dc.b $A8 ; 7 dc.b $FF ; 8 dc.b $50 ; 9 dc.b 0 ; 10 dc.b $40 ; 11 dc.b 1 ; 12 dc.b $E8 ; 13 dc.b $FF ; 14 dc.b $80 ; 15 dc.b 0 ; 16 dc.b $80 ; 17 dc.b 0 ; 18 dc.b $68 ; 19 dc.b 0 ; 20 dc.b $67 ; 21 dc.b 0 ; 22 dc.b 0 ; 23 ; =========================================================================== ; loc_293CC: Obj7A_Init: addq.b #2,routine(a0) move.l #Obj7A_MapUnc_29564,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CPZStairBlock,3,1),art_tile(a0) cmpi.b #mystic_cave_zone,(Current_Zone).w bne.s + move.l #Obj15_Obj7A_MapUnc_10256,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0) + jsrto (Adjust2PArtPointer).l, JmpTo41_Adjust2PArtPointer moveq #0,d1 move.b subtype(a0),d1 lea byte_293B4(pc,d1.w),a2 move.b (a2)+,d1 movea.l a0,a1 bra.s Obj7A_LoadSubObject ; =========================================================================== ; loc_29408: Obj7A_SubObjectLoop: jsrto (SingleObjLoad2).l, JmpTo17_SingleObjLoad2 bne.s Obj7A_SubObjectLoop_End _move.b id(a0),id(a1) ; load obj7A move.b #4,routine(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) ; loc_29426: Obj7A_LoadSubObject: move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) move.b #4,render_flags(a1) move.b #4,priority(a1) move.b #$18,width_pixels(a1) move.w x_pos(a1),objoff_30(a1) ; loc_2944A: Obj7A_SubObjectLoop_End: dbf d1,Obj7A_SubObjectLoop move.l a0,objoff_3C(a1) move.l a1,objoff_3C(a0) cmpi.b #$C,subtype(a0) bne.s + move.b #1,objoff_36(a0) + moveq #0,d1 move.b (a2)+,d1 move.w objoff_30(a0),d0 sub.w d1,d0 move.w d0,objoff_32(a0) move.w d0,objoff_32(a1) add.w d1,d0 add.w d1,d0 move.w d0,objoff_34(a0) move.w d0,objoff_34(a1) move.w (a2)+,d0 add.w d0,x_pos(a0) move.w (a2)+,d0 add.w d0,x_pos(a1) ; loc_2948E: Obj7A_Main: bsr.s loc_294F4 tst.w (Two_player_mode).w beq.s + ; if 2P VS mode is off, branch jmpto (DisplaySprite).l, JmpTo24_DisplaySprite ; =========================================================================== + move.w objoff_32(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bls.s + move.w objoff_34(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.s loc_294C4 + jmp (DisplaySprite).l ; =========================================================================== loc_294C4: movea.l objoff_3C(a0),a1 ; a1=object cmpa.l a0,a1 beq.s + jsr (DeleteObject2).l + lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s JmpTo39_DeleteObject bclr #7,2(a2,d0.w) JmpTo39_DeleteObject jmp (DeleteObject).l ; =========================================================================== ; loc_294EA: Obj7A_SubObject: bsr.s loc_294F4 bsr.s loc_2953E jmp (DisplaySprite).l ; =========================================================================== loc_294F4: move.w x_pos(a0),-(sp) tst.b objoff_36(a0) beq.s loc_29516 move.w x_pos(a0),d0 subq.w #1,d0 cmp.w objoff_32(a0),d0 bne.s + move.b #0,objoff_36(a0) + move.w d0,x_pos(a0) bra.s loc_2952C ; =========================================================================== loc_29516: move.w x_pos(a0),d0 addq.w #1,d0 cmp.w objoff_34(a0),d0 bne.s + move.b #1,objoff_36(a0) + move.w d0,x_pos(a0) loc_2952C: moveq #0,d1 move.b width_pixels(a0),d1 move.w #8,d3 move.w (sp)+,d4 jsrto (PlatformObject).l, JmpTo6_PlatformObject rts ; =========================================================================== loc_2953E: movea.l objoff_3C(a0),a1 ; a1=object move.w x_pos(a0),d0 subi.w #$18,d0 move.w x_pos(a1),d2 addi.w #$18,d2 cmp.w d0,d2 bne.s + ; rts eori.b #1,objoff_36(a0) eori.b #1,objoff_36(a1) + rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj7A_MapUnc_29564: BINCLUDE "mappings/sprite/obj7A.bin" ; =========================================================================== if ~~removeJmpTos JmpTo24_DisplaySprite jmp (DisplaySprite).l JmpTo17_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo41_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo6_PlatformObject jmp (PlatformObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 7B - Warp pipe exit spring from CPZ ; ---------------------------------------------------------------------------- ; Sprite_29590: Obj7B: moveq #0,d0 move.b routine(a0),d0 move.w Obj7B_Index(pc,d0.w),d1 jsr Obj7B_Index(pc,d1.w) tst.w (Two_player_mode).w beq.s + jmpto (DisplaySprite).l, JmpTo25_DisplaySprite ; =========================================================================== + move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w JmpTo40_DeleteObject jmpto (DisplaySprite).l, JmpTo25_DisplaySprite if removeJmpTos JmpTo40_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== ; off_295C0: Obj7B_Index: offsetTable offsetTableEntry.w Obj7B_Init ; 0 offsetTableEntry.w Obj7B_Main ; 2 ; =========================================================================== ; byte_295C4: Obj7B_Strengths: ; Speed applied on Sonic dc.w -$1000 dc.w -$A80 ; =========================================================================== ; loc_295C8: Obj7B_Init: addq.b #2,routine(a0) move.l #Obj7B_MapUnc_29780,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CPZTubeSpring,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #1,priority(a0) move.b subtype(a0),d0 andi.w #2,d0 move.w Obj7B_Strengths(pc,d0.w),objoff_30(a0) jsrto (Adjust2PArtPointer).l, JmpTo42_Adjust2PArtPointer ; loc_295FE: Obj7B_Main: cmpi.b #1,mapping_frame(a0) beq.s loc_29648 move.w #$1B,d1 move.w #8,d2 move.w #$10,d3 move.w x_pos(a0),d4 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) jsrto (SolidObject_Always_SingleCharacter).l, JmpTo4_SolidObject_Always_SingleCharacter btst #p1_standing_bit,status(a0) beq.s + bsr.w loc_296C2 + movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 jsrto (SolidObject_Always_SingleCharacter).l, JmpTo4_SolidObject_Always_SingleCharacter btst #p2_standing_bit,status(a0) beq.s loc_29648 bsr.s loc_296C2 loc_29648: move.w x_pos(a0),d4 move.w d4,d5 subi.w #$10,d4 addi.w #$10,d5 move.w y_pos(a0),d2 move.w d2,d3 addi.w #$30,d3 move.w (MainCharacter+x_pos).w,d0 cmp.w d4,d0 blo.s loc_29686 cmp.w d5,d0 bhs.s loc_29686 move.w (MainCharacter+y_pos).w,d0 cmp.w d2,d0 blo.s loc_29686 cmp.w d3,d0 bhs.s loc_29686 cmpi.b #2,next_anim(a0) beq.s loc_29686 move.b #2,anim(a0) loc_29686: move.w (Sidekick+x_pos).w,d0 cmp.w d4,d0 blo.s loc_296B6 cmp.w d5,d0 bhs.s loc_296B6 move.w (Sidekick+y_pos).w,d0 cmp.w d2,d0 blo.s loc_296B6 cmp.w d3,d0 bhs.s loc_296B6 cmpi.w #4,(Tails_CPU_routine).w ; TailsCPU_Flying beq.w loc_296B6 cmpi.b #3,next_anim(a0) beq.s loc_296B6 move.b #3,anim(a0) loc_296B6: lea (Ani_obj7B).l,a1 jmpto (AnimateSprite).l, JmpTo8_AnimateSprite ; =========================================================================== rts ; =========================================================================== loc_296C2: move.w #$100,anim(a0) addq.w #4,y_pos(a1) move.w objoff_30(a0),y_vel(a1) bset #1,status(a1) bclr #3,status(a1) move.b #AniIDSonAni_Spring,anim(a1) move.b #2,routine(a1) move.b subtype(a0),d0 bpl.s + move.w #0,x_vel(a1) + btst #0,d0 beq.s loc_29736 move.w #1,inertia(a1) move.b #1,flip_angle(a1) move.b #AniIDSonAni_Walk,anim(a1) move.b #0,flips_remaining(a1) move.b #4,flip_speed(a1) btst #1,d0 bne.s + move.b #1,flips_remaining(a1) + btst #0,status(a1) beq.s loc_29736 neg.b flip_angle(a1) neg.w inertia(a1) loc_29736: andi.b #$C,d0 cmpi.b #4,d0 bne.s + move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) + cmpi.b #8,d0 bne.s + move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) + move.w #SndID_Spring,d0 jmp (PlaySound).l ; =========================================================================== ; animation script ; off_29768: Ani_obj7B: offsetTable offsetTableEntry.w byte_29770 ; 0 offsetTableEntry.w byte_29773 ; 1 offsetTableEntry.w byte_29777 ; 2 offsetTableEntry.w byte_29777 ; 3 byte_29770: dc.b $F, 0,$FF rev02even byte_29773: dc.b 0, 3,$FD, 0 rev02even byte_29777: dc.b 5, 1, 2, 2, 2, 4,$FD, 0 even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj7B_MapUnc_29780: BINCLUDE "mappings/sprite/obj7B.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo25_DisplaySprite jmp (DisplaySprite).l JmpTo40_DeleteObject jmp (DeleteObject).l JmpTo8_AnimateSprite jmp (AnimateSprite).l JmpTo42_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo4_SolidObject_Always_SingleCharacter jmp (SolidObject_Always_SingleCharacter).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 7F - Vine switch that you hang off in MCZ ; ---------------------------------------------------------------------------- ; Sprite_297E4: Obj7F: moveq #0,d0 move.b routine(a0),d0 move.w Obj7F_Index(pc,d0.w),d1 jmp Obj7F_Index(pc,d1.w) ; =========================================================================== ; off_297F2: Obj7F_Index: offsetTable offsetTableEntry.w Obj7F_Init ; 0 offsetTableEntry.w Obj7F_Main ; 2 ; =========================================================================== ; loc_297F6: Obj7F_Init: addq.b #2,routine(a0) move.l #Obj7F_MapUnc_29938,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_VineSwitch,3,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo43_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #8,width_pixels(a0) move.b #4,priority(a0) ; loc_2981E: Obj7F_Main: lea objoff_30(a0),a2 lea (MainCharacter).w,a1 ; a1=character move.w (Ctrl_1).w,d0 bsr.s Obj7F_Action lea (Sidekick).w,a1 ; a1=character addq.w #1,a2 move.w (Ctrl_2).w,d0 bsr.s Obj7F_Action jmpto (MarkObjGone).l, JmpTo24_MarkObjGone ; =========================================================================== ; loc_2983C: Obj7F_Action: tst.b (a2) beq.s loc_29890 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 beq.w return_29936 clr.b obj_control(a1) clr.b (a2) move.b #$12,2(a2) andi.w #(button_up_mask|button_down_mask|button_left_mask|button_right_mask)<<8,d0 beq.s + move.b #$3C,2(a2) + move.w #-$300,y_vel(a1) move.b subtype(a0),d0 andi.w #$F,d0 lea (ButtonVine_Trigger).w,a3 lea (a3,d0.w),a3 bclr #0,(a3) move.b #0,mapping_frame(a0) tst.w objoff_30(a0) beq.s + move.b #1,mapping_frame(a0) + bra.w return_29936 ; =========================================================================== loc_29890: tst.b 2(a2) beq.s + subq.b #1,2(a2) bne.w return_29936 + move.w x_pos(a1),d0 sub.w x_pos(a0),d0 addi.w #$C,d0 cmpi.w #$18,d0 bhs.w return_29936 move.w y_pos(a1),d1 sub.w y_pos(a0),d1 subi.w #$28,d1 cmpi.w #$10,d1 bhs.w return_29936 tst.b obj_control(a1) bmi.s return_29936 cmpi.b #4,routine(a1) bhs.s return_29936 tst.w (Debug_placement_mode).w bne.s return_29936 clr.w x_vel(a1) clr.w y_vel(a1) clr.w inertia(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$30,y_pos(a1) move.b #AniIDSonAni_Hang2,anim(a1) move.b #1,obj_control(a1) move.b #1,(a2) move.b subtype(a0),d0 andi.w #$F,d0 lea (ButtonVine_Trigger).w,a3 bset #0,(a3,d0.w) move.w #SndID_Blip,d0 jsr (PlaySound).l move.b #0,mapping_frame(a0) tst.w objoff_30(a0) beq.s return_29936 move.b #1,mapping_frame(a0) return_29936: rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj7F_MapUnc_29938: BINCLUDE "mappings/sprite/obj7F.bin" ; =========================================================================== if ~~removeJmpTos JmpTo24_MarkObjGone jmp (MarkObjGone).l JmpTo43_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 80 - Vine that you hang off and it moves down from MCZ ; ---------------------------------------------------------------------------- ; Sprite_2997C: Obj80: moveq #0,d0 move.b routine(a0),d0 move.w Obj80_Index(pc,d0.w),d1 jmp Obj80_Index(pc,d1.w) ; =========================================================================== ; off_2998A: Obj80_Index: offsetTable offsetTableEntry.w Obj80_Init ; 0 - Init offsetTableEntry.w Obj80_MCZ_Main ; 2 - MCZ Vine offsetTableEntry.w Obj80_WFZ_Main ; 4 - WFZ Hook ; =========================================================================== ; loc_29990: Obj80_Init: addq.b #2,routine(a0) move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #4,priority(a0) move.b #$80,y_radius(a0) bset #4,render_flags(a0) move.w y_pos(a0),objoff_3C(a0) cmpi.b #wing_fortress_zone,(Current_Zone).w bne.s Obj80_MCZ_Init addq.b #2,routine(a0) move.l #Obj80_MapUnc_29DD0,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_WfzHook_Fudge,1,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo44_Adjust2PArtPointer move.w #$A0,objoff_2E(a0) move.b subtype(a0),d0 move.b d0,d1 andi.b #$F,d0 beq.s + move.w #$60,objoff_2E(a0) + move.b subtype(a0),d0 move.w #2,objoff_3A(a0) andi.b #$70,d1 beq.s + move.w objoff_2E(a0),d0 move.w d0,objoff_38(a0) move.b #1,objoff_36(a0) add.w d0,y_pos(a0) lsr.w #4,d0 addq.w #1,d0 move.b d0,mapping_frame(a0) + bra.w Obj80_WFZ_Main ; =========================================================================== ; loc_29A1C: Obj80_MCZ_Init: move.l #Obj80_MapUnc_29C64,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_VinePulley,3,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo44_Adjust2PArtPointer move.w #$B0,objoff_2E(a0) move.b subtype(a0),d0 bpl.s + move.b #1,objoff_34(a0) + move.w #2,objoff_3A(a0) andi.b #$70,d0 beq.s Obj80_MCZ_Main move.w objoff_2E(a0),d0 move.w d0,objoff_38(a0) move.b #1,objoff_36(a0) add.w d0,y_pos(a0) lsr.w #5,d0 addq.w #1,d0 move.b d0,mapping_frame(a0) ; loc_29A66: Obj80_MCZ_Main: tst.b objoff_36(a0) beq.s loc_29A74 tst.w objoff_30(a0) bne.s loc_29A8A bra.s loc_29A7A ; =========================================================================== loc_29A74: tst.w objoff_30(a0) beq.s loc_29A8A loc_29A7A: move.w objoff_38(a0),d2 cmp.w objoff_2E(a0),d2 beq.s loc_29AAE add.w objoff_3A(a0),d2 bra.s loc_29A94 ; =========================================================================== loc_29A8A: move.w objoff_38(a0),d2 beq.s loc_29AAE sub.w objoff_3A(a0),d2 loc_29A94: move.w d2,objoff_38(a0) move.w objoff_3C(a0),d0 add.w d2,d0 move.w d0,y_pos(a0) move.w d2,d0 beq.s + lsr.w #5,d0 addq.w #1,d0 + move.b d0,mapping_frame(a0) loc_29AAE: lea objoff_30(a0),a2 lea (MainCharacter).w,a1 ; a1=character move.w (Ctrl_1).w,d0 bsr.s Obj80_Action lea (Sidekick).w,a1 ; a1=character addq.w #1,a2 move.w (Ctrl_2).w,d0 bsr.s Obj80_Action jmpto (MarkObjGone).l, JmpTo25_MarkObjGone ; =========================================================================== ; loc_29ACC: Obj80_Action: tst.b (a2) beq.w loc_29B5E tst.b render_flags(a1) bpl.s loc_29B42 cmpi.b #4,routine(a1) bhs.s loc_29B42 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 beq.w loc_29B50 clr.b obj_control(a1) clr.b (a2) move.b #$12,2(a2) andi.w #(button_up_mask|button_down_mask|button_left_mask|button_right_mask)<<8,d0 beq.w + move.b #$3C,2(a2) + btst #(button_left+8),d0 beq.s + move.w #-$200,x_vel(a1) + btst #(button_right+8),d0 beq.s + move.w #$200,x_vel(a1) + move.w #-$380,y_vel(a1) bset #1,status(a1) tst.b objoff_34(a0) beq.s + ; rts move.b subtype(a0),d0 andi.w #$F,d0 lea (ButtonVine_Trigger).w,a3 lea (a3,d0.w),a3 bclr #0,(a3) + rts ; =========================================================================== loc_29B42: clr.b obj_control(a1) clr.b (a2) move.b #$3C,2(a2) rts ; =========================================================================== loc_29B50: move.w y_pos(a0),y_pos(a1) addi.w #$94,y_pos(a1) rts ; =========================================================================== loc_29B5E: tst.b 2(a2) beq.s + subq.b #1,2(a2) bne.w return_29BF8 + move.w x_pos(a1),d0 sub.w x_pos(a0),d0 addi.w #$10,d0 cmpi.w #$20,d0 bhs.w return_29BF8 move.w y_pos(a1),d1 sub.w y_pos(a0),d1 subi.w #$88,d1 cmpi.w #$18,d1 bhs.w return_29BF8 tst.b obj_control(a1) bmi.s return_29BF8 cmpi.b #4,routine(a1) bhs.s return_29BF8 tst.w (Debug_placement_mode).w bne.s return_29BF8 clr.w x_vel(a1) clr.w y_vel(a1) clr.w inertia(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$94,y_pos(a1) move.b #AniIDSonAni_Hang2,anim(a1) move.b #1,obj_control(a1) move.b #1,(a2) tst.b objoff_34(a0) beq.s return_29BF8 move.b subtype(a0),d0 andi.w #$F,d0 lea (ButtonVine_Trigger).w,a3 bset #0,(a3,d0.w) move.w #SndID_Blip,d0 jsr (PlaySound).l return_29BF8: rts ; =========================================================================== ; loc_29BFA: Obj80_WFZ_Main: tst.b objoff_36(a0) beq.s loc_29C08 tst.w objoff_30(a0) bne.s loc_29C1E bra.s loc_29C0E ; =========================================================================== loc_29C08: tst.w objoff_30(a0) beq.s loc_29C1E loc_29C0E: move.w objoff_38(a0),d2 cmp.w objoff_2E(a0),d2 beq.s loc_29C42 add.w objoff_3A(a0),d2 bra.s loc_29C28 ; =========================================================================== loc_29C1E: move.w objoff_38(a0),d2 beq.s loc_29C42 sub.w objoff_3A(a0),d2 loc_29C28: move.w d2,objoff_38(a0) move.w objoff_3C(a0),d0 add.w d2,d0 move.w d0,y_pos(a0) move.w d2,d0 beq.s + lsr.w #4,d0 addq.w #1,d0 + move.b d0,mapping_frame(a0) loc_29C42: lea objoff_30(a0),a2 lea (MainCharacter).w,a1 ; a1=character move.w (Ctrl_1).w,d0 bsr.w Obj80_Action lea (Sidekick).w,a1 ; a1=character addq.w #1,a2 move.w (Ctrl_2).w,d0 bsr.w Obj80_Action jmpto (MarkObjGone).l, JmpTo25_MarkObjGone ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj80_MapUnc_29C64: BINCLUDE "mappings/sprite/obj80_a.bin" ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj80_MapUnc_29DD0: BINCLUDE "mappings/sprite/obj80_b.bin" ; =========================================================================== if ~~removeJmpTos JmpTo25_MarkObjGone jmp (MarkObjGone).l JmpTo44_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 81 - Drawbridge (MCZ) ; ---------------------------------------------------------------------------- ; Sprite_2A000: Obj81: btst #6,render_flags(a0) bne.w + moveq #0,d0 move.b routine(a0),d0 move.w Obj81_Index(pc,d0.w),d1 jmp Obj81_Index(pc,d1.w) ; =========================================================================== + move.w #$280,d0 jmpto (DisplaySprite3).l, JmpTo2_DisplaySprite3 ; =========================================================================== ; off_2A020: Obj81_Index: offsetTable offsetTableEntry.w Obj81_Init ; 0 offsetTableEntry.w Obj81_BridgeUp ; 2 offsetTableEntry.w loc_2A18A ; 4 ; =========================================================================== ; loc_2A026: Obj81_Init: addq.b #2,routine(a0) move.l #Obj81_MapUnc_2A24E,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_MCZGateLog,3,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo45_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #5,priority(a0) move.b #8,width_pixels(a0) ori.b #$80,status(a0) move.w x_pos(a0),objoff_30(a0) move.w y_pos(a0),objoff_32(a0) subi.w #$48,y_pos(a0) move.b #-$40,angle(a0) moveq #-$10,d4 btst #1,status(a0) beq.s + addi.w #$90,y_pos(a0) move.b #$40,angle(a0) neg.w d4 + move.w #$100,d1 btst #0,status(a0) beq.s + neg.w d1 + move.w d1,objoff_34(a0) jsrto (SingleObjLoad2).l, JmpTo18_SingleObjLoad2 bne.s Obj81_BridgeUp _move.b id(a0),id(a1) ; load obj81 move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) move.b #4,render_flags(a1) bset #6,render_flags(a1) move.b #$40,mainspr_width(a1) move.w objoff_30(a0),d2 move.w objoff_32(a0),d3 moveq #8,d1 move.b d1,mainspr_childsprites(a1) subq.w #1,d1 lea sub2_x_pos(a1),a2 - add.w d4,d3 move.w d2,(a2)+ ; sub?_x_pos move.w d3,(a2)+ ; sub?_y_pos move.w #1,(a2)+ ; sub?_mapframe dbf d1,- move.w sub6_x_pos(a1),x_pos(a1) move.w sub6_y_pos(a1),y_pos(a1) move.l a1,objoff_3C(a0) move.b #$40,mainspr_height(a1) bset #4,render_flags(a1) ; loc_2A0FE: Obj81_BridgeUp: lea (ButtonVine_Trigger).w,a2 moveq #0,d0 move.b subtype(a0),d0 btst #0,(a2,d0.w) beq.s + tst.b objoff_36(a0) bne.s + move.b #1,objoff_36(a0) move.w #SndID_DrawbridgeMove,d0 jsr (PlaySoundStereo).l cmpi.b #$81,status(a0) bne.s + move.w objoff_30(a0),x_pos(a0) subi.w #$48,x_pos(a0) + tst.b objoff_36(a0) beq.s loc_2A188 move.w #$48,d1 tst.b angle(a0) beq.s loc_2A154 cmpi.b #$80,angle(a0) bne.s loc_2A180 neg.w d1 loc_2A154: move.w objoff_32(a0),y_pos(a0) move.w objoff_30(a0),x_pos(a0) add.w d1,x_pos(a0) move.b #$40,width_pixels(a0) move.b #0,objoff_36(a0) move.w #SndID_DrawbridgeDown,d0 jsr (PlaySound).l addq.b #2,routine(a0) bra.s loc_2A188 ; =========================================================================== loc_2A180: move.w objoff_34(a0),d0 add.w d0,angle(a0) loc_2A188: bsr.s loc_2A1EA loc_2A18A: move.w #$13,d1 move.w #$40,d2 move.w #$41,d3 move.b angle(a0),d0 beq.s loc_2A1A8 cmpi.b #$40,d0 beq.s loc_2A1B4 cmpi.b #-$40,d0 bhs.s loc_2A1B4 loc_2A1A8: move.w #$4B,d1 move.w #8,d2 move.w #9,d3 loc_2A1B4: move.w x_pos(a0),d4 jsrto (SolidObject).l, JmpTo22_SolidObject tst.w (Two_player_mode).w beq.s + jmpto (DisplaySprite).l, JmpTo26_DisplaySprite ; --------------------------------------------------------------------------- + move.w objoff_30(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w + jmpto (DisplaySprite).l, JmpTo26_DisplaySprite ; --------------------------------------------------------------------------- + movea.l objoff_3C(a0),a1 ; a1=object jsrto (DeleteObject2).l, JmpTo3_DeleteObject2 jmpto (DeleteObject).l, JmpTo41_DeleteObject ; =========================================================================== loc_2A1EA: tst.b objoff_36(a0) beq.s return_2A24C moveq #0,d0 moveq #0,d1 move.b angle(a0),d0 jsrto (CalcSine).l, JmpTo9_CalcSine move.w objoff_32(a0),d2 move.w objoff_30(a0),d3 moveq #0,d6 movea.l objoff_3C(a0),a1 ; a1=object move.b mainspr_childsprites(a1),d6 subq.w #1,d6 bcs.s return_2A24C swap d0 swap d1 asr.l #4,d0 asr.l #4,d1 move.l d0,d4 move.l d1,d5 lea sub2_x_pos(a1),a2 - movem.l d4-d5,-(sp) swap d4 swap d5 add.w d2,d4 add.w d3,d5 move.w d5,(a2)+ ; sub?_x_pos move.w d4,(a2)+ ; sub?_y_pos movem.l (sp)+,d4-d5 add.l d0,d4 add.l d1,d5 addq.w #next_subspr-4,a2 dbf d6,- move.w sub6_x_pos(a1),x_pos(a1) move.w sub6_y_pos(a1),y_pos(a1) return_2A24C: rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj81_MapUnc_2A24E: BINCLUDE "mappings/sprite/obj81.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo2_DisplaySprite3 jmp (DisplaySprite3).l JmpTo26_DisplaySprite jmp (DisplaySprite).l JmpTo41_DeleteObject jmp (DeleteObject).l JmpTo3_DeleteObject2 jmp (DeleteObject2).l JmpTo18_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo45_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo9_CalcSine jmp (CalcSine).l JmpTo22_SolidObject jmp (SolidObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 82 - Platform that is usually swinging, from ARZ ; ---------------------------------------------------------------------------- ; Sprite_2A290: Obj82: moveq #0,d0 move.b routine(a0),d0 move.w Obj82_Index(pc,d0.w),d1 jmp Obj82_Index(pc,d1.w) ; =========================================================================== ; off_2A29E: Obj82_Index: offsetTable offsetTableEntry.w Obj82_Init ; 0 offsetTableEntry.w Obj82_Main ; 2 ; =========================================================================== ; byte_2A2A2: Obj82_Properties: ; width_pixels ; y_radius dc.b $20, 8 ; 0 dc.b $1C,$30 ; 2 ; Unused and broken; these don't have an associated frame, so using them crashes the game dc.b $10,$10 ; 4 dc.b $10,$10 ; 6 ; =========================================================================== ; loc_2A2AA: Obj82_Init: addq.b #2,routine(a0) move.l #Obj82_MapUnc_2A476,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo46_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #3,priority(a0) moveq #0,d0 move.b subtype(a0),d0 lsr.w #3,d0 andi.w #$E,d0 lea Obj82_Properties(pc,d0.w),a2 move.b (a2)+,width_pixels(a0) move.b (a2),y_radius(a0) lsr.w #1,d0 move.b d0,mapping_frame(a0) move.w x_pos(a0),objoff_34(a0) move.w y_pos(a0),objoff_30(a0) move.b subtype(a0),d0 andi.b #$F,d0 beq.s + cmpi.b #7,d0 beq.s + move.b #1,objoff_38(a0) + andi.b #$F,subtype(a0) ; loc_2A312: Obj82_Main: move.w x_pos(a0),-(sp) moveq #0,d0 move.b subtype(a0),d0 add.w d0,d0 move.w Obj82_Types(pc,d0.w),d1 jsr Obj82_Types(pc,d1.w) move.w (sp)+,d4 tst.b render_flags(a0) bpl.s + moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b y_radius(a0),d2 move.w d2,d3 addq.w #1,d3 jsrto (SolidObject).l, JmpTo23_SolidObject swap d6 move.b d6,objoff_3F(a0) bsr.w loc_2A432 + move.w objoff_34(a0),d0 jmpto (MarkObjGone2).l, JmpTo7_MarkObjGone2 ; =========================================================================== ; off_2A358: Obj82_Types: offsetTable offsetTableEntry.w return_2A368 ; 0 offsetTableEntry.w loc_2A36A ; 1 offsetTableEntry.w loc_2A392 ; 2 offsetTableEntry.w loc_2A36A ; 3 offsetTableEntry.w loc_2A3B6 ; 4 offsetTableEntry.w loc_2A3D8 ; 5 offsetTableEntry.w loc_2A392 ; 6 offsetTableEntry.w loc_2A3EC ; 7 ; =========================================================================== return_2A368: rts ; =========================================================================== loc_2A36A: tst.w objoff_36(a0) bne.s loc_2A382 move.b status(a0),d0 andi.b #standing_mask,d0 beq.s return_2A380 move.w #$1E,objoff_36(a0) return_2A380: rts ; =========================================================================== loc_2A382: subq.w #1,objoff_36(a0) bne.s return_2A380 addq.b #1,subtype(a0) clr.b objoff_38(a0) rts ; =========================================================================== loc_2A392: jsrto (ObjectMove).l, JmpTo16_ObjectMove addi_.w #8,y_vel(a0) jsrto (ObjCheckFloorDist).l, JmpTo2_ObjCheckFloorDist tst.w d1 bpl.w return_2A3B4 addq.w #1,d1 add.w d1,y_pos(a0) clr.w y_vel(a0) clr.b subtype(a0) return_2A3B4: rts ; =========================================================================== loc_2A3B6: jsrto (ObjectMove).l, JmpTo16_ObjectMove subi_.w #8,y_vel(a0) jsrto (ObjCheckCeilingDist).l, JmpTo_ObjCheckCeilingDist tst.w d1 bpl.w return_2A3D6 sub.w d1,y_pos(a0) clr.w y_vel(a0) clr.b subtype(a0) return_2A3D6: rts ; =========================================================================== loc_2A3D8: move.b objoff_3F(a0),d0 andi.b #3,d0 beq.s return_2A3EA addq.b #1,subtype(a0) clr.b objoff_38(a0) return_2A3EA: rts ; =========================================================================== loc_2A3EC: move.w (Water_Level_1).w,d0 sub.w y_pos(a0),d0 beq.s return_2A430 bcc.s loc_2A414 cmpi.w #-2,d0 bge.s loc_2A400 moveq #-2,d0 loc_2A400: add.w d0,y_pos(a0) jsrto (ObjCheckCeilingDist).l, JmpTo_ObjCheckCeilingDist tst.w d1 bpl.w return_2A412 sub.w d1,y_pos(a0) return_2A412: rts ; =========================================================================== loc_2A414: cmpi.w #2,d0 ble.s loc_2A41C moveq #2,d0 loc_2A41C: add.w d0,y_pos(a0) jsrto (ObjCheckFloorDist).l, JmpTo2_ObjCheckFloorDist tst.w d1 bpl.w return_2A430 addq.w #1,d1 add.w d1,y_pos(a0) return_2A430: rts ; =========================================================================== loc_2A432: tst.b objoff_38(a0) beq.s return_2A474 move.b status(a0),d0 andi.b #standing_mask,d0 bne.s loc_2A44E tst.b objoff_3E(a0) beq.s return_2A474 subq.b #4,objoff_3E(a0) bra.s loc_2A45A ; =========================================================================== loc_2A44E: cmpi.b #$40,objoff_3E(a0) beq.s return_2A474 addq.b #4,objoff_3E(a0) loc_2A45A: move.b objoff_3E(a0),d0 jsr (CalcSine).l move.w #$400,d1 muls.w d1,d0 swap d0 add.w objoff_30(a0),d0 move.w d0,y_pos(a0) return_2A474: rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj82_MapUnc_2A476: BINCLUDE "mappings/sprite/obj82.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo2_ObjCheckFloorDist jmp (ObjCheckFloorDist).l JmpTo46_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo_ObjCheckCeilingDist jmp (ObjCheckCeilingDist).l JmpTo23_SolidObject jmp (SolidObject).l JmpTo7_MarkObjGone2 jmp (MarkObjGone2).l ; loc_2A4F6: JmpTo16_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 83 - 3 adjoined platforms from ARZ that rotate in a circle ; ---------------------------------------------------------------------------- ; OST Variables: Obj83_last_x_pos = objoff_2C ; word Obj83_speed = objoff_2E ; word Obj83_initial_x_pos = objoff_30 ; word Obj83_initial_y_pos = objoff_32 ; word ; Child object RAM pointers Obj83_childobjptr_chains = objoff_34 ; longword ; chain multisprite object Obj83_childobjptr_platform2 = objoff_38 ; longword ; 2nd platform object (parent object is 1st platform) Obj83_childobjptr_platform3 = objoff_3C ; longword ; 3rd platform object ; Sprite_2A4FC: Obj83: btst #6,render_flags(a0) bne.w .isMultispriteObject moveq #0,d0 move.b routine(a0),d0 move.w Obj83_Index(pc,d0.w),d1 jmp Obj83_Index(pc,d1.w) ; =========================================================================== .isMultispriteObject: move.w #$280,d0 jmpto (DisplaySprite3).l, JmpTo3_DisplaySprite3 ; =========================================================================== ; off_2A51C: Obj83_Index: offsetTable offsetTableEntry.w Obj83_Init ; 0 offsetTableEntry.w Obj83_Main ; 2 offsetTableEntry.w Obj83_PlatformSubObject ; 4 ; =========================================================================== ; loc_2A522: Obj83_Init: addq.b #2,routine(a0) move.l #Obj15_Obj83_MapUnc_1021E,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo47_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #4,priority(a0) move.b #$20,width_pixels(a0) move.w x_pos(a0),Obj83_initial_x_pos(a0) move.w y_pos(a0),Obj83_initial_y_pos(a0) ; Setup subtype variables (rotation speed and other unused variable) move.b subtype(a0),d1 move.b d1,d0 andi.w #$F,d1 ; The lower 4 bits of subtype are unused, making these instructions useless andi.b #$F0,d0 ext.w d0 asl.w #3,d0 move.w d0,Obj83_speed(a0) ; Set angle according to X-flip and Y-flip move.b status(a0),d0 ror.b #2,d0 andi.b #$C0,d0 move.b d0,angle(a0) ; Create child object (chain multisprite) jsrto (SingleObjLoad2).l, JmpTo19_SingleObjLoad2 bne.s .noRAMforChildObjects _move.b id(a0),id(a1) ; load obj83 move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) move.b #4,render_flags(a1) bset #6,render_flags(a1) move.b #$40,mainspr_width(a1) moveq #8,d1 move.b d1,mainspr_childsprites(a1) subq.w #1,d1 lea sub2_x_pos(a1),a2 .nextChildSprite: addq.w #next_subspr-2,a2 move.w #1,(a2)+ ; sub?_mapframe dbf d1,.nextChildSprite move.b #1,mainspr_mapframe(a1) move.b #$40,mainspr_height(a1) bset #4,render_flags(a1) move.l a1,Obj83_childobjptr_chains(a0) ; Create remaining child objects: platform 2 and 3 bsr.s Obj83_LoadSubObject move.l a1,Obj83_childobjptr_platform2(a0) bsr.s Obj83_LoadSubObject move.l a1,Obj83_childobjptr_platform3(a0) .noRAMforChildObjects: bra.s Obj83_Main ; =========================================================================== ; loc_2A5DE: Obj83_LoadSubObject: jsrto (SingleObjLoad2).l, JmpTo19_SingleObjLoad2 bne.s .noRAMforChildObject ; rts addq.b #4,routine(a1) _move.b id(a0),id(a1) ; load obj move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) move.b #4,render_flags(a1) move.b #4,priority(a1) move.b #$20,width_pixels(a1) move.w x_pos(a0),Obj83_initial_x_pos(a1) move.w y_pos(a0),Obj83_initial_y_pos(a1) move.w x_pos(a0),Obj83_last_x_pos(a1) .noRAMforChildObject: rts ; =========================================================================== ; loc_2A620: Obj83_Main: move.w x_pos(a0),-(sp) moveq #0,d0 moveq #0,d1 move.w Obj83_speed(a0),d0 add.w d0,angle(a0) move.w Obj83_initial_y_pos(a0),d2 move.w Obj83_initial_x_pos(a0),d3 moveq #0,d6 movea.l Obj83_childobjptr_chains(a0),a1 ; a1=object lea sub2_x_pos(a1),a2 ; Update first row of chains move.b angle(a0),d0 jsrto (CalcSine).l, JmpTo10_CalcSine swap d0 swap d1 asr.l #4,d0 asr.l #4,d1 move.l d0,d4 move.l d1,d5 swap d4 swap d5 add.w d2,d4 add.w d3,d5 move.w d5,x_pos(a1) ; update chainlink mainsprite x_pos move.w d4,y_pos(a1) ; update chainlink mainsprite y_pos move.l d0,d4 move.l d1,d5 add.l d0,d4 add.l d1,d5 moveq #1,d6 ; Update 2 chainlink childsprites (the third chainlink is the mainsprite, which has already been updated) bsr.w Obj83_UpdateChainSpritePosition swap d4 swap d5 add.w d2,d4 add.w d3,d5 move.w d5,x_pos(a0) move.w d4,y_pos(a0) ; Update second row of chains move.b angle(a0),d0 addi.b #256/3,d0 ; 360 degrees = 256 jsrto (CalcSine).l, JmpTo10_CalcSine swap d0 swap d1 asr.l #4,d0 asr.l #4,d1 move.l d0,d4 move.l d1,d5 moveq #2,d6 ; Update 3 chainlink childsprites bsr.w Obj83_UpdateChainSpritePosition swap d4 swap d5 add.w d2,d4 add.w d3,d5 movea.l Obj83_childobjptr_platform2(a0),a1 ; a1=object move.w d5,x_pos(a1) move.w d4,y_pos(a1) ; Update third row of chains move.b angle(a0),d0 subi.b #256/3,d0 ; 360 degrees = 256 jsrto (CalcSine).l, JmpTo10_CalcSine swap d0 swap d1 asr.l #4,d0 asr.l #4,d1 move.l d0,d4 move.l d1,d5 moveq #2,d6 ; Update 3 chainlink childsprites bsr.w Obj83_UpdateChainSpritePosition swap d4 swap d5 add.w d2,d4 add.w d3,d5 movea.l Obj83_childobjptr_platform3(a0),a1 ; a1=object move.w d5,x_pos(a1) move.w d4,y_pos(a1) moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 move.w #8,d2 move.w #9,d3 move.w (sp)+,d4 jsrto (PlatformObject).l, JmpTo7_PlatformObject tst.w (Two_player_mode).w beq.s .notTwoPlayerMode jmpto (DisplaySprite).l, JmpTo27_DisplaySprite ; =========================================================================== .notTwoPlayerMode: move.w Obj83_initial_x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w .objectOffscreen jmpto (DisplaySprite).l, JmpTo27_DisplaySprite ; =========================================================================== .objectOffscreen: movea.l Obj83_childobjptr_chains(a0),a1 ; a1=object jsrto (DeleteObject2).l, JmpTo4_DeleteObject2 jmpto (DeleteObject).l, JmpTo42_DeleteObject ; =========================================================================== ; loc_2A72E: Obj83_UpdateChainSpritePosition: .nextChainSprite: movem.l d4-d5,-(sp) swap d4 swap d5 add.w d2,d4 add.w d3,d5 move.w d5,(a2)+ ; sub?_x_pos move.w d4,(a2)+ ; sub?_y_pos movem.l (sp)+,d4-d5 add.l d0,d4 add.l d1,d5 addq.w #next_subspr-4,a2 dbf d6,.nextChainSprite rts ; =========================================================================== ; loc_2A74E: Obj83_SubObject: Obj83_PlatformSubObject: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 move.w #8,d2 move.w #9,d3 move.w Obj83_last_x_pos(a0),d4 jsrto (PlatformObject).l, JmpTo7_PlatformObject move.w x_pos(a0),Obj83_last_x_pos(a0) move.w Obj83_initial_x_pos(a0),d0 jmpto (MarkObjGone2).l, JmpTo8_MarkObjGone2 ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo3_DisplaySprite3 jmp (DisplaySprite3).l JmpTo27_DisplaySprite jmp (DisplaySprite).l JmpTo42_DeleteObject jmp (DeleteObject).l JmpTo4_DeleteObject2 jmp (DeleteObject2).l JmpTo19_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo47_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo10_CalcSine jmp (CalcSine).l JmpTo7_PlatformObject jmp (PlatformObject).l JmpTo8_MarkObjGone2 jmp (MarkObjGone2).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 3F - Fan from OOZ ; ---------------------------------------------------------------------------- ; Sprite_2A7B0: Obj3F: moveq #0,d0 move.b routine(a0),d0 move.w Obj3F_Index(pc,d0.w),d1 jmp Obj3F_Index(pc,d1.w) ; =========================================================================== ; off_2A7BE: Obj3F_Index: offsetTable offsetTableEntry.w Obj3F_Init ; 0 offsetTableEntry.w Obj3F_Horizontal ; 2 - pushes horizontally offsetTableEntry.w Obj3F_Vertical ; 4 - pushes vertically ; =========================================================================== ; loc_2A7C4: Obj3F_Init: addq.b #2,routine(a0) move.l #Obj3F_MapUnc_2AA12,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_OOZFanHoriz,3,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo48_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #4,priority(a0) tst.b subtype(a0) bpl.s Obj3F_Horizontal addq.b #2,routine(a0) move.l #Obj3F_MapUnc_2AAC4,mappings(a0) bra.w Obj3F_Vertical ; =========================================================================== ; loc_2A802: Obj3F_Horizontal: btst #1,subtype(a0) bne.s loc_2A82A subq.w #1,objoff_30(a0) bpl.s loc_2A82A move.w #0,objoff_34(a0) move.w #$78,objoff_30(a0) bchg #0,objoff_32(a0) beq.s loc_2A82A move.w #$B4,objoff_30(a0) loc_2A82A: tst.b objoff_32(a0) beq.w loc_2A84E subq.b #1,anim_frame_duration(a0) bpl.s BranchTo_JmpTo26_MarkObjGone cmpi.w #$400,objoff_34(a0) bhs.s BranchTo_JmpTo26_MarkObjGone addi.w #$2A,objoff_34(a0) move.b objoff_34(a0),anim_frame_duration(a0) bra.s loc_2A86A ; =========================================================================== loc_2A84E: lea (MainCharacter).w,a1 ; a1=character bsr.w loc_2A894 lea (Sidekick).w,a1 ; a1=character bsr.w loc_2A894 subq.b #1,anim_frame_duration(a0) bpl.s BranchTo_JmpTo26_MarkObjGone move.b #0,anim_frame_duration(a0) loc_2A86A: addq.b #1,anim_frame(a0) cmpi.b #6,anim_frame(a0) blo.s loc_2A87C move.b #0,anim_frame(a0) loc_2A87C: moveq #0,d0 btst #0,subtype(a0) beq.s loc_2A888 moveq #5,d0 loc_2A888: add.b anim_frame(a0),d0 move.b d0,mapping_frame(a0) BranchTo_JmpTo26_MarkObjGone jmpto (MarkObjGone).l, JmpTo26_MarkObjGone ; =========================================================================== loc_2A894: cmpi.b #4,routine(a1) bhs.s return_2A8FC tst.b obj_control(a1) bne.s return_2A8FC move.w x_pos(a1),d0 sub.w x_pos(a0),d0 btst #0,status(a0) bne.s loc_2A8B4 neg.w d0 loc_2A8B4: addi.w #$50,d0 cmpi.w #$F0,d0 bhs.s return_2A8FC move.w y_pos(a1),d1 addi.w #$60,d1 sub.w y_pos(a0),d1 bcs.s return_2A8FC cmpi.w #$70,d1 bhs.s return_2A8FC subi.w #$50,d0 bcc.s loc_2A8DC not.w d0 add.w d0,d0 loc_2A8DC: addi.w #$60,d0 btst #0,status(a0) bne.s loc_2A8EA neg.w d0 loc_2A8EA: neg.b d0 asr.w #4,d0 btst #0,subtype(a0) beq.s loc_2A8F8 neg.w d0 loc_2A8F8: add.w d0,x_pos(a1) return_2A8FC: rts ; =========================================================================== ; loc_2A8FE: Obj3F_Vertical: btst #1,subtype(a0) bne.s loc_2A926 subq.w #1,objoff_30(a0) bpl.s loc_2A926 move.w #0,objoff_34(a0) move.w #$78,objoff_30(a0) bchg #0,objoff_32(a0) beq.s loc_2A926 move.w #$B4,objoff_30(a0) loc_2A926: tst.b objoff_32(a0) beq.w loc_2A94A subq.b #1,anim_frame_duration(a0) bpl.s BranchTo2_JmpTo26_MarkObjGone cmpi.w #$400,objoff_34(a0) bhs.s BranchTo2_JmpTo26_MarkObjGone addi.w #$2A,objoff_34(a0) move.b objoff_34(a0),anim_frame_duration(a0) bra.s loc_2A966 ; =========================================================================== loc_2A94A: lea (MainCharacter).w,a1 ; a1=character bsr.w loc_2A990 lea (Sidekick).w,a1 ; a1=character bsr.w loc_2A990 subq.b #1,anim_frame_duration(a0) bpl.s BranchTo2_JmpTo26_MarkObjGone move.b #0,anim_frame_duration(a0) loc_2A966: addq.b #1,anim_frame(a0) cmpi.b #6,anim_frame(a0) blo.s + move.b #0,anim_frame(a0) + moveq #0,d0 btst #0,subtype(a0) beq.s + moveq #5,d0 + add.b anim_frame(a0),d0 move.b d0,mapping_frame(a0) BranchTo2_JmpTo26_MarkObjGone jmpto (MarkObjGone).l, JmpTo26_MarkObjGone ; =========================================================================== loc_2A990: cmpi.b #4,routine(a1) bhs.s return_2AA10 tst.b obj_control(a1) bne.s return_2AA10 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 addi.w #$40,d0 cmpi.w #$80,d0 bhs.s return_2AA10 moveq #0,d1 move.b (Oscillating_Data+$14).w,d1 add.w y_pos(a1),d1 addi.w #$60,d1 sub.w y_pos(a0),d1 bcs.s return_2AA10 cmpi.w #$90,d1 bhs.s return_2AA10 subi.w #$60,d1 bcs.s + not.w d1 add.w d1,d1 + addi.w #$60,d1 neg.w d1 asr.w #4,d1 add.w d1,y_pos(a1) bset #1,status(a1) move.w #0,y_vel(a1) move.w #1,inertia(a1) tst.b flip_angle(a1) bne.s return_2AA10 move.b #1,flip_angle(a1) move.b #AniIDSonAni_Walk,anim(a1) move.b #$7F,flips_remaining(a1) move.b #8,flip_speed(a1) return_2AA10: rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ; sidefacing fan Obj3F_MapUnc_2AA12: BINCLUDE "mappings/sprite/obj3F_a.bin" ; upfacing fan Obj3F_MapUnc_2AAC4: BINCLUDE "mappings/sprite/obj3F_b.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo26_MarkObjGone jmp (MarkObjGone).l JmpTo48_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 85 - Spring from CNZ that you hold jump on to pull back further ; ---------------------------------------------------------------------------- ; Sprite_2AB84: Obj85: moveq #0,d0 move.b routine(a0),d0 move.w Obj85_Index(pc,d0.w),d1 jsr Obj85_Index(pc,d1.w) move.w #$200,d0 tst.w (Two_player_mode).w beq.s + jmpto (DisplaySprite3).l, JmpTo4_DisplaySprite3 ; =========================================================================== + move.w x_pos(a0),d1 andi.w #$FF80,d1 sub.w (Camera_X_pos_coarse).w,d1 cmpi.w #$280,d1 bhi.w + jmpto (DisplaySprite3).l, JmpTo4_DisplaySprite3 ; =========================================================================== + lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s BranchTo_JmpTo43_DeleteObject bclr #7,2(a2,d0.w) BranchTo_JmpTo43_DeleteObject jmpto (DeleteObject).l, JmpTo43_DeleteObject ; =========================================================================== ; off_2ABCE: Obj85_Index: offsetTable offsetTableEntry.w Obj85_Init ; 0 offsetTableEntry.w Obj85_Up ; 2 offsetTableEntry.w Obj85_Diagonal ; 4 ; =========================================================================== ; loc_2ABD4: Obj85_Init: addq.b #2,routine(a0) move.l #Obj85_MapUnc_2B07E,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CNZVertPlunger,0,0),art_tile(a0) tst.b subtype(a0) beq.s + move.l #Obj85_MapUnc_2B0EC,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CNZDiagPlunger,0,0),art_tile(a0) + jsrto (Adjust2PArtPointer).l, JmpTo49_Adjust2PArtPointer move.b #4,render_flags(a0) bset #6,render_flags(a0) move.b #1,mainspr_mapframe(a0) tst.b subtype(a0) beq.s Obj85_Init_Up addq.b #2,routine(a0) move.b #$20,mainspr_width(a0) move.b #$18,width_pixels(a0) move.w x_pos(a0),objoff_2E(a0) move.w y_pos(a0),objoff_34(a0) move.w x_pos(a0),d2 move.w y_pos(a0),d3 addi.w #0,d3 move.b #1,mainspr_childsprites(a0) lea sub2_x_pos(a0),a2 move.w d2,(a2)+ ; sub2_x_pos move.w d3,(a2)+ ; sub2_y_pos move.w #2,(a2)+ ; sub2_mapframe bra.w Obj85_Diagonal ; =========================================================================== ; loc_2AC54: Obj85_Init_Up: move.b #$18,mainspr_width(a0) move.b #$18,width_pixels(a0) move.w y_pos(a0),objoff_34(a0) move.w x_pos(a0),d2 move.w y_pos(a0),d3 addi.w #$20,d3 move.b #1,mainspr_childsprites(a0) lea sub2_x_pos(a0),a2 move.w d2,(a2)+ ; sub2_x_pos move.w d3,(a2)+ ; sub2_y_pos move.w #2,(a2)+ ; sub2_mapframe ; loc_2AC84: Obj85_Up: move.b #0,objoff_3A(a0) move.w objoff_34(a0),d0 add.w objoff_38(a0),d0 move.w d0,y_pos(a0) move.b #2,sub2_mapframe(a0) cmpi.w #$10,objoff_38(a0) blo.s + move.b #3,sub2_mapframe(a0) + move.w #$23,d1 move.w #$20,d2 move.w #$1D,d3 move.w x_pos(a0),d4 lea objoff_36(a0),a2 lea (MainCharacter).w,a1 ; a1=character move.w (Ctrl_1_Logical).w,d5 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s loc_2AD26 movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character addq.w #1,a2 move.w (Ctrl_2).w,d5 moveq #p2_standing_bit,d6 bsr.s loc_2AD26 tst.w objoff_36(a0) beq.s loc_2AD14 tst.w objoff_38(a0) beq.s return_2AD24 moveq #0,d0 cmpi.b #1,objoff_36(a0) bne.s + or.w (Ctrl_1_Logical).w,d0 + cmpi.b #1,objoff_37(a0) bne.s + or.w (Ctrl_2).w,d0 + andi.w #(button_B_mask|button_C_mask|button_A_mask)<<8,d0 bne.s return_2AD24 move.w #$202,objoff_36(a0) rts ; =========================================================================== loc_2AD14: move.b #1,mainspr_mapframe(a0) subq.w #4,objoff_38(a0) bcc.s return_2AD24 clr.w objoff_38(a0) return_2AD24: rts ; =========================================================================== loc_2AD26: move.b (a2),d0 bne.s loc_2AD7A loc_2AD2A: tst.w (Debug_placement_mode).w bne.s return_2AD78 tst.w y_vel(a1) bmi.s return_2AD78 jsrto (SolidObject_Always_SingleCharacter).l, JmpTo5_SolidObject_Always_SingleCharacter btst d6,status(a0) beq.s return_2AD78 move.b #$81,obj_control(a1) move.w x_pos(a0),x_pos(a1) move.w #0,x_vel(a1) move.w #0,y_vel(a1) move.w #0,inertia(a1) bset #2,status(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #AniIDSonAni_Roll,anim(a1) addq.b #1,(a2) return_2AD78: rts ; =========================================================================== loc_2AD7A: if gameRevision>0 cmpi.b #4,routine(a1) bhs.s return_2AD78 endif subq.b #1,d0 bne.w loc_2AE0C tst.b render_flags(a1) bmi.s loc_2ADB0 bclr d6,status(a0) bset #1,status(a1) bclr #3,status(a1) move.b #2,routine(a1) move.b #0,obj_control(a1) move.b #0,(a2) rts ; =========================================================================== loc_2ADB0: andi.w #(button_B_mask|button_C_mask|button_A_mask)<<8,d5 beq.s loc_2ADFE tst.b objoff_3A(a0) bne.s loc_2ADFE move.b #1,objoff_3A(a0) subq.b #1,objoff_32(a0) bpl.s loc_2ADDA move.b #3,objoff_32(a0) cmpi.w #$20,objoff_38(a0) beq.s loc_2ADDA addq.w #1,objoff_38(a0) loc_2ADDA: subq.b #1,objoff_33(a0) bpl.s loc_2ADF8 move.w objoff_38(a0),d0 subi.w #$20,d0 neg.w d0 lsr.w #1,d0 move.b d0,objoff_33(a0) bchg #2,mainspr_mapframe(a0) bra.s loc_2ADFE ; =========================================================================== loc_2ADF8: move.b #1,mainspr_mapframe(a0) loc_2ADFE: move.w y_pos(a0),d0 subi.w #$2E,d0 move.w d0,y_pos(a1) rts ; =========================================================================== loc_2AE0C: move.b #0,(a2) bclr d6,status(a0) beq.w loc_2AD2A move.w objoff_38(a0),d0 addi.w #$10,d0 lsl.w #7,d0 neg.w d0 move.w d0,y_vel(a1) move.w #0,x_vel(a1) move.w #$800,inertia(a1) bset #1,status(a1) bclr #3,status(a1) move.b #2,routine(a1) move.b #0,obj_control(a1) move.w #SndID_CNZLaunch,d0 jmp (PlaySound).l ; =========================================================================== ; loc_2AE56: Obj85_Diagonal: move.b #0,objoff_3A(a0) move.w objoff_38(a0),d1 lsr.w #1,d1 move.w objoff_2E(a0),d0 sub.w d1,d0 move.w d0,x_pos(a0) move.w objoff_34(a0),d0 add.w d1,d0 move.w d0,y_pos(a0) move.b #2,sub2_mapframe(a0) cmpi.w #$10,objoff_38(a0) blo.s + move.b #3,sub2_mapframe(a0) + move.w #$23,d1 move.w #8,d2 move.w #5,d3 move.w x_pos(a0),d4 lea objoff_36(a0),a2 lea (MainCharacter).w,a1 ; a1=character move.w (Ctrl_1_Logical).w,d5 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s loc_2AF06 movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character addq.w #1,a2 move.w (Ctrl_2).w,d5 moveq #p2_standing_bit,d6 bsr.s loc_2AF06 tst.w objoff_36(a0) beq.s loc_2AEF4 tst.w objoff_38(a0) beq.s return_2AF04 moveq #0,d0 cmpi.b #1,objoff_36(a0) bne.s + or.w (Ctrl_1_Logical).w,d0 + cmpi.b #1,objoff_37(a0) bne.s + or.w (Ctrl_2).w,d0 + andi.w #(button_B_mask|button_C_mask|button_A_mask)<<8,d0 bne.s return_2AF04 move.w #$202,objoff_36(a0) rts ; =========================================================================== loc_2AEF4: move.b #1,mainspr_mapframe(a0) subq.w #4,objoff_38(a0) bcc.s return_2AF04 clr.w objoff_38(a0) return_2AF04: rts ; =========================================================================== loc_2AF06: move.b (a2),d0 bne.s loc_2AF7A tst.w (Debug_placement_mode).w bne.s return_2AF78 tst.w y_vel(a1) bmi.s return_2AF78 jsrto (SolidObject_Always_SingleCharacter).l, JmpTo5_SolidObject_Always_SingleCharacter btst d6,status(a0) bne.s loc_2AF2E move.b d6,d0 addq.b #pushing_bit_delta,d0 btst d0,status(a0) beq.s return_2AF78 bset d6,status(a0) loc_2AF2E: move.b #$81,obj_control(a1) move.w x_pos(a0),x_pos(a1) addi.w #$13,x_pos(a1) move.w y_pos(a0),y_pos(a1) subi.w #$13,y_pos(a1) move.w #0,x_vel(a1) move.w #0,y_vel(a1) move.w #0,inertia(a1) bset #2,status(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #AniIDSonAni_Roll,anim(a1) addq.b #1,(a2) return_2AF78: rts ; =========================================================================== loc_2AF7A: if gameRevision>0 cmpi.b #4,routine(a1) bhs.s return_2AF78 endif subq.b #1,d0 bne.w loc_2B018 tst.b render_flags(a1) bmi.s loc_2AFB0 bclr d6,status(a0) bset #1,status(a1) bclr #3,status(a1) move.b #2,routine(a1) move.b #0,obj_control(a1) move.b #0,(a2) rts ; =========================================================================== loc_2AFB0: andi.w #(button_B_mask|button_C_mask|button_A_mask)<<8,d5 beq.s loc_2AFFE tst.b objoff_3A(a0) bne.s loc_2AFFE move.b #1,objoff_3A(a0) subq.b #1,objoff_32(a0) bpl.s loc_2AFDA move.b #3,objoff_32(a0) cmpi.w #$1C,objoff_38(a0) beq.s loc_2AFDA addq.w #1,objoff_38(a0) loc_2AFDA: subq.b #1,objoff_33(a0) bpl.s loc_2AFF8 move.w objoff_38(a0),d0 subi.w #$1C,d0 neg.w d0 lsr.w #1,d0 move.b d0,objoff_33(a0) bchg #2,mainspr_mapframe(a0) bra.s loc_2AFFE ; =========================================================================== loc_2AFF8: move.b #1,mainspr_mapframe(a0) loc_2AFFE: move.w x_pos(a0),d0 addi.w #$13,d0 move.w d0,x_pos(a1) move.w y_pos(a0),d0 subi.w #$13,d0 move.w d0,y_pos(a1) rts ; =========================================================================== loc_2B018: move.b #0,(a2) bclr d6,status(a0) beq.w return_2AF78 move.w objoff_38(a0),d0 addi_.w #4,d0 lsl.w #7,d0 move.w d0,x_vel(a1) neg.w d0 move.w d0,y_vel(a1) move.w #$800,inertia(a1) bset #1,status(a1) bclr #3,status(a1) tst.b subtype(a0) bpl.s loc_2B068 neg.w d0 move.w d0,inertia(a1) bclr #0,status(a1) bclr #1,status(a1) move.b #-$20,angle(a1) loc_2B068: move.b #2,routine(a1) move.b #0,obj_control(a1) move.w #SndID_CNZLaunch,d0 jmp (PlaySound).l ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj85_MapUnc_2B07E: BINCLUDE "mappings/sprite/obj85_a.bin" Obj85_MapUnc_2B0EC: BINCLUDE "mappings/sprite/obj85_b.bin" ; =========================================================================== if ~~removeJmpTos JmpTo4_DisplaySprite3 jmp (DisplaySprite3).l JmpTo43_DeleteObject jmp (DeleteObject).l JmpTo49_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo5_SolidObject_Always_SingleCharacter jmp (SolidObject_Always_SingleCharacter).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 86 - Flipper from CNZ ; ---------------------------------------------------------------------------- ; Sprite_2B140: Obj86: moveq #0,d0 move.b routine(a0),d0 move.w Obj86_Index(pc,d0.w),d1 jsr Obj86_Index(pc,d1.w) jmpto (MarkObjGone).l, JmpTo27_MarkObjGone ; =========================================================================== ; off_2B152: Obj86_Index: offsetTable offsetTableEntry.w Obj86_Init ; 0 offsetTableEntry.w Obj86_UpwardsType ; 2 - sends you upwards offsetTableEntry.w Obj86_HorizontalType ; 4 - sends you leftward/rightward ; =========================================================================== ; loc_2B158: Obj86_Init: addq.b #2,routine(a0) move.l #Obj86_MapUnc_2B45A,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CNZFlipper,2,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo50_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$18,width_pixels(a0) move.b #4,priority(a0) tst.b subtype(a0) beq.s Obj86_UpwardsType addq.b #2,routine(a0) move.b #2,anim(a0) bra.w Obj86_HorizontalType ; =========================================================================== ; loc_2B194: Obj86_UpwardsType: tst.w (Debug_placement_mode).w bne.s return_2B208 lea (byte_2B3C6).l,a2 move.b mapping_frame(a0),d0 beq.s loc_2B1B6 lea (byte_2B3EA).l,a2 subq.b #1,d0 beq.s loc_2B1B6 lea (byte_2B40E).l,a2 loc_2B1B6: move.w #$23,d1 move.w #6,d2 move.w x_pos(a0),d4 jsrto (SlopedSolid).l, JmpTo2_SlopedSolid lea objoff_36(a0),a3 lea (MainCharacter).w,a1 ; a1=character move.w (Ctrl_1_Logical).w,d5 moveq #p1_standing_bit,d6 bsr.s loc_2B20A addq.w #1,a3 lea (Sidekick).w,a1 ; a1=character move.w (Ctrl_2).w,d5 moveq #p2_standing_bit,d6 bsr.s loc_2B20A tst.b objoff_38(a0) beq.s loc_2B1FE clr.b objoff_38(a0) bsr.w loc_2B290 subq.w #1,a3 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 bsr.w loc_2B290 loc_2B1FE: lea (Ani_obj86).l,a1 jmpto (AnimateSprite).l, JmpTo9_AnimateSprite ; =========================================================================== return_2B208: rts ; =========================================================================== loc_2B20A: move.b (a3),d0 bne.s loc_2B23C btst d6,status(a0) beq.s return_2B208 move.b #1,obj_control(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #AniIDSonAni_Roll,anim(a1) bset #2,status(a1) bne.s loc_2B238 addq.w #5,y_pos(a1) loc_2B238: addq.b #1,(a3) rts ; =========================================================================== loc_2B23C: andi.w #button_B_mask|button_C_mask|button_A_mask,d5 bne.s loc_2B288 btst d6,status(a0) bne.s loc_2B254 move.b #0,obj_control(a1) move.b #0,(a3) rts ; =========================================================================== loc_2B254: moveq #0,d1 move.b mapping_frame(a0),d1 subq.w #1,d1 bset #0,status(a1) btst #0,status(a0) bne.s loc_2B272 neg.w d1 bclr #0,status(a1) loc_2B272: add.w d1,x_pos(a1) lsl.w #8,d1 move.w d1,x_vel(a1) move.w d1,inertia(a1) move.w #0,y_vel(a1) rts ; =========================================================================== loc_2B288: move.b #1,objoff_38(a0) rts ; =========================================================================== loc_2B290: bclr d6,status(a0) beq.w return_2B208 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 btst #0,status(a0) beq.s loc_2B2AA neg.w d0 loc_2B2AA: addi.w #$23,d0 move.w d0,d2 cmpi.w #$40,d2 blo.s loc_2B2BA move.w #$40,d2 loc_2B2BA: lsl.w #5,d2 addi.w #$800,d2 neg.w d2 asr.w #2,d0 addi.w #$40,d0 jsrto (CalcSine).l, JmpTo11_CalcSine muls.w d2,d0 muls.w d2,d1 asr.l #8,d0 asr.l #8,d1 move.w d0,y_vel(a1) btst #0,status(a0) beq.s loc_2B2E2 neg.w d1 loc_2B2E2: move.w d1,x_vel(a1) bset #1,status(a1) bclr #3,status(a1) move.b #2,routine(a1) move.b #0,obj_control(a1) move.b #1,anim(a0) move.b #0,(a3) move.w #SndID_Flipper,d0 jmp (PlaySound).l ; =========================================================================== ; loc_2B312: Obj86_HorizontalType: move.w #$13,d1 move.w #$18,d2 move.w #$19,d3 move.w x_pos(a0),d4 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) jsrto (SolidObject_Always_SingleCharacter).l, JmpTo6_SolidObject_Always_SingleCharacter btst #p1_pushing_bit,status(a0) beq.s loc_2B33A bsr.s loc_2B35C loc_2B33A: movem.l (sp)+,d1-d4 lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 jsrto (SolidObject_Always_SingleCharacter).l, JmpTo6_SolidObject_Always_SingleCharacter btst #p2_pushing_bit,status(a0) beq.s loc_2B352 bsr.s loc_2B35C loc_2B352: lea (Ani_obj86).l,a1 jmpto (AnimateSprite).l, JmpTo9_AnimateSprite ; =========================================================================== loc_2B35C: move.w #$300,anim(a0) move.w #-$1000,x_vel(a1) addq.w #8,x_pos(a1) bset #0,status(a1) move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcc.s loc_2B392 bclr #0,status(a1) subi.w #$10,x_pos(a1) neg.w x_vel(a1) move.w #$400,anim(a0) loc_2B392: move.w #$F,move_lock(a1) move.w x_vel(a1),inertia(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #AniIDSonAni_Roll,anim(a1) bset #2,status(a1) bne.s loc_2B3BC addq.w #5,y_pos(a1) loc_2B3BC: move.w #SndID_Flipper,d0 jmp (PlaySound).l ; =========================================================================== byte_2B3C6: dc.b 7, 7, 7, 7, 7, 7, 7, 8, 9, $A, $B, $A, 9, 8, 7, 6 dc.b 5, 4, 3, 2, 1, 0,$FF,$FE,$FD,$FC,$FB,$FA,$F9,$F8,$F7,$F6; 16 dc.b $F5,$F4,$F3,$F2 ; 32 byte_2B3EA: dc.b 6, 6, 6, 6, 6, 6, 7, 8, 9, 9, 9, 9, 9, 9, 8, 8 dc.b 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 4, 4; 16 dc.b 4, 4, 4, 4 ; 32 byte_2B40E: dc.b 5, 5, 5, 5, 5, 6, 7, 8, 9, $A, $B, $B, $C, $C, $D, $D dc.b $E, $E, $F, $F,$10,$10,$11,$11,$12,$12,$11,$11,$10,$10,$10,$10; 16 dc.b $10,$10,$10,$10 ; 32 ; animation script ; off_2B432: Ani_obj86: offsetTable offsetTableEntry.w byte_2B43C ; 0 offsetTableEntry.w byte_2B43F ; 1 offsetTableEntry.w byte_2B445 ; 2 offsetTableEntry.w byte_2B448 ; 3 offsetTableEntry.w byte_2B451 ; 4 byte_2B43C: dc.b $F, 0,$FF rev02even byte_2B43F: dc.b 3, 1, 2, 1,$FD, 0 rev02even byte_2B445: dc.b $F, 4,$FF rev02even byte_2B448: dc.b 0, 5, 4, 3, 3, 3, 3,$FD, 2 rev02even byte_2B451: dc.b 0, 3, 4, 5, 5, 5, 5,$FD, 2 even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj86_MapUnc_2B45A: BINCLUDE "mappings/sprite/obj86.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo27_MarkObjGone jmp (MarkObjGone).l JmpTo9_AnimateSprite jmp (AnimateSprite).l JmpTo50_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo11_CalcSine jmp (CalcSine).l JmpTo6_SolidObject_Always_SingleCharacter jmp (SolidObject_Always_SingleCharacter).l JmpTo2_SlopedSolid jmp (SlopedSolid).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object D2 - Flashing blocks that appear and disappear in a rectangular shape that you can walk across, from CNZ ; ---------------------------------------------------------------------------- ; Sprite_2B528: ObjD2: moveq #0,d0 move.b routine(a0),d0 move.w ObjD2_Index(pc,d0.w),d1 jmp ObjD2_Index(pc,d1.w) ; =========================================================================== ; off_2B536: ObjD2_Index: offsetTable offsetTableEntry.w ObjD2_Init ; 0 offsetTableEntry.w ObjD2_Main ; 2 ; =========================================================================== ; loc_2B53A: ObjD2_Init: addq.b #2,routine(a0) move.l #ObjD2_MapUnc_2B694,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CNZSnake,2,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo51_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #8,width_pixels(a0) move.b #4,priority(a0) move.w x_pos(a0),objoff_30(a0) move.w y_pos(a0),objoff_32(a0) moveq #0,d0 move.b subtype(a0),d0 lsl.w #4,d0 move.w d0,objoff_38(a0) bsr.w loc_2B60C ; loc_2B57E: ObjD2_Main: tst.w objoff_38(a0) beq.s + subq.w #1,objoff_38(a0) jmpto (MarkObjGone3).l, JmpTo6_MarkObjGone3 ; =========================================================================== + subq.w #1,objoff_3A(a0) bpl.s loc_2B5EC move.w #$F,objoff_3A(a0) addq.b #1,mapping_frame(a0) andi.b #$F,mapping_frame(a0) bne.s loc_2B5EA moveq #0,d0 move.b subtype(a0),d0 lsl.w #4,d0 move.w d0,objoff_38(a0) move.b status(a0),d0 andi.b #standing_mask,d0 beq.s loc_2B5E2 bclr #p1_standing_bit,status(a0) beq.s + bclr #3,(MainCharacter+status).w bset #1,(MainCharacter+status).w + bclr #p2_standing_bit,status(a0) beq.s loc_2B5E2 bclr #3,(Sidekick+status).w bset #1,(Sidekick+status).w loc_2B5E2: move.w objoff_30(a0),x_pos(a0) bra.s loc_2B60C ; =========================================================================== loc_2B5EA: bsr.s loc_2B60C loc_2B5EC: move.w objoff_34(a0),d1 addi.w #$B,d1 move.w objoff_36(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsrto (SolidObject).l, JmpTo24_SolidObject move.w objoff_30(a0),d0 jmpto (MarkObjGone2).l, JmpTo9_MarkObjGone2 ; =========================================================================== loc_2B60C: moveq #0,d0 move.b mapping_frame(a0),d0 add.w d0,d0 add.w d0,d0 lea byte_2B654(pc,d0.w),a1 move.b (a1)+,d0 ext.w d0 btst #0,status(a0) beq.s + neg.w d0 + add.w objoff_30(a0),d0 move.w d0,x_pos(a0) move.b (a1)+,d0 ext.w d0 add.w objoff_32(a0),d0 move.w d0,y_pos(a0) moveq #0,d1 moveq #0,d2 moveq #0,d3 move.b (a1)+,d1 move.b (a1)+,d2 move.w d1,objoff_34(a0) move.b d1,width_pixels(a0) move.w d2,objoff_36(a0) rts ; =========================================================================== byte_2B654: dc.b $D8,$18, 8, 8,$D8,$10, 8,$10,$D8, 8, 8,$18,$D8, 0, 8,$20 dc.b $E0, 0,$10,$20,$E8,$F8,$18,$18,$F0,$F0,$20,$10,$F8,$E8,$28, 8; 16 dc.b 8,$E8,$28, 8,$10,$F0,$20,$10,$18,$F8,$18,$18,$20, 0,$10,$20; 32 dc.b $28, 0, 8,$20,$28, 8, 8,$18,$28,$10, 8,$10,$28,$18, 8, 8; 48 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjD2_MapUnc_2B694: BINCLUDE "mappings/sprite/objD2.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo6_MarkObjGone3 jmp (MarkObjGone3).l JmpTo51_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo24_SolidObject jmp (SolidObject).l JmpTo9_MarkObjGone2 jmp (MarkObjGone2).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object D3 - Bomb prize from CNZ ; ---------------------------------------------------------------------------- ; Note: see object DC (ring prize) for SST entries (casino_prize_*) ; Sprite_2B84C: ObjD3: moveq #0,d1 move.w casino_prize_machine_x_pos(a0),d1 swap d1 move.l casino_prize_x_pos(a0),d0 sub.l d1,d0 asr.l #4,d0 sub.l d0,casino_prize_x_pos(a0) move.w casino_prize_x_pos(a0),x_pos(a0) moveq #0,d1 move.w casino_prize_machine_y_pos(a0),d1 swap d1 move.l casino_prize_y_pos(a0),d0 sub.l d1,d0 asr.l #4,d0 sub.l d0,casino_prize_y_pos(a0) move.w casino_prize_y_pos(a0),y_pos(a0) subq.w #1,casino_prize_display_delay(a0) bne.w JmpTo28_DisplaySprite movea.l objoff_2A(a0),a1 subq.w #1,(a1) cmpi.w #5,(Bonus_Countdown_3).w blo.s + clr.w (Bonus_Countdown_3).w move.w #SndID_HurtBySpikes,d0 jsr (PlaySoundStereo).l + tst.b parent+1(a0) beq.s ++ tst.w (Ring_count_2P).w beq.s + subq.w #1,(Ring_count_2P).w ori.b #$81,(Update_HUD_rings_2P).w + tst.w (Two_player_mode).w bne.s BranchTo_JmpTo44_DeleteObject + tst.w (Ring_count).w beq.s BranchTo_JmpTo44_DeleteObject subq.w #1,(Ring_count).w ori.b #$81,(Update_HUD_rings).w BranchTo_JmpTo44_DeleteObject jmpto (DeleteObject).l, JmpTo44_DeleteObject if removeJmpTos JmpTo28_DisplaySprite jmp (DisplaySprite).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjD3_MapUnc_2B8D4: BINCLUDE "mappings/sprite/objD6_a.bin" ; =========================================================================== if ~~removeJmpTos JmpTo28_DisplaySprite jmp (DisplaySprite).l JmpTo44_DeleteObject jmp (DeleteObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object D4 - Big block from CNZ that moves back and forth ; ---------------------------------------------------------------------------- ; Sprite_2B8EC: ObjD4: moveq #0,d0 move.b routine(a0),d0 move.w ObjD4_Index(pc,d0.w),d1 jmp ObjD4_Index(pc,d1.w) ; =========================================================================== ; off_2B8FA: ObjD4_Index: offsetTable offsetTableEntry.w ObjD4_Init ; 0 offsetTableEntry.w ObjD4_Main ; 2 ; =========================================================================== ; loc_2B8FE: ObjD4_Init: addq.b #2,routine(a0) move.l #ObjD4_MapUnc_2B9CA,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_BigMovingBlock,2,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo52_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$20,width_pixels(a0) move.b #4,priority(a0) move.w x_pos(a0),objoff_30(a0) move.w y_pos(a0),objoff_32(a0) move.w #$8000,x_sub(a0) move.w #$8000,y_sub(a0) tst.b subtype(a0) bne.s loc_2B95A subi.w #$60,x_pos(a0) btst #0,status(a0) beq.s ObjD4_Main addi.w #$C0,x_pos(a0) bra.s ObjD4_Main ; =========================================================================== loc_2B95A: subi.w #$60,y_pos(a0) btst #1,status(a0) beq.s ObjD4_Main addi.w #$C0,y_pos(a0) ; loc_2B96E: ObjD4_Main: move.w x_pos(a0),-(sp) moveq #0,d0 move.b subtype(a0),d0 move.w ObjD4_Types(pc,d0.w),d1 jsr ObjD4_Types(pc,d1.w) jsrto (ObjectMove).l, JmpTo17_ObjectMove move.w #$2B,d1 move.w #$20,d2 move.w #$21,d3 move.w (sp)+,d4 jsrto (SolidObject).l, JmpTo25_SolidObject move.w objoff_30(a0),d0 jmpto (MarkObjGone2).l, JmpTo10_MarkObjGone2 ; =========================================================================== ; off_2B99E: ObjD4_Types: offsetTable offsetTableEntry.w ObjD4_Horizontal ; 0 offsetTableEntry.w ObjD4_Vertical ; 2 ; =========================================================================== ; loc_2B9A2: ObjD4_Horizontal: moveq #4,d1 move.w objoff_30(a0),d0 cmp.w x_pos(a0),d0 bhi.s + neg.w d1 + add.w d1,x_vel(a0) rts ; =========================================================================== ; loc_2B9B6: ObjD4_Vertical: moveq #4,d1 move.w objoff_32(a0),d0 cmp.w y_pos(a0),d0 bhi.s + neg.w d1 + add.w d1,y_vel(a0) rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjD4_MapUnc_2B9CA: BINCLUDE "mappings/sprite/objD4.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo52_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo25_SolidObject jmp (SolidObject).l JmpTo10_MarkObjGone2 jmp (MarkObjGone2).l ; loc_2BA02: JmpTo17_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object D5 - Elevator from CNZ ; ---------------------------------------------------------------------------- ; Sprite_2BA08: ObjD5: moveq #0,d0 move.b routine(a0),d0 move.w ObjD5_Index(pc,d0.w),d1 jmp ObjD5_Index(pc,d1.w) ; =========================================================================== ; off_2BA16: ObjD5_Index: offsetTable offsetTableEntry.w ObjD5_Init ; 0 offsetTableEntry.w ObjD5_Main ; 2 ; =========================================================================== ; loc_2BA1A: ObjD5_Init: addq.b #2,routine(a0) move.l #ObjD5_MapUnc_2BB40,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CNZElevator,2,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo53_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #4,priority(a0) move.w y_pos(a0),objoff_32(a0) move.w #$8000,y_sub(a0) moveq #0,d0 move.b subtype(a0),d0 lsl.w #2,d0 sub.w d0,y_pos(a0) btst #0,status(a0) beq.s ObjD5_Main add.w d0,d0 add.w d0,y_pos(a0) ; loc_2BA68: ObjD5_Main: jsrto (ObjectMove).l, JmpTo18_ObjectMove move.w objoff_34(a0),d0 move.w off_2BA94(pc,d0.w),d1 jsr off_2BA94(pc,d1.w) cmpi.w #6,objoff_34(a0) bhs.s + move.w #$10,d1 move.w #9,d3 move.w x_pos(a0),d4 jsrto (PlatformObjectD5).l, JmpTo_PlatformObjectD5 + jmpto (MarkObjGone).l, JmpTo28_MarkObjGone ; =========================================================================== off_2BA94: offsetTable offsetTableEntry.w loc_2BA9C ; 0 offsetTableEntry.w loc_2BAB6 ; 2 offsetTableEntry.w loc_2BAEE ; 4 offsetTableEntry.w loc_2BB08 ; 6 ; =========================================================================== loc_2BA9C: move.b status(a0),d0 andi.w #standing_mask,d0 beq.s + ; rts move.w #SndID_CNZElevator,d0 jsr (PlaySound).l addq.w #2,objoff_34(a0) + rts ; =========================================================================== loc_2BAB6: moveq #8,d1 move.w objoff_32(a0),d0 cmp.w y_pos(a0),d0 bhs.s + neg.w d1 + add.w d1,y_vel(a0) bne.s + ; rts addq.w #2,objoff_34(a0) move.w d0,y_pos(a0) moveq #0,d0 move.b subtype(a0),d0 lsl.w #2,d0 sub.w d0,y_pos(a0) btst #0,status(a0) bne.s + ; rts add.w d0,d0 add.w d0,y_pos(a0) + rts ; =========================================================================== loc_2BAEE: move.b status(a0),d0 andi.w #standing_mask,d0 bne.s + ; rts move.w #SndID_CNZElevator,d0 jsr (PlaySound).l addq.w #2,objoff_34(a0) + rts ; =========================================================================== loc_2BB08: moveq #8,d1 move.w objoff_32(a0),d0 cmp.w y_pos(a0),d0 bhs.s + neg.w d1 + add.w d1,y_vel(a0) bne.s + ; rts clr.w objoff_34(a0) move.w d0,y_pos(a0) moveq #0,d0 move.b subtype(a0),d0 lsl.w #2,d0 sub.w d0,y_pos(a0) btst #0,status(a0) beq.s + ; rts add.w d0,d0 add.w d0,y_pos(a0) + rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjD5_MapUnc_2BB40: BINCLUDE "mappings/sprite/objD5.bin" ; =========================================================================== if ~~removeJmpTos JmpTo28_MarkObjGone jmp (MarkObjGone).l JmpTo53_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo_PlatformObjectD5 jmp (PlatformObjectD5).l ; loc_2BB66: JmpTo18_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object D6 - Pokey that gives out points from CNZ ; ---------------------------------------------------------------------------- ; Sprite_2BB6C: ObjD6: moveq #0,d0 move.b routine(a0),d0 move.w ObjD6_Index(pc,d0.w),d1 jmp ObjD6_Index(pc,d1.w) ; =========================================================================== ; off_2BB7A: ObjD6_Index: offsetTable offsetTableEntry.w ObjD6_Init ; 0 offsetTableEntry.w ObjD6_Main ; 2 ; =========================================================================== ; loc_2BB7E: ObjD6_Init: addq.b #2,routine(a0) move.l #ObjD6_MapUnc_2BEBC,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CNZCage,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo54_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$18,width_pixels(a0) move.b #1,priority(a0) ; loc_2BBA6: ObjD6_Main: move.w #$23,d1 move.w #$10,d2 move.w #$11,d3 move.w x_pos(a0),d4 lea objoff_30(a0),a2 lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w loc_2BBE8 movem.l (sp)+,d1-d4 lea objoff_34(a0),a2 ; a2=object lea (Sidekick).w,a1 ; a1=character moveq #p2_standing_bit,d6 bsr.w loc_2BBE8 lea (Ani_objD6).l,a1 jsrto (AnimateSprite).l, JmpTo10_AnimateSprite jmpto (MarkObjGone).l, JmpTo29_MarkObjGone ; =========================================================================== loc_2BBE8: move.w (a2),d0 move.w off_2BBF2(pc,d0.w),d0 jmp off_2BBF2(pc,d0.w) ; =========================================================================== off_2BBF2: offsetTable offsetTableEntry.w loc_2BBF8 ; 0 offsetTableEntry.w loc_2BDF8 ; 2 offsetTableEntry.w loc_2BE9C ; 4 ; =========================================================================== loc_2BBF8: tst.b obj_control(a1) bne.w return_2BC84 tst.b subtype(a0) beq.s loc_2BC0C tst.w (SlotMachineInUse).w bne.s return_2BC84 loc_2BC0C: jsrto (SolidObject_Always_SingleCharacter).l, JmpTo7_SolidObject_Always_SingleCharacter tst.w d4 bpl.s return_2BC84 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w #0,x_vel(a1) move.w #0,y_vel(a1) move.w #0,inertia(a1) move.b #$81,obj_control(a1) bset #2,status(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #AniIDSonAni_Roll,anim(a1) move.b #1,anim(a0) addq.w #2,(a2)+ move.w #$78,(a2) move.w a1,parent(a0) tst.b subtype(a0) beq.s return_2BC84 cmpi.b #$18,(SlotMachine_Routine).w ; Is it the null routine? bne.s return_2BC84 ; Branch if not move.b #8,(SlotMachine_Routine).w ; => SlotMachine_Routine3 clr.w objoff_2E(a0) move.w #-1,(SlotMachineInUse).w move.w #-1,objoff_2A(a0) return_2BC84: rts ; =========================================================================== loc_2BC86: move.w (SlotMachine_Reward).w,d0 bpl.w loc_2BD4E tst.w objoff_2A(a0) bpl.s + move.w #$64,objoff_2A(a0) + tst.w objoff_2A(a0) beq.w + btst #0,(Timer_frames+1).w beq.w loc_2BD48 cmpi.w #$10,objoff_2C(a0) bhs.w loc_2BD48 jsrto (SingleObjLoad).l, JmpTo10_SingleObjLoad bne.w loc_2BD48 _move.b #ObjID_BombPrize,id(a1) ; load objD3 move.l #ObjD3_MapUnc_2B8D4,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_CNZBonusSpike,0,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo6_Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #$10,width_pixels(a1) move.b #4,priority(a1) move.w #$1E,casino_prize_display_delay(a1) move.w objoff_2E(a0),objoff_2E(a1) addi.w #$90,objoff_2E(a0) move.w x_pos(a0),casino_prize_machine_x_pos(a1) move.w y_pos(a0),casino_prize_machine_y_pos(a1) move.w objoff_2E(a1),d0 jsrto (CalcSine).l, JmpTo12_CalcSine asr.w #1,d1 add.w casino_prize_machine_x_pos(a1),d1 move.w d1,casino_prize_x_pos(a1) move.w d1,x_pos(a1) asr.w #1,d0 add.w casino_prize_machine_y_pos(a1),d0 move.w d0,casino_prize_y_pos(a1) move.w d0,y_pos(a1) lea objoff_2C(a0),a2 move.l a2,objoff_2A(a1) move.w parent(a0),parent(a1) addq.w #1,objoff_2C(a0) subq.w #1,objoff_2A(a0) + tst.w objoff_2C(a0) beq.w loc_2BE2E loc_2BD48: addq.w #1,(Bonus_Countdown_3).w rts ; =========================================================================== loc_2BD4E: beq.w + btst #0,(Timer_frames+1).w beq.w return_2BDF6 cmpi.w #$10,objoff_2C(a0) bhs.w return_2BDF6 jsrto (SingleObjLoad).l, JmpTo10_SingleObjLoad bne.w return_2BDF6 _move.b #ObjID_RingPrize,id(a1) ; load objDC move.l #Obj25_MapUnc_12382,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_Ring,1,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo6_Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #3,priority(a1) move.b #8,width_pixels(a1) move.w #$1A,casino_prize_display_delay(a1) move.w objoff_2E(a0),objoff_2E(a1) addi.w #$89,objoff_2E(a0) move.w x_pos(a0),casino_prize_machine_x_pos(a1) move.w y_pos(a0),casino_prize_machine_y_pos(a1) move.w objoff_2E(a1),d0 jsrto (CalcSine).l, JmpTo12_CalcSine asr.w #1,d1 add.w casino_prize_machine_x_pos(a1),d1 move.w d1,casino_prize_x_pos(a1) move.w d1,x_pos(a1) asr.w #1,d0 add.w casino_prize_machine_y_pos(a1),d0 move.w d0,casino_prize_y_pos(a1) move.w d0,y_pos(a1) lea objoff_2C(a0),a2 move.l a2,objoff_2A(a1) move.w parent(a0),parent(a1) addq.w #1,objoff_2C(a0) subq.w #1,(SlotMachine_Reward).w + tst.w objoff_2C(a0) beq.s loc_2BE2E return_2BDF6: rts ; =========================================================================== loc_2BDF8: tst.b render_flags(a0) bpl.s loc_2BE2E tst.b subtype(a0) beq.s loc_2BE28 move.w a1,objoff_3E(a0) cmpi.b #$18,(SlotMachine_Routine).w ; Is it the null routine? beq.w loc_2BC86 ; Branch if yes move.b (Vint_runcount+3).w,d0 andi.w #$F,d0 bne.s + ; rts move.w #SndID_CasinoBonus,d0 jsr (PlaySound).l + rts ; =========================================================================== loc_2BE28: subq.w #1,2(a2) bpl.s loc_2BE5E loc_2BE2E: move.w #0,objoff_2C(a0) move.b #0,anim(a0) move.b #0,objoff_2A(a1) bclr d6,status(a0) bclr #3,status(a1) bset #1,status(a1) move.w #$400,y_vel(a1) addq.w #2,(a2)+ move.w #$1E,(a2) rts ; =========================================================================== loc_2BE5E: move.w 2(a2),d0 andi.w #$F,d0 bne.s + ; rts move.w #SndID_CasinoBonus,d0 jsr (PlaySound).l moveq #10,d0 movea.w a1,a3 jsr (AddPoints2).l jsrto (SingleObjLoad).l, JmpTo10_SingleObjLoad bne.s + ; rts _move.b #ObjID_Points,id(a1) ; load obj29 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b #0,mapping_frame(a1) + rts ; =========================================================================== loc_2BE9C: subq.w #1,2(a2) bpl.s + ; rts clr.w (a2) tst.b subtype(a0) beq.s + ; rts clr.w (SlotMachineInUse).w + rts ; =========================================================================== ; animation script ; off_2BEB0: Ani_objD6: offsetTable offsetTableEntry.w byte_2BEB4 ; 0 offsetTableEntry.w byte_2BEB7 ; 1 byte_2BEB4: dc.b $F, 0,$FF rev02even byte_2BEB7: dc.b 1, 1, 0,$FF even ; ------------------------------------------------------------------------------ ; sprite mappings ; ------------------------------------------------------------------------------ ObjD6_MapUnc_2BEBC: BINCLUDE "mappings/sprite/objD6_b.bin" ; =========================================================================== ; ------------------------------------------------------------------------------ ; runs the slot machines in CNZ ; ------------------------------------------------------------------------------ slot_rout = 0 slot_timer = 1 slot_index = 3 slots_targ = 4 slot1_targ = 4 slot23_targ = 5 slots_data = 6 slot1_index = slots_data slot1_offset = slots_data+1 slot1_speed = slots_data+2 slot1_rout = slots_data+3 slot2_index = slots_data+4 slot2_offset = slots_data+5 slot2_speed = slots_data+6 slot2_rout = slots_data+7 slot3_index = slots_data+8 slot3_offset = slots_data+9 slot3_speed = slots_data+10 slot3_rout = slots_data+11 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_2BF24: SlotMachine: lea (SlotMachineVariables).w,a4 moveq #0,d0 _move.b slot_rout(a4),d0 jmp SlotMachine_JmpTable(pc,d0.w) ; =========================================================================== ; loc_2BF32: SlotMachine_JmpTable: ;; bra.w SlotMachine_Routine1 ; $00 bra.w SlotMachine_Routine2 ; $04 bra.w SlotMachine_Routine3 ; $08 bra.w SlotMachine_Routine4 ; $0C bra.w SlotMachine_Routine5 ; $10 bra.w SlotMachine_Routine6 ; $14 rts ; $18 ; =========================================================================== ; loc_2BF4C: SlotMachine_Routine1: movea.l a4,a1 ; Copy destination moveq #8,d0 ; 18 bytes, in words - clr.w (a1)+ dbf d0,- move.b (Vint_runcount+3).w,d0 ; 'Random' seed move.b d0,slot1_index(a4) ; Only last 3 bits matter ror.b #3,d0 ; Remove last 3 bits move.b d0,slot2_index(a4) ; Again, only last 3 bits matter ror.b #3,d0 ; Remove 3 more bits (only have 2 bits now!) move.b d0,slot3_index(a4) ; Only 3 bits matter, but we only have 2 anyway move.b #8,slot1_offset(a4) ; This will set a draw from start of tile move.b #8,slot2_offset(a4) ; This will set a draw from start of tile move.b #8,slot3_offset(a4) ; This will set a draw from start of tile move.b #8,slot1_speed(a4) ; Initial rolling speed move.b #8,slot2_speed(a4) ; Initial rolling speed move.b #8,slot3_speed(a4) ; Initial rolling speed move.b #1,slot_timer(a4) ; Roll each slot once _addq.b #4,slot_rout(a4) ; => SlotMachine_Routine2 rts ; =========================================================================== ; loc_2BF9A: SlotMachine_Routine2: bsr.w SlotMachine_DrawSlot ; Draw the slots tst.b slot_timer(a4) ; Are we still rolling? beq.s + ; Branch if not rts ; =========================================================================== + _move.b #$18,slot_rout(a4) ; => null routine (rts) clr.w slot1_speed(a4) ; Stop slot 1 clr.w slot2_speed(a4) ; Stop slot 2 clr.w slot3_speed(a4) ; Stop slot 3 rts ; =========================================================================== ; loc_2BFBA: SlotMachine_Routine3: move.b (Vint_runcount+3).w,d0 ; 'Random' seed andi.b #7,d0 ; Only want last 3 bits subq.b #4,d0 ; Subtract 4... addi.b #$30,d0 ; ... then add $30 (why not just add $2C?) move.b d0,slot1_speed(a4) ; This is our starting speed for slot 1 move.b (Vint_runcount+3).w,d0 ; 'Random' seed rol.b #4,d0 ; Get top nibble... andi.b #7,d0 ; ... but discard what was the sign bit subq.b #4,d0 ; Subtract 4... addi.b #$30,d0 ; ... then add $30 (why not just add $2C?) move.b d0,slot2_speed(a4) ; This is our starting speed for slot 2 move.b (Vint_runcount+2).w,d0 ; 'Random' seed andi.b #7,d0 ; Only want last 3 bits subq.b #4,d0 ; Subtract 4... addi.b #$30,d0 ; ... then add $30 (why not just add $2C?) move.b d0,slot3_speed(a4) ; This is our starting speed for slot 3 move.b #2,slot_timer(a4) ; Roll each slot twice under these conditions clr.b slot_index(a4) ; => SlotMachine_Subroutine1 clr.b slot1_rout(a4) ; => SlotMachine_Routine5_1 clr.b slot2_rout(a4) ; => SlotMachine_Routine5_1 clr.b slot3_rout(a4) ; => SlotMachine_Routine5_1 _addq.b #4,slot_rout(a4) ; => SlotMachine_Routine4 move.b (Vint_runcount+3).w,d0 ; 'Random' seed ror.b #3,d0 ; Mess it around lea (SlotTargetValues).l,a2 - sub.b (a2),d0 ; Subtract from random seed bcs.s + ; Branch if result is less than zero addq.w #3,a2 ; Advance 3 bytes bra.s - ; Keep looping ; =========================================================================== + cmpi.b #-1,(a2) ; Is the previous value -1? beq.s + ; Branch if yes (end of array) move.b 1(a2),slot1_targ(a4) ; Target value for slot 1 move.b 2(a2),slot23_targ(a4) ; Target values for slots 2 and 3 rts ; =========================================================================== + move.b d0,d1 ; Copy our 'random' value andi.w #7,d1 ; Want only last 3 bits lea (SlotSequence1).l,a1 ; Slot sequence array for slot 1 move.b (a1,d0.w),slot1_targ(a4) ; Uhhh... use d0 as array index? This should have been d1! Anyway, set slot 1 target ror.b #3,d0 ; Rotate it move.b d0,d1 ; Copy it andi.w #7,d1 ; Want only last 3 bits lea (SlotSequence2).l,a1 ; Slot sequence array for slot 2 move.b (a1,d1.w),d2 ; Use as array index lsl.b #4,d2 ; Move to high nibble ror.b #3,d0 ; Rotate it again andi.w #7,d0 ; Want only last 3 bits lea (SlotSequence3).l,a1 ; Slot sequence array for slot 3 or.b (a1,d0.w),d2 ; Combine with earlier value move.b d2,slot23_targ(a4) ; Target values for slots 2 and 3 rts ; =========================================================================== ; loc_2C070: SlotMachine_Routine4: bsr.w SlotMachine_DrawSlot tst.b slot_timer(a4) ; Are slots still going? beq.s + ; Branch if not rts ; =========================================================================== + addi.b #$30,slot1_speed(a4) ; Increase slot 1 speed addi.b #$30,slot2_speed(a4) ; Increase slot 2 speed addi.b #$30,slot3_speed(a4) ; Increase slot 3 speed move.b (Vint_runcount+3).w,d0 ; 'Random' seed andi.b #$F,d0 ; Want only low nibble addi.b #$C,d0 ; Increase by $C move.b d0,slot_timer(a4) ; New value for slot timer clr.b 2(a4) ; Clear otherwise unused variable _addq.b #4,slot_rout(a4) ; => SlotMachine_Routine5 rts ; =========================================================================== ; loc_2C0A8: SlotMachine_Routine5: bsr.w SlotMachine_DrawSlot cmpi.b #$C,slot1_rout(a4) ; Is slot done? bne.s + ; Branch if not cmpi.b #$C,slot2_rout(a4) ; Is slot done? bne.s + ; Branch if not cmpi.b #$C,slot3_rout(a4) ; Is slot done? beq.w SlotMachine_Routine6 ; Branch if yes + moveq #0,d0 ; Clear d0 move.b slot_index(a4),d0 ; Get current slot index lea slots_data(a4),a1 ; a1 = pointer to slots data adda.w d0,a1 ; a1 = pointer to current slot data lea (SlotSequence1).l,a3 ; Get pointer to slot sequences add.w d0,d0 ; Turn into index adda.w d0,a3 ; Get sequence for this slot moveq #0,d0 ; Clear d0 again move.b slot1_rout-slot1_index(a1),d0 ; Slot routine jmp SlotMachine_Routine5_JmpTable(pc,d0.w) ; =========================================================================== ; loc_2C0E6 SlotMachine_Routine5_JmpTable: ;; bra.w SlotMachine_Routine5_1 ; $00 bra.w SlotMachine_Routine5_2 ; $04 bra.w SlotMachine_Routine5_3 ; $08 bra.w SlotMachine_Routine5_4 ; $0C ; =========================================================================== ;loc_2C0F6 SlotMachine_GetTargetForSlot: move.w slots_targ(a4),d1 ; Get target slot faces move.b slot_index(a4),d0 ; Get current slot index beq.s + ; Branch if zero lsr.w d0,d1 ; Shift slot face into position + andi.w #7,d1 ; Only 8 slot faces cmpi.b #5,d1 ; Is this above bar? bgt.s + ; Branch if yes rts ; =========================================================================== + subq.b #2,d1 ; Wrap back to ring/bar rts ; =========================================================================== ;loc_2C112 SlotMachine_ChangeTarget: move.w #$FFF0,d2 ; Kept faces mask andi.w #$F,d1 ; New slot target move.b slot_index(a4),d0 ; Get current slot beq.s + ; Branch if it is slot 0 lsl.w d0,d1 ; Shift new slot target into position rol.w d0,d2 ; Shift kept faces mask into position + and.w d2,slots_targ(a4) ; Mask off current slot or.w d1,slots_targ(a4) ; Put in new value for it andi.w #$777,slots_targ(a4) ; Slots are only 0-7 rts ; =========================================================================== ; loc_2C134: SlotMachine_Routine5_1: tst.b slot_index(a4) ; Is this slot 1? bne.s + ; Branch if not tst.b slot_timer(a4) ; Is timer positive or zero? bmi.s ++ ; Branch if not rts ; =========================================================================== + cmpi.b #8,slot1_rout-slot2_index(a1) ; Is previous slot in state SlotMachine_Routine5_3 or SlotMachine_Routine5_4? bge.s + ; Branch if yes rts ; =========================================================================== + bsr.s SlotMachine_GetTargetForSlot move.w (a1),d0 ; Get current slot index/offset subi.w #$A0,d0 ; Subtract 20 lines (2.5 tiles) from it lsr.w #8,d0 ; Get effective slot index andi.w #7,d0 ; Only want 3 bits move.b (a3,d0.w),d0 ; Get face from sequence cmp.b d1,d0 ; Are we close to target? beq.s + ; Branch if yes rts ; =========================================================================== + addq.b #4,slot1_rout-slot1_index(a1) ; => SlotMachine_Routine5_2 move.b #$60,slot1_speed-slot1_index(a1) ; Decrease slot speed rts ; =========================================================================== ; loc_2C170: SlotMachine_Routine5_2: bsr.s SlotMachine_GetTargetForSlot move.w (a1),d0 ; Get current slot index/offset addi.w #$F0,d0 ; Add 30 lines (3.75 tiles) to it andi.w #$700,d0 ; Limit to 8 faces lsr.w #8,d0 ; Get effective slot index move.b (a3,d0.w),d0 ; Get face from sequence cmp.b d0,d1 ; Are we this close to target? beq.s loc_2C1AE ; Branch if yes cmpi.b #$20,slot1_speed-slot1_index(a1) ; Is slot speed more than $20? bls.s + ; Branch if not subi.b #$C,slot1_speed-slot1_index(a1) ; Reduce slot speed + cmpi.b #$18,slot1_speed-slot1_index(a1) ; Is slot speed $18 or less? bgt.s + ; Branch if not rts ; =========================================================================== + cmpi.b #$80,slot1_offset-slot1_index(a1) ; Is offset $80 or less? bls.s + ; Branch if yes rts ; =========================================================================== + subq.b #2,slot1_speed-slot1_index(a1) ; Reduce slot speed rts ; =========================================================================== loc_2C1AE: move.w (a1),d0 ; Get current slot index/offset addi.w #$80,d0 ; Subtract 16 lines (2 tiles) to it move.w d0,d1 ; Copy to d1 andi.w #$700,d1 ; Limit to 8 faces subi.w #$10,d1 ; Subtract 2 lines (1/4 tile) from it move.w d1,(a1) ; Store new value for index/offset lsr.w #8,d0 ; Convert to index andi.w #7,d0 ; Limit to 8 faces move.b (a3,d0.w),d1 ; Get face from sequence bsr.w SlotMachine_ChangeTarget ; Set slot index to face number, indtead of sequence index move.b #-8,slot1_speed-slot1_index(a1) ; Rotate slowly on the other direction addq.b #4,slot1_rout-slot1_index(a1) ; => SlotMachine_Routine5_3 rts ; =========================================================================== ; loc_2C1DA: SlotMachine_Routine5_3: tst.b slot1_offset-slot1_index(a1) ; Is offset zero? beq.s + ; Branch if yes rts ; =========================================================================== + clr.b slot1_speed-slot1_index(a1) ; Stop slot addq.b #4,slot1_rout-slot1_index(a1) ; => SlotMachine_Routine5_4 rts ; =========================================================================== ; return_2C1EC: SlotMachine_Routine5_4: rts ; =========================================================================== ; loc_2C1EE: SlotMachine_Routine6: clr.w slot1_speed(a4) ; Stop slot 1 clr.w slot2_speed(a4) ; Stop slot 2 clr.w slot3_speed(a4) ; Stop slot 3 clr.b slot_timer(a4) ; Stop drawing the slots bsr.w SlotMachine_ChooseReward _move.b #$18,slot_rout(a4) ; => null routine (rts) rts ; =========================================================================== ; loc_2C20A SlotMachine_DrawSlot: moveq #0,d0 ; Clear d0 move.b slot_index(a4),d0 ; d0 = index of slot to draw lea slots_data(a4),a1 ; a1 = pointer to slots data adda.w d0,a1 ; a1 = pointer to current slot data lea (SlotSequence1).l,a3 ; Get slot sequence adda.w d0,a3 ; Add offset... adda.w d0,a3 ; ... twice jmp BranchTo_SlotMachine_Subroutine(pc,d0.w) ; =========================================================================== BranchTo_SlotMachine_Subroutine bra.w SlotMachine_Subroutine1 ; $00 bra.w SlotMachine_Subroutine2 ; $04 ; bra.w SlotMachine_Subroutine3 ; $08 ;SlotMachine_Subroutine3: clr.b slot_index(a4) ; => SlotMachine_Subroutine1 subq.b #1,slot_timer(a4) ; Decrease timer move.w #tiles_to_bytes(ArtTile_ArtUnc_CNZSlotPics_3),d2 ; DMA destination bra.s + ; =========================================================================== ; loc_2C23A: SlotMachine_Subroutine1: addq.b #4,slot_index(a4) ; => SlotMachine_Subroutine2 move.w #tiles_to_bytes(ArtTile_ArtUnc_CNZSlotPics_1),d2 ; DMA destination bra.w + ; =========================================================================== ; loc_2C246: SlotMachine_Subroutine2: addq.b #4,slot_index(a4) ; => SlotMachine_Subroutine3 move.w #tiles_to_bytes(ArtTile_ArtUnc_CNZSlotPics_2),d2 ; DMA destination + move.w (a1),d0 ; Get last pixel offset move.b 2(a1),d1 ; Get slot rotation speed ext.w d1 ; Extend to word sub.w d1,(a1) ; Modify pixel offset move.w (a1),d3 ; Get current pixel offset andi.w #$7F8,d0 ; Get only desired bits of last pixel offset andi.w #$7F8,d3 ; Get only desired bits of current pixel offset cmp.w d0,d3 ; Are those equal? bne.s + ; Branch if not (need new picture) rts ; --------------------------------------------------------------------------- + bsr.w SlotMachine_GetPixelRow ; Get pointer to pixel row lea (Block_Table+$1000).w,a1 ; Destination for pixel rows move.w #4*8-1,d1 ; Slot picture is 4 tiles - move.l $80(a2),$80(a1) ; Copy pixel row for second column move.l $100(a2),$100(a1) ; Copy pixel row for third column move.l $180(a2),$180(a1) ; Copy pixel row for fourth column move.l (a2)+,(a1)+ ; Copy pixel row for first column, advance destination to next line addq.b #8,d3 ; Increase offset by 8 (byte operation) bne.s + ; If the result is not zero, branch addi.w #$100,d3 ; Advance to next slot picture andi.w #$700,d3 ; Limit the sequence to 8 pictures bsr.w SlotMachine_GetPixelRow ; Need pointer to next pixel row + dbf d1,- ; Loop for aoo pixel rows move.l #(Block_Table+$1000)&$FFFFFF,d1 ; Source tst.w (Two_player_mode).w beq.s + addi.w #tiles_to_bytes(ArtTile_ArtUnc_CNZSlotPics_1_2p-ArtTile_ArtUnc_CNZSlotPics_1),d2 + move.w #$100,d3 ; Number of bytes jsr (QueueDMATransfer).l rts ; =========================================================================== ; loc_2C2B8 SlotMachine_GetPixelRow: move.w d3,d0 ; d0 = pixel offset into slot picture lsr.w #8,d0 ; Convert offset into index andi.w #7,d0 ; Limit each sequence to 8 pictures move.b (a3,d0.w),d0 ; Get slot pic id andi.w #7,d0 ; Get only lower 3 bits; leaves space for 2 more images ror.w #7,d0 ; Equal to shifting left 9 places, or multiplying by 4*4 tiles, in bytes lea (ArtUnc_CNZSlotPics).l,a2 ; Load slot pictures adda.w d0,a2 ; a2 = pointer to first tile of slot picture move.w d3,d0 ; d0 = d3 andi.w #$F8,d0 ; Strip high word (picture index) lsr.w #1,d0 ; Convert into bytes adda.w d0,a2 ; a2 = pointer to desired pixel row rts ; ========================================================================== ; loc_2C2DE: SlotMachine_ChooseReward: move.b slot23_targ(a4),d2 ; Get slots 2 and 3 move.b d2,d3 ; Copy to d3 andi.w #$F0,d2 ; Strip off slot 3 nibble lsr.w #4,d2 ; Shift slot 2 to position andi.w #$F,d3 ; Strip off slot 2 nibble moveq #0,d0 ; Clear d0 cmp.b slot1_targ(a4),d2 ; Are slots 1 and 2 equal? bne.s + ; Branch if not addq.w #4,d0 + cmp.b slot1_targ(a4),d3 ; Are slots 1 and 3 equal? bne.s + ; Branch if not addq.w #8,d0 + jmp SlotMachine_ChooseReward_JmpTable(pc,d0.w) ; ========================================================================== ; loc_2C304: SlotMachine_ChooseReward_JmpTable: ;; bra.w SlotMachine_Unmatched1 ; $00 bra.w SlotMachine_Match12 ; $04 bra.w SlotMachine_Match13 ; $08 ; ========================================================================== ; SlotMachine_TripleMatch: move.w d2,d0 ; d0 = reward index bsr.w SlotMachine_GetReward move.w d0,slots_targ(a4) ; Store reward rts ; =========================================================================== ;loc_2C31C SlotMachine_Match13: cmpi.b #3,d3 ; is slot 3 a jackpot? bne.s + ; Branch if not move.w d2,d0 ; Slot 2 is reward index bsr.w SlotMachine_GetReward bsr.w SlotMachine_QuadrupleUp move.w d0,slots_targ(a4) ; Store reward rts ; =========================================================================== + cmpi.b #3,d2 ; Is slot 2 a jackpot? bne.w SlotMachine_Unmatched1 ; Branch if not move.w d3,d0 ; Slot 3 is reward index bsr.w SlotMachine_GetReward bsr.w SlotMachine_DoubleUp move.w d0,slots_targ(a4) ; Store reward rts ; =========================================================================== ;loc_2C34A SlotMachine_Match12: cmpi.b #3,d2 ; Is slot 2 a jackpot? bne.s + ; Branch if not move.w d3,d0 ; Slot 3 is reward index bsr.s SlotMachine_GetReward bsr.w SlotMachine_QuadrupleUp move.w d0,slots_targ(a4) ; Store reward rts ; =========================================================================== + cmpi.b #3,d3 ; Is slot 3 a jackpot? bne.w SlotMachine_Unmatched1 ; Branch if not move.w d2,d0 ; Slot 2 is reward index bsr.s SlotMachine_GetReward bsr.w SlotMachine_DoubleUp move.w d0,slots_targ(a4) ; Store reward rts ; =========================================================================== ;loc_2C374 SlotMachine_Unmatched1: cmp.b d2,d3 ; Are slots 2 and 3 equal? bne.s SlotMachine_CheckBars ; Branch if not cmpi.b #3,slot1_targ(a4) ; Is slot 1 a jackpot? bne.s + ; Branch if not move.w d2,d0 ; Use slot 2 as reward index bsr.s SlotMachine_GetReward bsr.w SlotMachine_DoubleUp move.w d0,slots_targ(a4) ; Store reward rts ; =========================================================================== + cmpi.b #3,d2 ; Is slot 2 a jackpot? bne.s SlotMachine_CheckBars ; Branch if not move.b slot1_targ(a4),d0 ; Get slot 1 face andi.w #$F,d0 ; Strip high nibble bsr.s SlotMachine_GetReward bsr.w SlotMachine_QuadrupleUp move.w d0,slots_targ(a4) ; Store reward rts ; =========================================================================== ;loc_2C3A8 SlotMachine_CheckBars: moveq #2,d1 ; Number of rings per bar moveq #0,d0 ; Start with zero cmpi.b #5,slot1_targ(a4) ; Is slot 1 a bar? bne.s + ; Branch if not add.w d1,d0 ; Gain 2 rings + cmpi.b #5,d2 ; Is slot 2 a bar? bne.s + ; Branch if not add.w d1,d0 ; Gain 2 rings + cmpi.b #5,d3 ; Is slot 3 a bar? bne.s + ; Branch if not add.w d1,d0 ; Gain 2 rings + move.w d0,slots_targ(a4) ; Store reward ; For bars, the code past this line is useless. There should be an rts here. ;loc_2C3CA SlotMachine_GetReward: add.w d0,d0 ; Convert to index lea (SlotRingRewards).l,a2 ; Ring reward array move.w (a2,d0.w),d0 ; Get ring reward rts ; =========================================================================== ;loc_2C3D8 SlotMachine_QuadrupleUp: asl.w #2,d0 ; Quadruple reward rts ; =========================================================================== ;loc_2C3DC SlotMachine_DoubleUp: add.w d0,d0 ; Double reward rts ; =========================================================================== ; data for the slot machines ;byte_2C3E0 SlotRingRewards: dc.w 30, 25, -1, 150, 10, 20 rev02even ;byte_2C3EC SlotTargetValues: dc.b 8, 3,$33, $12, 0,$00, $12, 1,$11 ,$24, 2,$22 dc.b $1E, 4,$44, $1E, 5,$55, $FF,$F,$FF rev02even ;byte_2C401 SlotSequence1: dc.b 3, 0, 1, 4, 2, 5, 4, 1 rev02even ;byte_2C409 SlotSequence2: dc.b 3, 0, 1, 4, 2, 5, 0, 2 rev02even ;byte_2C411 SlotSequence3: dc.b 3, 0, 1, 4, 2, 5, 4, 1 even ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo10_SingleObjLoad jmp (SingleObjLoad).l JmpTo29_MarkObjGone jmp (MarkObjGone).l JmpTo10_AnimateSprite jmp (AnimateSprite).l JmpTo6_Adjust2PArtPointer2 jmp (Adjust2PArtPointer2).l JmpTo54_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo12_CalcSine jmp (CalcSine).l JmpTo7_SolidObject_Always_SingleCharacter jmp (SolidObject_Always_SingleCharacter).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object D7 - Bumper from Casino Night Zone ; ---------------------------------------------------------------------------- ; Sprite_2C448: ObjD7: moveq #0,d0 move.b routine(a0),d0 move.w ObjD7_Index(pc,d0.w),d1 jmp ObjD7_Index(pc,d1.w) ; =========================================================================== ; off_2C456: ObjD7_Index: offsetTable offsetTableEntry.w ObjD7_Init ; 0 offsetTableEntry.w ObjD7_Main ; 2 ; =========================================================================== ; loc_2C45A: ObjD7_Init: addq.b #2,routine(a0) move.l #ObjD7_MapUnc_2C626,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CNZHexBumper,2,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo55_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #1,priority(a0) move.b #$CA,collision_flags(a0) btst #0,status(a0) beq.s + move.b #1,objoff_34(a0) + move.w x_pos(a0),d0 move.w d0,d1 subi.w #$60,d0 move.w d0,objoff_30(a0) addi.w #$60,d1 move.w d1,objoff_32(a0) ; loc_2C4AC: ObjD7_Main: move.b collision_property(a0),d0 beq.w ObjD7_MainContinued lea (MainCharacter).w,a1 ; a1=character bclr #0,collision_property(a0) beq.s + bsr.s ObjD7_BouncePlayerOff + lea (Sidekick).w,a1 ; a1=character bclr #1,collision_property(a0) beq.s + bsr.s ObjD7_BouncePlayerOff + clr.b collision_property(a0) bra.w ObjD7_MainContinued ; =========================================================================== ; loc_2C4D8: ObjD7_BouncePlayerOff: move.w x_pos(a0),d1 move.w y_pos(a0),d2 sub.w x_pos(a1),d1 sub.w y_pos(a1),d2 jsr (CalcAngle).l addi.b #$20,d0 andi.w #$C0,d0 cmpi.w #$40,d0 beq.s ObjD7_BounceDown cmpi.w #$80,d0 beq.s ObjD7_BounceRight cmpi.w #$C0,d0 beq.s ObjD7_BounceUp move.w #-$800,x_vel(a1) move.b #2,anim(a0) bra.s ObjD7_BounceEnd ; =========================================================================== ; loc_2C516: ObjD7_BounceDown: subi.w #$200,x_vel(a1) tst.w d1 bpl.s + addi.w #$400,x_vel(a1) + move.w #-$800,y_vel(a1) move.b #1,anim(a0) bra.s ObjD7_BounceEnd ; =========================================================================== ; loc_2C534: ObjD7_BounceRight: move.w #$800,x_vel(a1) move.b #2,anim(a0) bra.s ObjD7_BounceEnd ; =========================================================================== ; loc_2C542: ObjD7_BounceUp: subi.w #$200,x_vel(a1) tst.w d1 bpl.s + addi.w #$400,x_vel(a1) + move.w #$800,y_vel(a1) move.b #1,anim(a0) ; loc_2C55E: ObjD7_BounceEnd: bset #1,status(a1) bclr #4,status(a1) bclr #5,status(a1) clr.b jumping(a1) move.w #SndID_Bumper,d0 jmp (PlaySound).l ; =========================================================================== ; loc_2C57E: ObjD7_MainContinued: lea (Ani_objD7).l,a1 jsrto (AnimateSprite).l, JmpTo11_AnimateSprite tst.b subtype(a0) beq.w JmpTo30_MarkObjGone tst.b objoff_34(a0) beq.s loc_2C5AE move.w x_pos(a0),d0 subq.w #1,d0 cmp.w objoff_30(a0),d0 bne.s + move.b #0,objoff_34(a0) + move.w d0,x_pos(a0) bra.s loc_2C5C4 ; =========================================================================== loc_2C5AE: move.w x_pos(a0),d0 addq.w #1,d0 cmp.w objoff_32(a0),d0 bne.s + move.b #1,objoff_34(a0) + move.w d0,x_pos(a0) loc_2C5C4: tst.w (Two_player_mode).w beq.s + jmpto (DisplaySprite).l, JmpTo30_DisplaySprite ; --------------------------------------------------------------------------- + move.w objoff_30(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bls.s + move.w objoff_32(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.s loc_2C5F8 + jmp (DisplaySprite).l ; =========================================================================== loc_2C5F8: lea (Object_Respawn_Table).w,a2 moveq #0,d0 move.b respawn_index(a0),d0 beq.s + bclr #7,2(a2,d0.w) + jmp (DeleteObject).l if removeJmpTos JmpTo30_MarkObjGone jmp (MarkObjGone).l endif ; =========================================================================== ; animation script ; off_2C610: Ani_objD7: offsetTable offsetTableEntry.w byte_2C616 ; 0 offsetTableEntry.w byte_2C619 ; 1 offsetTableEntry.w byte_2C61F ; 2 byte_2C616: dc.b $F, 0,$FF rev02even byte_2C619: dc.b 3, 1, 0, 1,$FD, 0 rev02even byte_2C61F: dc.b 3, 2, 0, 2,$FD, 0 even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjD7_MapUnc_2C626: BINCLUDE "mappings/sprite/objD7.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo30_DisplaySprite jmp (DisplaySprite).l JmpTo30_MarkObjGone jmp (MarkObjGone).l JmpTo11_AnimateSprite jmp (AnimateSprite).l JmpTo55_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object D8 - Block thingy from CNZ that disappears after 3 hits (UFO saucer-shaped) ; ---------------------------------------------------------------------------- ; Sprite_2C6AC: ObjD8: moveq #0,d0 move.b routine(a0),d0 move.w ObjD8_Index(pc,d0.w),d1 jmp ObjD8_Index(pc,d1.w) ; =========================================================================== ; off_2C6BA: ObjD8_Index: offsetTable offsetTableEntry.w ObjD8_Init ; 0 offsetTableEntry.w loc_2C6FC ; 2 offsetTableEntry.w loc_2C884 ; 4 ; =========================================================================== ; loc_2C6C0: ObjD8_Init: addq.b #2,routine(a0) move.l #ObjD8_MapUnc_2C8C4,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CNZMiniBumper,2,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo56_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #1,priority(a0) move.b #$D7,collision_flags(a0) move.b subtype(a0),d0 rol.b #2,d0 andi.b #3,d0 move.b d0,anim(a0) loc_2C6FC: move.b collision_property(a0),d0 bne.w loc_2C70A tst.w objoff_30(a0) beq.s loc_2C740 loc_2C70A: lea objoff_30(a0),a4 tst.b (a4) beq.s loc_2C716 subq.b #1,(a4) bra.s loc_2C724 ; =========================================================================== loc_2C716: lea (MainCharacter).w,a1 ; a1=character bclr #0,collision_property(a0) beq.s loc_2C724 bsr.s loc_2C74E loc_2C724: addq.w #1,a4 tst.b (a4) beq.s loc_2C72E subq.b #1,(a4) bra.s loc_2C73C ; =========================================================================== loc_2C72E: lea (Sidekick).w,a1 ; a1=character bclr #1,collision_property(a0) beq.s loc_2C73C bsr.s loc_2C74E loc_2C73C: clr.b collision_property(a0) loc_2C740: lea (Ani_objD8).l,a1 jsrto (AnimateSprite).l, JmpTo12_AnimateSprite jmpto (MarkObjGone).l, JmpTo31_MarkObjGone ; =========================================================================== loc_2C74E: move.b mapping_frame(a0),d0 subq.b #3,d0 beq.s loc_2C75C bcc.s loc_2C77A addq.b #3,d0 bne.s loc_2C77A loc_2C75C: move.b #3,anim(a0) move.w #-$700,y_vel(a1) move.w y_pos(a0),d2 sub.w y_pos(a1),d2 bpl.s BranchTo_loc_2C806 neg.w y_vel(a1) BranchTo_loc_2C806 bra.w loc_2C806 ; =========================================================================== loc_2C77A: subq.b #1,d0 bne.s loc_2C7EC move.b #4,anim(a0) move.w #$20,d3 btst #0,status(a0) bne.s loc_2C794 move.w #$60,d3 loc_2C794: move.w x_vel(a1),d1 move.w y_vel(a1),d2 jsr (CalcAngle).l sub.w d3,d0 mvabs.w d0,d1 neg.w d0 add.w d3,d0 cmpi.b #$40,d1 bhs.s loc_2C7BE cmpi.b #$38,d1 blo.s loc_2C7D0 move.w d3,d0 bra.s loc_2C7D0 ; =========================================================================== loc_2C7BE: subi.w #$80,d1 neg.w d1 cmpi.b #$38,d1 blo.s loc_2C7D0 move.w d3,d0 addi.w #$80,d0 loc_2C7D0: jsr (CalcSine).l muls.w #-$700,d1 asr.l #8,d1 move.w d1,x_vel(a1) muls.w #-$700,d0 asr.l #8,d0 move.w d0,y_vel(a1) bra.s loc_2C806 ; =========================================================================== loc_2C7EC: move.b #5,anim(a0) move.w #-$700,x_vel(a1) move.w x_pos(a0),d2 sub.w x_pos(a1),d2 bpl.s loc_2C806 neg.w x_vel(a1) loc_2C806: bset #1,status(a1) bclr #4,status(a1) bclr #5,status(a1) clr.b jumping(a1) move.w #SndID_BonusBumper,d0 jsr (PlaySound).l movea.w a1,a3 moveq #4,d3 moveq #1,d0 subi.w #palette_line_1,art_tile(a0) bcc.s loc_2C85C addi.w #palette_line_1,art_tile(a0) move.b #4,routine(a0) lea (CNZ_saucer_data).w,a1 move.b subtype(a0),d1 andi.w #$3F,d1 ; This means CNZ_saucer_data is only $40 bytes large lea (a1,d1.w),a1 addq.b #1,(a1) cmpi.b #3,(a1) blo.s loc_2C85C moveq #2,d3 moveq #50,d0 loc_2C85C: jsr (AddPoints2).l jsrto (SingleObjLoad).l, JmpTo11_SingleObjLoad bne.s loc_2C87E _move.b #ObjID_Points,id(a1) ; load obj29 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b d3,mapping_frame(a1) loc_2C87E: move.b #4,(a4) rts ; =========================================================================== loc_2C884: lea (Ani_objD8).l,a1 jsrto (AnimateSprite).l, JmpTo12_AnimateSprite cmpi.b #3,anim(a0) blo.w JmpTo46_DeleteObject jmpto (MarkObjGone).l, JmpTo31_MarkObjGone if removeJmpTos JmpTo46_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== ; animation script ; off_2C89C: Ani_objD8: offsetTable offsetTableEntry.w byte_2C8A8 ; 0 offsetTableEntry.w byte_2C8AB ; 1 offsetTableEntry.w byte_2C8AE ; 2 offsetTableEntry.w byte_2C8B1 ; 3 offsetTableEntry.w byte_2C8B7 ; 4 offsetTableEntry.w byte_2C8BD ; 5 byte_2C8A8: dc.b $F, 0,$FF rev02even byte_2C8AB: dc.b $F, 1,$FF rev02even byte_2C8AE: dc.b $F, 2,$FF rev02even byte_2C8B1: dc.b 3, 3, 0, 3,$FD, 0 rev02even byte_2C8B7: dc.b 3, 4, 1, 4,$FD, 1 rev02even byte_2C8BD: dc.b 3, 5, 2, 5,$FD, 2 even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjD8_MapUnc_2C8C4: BINCLUDE "mappings/sprite/objD8.bin" ; =========================================================================== if ~~removeJmpTos JmpTo46_DeleteObject jmp (DeleteObject).l JmpTo11_SingleObjLoad jmp (SingleObjLoad).l JmpTo31_MarkObjGone jmp (MarkObjGone).l JmpTo12_AnimateSprite jmp (AnimateSprite).l JmpTo56_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object D9 - Invisible sprite that you can hang on to, like the blocks in WFZ ; ---------------------------------------------------------------------------- ; Sprite_2C92C: ObjD9: moveq #0,d0 move.b routine(a0),d0 move.w ObjD9_Index(pc,d0.w),d1 jmp ObjD9_Index(pc,d1.w) ; =========================================================================== ; off_2C93A: ObjD9_Index: offsetTable offsetTableEntry.w ObjD9_Init ; 0 offsetTableEntry.w ObjD9_Main ; 2 ; =========================================================================== ; loc_2C93E: ObjD9_Init: addq.b #2,routine(a0) move.b #4,render_flags(a0) move.b #$18,width_pixels(a0) move.b #4,priority(a0) ; loc_2C954: ObjD9_Main: lea objoff_30(a0),a2 lea (MainCharacter).w,a1 ; a1=character move.w (Ctrl_1).w,d0 bsr.s ObjD9_CheckCharacter lea (Sidekick).w,a1 ; a1=character addq.w #1,a2 move.w (Ctrl_2).w,d0 bsr.s ObjD9_CheckCharacter jmpto (MarkObjGone3).l, JmpTo7_MarkObjGone3 ; =========================================================================== ; loc_2C972: ObjD9_CheckCharacter: tst.b (a2) beq.s loc_2C9A0 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 beq.w ObjD9_CheckCharacter_End clr.b obj_control(a1) clr.b (a2) move.b #$12,2(a2) andi.w #(button_up_mask|button_down_mask|button_left_mask|button_right_mask)<<8,d0 beq.s + move.b #$3C,2(a2) + move.w #-$300,y_vel(a1) bra.w ObjD9_CheckCharacter_End ; =========================================================================== loc_2C9A0: tst.b 2(a2) beq.s + subq.b #1,2(a2) bne.w ObjD9_CheckCharacter_End + move.w x_pos(a1),d0 sub.w x_pos(a0),d0 addi.w #$18,d0 cmpi.w #$30,d0 bhs.w ObjD9_CheckCharacter_End move.w y_pos(a1),d1 sub.w y_pos(a0),d1 cmpi.w #$10,d1 bhs.w ObjD9_CheckCharacter_End tst.b obj_control(a1) bmi.s ObjD9_CheckCharacter_End cmpi.b #6,routine(a1) bhs.s ObjD9_CheckCharacter_End tst.w (Debug_placement_mode).w bne.s ObjD9_CheckCharacter_End clr.w x_vel(a1) clr.w y_vel(a1) clr.w inertia(a1) move.w y_pos(a0),y_pos(a1) move.b #AniIDSonAni_Hang2,anim(a1) move.b #1,obj_control(a1) move.b #1,(a2) ; return_2CA08: ObjD9_CheckCharacter_End: rts ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo7_MarkObjGone3 jmp (MarkObjGone3).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 4A - Octus (octopus badnik) from OOZ ; ---------------------------------------------------------------------------- octus_start_position = objoff_2A ; Sprite_2CA14: Obj4A: moveq #0,d0 move.b routine(a0),d0 move.w Obj4A_Index(pc,d0.w),d1 jmp Obj4A_Index(pc,d1.w) ; =========================================================================== ; off_2CA22: Obj4A_Index: offsetTable offsetTableEntry.w Obj4A_Init ; 0 offsetTableEntry.w Obj4A_Main ; 2 offsetTableEntry.w Obj4A_Angry ; 4 - unused offsetTableEntry.w Obj4A_Bullet ; 6 ; =========================================================================== ; loc_2CA2A: Obj4A_Bullet: subi_.w #1,objoff_2C(a0) bmi.s + rts ; --------------------------------------------------------------------------- + jsrto (ObjectMove).l, JmpTo19_ObjectMove lea (Ani_obj4A).l,a1 jsrto (AnimateSprite).l, JmpTo13_AnimateSprite jmpto (MarkObjGone).l, JmpTo32_MarkObjGone ; =========================================================================== ; loc_2CA46: Obj4A_Angry: ; Used by removed sub-object subq.w #1,objoff_2C(a0) beq.w JmpTo47_DeleteObject jmpto (DisplaySprite).l, JmpTo31_DisplaySprite if removeJmpTos JmpTo47_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== ; loc_2CA52: Obj4A_Init: move.l #Obj4A_MapUnc_2CBFE,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Octus,1,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$A,collision_flags(a0) move.b #4,priority(a0) move.b #$10,width_pixels(a0) move.b #$B,y_radius(a0) move.b #8,x_radius(a0) jsrto (ObjectMoveAndFall).l, JmpTo2_ObjectMoveAndFall jsr (ObjCheckFloorDist).l tst.w d1 bpl.s + add.w d1,y_pos(a0) move.w #0,y_vel(a0) addq.b #2,routine(a0) move.w x_pos(a0),d0 sub.w (MainCharacter+x_pos).w,d0 bpl.s + bchg #0,status(a0) + move.w y_pos(a0),octus_start_position(a0) rts ; =========================================================================== ; loc_2CAB8: Obj4A_Main: moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj4A_Main_Index(pc,d0.w),d1 jsr Obj4A_Main_Index(pc,d1.w) lea (Ani_obj4A).l,a1 jsrto (AnimateSprite).l, JmpTo13_AnimateSprite jmpto (MarkObjGone).l, JmpTo32_MarkObjGone ; =========================================================================== ; off_2CAD4: Obj4A_Main_Index: offsetTable offsetTableEntry.w Obj4A_WaitForCharacter ; 0 offsetTableEntry.w Obj4A_DelayBeforeMoveUp ; 2 offsetTableEntry.w Obj4A_MoveUp ; 4 offsetTableEntry.w Obj4A_Hover ; 6 offsetTableEntry.w Obj4A_MoveDown ; 8 ; =========================================================================== ; loc_2CADE: Obj4A_WaitForCharacter: move.w x_pos(a0),d0 sub.w (MainCharacter+x_pos).w,d0 cmpi.w #$80,d0 bgt.s + ; rts cmpi.w #-$80,d0 blt.s + ; rts addq.b #2,routine_secondary(a0) move.b #3,anim(a0) move.w #$20,objoff_2C(a0) + rts ; =========================================================================== ; loc_2CB04: Obj4A_DelayBeforeMoveUp: subq.w #1,objoff_2C(a0) bmi.s + rts ; --------------------------------------------------------------------------- + addq.b #2,routine_secondary(a0) move.b #4,anim(a0) move.w #-$200,y_vel(a0) jmpto (ObjectMove).l, JmpTo19_ObjectMove ; =========================================================================== ; loc_2CB20: Obj4A_MoveUp: addi.w #$10,y_vel(a0) bpl.s + jmpto (ObjectMove).l, JmpTo19_ObjectMove ; =========================================================================== + addq.b #2,routine_secondary(a0) move.w #$3C,objoff_2C(a0) bra.w Obj4A_FireBullet ; =========================================================================== ; loc_2CB3A: Obj4A_Hover: subq.w #1,objoff_2C(a0) bmi.s + rts ; --------------------------------------------------------------------------- + addq.b #2,routine_secondary(a0) rts ; =========================================================================== ; loc_2CB48: Obj4A_MoveDown: addi.w #$10,y_vel(a0) move.w y_pos(a0),d0 cmp.w octus_start_position(a0),d0 bhs.s + jmpto (ObjectMove).l, JmpTo19_ObjectMove ; =========================================================================== + clr.b routine_secondary(a0) clr.b anim(a0) clr.w y_vel(a0) move.b #1,mapping_frame(a0) rts ; =========================================================================== ; loc_2CB70: Obj4A_FireBullet: ; In the Simon Wai beta, the object loads another object ; here, which makes it look angry as it fires. ; This object would have used Obj4A_Angry. jsr (SingleObjLoad).l bne.s + ; rts _move.b #ObjID_Octus,id(a1) ; load obj4A move.b #6,routine(a1) move.l #Obj4A_MapUnc_2CBFE,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_Octus,1,0),art_tile(a1) move.b #4,priority(a1) move.b #$10,width_pixels(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w #$F,objoff_2C(a1) move.b render_flags(a0),render_flags(a1) move.b status(a0),status(a1) move.b #2,anim(a1) move.b #$98,collision_flags(a1) move.w #-$200,x_vel(a1) btst #0,render_flags(a1) beq.s + ; rts neg.w x_vel(a1) + rts ; =========================================================================== ; animation script ; off_2CBDC: Ani_obj4A: offsetTable offsetTableEntry.w byte_2CBE6 ; 0 offsetTableEntry.w byte_2CBEA ; 1 offsetTableEntry.w byte_2CBEF ; 2 offsetTableEntry.w byte_2CBF4 ; 3 offsetTableEntry.w byte_2CBF8 ; 4 byte_2CBE6: dc.b $F, 1, 0,$FF rev02even byte_2CBEA: dc.b 3, 1, 2, 3,$FF rev02even byte_2CBEF: dc.b 2, 5, 6,$FF even byte_2CBF4: dc.b $F, 4,$FF even byte_2CBF8: dc.b 7, 0, 1,$FD, 1 even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj4A_MapUnc_2CBFE: BINCLUDE "mappings/sprite/obj4A.bin" if ~~removeJmpTos align 4 endif ; =========================================================================== if ~~removeJmpTos JmpTo31_DisplaySprite jmp (DisplaySprite).l JmpTo47_DeleteObject jmp (DeleteObject).l JmpTo32_MarkObjGone jmp (MarkObjGone).l JmpTo13_AnimateSprite jmp (AnimateSprite).l JmpTo2_ObjectMoveAndFall jmp (ObjectMoveAndFall).l ; loc_2CCC2: JmpTo19_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 50 - Aquis (seahorse badnik) from OOZ ; ---------------------------------------------------------------------------- ; OST Variables: Obj50_unkown1 = objoff_2A ; word Obj50_shooting_flag = objoff_2D ; byte ; if set, shooting is disabled Obj50_shots_remaining = objoff_2E ; word ; number of shots before retreating Obj50_unkown2 = objoff_30 ; word Obj50_unkown3 = objoff_32 ; word Obj50_unkown4 = objoff_34 ; word Obj50_child = objoff_36 ; long ; pointer to wing object (main) Obj50_parent = objoff_36 ; long ; pointer to main object (wing) Obj50_unkown5 = objoff_3A ; word Obj50_timer = objoff_3C ; byte ; time spent following the player before shooting and time to wait before actually shooting ; Sprite_2CCC8: Obj50: moveq #0,d0 move.b routine(a0),d0 move.w Obj50_Index(pc,d0.w),d1 jmp Obj50_Index(pc,d1.w) ; =========================================================================== ; off_2CCD6: Obj50_Index: offsetTable offsetTableEntry.w Obj50_Init ; 0 offsetTableEntry.w Obj50_Main ; 2 offsetTableEntry.w Obj50_Wing ; 4 offsetTableEntry.w Obj50_Bullet ; 6 ; =========================================================================== ; loc_2CCDE: Obj50_Init: addq.b #2,routine(a0) move.l #Obj50_MapUnc_2CF94,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Aquis,1,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$A,collision_flags(a0) move.b #4,priority(a0) move.b #$10,width_pixels(a0) move.w #-$100,x_vel(a0) move.b subtype(a0),d0 move.b d0,d1 andi.w #$F0,d1 lsl.w #4,d1 move.w d1,Obj50_shots_remaining(a0) ; looks like the number of shots could be set via subtype at one point move.w d1,Obj50_unkown2(a0) ; unused andi.w #$F,d0 lsl.w #4,d0 subq.w #1,d0 move.w d0,Obj50_unkown3(a0) ; unused move.w d0,Obj50_unkown4(a0) ; unused move.w y_pos(a0),Obj50_unkown1(a0) ; unused move.w (Water_Level_1).w,Obj50_unkown5(a0) move.b #3,Obj50_shots_remaining(a0) ; hardcoded to three shots ; creat wing child object jsrto (SingleObjLoad).l, JmpTo12_SingleObjLoad bne.s Obj50_Main _move.b #ObjID_Aquis,id(a1) ; load obj50 move.b #4,routine(a1) ; => Obj50_Wing move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$A,x_pos(a1) addi.w #-6,y_pos(a1) move.l #Obj50_MapUnc_2CF94,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_Aquis,1,0),art_tile(a1) ori.b #4,render_flags(a1) move.b #3,priority(a1) move.b status(a0),status(a1) move.b #3,anim(a1) move.l a1,Obj50_child(a0) move.l a0,Obj50_parent(a1) bset #6,status(a0) ; set compund sprite flag. This is useless, as the object doesn't define any child spites, nor does it set its child sprite count ; loc_2CDA2: Obj50_Main: lea (Ani_obj50).l,a1 jsrto (AnimateSprite).l, JmpTo14_AnimateSprite moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj50_Main_Index(pc,d0.w),d1 jsr Obj50_Main_Index(pc,d1.w) bsr.w Obj50_ControlWing jmpto (MarkObjGone).l, JmpTo33_MarkObjGone ; =========================================================================== ; off_2CDC2: Obj50_Main_Index: offsetTable offsetTableEntry.w Obj50_CheckIfOnScreen ; 0 offsetTableEntry.w Obj50_Chase ; 2 offsetTableEntry.w Obj50_Shooting ; 4 offsetTableEntry.w BranchTo_JmpTo20_ObjectMove ; 6 ; =========================================================================== ; loc_2CDCA: Obj50_Wing: movea.l Obj50_parent(a0),a1 ; a1=object tst.b id(a1) ; is parent object's slot empty? beq.w JmpTo48_DeleteObject ; if yes, branch cmpi.b #ObjID_Aquis,(a1) ; is parent object ObjID_Aquis? bne.w JmpTo48_DeleteObject ; if not, branch btst #7,status(a1) ; is parent object marked as destroyed? bne.w JmpTo48_DeleteObject ; if yes, branch lea (Ani_obj50).l,a1 jsrto (AnimateSprite).l, JmpTo14_AnimateSprite jmpto (DisplaySprite).l, JmpTo32_DisplaySprite ; =========================================================================== ; loc_2CDF4: Obj50_Bullet: jsrto (ObjectMove).l, JmpTo20_ObjectMove lea (Ani_obj50).l,a1 jsrto (AnimateSprite).l, JmpTo14_AnimateSprite jmpto (MarkObjGone).l, JmpTo33_MarkObjGone ; =========================================================================== ; wait and do nothing until on screen ; loc_2CE06: Obj50_CheckIfOnScreen: tst.b render_flags(a0) bmi.s + rts ; =========================================================================== + addq.b #2,routine_secondary(a0) ; => Obj50_Chase rts ; =========================================================================== ; loc_2CE14: Obj50_Chase: bsr.w Obj50_FollowPlayer rts ; =========================================================================== ; loc_2CE1A: Obj50_Shooting: bsr.w Obj50_WaitForNextShot bsr.w Obj50_ChkIfShoot rts ; =========================================================================== ; loc_2CE24: Obj50_ChkIfShoot: tst.b Obj50_shooting_flag(a0) ; is object allowed to shoot? bne.w return_2CEAC ; if not, branch st Obj50_shooting_flag(a0) ; else, disallow shooting after this jsrto (Obj_GetOrientationToPlayer).l, JmpTo_Obj_GetOrientationToPlayer tst.w d1 ; is player above object? beq.s return_2CEAC ; if yes, don't shoot cmpi.w #$FFF0,d1 ; ? d1 should only be 0 or 2 here... bhs.s return_2CEAC ; shoot bullet jsrto (SingleObjLoad).l, JmpTo12_SingleObjLoad bne.s return_2CEAC _move.b #ObjID_Aquis,id(a1) ; load obj50 move.b #6,routine(a1) ; => Obj50_Bullet move.w x_pos(a0),x_pos(a1) ; align with parent object move.w y_pos(a0),y_pos(a1) move.l #Obj50_MapUnc_2CF94,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_Aquis,1,0),art_tile(a1) ori.b #4,render_flags(a1) move.b #3,priority(a1) move.b #$98,collision_flags(a1) move.b #2,anim(a1) move.w #$A,d0 ; set y offset move.w #$10,d1 ; set x offset move.w #-$300,d2 ; set x velocity btst #0,status(a0) ; is object facing right? beq.s + ; if yes, branch neg.w d1 ; else, align bullet with other side of object... neg.w d2 ; ... and move in the opposite direction + sub.w d0,y_pos(a1) sub.w d1,x_pos(a1) move.w d2,x_vel(a1) move.w #$200,y_vel(a1) return_2CEAC: rts ; =========================================================================== ; follow player for a while; target is whichever character is the closest ; loc_2CEAE: Obj50_FollowPlayer: subq.b #1,Obj50_timer(a0) bmi.s Obj50_DoneFollowing ; branch, if counter has expired jsrto (Obj_GetOrientationToPlayer).l, JmpTo_Obj_GetOrientationToPlayer bclr #0,status(a0) ; face right tst.w d0 beq.s + ; branch, if player is right from object bset #0,status(a0) ; otherwise, face left + ; make object move towards player; d0 and d1 were set by the GetOrientationToPlayer routine move.w Obj50_Speeds(pc,d0.w),d2 add.w d2,x_vel(a0) move.w Obj50_Speeds(pc,d1.w),d2 add.w d2,y_vel(a0) move.w #$100,d0 ; $100 is object's max x... move.w d0,d1 ; ... and y velocity jsrto (Obj_CapSpeed).l, JmpTo_Obj_CapSpeed jmpto (ObjectMove).l, JmpTo20_ObjectMove ; =========================================================================== ; word_2CEE6: Obj50_Speeds: dc.w -$10 ; 0 - left/up dc.w $10 ; 2 - right/down ; =========================================================================== ; loc_2CEEA: Obj50_DoneFollowing: addq.b #2,routine_secondary(a0) ; => Obj50_Shooting move.b #$20,Obj50_timer(a0) jmpto (Obj_MoveStop).l, JmpTo_Obj_MoveStop ; =========================================================================== ; loc_2CEF8: Obj50_WaitForNextShot: subq.b #1,Obj50_timer(a0) ; wait for a while bmi.s + ; branch, if counter has expired rts ; =========================================================================== + ; check if object is out of shots and flee if it is subq.b #1,Obj50_shots_remaining(a0) bmi.s Obj50_GoAway ; branch, if object is out of atttacks ; otherwise, shoot and return to chasing the player subq.b #2,routine_secondary(a0) ; => Obj50_Chase move.w #-$100,y_vel(a0) move.b #$80,Obj50_timer(a0) ; reset timer clr.b Obj50_shooting_flag(a0) ; reenbale shooting rts ; =========================================================================== ; loc_2CF1C: Obj50_GoAway: move.b #6,routine_secondary(a0) ; => BranchTo_JmpTo20_ObjectMove move.w #-$200,x_vel(a0) ; fly off to the left clr.w y_vel(a0) rts ; =========================================================================== BranchTo_JmpTo20_ObjectMove jmpto (ObjectMove).l, JmpTo20_ObjectMove ; =========================================================================== ; loc_2CF32: Obj50_ControlWing: moveq #$A,d0 ; x offset moveq #-6,d1 ; y offset movea.l Obj50_child(a0),a1 ; a1=object move.w x_pos(a0),x_pos(a1) ; align child with parent object move.w y_pos(a0),y_pos(a1) move.b status(a0),status(a1) move.b respawn_index(a0),respawn_index(a1) move.b render_flags(a0),render_flags(a1) btst #0,status(a1) ; is object facing right? beq.s + ; if yes, branch neg.w d0 ; else, align wing with other side of object + add.w d0,x_pos(a1) add.w d1,y_pos(a1) rts ; =========================================================================== ; animation script ; off_2CF6C: Ani_obj50: offsetTable offsetTableEntry.w Ani_obj50_Normal ; 0 offsetTableEntry.w byte_2CF7B ; 1 offsetTableEntry.w Ani_obj50_Bullet ; 2 offsetTableEntry.w Ani_obj50_Wing ; 3 offsetTableEntry.w byte_2CF8D ; 4 offsetTableEntry.w byte_2CF90 ; 5 Ani_obj50_Normal: dc.b $E, 0,$FF ; byte_2CF78 rev02even byte_2CF7B: dc.b 5, 3, 4, 3, 4, 3, 4,$FF rev02even Ani_obj50_Bullet: dc.b 3, 5, 6, 7, 6,$FF ; byte_2CF83 rev02even Ani_obj50_Wing: dc.b 3, 1, 2,$FF ; byte_2CF89 rev02even byte_2CF8D: dc.b 1, 5,$FF rev02even byte_2CF90: dc.b $E, 8,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj50_MapUnc_2CF94: BINCLUDE "mappings/sprite/obj50.bin" ; =========================================================================== if ~~removeJmpTos JmpTo32_DisplaySprite jmp (DisplaySprite).l JmpTo48_DeleteObject jmp (DeleteObject).l JmpTo12_SingleObjLoad jmp (SingleObjLoad).l JmpTo33_MarkObjGone jmp (MarkObjGone).l JmpTo14_AnimateSprite jmp (AnimateSprite).l JmpTo_Obj_GetOrientationToPlayer jmp (Obj_GetOrientationToPlayer).l JmpTo_Obj_CapSpeed jmp (Obj_CapSpeed).l JmpTo_Obj_MoveStop jmp (Obj_MoveStop).l ; loc_2D060: JmpTo20_ObjectMove jmp (ObjectMove).l align 4 else JmpTo48_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 4B - Buzzer (Buzz bomber) from EHZ ; ---------------------------------------------------------------------------- ; OST Variables: Obj4B_parent = objoff_2A ; long Obj4B_move_timer = objoff_2E ; word Obj4B_turn_delay = objoff_30 ; word Obj4B_shooting_flag = objoff_32 ; byte Obj4B_shot_timer = objoff_34 ; word ; Sprite_2D068: ; Obj_Buzzer: Obj4B: moveq #0,d0 move.b routine(a0),d0 move.w Obj4B_Index(pc,d0.w),d1 jmp Obj4B_Index(pc,d1.w) ; =========================================================================== ; off_2D076: Obj4B_Index: offsetTable offsetTableEntry.w Obj4B_Init ; 0 offsetTableEntry.w Obj4B_Main ; 2 offsetTableEntry.w Obj4B_Flame ; 4 offsetTableEntry.w Obj4B_Projectile ; 6 ; =========================================================================== ; loc_2D07E: Obj4B_Projectile: jsrto (ObjectMove).l, JmpTo21_ObjectMove lea (Ani_obj4B).l,a1 jsrto (AnimateSprite).l, JmpTo15_AnimateSprite jmpto (MarkObjGone_P1).l, JmpTo_MarkObjGone_P1 ; =========================================================================== ; loc_2D090: Obj4B_Flame: movea.l Obj4B_parent(a0),a1 ; a1=object tst.b id(a1) beq.w JmpTo49_DeleteObject ; branch, if object slot is empty. This check is incomplete and very unreliable; check Obj50_Wing to see how it should be done tst.w Obj4B_turn_delay(a1) bmi.s + ; branch, if parent isn't currently turning around rts ; --------------------------------------------------------------------------- + ; follow parent object move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) move.b status(a1),status(a0) move.b render_flags(a1),render_flags(a0) lea (Ani_obj4B).l,a1 jsrto (AnimateSprite).l, JmpTo15_AnimateSprite jmpto (MarkObjGone_P1).l, JmpTo_MarkObjGone_P1 ; =========================================================================== ; loc_2D0C8: Obj4B_Init: move.l #Obj4B_MapUnc_2D2EA,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Buzzer,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo57_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #$A,collision_flags(a0) move.b #4,priority(a0) move.b #$10,width_pixels(a0) move.b #$10,y_radius(a0) move.b #$18,x_radius(a0) move.b #3,priority(a0) addq.b #2,routine(a0) ; => Obj4B_Main ; load exhaust flame object jsrto (SingleObjLoad2).l, JmpTo20_SingleObjLoad2 bne.s + ; rts _move.b #ObjID_Buzzer,id(a1) ; load obj4B move.b #4,routine(a1) ; => Obj4B_Flame move.l #Obj4B_MapUnc_2D2EA,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_Buzzer,0,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo7_Adjust2PArtPointer2 move.b #4,priority(a1) move.b #$10,width_pixels(a1) move.b status(a0),status(a1) move.b render_flags(a0),render_flags(a1) move.b #1,anim(a1) move.l a0,Obj4B_parent(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w #$100,Obj4B_move_timer(a0) move.w #-$100,x_vel(a0) btst #0,render_flags(a0) beq.s + ; rts neg.w x_vel(a0) + rts ; =========================================================================== ; loc_2D174: Obj4B_Main: moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj4B_Buzzer_States(pc,d0.w),d1 jsr Obj4B_Buzzer_States(pc,d1.w) lea (Ani_obj4B).l,a1 jsrto (AnimateSprite).l, JmpTo15_AnimateSprite jmpto (MarkObjGone_P1).l, JmpTo_MarkObjGone_P1 ; =========================================================================== ; off_2D190: Obj4B_Buzzer_States: offsetTable offsetTableEntry.w Obj4B_Roaming ; 0 offsetTableEntry.w Obj4B_Shooting ; 2 ; =========================================================================== ; loc_2D194: Obj4B_Roaming: bsr.w Obj4B_ChkPlayers subq.w #1,Obj4B_turn_delay(a0) move.w Obj4B_turn_delay(a0),d0 cmpi.w #$F,d0 beq.s Obj4B_TurnAround tst.w d0 bpl.s return_2D1B8 subq.w #1,Obj4B_move_timer(a0) bgt.w JmpTo21_ObjectMove move.w #$1E,Obj4B_turn_delay(a0) return_2D1B8: rts ; --------------------------------------------------------------------------- ; loc_2D1BA: Obj4B_TurnAround: sf Obj4B_shooting_flag(a0) ; reenable shooting neg.w x_vel(a0) ; reverse movement direction bchg #0,render_flags(a0) bchg #0,status(a0) move.w #$100,Obj4B_move_timer(a0) rts ; =========================================================================== ; Start of subroutine Obj4B_ChkPlayers ; sub_2D1D6: Obj4B_ChkPlayers: tst.b Obj4B_shooting_flag(a0) bne.w return_2D232 ; branch, if shooting is disabled move.w x_pos(a0),d0 lea (MainCharacter).w,a1 ; a1=character btst #0,(Vint_runcount+3).w beq.s + ; target Sidekick on uneven frames lea (Sidekick).w,a1 ; a1=character + sub.w x_pos(a1),d0 ; get object's distance to player move.w d0,d1 ; save value for later bpl.s + ; branch, if it was positive neg.w d0 ; get absolute value + ; test if player is inside an 8 pixel wide strip cmpi.w #$28,d0 blt.s return_2D232 cmpi.w #$30,d0 bgt.s return_2D232 tst.w d1 ; test sign of distance bpl.s Obj4B_PlayerIsLeft ; branch, if player is left from object btst #0,render_flags(a0) beq.s return_2D232 ; branch, if object is facing right bra.s Obj4B_ReadyToShoot ; --------------------------------------------------------------------------- ; loc_2D216: Obj4B_PlayerIsLeft: btst #0,render_flags(a0) bne.s return_2D232 ; branch, if object is facing left ; loc_2D21E: Obj4B_ReadyToShoot: st Obj4B_shooting_flag(a0) ; disable shooting addq.b #2,routine_secondary(a0) ; => Obj4B_Shooting move.b #3,anim(a0) ; play shooting animation move.w #$32,Obj4B_shot_timer(a0) return_2D232: rts ; End of subroutine Obj4B_ChkPlayers ; =========================================================================== ; loc_2D234: Obj4B_Shooting: move.w Obj4B_shot_timer(a0),d0 ; get timer value subq.w #1,d0 ; decrement blt.s Obj4B_DoneShooting ; branch, if timer has expired move.w d0,Obj4B_shot_timer(a0) ; update timer value cmpi.w #$14,d0 ; has timer reached a certain value? beq.s Obj4B_ShootProjectile ; if yes, branch rts ; --------------------------------------------------------------------------- ; loc_2D248: Obj4B_DoneShooting: subq.b #2,routine_secondary(a0) ; => Obj4B_Roaming rts ; --------------------------------------------------------------------------- ; loc_2D24E Obj4B_ShootProjectile: jsr (SingleObjLoad2).l ; Find next open object space bne.s + _move.b #ObjID_Buzzer,id(a1) ; load obj4B move.b #6,routine(a1) ; => Obj4B_Projectile move.l #Obj4B_MapUnc_2D2EA,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_Buzzer,0,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo7_Adjust2PArtPointer2 move.b #4,priority(a1) move.b #$98,collision_flags(a1) move.b #$10,width_pixels(a1) move.b status(a0),status(a1) move.b render_flags(a0),render_flags(a1) move.b #2,anim(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$18,y_pos(a1) ; align vertically with stinger move.w #$D,d0 ; absolute horizontal offset for stinger move.w #$180,y_vel(a1) move.w #-$180,x_vel(a1) btst #0,render_flags(a1) ; is object facing left? beq.s + ; if not, branch neg.w x_vel(a1) ; move in other direction neg.w d0 ; make offset negative + add.w d0,x_pos(a1) ; align horizontally with stinger rts ; =========================================================================== ; animation script ; off_2D2CE: Ani_obj4B: offsetTable offsetTableEntry.w byte_2D2D6 ; 0 offsetTableEntry.w byte_2D2D9 ; 1 offsetTableEntry.w byte_2D2DD ; 2 offsetTableEntry.w byte_2D2E1 ; 3 byte_2D2D6: dc.b $0F, $00, $FF rev02even byte_2D2D9: dc.b $02, $03, $04, $FF rev02even byte_2D2DD: dc.b $03, $05, $06, $FF rev02even byte_2D2E1: dc.b $09, $01, $01, $01, $01, $01, $FD, $00 even ; ---------------------------------------------------------------------------- ; sprite mappings -- Buzz Bomber Sprite Table ; ---------------------------------------------------------------------------- ; MapUnc_2D2EA: SprTbl_Buzzer: Obj4B_MapUnc_2D2EA: BINCLUDE "mappings/sprite/obj4B.bin" if ~~removeJmpTos align 4 endif ; =========================================================================== if ~~removeJmpTos ; loc_2D368: JmpTo49_DeleteObject jmp (DeleteObject).l JmpTo20_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo15_AnimateSprite jmp (AnimateSprite).l JmpTo7_Adjust2PArtPointer2 jmp (Adjust2PArtPointer2).l JmpTo_MarkObjGone_P1 jmp (MarkObjGone_P1).l JmpTo57_Adjust2PArtPointer jmp (Adjust2PArtPointer).l ; loc_2D38C: JmpTo21_ObjectMove jmp (ObjectMove).l align 4 else JmpTo49_DeleteObject jmp (DeleteObject).l ; loc_2D38C: JmpTo21_ObjectMove jmp (ObjectMove).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 5C - Masher (jumping piranha fish badnik) from EHZ ; ---------------------------------------------------------------------------- ; OST Variables: Obj5C_initial_y_pos = objoff_30 ; word ; Sprite_2D394: Obj5C: moveq #0,d0 move.b routine(a0),d0 move.w Obj5C_Index(pc,d0.w),d1 jsr Obj5C_Index(pc,d1.w) jmpto (MarkObjGone).l, JmpTo34_MarkObjGone ; =========================================================================== ; off_2D3A6: Obj5C_Index: offsetTable offsetTableEntry.w Obj5C_Init ; 0 offsetTableEntry.w Obj5C_Main ; 2 ; =========================================================================== ; loc_2D3AA: Obj5C_Init: addq.b #2,routine(a0) move.l #Obj5C_MapUnc_2D442,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Masher,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo58_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #4,priority(a0) move.b #9,collision_flags(a0) move.b #$10,width_pixels(a0) move.w #-$400,y_vel(a0) move.w y_pos(a0),Obj5C_initial_y_pos(a0) ; set initial (and lowest) y position ; loc_2D3E4: Obj5C_Main: lea (Ani_obj5C).l,a1 jsrto (AnimateSprite).l, JmpTo16_AnimateSprite jsrto (ObjectMove).l, JmpTo22_ObjectMove addi.w #$18,y_vel(a0) ; apply gravity move.w Obj5C_initial_y_pos(a0),d0 cmp.w y_pos(a0),d0 ; has object reached its initial y position? bhs.s + ; if not, branch move.w d0,y_pos(a0) move.w #-$500,y_vel(a0) ; jump + move.b #1,anim(a0) subi.w #$C0,d0 cmp.w y_pos(a0),d0 bhs.s + ; rts move.b #0,anim(a0) tst.w y_vel(a0) ; is object falling? bmi.s + ; rts ; if not, branch move.b #2,anim(a0) ; use closed mouth animation + rts ; =========================================================================== ; animation script ; off_2D430: Ani_obj5C: offsetTable offsetTableEntry.w byte_2D436 ; 0 offsetTableEntry.w byte_2D43A ; 1 offsetTableEntry.w byte_2D43E ; 2 byte_2D436: dc.b 7, 0, 1,$FF byte_2D43A: dc.b 3, 0, 1,$FF byte_2D43E: dc.b 7, 0,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj5C_MapUnc_2D442: BINCLUDE "mappings/sprite/obj5C.bin" if ~~removeJmpTos align 4 endif ; =========================================================================== if ~~removeJmpTos JmpTo34_MarkObjGone jmp (MarkObjGone).l JmpTo16_AnimateSprite jmp (AnimateSprite).l JmpTo58_Adjust2PArtPointer jmp (Adjust2PArtPointer).l ; loc_2D48E: JmpTo22_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 58 - Boss explosion ; ---------------------------------------------------------------------------- ; Sprite_2D494: Obj58: moveq #0,d0 move.b routine(a0),d0 move.w Obj58_Index(pc,d0.w),d1 jmp Obj58_Index(pc,d1.w) ; =========================================================================== ; off_2D4A2: Obj58_Index: offsetTable offsetTableEntry.w Obj58_Init ; 0 offsetTableEntry.w Obj58_Main ; 2 ; =========================================================================== ; loc_2D4A6: Obj58_Init: addq.b #2,routine(a0) move.l #Obj58_MapUnc_2D50A,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_FieryExplosion,0,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo59_Adjust2PArtPointer move.b #4,render_flags(a0) move.b #0,priority(a0) move.b #0,collision_flags(a0) move.b #$C,width_pixels(a0) move.b #7,anim_frame_duration(a0) move.b #0,mapping_frame(a0) move.w #SndID_BossExplosion,d0 jmp (PlaySound).l ; =========================================================================== rts ; =========================================================================== ; loc_2D4EC: Obj58_Main: subq.b #1,anim_frame_duration(a0) bpl.s + move.b #7,anim_frame_duration(a0) addq.b #1,mapping_frame(a0) cmpi.b #7,mapping_frame(a0) beq.w JmpTo50_DeleteObject + jmpto (DisplaySprite).l, JmpTo33_DisplaySprite if removeJmpTos JmpTo50_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj58_MapUnc_2D50A: BINCLUDE "mappings/sprite/obj58.bin" ; =========================================================================== ; Unused - a little dead code here (until the next label) ;Boss_HoverPos: move.b boss_sine_count(a0),d0 ; a0=object jsr (CalcSine).l asr.w #6,d0 add.w (Boss_Y_pos).w,d0 move.w d0,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) addq.b #2,boss_sine_count(a0) ;loc_2D57C Boss_HandleHits: cmpi.b #8,boss_routine(a0) ; is boss exploding or retreating? bhs.s return_2D5C2 ; if yes, branch tst.b boss_hitcount2(a0) ; has boss run out of hits? beq.s Boss_Defeat ; if yes, branch tst.b collision_flags(a0) ; are boss' collisions enabled? bne.s return_2D5C2 ; if yes, branch tst.b boss_invulnerable_time(a0) ; is boss invulnerable? bne.s + ; if yes, branch move.b #$20,boss_invulnerable_time(a0) ; make boss invulnerable move.w #SndID_BossHit,d0 ; play "boss hit" sound jsr (PlaySound).l + ; do palette flashing effect lea (Normal_palette_line2+2).w,a1 moveq #0,d0 ; 0000 = black tst.w (a1) ; is current color black? bne.s + ; if not, branch move.w #$EEE,d0 ; 0EEE = white + move.w d0,(a1) ; set color to white or black subq.b #1,boss_invulnerable_time(a0) ; decrease boss' invulnerable time bne.s return_2D5C2 ; branch, if it hasn't run out move.b #$F,collision_flags(a0) ; else, restore collisions return_2D5C2: rts ; =========================================================================== ; loc_2D5C4: Boss_Defeat: moveq #100,d0 jsrto (AddPoints).l, JmpTo_AddPoints move.w #$B3,(Boss_Countdown).w move.b #8,boss_routine(a0) moveq #PLCID_Capsule,d0 jsrto (LoadPLC).l, JmpTo4_LoadPLC rts ; =========================================================================== ;loc_2D5DE: Boss_MoveObject: move.l (Boss_X_pos).w,d2 move.l (Boss_Y_pos).w,d3 move.w (Boss_X_vel).w,d0 ext.l d0 asl.l #8,d0 add.l d0,d2 move.w (Boss_Y_vel).w,d0 ext.l d0 asl.l #8,d0 add.l d0,d3 move.l d2,(Boss_X_pos).w move.l d3,(Boss_Y_pos).w rts ; =========================================================================== ; a1 = animation script pointer ;AnimationArray: up to 8 2-byte entries: ; 4-bit: anim_ID (1) ; 4-bit: anim_ID (2) - the relevant one ; 4-bit: anim_frame ; 4-bit: anim_timer until next anim_frame ; if anim_ID (1) & (2) are not equal, new animation data is loaded ;loc_2D604: AnimateBoss: moveq #0,d6 movea.l a1,a4 ; address of animation script lea (Boss_AnimationArray).w,a2 lea mainspr_mapframe(a0),a3 ; mapframe 1 (main object) tst.b (a3) bne.s + addq.w #2,a2 bra.s ++ ; ---------------------------------------------------------------------------- + bsr.w AnimateBoss_Loop + moveq #0,d6 move.b mainspr_childsprites(a0),d6 ; number of child sprites subq.w #1,d6 ; = amount of iterations to run the code from AnimateBoss_Loop bmi.s return_2D690 ; if was 0, don't run lea sub2_mapframe(a0),a3 ; mapframe 2 ; ---------------------------------------------------------------------------- ;loc_2D62A: AnimateBoss_Loop: ; increases a2 (AnimationArray) by 2 each iteration movea.l a4,a1 moveq #0,d0 moveq #0,d1 moveq #0,d2 moveq #0,d4 move.b (a2)+,d0 move.b d0,d1 lsr.b #4,d1 ; anim_ID (1) andi.b #$F,d0 ; anim_ID (2) move.b d0,d2 cmp.b d0,d1 beq.s + st d4 ; anim_IDs not equal + move.b d0,d5 lsl.b #4,d5 or.b d0,d5 ; anim_ID (2) in both nybbles move.b (a2)+,d0 move.b d0,d1 lsr.b #4,d1 ; anim_frame tst.b d4 ; are the anim_IDs equal? beq.s + moveq #0,d0 moveq #0,d1 ; reset d0,d1 if anim_IDs not equal + andi.b #$F,d0 ; timer until next anim_frame subi_.b #1,d0 bpl.s loc_2D67C ; timer not yet at 0, and anim_IDs are equal add.w d2,d2 ; anim_ID (2) adda.w (a1,d2.w),a1 ; address of animation data with this ID move.b (a1),d0 ; animation speed move.b 1(a1,d1.w),d2 ; mapping_frame of first/next anim_frame bmi.s AnimateBoss_CmdParam ; if animation command parameter, branch loc_2D672: andi.b #$7F,d2 move.b d2,(a3) ; store mapping_frame to OST of object addi_.b #1,d1 ; anim_frame loc_2D67C: lsl.b #4,d1 or.b d1,d0 move.b d0,-1(a2) ; (2nd byte) anim_frame and anim_timer move.b d5,-2(a2) ; (1st byte) anim_ID (both nybbles) adda_.w #6,a3 ; mapping_frame of next subobject dbf d6,AnimateBoss_Loop return_2D690: rts ; ---------------------------------------------------------------------------- ;loc_2D692: AnimateBoss_CmdParam: ; parameter $FF - reset animation to first frame addq.b #1,d2 bne.s + move.b #0,d1 move.b 1(a1),d2 bra.s loc_2D672 ; ---------------------------------------------------------------------------- + ; parameter $FE - increase boss routine addq.b #1,d2 bne.s + addi_.b #2,angle(a0) ; boss routine rts ; ---------------------------------------------------------------------------- + ; parameter $FD - change anim_ID to byte after parameter addq.b #1,d2 bne.s + andi.b #$F0,d5 ; keep anim_ID (1) or.b 2(a1,d1.w),d5 ; set anim_ID (2) bra.s loc_2D67C ; ---------------------------------------------------------------------------- + ; parameter $FC - jump back to anim_frame d1 addq.b #1,d2 bne.s + ; rts moveq #0,d3 move.b 2(a1,d1.w),d1 ; anim_frame move.b 1(a1,d1.w),d2 ; mapping_frame bra.s loc_2D672 ; ---------------------------------------------------------------------------- + ; parameter $80-$FB rts ; =========================================================================== ;loc_2D6CC: Boss_LoadExplosion: move.b (Vint_runcount+3).w,d0 andi.b #7,d0 bne.s + ; rts jsr (SingleObjLoad).l bne.s + ; rts _move.b #ObjID_BossExplosion,id(a1) ; load obj58 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) jsr (RandomNumber).l move.w d0,d1 moveq #0,d1 move.b d0,d1 lsr.b #2,d1 subi.w #$20,d1 add.w d1,x_pos(a1) lsr.w #8,d0 lsr.b #2,d0 subi.w #$20,d0 add.w d0,y_pos(a1) + rts ; =========================================================================== if ~~removeJmpTos JmpTo33_DisplaySprite jmp (DisplaySprite).l JmpTo50_DeleteObject jmp (DeleteObject).l JmpTo4_LoadPLC jmp (LoadPLC).l JmpTo_AddPoints jmp (AddPoints).l JmpTo59_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 5D - CPZ boss ; ---------------------------------------------------------------------------- ; OST Variables: Obj5D_timer2 = objoff_2A Obj5D_pipe_segments = objoff_2C Obj5D_status = objoff_2D Obj5D_status2 = objoff_2E Obj5D_x_vel = objoff_2E ; and $2F Obj5D_x_pos_next = objoff_30 Obj5D_timer = objoff_30 Obj5D_y_offset = objoff_31 Obj5D_timer3 = objoff_32 Obj5D_parent = objoff_34 Obj5D_y_pos_next = objoff_38 Obj5D_defeat_timer = objoff_3C Obj5D_flag = objoff_3C Obj5D_timer4 = objoff_3C Obj5D_invulnerable_time = objoff_3E Obj5D_hover_counter = objoff_3F ; Sprite_2D734: Obj5D: moveq #0,d0 move.b routine(a0),d0 move.w Obj5D_Index(pc,d0.w),d1 jmp Obj5D_Index(pc,d1.w) ; =========================================================================== ; off_2D742: Obj5D_Index: offsetTable offsetTableEntry.w Obj5D_Init ; 0 offsetTableEntry.w Obj5D_Main ; 2 offsetTableEntry.w Obj5D_Pipe ; 4 offsetTableEntry.w Obj5D_Pipe_Pump ; 6 offsetTableEntry.w Obj5D_Pipe_Retract ; 8 offsetTableEntry.w Obj5D_Dripper ; $A offsetTableEntry.w Obj5D_Gunk ; $C offsetTableEntry.w Obj5D_PipeSegment ; $E offsetTableEntry.w Obj5D_Container ; $10 offsetTableEntry.w Obj5D_Pump ; $12 offsetTableEntry.w Obj5D_FallingParts ; $14 offsetTableEntry.w Obj5D_Robotnik ; $16 offsetTableEntry.w Obj5D_Flame ; $18 offsetTableEntry.w Obj5D_1A ; $1A ; =========================================================================== ; loc_2D75E: Obj5D_Init: ; main vehicle move.l #Obj5D_MapUnc_2ED8C,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Eggpod_3,1,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$20,width_pixels(a0) move.w #$2B80,x_pos(a0) move.w #$4B0,y_pos(a0) move.b #3,priority(a0) move.b #$F,collision_flags(a0) move.b #8,collision_property(a0) addq.b #2,routine(a0) ; => Obj5D_Main move.w x_pos(a0),Obj5D_x_pos_next(a0) move.w y_pos(a0),Obj5D_y_pos_next(a0) bclr #3,Obj5D_status(a0) jsrto (Adjust2PArtPointer).l, JmpTo60_Adjust2PArtPointer ; robotnik sitting in his eggmobile jsr (SingleObjLoad2).l bne.w loc_2D8AC _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.l a0,Obj5D_parent(a1) move.l a1,Obj5D_parent(a0) move.l #Obj5D_MapUnc_2ED8C,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_Eggpod_3,0,0),art_tile(a1) move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #3,priority(a1) move.l x_pos(a0),x_pos(a1) move.l y_pos(a0),y_pos(a1) move.b #$16,routine(a1) ; => Obj5D_Robotnik move.b #1,anim(a1) move.b render_flags(a0),render_flags(a1) jsrto (Adjust2PArtPointer2).l, JmpTo8_Adjust2PArtPointer2 tst.b subtype(a0) bmi.w loc_2D8AC ; eggmobile's exhaust flame jsr (SingleObjLoad2).l bne.w loc_2D8AC _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.l a0,Obj5D_parent(a1) move.l #Obj5D_MapUnc_2EE88,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_EggpodJets_1,0,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo8_Adjust2PArtPointer2 move.b #1,anim_frame_duration(a0) move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #3,priority(a1) move.l x_pos(a0),x_pos(a1) move.l y_pos(a0),y_pos(a1) move.b #$18,routine(a1) ; => Obj5D_Flame move.b render_flags(a0),render_flags(a1) ; large pump mechanism on top of eggmobile jsr (SingleObjLoad2).l bne.s loc_2D8AC _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.l a0,Obj5D_parent(a1) move.l #Obj5D_MapUnc_2EADC,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1) move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #2,priority(a1) move.l x_pos(a0),x_pos(a1) move.l y_pos(a0),y_pos(a1) move.b #$12,routine(a1) ; => Obj5D_Pump loc_2D8AC: ; glass container that dumps mega mack on player jsr (SingleObjLoad2).l bne.s loc_2D908 _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.l a0,Obj5D_parent(a1) move.l #Obj5D_MapUnc_2EADC,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1) move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #4,priority(a1) move.l x_pos(a0),x_pos(a1) move.l y_pos(a0),y_pos(a1) subi.w #$38,y_pos(a1) subi.w #$10,x_pos(a1) move.w #-$10,Obj5D_x_vel(a1) addi.b #$10,routine(a1) ; => Obj5D_Container move.b #6,anim(a1) loc_2D908: ; pipe used to suck mega mack from tube below jsr (SingleObjLoad2).l bne.s return_2D94C _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.l a0,Obj5D_parent(a1) move.l #Obj5D_MapUnc_2EADC,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1) move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #4,priority(a1) move.l x_pos(a0),x_pos(a1) move.l y_pos(a0),y_pos(a1) move.b #4,routine(a1) ; => Obj5D_Pipe return_2D94C: rts ; =========================================================================== Obj5D_Main: bsr.w Obj5D_LookAtChar moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj5D_Main_Index(pc,d0.w),d1 jsr Obj5D_Main_Index(pc,d1.w) lea (Ani_obj5D_b).l,a1 jsr (AnimateSprite).l move.b status(a0),d0 andi.b #3,d0 andi.b #$FC,render_flags(a0) or.b d0,render_flags(a0) jmp (DisplaySprite).l ; =========================================================================== Obj5D_Main_Index: offsetTable offsetTableEntry.w Obj5D_Main_0 ; 0 offsetTableEntry.w Obj5D_Main_2 ; 2 offsetTableEntry.w Obj5D_Main_4 ; 4 offsetTableEntry.w Obj5D_Main_6 ; 6 offsetTableEntry.w Obj5D_Main_8 ; 8 offsetTableEntry.w Obj5D_Main_A ; $A offsetTableEntry.w Obj5D_Main_C ; $C ; =========================================================================== ; Makes the boss look in Sonic's direction under certain circumstances. Obj5D_LookAtChar: cmpi.b #8,routine_secondary(a0) bge.s + move.w (MainCharacter+x_pos).w,d0 sub.w x_pos(a0),d0 bgt.s ++ bclr #0,status(a0) + rts ; --------------------------------------------------------------------------- + bset #0,status(a0) rts ; =========================================================================== Obj5D_Main_8: subq.w #1,Obj5D_defeat_timer(a0) bpl.w Obj5D_Main_Explode bset #0,status(a0) bclr #7,status(a0) clr.w x_vel(a0) addq.b #2,routine_secondary(a0) ; => Obj5D_Main_A move.w #-$26,Obj5D_defeat_timer(a0) rts ; =========================================================================== Obj5D_Main_A: addq.w #1,Obj5D_defeat_timer(a0) beq.s + bpl.s ++ addi.w #$18,y_vel(a0) bra.s Obj5D_Main_A_End ; --------------------------------------------------------------------------- + clr.w y_vel(a0) bra.s Obj5D_Main_A_End ; --------------------------------------------------------------------------- + cmpi.w #$30,Obj5D_defeat_timer(a0) blo.s + beq.s ++ cmpi.w #$38,Obj5D_defeat_timer(a0) blo.s Obj5D_Main_A_End addq.b #2,routine_secondary(a0) ; => Obj5D_Main_C bra.s Obj5D_Main_A_End ; --------------------------------------------------------------------------- + subi_.w #8,y_vel(a0) bra.s Obj5D_Main_A_End ; --------------------------------------------------------------------------- + clr.w y_vel(a0) jsrto (PlayLevelMusic).l, JmpTo_PlayLevelMusic jsrto (LoadPLC_AnimalExplosion).l, JmpTo_LoadPLC_AnimalExplosion Obj5D_Main_A_End: bsr.w Obj5D_Main_Move bra.w Obj5D_Main_Pos_and_Collision ; =========================================================================== Obj5D_Main_C: bset #6,Obj5D_status2(a0) move.w #$400,x_vel(a0) move.w #-$40,y_vel(a0) cmpi.w #$2C30,(Camera_Max_X_pos).w bhs.s + addq.w #2,(Camera_Max_X_pos).w bra.s Obj5D_Main_C_End ; =========================================================================== + tst.b render_flags(a0) bpl.s Obj5D_Main_Delete Obj5D_Main_C_End: bsr.w Obj5D_Main_Move bra.w Obj5D_Main_Pos_and_Collision ; =========================================================================== Obj5D_Main_Delete: addq.l #4,sp movea.l Obj5D_parent(a0),a1 ; a1=object jsr (DeleteObject2).l if removeJmpTos JmpTo51_DeleteObject endif jmp (DeleteObject).l ; =========================================================================== Obj5D_Main_0: move.w #$100,y_vel(a0) bsr.w Obj5D_Main_Move cmpi.w #$4C0,Obj5D_y_pos_next(a0) bne.s Obj5D_Main_Pos_and_Collision move.w #0,y_vel(a0) addq.b #2,routine_secondary(a0) ; => Obj5D_Main_2 Obj5D_Main_Pos_and_Collision: ; do hovering motion using sine wave move.b Obj5D_hover_counter(a0),d0 jsr (CalcSine).l asr.w #6,d0 add.w Obj5D_y_pos_next(a0),d0 ; get y position for next frame, add sine value move.w d0,y_pos(a0) ; set y and x positions move.w Obj5D_x_pos_next(a0),x_pos(a0) addq.b #2,Obj5D_hover_counter(a0) cmpi.b #8,routine_secondary(a0) ; exploding or retreating? bhs.s return_2DAE8 ; if yes, branch tst.b status(a0) bmi.s Obj5D_Defeated ; branch, if boss is defeated tst.b collision_flags(a0) bne.s return_2DAE8 ; branch, if collisions are not turned off ; if collisions are turned off, it means the boss was hit tst.b Obj5D_invulnerable_time(a0) bne.s + ; branch, if still invulnerable move.b #$20,Obj5D_invulnerable_time(a0) move.w #SndID_BossHit,d0 jsr (PlaySound).l + lea (Normal_palette_line2+2).w,a1 moveq #0,d0 ; color black tst.w (a1) ; test palette entry bne.s + ; branch, if it's not black move.w #$EEE,d0 ; color white + move.w d0,(a1) ; set color for flashing effect subq.b #1,Obj5D_invulnerable_time(a0) bne.s return_2DAE8 move.b #$F,collision_flags(a0) ; restore collisions bclr #1,Obj5D_status(a0) return_2DAE8: rts ; =========================================================================== ; called when status bit 7 is set (check Touch_Enemy_Part2) Obj5D_Defeated: moveq #100,d0 jsrto (AddPoints).l, JmpTo2_AddPoints move.b #8,routine_secondary(a0) ; => Obj5D_Main_8 move.w #$B3,Obj5D_defeat_timer(a0) movea.l Obj5D_parent(a0),a1 ; a1=object move.b #4,anim(a1) moveq #PLCID_Capsule,d0 jmpto (LoadPLC).l, JmpTo5_LoadPLC ; =========================================================================== rts ; =========================================================================== Obj5D_Main_Move: move.l Obj5D_x_pos_next(a0),d2 move.l Obj5D_y_pos_next(a0),d3 move.w x_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d2 move.w y_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d3 move.l d2,Obj5D_x_pos_next(a0) move.l d3,Obj5D_y_pos_next(a0) rts ; =========================================================================== ; Creates an explosion every 8 frames at a random position relative to boss. Obj5D_Main_Explode: move.b (Vint_runcount+3).w,d0 andi.b #7,d0 bne.s + ; rts jsr (SingleObjLoad).l bne.s + ; rts _move.b #ObjID_BossExplosion,id(a1) ; load obj58 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) jsr (RandomNumber).l move.w d0,d1 moveq #0,d1 move.b d0,d1 lsr.b #2,d1 subi.w #$20,d1 add.w d1,x_pos(a1) lsr.w #8,d0 lsr.b #2,d0 subi.w #$20,d0 add.w d0,y_pos(a1) + rts ; =========================================================================== ; Creates an explosion. Obj5D_Main_Explode2: jsr (SingleObjLoad).l bne.s + ; rts _move.b #ObjID_BossExplosion,id(a1) ; load obj58 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) + rts ; =========================================================================== Obj5D_Main_2: btst #3,Obj5D_status(a0) ; is boss on the left side of the arena? bne.s + ; if yes, branch move.w #$2B30,d0 ; right side of arena bra.s ++ ; --------------------------------------------------------------------------- + move.w #$2A50,d0 ; left side of arena + move.w d0,d1 sub.w Obj5D_x_pos_next(a0),d0 bpl.s + neg.w d0 ; get absolute value + cmpi.w #3,d0 ble.s Obj5D_Main_2_Stop ; branch, if boss is within 3 pixels to his target cmp.w Obj5D_x_pos_next(a0),d1 bgt.s Obj5D_Main_2_MoveRight ;Obj5D_Main_2_MoveLeft: move.w #-$300,x_vel(a0) bra.s Obj5D_Main_2_End ; --------------------------------------------------------------------------- Obj5D_Main_2_MoveRight: move.w #$300,x_vel(a0) Obj5D_Main_2_End: bsr.w Obj5D_Main_Move bra.w Obj5D_Main_Pos_and_Collision ; =========================================================================== Obj5D_Main_2_Stop: cmpi.w #$4C0,Obj5D_y_pos_next(a0) bne.w Obj5D_Main_Pos_and_Collision move.w #0,x_vel(a0) move.w #0,y_vel(a0) addq.b #2,routine_secondary(a0) ; => Obj5D_Main_4 bchg #3,Obj5D_status(a0) ; indicate boss is now at the other side bset #0,Obj5D_status2(a0) ; action 0 bra.w Obj5D_Main_Pos_and_Collision ; =========================================================================== ; when status2 bit 0 set, wait for something Obj5D_Main_4: btst #0,Obj5D_status2(a0) ; action 0? beq.s + ; if not, branch bra.w Obj5D_Main_Pos_and_Collision ; --------------------------------------------------------------------------- + addq.b #2,routine_secondary(a0) ; => Obj5D_Main_6 bra.w Obj5D_Main_Pos_and_Collision ; =========================================================================== Obj5D_Main_6: move.w (MainCharacter+x_pos).w,d0 addi.w #$4C,d0 cmp.w Obj5D_x_pos_next(a0),d0 bgt.s Obj5D_Main_6_MoveRight beq.w Obj5D_Main_Pos_and_Collision ;Obj5D_Main_6_MoveLeft: subi.l #$10000,Obj5D_x_pos_next(a0) ; move left one pixel ; stop at left boundary cmpi.w #$2A28,Obj5D_x_pos_next(a0) bgt.w Obj5D_Main_Pos_and_Collision move.w #$2A28,Obj5D_x_pos_next(a0) bra.w Obj5D_Main_Pos_and_Collision ; --------------------------------------------------------------------------- Obj5D_Main_6_MoveRight: addi.l #$10000,Obj5D_x_pos_next(a0) ; move right one pixel ; stop at right boundary cmpi.w #$2B70,Obj5D_x_pos_next(a0) blt.w Obj5D_Main_Pos_and_Collision move.w #$2B70,Obj5D_x_pos_next(a0) bra.w Obj5D_Main_Pos_and_Collision ; =========================================================================== Obj5D_FallingParts: cmpi.b #-7,Obj5D_timer(a0) beq.s + subi_.b #1,Obj5D_timer(a0) bgt.w JmpTo34_DisplaySprite bsr.w Obj5D_Main_Explode2 move.b #-7,Obj5D_timer(a0) move.w #$1E,Obj5D_timer2(a0) + subq.w #1,Obj5D_timer2(a0) bpl.w JmpTo34_DisplaySprite move.w x_vel(a0),d0 add.w d0,x_pos(a0) move.l y_pos(a0),d3 move.w y_vel(a0),d0 addi.w #$38,y_vel(a0) ext.l d0 asl.l #8,d0 add.l d0,d3 move.l d3,y_pos(a0) cmpi.l #$5800000,d3 bhs.w JmpTo51_DeleteObject jmpto (MarkObjGone).l, JmpTo35_MarkObjGone ; =========================================================================== Obj5D_Pump: btst #7,status(a0) bne.s + movea.l Obj5D_parent(a0),a1 ; a1=object move.l x_pos(a1),x_pos(a0) move.l y_pos(a1),y_pos(a0) move.b render_flags(a1),render_flags(a0) move.b status(a1),status(a0) movea.l #Ani_Obj5D_Dripper,a1 jsr (AnimateSprite).l jmp (DisplaySprite).l ; --------------------------------------------------------------------------- + moveq #$22,d3 move.b #$78,Obj5D_timer(a0) movea.l Obj5D_parent(a0),a1 ; a1=object move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) move.b d3,mapping_frame(a0) move.b #$14,routine(a0) ; => Obj5D_FallingParts jsr (RandomNumber).l asr.w #8,d0 asr.w #6,d0 move.w d0,x_vel(a0) move.w #-$380,y_vel(a0) moveq #1,d2 addq.w #1,d3 - jsr (SingleObjLoad).l bne.w JmpTo51_DeleteObject _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.l #Obj5D_MapUnc_2EADC,mappings(a1) move.b d3,mapping_frame(a1) move.b #$14,routine(a1) ; => Obj5D_FallingParts move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1) move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #2,priority(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b status(a0),status(a1) move.b render_flags(a0),render_flags(a1) jsr (RandomNumber).l asr.w #8,d0 asr.w #6,d0 move.w d0,x_vel(a1) move.w #-$380,y_vel(a1) swap d0 addi.b #$1E,d0 andi.w #$7F,d0 move.b d0,Obj5D_timer(a1) addq.w #1,d3 dbf d2,- rts ; =========================================================================== ; Object to control the pipe's actions before pumping starts. Obj5D_Pipe: moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj5D_Pipe_Index(pc,d0.w),d1 jmp Obj5D_Pipe_Index(pc,d1.w) ; =========================================================================== Obj5D_Pipe_Index: offsetTable offsetTableEntry.w Obj5D_Pipe_0 ; 0 offsetTableEntry.w Obj5D_Pipe_2_Load ; 2 ; =========================================================================== ; wait for main vehicle's action 0 Obj5D_Pipe_0: movea.l Obj5D_parent(a0),a1 ; parent = main vehicle ; a1=object btst #0,Obj5D_status2(a1) ; parent's action 0? bne.s + ; if yes, branch ; else, do nothing rts ; --------------------------------------------------------------------------- + move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) addi.w #$18,y_pos(a0) move.w #$C,Obj5D_pipe_segments(a0) addq.b #2,routine_secondary(a0) ; => Obj5D_Pipe_2_Load movea.l a0,a1 bra.s Obj5D_Pipe_2_Load_Part2 ; skip initial loading setup ; =========================================================================== ; load pipe segments, first object controls rest of pipe ; objects not loaded in a loop => one segment loaded per frame ; pipe extends gradually Obj5D_Pipe_2_Load: jsr (SingleObjLoad2).l beq.s + rts ; --------------------------------------------------------------------------- + move.l a0,Obj5D_parent(a1) Obj5D_Pipe_2_Load_Part2: subq.w #1,Obj5D_pipe_segments(a0) ; is pipe fully extended? blt.s Obj5D_Pipe_2_Load_End ; if yes, branch _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.l #Obj5D_MapUnc_2EADC,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1) move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #5,priority(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) ; calculate y position for current pipe segment move.w Obj5D_pipe_segments(a0),d0 subi.w #$B,d0 ; $B = maximum number of pipe segments -1, result is always negative or zero neg.w d0 ; positive value needed lsl.w #3,d0 ; multiply with 8 move.w d0,Obj5D_y_pos_next(a1) add.w d0,y_pos(a1) move.b #1,anim(a1) cmpi.b #2,routine_secondary(a1) beq.w Obj5D_PipeSegment ; only true for the first object move.b #$E,routine(a1) ; => Obj5D_PipeSegment bra.w Obj5D_PipeSegment ; =========================================================================== ; once all pipe segments have been loaded, switch to pumping routine Obj5D_Pipe_2_Load_End: move.b #0,routine_secondary(a0) move.b #6,routine(a0) ; => Obj5D_Pipe_Pump_0 bra.w Obj5D_PipeSegment ; =========================================================================== ; Object to control the pipe's actions while pumping. Obj5D_Pipe_Pump: moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj5D_Pipe_Pump_Index(pc,d0.w),d1 jmp Obj5D_Pipe_Pump_Index(pc,d1.w) ; =========================================================================== Obj5D_Pipe_Pump_Index: offsetTable offsetTableEntry.w Obj5D_Pipe_Pump_0 ; 0 offsetTableEntry.w Obj5D_Pipe_Pump_2 ; 2 offsetTableEntry.w Obj5D_Pipe_Pump_4 ; 4 ; =========================================================================== ; prepares for pumping animation Obj5D_Pipe_Pump_0: jsr (SingleObjLoad2).l bne.w Obj5D_PipeSegment move.b #$E,routine(a0) ; => Obj5D_PipeSegment ; temporarily turn control object into a pipe segment move.b #6,routine(a1) move.b #2,routine_secondary(a1) ; => Obj5D_Pipe_Pump_2 _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.l #Obj5D_MapUnc_2EADC,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1) move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #4,priority(a1) move.b #2,Obj5D_timer3(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) ; starting position for pumping animation move.w #$B*8,d0 move.b d0,Obj5D_y_offset(a1) add.w d0,y_pos(a1) move.b #2,anim(a1) move.l a0,Obj5D_parent(a1) ; address of control object move.b #$12,Obj5D_timer(a1) jsr (SingleObjLoad2).l bne.s BranchTo_Obj5D_PipeSegment _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.b #$A,routine(a1) ; => Obj5D_Dripper move.l Obj5D_parent(a0),Obj5D_parent(a1) BranchTo_Obj5D_PipeSegment bra.w Obj5D_PipeSegment ; =========================================================================== ; do pumping animation Obj5D_Pipe_Pump_2: movea.l Obj5D_parent(a0),a1 ; parent = pipe segment (control object) ; a1=object movea.l Obj5D_parent(a1),a2 ; parent = main vehicle ; a2=object btst #7,status(a2) ; has boss been defeated? bne.w JmpTo51_DeleteObject ; if yes, branch move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) subi_.b #1,Obj5D_timer(a0) ; animation timer bne.s Obj5D_Pipe_Pump_2_End ; when timer reaches zero move.b #$12,Obj5D_timer(a0) ; reset animation timer subi_.b #8,Obj5D_y_offset(a0) ; move one segment up bgt.s Obj5D_Pipe_Pump_2_End bmi.s + ; pumping sequence is over when y offset becomes negative ; one final delay when last segment is reached move.b #3,anim(a0) move.b #$C,Obj5D_timer(a0) bra.s Obj5D_Pipe_Pump_2_End ; --------------------------------------------------------------------------- + ; when pumping sequence is over move.b #6,Obj5D_timer(a0) move.b #4,routine_secondary(a0) ; => Obj5D_Pipe_Pump_4 rts ; --------------------------------------------------------------------------- Obj5D_Pipe_Pump_2_End: ; set y position based on y offset moveq #0,d0 move.b Obj5D_y_offset(a0),d0 add.w d0,y_pos(a0) lea (Ani_Obj5D_Dripper).l,a1 jsr (AnimateSprite).l jmp (DisplaySprite).l ; =========================================================================== Obj5D_Pipe_Pump_4: subi_.b #1,Obj5D_timer(a0) ; wait a few frames beq.s + rts ; --------------------------------------------------------------------------- + subq.b #1,Obj5D_timer3(a0) beq.s + move.b #2,anim(a0) move.b #$12,Obj5D_timer(a0) move.b #2,routine_secondary(a0) ; => Obj5D_Pipe_Pump_2 move.b #$B*8,Obj5D_y_offset(a0) + ; set control object's routine movea.l Obj5D_parent(a0),a1 ; parent = pipe segment (control object) ; a1=object move.b #8,routine(a1) ; => Obj5D_Pipe_Retract move.b #$B*8,Obj5D_y_offset(a1) bra.w JmpTo51_DeleteObject ; =========================================================================== ; Object to control the pipe's actions after pumping is finished. Obj5D_Pipe_Retract: tst.b Obj5D_flag(a0) ; is flag set? bne.s loc_2DFEE ; if yes, branch moveq #0,d0 move.b Obj5D_y_offset(a0),d0 add.w y_pos(a0),d0 ; get y pos of current pipe segment lea (MainCharacter).w,a1 ; a1=object moveq #(Dynamic_Object_RAM_End-Object_RAM)/object_size-1,d1 Obj5D_Pipe_Retract_Loop: cmp.w y_pos(a1),d0 ; compare object's y position with current y offset beq.s Obj5D_Pipe_Retract_ChkID ; if they match, branch lea next_object(a1),a1 ; a1=object dbf d1,Obj5D_Pipe_Retract_Loop ; continue as long as there are object slots left bra.s Obj5D_PipeSegment ; =========================================================================== loc_2DFD8: st Obj5D_flag(a0) bra.s Obj5D_PipeSegment ; =========================================================================== Obj5D_Pipe_Retract_ChkID: moveq #0,d7 move.b #ObjID_CPZBoss,d7 cmp.b id(a1),d7 ; is object a subtype of the CPZ Boss? beq.s loc_2DFF0 ; if yes, branch dbf d1,Obj5D_Pipe_Retract_Loop bra.s Obj5D_PipeSegment ; =========================================================================== loc_2DFEE: movea.l a0,a1 loc_2DFF0: bset #7,status(a1) ; mark segment for deletion subi_.b #8,Obj5D_y_offset(a0) ; position of next segment up beq.s loc_2DFD8 Obj5D_PipeSegment: movea.l Obj5D_parent(a0),a1 ; a1=object movea.l Obj5D_parent(a1),a2 ; a2=object btst #7,status(a2) ; has boss been defeated? bne.s Obj5D_PipeSegment_End ; if yes, branch move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) cmpi.b #4,routine_secondary(a0) bne.s + addi.w #$18,y_pos(a0) + btst #7,status(a0) ; is object marked for deletion? bne.s BranchTo_JmpTo51_DeleteObject ; if yes, branch move.w Obj5D_y_pos_next(a0),d0 add.w d0,y_pos(a0) lea (Ani_Obj5D_Dripper).l,a1 jsr (AnimateSprite).l jmp (DisplaySprite).l ; =========================================================================== BranchTo_JmpTo51_DeleteObject bra.w JmpTo51_DeleteObject ; =========================================================================== Obj5D_PipeSegment_End: move.b #$14,routine(a0) jsr (RandomNumber).l asr.w #8,d0 asr.w #6,d0 move.w d0,x_vel(a0) move.w #-$380,y_vel(a0) swap d0 addi.b #$1E,d0 andi.w #$7F,d0 move.b d0,Obj5D_timer(a0) jmpto (DisplaySprite).l, JmpTo34_DisplaySprite ; =========================================================================== Obj5D_Dripper: btst #7,status(a0) bne.w JmpTo51_DeleteObject moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj5D_Dripper_States(pc,d0.w),d1 jmp Obj5D_Dripper_States(pc,d1.w) ; =========================================================================== Obj5D_Dripper_States: offsetTable offsetTableEntry.w Obj5D_Dripper_0 ; 0 offsetTableEntry.w Obj5D_Dripper_2 ; 2 offsetTableEntry.w Obj5D_Dripper_4 ; 4 ; =========================================================================== Obj5D_Dripper_0: addq.b #2,routine_secondary(a0) ; => Obj5D_Dripper_2 _move.b #ObjID_CPZBoss,id(a0) ; load 0bj5D move.l #Obj5D_MapUnc_2EADC,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,3,0),art_tile(a0) move.b #4,render_flags(a0) move.b #$20,width_pixels(a0) move.b #4,priority(a0) movea.l Obj5D_parent(a0),a1 ; a1=object move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) move.b #$F,Obj5D_timer(a0) move.b #4,anim(a0) Obj5D_Dripper_2: subq.b #1,Obj5D_timer(a0) bne.s + move.b #5,anim(a0) move.b #4,Obj5D_timer(a0) addq.b #2,routine_secondary(a0) subi.w #$24,y_pos(a0) subi_.w #2,x_pos(a0) rts ; --------------------------------------------------------------------------- + movea.l Obj5D_parent(a0),a1 ; a1=object move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) move.b status(a1),status(a0) move.b render_flags(a1),render_flags(a0) lea (Ani_Obj5D_Dripper).l,a1 jsr (AnimateSprite).l jmp (DisplaySprite).l ; =========================================================================== Obj5D_Dripper_4: subq.b #1,Obj5D_timer(a0) bne.s + move.b #0,routine_secondary(a0) movea.l Obj5D_parent(a0),a1 ; a1=object bset #1,Obj5D_status2(a1) addq.b #1,Obj5D_timer4(a0) cmpi.b #$C,Obj5D_timer4(a0) bge.w JmpTo51_DeleteObject rts ; --------------------------------------------------------------------------- + movea.l Obj5D_parent(a0),a1 ; a1=object move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) subi.w #$24,y_pos(a0) subi_.w #2,x_pos(a0) btst #0,render_flags(a0) beq.s + addi_.w #4,x_pos(a0) + lea (Ani_Obj5D_Dripper).l,a1 jsr (AnimateSprite).l jmp (DisplaySprite).l ; =========================================================================== Obj5D_Container: moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj5D_Container_States(pc,d0.w),d1 jmp Obj5D_Container_States(pc,d1.w) ; =========================================================================== Obj5D_Container_States: offsetTable offsetTableEntry.w Obj5D_Container_Init ; 0 offsetTableEntry.w Obj5D_Container_Main ; 2 offsetTableEntry.w Obj5D_Container_Floor ; 4 offsetTableEntry.w Obj5D_Container_Extend ; 6 offsetTableEntry.w Obj5D_Container_Floor2 ; 8 offsetTableEntry.w Obj5D_Container_FallOff ; A ; =========================================================================== Obj5D_Container_Init: movea.l Obj5D_parent(a0),a1 ; a1=object btst #7,Obj5D_status2(a1) bne.s + bset #7,Obj5D_status2(a1) jsr (SingleObjLoad2).l bne.s + _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.l a0,Obj5D_parent(a1) move.l #Obj5D_MapUnc_2EADC,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1) move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #4,priority(a1) move.l x_pos(a0),x_pos(a1) move.l y_pos(a0),y_pos(a1) move.b #$10,routine(a1) move.b #4,routine_secondary(a1) ; => Obj5D_Container_Floor move.b #9,anim(a1) + jsr (SingleObjLoad2).l bne.s + _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.l a0,Obj5D_parent(a1) move.l #Obj5D_MapUnc_2EADC,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,3,0),art_tile(a1) move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #4,priority(a1) move.l x_pos(a0),x_pos(a1) move.l y_pos(a0),y_pos(a1) addi.b #$10,routine(a1) move.b #6,routine_secondary(a1) ; => Obj5D_Container_Extend + addq.b #2,routine_secondary(a0) ; => Obj5D_Container_Main Obj5D_Container_Main: movea.l Obj5D_parent(a0),a1 ; a1=object move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) subi.w #$38,y_pos(a0) btst #7,status(a0) bne.s loc_2E2E0 btst #2,Obj5D_status2(a1) beq.s + bsr.w loc_2E4CE bsr.w loc_2E3F2 bra.s loc_2E2AC ; --------------------------------------------------------------------------- + btst #5,Obj5D_status2(a1) beq.s loc_2E2AC subq.w #1,Obj5D_timer2(a0) bne.s loc_2E2AC bclr #5,Obj5D_status2(a1) bset #3,Obj5D_status2(a1) bset #4,Obj5D_status2(a1) loc_2E2AC: movea.l Obj5D_parent(a0),a1 ; a1=object move.b status(a1),status(a0) move.b render_flags(a1),render_flags(a0) move.w Obj5D_x_vel(a0),d0 btst #0,render_flags(a0) beq.s + neg.w d0 + add.w d0,x_pos(a0) lea (Ani_Obj5D_Dripper).l,a1 jsr (AnimateSprite).l jmp (DisplaySprite).l ; =========================================================================== loc_2E2E0: move.b #$A,routine_secondary(a0) bra.s loc_2E2AC ; =========================================================================== Obj5D_Container_FallOff: move.l d7,-(sp) move.b #$1E,Obj5D_timer(a0) movea.l Obj5D_parent(a0),a1 ; a1=object move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) subi.w #$38,y_pos(a0) move.w Obj5D_x_vel(a0),d0 btst #0,render_flags(a0) beq.s + neg.w d0 + add.w d0,x_pos(a0) move.b #$20,mapping_frame(a0) move.b #$14,routine(a0) jsr (RandomNumber).l asr.w #8,d0 asr.w #6,d0 move.w d0,x_vel(a0) move.w #-$380,y_vel(a0) moveq #0,d7 move.w Obj5D_x_vel(a0),d0 addi.w #$18,d0 bge.s loc_2E356 addi.w #$18,d0 bge.s loc_2E354 addi.w #$18,d0 bge.s loc_2E352 addq.w #1,d7 loc_2E352: addq.w #1,d7 loc_2E354: addq.w #1,d7 loc_2E356: subq.w #1,d7 bmi.w loc_2E3E6 loc_2E35C: jsr (SingleObjLoad).l bne.w JmpTo51_DeleteObject _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.l #Obj5D_MapUnc_2EADC,mappings(a1) move.b #$21,mapping_frame(a1) move.b #$14,routine(a1) move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1) move.b render_flags(a0),render_flags(a1) move.b #$20,width_pixels(a1) move.b #2,priority(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi_.w #8,y_pos(a1) move.w d7,d2 add.w d2,d2 move.w word_2E3EC(pc,d2.w),d3 btst #0,render_flags(a0) beq.s + neg.w d3 + add.w d3,x_pos(a1) jsr (RandomNumber).l asr.w #8,d0 asr.w #6,d0 move.w d0,x_vel(a1) move.w #-$380,y_vel(a1) swap d0 addi.b #$1E,d0 andi.w #$7F,d0 move.b d0,Obj5D_timer(a1) dbf d7,loc_2E35C loc_2E3E6: move.l (sp)+,d7 if removeJmpTos JmpTo34_DisplaySprite endif jmpto (DisplaySprite).l, JmpTo34_DisplaySprite ; =========================================================================== word_2E3EC: dc.w $18 dc.w $30 ; 1 dc.w $48 ; 2 ; =========================================================================== loc_2E3F2: btst #3,Obj5D_status2(a1) bne.w return_2E4CC btst #4,Obj5D_status2(a1) bne.w return_2E4CC cmpi.w #-$14,Obj5D_x_vel(a0) blt.s + btst #1,Obj5D_status(a1) beq.w return_2E4CC bclr #1,Obj5D_status(a1) bset #2,Obj5D_status(a1) bra.s loc_2E464 ; --------------------------------------------------------------------------- + cmpi.w #-$40,Obj5D_x_vel(a0) bge.w return_2E4CC move.w (MainCharacter+x_pos).w,d1 subi_.w #8,d1 btst #0,render_flags(a0) beq.s + add.w Obj5D_x_vel(a0),d1 sub.w x_pos(a0),d1 bgt.w return_2E4CC cmpi.w #-$18,d1 bge.s loc_2E464 rts ; --------------------------------------------------------------------------- + sub.w Obj5D_x_vel(a0),d1 sub.w x_pos(a0),d1 blt.s return_2E4CC cmpi.w #$18,d1 bgt.s return_2E4CC loc_2E464: bset #5,Obj5D_status2(a1) bclr #2,Obj5D_status2(a1) move.w #$12,Obj5D_timer2(a0) jsr (SingleObjLoad2).l bne.s return_2E4CC _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.l a0,Obj5D_parent(a1) move.b #$10,routine(a1) move.b #8,routine_secondary(a1) move.l #Obj5D_MapUnc_2EADC,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1) move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #5,priority(a1) move.l x_pos(a0),x_pos(a1) move.l y_pos(a0),y_pos(a1) move.b #$B,anim(a1) move.w #$24,Obj5D_timer2(a1) return_2E4CC: rts ; =========================================================================== loc_2E4CE: moveq #1,d0 btst #4,Obj5D_status2(a1) bne.s + moveq #-1,d0 + cmpi.w #-$10,Obj5D_x_vel(a0) bne.s loc_2E552 bclr #4,Obj5D_status2(a1) beq.s loc_2E552 bclr #2,Obj5D_status2(a1) clr.b routine_secondary(a0) movea.l a1,a2 jsr (SingleObjLoad2).l bne.s return_2E550 _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.l Obj5D_parent(a0),Obj5D_parent(a1) move.l #Obj5D_MapUnc_2EADC,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1) move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #4,priority(a1) move.l x_pos(a0),x_pos(a1) move.l y_pos(a0),y_pos(a1) move.b #4,routine(a1) move.b #0,routine_secondary(a0) bra.s return_2E550 ; =========================================================================== move.b #$A,routine(a1) move.l Obj5D_parent(a0),Obj5D_parent(a1) return_2E550: rts ; =========================================================================== loc_2E552: move.w Obj5D_x_vel(a0),d1 cmpi.w #-$28,d1 bge.s loc_2E59C cmpi.w #-$40,d1 bge.s loc_2E594 move.b #8,anim(a0) cmpi.w #-$58,d1 blt.s loc_2E57E bgt.s loc_2E578 btst #4,Obj5D_status2(a1) beq.s return_2E57C loc_2E578: add.w d0,Obj5D_x_vel(a0) return_2E57C: rts ; =========================================================================== loc_2E57E: move.w #-$58,Obj5D_x_vel(a0) btst #0,render_flags(a0) beq.s loc_2E578 move.w #$58,Obj5D_x_vel(a0) bra.s loc_2E578 ; =========================================================================== loc_2E594: move.b #7,anim(a0) bra.s loc_2E578 ; =========================================================================== loc_2E59C: move.b #6,anim(a0) bra.s loc_2E578 ; =========================================================================== Obj5D_Container_Extend: btst #7,status(a0) bne.w JmpTo51_DeleteObject movea.l Obj5D_parent(a0),a1 ; a1=object move.l Obj5D_parent(a1),d0 beq.w JmpTo51_DeleteObject movea.l d0,a1 ; a1=object bclr #3,Obj5D_status2(a1) beq.s + move.b #$C,routine(a0) move.b #0,routine_secondary(a0) move.b #$87,collision_flags(a0) bra.s Obj5D_Container_Floor_End ; ---------------------------------------------------------------------------- + bclr #1,Obj5D_status2(a1) bne.s + tst.b anim(a0) bne.s Obj5D_Container_Floor_End rts ; --------------------------------------------------------------------------- + tst.b anim(a0) bne.s + move.b #$B,anim(a0) + addi_.b #1,anim(a0) cmpi.b #$17,anim(a0) blt.s Obj5D_Container_Floor_End bclr #0,Obj5D_status2(a1) bset #2,Obj5D_status2(a1) bra.s Obj5D_Container_Floor_End ; =========================================================================== Obj5D_Container_Floor: btst #7,status(a0) bne.w JmpTo51_DeleteObject movea.l Obj5D_parent(a0),a1 ; a1=object movea.l Obj5D_parent(a1),a1 btst #5,Obj5D_status2(a1) beq.s Obj5D_Container_Floor_End cmpi.b #9,anim(a0) bne.s Obj5D_Container_Floor_End move.b #$A,anim(a0) Obj5D_Container_Floor_End: movea.l Obj5D_parent(a0),a1 ; a1=object move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) move.b render_flags(a1),render_flags(a0) move.b status(a1),status(a0) lea (Ani_Obj5D_Dripper).l,a1 jsr (AnimateSprite).l jmp (DisplaySprite).l ; =========================================================================== Obj5D_Container_Floor2: btst #7,status(a0) bne.w JmpTo51_DeleteObject subq.w #1,Obj5D_timer2(a0) beq.w JmpTo51_DeleteObject bra.s Obj5D_Container_Floor_End ; =========================================================================== Obj5D_Gunk: moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj5D_Gunk_States(pc,d0.w),d1 jmp Obj5D_Gunk_States(pc,d1.w) ; =========================================================================== Obj5D_Gunk_States: offsetTable offsetTableEntry.w Obj5D_Gunk_Init ; 0 offsetTableEntry.w Obj5D_Gunk_Main ; 2 offsetTableEntry.w Obj5D_Gunk_Droplets ; 4 offsetTableEntry.w Obj5D_Gunk_6 ; 6 offsetTableEntry.w Obj5D_Gunk_8 ; 8 ; =========================================================================== Obj5D_Gunk_Init: addq.b #2,routine_secondary(a0) ; => Obj5D_Gunk_Main move.b #$20,y_radius(a0) move.b #$19,anim(a0) move.w #0,y_vel(a0) movea.l Obj5D_parent(a0),a1 ; a1=object movea.l Obj5D_parent(a1),a1 btst #2,Obj5D_status(a1) beq.s Obj5D_Gunk_Main bclr #2,Obj5D_status(a1) move.b #6,routine_secondary(a0) ; => Obj5D_Gunk_6 move.w #9,Obj5D_timer2(a0) Obj5D_Gunk_Main: jsrto (ObjectMoveAndFall).l, JmpTo3_ObjectMoveAndFall jsr (ObjCheckFloorDist).l tst.w d1 bmi.s + ; branch, if hit the floor cmpi.w #$518,y_pos(a0) bge.s Obj5D_Gunk_OffScreen ; branch, if fallen off screen lea (Ani_Obj5D_Dripper).l,a1 jsr (AnimateSprite).l jmp (DisplaySprite).l ; =========================================================================== + add.w d1,y_pos(a0) movea.l Obj5D_parent(a0),a1 ; a1=object movea.l Obj5D_parent(a1),a1 bset #2,Obj5D_status2(a1) bset #4,Obj5D_status2(a1) move.b #2,routine_secondary(a1) addq.b #2,routine_secondary(a0) ; => Obj5D_Gunk_Droplets move.b #0,subtype(a0) move.w #SndID_MegaMackDrop,d0 jsrto (PlaySound).l, JmpTo5_PlaySound jmp (DisplaySprite).l ; =========================================================================== Obj5D_Gunk_OffScreen: movea.l Obj5D_parent(a0),a1 ; a1=object movea.l Obj5D_parent(a1),a1 bset #2,Obj5D_status2(a1) bset #4,Obj5D_status2(a1) move.b #2,routine_secondary(a1) bra.w JmpTo51_DeleteObject ; =========================================================================== Obj5D_Gunk_6: subi_.w #1,Obj5D_timer2(a0) bpl.s + move.b #2,priority(a0) move.b #$25,mapping_frame(a0) movea.l Obj5D_parent(a0),a1 ; a1=object movea.l Obj5D_parent(a1),a1 ; a1=object move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) addq.b #2,routine_secondary(a0) ; => Obj5D_Gunk_8 move.b #8,anim_frame_duration(a0) bra.s Obj5D_Gunk_8 ; =========================================================================== + jsrto (ObjectMove).l, JmpTo23_ObjectMove lea (Ani_Obj5D_Dripper).l,a1 jsr (AnimateSprite).l jmp (DisplaySprite).l ; =========================================================================== Obj5D_Gunk_8: subi_.b #1,anim_frame_duration(a0) bpl.s + addi_.b #1,mapping_frame(a0) move.b #8,anim_frame_duration(a0) cmpi.b #$27,mapping_frame(a0) bgt.w Obj5D_Gunk_OffScreen blt.s + addi.b #$C,anim_frame_duration(a0) + movea.l Obj5D_parent(a0),a1 ; a1=object movea.l Obj5D_parent(a1),a1 ; a1=object move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) jmp (DisplaySprite).l ; =========================================================================== Obj5D_Gunk_Droplets: moveq #0,d0 move.b subtype(a0),d0 bne.w Obj5D_Gunk_Droplets_Move addi.w #$18,y_pos(a0) addi.w #$C,x_pos(a0) btst #0,render_flags(a0) beq.s + subi.w #$18,x_pos(a0) + move.b #4,y_radius(a0) move.b #4,x_radius(a0) addq.b #1,subtype(a0) move.b #9,mapping_frame(a0) move.w y_vel(a0),d0 lsr.w #1,d0 neg.w d0 move.w d0,y_vel(a0) jsr (RandomNumber).l asr.w #6,d0 bmi.s + addi.w #$200,d0 + addi.w #-$100,d0 move.w d0,x_vel(a0) move.b #0,collision_flags(a0) moveq #3,d3 Obj5D_Gunk_Droplets_Loop: jsr (SingleObjLoad2).l bne.w BranchTo_JmpTo34_DisplaySprite _move.b #ObjID_CPZBoss,id(a1) ; load obj5D move.l a0,Obj5D_parent(a1) move.l #Obj5D_MapUnc_2EADC,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,3,0),art_tile(a1) move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #2,priority(a1) move.l x_pos(a0),x_pos(a1) move.l y_pos(a0),y_pos(a1) move.b #4,y_radius(a1) move.b #4,x_radius(a1) move.b #9,mapping_frame(a1) move.b #$C,routine(a1) move.b #4,routine_secondary(a1) move.b #1,subtype(a1) move.w y_vel(a0),y_vel(a1) move.b collision_flags(a0),collision_flags(a1) jsr (RandomNumber).l asr.w #6,d0 bmi.s + addi.w #$80,d0 + addi.w #-$80,d0 move.w d0,x_vel(a1) swap d0 andi.w #$3FF,d0 sub.w d0,y_vel(a1) dbf d3,Obj5D_Gunk_Droplets_Loop BranchTo_JmpTo34_DisplaySprite jmpto (DisplaySprite).l, JmpTo34_DisplaySprite ; =========================================================================== Obj5D_Gunk_Droplets_Move: jsrto (ObjectMoveAndFall).l, JmpTo3_ObjectMoveAndFall jsr (ObjCheckFloorDist).l tst.w d1 bmi.s + jmpto (MarkObjGone).l, JmpTo35_MarkObjGone ; --------------------------------------------------------------------------- + bra.w JmpTo51_DeleteObject ; =========================================================================== ; a bit of unused/dead code here add.w d1,y_pos(a0) ; a0=object move.w y_vel(a0),d0 lsr.w #1,d0 neg.w d0 move.w d0,y_vel(a0) jmpto (DisplaySprite).l, JmpTo34_DisplaySprite ; =========================================================================== Obj5D_Robotnik: movea.l Obj5D_parent(a0),a1 ; a1=object move.l x_pos(a1),x_pos(a0) move.l y_pos(a1),y_pos(a0) move.b status(a1),status(a0) move.b render_flags(a1),render_flags(a0) move.b Obj5D_invulnerable_time(a1),d0 cmpi.b #$1F,d0 bne.s + move.b #2,anim(a0) + cmpi.b #4,(MainCharacter+routine).w beq.s + cmpi.b #4,(Sidekick+routine).w bne.s Obj5D_Robotnik_End + move.b #3,anim(a0) Obj5D_Robotnik_End: lea (Ani_obj5D_b).l,a1 jsr (AnimateSprite).l jmp (DisplaySprite).l ; =========================================================================== byte_2E94A: dc.b 0 dc.b $FF ; 1 dc.b 1 ; 2 dc.b 0 ; 3 ; =========================================================================== Obj5D_Flame: btst #7,status(a0) bne.s loc_2E9A8 movea.l Obj5D_parent(a0),a1 ; a1=object move.l x_pos(a1),x_pos(a0) move.l y_pos(a1),y_pos(a0) move.b status(a1),status(a0) move.b render_flags(a1),render_flags(a0) subq.b #1,anim_frame_duration(a0) bpl.s loc_2E996 move.b #1,anim_frame_duration(a0) move.b Obj5D_timer2(a0),d0 addq.b #1,d0 cmpi.b #2,d0 ble.s + moveq #0,d0 + move.b byte_2E94A(pc,d0.w),mapping_frame(a0) move.b d0,Obj5D_timer2(a0) loc_2E996: cmpi.b #-1,mapping_frame(a0) bne.w JmpTo34_DisplaySprite move.b #0,mapping_frame(a0) rts ; =========================================================================== loc_2E9A8: movea.l Obj5D_parent(a0),a1 ; a1=object btst #6,Obj5D_status2(a1) bne.s + rts ; =========================================================================== + addq.b #2,routine_secondary(a0) move.l #Obj5D_MapUnc_2EEA0,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_EggpodJets_1,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo60_Adjust2PArtPointer move.b #0,mapping_frame(a0) move.b #5,anim_frame_duration(a0) movea.l Obj5D_parent(a0),a1 ; a1=object move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) addi_.w #4,y_pos(a0) subi.w #$28,x_pos(a0) rts ; =========================================================================== Obj5D_1A: subq.b #1,anim_frame_duration(a0) bpl.s BranchTo2_JmpTo34_DisplaySprite move.b #5,anim_frame_duration(a0) addq.b #1,mapping_frame(a0) cmpi.b #4,mapping_frame(a0) bne.w BranchTo2_JmpTo34_DisplaySprite move.b #0,mapping_frame(a0) movea.l Obj5D_parent(a0),a1 ; a1=object move.b id(a1),d0 beq.w JmpTo51_DeleteObject ; branch, if parent object is gone move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) addi_.w #4,y_pos(a0) subi.w #$28,x_pos(a0) BranchTo2_JmpTo34_DisplaySprite jmpto (DisplaySprite).l, JmpTo34_DisplaySprite ; =========================================================================== ; animation script ; off_2EA3C: Ani_Obj5D_Dripper: offsetTable offsetTableEntry.w byte_2EA72 ; 0 offsetTableEntry.w byte_2EA75 ; 1 offsetTableEntry.w byte_2EA78 ; 2 offsetTableEntry.w byte_2EA7D ; 3 offsetTableEntry.w byte_2EA81 ; 4 offsetTableEntry.w byte_2EA88 ; 5 offsetTableEntry.w byte_2EA8B ; 6 offsetTableEntry.w byte_2EA8E ; 7 offsetTableEntry.w byte_2EA91 ; 8 offsetTableEntry.w byte_2EA94 ; 9 offsetTableEntry.w byte_2EA97 ; $A offsetTableEntry.w byte_2EAA3 ; $B offsetTableEntry.w byte_2EAAE ; $C offsetTableEntry.w byte_2EAB1 ; $D offsetTableEntry.w byte_2EAB4 ; $E offsetTableEntry.w byte_2EAB7 ; $F offsetTableEntry.w byte_2EABA ; $10 offsetTableEntry.w byte_2EABD ; $11 offsetTableEntry.w byte_2EAC0 ; $12 offsetTableEntry.w byte_2EAC3 ; $13 offsetTableEntry.w byte_2EAC6 ; $14 offsetTableEntry.w byte_2EAC9 ; $15 offsetTableEntry.w byte_2EACC ; $16 offsetTableEntry.w byte_2EACF ; $17 offsetTableEntry.w byte_2EAD2 ; $18 offsetTableEntry.w byte_2EAD5 ; $19 offsetTableEntry.w byte_2EAD9 ; $1A byte_2EA72: dc.b $F, 0,$FF rev02even byte_2EA75: dc.b $F, 1,$FF rev02even byte_2EA78: dc.b 5, 2, 3, 2,$FF rev02even byte_2EA7D: dc.b 5, 2, 3,$FF rev02even byte_2EA81: dc.b 2, 4, 5, 6, 7, 8,$FF rev02even byte_2EA88: dc.b 3, 9,$FF rev02even byte_2EA8B: dc.b $F, $A,$FF rev02even byte_2EA8E: dc.b $F,$1C,$FF rev02even byte_2EA91: dc.b $F,$1E,$FF rev02even byte_2EA94: dc.b $F, $B,$FF rev02even byte_2EA97: dc.b 3, $C, $C, $D, $D, $D, $D, $D, $C, $C,$FD, 9 rev02even byte_2EAA3: dc.b 3, $E, $E, $F, $F, $F, $F, $F, $E, $E,$FF rev02even byte_2EAAE: dc.b $F,$10,$FF rev02even byte_2EAB1: dc.b $F,$11,$FF rev02even byte_2EAB4: dc.b $F,$12,$FF rev02even byte_2EAB7: dc.b $F,$13,$FF rev02even byte_2EABA: dc.b $F,$14,$FF rev02even byte_2EABD: dc.b $F,$15,$FF rev02even byte_2EAC0: dc.b $F,$16,$FF rev02even byte_2EAC3: dc.b $F,$17,$FF rev02even byte_2EAC6: dc.b $F,$18,$FF rev02even byte_2EAC9: dc.b $F,$19,$FF rev02even byte_2EACC: dc.b $F,$1A,$FF rev02even byte_2EACF: dc.b $F,$1B,$FF rev02even byte_2EAD2: dc.b $F,$1C,$FF rev02even byte_2EAD5: dc.b 1,$1D,$1F,$FF rev02even byte_2EAD9: dc.b $F,$1E,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings - uses ArtNem_CPZBoss ; ---------------------------------------------------------------------------- Obj5D_MapUnc_2EADC: BINCLUDE "mappings/sprite/obj5D_a.bin" ; animation script ; off_2ED5C: Ani_obj5D_b: offsetTable offsetTableEntry.w byte_2ED66 ; 0 offsetTableEntry.w byte_2ED69 ; 1 offsetTableEntry.w byte_2ED6D ; 2 offsetTableEntry.w byte_2ED76 ; 3 offsetTableEntry.w byte_2ED7F ; 4 byte_2ED66: dc.b $F, 0,$FF rev02even byte_2ED69: dc.b 7, 1, 2,$FF rev02even byte_2ED6D: dc.b 7, 5, 5, 5, 5, 5, 5,$FD, 1 rev02even byte_2ED76: dc.b 7, 3, 4, 3, 4, 3, 4,$FD, 1 rev02even byte_2ED7F: dc.b $F, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,$FD, 1 even ; ---------------------------------------------------------------------------- ; sprite mappings - uses ArtNem_Eggpod ; ---------------------------------------------------------------------------- Obj5D_MapUnc_2ED8C: BINCLUDE "mappings/sprite/obj5D_b.bin" ; ---------------------------------------------------------------------------- ; sprite mappings - uses ArtNem_EggpodJets ; ---------------------------------------------------------------------------- Obj5D_MapUnc_2EE88: BINCLUDE "mappings/sprite/obj5D_c.bin" ; ---------------------------------------------------------------------------- ; sprite mappings - uses ArtNem_BossSmoke ; ---------------------------------------------------------------------------- Obj5D_MapUnc_2EEA0: BINCLUDE "mappings/sprite/obj5D_d.bin" ; =========================================================================== if ~~removeJmpTos JmpTo34_DisplaySprite jmp (DisplaySprite).l JmpTo51_DeleteObject jmp (DeleteObject).l JmpTo35_MarkObjGone jmp (MarkObjGone).l JmpTo5_PlaySound jmp (PlaySound).l JmpTo8_Adjust2PArtPointer2 jmp (Adjust2PArtPointer2).l JmpTo5_LoadPLC jmp (LoadPLC).l JmpTo2_AddPoints jmp (AddPoints).l JmpTo60_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo_PlayLevelMusic jmp (PlayLevelMusic).l JmpTo_LoadPLC_AnimalExplosion jmp (LoadPLC_AnimalExplosion).l JmpTo3_ObjectMoveAndFall jmp (ObjectMoveAndFall).l ; loc_2EF12: JmpTo23_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 56 - EHZ boss ; the bottom part of the vehicle with the ability to fly is the parent object ; ---------------------------------------------------------------------------- ; Sprite_2EF18: Obj56: moveq #0,d0 move.b routine(a0),d0 move.w Obj56_Index(pc,d0.w),d1 jmp Obj56_Index(pc,d1.w) ; =========================================================================== ; off_2EF26: Obj56_Index: offsetTable offsetTableEntry.w Obj56_Init ; 0 - Init offsetTableEntry.w loc_2F262 ; 2 - Flying vehicle, bottom = main object offsetTableEntry.w loc_2F54E ; 4 - Propeller normal offsetTableEntry.w loc_2F5F6 ; 6 - Vehicle on ground offsetTableEntry.w loc_2F664 ; 8 - Wheels offsetTableEntry.w loc_2F7F4 ; A - Spike offsetTableEntry.w loc_2F52A ; C - Propeller after defeat offsetTableEntry.w loc_2F8DA ; E - Flying vehicle, top ; =========================================================================== ; #7,status(ax) set via collision response routine (Touch_Enemy_Part2) ; when after a hit collision_property(ax) = hitcount has reached zero ; objoff_2A(ax) used as timer (countdown) ; objoff_2C(ax) tertiary rountine counter ; #0,objoff_2D(ax) set when robotnik is on ground ; #1,objoff_2D(ax) set when robotnik is active (moving back & forth) ; #2,objoff_2D(ax) set when robotnik is flying off after being defeated ; #3,objoff_2D(ax) flag to separate spike from vehicle ; objoff_2E(ax) y_position of wheels ; objoff_34(ax) parent object ; objoff_3C(ax) timer after defeat ; loc_2EF36: Obj56_Init: move.l #Obj56_MapUnc_2FAF8,mappings(a0) ; main object move.w #make_art_tile(ArtTile_ArtNem_Eggpod_1,1,0),art_tile(a0) ; vehicle with ability to fly, bottom part ori.b #4,render_flags(a0) move.b #$81,subtype(a0) move.w #$29D0,x_pos(a0) move.w #$426,y_pos(a0) move.b #$20,width_pixels(a0) move.b #$14,y_radius(a0) move.b #4,priority(a0) move.b #$F,collision_flags(a0) move.b #8,collision_property(a0) ; hitcount addq.b #2,routine(a0) move.w x_pos(a0),objoff_30(a0) move.w y_pos(a0),objoff_38(a0) jsrto (Adjust2PArtPointer).l, JmpTo61_Adjust2PArtPointer jsr (SingleObjLoad2).l ; vehicle with ability to fly, top part bne.w + _move.b #ObjID_EHZBoss,id(a1) ; load obj56 move.l a0,objoff_34(a1) ; link top and bottom to each other move.l a1,objoff_34(a0) ; i.e. addresses for cross references move.l #Obj56_MapUnc_2FAF8,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_Eggpod_1,0,0),art_tile(a1) move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #4,priority(a1) move.l x_pos(a0),x_pos(a1) move.l y_pos(a0),y_pos(a1) move.b #$E,routine(a1) move.b #1,anim(a1) ; normal animation move.b render_flags(a0),render_flags(a1) + jsr (SingleObjLoad2).l ; Vehicle on ground bne.s + _move.b #ObjID_EHZBoss,id(a1) ; load obj56 move.l a0,objoff_34(a1) ; linked to main object move.l #Obj56_MapUnc_2FA58,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_EHZBoss,0,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo9_Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #$30,width_pixels(a1) move.b #$10,y_radius(a1) move.b #3,priority(a1) move.w #$2AF0,x_pos(a1) move.l y_pos(a0),y_pos(a1) move.b #6,routine(a1) + bsr.w loc_2F098 subi_.w #8,objoff_38(a0) move.w #$2AF0,x_pos(a0) move.w #$2F8,y_pos(a0) jsr (SingleObjLoad2).l ; propeller normal bne.s + ; rts _move.b #ObjID_EHZBoss,id(a1) ; load obj56 move.l a0,objoff_34(a1) ; linked to main object move.l #Obj56_MapUnc_2F970,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_EggChoppers,1,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo9_Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #$40,width_pixels(a1) move.b #3,priority(a1) move.l x_pos(a0),x_pos(a1) move.l y_pos(a0),y_pos(a1) move.w #$1E,objoff_2A(a1) move.b #4,routine(a1) + rts ; --------------------------------------------------------------------------- loc_2F098: jsr (SingleObjLoad2).l ; first foreground wheel bne.s + _move.b #ObjID_EHZBoss,id(a1) ; load obj56 move.l a0,objoff_34(a1) ; linked to main object move.l #Obj56_MapUnc_2FA58,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_EHZBoss,1,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo9_Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #$10,width_pixels(a1) move.b #2,priority(a1) move.b #$10,y_radius(a1) move.b #$10,x_radius(a1) move.w #$2AF0,x_pos(a1) move.l y_pos(a0),y_pos(a1) addi.w #$1C,x_pos(a1) addi.w #$C,y_pos(a1) move.b #8,routine(a1) move.b #4,mapping_frame(a1) move.b #1,anim(a1) move.w #$A,objoff_2A(a1) move.b #0,subtype(a1) + jsr (SingleObjLoad2).l ; second foreground wheel bne.s + _move.b #ObjID_EHZBoss,id(a1) ; load obj56 move.l a0,objoff_34(a1) ; linked to main object move.l #Obj56_MapUnc_2FA58,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_EHZBoss,1,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo9_Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #$10,width_pixels(a1) move.b #2,priority(a1) move.b #$10,y_radius(a1) move.b #$10,x_radius(a1) move.w #$2AF0,x_pos(a1) move.l y_pos(a0),y_pos(a1) addi.w #-$C,x_pos(a1) addi.w #$C,y_pos(a1) move.b #8,routine(a1) move.b #4,mapping_frame(a1) move.b #1,anim(a1) move.w #$A,objoff_2A(a1) move.b #1,subtype(a1) + jsr (SingleObjLoad2).l ; background wheel bne.s + _move.b #ObjID_EHZBoss,id(a1) ; load obj56 move.l a0,objoff_34(a1) ; linked to main object move.l #Obj56_MapUnc_2FA58,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_EHZBoss,1,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo9_Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #$10,width_pixels(a1) move.b #3,priority(a1) move.b #$10,y_radius(a1) move.b #$10,x_radius(a1) move.w #$2AF0,x_pos(a1) move.l y_pos(a0),y_pos(a1) addi.w #-$2C,x_pos(a1) addi.w #$C,y_pos(a1) move.b #8,routine(a1) move.b #6,mapping_frame(a1) move.b #2,anim(a1) move.w #$A,objoff_2A(a1) move.b #2,subtype(a1) + jsr (SingleObjLoad2).l ; Spike bne.s + _move.b #ObjID_EHZBoss,id(a1) ; load obj56 move.l a0,objoff_34(a1) ; linked to main object move.l #Obj56_MapUnc_2FA58,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_EHZBoss,1,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo9_Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #2,priority(a1) move.w #$2AF0,x_pos(a1) move.l y_pos(a0),y_pos(a1) addi.w #-$36,x_pos(a1) addi_.w #8,y_pos(a1) move.b #$A,routine(a1) move.b #1,mapping_frame(a1) move.b #0,anim(a1) + rts ; =========================================================================== loc_2F262: ; Obj56_VehicleMain: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_2F270(pc,d0.w),d1 jmp off_2F270(pc,d1.w) ; --------------------------------------------------------------------------- off_2F270: offsetTable offsetTableEntry.w loc_2F27C ; 0 - approaching diagonally offsetTableEntry.w loc_2F2A8 ; 2 - final approaching stage (vertically/waiting) offsetTableEntry.w loc_2F304 ; 4 - moving back and forth offsetTableEntry.w loc_2F336 ; 6 - boss defeated, falling/lying on ground offsetTableEntry.w loc_2F374 ; 8 - boss idle for $C frames offsetTableEntry.w loc_2F38A ; A - flying off, moving camera ; =========================================================================== loc_2F27C: ; Obj56_VehicleMain_Sub0: move.b #0,collision_flags(a0) cmpi.w #$29D0,x_pos(a0) ; reached the point to unite with bottom vehicle? ble.s loc_2F29A subi_.w #1,x_pos(a0) addi_.w #1,y_pos(a0) ; move diagonally down bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F29A: move.w #$29D0,x_pos(a0) addq.b #2,routine_secondary(a0) ; next routine bra.w JmpTo35_DisplaySprite ; =========================================================================== loc_2F2A8: ; Obj56_VehicleMain_Sub2: moveq #0,d0 move.b objoff_2C(a0),d0 ; tertiary routine move.w off_2F2B6(pc,d0.w),d1 jmp off_2F2B6(pc,d1.w) ; --------------------------------------------------------------------------- off_2F2B6: offsetTable offsetTableEntry.w loc_2F2BA ; 0 - moving down to ground vehicle vertically offsetTableEntry.w loc_2F2E0 ; 2 - not moving, delay until activation ; --------------------------------------------------------------------------- loc_2F2BA: ; Obj56_VehicleMain_Sub2_0: cmpi.w #$41E,y_pos(a0) bge.s loc_2F2CC addi_.w #1,y_pos(a0) ; move vertically (down) bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F2CC: addq.b #2,objoff_2C(a0) ; tertiary routine bset #0,objoff_2D(a0) ; robotnik on ground (relevant for propeller) move.w #$3C,objoff_2A(a0) ; timer for standing still bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F2E0: ; Obj56_VehicleMain_Sub2_2: subi_.w #1,objoff_2A(a0) ; timer bpl.w JmpTo35_DisplaySprite move.w #-$200,x_vel(a0) addq.b #2,routine_secondary(a0) move.b #$F,collision_flags(a0) bset #1,objoff_2D(a0) ; boss now active and moving bra.w JmpTo35_DisplaySprite ; =========================================================================== loc_2F304: ; Obj56_VehicleMain_Sub4: bsr.w loc_2F4A6 ; routine to handle hits bsr.w loc_2F484 ; position check, sets direction move.w objoff_2E(a0),d0 ; y_position of wheels lsr.w #1,d0 subi.w #$14,d0 move.w d0,y_pos(a0) ; set y_pos depending on wheels move.w #0,objoff_2E(a0) move.l x_pos(a0),d2 move.w x_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d2 move.l d2,x_pos(a0) ; set x_pos depening on velocity bra.w JmpTo35_DisplaySprite ; =========================================================================== loc_2F336: ; Obj56_VehicleMain_Sub6: subq.w #1,objoff_3C(a0) ; timer set after defeat bmi.s loc_2F35C ; if countdown finished bsr.w Boss_LoadExplosion jsrto (ObjectMoveAndFall).l, JmpTo4_ObjectMoveAndFall jsrto (ObjCheckFloorDist).l, JmpTo3_ObjCheckFloorDist tst.w d1 bpl.w JmpTo35_DisplaySprite add.w d1,y_pos(a0) move.w #0,y_vel(a0) ; set to ground and stand still bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F35C: clr.w x_vel(a0) addq.b #2,routine_secondary(a0) move.w #-$26,objoff_3C(a0) move.w #$C,objoff_2A(a0) bra.w JmpTo35_DisplaySprite ; =========================================================================== loc_2F374: ; Obj56_VehicleMain_Sub8: subq.w #1,objoff_2A(a0) ; timer bpl.w JmpTo35_DisplaySprite addq.b #2,routine_secondary(a0) move.b #0,objoff_2C(a0) ; tertiary routine bra.w JmpTo35_DisplaySprite ; =========================================================================== loc_2F38A: ; Obj56_VehicleMain_SubA: moveq #0,d0 move.b objoff_2C(a0),d0 ; tertiary routine move.w off_2F39C(pc,d0.w),d1 jsr off_2F39C(pc,d1.w) bra.w JmpTo35_DisplaySprite ; =========================================================================== off_2F39C: offsetTable offsetTableEntry.w loc_2F3A2 ; 0 - initialize propellor offsetTableEntry.w loc_2F424 ; 2 - waiting offsetTableEntry.w loc_2F442 ; 4 - flying off ; =========================================================================== loc_2F3A2: ; Obj56_VehicleMain_SubA_0: bclr #0,objoff_2D(a0) ; robotnik off ground jsrto (SingleObjLoad2).l, JmpTo21_SingleObjLoad2 ; reload propeller after defeat bne.w + ; rts _move.b #ObjID_EHZBoss,id(a1) ; load obj56 move.l a0,objoff_34(a1) ; linked to main object move.l #Obj56_MapUnc_2F970,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_EggChoppers,1,0),art_tile(a1) jsrto (Adjust2PArtPointer2).l, JmpTo9_Adjust2PArtPointer2 move.b #4,render_flags(a1) move.b #$20,width_pixels(a1) move.b #3,priority(a1) move.l x_pos(a0),x_pos(a1) move.l y_pos(a0),y_pos(a1) addi.w #$C,y_pos(a1) move.b status(a0),status(a1) move.b render_flags(a0),render_flags(a1) move.b #$C,routine(a1) move.b #2,anim(a1) move.w #$10,objoff_2A(a1) ; timer move.w #$32,objoff_2A(a0) ; timer addq.b #2,objoff_2C(a0) ; tertiary routine - increase jsrto (PlayLevelMusic).l, JmpTo2_PlayLevelMusic ; play level Music move.b #1,(Boss_defeated_flag).w + rts ; =========================================================================== loc_2F424: ; Obj56_VehicleMain_SubA_2: subi_.w #1,objoff_2A(a0) ; timer bpl.s + ; rts bset #2,objoff_2D(a0) ; robotnik flying off move.w #$60,objoff_2A(a0) ; timer addq.b #2,objoff_2C(a0) ; tertiary routine jsrto (LoadPLC_AnimalExplosion).l, JmpTo2_LoadPLC_AnimalExplosion ; PLC_Explosion + rts ; =========================================================================== loc_2F442: ; Obj56_VehicleMain_SubA_4: subi_.w #1,objoff_2A(a0) ; timer bpl.s loc_2F45C bset #0,status(a0) bset #0,render_flags(a0) addq.w #6,x_pos(a0) bra.s loc_2F460 ; =========================================================================== loc_2F45C: subq.w #1,y_pos(a0) loc_2F460: cmpi.w #$2AB0,(Camera_Max_X_pos).w bhs.s loc_2F46E addq.w #2,(Camera_Max_X_pos).w bra.s return_2F482 ; =========================================================================== loc_2F46E: tst.b render_flags(a0) bmi.s return_2F482 addq.w #4,sp movea.l objoff_34(a0),a1 ; parent address (vehicle) jsrto (DeleteObject2).l, JmpTo5_DeleteObject2 jmpto (DeleteObject).l, JmpTo52_DeleteObject ; =========================================================================== return_2F482: rts ; =========================================================================== loc_2F484: ; shared routine, checks positions and sets direction move.w x_pos(a0),d0 cmpi.w #$28A0,d0 ; beyond left boundary? ble.s loc_2F494 cmpi.w #$2B08,d0 blt.s return_2F4A4 ; beyond right boundary? loc_2F494: ; beyond boundary bchg #0,status(a0) ; change direction bchg #0,render_flags(a0) ; mirror sprite neg.w x_vel(a0) ; change direction of velocity return_2F4A4: rts ; =========================================================================== loc_2F4A6: ; routine to handle hits cmpi.b #6,routine_secondary(a0) ; is only called when value is 4? bhs.s return_2F4EC ; thus unnecessary? (return if greater or equal than 6) tst.b status(a0) bmi.s loc_2F4EE ; sonic has just defeated the boss (i.e. bit 7 set) tst.b collision_flags(a0) ; set to 0 when boss was hit by Touch_Enemy_Part2 bne.s return_2F4EC ; not 0, i.e. boss not hit tst.b objoff_3E(a0) bne.s loc_2F4D0 ; boss already invincibile move.b #$20,objoff_3E(a0) ; boss invincibility timer move.w #SndID_BossHit,d0 jsr (PlaySound).l ; play boss hit sound loc_2F4D0: lea (Normal_palette_line2+2).w,a1 moveq #0,d0 ; black tst.w (a1) bne.s loc_2F4DE ; already not black (i.e. white)? move.w #$EEE,d0 ; white loc_2F4DE: move.w d0,(a1) ; set respective color subq.b #1,objoff_3E(a0) ; decrease boss invincibility timer bne.s return_2F4EC move.b #$F,collision_flags(a0) ; if invincibility ended, allow collision again return_2F4EC: rts ; =========================================================================== loc_2F4EE: ; boss defeated moveq #100,d0 jsrto (AddPoints).l, JmpTo3_AddPoints ; add 1000 points, reward for defeating boss move.b #6,routine_secondary(a0) move.w #0,x_vel(a0) move.w #-$180,y_vel(a0) move.w #$B3,objoff_3C(a0) ; timer bset #3,objoff_2D(a0) ; flag to separate spike from vehicle movea.l objoff_34(a0),a1 ; address top part move.b #4,anim(a1) ; flying off animation move.b #6,mapping_frame(a1) moveq #PLCID_Capsule,d0 jmpto (LoadPLC).l, JmpTo6_LoadPLC ; load egg prison ; =========================================================================== rts ; =========================================================================== loc_2F52A: ; Obj56_PropellerReloaded: ; Propeller after defeat subi_.w #1,y_pos(a0) ; move up subi_.w #1,objoff_2A(a0) ; decrease timer bpl.w JmpTo35_DisplaySprite move.b #4,routine(a0) ; Propeller normal lea (Ani_obj56_a).l,a1 jsrto (AnimateSprite).l, JmpTo17_AnimateSprite bra.w JmpTo35_DisplaySprite ; =========================================================================== loc_2F54E: ; Obj56_Propeller: ; Propeller normal moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_2F55C(pc,d0.w),d1 jmp off_2F55C(pc,d1.w) ; --------------------------------------------------------------------------- off_2F55C: offsetTable offsetTableEntry.w loc_2F560 ; 0 - robotnik in air offsetTableEntry.w loc_2F5C6 ; 2 - robotnik on ground ; --------------------------------------------------------------------------- loc_2F560: ; Obj56_Propeller_Sub0 movea.l objoff_34(a0),a1 ; parent address (vehicle) cmpi.b #ObjID_EHZBoss,id(a1) bne.w JmpTo52_DeleteObject ; if boss non-existant btst #0,objoff_2D(a1) ; is robotnik on ground? beq.s loc_2F58E ; if not, branch move.b #1,anim(a0) move.w #$18,objoff_2A(a0) ; timer until deletion addq.b #2,routine_secondary(a0) move.b #MusID_StopSFX,d0 jsrto (PlaySound).l, JmpTo6_PlaySound bra.s loc_2F5A0 ; --------------------------------------------------------------------------- loc_2F58E: ; not on ground move.b (Vint_runcount+3).w,d0 andi.b #$1F,d0 bne.s loc_2F5A0 move.b #SndID_Helicopter,d0 jsrto (PlaySound).l, JmpTo6_PlaySound loc_2F5A0: move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) move.b status(a1),status(a0) move.b render_flags(a1),render_flags(a0) lea (Ani_obj56_a).l,a1 jsrto (AnimateSprite).l, JmpTo17_AnimateSprite bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F5C6: ; Obj56_Propeller_Sub2 subi_.w #1,objoff_2A(a0) ; timer bpl.s loc_2F5E8 cmpi.w #-$10,objoff_2A(a0) ble.w JmpTo52_DeleteObject move.b #4,priority(a0) addi_.w #1,y_pos(a0) ; move down bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F5E8: lea (Ani_obj56_a).l,a1 jsrto (AnimateSprite).l, JmpTo17_AnimateSprite bra.w JmpTo35_DisplaySprite ; =========================================================================== loc_2F5F6: ; Obj56_GroundVehicle: tst.b routine_secondary(a0) bne.s loc_2F626 ; Obj56_GroundVehicle_Sub0: cmpi.w #$28F0,(Camera_Min_X_pos).w blo.w JmpTo35_DisplaySprite cmpi.w #$29D0,x_pos(a0) ble.s loc_2F618 subi_.w #1,x_pos(a0) bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F618: move.w #$29D0,x_pos(a0) addq.b #2,routine_secondary(a0) bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F626: ; Obj56_GroundVehicle_Sub2: movea.l objoff_34(a0),a1 ; parent address (vehicle) btst #1,objoff_2D(a1) beq.w JmpTo35_DisplaySprite ; boss not moving yet (inactive) btst #2,objoff_2D(a1) ; robotnik flying off flag bne.w JmpTo35_DisplaySprite move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) addi_.w #8,y_pos(a0) move.b status(a1),status(a0) bmi.w JmpTo35_DisplaySprite move.b render_flags(a1),render_flags(a0) bra.w JmpTo35_DisplaySprite ; =========================================================================== loc_2F664: ; Obj56_Wheel: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_2F672(pc,d0.w),d1 jmp off_2F672(pc,d1.w) ; --------------------------------------------------------------------------- off_2F672: offsetTable offsetTableEntry.w loc_2F67C ; 0 - wheels moving towards start position offsetTableEntry.w loc_2F714 ; 2 - standing still (boss inactive) offsetTableEntry.w loc_2F746 ; 4 - normal mode (boss active) offsetTableEntry.w loc_2F7A6 ; 6 - inactive while defeat offsetTableEntry.w loc_2F7D2 ; 8 - wheels bouncing away after defeat ; --------------------------------------------------------------------------- loc_2F67C: ; Obj56_Wheel_Sub0: cmpi.w #$28F0,(Camera_Min_X_pos).w blo.w JmpTo35_DisplaySprite move.w #$100,y_vel(a0) cmpi.b #1,subtype(a0) ; wheel number (0-2) bgt.s loc_2F6B6 ; background wheel beq.s loc_2F6A6 ; second foreground wheel ; --------------------------------------------------------------------------- cmpi.w #$29EC,x_pos(a0) ; first foreground wheel ble.s loc_2F6C6 subi_.w #1,x_pos(a0) bra.s loc_2F6E8 loc_2F6A6: ; second foreground wheel cmpi.w #$29C4,x_pos(a0) ble.s loc_2F6D2 subi_.w #1,x_pos(a0) bra.s loc_2F6E8 loc_2F6B6: ; background wheel cmpi.w #$29A4,x_pos(a0) ble.s loc_2F6DE subi_.w #1,x_pos(a0) bra.s loc_2F6E8 ; --------------------------------------------------------------------------- loc_2F6C6: ; first foreground wheel move.w #$29EC,x_pos(a0) addq.b #2,routine_secondary(a0) bra.s loc_2F6E8 loc_2F6D2: ; second foreground wheel move.w #$29C4,x_pos(a0) addq.b #2,routine_secondary(a0) bra.s loc_2F6E8 loc_2F6DE: ; background wheel move.w #$29A4,x_pos(a0) addq.b #2,routine_secondary(a0) ; --------------------------------------------------------------------------- loc_2F6E8: ; routine for all wheels jsrto (ObjectMoveAndFall).l, JmpTo4_ObjectMoveAndFall jsr (ObjCheckFloorDist).l tst.w d1 bpl.s loc_2F6FA add.w d1,y_pos(a0) ; reset on floor loc_2F6FA: tst.b routine_secondary(a0) beq.s loc_2F706 move.w #-$200,x_vel(a0) ; if reached position, set velocity loc_2F706: lea (Ani_obj56_b).l,a1 jsrto (AnimateSprite).l, JmpTo17_AnimateSprite bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F714: ; Obj56_Wheel_Sub2: movea.l objoff_34(a0),a1 ; parent address (vehicle) cmpi.b #ObjID_EHZBoss,id(a1) bne.w JmpTo52_DeleteObject ; if boss non-existant btst #1,objoff_2D(a1) beq.w JmpTo35_DisplaySprite ; boss not moving yet (inactive) addq.b #2,routine_secondary(a0) cmpi.b #2,priority(a0) bne.s BranchTo_JmpTo35_DisplaySprite move.w y_pos(a0),d0 movea.l objoff_34(a0),a1 ; parent address (vehicle) add.w d0,objoff_2E(a1) BranchTo_JmpTo35_DisplaySprite bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F746: ; Obj56_Wheel_Sub4: movea.l objoff_34(a0),a1 ; parent address (vehicle) cmpi.b #ObjID_EHZBoss,id(a1) bne.w JmpTo52_DeleteObject ; if boss non-existant move.b status(a1),status(a0) move.b render_flags(a1),render_flags(a0) tst.b status(a0) bpl.s loc_2F768 ; has sonic just defeated the boss (i.e. bit7 set)? addq.b #2,routine_secondary(a0) ; if yes, Sub6 loc_2F768: bsr.w loc_2F484 ; position check, sets direction jsrto (ObjectMoveAndFall).l, JmpTo4_ObjectMoveAndFall jsr (ObjCheckFloorDist).l tst.w d1 bpl.s loc_2F77E add.w d1,y_pos(a0) ; reset on floor loc_2F77E: move.w #$100,y_vel(a0) cmpi.b #2,priority(a0) bne.s loc_2F798 move.w y_pos(a0),d0 movea.l objoff_34(a0),a1 ; parent address (vehicle) add.w d0,objoff_2E(a1) loc_2F798: lea (Ani_obj56_b).l,a1 jsrto (AnimateSprite).l, JmpTo17_AnimateSprite bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F7A6: ; Obj56_Wheel_Sub6: subi_.w #1,objoff_2A(a0) ; timer, initially set to $A (first delay until wheels rolling off) bpl.w JmpTo35_DisplaySprite addq.b #2,routine_secondary(a0) ; Sub8 move.w #$A,objoff_2A(a0) move.w #-$300,y_vel(a0) ; first bounce higher cmpi.b #2,priority(a0) beq.w JmpTo35_DisplaySprite neg.w x_vel(a0) ; into other direction bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F7D2: ; Obj56_Wheel_Sub8: subq.w #1,objoff_2A(a0) ; timer, initially set to $A (second delay until wheels rolling off) bpl.w JmpTo35_DisplaySprite jsrto (ObjectMoveAndFall).l, JmpTo4_ObjectMoveAndFall jsrto (ObjCheckFloorDist).l, JmpTo3_ObjCheckFloorDist tst.w d1 bpl.s BranchTo_JmpTo36_MarkObjGone move.w #-$200,y_vel(a0) ; negative velocity to have bouncing effect add.w d1,y_pos(a0) ; reset on floor BranchTo_JmpTo36_MarkObjGone jmpto (MarkObjGone).l, JmpTo36_MarkObjGone ; =========================================================================== loc_2F7F4: ; Obj56_Spike: tst.b routine_secondary(a0) bne.s loc_2F824 ; Obj56_Spike_Sub0: cmpi.w #$28F0,(Camera_Min_X_pos).w blo.w JmpTo35_DisplaySprite cmpi.w #$299A,x_pos(a0) ble.s loc_2F816 subi_.w #1,x_pos(a0) bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F816: move.w #$299A,x_pos(a0) addq.b #2,routine_secondary(a0) bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F824: ; Obj56_Spike_Sub2: movea.l objoff_34(a0),a1 ; parent address (vehicle) cmpi.b #ObjID_EHZBoss,id(a1) bne.w JmpTo52_DeleteObject ; if boss non-existant btst #3,objoff_2D(a1) bne.s loc_2F88A ; spike separated from vehicle bsr.w loc_2F8AA btst #1,objoff_2D(a1) beq.w JmpTo35_DisplaySprite ; boss not moving yet (inactive) move.b #$8B,collision_flags(a0) ; spike still linked to vehicle move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) move.b status(a1),status(a0) ; transfer positions move.b render_flags(a1),render_flags(a0) addi.w #$10,y_pos(a0) ; vertical offset move.w #-$36,d0 btst #0,status(a0) beq.s loc_2F878 neg.w d0 loc_2F878: add.w d0,x_pos(a0) ; horizontal offset lea (Ani_obj56_b).l,a1 jsrto (AnimateSprite).l, JmpTo17_AnimateSprite bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F88A: ; spike separated from vehicle move.w #-3,d0 ; velocity of spike in pixels/frame btst #0,status(a0) ; check direction beq.s loc_2F898 neg.w d0 loc_2F898: add.w d0,x_pos(a0) lea (Ani_obj56_b).l,a1 jsrto (AnimateSprite).l, JmpTo17_AnimateSprite bra.w JmpTo35_DisplaySprite ; --------------------------------------------------------------------------- loc_2F8AA: cmpi.b #1,collision_property(a1) ; hit counter, only 1 life left? beq.s loc_2F8B4 rts ; --------------------------------------------------------------------------- loc_2F8B4: move.w x_pos(a0),d0 sub.w (MainCharacter+x_pos).w,d0 bpl.s loc_2F8C8 btst #0,status(a1) ; sonic right from spike bne.s loc_2F8D2 ; spike facing right rts ; --------------------------------------------------------------------------- loc_2F8C8: btst #0,status(a1) ; sonic left from spike beq.s loc_2F8D2 ; spike facing left rts ; --------------------------------------------------------------------------- loc_2F8D2: bset #3,objoff_2D(a1) ; flag to separate spike from vehicle rts ; =========================================================================== loc_2F8DA: ; Obj56_VehicleTop: movea.l objoff_34(a0),a1 ; parent address (vehicle) move.l x_pos(a1),x_pos(a0) move.l y_pos(a1),y_pos(a0) move.b status(a1),status(a0) ; update position and status move.b render_flags(a1),render_flags(a0) move.b objoff_3E(a1),d0 ; boss invincibility timer cmpi.b #$1F,d0 ; boss just got hit? bne.s loc_2F906 move.b #2,anim(a0) ; robotnik animation when hit loc_2F906: cmpi.b #4,(MainCharacter+routine).w ; Sonic = ball beq.s loc_2F916 cmpi.b #4,(Sidekick+routine).w ; Tails = ball bne.s loc_2F924 loc_2F916: cmpi.b #2,anim(a0) ; check eggman animation (when hit) beq.s loc_2F924 move.b #3,anim(a0) ; eggman animation when hurting sonic loc_2F924: lea (Ani_obj56_c).l,a1 ; animation script jsr (AnimateSprite).l jmp (DisplaySprite).l ; =========================================================================== ; animation script ; off_2F936: Ani_obj56_a: offsetTable offsetTableEntry.w byte_2F93C ; 0 offsetTableEntry.w byte_2F940 ; 1 offsetTableEntry.w byte_2F956 ; 2 byte_2F93C: dc.b 1, 5, 6,$FF byte_2F940: dc.b 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0 dc.b 0, 0, 0, 0, 0,$FF; 16 byte_2F956: dc.b 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 3, 3, 3, 2 dc.b 2, 2, 1, 1, 1, 5, 6,$FE, 2 even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj56_MapUnc_2F970: BINCLUDE "mappings/sprite/obj56_a.bin" ; propeller ; 7 frames ; animation script ; off_2FA44: Ani_obj56_b: offsetTable offsetTableEntry.w byte_2FA4A ; 0 offsetTableEntry.w byte_2FA4F ; 1 offsetTableEntry.w byte_2FA53 ; 2 byte_2FA4A: dc.b 5, 1, 2, 3,$FF ; spike rev02even byte_2FA4F: dc.b 1, 4, 5,$FF ; foreground wheel rev02even byte_2FA53: dc.b 1, 6, 7,$FF ; background wheel even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj56_MapUnc_2FA58: BINCLUDE "mappings/sprite/obj56_b.bin" ; ground vehicle ; frame 0 = vehicle itself ; frame 1-3 = spike ; frame 4-5 = foreground wheel ; frame 6-7 = background wheel ; animation script ; off_2FAC8: Ani_obj56_c: offsetTable offsetTableEntry.w byte_2FAD2 ; 0 offsetTableEntry.w byte_2FAD5 ; 1 offsetTableEntry.w byte_2FAD9 ; 2 offsetTableEntry.w byte_2FAE2 ; 3 offsetTableEntry.w byte_2FAEB ; 4 byte_2FAD2: dc.b $F, 0,$FF ; bottom rev02even byte_2FAD5: dc.b 7, 1, 2,$FF ; top, normal rev02even byte_2FAD9: dc.b 7, 5, 5, 5, 5, 5, 5,$FD, 1 ; top, when hit rev02even byte_2FAE2: dc.b 7, 3, 4, 3, 4, 3, 4,$FD, 1 ; top, laughter (when hurting sonic) rev02even byte_2FAEB: dc.b $F, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,$FD, 1 ; top, when flying off even ; for top part, after end of special animations always return to normal one ($FD->1) ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj56_MapUnc_2FAF8: BINCLUDE "mappings/sprite/obj56_c.bin" ; flying vehicle ; frame 0 = bottom ; frame 1-2 = top, normal ; frame 3-4 = top, laughter ; frame 5 = top, when hit ; frame 6 = top, when flying off ; =========================================================================== if ~~removeJmpTos JmpTo35_DisplaySprite jmp (DisplaySprite).l JmpTo52_DeleteObject jmp (DeleteObject).l JmpTo36_MarkObjGone jmp (MarkObjGone).l JmpTo5_DeleteObject2 jmp (DeleteObject2).l JmpTo6_PlaySound jmp (PlaySound).l JmpTo21_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo17_AnimateSprite jmp (AnimateSprite).l JmpTo9_Adjust2PArtPointer2 jmp (Adjust2PArtPointer2).l JmpTo3_ObjCheckFloorDist jmp (ObjCheckFloorDist).l JmpTo6_LoadPLC jmp (LoadPLC).l JmpTo3_AddPoints jmp (AddPoints).l JmpTo61_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo2_PlayLevelMusic ; play level Music jmp (PlayLevelMusic).l JmpTo2_LoadPLC_AnimalExplosion ; PLC_Explosion jmp (LoadPLC_AnimalExplosion).l JmpTo4_ObjectMoveAndFall jmp (ObjectMoveAndFall).l align 4 else JmpTo52_DeleteObject jmp (DeleteObject).l JmpTo35_DisplaySprite jmp (DisplaySprite).l endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 52 - HTZ boss ; ---------------------------------------------------------------------------- ; Sprite_2FC50: Obj52: moveq #0,d0 move.b boss_subtype(a0),d0 move.w Obj52_Index(pc,d0.w),d1 jmp Obj52_Index(pc,d1.w) ; =========================================================================== ; off_2FC5E: Obj52_Index: offsetTable offsetTableEntry.w Obj52_Init ; 0 offsetTableEntry.w Obj52_Mobile ; 2 offsetTableEntry.w Obj52_FlameThrower ; 4 offsetTableEntry.w Obj52_LavaBall ; 6 offsetTableEntry.w loc_30210 ; 8 ; =========================================================================== ; loc_2FC68: Obj52_Init: move.l #Obj52_MapUnc_302BC,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Eggpod_2,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #-$70,mainspr_width(a0) move.b #-$70,mainspr_height(a0) move.b #4,priority(a0) move.w #$3040,x_pos(a0) move.w #$580,y_pos(a0) move.b #1,objoff_2C(a0) move.b #1,mainspr_mapframe(a0) addq.b #2,boss_subtype(a0) bset #6,render_flags(a0) move.b #$32,collision_flags(a0) move.b #8,objoff_32(a0) move.w #-$E0,(Boss_Y_vel).w move.w x_pos(a0),(Boss_X_pos).w move.w y_pos(a0),(Boss_Y_pos).w clr.b objoff_14(a0) move.w x_pos(a0),sub2_x_pos(a0) move.w y_pos(a0),sub2_y_pos(a0) move.b #2,sub2_mapframe(a0) bsr.w loc_2FCEA rts ; =========================================================================== loc_2FCEA: lea (Boss_AnimationArray).w,a2 move.b #6,(a2)+ move.b #0,(a2)+ move.b #$10,(a2)+ move.b #0,(a2)+ rts ; =========================================================================== ; loc_2FD00: Obj52_Mobile: moveq #0,d0 move.b angle(a0),d0 move.w off_2FD0E(pc,d0.w),d1 jmp off_2FD0E(pc,d1.w) ; =========================================================================== off_2FD0E: offsetTable offsetTableEntry.w Obj52_Mobile_Raise ; 0 offsetTableEntry.w Obj52_Mobile_Flamethrower ; 2 offsetTableEntry.w Obj52_Mobile_BeginLower ; 4 offsetTableEntry.w Obj52_Mobile_Lower ; 6 offsetTableEntry.w Obj52_Mobile_Defeated ; 8 ; =========================================================================== ; loc_2FD18: Obj52_Mobile_Raise: move.b #0,(Boss_CollisionRoutine).w bsr.w Boss_MoveObject tst.b objoff_2C(a0) bne.s loc_2FD32 cmpi.w #$518,(Boss_Y_pos).w bgt.s loc_2FD50 bra.s loc_2FD3A ; =========================================================================== loc_2FD32: cmpi.w #$4FC,(Boss_Y_pos).w bgt.s loc_2FD50 loc_2FD3A: move.w #0,(Boss_Y_vel).w move.b #4,mapping_frame(a0) addq.b #2,angle(a0) move.b #$3C,objoff_3E(a0) loc_2FD50: move.w (Boss_Y_pos).w,y_pos(a0) bsr.w loc_300A4 if removeJmpTos JmpTo36_DisplaySprite endif jmpto (DisplaySprite).l, JmpTo36_DisplaySprite ; =========================================================================== ; loc_2FD5E: Obj52_Mobile_Flamethrower: subi_.b #1,objoff_3E(a0) bpl.s Obj52_Mobile_Hover move.b #1,(Boss_CollisionRoutine).w move.b #1,mainspr_childsprites(a0) cmpi.b #-$18,objoff_3E(a0) bne.s Obj52_Mobile_Hover jsrto (SingleObjLoad).l, JmpTo13_SingleObjLoad bne.s loc_2FDAA _move.b #ObjID_HTZBoss,id(a1) ; load obj52 move.b #4,boss_subtype(a1) move.b render_flags(a0),render_flags(a1) andi.b #1,render_flags(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b #$2F,objoff_3E(a0) loc_2FDAA: bsr.w loc_300A4 bsr.w loc_2FEDE lea (Ani_obj52).l,a1 bsr.w AnimateBoss jmpto (DisplaySprite).l, JmpTo36_DisplaySprite ; =========================================================================== ; loc_2FDC0: Obj52_Mobile_Hover: move.b mapping_frame(a0),d0 jsr (CalcSine).l asr.w #7,d1 add.w (Boss_Y_pos).w,d1 move.w d1,y_pos(a0) addq.b #4,mapping_frame(a0) bra.s loc_2FDAA ; =========================================================================== ; loc_2FDDA: Obj52_Mobile_BeginLower: move.b #0,(Boss_CollisionRoutine).w move.b #0,mainspr_childsprites(a0) move.b #$10,(Boss_AnimationArray+2).w move.b #0,(Boss_AnimationArray+3).w subi_.b #1,objoff_3E(a0) bne.w Obj52_Mobile_Hover move.w #$E0,(Boss_Y_vel).w addq.b #2,angle(a0) bsr.w loc_2FEDE jmpto (DisplaySprite).l, JmpTo36_DisplaySprite ; =========================================================================== ; loc_2FE0E: Obj52_Mobile_Lower: bsr.w Boss_MoveObject tst.b objoff_2C(a0) bne.s loc_2FE22 cmpi.w #$538,(Boss_Y_pos).w blt.s loc_2FE58 bra.s Obj52_CreateLavaBall ; =========================================================================== loc_2FE22: cmpi.w #$548,(Boss_Y_pos).w blt.s loc_2FE58 ; loc_2FE2A Obj52_CreateLavaBall: tst.b objoff_38(a0) bne.s loc_2FE58 st objoff_38(a0) jsrto (SingleObjLoad).l, JmpTo13_SingleObjLoad bne.s loc_2FE58 move.b #ObjID_HTZBoss,id(a1) ; load obj52 move.b #6,boss_subtype(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b #SndID_LavaBall,d0 jsrto (PlaySound).l, JmpTo7_PlaySound loc_2FE58: tst.b objoff_2C(a0) bne.s loc_2FE6E cmpi.w #$5A0,(Boss_Y_pos).w blt.s loc_2FED0 move.w #$5A0,(Boss_Y_pos).w bra.s loc_2FE7C ; =========================================================================== loc_2FE6E: cmpi.w #$580,(Boss_Y_pos).w blt.s loc_2FED0 move.w #$580,(Boss_Y_pos).w loc_2FE7C: move.w #-$E0,(Boss_Y_vel).w move.b #0,angle(a0) sf objoff_38(a0) move.w (MainCharacter+x_pos).w,d0 subi.w #$2FC0,d0 bmi.s loc_2FEA8 move.w #$580,(Boss_Y_pos).w move.w #$3040,x_pos(a0) st objoff_2C(a0) bra.s loc_2FEB8 ; =========================================================================== loc_2FEA8: move.w #$2F40,x_pos(a0) move.w #$5A0,(Boss_Y_pos).w sf objoff_2C(a0) loc_2FEB8: move.w x_pos(a0),d0 cmp.w (MainCharacter+x_pos).w,d0 bgt.s loc_2FECA bset #0,render_flags(a0) bra.s loc_2FED0 ; =========================================================================== loc_2FECA: bclr #0,render_flags(a0) loc_2FED0: move.w (Boss_Y_pos).w,y_pos(a0) bsr.w loc_300A4 jmpto (DisplaySprite).l, JmpTo36_DisplaySprite ; =========================================================================== loc_2FEDE: move.w x_pos(a0),d0 move.w y_pos(a0),d1 move.w d0,sub2_x_pos(a0) move.w d1,sub2_y_pos(a0) rts ; =========================================================================== ; loc_2FEF0: Obj52_FlameThrower: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_2FEFE(pc,d0.w),d1 jmp off_2FEFE(pc,d1.w) ; =========================================================================== off_2FEFE: offsetTable offsetTableEntry.w loc_2FF02 ; 0 offsetTableEntry.w loc_2FF50 ; 2 ; =========================================================================== loc_2FF02: move.l #Obj52_MapUnc_302BC,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_HTZBoss,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #4,priority(a0) addq.b #2,routine_secondary(a0) move.b #5,anim(a0) move.b #$98,collision_flags(a0) subi.w #$1C,y_pos(a0) move.w #-$70,d0 move.w #-4,d1 btst #0,render_flags(a0) beq.s loc_2FF46 neg.w d0 neg.w d1 loc_2FF46: add.w d0,x_pos(a0) move.w d1,x_vel(a0) rts ; =========================================================================== loc_2FF50: move.w x_vel(a0),d1 add.w d1,x_pos(a0) lea (Ani_obj52).l,a1 jsrto (AnimateSprite).l, JmpTo18_AnimateSprite jmpto (MarkObjGone).l, JmpTo37_MarkObjGone ; =========================================================================== ; loc_2FF66: Obj52_LavaBall: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_2FF74(pc,d0.w),d1 jmp off_2FF74(pc,d1.w) ; =========================================================================== off_2FF74: offsetTable offsetTableEntry.w loc_2FF78 ; 0 offsetTableEntry.w loc_30008 ; 2 ; =========================================================================== loc_2FF78: movea.l a0,a1 moveq #0,d2 moveq #1,d1 bra.s loc_2FF94 ; =========================================================================== loc_2FF80: jsrto (SingleObjLoad).l, JmpTo13_SingleObjLoad bne.w return_30006 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) loc_2FF94: move.b #ObjID_HTZBoss,id(a1) ; load obj52 move.b #6,boss_subtype(a1) move.l #Obj52_MapUnc_302BC,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_HTZBoss,0,0),art_tile(a1) ori.b #4,render_flags(a1) move.b #3,priority(a1) addq.b #2,routine_secondary(a1) move.b #7,anim(a1) move.b #$8B,collision_flags(a1) move.b d2,objoff_2E(a1) move.b #8,y_radius(a1) move.b #8,x_radius(a1) move.w x_pos(a1),objoff_2A(a1) move.w #$1C00,d0 tst.w d2 bne.s loc_2FFE8 neg.w d0 loc_2FFE8: move.w d0,x_vel(a1) move.w #-$5400,y_vel(a1) cmpi.w #$2F40,x_pos(a1) beq.s loc_30000 move.w #-$6400,y_vel(a1) loc_30000: addq.w #1,d2 dbf d1,loc_2FF80 return_30006: rts ; =========================================================================== loc_30008: bsr.w Obj52_LavaBall_Move jsrto (ObjCheckFloorDist).l, JmpTo4_ObjCheckFloorDist tst.w d1 bpl.s loc_30064 add.w d1,y_pos(a0) move.b #ObjID_LavaBubble,id(a0) ; load 0bj20 move.b #$A,routine(a0) move.b #2,anim(a0) move.b #4,mapping_frame(a0) move.w #0,y_vel(a0) move.l #Obj20_MapUnc_23294,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_Buzzer_Fireball_1,0,1),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo62_Adjust2PArtPointer move.b #0,mapping_frame(a0) move.w #9,objoff_32(a0) move.b #3,objoff_36(a0) move.b #SndID_FireBurn,d0 jsrto (PlaySound).l, JmpTo7_PlaySound jmpto (Obj20).l, JmpTo_Obj20 ; =========================================================================== loc_30064: lea (Ani_obj52).l,a1 jsrto (AnimateSprite).l, JmpTo18_AnimateSprite jmpto (MarkObjGone).l, JmpTo37_MarkObjGone ; =========================================================================== ; loc_30072: Obj52_LavaBall_Move: move.l objoff_2A(a0),d2 move.l y_pos(a0),d3 move.w x_vel(a0),d0 ext.l d0 asl.l #4,d0 add.l d0,d2 move.w y_vel(a0),d0 addi.w #$380,y_vel(a0) ext.l d0 asl.l #4,d0 add.l d0,d3 move.l d2,objoff_2A(a0) move.l d3,y_pos(a0) move.w objoff_2A(a0),x_pos(a0) rts ; =========================================================================== loc_300A4: cmpi.b #8,angle(a0) bhs.s return_300EA tst.b objoff_32(a0) beq.s Obj52_Defeat tst.b collision_flags(a0) bne.s return_300EA tst.b objoff_14(a0) bne.s loc_300CE move.b #$20,objoff_14(a0) move.w #SndID_BossHit,d0 jsr (PlaySound).l loc_300CE: lea (Normal_palette_line2+2).w,a1 moveq #0,d0 tst.w (a1) bne.s loc_300DC move.w #$EEE,d0 loc_300DC: move.w d0,(a1) subq.b #1,objoff_14(a0) bne.s return_300EA move.b #$32,collision_flags(a0) return_300EA: rts ; =========================================================================== ; loc_300EC: Obj52_Defeat: moveq #100,d0 jsrto (AddPoints).l, JmpTo4_AddPoints move.w #$B3,(Boss_Countdown).w move.b #8,angle(a0) moveq #PLCID_Capsule,d0 jsrto (LoadPLC).l, JmpTo7_LoadPLC rts ; =========================================================================== ; loc_30106: Obj52_Mobile_Defeated: move.b #0,mainspr_childsprites(a0) subi_.w #1,(Boss_Countdown).w bmi.s loc_30142 cmpi.w #$1E,(Boss_Countdown).w bgt.s Obj52_Mobile_UpdateExplosion move.b #$10,mainspr_mapframe(a0) bsr.w Boss_LoadExplosion move.b (Vint_runcount+3).w,d0 andi.b #$1F,d0 bne.w JmpTo36_DisplaySprite bsr.w Obj52_CreateSmoke jmpto (DisplaySprite).l, JmpTo36_DisplaySprite ; =========================================================================== ; loc_3013A: Obj52_Mobile_UpdateExplosion: bsr.w Boss_LoadExplosion jmpto (DisplaySprite).l, JmpTo36_DisplaySprite ; =========================================================================== loc_30142: move.b (Vint_runcount+3).w,d0 andi.b #$1F,d0 bne.w Obj52_Mobile_Flee bsr.w Obj52_CreateSmoke ; loc_30152: Obj52_Mobile_Flee: cmpi.w #-$3C,(Boss_Countdown).w bgt.w JmpTo36_DisplaySprite tst.b (Boss_defeated_flag).w bne.s loc_30170 jsrto (PlayLevelMusic).l, JmpTo3_PlayLevelMusic jsrto (LoadPLC_AnimalExplosion).l, JmpTo3_LoadPLC_AnimalExplosion move.b #1,(Boss_defeated_flag).w loc_30170: addq.w #2,y_pos(a0) cmpi.w #$3160,(Camera_Max_X_pos).w bhs.s loc_30182 addq.w #2,(Camera_Max_X_pos).w bra.s BranchTo_JmpTo36_DisplaySprite ; =========================================================================== loc_30182: tst.b render_flags(a0) bpl.s loc_301AA tst.b objoff_2C(a0) bne.s loc_3019C cmpi.w #$578,y_pos(a0) bgt.w loc_301AA jmpto (DisplaySprite).l, JmpTo36_DisplaySprite ; =========================================================================== loc_3019C: cmpi.w #$588,y_pos(a0) bgt.w loc_301AA BranchTo_JmpTo36_DisplaySprite jmpto (DisplaySprite).l, JmpTo36_DisplaySprite ; =========================================================================== loc_301AA: move.w #$3160,(Camera_Max_X_pos).w if removeJmpTos JmpTo53_DeleteObject endif jmpto (DeleteObject).l, JmpTo53_DeleteObject ; =========================================================================== ; loc_301B4: Obj52_CreateSmoke jsrto (SingleObjLoad).l, JmpTo13_SingleObjLoad bne.s return_3020E move.b #ObjID_HTZBoss,id(a1) ; load obj52 move.b #8,boss_subtype(a1) move.l #Obj52_MapUnc_30258,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_BossSmoke_2,0,0),art_tile(a1) ori.b #4,render_flags(a1) move.b #1,priority(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w x_pos(a0),objoff_2A(a1) subi.w #$28,y_pos(a1) move.w #-$60,x_vel(a1) move.w #-$C0,y_vel(a1) move.b #0,mapping_frame(a1) move.b #$11,anim_frame_duration(a1) return_3020E: rts ; =========================================================================== loc_30210: subq.b #1,anim_frame_duration(a0) bpl.s loc_3022A move.b #$11,anim_frame_duration(a0) addq.b #1,mapping_frame(a0) cmpi.b #4,mapping_frame(a0) beq.w JmpTo53_DeleteObject loc_3022A: move.l objoff_2A(a0),d2 move.l y_pos(a0),d3 move.w x_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d2 move.w y_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d3 move.l d2,objoff_2A(a0) move.w objoff_2A(a0),x_pos(a0) move.l d3,y_pos(a0) jmpto (DisplaySprite).l, JmpTo36_DisplaySprite ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings - uses ArtNem_BossSmoke ; ---------------------------------------------------------------------------- Obj52_MapUnc_30258: BINCLUDE "mappings/sprite/obj52_a.bin" ; animation script ; off_30288: Ani_obj52: offsetTable offsetTableEntry.w byte_30298 ; 0 offsetTableEntry.w byte_3029D ; 1 offsetTableEntry.w byte_302A2 ; 2 offsetTableEntry.w byte_302A7 ; 3 offsetTableEntry.w byte_302AC ; 4 offsetTableEntry.w byte_302B0 ; 5 offsetTableEntry.w byte_302B4 ; 6 offsetTableEntry.w byte_302B7 ; 7 byte_30298: dc.b 1, 2, 3,$FD, 1 rev02even byte_3029D: dc.b 2, 4, 5,$FD, 2 rev02even byte_302A2: dc.b 3, 6, 7,$FD, 3 rev02even byte_302A7: dc.b 4, 8, 9,$FD, 4 rev02even byte_302AC: dc.b 5, $A, $B,$FE rev02even byte_302B0: dc.b 3, $C, $D,$FF rev02even byte_302B4: dc.b $F, 1,$FF rev02even byte_302B7: dc.b 3, $E, $F,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings - uses ArtNem_Eggpod + ? ; ---------------------------------------------------------------------------- Obj52_MapUnc_302BC: BINCLUDE "mappings/sprite/obj52_b.bin" if ~~removeJmpTos align 4 endif ; =========================================================================== if ~~removeJmpTos JmpTo36_DisplaySprite jmp (DisplaySprite).l JmpTo53_DeleteObject jmp (DeleteObject).l JmpTo13_SingleObjLoad jmp (SingleObjLoad).l JmpTo37_MarkObjGone jmp (MarkObjGone).l JmpTo7_PlaySound jmp (PlaySound).l JmpTo18_AnimateSprite jmp (AnimateSprite).l JmpTo4_ObjCheckFloorDist jmp (ObjCheckFloorDist).l JmpTo7_LoadPLC jmp (LoadPLC).l JmpTo_Obj20 jmp (Obj20).l JmpTo4_AddPoints jmp (AddPoints).l JmpTo62_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo3_PlayLevelMusic jmp (PlayLevelMusic).l JmpTo3_LoadPLC_AnimalExplosion jmp (LoadPLC_AnimalExplosion).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 89 - ARZ boss ; ---------------------------------------------------------------------------- ; OST Variables: ; Main Vehicle obj89_hammer_y_vel = objoff_2E ; falling hammer's y velocity obj89_target = objoff_38 obj89_hammer_y_pos = objoff_3A ; falling hammer's y position obj89_hammer_flags = objoff_3E ; Pillars & Arrows obj89_pillar_parent = objoff_2A ; address of main vehicle obj89_pillar_shake_time = objoff_30 obj89_pillar_shaking = objoff_38 obj89_eyes_timer = objoff_30 obj89_arrow_routine = objoff_2A obj89_arrow_timer = objoff_30 obj89_arrow_parent2 = objoff_34 obj89_arrow_parent = objoff_38 ; address of main vehicle ; Sprite_30480: Obj89: moveq #0,d0 move.b boss_subtype(a0),d0 move.w Obj89_Index(pc,d0.w),d1 jmp Obj89_Index(pc,d1.w) ; =========================================================================== ; off_3048E: Obj89_Index: offsetTable offsetTableEntry.w Obj89_Init ; 0 - Init offsetTableEntry.w Obj89_Main ; 2 - Main Vehicle offsetTableEntry.w Obj89_Pillar ; 4 - Pillars & Arrows ; =========================================================================== ; loc_30494: Obj89_Init: tst.l (Plc_Buffer).w ; is art finished loading? beq.s + ; if yes, branch rts ; --------------------------------------------------------------------------- + tst.w (Player_mode).w ; is player mode anything other than Sonic & Tails? bne.s Obj89_Init_RaisePillars ; if yes, branch move.w (MainCharacter+x_pos).w,d0 cmpi.w #$2A60,d0 ; is Sonic too close to the left edge? blt.w Obj89_Init_Standard ; if yes, branch cmpi.w #$2B60,d0 ; is Sonic too close to the right edge? bgt.w Obj89_Init_Standard ; if yes, branch cmpi.b #$81,(Sidekick+obj_control).w beq.w Obj89_Init_RaisePillars ; branch, if Tails is flying move.w (Sidekick+x_pos).w,d0 cmpi.w #$2A60,d0 ; is Tails too close to the left edge? blt.w Obj89_Init_Standard ; if yes, branch cmpi.w #$2B60,d0 ; is Tails too close to the right edge? bgt.w Obj89_Init_Standard ; if yes, branch ; loc_304D4: Obj89_Init_RaisePillars: move.b #1,(Screen_Shaking_Flag).w ; make screen shake move.w #make_art_tile(ArtTile_ArtNem_ARZBoss,0,0),art_tile(a0) move.l #Obj89_MapUnc_30E04,mappings(a0) ori.b #4,render_flags(a0) move.b #$20,mainspr_width(a0) move.b #2,priority(a0) move.b #2,boss_subtype(a0) ; => Obj89_Main move.w #$2AE0,x_pos(a0) move.w #$388,y_pos(a0) move.w #$2AE0,(Boss_X_pos).w move.w #$388,(Boss_Y_pos).w bset #6,render_flags(a0) move.b #3,mainspr_childsprites(a0) move.b #$F,collision_flags(a0) move.b #8,boss_hitcount2(a0) move.b #8,mainspr_mapframe(a0) move.w #-$380,obj89_hammer_y_vel(a0) clr.b (Boss_CollisionRoutine).w ; disable special collisions move.w #$2AE0,sub2_x_pos(a0) ; move.w #$488,sub2_y_pos(a0) move.b #0,sub2_mapframe(a0) move.w #$2AE0,sub3_x_pos(a0) ; move.w #$488,sub3_y_pos(a0) move.b #9,sub3_mapframe(a0) move.w #$2AE0,sub4_x_pos(a0) ; move.w #$488,sub4_y_pos(a0) move.b #6,sub4_mapframe(a0) move.w #$100,(Boss_Y_vel).w ; load first pillar object jsrto (SingleObjLoad).l, JmpTo14_SingleObjLoad bne.w Obj89_Init_Standard move.b #ObjID_ARZBoss,id(a1) ; load obj89 move.l #Obj89_MapUnc_30D68,mappings(a1) ori.b #4,render_flags(a1) move.w #make_art_tile(ArtTile_ArtNem_ARZBoss,0,0),art_tile(a1) move.b #$10,width_pixels(a1) move.b #4,priority(a1) move.w #$2A50,x_pos(a1) move.w #$510,y_pos(a1) addq.b #4,boss_subtype(a1) ; => Obj89_Pillar move.l a0,obj89_pillar_parent(a1) move.b #0,mapping_frame(a1) move.b #2,priority(a1) move.b #$20,y_radius(a1) movea.l a1,a2 ; save first pillar's address jsrto (SingleObjLoad2).l, JmpTo22_SingleObjLoad2 bne.s Obj89_Init_Standard moveq #0,d0 move.w #bytesToLcnt(object_size),d1 ; loc_305DC: Obj89_Init_DuplicatePillar: move.l (a2,d0.w),(a1,d0.w) addq.w #4,d0 dbf d1,Obj89_Init_DuplicatePillar if object_size&3 move.w (a2,d0.w),(a1,d0.w) endif bset #0,render_flags(a1) move.w #$2B70,x_pos(a1) ; move pillar to other side of boss area ; loc_305F4: Obj89_Init_Standard: bsr.w Obj89_Init_AnimationArray rts ; =========================================================================== ; loc_305FA: Obj89_Init_AnimationArray: lea (Boss_AnimationArray).w,a2 move.b #4,(a2)+ ; main vehicle move.b #0,(a2)+ move.b #0,(a2)+ ; face move.b #0,(a2)+ move.b #2,(a2)+ ; hammer move.b #0,(a2)+ move.b #1,(a2)+ ; flames move.b #0,(a2)+ rts ; =========================================================================== ; loc_30620: Obj89_Main: moveq #0,d0 move.b boss_routine(a0),d0 move.w Obj89_Main_Index(pc,d0.w),d1 jmp Obj89_Main_Index(pc,d1.w) ; =========================================================================== ; off_3062E: Obj89_Main_Index: offsetTable ; main boss object offsetTableEntry.w Obj89_Main_Sub0 ; 0 - moving down into arena offsetTableEntry.w Obj89_Main_Sub2 ; 2 - moving left/right offsetTableEntry.w Obj89_Main_Sub4 ; 4 - having reached pillar offsetTableEntry.w Obj89_Main_Sub6 ; 6 - hit with hammer offsetTableEntry.w Obj89_Main_Sub8 ; 8 - boss exploding offsetTableEntry.w Obj89_Main_SubA ; A - move boss down and alter a little up again offsetTableEntry.w Obj89_Main_SubC ; C - beaten boss moving away ; =========================================================================== ; loc_3063C: Obj89_Main_Sub0: bsr.w Boss_MoveObject bsr.w Obj89_Main_HandleFace bsr.w Obj89_Main_AlignParts cmpi.w #$430,(Boss_Y_pos).w ; has boss reached its target? blt.s Obj89_Main_Sub0_Standard ; if not, branch move.w #$430,(Boss_Y_pos).w addi_.b #2,boss_routine(a0) ; => Obj89_Main_Sub2 move.w #0,(Boss_Y_vel).w ; stop y movement move.w #-$C8,(Boss_X_vel).w ; move leftward st obj89_target(a0) ; loc_3066C: Obj89_Main_Sub0_Standard: lea (Ani_obj89_b).l,a1 bsr.w AnimateBoss jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== ; loc_3067A: Obj89_Main_Sub2: bsr.w Boss_MoveObject bsr.w Obj89_Main_HandleFace bsr.w Obj89_Main_AlignParts tst.b obj89_target(a0) ; is boss going left? bne.s Obj89_Main_Sub2_GoingLeft ; if yes, branch cmpi.w #$2B10,(Boss_X_pos).w ; is boss right in front of the right pillar? blt.s Obj89_Main_Sub2_Standard ; branch, if still too far away bra.s Obj89_Main_Sub2_AtTarget ; =========================================================================== ; loc_30696: Obj89_Main_Sub2_GoingLeft: cmpi.w #$2AB0,(Boss_X_pos).w ; is boss right in front of the left pillar? bgt.s Obj89_Main_Sub2_Standard ; branch, if still too far away ; loc_3069E: Obj89_Main_Sub2_AtTarget: addi_.b #2,boss_routine(a0) ; => Obj89_Main_Sub4 move.w #0,(Boss_X_vel).w ; loc_306AA: Obj89_Main_Sub2_Standard: lea (Ani_obj89_b).l,a1 bsr.w AnimateBoss jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== ; loc_306B8: Obj89_Main_Sub4: bsr.w Boss_MoveObject bsr.w Obj89_Main_HandleFace bsr.w Obj89_Main_AlignParts cmpi.b #-$40,boss_sine_count(a0) ; has boss reached the right height in its hovering animation? bne.s Obj89_Main_Sub4_Standard ; if not, branch lea (Boss_AnimationArray).w,a1 andi.b #$F0,2*2(a1) ; reset hammer animation ori.b #3,2*2(a1) ; reset hammer animation timer addq.b #2,boss_routine(a0) ; => Obj89_Main_Sub6 btst #0,render_flags(a0) sne obj89_target(a0) ; target opposite side move.w #$1E,(Boss_Countdown).w move.b #SndID_Hammer,d0 jsrto (PlaySound).l, JmpTo8_PlaySound ; loc_306F8: Obj89_Main_Sub4_Standard: lea (Ani_obj89_b).l,a1 bsr.w AnimateBoss jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== ; loc_30706: Obj89_Main_Sub6: cmpi.w #$14,(Boss_Countdown).w ; has counter reached a specific value? bne.s + ; if not, branch bset #0,obj89_hammer_flags(a0) ; hammer just hit a pillar move.b #1,(Boss_CollisionRoutine).w ; enable hammer collision + subi_.w #1,(Boss_Countdown).w ; decrement counter bpl.s Obj89_Main_Sub6_Standard ; branch, if counter > 0 clr.b (Boss_CollisionRoutine).w ; disable hammer collision move.b #2,boss_routine(a0) ; => Obj89_Main_Sub2 bchg #0,render_flags(a0) ; face opposite direction beq.s Obj89_Main_Sub6_MoveRight ; branch, if new direction is right move.w #-$C8,(Boss_X_vel).w ; move left bra.s Obj89_Main_Sub6_Standard ; =========================================================================== ; loc_3073C: Obj89_Main_Sub6_MoveRight: move.w #$C8,(Boss_X_vel).w ; move right ; loc_30742: Obj89_Main_Sub6_Standard: bsr.w Boss_MoveObject bsr.w Obj89_Main_HandleFace bsr.w Obj89_Main_AlignParts lea (Ani_obj89_b).l,a1 bsr.w AnimateBoss jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== ; loc_3075C: Obj89_Main_HandleFace: bsr.w Obj89_Main_HandleHoveringAndHits cmpi.b #4,(MainCharacter+routine).w ; is Sonic hurt? beq.s Obj89_Main_Laugh ; if yes, branch cmpi.b #4,(Sidekick+routine).w ; is Tails hurt? bne.s Obj89_Main_ChkHurt ; if not, branch ; loc_30770: Obj89_Main_Laugh: lea (Boss_AnimationArray).w,a1 move.b #$31,1*2+1(a1) ; use laughing animation ; loc_3077A: Obj89_Main_ChkHurt: cmpi.b #$3F,boss_invulnerable_time(a0) ; was boss hurt? bne.s return_3078C ; if not, branch lea (Boss_AnimationArray).w,a1 move.b #-$40,1*2+1(a1) ; use hurt animation return_3078C: rts ; =========================================================================== ; loc_3078E: Obj89_Main_HandleHoveringAndHits: move.b boss_sine_count(a0),d0 jsr (CalcSine).l asr.w #6,d0 add.w (Boss_Y_pos).w,d0 move.w d0,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) addq.b #2,boss_sine_count(a0) cmpi.b #8,boss_routine(a0) ; has boss been defeated? bhs.s return_307F2 ; if yes, branch tst.b boss_hitcount2(a0) ; has boss run out of hits? beq.s Obj89_Main_KillBoss ; if yes, branch tst.b collision_flags(a0) ; are boss's collisions enabled? bne.s return_307F2 ; if yes, branch tst.b boss_invulnerable_time(a0) ; is boss invulnerable? bne.s Obj89_Main_Flash ; if yes, branch move.b #$40,boss_invulnerable_time(a0) ; make boss invulnerable move.w #SndID_BossHit,d0 ; play "boss hit" sound jsr (PlaySound).l ; loc_307D6: Obj89_Main_Flash: lea (Normal_palette_line2+2).w,a1 moveq #0,d0 ; 0000 = black tst.w (a1) ; is current color black? bne.s + ; if not, branch move.w #$EEE,d0 ; 0EEE = white + move.w d0,(a1) ; set color subq.b #1,boss_invulnerable_time(a0) bne.s return_307F2 ; branch, if invulnerability hasn't run out move.b #$F,collision_flags(a0) ; restore collisions return_307F2: rts ; =========================================================================== ; loc_307F4: Obj89_Main_KillBoss: moveq #100,d0 jsrto (AddPoints).l, JmpTo5_AddPoints move.w #$B3,(Boss_Countdown).w ; set timer move.b #8,boss_routine(a0) ; => Obj89_Main_Sub8 lea (Boss_AnimationArray).w,a1 move.b #5,1*2(a1) ; use defeated animation move.b #0,1*2+1(a1) ; reset animation moveq #PLCID_Capsule,d0 jsrto (LoadPLC).l, JmpTo8_LoadPLC move.b #5,sub2_mapframe(a0) rts ; =========================================================================== ; loc_30824: Obj89_Main_AlignParts: move.w x_pos(a0),d0 move.w y_pos(a0),d1 move.w d0,sub2_x_pos(a0) move.w d1,sub2_y_pos(a0) move.w d0,sub4_x_pos(a0) move.w d1,sub4_y_pos(a0) tst.b boss_defeated(a0) bne.s Obj89_Main_DropHammer ; branch, if boss was defeated move.w d0,sub3_x_pos(a0) move.w d1,sub3_y_pos(a0) move.w d1,obj89_hammer_y_pos(a0) rts ; =========================================================================== ; loc_30850: Obj89_Main_DropHammer: cmpi.w #$78,(Boss_Countdown).w bgt.s return_3088A ; wait until timer is below $78 subi_.w #1,sub3_x_pos(a0) ; make hammer move left move.l obj89_hammer_y_pos(a0),d0 move.w obj89_hammer_y_vel(a0),d1 addi.w #$38,obj89_hammer_y_vel(a0) ; add gravity ext.l d1 asl.l #8,d1 add.l d1,d0 move.l d0,obj89_hammer_y_pos(a0) ; update position move.w obj89_hammer_y_pos(a0),sub3_y_pos(a0) cmpi.w #$540,sub3_y_pos(a0) ; has the hammer reached the bottom? blt.s return_3088A ; if not, branch move.w #0,obj89_hammer_y_vel(a0) ; else, make hammer invisible return_3088A: rts ; =========================================================================== ; loc_3088C: Obj89_Main_Sub8: st boss_defeated(a0) subq.w #1,(Boss_Countdown).w bmi.s Obj89_Main_SetupEscapeAnim bsr.w Boss_LoadExplosion bra.s Obj89_Main_Sub8_Standard ; =========================================================================== ; loc_3089C: Obj89_Main_SetupEscapeAnim: move.b #3,mainspr_childsprites(a0) lea (Boss_AnimationArray).w,a2 move.b #1,2*2(a2) ; hammer move.b #0,2*2+1(a2) move.b #0,1*2(a2) ; face move.b #0,1*2+1(a2) bset #0,render_flags(a0) clr.w (Boss_X_vel).w ; stop movement clr.w (Boss_Y_vel).w addq.b #2,boss_routine(a0) ; => Obj89_Main_SubA move.w #-$12,(Boss_Countdown).w ; loc_308D6: Obj89_Main_Sub8_Standard: move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) lea (Ani_obj89_b).l,a1 bsr.w AnimateBoss bsr.w Obj89_Main_AlignParts jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== ; loc_308F4: Obj89_Main_SubA: addq.w #1,(Boss_Countdown).w ; note: countdown starts out as -$12 beq.s Obj89_Main_SubA_StopFall ; branch, if countdown reached 0 bpl.s Obj89_Main_SubA_Phase2 ; branch, if falling phase is over addi.w #$18,(Boss_Y_vel).w ; else, make boss fall bra.s Obj89_Main_SubA_Standard ; =========================================================================== ; loc_30904: Obj89_Main_SubA_StopFall: clr.w (Boss_Y_vel).w ; stop fall bra.s Obj89_Main_SubA_Standard ; =========================================================================== ; loc_3090A: Obj89_Main_SubA_Phase2: cmpi.w #$18,(Boss_Countdown).w blo.s Obj89_Main_SubA_Ascend beq.s Obj89_Main_SubA_StopAscent cmpi.w #$20,(Boss_Countdown).w blo.s Obj89_Main_SubA_Standard addq.b #2,boss_routine(a0) ; => Obj89_Main_SubC bra.s Obj89_Main_SubA_Standard ; =========================================================================== ; loc_30922: Obj89_Main_SubA_Ascend: subi_.w #8,(Boss_Y_vel).w ; ascend slowly bra.s Obj89_Main_SubA_Standard ; =========================================================================== ; loc_3092A: Obj89_Main_SubA_StopAscent: clr.w (Boss_Y_vel).w ; stop ascent jsrto (PlayLevelMusic).l, JmpTo4_PlayLevelMusic jsrto (LoadPLC_AnimalExplosion).l, JmpTo4_LoadPLC_AnimalExplosion ; loc_30936: Obj89_Main_SubA_Standard: bsr.w Boss_MoveObject bsr.w Obj89_Main_HandleHoveringAndHits move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) lea (Ani_obj89_b).l,a1 bsr.w AnimateBoss bsr.w Obj89_Main_AlignParts jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== ; loc_3095C: Obj89_Main_SubC: move.w #$400,(Boss_X_vel).w move.w #-$40,(Boss_Y_vel).w cmpi.w #$2C00,(Camera_Max_X_pos).w ; has camera reached its target position? bhs.s Obj89_Main_SubC_ChkDelete ; if yes, branch addq.w #2,(Camera_Max_X_pos).w ; else, move camera bra.s Obj89_Main_SubC_Standard ; =========================================================================== ; loc_30976: Obj89_Main_SubC_ChkDelete: tst.b render_flags(a0) ; is boss still visible? bpl.s JmpTo54_DeleteObject ; if not, branch ; loc_3097C: Obj89_Main_SubC_Standard: bsr.w Boss_MoveObject bsr.w Obj89_Main_HandleHoveringAndHits move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) lea (Ani_obj89_b).l,a1 bsr.w AnimateBoss bsr.w Obj89_Main_AlignParts jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== JmpTo54_DeleteObject jmp (DeleteObject).l ; =========================================================================== ; loc_309A8: Obj89_Pillar: moveq #0,d0 movea.l obj89_pillar_parent(a0),a1 ; a1=object cmpi.b #8,boss_routine(a1) ; has boss been defeated? blt.s Obj89_Pillar_Normal ; if not, branch move.b #4,routine_secondary(a0) ; loc_309BC: Obj89_Pillar_Normal: move.b routine_secondary(a0),d0 move.w Obj89_Pillar_Index(pc,d0.w),d1 jmp Obj89_Pillar_Index(pc,d1.w) ; =========================================================================== ; off_309C8: Obj89_Pillar_Index: offsetTable ; pillar/arrow object offsetTableEntry.w Obj89_Pillar_Sub0 ; 0 - raise pillars offsetTableEntry.w Obj89_Pillar_Sub2 ; 2 - pillars shaking(?) offsetTableEntry.w Obj89_Pillar_Sub4 ; 4 - move pillars down offsetTableEntry.w Obj89_Arrow ; 6 - arrow offsetTableEntry.w Obj89_Pillar_BulgingEyes ; 8 - pillar normal (standing) ; =========================================================================== ; loc_309D2: Obj89_Pillar_Sub0: bsr.w Obj89_Pillar_SolidObject move.b (Vint_runcount+3).w,d0 andi.b #$1F,d0 bne.s + move.w #SndID_Rumbling2,d0 ; play rumbling sound every 32 frames jsrto (PlaySound).l, JmpTo8_PlaySound + subi_.w #1,y_pos(a0) ; raise pillar cmpi.w #$488,y_pos(a0) ; has pillar reached its target height? bgt.s BranchTo_JmpTo37_DisplaySprite ; if not, branch addq.b #2,routine_secondary(a0) ; => Obj89_Pillar_Sub2 move.b #0,(Screen_Shaking_Flag).w ; stop screen shaking BranchTo_JmpTo37_DisplaySprite jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== ; loc_30A04: Obj89_Pillar_Sub2: ; note: the boss switches targets before bit 0 of obj89_hammer_flags is set. In other ; words, it's always the pillar facing the new target that fires. bsr.w Obj89_Pillar_SolidObject movea.l obj89_pillar_parent(a0),a3 ; a3=object btst #0,obj89_hammer_flags(a3) beq.s Obj89_Pillar_Sub2_Standard ; branch, if hammer hasn't hit a pillar tst.b obj89_target(a3) ; is boss targeting the right? beq.s Obj89_Pillar_Sub2_RightPillar ; if yes, branch btst #0,render_flags(a0) ; is pillar facing left? beq.s Obj89_Pillar_Sub2_Standard ; if not, branch bra.s loc_30A2C ; =========================================================================== ; loc_30A24: Obj89_Pillar_Sub2_RightPillar: btst #0,render_flags(a0) ; is pillar facing right? bne.s Obj89_Pillar_Sub2_Standard ; if not, branch loc_30A2C: bclr #0,obj89_hammer_flags(a3) ; clear "hitting-pillar" flag bsr.w Obj89_Pillar_Shoot ; shoot an arrow st obj89_pillar_shaking(a0) ; make pillar shake ; loc_30A3A: Obj89_Pillar_Sub2_Standard: bsr.w Obj89_Pillar_ChkShake jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== ; loc_30A42: Obj89_Pillar_ChkShake: tst.b obj89_pillar_shaking(a0) ; is pillar shaking? beq.s return_30AAE ; if not, branch tst.w obj89_pillar_shake_time(a0) ; has timer been set? bgt.s + ; if yes, branch move.w #$1F,obj89_pillar_shake_time(a0); else, initialize timer + subi_.w #1,obj89_pillar_shake_time(a0) bgt.s Obj89_Pillar_Shake ; branch, if timer hasn't expired sf obj89_pillar_shaking(a0) ; stop shaking move.w #0,obj89_pillar_shake_time(a0) ; clear timer tst.b obj89_target(a3) ; is boss targeting the left? bne.s + ; if yes, branch move.w #$2A50,x_pos(a0) ; reset x position of left pillar bra.s Obj89_Pillar_Sub2_End ; =========================================================================== + move.w #$2B70,x_pos(a0) ; reset x position of right pillar ; loc_30A7A: Obj89_Pillar_Sub2_End: move.w #$488,y_pos(a0) ; reset y position bra.s return_30AAE ; =========================================================================== ; loc_30A82: Obj89_Pillar_Shake: move.w #$2A50,d1 ; load left pillar's default x position tst.b obj89_target(a3) ; is boss targeting the left beq.s + ; if not, branch move.w #$2B70,d1 ; load right pillar's default x position + move.b (Vint_runcount+3).w,d0 andi.w #1,d0 add.w d0,d0 add.w Obj89_Pillar_ShakeOffsets(pc,d0.w),d1 move.w d1,x_pos(a0) ; add offset to x position move.w #$488,d1 ; load pillar's default y position add.w Obj89_Pillar_ShakeOffsets(pc,d0.w),d1 move.w d1,y_pos(a0) ; add offset to y position return_30AAE: rts ; =========================================================================== ; word_30AB0: Obj89_Pillar_ShakeOffsets: dc.w 1 ; 0 dc.w -1 ; 1 ; =========================================================================== ; loc_30AB4: Obj89_Pillar_Shoot: jsrto (SingleObjLoad).l, JmpTo14_SingleObjLoad bne.w return_30B40 _move.b #ObjID_ARZBoss,id(a1) ; load obj89 move.b #4,boss_subtype(a1) move.b #8,routine_secondary(a1) ; => Obj89_Pillar_BulgingEyes move.l #Obj89_MapUnc_30D68,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_ARZBoss,0,0),art_tile(a1) ori.b #4,render_flags(a1) moveq #0,d6 move.b #2,mapping_frame(a1) move.w #$2A6A,x_pos(a1) ; align with left pillar tst.b obj89_target(a3) ; is boss targeting the right? beq.s + ; if yes, branch st d6 move.w #$2B56,x_pos(a1) ; align with right pillar bset #0,render_flags(a1) + move.w #$28,obj89_eyes_timer(a1) jsrto (RandomNumber).l, JmpTo3_RandomNumber andi.w #3,d0 add.w d0,d0 move.w Obj89_Arrow_Offsets(pc,d0.w),y_pos(a1) movea.l a1,a2 jsrto (SingleObjLoad).l, JmpTo14_SingleObjLoad bne.s return_30B40 _move.b #ObjID_ARZBoss,id(a1) ; load obj89 move.b #4,boss_subtype(a1) move.b #6,routine_secondary(a1) ; => Obj89_Arrow move.l a2,obj89_arrow_parent2(a1) move.b d6,subtype(a1) move.l a3,obj89_arrow_parent(a1) return_30B40: rts ; =========================================================================== ; word_30B42: Obj89_Arrow_Offsets: dc.w $458 dc.w $478 ; 1 dc.w $498 ; 2 dc.w $4B8 ; 3 ; =========================================================================== ; loc_30B4A: Obj89_Pillar_Sub4: move.b #1,(Screen_Shaking_Flag).w ; make screen shake addi_.w #1,y_pos(a0) ; lower pillar cmpi.w #$510,y_pos(a0) ; has pillar lowered into the ground? blt.s BranchTo2_JmpTo37_DisplaySprite ; if not, branch move.b #0,(Screen_Shaking_Flag).w ; else, stop shaking the screen jmpto (DeleteObject).l, JmpTo55_DeleteObject ; =========================================================================== BranchTo2_JmpTo37_DisplaySprite jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== ; loc_30B6C: Obj89_Pillar_BulgingEyes: subi_.w #1,obj89_eyes_timer(a0) beq.w JmpTo55_DeleteObject jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== ; loc_30B7A: Obj89_Pillar_SolidObject: move.w #$23,d1 move.w #$44,d2 move.w #$45,d3 move.w x_pos(a0),d4 move.w y_pos(a0),-(sp) addi_.w #4,y_pos(a0) ; assume a slightly lower y position jsrto (SolidObject).l, JmpTo26_SolidObject move.w (sp)+,y_pos(a0) ; restore y position rts ; =========================================================================== ;loc_30B9E: Obj89_Arrow: moveq #0,d0 movea.l obj89_arrow_parent(a0),a1 ; a1=object cmpi.b #8,boss_routine(a1) ; has boss been defeated? blt.s Obj89_Arrow_Normal ; if not, branch move.b #6,obj89_arrow_routine(a0) ; => Obj89_Arrow_Sub6 ; loc_30BB2: Obj89_Arrow_Normal: move.b obj89_arrow_routine(a0),d0 move.w Obj89_Arrow_Index(pc,d0.w),d1 jmp Obj89_Arrow_Index(pc,d1.w) ; =========================================================================== ; off_30BBE: Obj89_Arrow_Index: offsetTable offsetTableEntry.w Obj89_Arrow_Init ; 0 - launch arrow (init) offsetTableEntry.w Obj89_Arrow_Sub2 ; 2 - arrow in air offsetTableEntry.w Obj89_Arrow_Sub4 ; 4 - arrow stuck offsetTableEntry.w Obj89_Arrow_Sub6 ; 6 - falling down offsetTableEntry.w BranchTo_JmpTo55_DeleteObject ; 8 - delete arrow ; =========================================================================== ; loc_30BC8: Obj89_Arrow_Init: move.l #Obj89_MapUnc_30D68,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_ARZBoss,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #-$70,mainspr_width(a0) move.b #4,priority(a0) addq.b #2,obj89_arrow_routine(a0) ; => Obj89_Arrow_Sub2 movea.l obj89_arrow_parent2(a0),a1 ; a1=object move.w x_pos(a1),x_pos(a0) ; align with parent object move.w y_pos(a1),y_pos(a0) move.w #4,y_vel(a0) move.b #4,mapping_frame(a0) addi.w #9,y_pos(a0) tst.b subtype(a0) ; was arrow fired from right pillar? beq.s + ; if not, branch bset #0,status(a0) ; make arrow face left bset #0,render_flags(a0) move.w #-3,x_vel(a0) ; move left bra.s Obj89_Arrow_Init_End ; =========================================================================== + move.w #3,x_vel(a0) ; move right ; loc_30C2E: Obj89_Arrow_Init_End: move.b #$B0,collision_flags(a0) rts ; =========================================================================== ; loc_30C36: Obj89_Arrow_Sub2: btst #7,status(a0) beq.s + move.b #8,obj89_arrow_routine(a0) ; => BranchTo_JmpTo55_DeleteObject + move.w x_pos(a0),d0 ; load x position... add.w x_vel(a0),d0 ; ... and add x velocity tst.w x_vel(a0) ; is arrow moving right? bpl.s Obj89_Arrow_Sub2_GoingRight ; if yes, branch cmpi.w #$2A77,d0 bgt.s Obj89_Arrow_Sub2_Move ; branch, if arrow hasn't reached left pillar move.w #$2A77,d0 ; else, make arrow stick to left pillar bra.s Obj89_Arrow_Sub2_Stop ; =========================================================================== ; loc_30C5E: Obj89_Arrow_Sub2_GoingRight: cmpi.w #$2B49,d0 blt.s Obj89_Arrow_Sub2_Move ; branch, if arrow hasn't reached right pillar move.w #$2B49,d0 ; else, make arrow stick to right pillar ; loc_30C68: Obj89_Arrow_Sub2_Stop: addi_.b #2,obj89_arrow_routine(a0) ; => Obj89_Arrow_Sub4 move.w d0,x_pos(a0) ; update position move.b #SndID_ArrowStick,d0 jsrto (PlaySound).l, JmpTo8_PlaySound jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== ; loc_30C7E: Obj89_Arrow_Sub2_Move: move.w d0,x_pos(a0) ; update position jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== ; loc_30C86: Obj89_Arrow_Sub4: move.b #0,collision_flags(a0) ; make arrow harmless btst #7,status(a0) beq.s + addi_.b #2,obj89_arrow_routine(a0) ; => Obj89_Arrow_Sub6 + bsr.w Obj89_Arrow_Platform lea (Ani_obj89_a).l,a1 jsrto (AnimateSprite).l, JmpTo19_AnimateSprite jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== ; loc_30CAC: Obj89_Arrow_Sub6: bsr.w Obj89_Arrow_ChkDropPlayers move.w y_pos(a0),d0 ; load y position... add.w y_vel(a0),d0 ; ... and add y velocity cmpi.w #$4F0,d0 ; has arrow dropped to the ground? bgt.w JmpTo55_DeleteObject ; if yes, branch move.w d0,y_pos(a0) ; update y position jmpto (DisplaySprite).l, JmpTo37_DisplaySprite ; =========================================================================== if removeJmpTos JmpTo55_DeleteObject endif BranchTo_JmpTo55_DeleteObject jmpto (DeleteObject).l, JmpTo55_DeleteObject ; =========================================================================== ; loc_30CCC: Obj89_Arrow_Platform: tst.w obj89_arrow_timer(a0) ; is timer set? bne.s Obj89_Arrow_Platform_Decay ; if yes, branch move.w #$1B,d1 move.w #1,d2 move.w #2,d3 move.w x_pos(a0),d4 jsrto (PlatformObject).l, JmpTo8_PlatformObject btst #3,status(a0) ; is Sonic standing on the arrow? beq.s return_30D02 ; if not, branch move.w #$1F,obj89_arrow_timer(a0) ; else, set timer ; loc_30CF4: Obj89_Arrow_Platform_Decay: subi_.w #1,obj89_arrow_timer(a0) ; decrement timer bne.s return_30D02 ; branch, if timer hasn't expired move.b #6,obj89_arrow_routine(a0) ; => Obj89_Arrow_Sub6 return_30D02: rts ; =========================================================================== ; loc_30D04: Obj89_Arrow_ChkDropPlayers: bclr #p1_standing_bit,status(a0) beq.s + ; branch, if Sonic wasn't standing on the arrow lea (MainCharacter).w,a1 ; a1=character bsr.s Obj89_Arrow_DropPlayer + bclr #p2_standing_bit,status(a0) beq.s return_30D2A ; branch, if Tails wasn't standing on the arrow lea (Sidekick).w,a1 ; a1=character ; loc_30D1E: Obj89_Arrow_DropPlayer: bset #1,status(a1) bclr #3,status(a1) return_30D2A: rts ; =========================================================================== ; animation script ; off_30D2C: Ani_obj89_a: offsetTable offsetTableEntry.w byte_30D30 ; 0 offsetTableEntry.w byte_30D47 ; 1 byte_30D30: dc.b 1, 4, 6, 5, 4, 6, 4, 5, 4, 6, 4, 4, 6, 5, 4, 6 dc.b 4, 5, 4, 6, 4,$FD, 1; 16 rev02even byte_30D47: dc.b $F, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 dc.b 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,$F9; 16 even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj89_MapUnc_30D68: BINCLUDE "mappings/sprite/obj89_a.bin" ; animation script ; off_30DC8: Ani_obj89_b: offsetTable offsetTableEntry.w byte_30DD4 ; 0 offsetTableEntry.w byte_30DEA ; 2 offsetTableEntry.w byte_30DEE ; 4 offsetTableEntry.w byte_30DF1 ; 6 offsetTableEntry.w byte_30DFD ; 8 offsetTableEntry.w byte_30E00 ; $A byte_30DD4: dc.b 7, 0, 1,$FF, 2, 3, 2, 3, 2, 3, 2, 3,$FF, 4, 4, 4 dc.b 4, 4, 4, 4, 4,$FF; 16 rev02even byte_30DEA: dc.b 1, 6, 7,$FF rev02even byte_30DEE: dc.b $F, 9,$FF rev02even byte_30DF1: dc.b 2, $A, $A, $B, $B, $B, $B, $B, $A, $A,$FD, 2 rev02even byte_30DFD: dc.b $F, 8,$FF rev02even byte_30E00: dc.b 7, 5,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj89_MapUnc_30E04: BINCLUDE "mappings/sprite/obj89_b.bin" ; =========================================================================== if ~~removeJmpTos JmpTo37_DisplaySprite jmp (DisplaySprite).l JmpTo55_DeleteObject jmp (DeleteObject).l JmpTo14_SingleObjLoad jmp (SingleObjLoad).l JmpTo8_PlaySound jmp (PlaySound).l JmpTo22_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo19_AnimateSprite jmp (AnimateSprite).l JmpTo3_RandomNumber jmp (RandomNumber).l JmpTo8_LoadPLC jmp (LoadPLC).l JmpTo5_AddPoints jmp (AddPoints).l JmpTo4_PlayLevelMusic jmp (PlayLevelMusic).l JmpTo4_LoadPLC_AnimalExplosion jmp (LoadPLC_AnimalExplosion).l JmpTo8_PlatformObject jmp (PlatformObject).l JmpTo26_SolidObject jmp (SolidObject).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 57 - MCZ boss ; ---------------------------------------------------------------------------- ; OST: first $10 bytes for main sprite, 6 bytes for childsprites (5th byte unused) obj57_sub5_y_vel = $2E ; word - y_vel of second digger when falling down obj57_sub2_y_vel = $30 ; word - y_vel of first digger when falling down obj57_sub2_y_pos2 = $34 ; longword - y_pos of first digger when falling down obj57_sub5_y_pos2 = $3A ; longword - y_pos of second digger when falling down ; ---------------------------------------------------------------------------- ; Sprite_30FA4: Obj57: moveq #0,d0 move.b boss_subtype(a0),d0 move.w Obj57_Index(pc,d0.w),d1 jmp Obj57_Index(pc,d1.w) ; =========================================================================== ;off_30FB2: Obj57_Index: offsetTable offsetTableEntry.w Obj57_Init ; 0 - Init offsetTableEntry.w Obj57_Main ; 2 - Main Vehicle offsetTableEntry.w Obj57_FallingStuff ; 4 - Spikes & Stones ; =========================================================================== ;loc_30FB8: Obj57_Init: move.l #Obj57_MapUnc_316EC,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_MCZBoss,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #3,priority(a0) ; gets overwritten move.w #$21A0,x_pos(a0) move.w #$560,y_pos(a0) move.b #5,mainspr_mapframe(a0) addq.b #2,boss_subtype(a0) move.b #2,boss_routine(a0) bset #6,render_flags(a0) ; use subobjects for rendering move.b #4,mainspr_childsprites(a0) move.b #$F,collision_flags(a0) move.b #8,boss_hitcount2(a0) move.w x_pos(a0),(Boss_X_pos).w move.w y_pos(a0),(Boss_Y_pos).w move.w #$C0,(Boss_Y_vel).w ; move down move.b #0,(Boss_CollisionRoutine).w move.b #1,(Screen_Shaking_Flag).w move.b #$40,mainspr_width(a0) move.w x_pos(a0),sub2_x_pos(a0) move.w y_pos(a0),sub2_y_pos(a0) move.b #2,sub2_mapframe(a0) move.w x_pos(a0),sub3_x_pos(a0) move.w y_pos(a0),sub3_y_pos(a0) move.b #1,sub3_mapframe(a0) move.w x_pos(a0),sub4_x_pos(a0) move.w y_pos(a0),sub4_y_pos(a0) move.b #$E,sub4_mapframe(a0) move.w x_pos(a0),sub5_x_pos(a0) move.w y_pos(a0),sub5_y_pos(a0) move.b #2,sub5_mapframe(a0) subi.w #$28,sub5_x_pos(a0) move.w #$28,(Boss_Countdown).w move.w #-$380,obj57_sub5_y_vel(a0) move.w #-$380,obj57_sub2_y_vel(a0) bsr.w Obj57_InitAnimationData rts ; =========================================================================== ;loc_31090: Obj57_InitAnimationData: lea (Boss_AnimationArray).w,a2 move.b #2,(a2)+ ; hover thingies (fire on) move.b #0,(a2)+ move.b #3,(a2)+ ; digger 1 (vertical) move.b #0,(a2)+ move.b #$10,(a2)+ ; main vehicle move.b #0,(a2)+ move.b #$D,(a2)+ ; main vehicle center (including robotnik's face) move.b #0,(a2)+ move.b #3,(a2)+ ; digger 2 (vertical) move.b #0,(a2)+ rts ; =========================================================================== ;loc_310BE: Obj57_Main: ; Main Vehicle moveq #0,d0 move.b boss_routine(a0),d0 move.w Obj57_Main_Index(pc,d0.w),d1 jmp Obj57_Main_Index(pc,d1.w) ; =========================================================================== ;off_310CC: Obj57_Main_Index: offsetTable offsetTableEntry.w Obj57_Main_Sub0 ; 0 - boss just moving up offsetTableEntry.w Obj57_Main_Sub2 ; 2 - boss moving down, stuff falling down offsetTableEntry.w Obj57_Main_Sub4 ; 4 - moving down, stop stuff falling down offsetTableEntry.w Obj57_Main_Sub6 ; 6 - digger transition (rotation), moving back and forth offsetTableEntry.w Obj57_Main_Sub8 ; 8 - boss defeated, standing still, exploding offsetTableEntry.w Obj57_Main_SubA ; $A - slowly hovering down, no explosions offsetTableEntry.w Obj57_Main_SubC ; $C - moving away fast ; =========================================================================== ;loc_310DA: Obj57_Main_Sub0: ; boss just moving up subi_.w #1,(Boss_Countdown).w ; countdown bpl.s Obj57_Main_Sub0_Continue move.b #0,(Boss_AnimationArray+5).w ; reset anim main vehicle bsr.w Boss_MoveObject cmpi.w #$560,(Boss_Y_pos).w ; a little above top screen boundary bgt.s Obj57_Main_Sub0_Continue ; if below that, branch move.w #$100,(Boss_Y_vel).w move.w (MainCharacter+x_pos).w,d3 cmpi.w #$2190,d3 bhs.s + move.w #$2200,d3 bra.s ++ ; =========================================================================== + move.w #$2120,d3 + move.w d3,(Boss_X_pos).w addq.b #2,boss_routine(a0) ; stuff falling down bclr #0,render_flags(a0) move.w (MainCharacter+x_pos).w,d0 sub.w (Boss_X_pos).w,d0 bmi.s Obj57_Main_Sub0_Continue bset #0,render_flags(a0) ;loc_3112C: Obj57_Main_Sub0_Continue: ; if countdown finished or boss below $560 cmpi.w #$28,(Boss_Countdown).w bne.s + move.b #0,(Boss_CollisionRoutine).w + cmpi.w #$620,(Boss_Y_pos).w ; if above, screenshaking & stones bge.s Obj57_Main_Sub0_Standard move.b #1,(Screen_Shaking_Flag).w bsr.w Obj57_SpawnStoneSpike Obj57_Main_Sub0_Standard: move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) bsr.w Obj57_HandleHits lea (Ani_obj57).l,a1 bsr.w AnimateBoss bsr.w Obj57_TransferPositions jmpto (DisplaySprite).l, JmpTo38_DisplaySprite ; =========================================================================== ;loc_3116E: Obj57_Main_Sub2: ; boss moving down, stuff falling down bsr.w Boss_MoveObject bsr.w Obj57_SpawnStoneSpike cmpi.w #$620,(Boss_Y_pos).w ; if below... blt.s Obj57_Main_Sub2_Standard addq.b #2,boss_routine(a0) ; ...next routine move.b #0,(Screen_Shaking_Flag).w ; no screen shaking Obj57_Main_Sub2_Standard: move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) bsr.w Obj57_HandleHits lea (Ani_obj57).l,a1 bsr.w AnimateBoss bsr.w Obj57_TransferPositions jmpto (DisplaySprite).l, JmpTo38_DisplaySprite ; =========================================================================== ;loc_311AA: Obj57_Main_Sub4: ; moving down, stop stuff falling down bsr.w Boss_MoveObject cmpi.w #$660,(Boss_Y_pos).w blt.s Obj57_Main_Sub4_Standard ; if above, keep moving down move.w #$660,(Boss_Y_pos).w ; if below, routine 6 + new anim addq.b #2,boss_routine(a0) lea (Boss_AnimationArray).w,a1 andi.b #$F0,2(a1) ori.b #6,2(a1) ; (6) prepare for digger rotation to diag/hztl andi.b #$F0,8(a1) ori.b #6,8(a1) ; (6) prepare for digger rotation to diag/hztl andi.b #$F0,6(a1) ori.b #$D,6(a1) ; (D) robotnik face normal move.b #$20,5(a1) ; main vehicle light on move.w #$64,(Boss_Countdown).w move.b #$30,1(a1) ; hover thingies fire off bclr #0,render_flags(a0) move.w (MainCharacter+x_pos).w,d0 sub.w (Boss_X_pos).w,d0 bmi.s + bset #0,render_flags(a0) + move.w #-$200,(Boss_X_vel).w ; boss moving horizontally move.w #0,(Boss_Y_vel).w btst #0,render_flags(a0) beq.s Obj57_Main_Sub4_Standard neg.w (Boss_X_vel).w Obj57_Main_Sub4_Standard: move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) bsr.w Obj57_HandleHits lea (Ani_obj57).l,a1 bsr.w AnimateBoss bsr.w Obj57_TransferPositions jmpto (DisplaySprite).l, JmpTo38_DisplaySprite ; =========================================================================== ;loc_3124A: Obj57_Main_Sub6: ; digger transition (rotation), moving back and forth subi_.w #1,(Boss_Countdown).w cmpi.w #$28,(Boss_Countdown).w bgt.w Obj57_Main_Sub6_Standard move.b #1,(Boss_CollisionRoutine).w tst.w (Boss_Countdown).w bpl.w Obj57_Main_Sub6_Standard tst.b boss_hurt_sonic(a0) ; has sonic just been hurt? beq.s + sf boss_hurt_sonic(a0) ; if yes, clear this flag bra.s Obj57_Main_Sub6_ReAscend1 ; =========================================================================== + bsr.w Boss_MoveObject cmpi.w #$2120,(Boss_X_pos).w bgt.s + move.w #$2120,(Boss_X_pos).w bra.s Obj57_Main_Sub6_ReAscend2 ; =========================================================================== + cmpi.w #$2200,(Boss_X_pos).w blt.s Obj57_Main_Sub6_Standard move.w #$2200,(Boss_X_pos).w bra.s Obj57_Main_Sub6_ReAscend2 ; =========================================================================== ;loc_31298: Obj57_Main_Sub6_ReAscend1: ; that's a dumb name for a label lea (Boss_AnimationArray).w,a1 move.b #$30,7(a1) ; face grin after hurting sonic ;loc_312A2: Obj57_Main_Sub6_ReAscend2: ; set to routine 0 and make boss move up again move.w #0,(Boss_X_vel).w move.b #0,boss_routine(a0) lea (Boss_AnimationArray).w,a1 andi.b #$F0,2(a1) ori.b #$B,2(a1) ; (B) prepare for digger rotation to diag/vert andi.b #$F0,8(a1) ori.b #$B,8(a1) ; (B) prepare for digger rotation to diag/vert move.b #0,1(a1) ; hover thingies fire on andi.b #$F0,6(a1) ori.b #$D,6(a1) ; (D) robotnik face normal move.w #$64,(Boss_Countdown).w move.w #-$C0,(Boss_Y_vel).w ; move up Obj57_Main_Sub6_Standard: move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) bsr.w Obj57_HandleHits lea (Ani_obj57).l,a1 bsr.w AnimateBoss bsr.w Obj57_TransferPositions jmpto (DisplaySprite).l, JmpTo38_DisplaySprite ; =========================================================================== ;loc_3130A: Obj57_TransferPositions: move.w x_pos(a0),d0 move.w y_pos(a0),d1 move.w d0,sub3_x_pos(a0) move.w d1,sub3_y_pos(a0) move.w d0,sub4_x_pos(a0) move.w d1,sub4_y_pos(a0) tst.b boss_defeated(a0) bne.s Obj57_FallApart ; if boss defeated move.w d0,sub5_x_pos(a0) move.w d1,sub5_y_pos(a0) move.w d0,sub2_x_pos(a0) move.w d1,sub2_y_pos(a0) move.w d1,obj57_sub5_y_pos2(a0) move.w d1,obj57_sub2_y_pos2(a0) btst #0,render_flags(a0) beq.s + addi.w #$28,sub5_x_pos(a0) rts ; =========================================================================== + subi.w #$28,sub5_x_pos(a0) rts ; =========================================================================== ;loc_31358: Obj57_FallApart: ; make the digger thingies fall down cmpi.w #$78,(Boss_Countdown).w bgt.s return_313C4 subi_.w #1,sub5_x_pos(a0) move.l obj57_sub5_y_pos2(a0),d0 move.w obj57_sub5_y_vel(a0),d1 addi.w #$38,obj57_sub5_y_vel(a0) ext.l d1 asl.l #8,d1 add.l d1,d0 move.l d0,obj57_sub5_y_pos2(a0) move.w obj57_sub5_y_pos2(a0),sub5_y_pos(a0) cmpi.w #$6F0,sub5_y_pos(a0) blt.s + move.w #0,obj57_sub5_y_vel(a0) + ; second one addi_.w #1,sub2_x_pos(a0) move.l obj57_sub2_y_pos2(a0),d0 move.w obj57_sub2_y_vel(a0),d1 addi.w #$38,obj57_sub2_y_vel(a0) ext.l d1 asl.l #8,d1 add.l d1,d0 move.l d0,obj57_sub2_y_pos2(a0) move.w obj57_sub2_y_pos2(a0),sub2_y_pos(a0) cmpi.w #$6F0,sub2_y_pos(a0) blt.s return_313C4 move.w #0,obj57_sub2_y_vel(a0) return_313C4: rts ; =========================================================================== ;loc_313C6: Obj57_SpawnStoneSpike: ; decide whether stone or spike move.b (Vint_runcount+3).w,d1 ; not so random number? sf d2 andi.b #$1F,d1 beq.s Obj57_LoadStoneSpike andi.b #7,d1 bne.s return_31438 st d2 ;loc_313DA: Obj57_LoadStoneSpike: jsrto (RandomNumber).l, JmpTo4_RandomNumber swap d1 andi.w #$1FF,d1 addi.w #$20F0,d1 cmpi.w #$2230,d1 bgt.s Obj57_LoadStoneSpike jsrto (SingleObjLoad).l, JmpTo15_SingleObjLoad bne.s return_31438 move.b #ObjID_MCZBoss,id(a1) ; load obj57 move.b #4,boss_subtype(a1) move.w d1,x_pos(a1) move.w #$5F0,y_pos(a1) move.l #Obj57_MapUnc_316EC,mappings(a1) move.w #make_art_tile(ArtTile_ArtUnc_FallingRocks,0,0),art_tile(a1) ori.b #4,render_flags(a1) move.b #3,priority(a1) move.b #$D,mapping_frame(a1) tst.b d2 bne.s return_31438 ; stone move.b #$14,mapping_frame(a1) ; spike move.b #$B1,collision_flags(a1) return_31438: rts ; =========================================================================== ;loc_3143A: Obj57_HandleHits: bsr.w Obj57_HandleHits_Main cmpi.b #$1F,boss_invulnerable_time(a0) bne.s + ; rts lea (Boss_AnimationArray).w,a1 move.b #$C0,7(a1) ; face grin when hit + rts ; =========================================================================== ;loc_31452: Obj57_AddSinusOffset: ; called from routine $A and $C move.b boss_sine_count(a0),d0 ; sinus offset something jsr (CalcSine).l asr.w #6,d0 add.w (Boss_Y_pos).w,d0 move.w d0,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) addq.b #2,boss_sine_count(a0) ; increment frame counter for sinus offset ;loc_31470: Obj57_HandleHits_Main: cmpi.b #8,boss_routine(a0) bhs.s return_314B6 ; skip if boss already defeated tst.b boss_hitcount2(a0) beq.s Obj57_FinalDefeat tst.b collision_flags(a0) bne.s return_314B6 tst.b boss_invulnerable_time(a0) bne.s + move.b #$20,boss_invulnerable_time(a0) ; set invincibility timer move.w #SndID_BossHit,d0 jsr (PlaySound).l + lea (Normal_palette_line2+2).w,a1 moveq #0,d0 tst.w (a1) bne.s + move.w #$EEE,d0 + move.w d0,(a1) subq.b #1,boss_invulnerable_time(a0) bne.s return_314B6 move.b #$F,collision_flags(a0) return_314B6: rts ; =========================================================================== ;loc_314B8: Obj57_FinalDefeat: moveq #100,d0 jsrto (AddPoints).l, JmpTo6_AddPoints move.w #$B3,(Boss_Countdown).w move.b #8,boss_routine(a0) ; routine boss defeated moveq #PLCID_Capsule,d0 jsrto (LoadPLC).l, JmpTo9_LoadPLC rts ; =========================================================================== ;loc_314D2: Obj57_Main_Sub8: ; boss defeated, standing still, exploding st boss_defeated(a0) move.b #0,(Screen_Shaking_Flag).w subq.w #1,(Boss_Countdown).w ; countdown initially $B3 bmi.s + ; branch if countdown finished move.b #$13,sub4_mapframe(a0) ; burnt face move.b #7,mainspr_mapframe(a0) bsr.w Boss_LoadExplosion bra.s Obj57_Main_Sub8_Standard ; =========================================================================== + bset #0,render_flags(a0) clr.w (Boss_X_vel).w clr.w (Boss_Y_vel).w addq.b #2,boss_routine(a0) ; next routine move.b #$12,sub4_mapframe(a0) ; face grin when hit move.w #-$12,(Boss_Countdown).w Obj57_Main_Sub8_Standard: move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) bsr.w Obj57_TransferPositions jmpto (DisplaySprite).l, JmpTo38_DisplaySprite ; =========================================================================== ;loc_31526: Obj57_Main_SubA: ; slowly hovering down, no explosions addq.w #1,(Boss_Countdown).w ; countdown initially -$12 beq.s ++ ; reset y_vel bpl.s +++ cmpi.w #$620,(Boss_Y_pos).w bhs.s + subq.w #1,(Boss_Countdown).w + addi.w #$10,(Boss_Y_vel).w ; add gravity bra.s Obj57_Main_SubA_Standard ; =========================================================================== + clr.w (Boss_Y_vel).w bra.s Obj57_Main_SubA_Standard ; =========================================================================== + cmpi.w #$18,(Boss_Countdown).w blo.s + ; accelerate boss upwards beq.s ++ ; reset y_vel, PlayLevelMusic cmpi.w #$20,(Boss_Countdown).w blo.s Obj57_Main_SubA_Standard lea (Boss_AnimationArray).w,a1 move.b #$D,7(a1) ; face grin when hit _move.b #2,0(a2) ; There is a bug here. This should be a1 instead of a2. A random part of RAM gets written to instead. move.b #0,1(a1) ; hover thingies fire off addq.b #2,boss_routine(a0) bra.s Obj57_Main_SubA_Standard ; =========================================================================== + subi_.w #8,(Boss_Y_vel).w bra.s Obj57_Main_SubA_Standard ; =========================================================================== + clr.w (Boss_Y_vel).w jsrto (PlayLevelMusic).l, JmpTo5_PlayLevelMusic jsrto (LoadPLC_AnimalExplosion).l, JmpTo5_LoadPLC_AnimalExplosion ;loc_3158A: Obj57_Main_SubA_Standard: bsr.w Boss_MoveObject bsr.w Obj57_AddSinusOffset move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) bsr.w Obj57_TransferPositions jmpto (DisplaySprite).l, JmpTo38_DisplaySprite ; =========================================================================== ;loc_315A6: Obj57_Main_SubC: ; moving away fast move.w #$400,(Boss_X_vel).w move.w #-$40,(Boss_Y_vel).w ; escape to the right cmpi.w #$2240,(Camera_Max_X_pos).w beq.s + addq.w #2,(Camera_Max_X_pos).w bra.s Obj57_Main_SubC_Standard ; =========================================================================== + tst.b render_flags(a0) bpl.s JmpTo56_DeleteObject ; if off screen ;loc_315C6: Obj57_Main_SubC_Standard: bsr.w Boss_MoveObject bsr.w Obj57_AddSinusOffset move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) lea (Ani_obj57).l,a1 bsr.w AnimateBoss bsr.w Obj57_TransferPositions jmpto (DisplaySprite).l, JmpTo38_DisplaySprite ; =========================================================================== JmpTo56_DeleteObject jmp (DeleteObject).l ; =========================================================================== ;loc_315F2: Obj57_FallingStuff: ; Spikes & Stones jsrto (ObjectMoveAndFall).l, JmpTo5_ObjectMoveAndFall subi.w #$28,sub2_y_pos(a0) ; decrease gravity cmpi.w #$6F0,y_pos(a0) ; if below boundary, delete if ~~removeJmpTos bgt.w JmpTo57_DeleteObject else bgt.s JmpTo56_DeleteObject endif jmpto (DisplaySprite).l, JmpTo38_DisplaySprite ; =========================================================================== ; off_3160A: Obj57_AnimIndex: Ani_obj57: offsetTable offsetTableEntry.w byte_31628 ; 0 - main vehicle offsetTableEntry.w byte_3162E ; 1 - digger diagonal offsetTableEntry.w byte_31631 ; 2 - hover fire thingies to keep boss in air offsetTableEntry.w byte_31638 ; 3 - digger vertical animated 1 -> (4) offsetTableEntry.w byte_31649 ; 4 - digger vertical animated 2 -> (5) offsetTableEntry.w byte_3165A ; 5 - digger vertical animated 3 (loop) offsetTableEntry.w byte_31661 ; 6 - digger vertical animated 4 -> (7) offsetTableEntry.w byte_31673 ; 7 - digger vertical + diagonal transition -> (8) offsetTableEntry.w byte_31684 ; 8 - digger horizontal animated 1 -> (9) offsetTableEntry.w byte_31695 ; 9 - digger horizontal animated 2 -> (A) offsetTableEntry.w byte_316A6 ; A - digger horizontal animated 3 (loop) offsetTableEntry.w byte_316AD ; B - digger horizontal animated 4 -> (C) offsetTableEntry.w byte_316BF ; C - digger horizontal + diagonal transition -> (3) offsetTableEntry.w byte_316D1 ; D - center vehicle, robotnik's face normal offsetTableEntry.w byte_316E8 ; E - center vehicle, robotnik's face when hit byte_31628: dc.b $F, 1,$FF ; light off dc.b 0,$FC, 2 ; light on; (3) subanimation rev02even byte_3162E: dc.b 5, 8,$FF rev02even byte_31631: dc.b 1, 5, 6,$FF ; fire on dc.b 7,$FC, 3 ; fire off; (4) subanimation rev02even byte_31638: dc.b 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4,$FD, 4 rev02even byte_31649: dc.b 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 2, 2, 3, 3,$FD, 5 rev02even byte_3165A: dc.b 1, 4, 2, 3, 4,$FC, 1 rev02even byte_31661: dc.b 1, 2, 3, 4, 4, 2, 2, 3, 3, 3, 4, 4, 4, 2, 2, 2,$FD, 7 rev02even byte_31673: dc.b 1, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 2, 8, 8, 8,$FD, 8 rev02even byte_31684: dc.b 1, 9, 9, 9, 9, 9, $A, $A, $A, $A, $A, $B, $B, $B, $B,$FD, 9 rev02even byte_31695: dc.b 1, 9, 9, 9, 9, $A, $A, $A, $B, $B, $B, 9, 9, $A, $A,$FD, $A rev02even byte_316A6: dc.b 1, $B, 9, $A, $B,$FC, 1 rev02even byte_316AD: dc.b 1, 9, $A, $B, $B, 9, 9, $A, $A, $A, $B, $B, $B, 9, 9, 9,$FD, $C rev02even byte_316BF: dc.b 1, 9, $A, $A, $A, $A, $B, $B, $B, $B, $B, 9, 8, 8, 8, 8,$FD, 3 rev02even byte_316D1: dc.b 7, $E, $F,$FF dc.b $10,$11,$10,$11,$10,$11,$10,$11,$FF ; (4) subanimation (grin after hurting sonic) dc.b $12,$12,$12,$12,$12,$12,$12,$12,$12,$FF ; (D) subanimation (grin when hit) rev02even byte_316E8: dc.b 7,$12,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj57_MapUnc_316EC: BINCLUDE "mappings/sprite/obj57.bin" ; =========================================================================== if ~~removeJmpTos JmpTo38_DisplaySprite jmp (DisplaySprite).l JmpTo57_DeleteObject jmp (DeleteObject).l JmpTo15_SingleObjLoad jmp (SingleObjLoad).l JmpTo4_RandomNumber jmp (RandomNumber).l JmpTo9_LoadPLC jmp (LoadPLC).l JmpTo6_AddPoints jmp (AddPoints).l JmpTo5_PlayLevelMusic jmp (PlayLevelMusic).l JmpTo5_LoadPLC_AnimalExplosion jmp (LoadPLC_AnimalExplosion).l JmpTo5_ObjectMoveAndFall jmp (ObjectMoveAndFall).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 51 - CNZ boss ; ---------------------------------------------------------------------------- ; Sprite_318F0: Obj51: moveq #0,d0 move.b boss_subtype(a0),d0 move.w Obj51_Index(pc,d0.w),d1 jmp Obj51_Index(pc,d1.w) ; =========================================================================== ; off_318FE: Obj51_Index: offsetTable offsetTableEntry.w Obj51_Init ; 0 offsetTableEntry.w loc_31A04 ; 2 offsetTableEntry.w loc_31F24 ; 4 ; =========================================================================== ; loc_31904: Obj51_Init: move.l #Obj51_MapUnc_320EA,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CNZBoss_Fudge,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #3,priority(a0) move.w #$2A46,x_pos(a0) move.w #$654,y_pos(a0) move.b #0,mainspr_mapframe(a0) move.b #$20,mainspr_width(a0) move.b #$80,mainspr_height(a0) addq.b #2,boss_subtype(a0) move.b #0,angle(a0) bset #6,render_flags(a0) move.b #4,mainspr_childsprites(a0) move.b #$F,collision_flags(a0) move.b #8,objoff_32(a0) move.w x_pos(a0),(Boss_X_pos).w move.w y_pos(a0),(Boss_Y_pos).w move.w x_pos(a0),sub2_x_pos(a0) move.w y_pos(a0),sub2_y_pos(a0) move.b #5,sub2_mapframe(a0) move.w x_pos(a0),sub3_x_pos(a0) move.w y_pos(a0),sub3_y_pos(a0) move.b #1,sub3_mapframe(a0) move.w x_pos(a0),sub4_x_pos(a0) move.w y_pos(a0),sub4_y_pos(a0) move.b #6,sub4_mapframe(a0) move.w x_pos(a0),sub5_x_pos(a0) move.w y_pos(a0),sub5_y_pos(a0) move.b #2,sub5_mapframe(a0) move.b #0,objoff_38(a0) move.w #0,(Boss_Y_vel).w move.w #-$180,(Boss_X_vel).w move.b #0,objoff_2D(a0) move.w #1,(Boss_Countdown).w bsr.w loc_319D6 rts ; =========================================================================== loc_319D6: lea (Boss_AnimationArray).w,a2 move.b #8,(a2)+ move.b #0,(a2)+ move.b #1,(a2)+ move.b #0,(a2)+ move.b #$10,(a2)+ move.b #0,(a2)+ move.b #3,(a2)+ move.b #0,(a2)+ move.b #2,(a2)+ move.b #0,(a2)+ rts ; =========================================================================== loc_31A04: tst.b (Boss_CollisionRoutine).w beq.s loc_31A1C move.b (Vint_runcount+3).w,d0 andi.b #$1F,d0 bne.s loc_31A1C move.b #SndID_CNZBossZap,d0 jsrto (PlaySound).l, JmpTo9_PlaySound loc_31A1C: moveq #0,d0 move.b angle(a0),d0 move.w off_31A2A(pc,d0.w),d1 jmp off_31A2A(pc,d1.w) ; =========================================================================== off_31A2A: offsetTable offsetTableEntry.w loc_31A36 ; 0 offsetTableEntry.w loc_31BA8 ; 2 offsetTableEntry.w loc_31C22 ; 4 offsetTableEntry.w loc_31D5C ; 6 offsetTableEntry.w loc_31DCC ; 8 offsetTableEntry.w loc_31E2A ; $A ; =========================================================================== loc_31A36: moveq #0,d0 move.b objoff_38(a0),d0 move.w off_31A44(pc,d0.w),d0 jmp off_31A44(pc,d0.w) ; =========================================================================== off_31A44: offsetTable offsetTableEntry.w loc_31A48 ; 0 offsetTableEntry.w loc_31A78 ; 2 ; =========================================================================== loc_31A48: cmpi.w #$28C0,(Boss_X_pos).w bgt.s BranchTo_loc_31AA4 move.w #$28C0,(Boss_X_pos).w move.w #0,(Boss_Y_vel).w move.w #$180,(Boss_X_vel).w move.b #2,objoff_38(a0) bset #0,render_flags(a0) move.b #0,objoff_2D(a0) BranchTo_loc_31AA4 bra.w loc_31AA4 ; =========================================================================== loc_31A78: cmpi.w #$29C0,(Boss_X_pos).w blt.s loc_31AA4 move.w #$29C0,(Boss_X_pos).w move.w #0,(Boss_Y_vel).w move.w #-$180,(Boss_X_vel).w move.b #0,objoff_38(a0) bclr #0,render_flags(a0) move.b #0,objoff_2D(a0) loc_31AA4: bsr.w Boss_MoveObject tst.b objoff_3F(a0) beq.s loc_31AB6 subq.b #1,objoff_3F(a0) bra.w loc_31B46 ; =========================================================================== loc_31AB6: move.w (MainCharacter+x_pos).w,d0 sub.w x_pos(a0),d0 addi.w #$10,d0 cmpi.w #$20,d0 bhs.s loc_31B46 cmpi.w #$6B0,(MainCharacter+y_pos).w blo.s loc_31B06 cmpi.b #3,objoff_2D(a0) bhs.s loc_31B46 addq.b #1,objoff_2D(a0) addq.b #2,angle(a0) move.b #8,(Boss_AnimationArray).w move.b #0,(Boss_AnimationArray+3).w move.b #0,(Boss_AnimationArray+9).w move.b #0,(Boss_CollisionRoutine).w bsr.w loc_31BF2 move.w #$50,(Boss_Countdown).w bra.w loc_31C08 ; =========================================================================== loc_31B06: cmpi.w #$67C,(MainCharacter+y_pos).w blo.s loc_31B46 move.b #$F,mainspr_mapframe(a0) move.b #2,(Boss_CollisionRoutine).w move.b #$20,(Boss_AnimationArray+3).w move.b #$20,(Boss_AnimationArray+9).w move.b #9,(Boss_AnimationArray).w addq.b #4,angle(a0) move.w #0,(Boss_X_vel).w move.w #$180,(Boss_Y_vel).w move.b #0,objoff_3E(a0) bra.w loc_31C08 ; =========================================================================== loc_31B46: bra.w + + addi_.w #1,(Boss_Countdown).w move.w (Boss_Countdown).w,d0 andi.w #$3F,d0 bne.w loc_31C08 btst #6,(Boss_Countdown+1).w beq.s loc_31B86 move.b #$F,mainspr_mapframe(a0) move.b #2,(Boss_CollisionRoutine).w move.b #$20,(Boss_AnimationArray+3).w move.b #$20,(Boss_AnimationArray+9).w move.b #9,(Boss_AnimationArray).w bra.w loc_31C08 ; =========================================================================== loc_31B86: move.b #$C,mainspr_mapframe(a0) move.b #1,(Boss_CollisionRoutine).w move.b #0,(Boss_AnimationArray+3).w move.b #0,(Boss_AnimationArray+9).w move.b #4,(Boss_AnimationArray).w bra.w loc_31C08 ; =========================================================================== loc_31BA8: move.b #0,(Boss_CollisionRoutine).w subi_.w #1,(Boss_Countdown).w bne.s loc_31BC6 move.b #$20,(Boss_AnimationArray+3).w move.b #$20,(Boss_AnimationArray+9).w bra.w loc_31C08 ; =========================================================================== loc_31BC6: cmpi.w #-$14,(Boss_Countdown).w bgt.w loc_31C08 move.b #0,(Boss_AnimationArray+3).w move.b #0,(Boss_AnimationArray+9).w move.b #0,angle(a0) move.w #-1,(Boss_Countdown).w move.b #$40,objoff_3F(a0) bra.w loc_31C08 ; =========================================================================== loc_31BF2: jsrto (SingleObjLoad).l, JmpTo16_SingleObjLoad bne.s return_31C06 move.b #ObjID_CNZBoss,id(a1) ; load obj51 move.b #4,boss_subtype(a1) move.l a0,objoff_34(a1) return_31C06: rts ; =========================================================================== loc_31C08: bsr.w loc_31CDC bsr.w loc_31E76 bsr.w loc_31C92 lea (Ani_obj51).l,a1 bsr.w AnimateBoss if removeJmpTos JmpTo39_DisplaySprite endif jmpto (DisplaySprite).l, JmpTo39_DisplaySprite ; =========================================================================== loc_31C22: bsr.w Boss_MoveObject tst.b objoff_3E(a0) bne.s loc_31C60 cmpi.w #$680,y_pos(a0) blo.s loc_31C08 move.w #0,(Boss_X_vel).w move.w #-$180,(Boss_Y_vel).w move.b #-1,objoff_3E(a0) move.b #1,(Boss_CollisionRoutine).w move.b #0,(Boss_AnimationArray+3).w move.b #0,(Boss_AnimationArray+9).w move.b #4,(Boss_AnimationArray).w bra.s loc_31C08 ; =========================================================================== loc_31C60: cmpi.w #$654,y_pos(a0) bhs.s loc_31C08 move.b #0,angle(a0) move.w #0,(Boss_Y_vel).w move.w #-$180,(Boss_X_vel).w btst #0,render_flags(a0) beq.s BranchTo_loc_31C08 move.w #$180,(Boss_X_vel).w move.b #$C,mainspr_mapframe(a0) BranchTo_loc_31C08 bra.w loc_31C08 ; =========================================================================== loc_31C92: cmpi.b #$2F,mainspr_height(a0) bne.s loc_31CAC lea (Boss_AnimationArray).w,a1 andi.b #$F0,6(a1) ori.b #6,6(a1) rts ; =========================================================================== loc_31CAC: cmpi.b #4,(MainCharacter+routine).w beq.s loc_31CBC cmpi.b #4,(Sidekick+routine).w bne.s return_31CDA loc_31CBC: lea (Boss_AnimationArray).w,a1 move.b 6(a1),d0 andi.b #$F,d0 cmpi.b #6,d0 beq.s return_31CDA andi.b #$F0,6(a1) ori.b #5,6(a1) return_31CDA: rts ; =========================================================================== loc_31CDC: move.b mapping_frame(a0),d0 jsr (CalcSine).l asr.w #6,d0 add.w (Boss_Y_pos).w,d0 move.w d0,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) addq.b #2,mapping_frame(a0) cmpi.b #6,angle(a0) bhs.s return_31D40 tst.b objoff_32(a0) beq.s loc_31D42 tst.b collision_flags(a0) bne.s return_31D40 tst.b mainspr_height(a0) bne.s loc_31D24 move.b #$30,mainspr_height(a0) move.w #SndID_BossHit,d0 jsr (PlaySound).l loc_31D24: lea (Normal_palette_line2+2).w,a1 moveq #0,d0 tst.w (a1) bne.s loc_31D32 move.w #$EEE,d0 loc_31D32: move.w d0,(a1) subq.b #1,mainspr_height(a0) bne.s return_31D40 move.b #$F,collision_flags(a0) return_31D40: rts ; =========================================================================== loc_31D42: moveq #100,d0 jsrto (AddPoints).l, JmpTo7_AddPoints move.w #$B3,(Boss_Countdown).w move.b #6,angle(a0) moveq #PLCID_Capsule,d0 jsrto (LoadPLC).l, JmpTo10_LoadPLC rts ; =========================================================================== loc_31D5C: st objoff_2C(a0) subq.w #1,(Boss_Countdown).w bmi.s loc_31D7E move.b #0,(Boss_CollisionRoutine).w move.b #0,mainspr_mapframe(a0) move.b #$B,collision_property(a0) bsr.w Boss_LoadExplosion bra.s loc_31DB8 ; =========================================================================== loc_31D7E: bset #0,render_flags(a0) clr.w (Boss_X_vel).w clr.w (Boss_Y_vel).w addq.b #2,angle(a0) lea (Boss_AnimationArray).w,a1 andi.b #$F0,6(a1) ori.b #3,6(a1) _move.b #8,0(a1) move.b #$DD,(Level_Layout+$C54).w move.b #1,(Screen_redraw_flag).w move.w #-$12,(Boss_Countdown).w loc_31DB8: move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) bsr.w loc_31E76 jmpto (DisplaySprite).l, JmpTo39_DisplaySprite ; =========================================================================== loc_31DCC: addq.w #1,(Boss_Countdown).w beq.s loc_31DDC bpl.s loc_31DE2 addi.w #$18,(Boss_Y_vel).w bra.s loc_31E0E ; =========================================================================== loc_31DDC: clr.w (Boss_Y_vel).w bra.s loc_31E0E ; =========================================================================== loc_31DE2: cmpi.w #$18,(Boss_Countdown).w blo.s loc_31DFA beq.s loc_31E02 cmpi.w #$20,(Boss_Countdown).w blo.s loc_31E0E addq.b #2,angle(a0) bra.s loc_31E0E ; =========================================================================== loc_31DFA: subi_.w #8,(Boss_Y_vel).w bra.s loc_31E0E ; =========================================================================== loc_31E02: clr.w (Boss_Y_vel).w jsrto (PlayLevelMusic).l, JmpTo6_PlayLevelMusic jsrto (LoadPLC_AnimalExplosion).l, JmpTo6_LoadPLC_AnimalExplosion loc_31E0E: bsr.w Boss_MoveObject bsr.w loc_31CDC move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) bsr.w loc_31E76 jmpto (DisplaySprite).l, JmpTo39_DisplaySprite ; =========================================================================== loc_31E2A: move.w #$400,(Boss_X_vel).w move.w #-$40,(Boss_Y_vel).w cmpi.w #$2B20,(Camera_Max_X_pos).w beq.s loc_31E44 addq.w #2,(Camera_Max_X_pos).w bra.s loc_31E4A ; =========================================================================== loc_31E44: tst.b render_flags(a0) bpl.s JmpTo58_DeleteObject loc_31E4A: bsr.w Boss_MoveObject bsr.w loc_31CDC move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) bsr.w loc_31E76 lea (Ani_obj51).l,a1 bsr.w AnimateBoss jmpto (DisplaySprite).l, JmpTo39_DisplaySprite ; =========================================================================== if removeJmpTos JmpTo59_DeleteObject endif JmpTo58_DeleteObject jmp (DeleteObject).l ; =========================================================================== loc_31E76: move.w x_pos(a0),d0 move.w y_pos(a0),d1 move.w d0,sub3_x_pos(a0) move.w d1,sub3_y_pos(a0) move.w d0,sub4_x_pos(a0) move.w d1,sub4_y_pos(a0) tst.b objoff_2C(a0) bne.s loc_31EAE move.w d0,sub5_x_pos(a0) move.w d1,sub5_y_pos(a0) move.w d0,sub2_x_pos(a0) move.w d1,sub2_y_pos(a0) move.w d1,objoff_3A(a0) move.w d1,objoff_34(a0) rts ; =========================================================================== loc_31EAE: cmpi.w #$78,(Boss_Countdown).w bgt.s return_31F22 subi_.w #1,sub5_x_pos(a0) move.l objoff_3A(a0),d0 move.w objoff_2E(a0),d1 addi.w #$38,objoff_2E(a0) ext.l d1 asl.l #8,d1 add.l d1,d0 move.l d0,objoff_3A(a0) move.w objoff_3A(a0),sub5_y_pos(a0) cmpi.w #$6F0,sub5_y_pos(a0) blt.s loc_31EE8 move.w #0,objoff_2E(a0) loc_31EE8: cmpi.w #$3C,(Boss_Countdown).w bgt.s return_31F22 addi_.w #1,sub2_x_pos(a0) move.l objoff_34(a0),d0 move.w objoff_30(a0),d1 addi.w #$38,objoff_30(a0) ext.l d1 asl.l #8,d1 add.l d1,d0 move.l d0,objoff_34(a0) move.w objoff_34(a0),sub2_y_pos(a0) cmpi.w #$6F0,sub2_y_pos(a0) blt.s return_31F22 move.w #0,objoff_30(a0) return_31F22: rts ; =========================================================================== loc_31F24: movea.l objoff_34(a0),a1 ; a1=object cmpi.b #6,angle(a1) bhs.w JmpTo59_DeleteObject moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_31F40(pc,d0.w),d1 jmp off_31F40(pc,d1.w) ; =========================================================================== off_31F40: offsetTable offsetTableEntry.w loc_31F48 ; 0 offsetTableEntry.w loc_31F96 ; 2 offsetTableEntry.w loc_31FDC ; 4 offsetTableEntry.w loc_32080 ; 6 ; =========================================================================== loc_31F48: move.l #Obj51_MapUnc_320EA,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_CNZBoss_Fudge,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #7,priority(a0) addq.b #2,routine_secondary(a0) movea.l objoff_34(a0),a1 ; a1=object move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) addi.w #$30,y_pos(a0) move.b #8,y_radius(a0) move.b #8,x_radius(a0) move.b #$12,mapping_frame(a0) move.b #$98,collision_flags(a0) rts ; =========================================================================== loc_31F96: movea.l objoff_34(a0),a1 ; a1=object move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) move.w objoff_28(a0),d0 add.w d0,y_pos(a0) addi_.w #1,d0 cmpi.w #$2E,d0 blt.s + move.w #$2E,d0 + move.w d0,objoff_28(a0) tst.w (Boss_Countdown).w bne.w JmpTo39_DisplaySprite addq.b #2,routine_secondary(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) jmpto (DisplaySprite).l, JmpTo39_DisplaySprite ; =========================================================================== loc_31FDC: bsr.w loc_31FF8 jsr (ObjCheckFloorDist).l tst.w d1 bpl.w JmpTo39_DisplaySprite add.w d1,y_pos(a0) bsr.w loc_32030 jmpto (DisplaySprite).l, JmpTo39_DisplaySprite ; =========================================================================== loc_31FF8: moveq #0,d2 move.w x_pos(a0),d2 swap d2 moveq #0,d3 move.w y_pos(a0),d3 swap d3 move.w x_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d2 move.w y_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d3 addi.w #$38,y_vel(a0) swap d2 move.w d2,x_pos(a0) swap d3 move.w d3,y_pos(a0) rts ; =========================================================================== loc_32030: move.b #SndID_BossExplosion,d0 jsrto (PlaySound).l, JmpTo9_PlaySound move.w #make_art_tile(ArtTile_ArtNem_CNZBoss_Fudge,0,0),art_tile(a0) move.b #7,anim(a0) move.w #-$300,y_vel(a0) move.w #-$100,x_vel(a0) move.b #4,boss_subtype(a0) move.b #6,routine_secondary(a0) move.b #$98,collision_flags(a0) jsrto (SingleObjLoad2).l, JmpTo23_SingleObjLoad2 bne.s return_3207E moveq #0,d0 move.w #bytesToLcnt(object_size),d1 loc_3206E: move.l (a0,d0.w),(a1,d0.w) addq.w #4,d0 dbf d1,loc_3206E if object_size&3 move.w (a0,d0.w),(a1,d0.w) endif neg.w x_vel(a1) return_3207E: rts ; =========================================================================== loc_32080: bsr.w loc_31FF8 lea (Ani_obj51).l,a1 jsrto (AnimateSprite).l, JmpTo20_AnimateSprite cmpi.w #$705,y_pos(a0) blo.w JmpTo39_DisplaySprite jmpto JmpTo59_DeleteObject, JmpTo59_DeleteObject ; =========================================================================== ; animation script ; off_3209C: Ani_obj51: offsetTable offsetTableEntry.w byte_320B0 ; 0 offsetTableEntry.w byte_320B3 ; 1 offsetTableEntry.w byte_320B9 ; 2 offsetTableEntry.w byte_320BF ; 3 offsetTableEntry.w byte_320C3 ; 4 offsetTableEntry.w byte_320C8 ; 5 offsetTableEntry.w byte_320D3 ; 6 offsetTableEntry.w byte_320DD ; 7 offsetTableEntry.w byte_320E1 ; 8 offsetTableEntry.w byte_320E4 ; 9 byte_320B0: dc.b $F, 1,$FF rev02even byte_320B3: dc.b $F, 4,$FF, 5,$FC, 2 rev02even byte_320B9: dc.b $F, 2,$FF, 3,$FC, 2 rev02even byte_320BF: dc.b 7, 6, 7,$FF rev02even byte_320C3: dc.b 1, $C, $D, $E,$FF rev02even byte_320C8: dc.b 7, 8, 9, 8, 9, 8, 9, 8, 9,$FD, 3 rev02even byte_320D3: dc.b 7, $A, $A, $A, $A, $A, $A, $A,$FD, 3 rev02even byte_320DD: dc.b 3,$13,$14,$FF rev02even byte_320E1: dc.b 1, 0,$FF rev02even byte_320E4: dc.b 1, $F,$10,$11,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj51_MapUnc_320EA: BINCLUDE "mappings/sprite/obj51.bin" ; =========================================================================== if ~~removeJmpTos JmpTo39_DisplaySprite jmp (DisplaySprite).l JmpTo59_DeleteObject jmp (DeleteObject).l JmpTo16_SingleObjLoad jmp (SingleObjLoad).l JmpTo9_PlaySound jmp (PlaySound).l JmpTo23_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo20_AnimateSprite jmp (AnimateSprite).l JmpTo10_LoadPLC jmp (LoadPLC).l JmpTo7_AddPoints jmp (AddPoints).l JmpTo6_PlayLevelMusic jmp (PlayLevelMusic).l JmpTo6_LoadPLC_AnimalExplosion jmp (LoadPLC_AnimalExplosion).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 54 - MTZ boss ; ---------------------------------------------------------------------------- ; Sprite_32288: Obj54: moveq #0,d0 move.b boss_subtype(a0),d0 move.w Obj54_Index(pc,d0.w),d1 jmp Obj54_Index(pc,d1.w) ; =========================================================================== ; off_32296: Obj54_Index: offsetTable offsetTableEntry.w Obj54_Init ; 0 offsetTableEntry.w Obj54_Main ; 2 offsetTableEntry.w Obj54_Laser ; 4 offsetTableEntry.w Obj54_LaserShooter ; 6 ; =========================================================================== ; loc_3229E: Obj54_Init: move.l #Obj54_MapUnc_32DC6,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_MTZBoss,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #3,priority(a0) move.w #$2B50,x_pos(a0) move.w #$380,y_pos(a0) move.b #2,mainspr_mapframe(a0) addq.b #2,boss_subtype(a0) ; => Obj54_Main bset #6,render_flags(a0) move.b #2,mainspr_childsprites(a0) move.b #$F,collision_flags(a0) move.b #8,boss_hitcount2(a0) move.b #7,objoff_3E(a0) move.w x_pos(a0),(Boss_X_pos).w move.w y_pos(a0),(Boss_Y_pos).w move.w #0,(Boss_X_vel).w move.w #$100,(Boss_Y_vel).w move.b #$20,mainspr_width(a0) clr.b objoff_2B(a0) clr.b objoff_2C(a0) move.b #$40,mapping_frame(a0) move.b #$27,objoff_33(a0) move.b #$27,objoff_39(a0) move.w x_pos(a0),sub2_x_pos(a0) move.w y_pos(a0),sub2_y_pos(a0) move.b #$C,sub2_mapframe(a0) move.w x_pos(a0),sub3_x_pos(a0) move.w y_pos(a0),sub3_y_pos(a0) move.b #0,sub3_mapframe(a0) jsrto (SingleObjLoad).l, JmpTo17_SingleObjLoad bne.s + move.b #ObjID_MTZBoss,id(a1) ; load obj54 move.b #6,boss_subtype(a1) ; => Obj54_LaserShooter move.b #$13,mapping_frame(a1) move.l #Obj54_MapUnc_32DC6,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_MTZBoss,0,0),art_tile(a1) ori.b #4,render_flags(a1) move.b #6,priority(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.l a0,objoff_34(a1) move.b #$20,width_pixels(a1) jsrto (SingleObjLoad).l, JmpTo17_SingleObjLoad bne.s + move.b #ObjID_MTZBossOrb,id(a1) ; load obj53 move.l a0,objoff_34(a1) + lea (Boss_AnimationArray).w,a2 move.b #$10,(a2)+ move.b #0,(a2)+ move.b #3,(a2)+ move.b #0,(a2)+ move.b #1,(a2)+ move.b #0,(a2)+ rts ; =========================================================================== ;loc_323BA Obj54_Main: moveq #0,d0 move.b angle(a0),d0 move.w Obj54_MainSubStates(pc,d0.w),d1 jmp Obj54_MainSubStates(pc,d1.w) ; =========================================================================== Obj54_MainSubStates: offsetTable offsetTableEntry.w Obj54_MainSub0 ; 0 offsetTableEntry.w Obj54_MainSub2 ; 2 offsetTableEntry.w Obj54_MainSub4 ; 4 offsetTableEntry.w Obj54_MainSub6 ; 6 offsetTableEntry.w Obj54_MainSub8 ; 8 offsetTableEntry.w Obj54_MainSubA ; $A offsetTableEntry.w Obj54_MainSubC ; $C offsetTableEntry.w Obj54_MainSubE ; $E offsetTableEntry.w Obj54_MainSub10 ; $10 offsetTableEntry.w Obj54_MainSub12 ; $12 ; =========================================================================== ;loc_323DC Obj54_MainSub0: bsr.w Boss_MoveObject move.w (Boss_Y_pos).w,y_pos(a0) cmpi.w #$4A0,(Boss_Y_pos).w blo.s + addq.b #2,angle(a0) ; => Obj54_MainSub2 move.w #0,(Boss_Y_vel).w move.w #-$100,(Boss_X_vel).w bclr #7,objoff_2B(a0) bclr #0,render_flags(a0) move.w (MainCharacter+x_pos).w,d0 cmp.w (Boss_X_pos).w,d0 blo.s + move.w #$100,(Boss_X_vel).w bset #7,objoff_2B(a0) bset #0,render_flags(a0) + bsr.w Obj54_AnimateFace lea (Ani_obj53).l,a1 bsr.w AnimateBoss bsr.w Obj54_AlignSprites jmpto (DisplaySprite).l, JmpTo40_DisplaySprite ; =========================================================================== ;loc_3243C Obj54_Float: move.b mapping_frame(a0),d0 jsr (CalcSine).l asr.w #6,d0 add.w (Boss_Y_pos).w,d0 move.w d0,y_pos(a0) addq.b #4,mapping_frame(a0) rts ; =========================================================================== ;loc_32456 Obj54_MainSub2: bsr.w Boss_MoveObject btst #7,objoff_2B(a0) bne.s + cmpi.w #$2AD0,(Boss_X_pos).w bhs.s Obj54_MoveAndShow bchg #7,objoff_2B(a0) move.w #$100,(Boss_X_vel).w bset #0,render_flags(a0) bset #6,objoff_2B(a0) beq.s Obj54_MoveAndShow addq.b #2,angle(a0) ; => Obj54_MainSub4 move.w #-$100,(Boss_Y_vel).w bra.s Obj54_MoveAndShow ; =========================================================================== + cmpi.w #$2BD0,(Boss_X_pos).w blo.s Obj54_MoveAndShow bchg #7,objoff_2B(a0) move.w #-$100,(Boss_X_vel).w bclr #0,render_flags(a0) bset #6,objoff_2B(a0) beq.s Obj54_MoveAndShow addq.b #2,angle(a0) ; => Obj54_MainSub4 move.w #-$100,(Boss_Y_vel).w ;loc_324BC Obj54_MoveAndShow: move.w (Boss_X_pos).w,x_pos(a0) bsr.w Obj54_Float ;loc_324C6 Obj54_Display: bsr.w Obj54_AnimateFace lea (Ani_obj53).l,a1 bsr.w AnimateBoss bsr.w Obj54_AlignSprites jmpto (DisplaySprite).l, JmpTo40_DisplaySprite ; =========================================================================== ;loc_324DC Obj54_MainSub4: bsr.w Boss_MoveObject cmpi.w #$470,(Boss_Y_pos).w bhs.s + move.w #0,(Boss_Y_vel).w + btst #7,objoff_2B(a0) bne.s + cmpi.w #$2B50,(Boss_X_pos).w bhs.s ++ move.w #0,(Boss_X_vel).w bra.s ++ ; =========================================================================== + cmpi.w #$2B50,(Boss_X_pos).w blo.s + move.w #0,(Boss_X_vel).w + move.w (Boss_X_vel).w,d0 or.w (Boss_Y_vel).w,d0 bne.s BranchTo_Obj54_MoveAndShow addq.b #2,angle(a0) ; => Obj54_MainSub6 BranchTo_Obj54_MoveAndShow bra.s Obj54_MoveAndShow ; =========================================================================== ;loc_32524 Obj54_MainSub6: cmpi.b #$68,objoff_33(a0) bhs.s + addq.b #1,objoff_33(a0) addq.b #1,objoff_39(a0) bra.s BranchTo2_Obj54_MoveAndShow ; =========================================================================== + subq.b #1,objoff_39(a0) bne.s BranchTo2_Obj54_MoveAndShow addq.b #2,angle(a0) ; => Obj54_MainSub8 BranchTo2_Obj54_MoveAndShow bra.w Obj54_MoveAndShow ; =========================================================================== ;loc_32544 Obj54_MainSub8: cmpi.b #$27,objoff_33(a0) blo.s + subq.b #1,objoff_33(a0) bra.s BranchTo3_Obj54_MoveAndShow ; =========================================================================== + addq.b #1,objoff_39(a0) cmpi.b #$27,objoff_39(a0) blo.s BranchTo3_Obj54_MoveAndShow move.w #$100,(Boss_Y_vel).w move.b #0,angle(a0) ; => Obj54_MainSub0 bclr #6,objoff_2B(a0) BranchTo3_Obj54_MoveAndShow bra.w Obj54_MoveAndShow ; =========================================================================== ;loc_32574 Obj54_MainSubA: tst.b objoff_39(a0) beq.s + subq.b #1,objoff_39(a0) bra.s ++ ; =========================================================================== + move.b #-1,objoff_3A(a0) + cmpi.b #$27,objoff_33(a0) blo.s + subq.b #1,objoff_33(a0) + bsr.w Boss_MoveObject cmpi.w #$420,(Boss_Y_pos).w bhs.s + move.w #0,(Boss_Y_vel).w + tst.b objoff_2C(a0) bne.s BranchTo4_Obj54_MoveAndShow tst.b objoff_3A(a0) beq.s + move.b #$80,objoff_3A(a0) + addq.b #2,angle(a0) ; => Obj54_MainSubC BranchTo4_Obj54_MoveAndShow bra.w Obj54_MoveAndShow ; =========================================================================== ;loc_325BE Obj54_MainSubC: tst.b objoff_3E(a0) beq.s ++ tst.b objoff_3A(a0) bne.s BranchTo5_Obj54_MoveAndShow cmpi.b #$27,objoff_39(a0) bhs.s + addq.b #1,objoff_39(a0) bra.s BranchTo5_Obj54_MoveAndShow ; =========================================================================== + move.w #$100,(Boss_Y_vel).w move.b #0,angle(a0) ; => Obj54_MainSub0 bclr #6,objoff_2B(a0) bra.s BranchTo5_Obj54_MoveAndShow ; =========================================================================== + move.w #-$180,(Boss_Y_vel).w move.w #-$100,(Boss_X_vel).w bclr #0,render_flags(a0) btst #7,objoff_2B(a0) beq.s + move.w #$100,(Boss_X_vel).w bset #0,render_flags(a0) + move.b #$E,angle(a0) ; => Obj54_MainSubE move.b #0,objoff_2E(a0) bclr #6,objoff_2B(a0) move.b #0,objoff_2F(a0) BranchTo5_Obj54_MoveAndShow bra.w Obj54_MoveAndShow ; =========================================================================== ;loc_3262E Obj54_MainSubE: tst.b objoff_2F(a0) beq.s + subq.b #1,objoff_2F(a0) bra.w Obj54_Display ; =========================================================================== + moveq #0,d0 move.b objoff_2E(a0),d0 move.w off_3264A(pc,d0.w),d1 jmp off_3264A(pc,d1.w) ; =========================================================================== off_3264A: offsetTable offsetTableEntry.w loc_32650 ; 0 offsetTableEntry.w loc_326B8 ; 2 offsetTableEntry.w loc_32704 ; 4 ; =========================================================================== loc_32650: bsr.w Boss_MoveObject cmpi.w #$420,(Boss_Y_pos).w bhs.s + move.w #0,(Boss_Y_vel).w + btst #7,objoff_2B(a0) bne.s + cmpi.w #$2AF0,(Boss_X_pos).w bhs.s BranchTo6_Obj54_MoveAndShow addq.b #2,objoff_2E(a0) move.w #$180,(Boss_Y_vel).w move.b #3,objoff_2D(a0) move.w #$1E,(Boss_Countdown).w bset #0,render_flags(a0) bra.s BranchTo6_Obj54_MoveAndShow ; =========================================================================== + cmpi.w #$2BB0,(Boss_X_pos).w blo.s BranchTo6_Obj54_MoveAndShow addq.b #2,objoff_2E(a0) move.w #$180,(Boss_Y_vel).w move.b #3,objoff_2D(a0) move.w #$1E,(Boss_Countdown).w bclr #0,render_flags(a0) BranchTo6_Obj54_MoveAndShow bra.w Obj54_MoveAndShow ; =========================================================================== loc_326B8: bsr.w Boss_MoveObject cmpi.w #$4A0,(Boss_Y_pos).w blo.s + move.w #-$180,(Boss_Y_vel).w addq.b #2,objoff_2E(a0) bchg #7,objoff_2B(a0) bra.s +++ ; =========================================================================== + btst #7,objoff_2B(a0) bne.s + cmpi.w #$2AD0,(Boss_X_pos).w bhs.s ++ move.w #0,(Boss_X_vel).w bra.s ++ ; =========================================================================== + cmpi.w #$2BD0,(Boss_X_pos).w blo.s + move.w #0,(Boss_X_vel).w + bsr.w Obj54_FireLaser bra.w Obj54_MoveAndShow ; =========================================================================== loc_32704: bsr.w Boss_MoveObject cmpi.w #$470,(Boss_Y_pos).w bhs.s + move.w #$100,(Boss_X_vel).w btst #7,objoff_2B(a0) bne.s + move.w #-$100,(Boss_X_vel).w + cmpi.w #$420,(Boss_Y_pos).w bhs.s + move.w #0,(Boss_Y_vel).w move.b #0,objoff_2E(a0) + bsr.w Obj54_FireLaser bra.w Obj54_MoveAndShow ; =========================================================================== ;loc_32740 Obj54_FireLaser: subi_.w #1,(Boss_Countdown).w bne.s + ; rts tst.b objoff_2D(a0) beq.s + ; rts subq.b #1,objoff_2D(a0) jsrto (SingleObjLoad).l, JmpTo17_SingleObjLoad bne.s + ; rts move.b #ObjID_MTZBoss,id(a1) ; load obj54 move.b #4,boss_subtype(a1) ; => Obj54_Laser move.l a0,objoff_34(a1) move.w #$1E,(Boss_Countdown).w move.b #$10,objoff_2F(a0) + rts ; =========================================================================== ;loc_32774 Obj54_AlignSprites: move.w x_pos(a0),d0 move.w y_pos(a0),d1 move.w d0,sub2_x_pos(a0) move.w d1,sub2_y_pos(a0) move.w d0,sub3_x_pos(a0) move.w d1,sub3_y_pos(a0) rts ; =========================================================================== ;loc_3278E Obj54_AnimateFace: bsr.w Obj54_CheckHit cmpi.b #$3F,boss_invulnerable_time(a0) bne.s ++ st.b objoff_38(a0) lea (Boss_AnimationArray).w,a1 andi.b #$F0,2(a1) ori.b #5,2(a1) tst.b objoff_3E(a0) beq.s + move.b #$A,angle(a0) ; => Obj54_MainSubA move.w #-$180,(Boss_Y_vel).w subq.b #1,objoff_3E(a0) move.w #0,(Boss_X_vel).w + move.w #0,(Boss_X_vel).w rts ; =========================================================================== + cmpi.b #4,(MainCharacter+routine).w beq.s + cmpi.b #4,(Sidekick+routine).w bne.s ++ ; rts + lea (Boss_AnimationArray).w,a1 move.b 2(a1),d0 andi.b #$F,d0 cmpi.b #4,d0 beq.s + ; rts andi.b #$F0,2(a1) ori.b #4,2(a1) + rts ; =========================================================================== ;loc_32802 Obj54_MainSub10: subq.w #1,(Boss_Countdown).w cmpi.w #$3C,(Boss_Countdown).w blo.s ++ bmi.s + bsr.w Boss_LoadExplosion lea (Boss_AnimationArray).w,a1 move.b #7,2(a1) bra.s ++ ; =========================================================================== + bset #0,render_flags(a0) clr.w (Boss_X_vel).w clr.w (Boss_Y_vel).w addq.b #2,angle(a0) ; => Obj54_MainSub12 move.w #-$12,(Boss_Countdown).w lea (Boss_AnimationArray).w,a1 move.b #3,2(a1) jsrto (PlayLevelMusic).l, JmpTo7_PlayLevelMusic + move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) lea (Ani_obj53).l,a1 bsr.w AnimateBoss bsr.w Obj54_AlignSprites jmpto (DisplaySprite).l, JmpTo40_DisplaySprite ; =========================================================================== ;loc_32864 Obj54_MainSub12: move.w #$400,(Boss_X_vel).w move.w #-$40,(Boss_Y_vel).w cmpi.w #$2BF0,(Camera_Max_X_pos).w bhs.s + addq.w #2,(Camera_Max_X_pos).w bra.s ++ ; =========================================================================== + tst.b render_flags(a0) bpl.s JmpTo60_DeleteObject + tst.b (Boss_defeated_flag).w bne.s + move.b #1,(Boss_defeated_flag).w jsrto (LoadPLC_AnimalExplosion).l, JmpTo7_LoadPLC_AnimalExplosion + bsr.w Boss_MoveObject bsr.w loc_328C0 move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) lea (Ani_obj53).l,a1 bsr.w AnimateBoss bsr.w Obj54_AlignSprites jmpto (DisplaySprite).l, JmpTo40_DisplaySprite ; =========================================================================== JmpTo60_DeleteObject jmp (DeleteObject).l ; =========================================================================== loc_328C0: move.b mapping_frame(a0),d0 jsr (CalcSine).l asr.w #6,d0 add.w (Boss_Y_pos).w,d0 move.w d0,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) addq.b #2,mapping_frame(a0) ;loc_328DE Obj54_CheckHit: cmpi.b #$10,angle(a0) bhs.s return_32924 tst.b boss_hitcount2(a0) beq.s Obj54_Defeated tst.b collision_flags(a0) bne.s return_32924 tst.b boss_invulnerable_time(a0) bne.s + move.b #$40,boss_invulnerable_time(a0) move.w #SndID_BossHit,d0 jsr (PlaySound).l + lea (Normal_palette_line2+2).w,a1 moveq #0,d0 tst.w (a1) bne.s + move.w #$EEE,d0 + move.w d0,(a1) subq.b #1,boss_invulnerable_time(a0) bne.s return_32924 move.b #$F,collision_flags(a0) return_32924: rts ; =========================================================================== ;loc_32926 Obj54_Defeated: moveq #100,d0 jsrto (AddPoints).l, JmpTo8_AddPoints move.w #$EF,(Boss_Countdown).w move.b #$10,angle(a0) ; => Obj54_MainSub10 moveq #PLCID_Capsule,d0 jsrto (LoadPLC).l, JmpTo11_LoadPLC rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 53 - Shield orbs that surround MTZ boss ; ---------------------------------------------------------------------------- ; Sprite_32940: Obj53: moveq #0,d0 move.b routine(a0),d0 move.w Obj53_Index(pc,d0.w),d1 jmp Obj53_Index(pc,d1.w) ; =========================================================================== ; off_3294E: Obj53_Index: offsetTable offsetTableEntry.w Obj53_Init ; 0 offsetTableEntry.w Obj53_Main ; 2 offsetTableEntry.w Obj53_BreakAway ; 4 offsetTableEntry.w Obj53_BounceAround ; 6 offsetTableEntry.w Obj53_Burst ; 8 ; =========================================================================== ; loc_32958: Obj53_Init: movea.l a0,a1 moveq #6,d3 moveq #0,d2 bra.s + ; =========================================================================== - jsrto (SingleObjLoad).l, JmpTo17_SingleObjLoad bne.s ++ + move.b #$20,width_pixels(a1) move.l objoff_34(a0),objoff_34(a1) move.b #ObjID_MTZBossOrb,id(a1) ; load obj53 move.l #Obj54_MapUnc_32DC6,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_MTZBoss,0,0),art_tile(a1) ori.b #4,render_flags(a1) move.b #3,priority(a1) addq.b #2,routine(a1) ; => Obj53_Main move.b #5,mapping_frame(a1) move.b byte_329CC(pc,d2.w),objoff_28(a1) move.b byte_329CC(pc,d2.w),objoff_3B(a1) move.b byte_329D3(pc,d2.w),objoff_3A(a1) move.b #$40,objoff_29(a1) move.b #$87,collision_flags(a1) move.b #2,collision_property(a1) move.b #0,objoff_3C(a1) addq.w #1,d2 dbf d3,- + rts ; =========================================================================== byte_329CC: dc.b $24 dc.b $6C ; 1 dc.b $B4 ; 2 dc.b $FC ; 3 dc.b $48 ; 4 dc.b $90 ; 5 dc.b $D8 ; 6 rev02even byte_329D3: dc.b 0 dc.b 1 ; 1 dc.b 1 ; 2 dc.b 0 ; 3 dc.b 1 ; 4 dc.b 1 ; 5 dc.b 0 ; 6 even ; =========================================================================== ;loc_329DA Obj53_Main: movea.l objoff_34(a0),a1 ; a1=object move.w y_pos(a1),objoff_2A(a0) subi_.w #4,objoff_2A(a0) move.w x_pos(a1),objoff_38(a0) tst.b objoff_38(a1) beq.s Obj53_ClearBossCollision move.b #0,objoff_38(a1) addi_.b #1,objoff_2C(a1) addq.b #2,routine(a0) ; => Obj53_BreakAway move.b #$3C,objoff_32(a0) move.b #2,anim(a0) move.w #-$400,y_vel(a0) move.w #-$80,d1 move.w (MainCharacter+x_pos).w,d0 sub.w x_pos(a0),d0 bpl.s + neg.w d1 + cmpi.w #$2AF0,x_pos(a0) bhs.s + move.w #$80,d1 + cmpi.w #$2BB0,x_pos(a0) blo.s + move.w #-$80,d1 + bclr #0,render_flags(a0) tst.w d1 bmi.s + bset #0,render_flags(a0) + move.w d1,x_vel(a0) bra.s + ; =========================================================================== ;loc_32A56 Obj53_ClearBossCollision: cmpi.b #2,collision_property(a0) beq.s + move.b #0,collision_flags(a1) + bsr.w Obj53_OrbitBoss bsr.w Obj53_SetAnimPriority jmpto (DisplaySprite).l, JmpTo40_DisplaySprite ; =========================================================================== ;loc_32A70 Obj53_OrbitBoss: move.b objoff_29(a0),d0 jsr (CalcSine).l move.w d0,d3 moveq #0,d1 move.b objoff_33(a1),d1 muls.w d1,d0 move.w d0,d5 move.w d0,d4 move.b objoff_39(a1),d2 tst.b objoff_3A(a1) beq.s + move.w #$10,d2 + muls.w d3,d2 move.w objoff_38(a0),d6 move.b objoff_28(a0),d0 jsr (CalcSine).l muls.w d0,d5 swap d5 add.w d6,d5 move.w d5,x_pos(a0) muls.w d1,d4 swap d4 move.w d4,objoff_30(a0) move.w objoff_2A(a0),d6 move.b objoff_3B(a0),d0 tst.b objoff_3A(a1) beq.s + move.b objoff_3C(a0),d0 + jsr (CalcSine).l muls.w d0,d2 swap d2 add.w d6,d2 move.w d2,y_pos(a0) addq.b #4,objoff_28(a0) tst.b objoff_3A(a1) bne.s + addq.b #8,objoff_3B(a0) rts ; =========================================================================== + cmpi.b #-1,objoff_3A(a1) beq.s ++ cmpi.b #$80,objoff_3A(a1) bne.s + subq.b #2,objoff_3C(a0) bpl.s return_32B18 clr.b objoff_3C(a0) + move.b #0,objoff_3A(a1) rts ; =========================================================================== + cmpi.b #$40,objoff_3C(a0) bhs.s return_32B18 addq.b #2,objoff_3C(a0) return_32B18: rts ; =========================================================================== ;loc_32B1A Obj53_SetAnimPriority: move.w objoff_30(a0),d0 bmi.s ++ cmpi.w #$C,d0 blt.s + move.b #3,mapping_frame(a0) move.b #1,priority(a0) rts ; =========================================================================== + move.b #4,mapping_frame(a0) move.b #2,priority(a0) rts ; =========================================================================== + cmpi.w #-$C,d0 blt.s + move.b #4,mapping_frame(a0) move.b #6,priority(a0) rts ; =========================================================================== + move.b #5,mapping_frame(a0) move.b #7,priority(a0) rts ; =========================================================================== ;loc_32B64 Obj53_BreakAway: tst.b objoff_32(a0) bmi.s + subq.b #1,objoff_32(a0) bpl.s + move.b #$DA,collision_flags(a0) + jsrto (ObjectMoveAndFall).l, JmpTo6_ObjectMoveAndFall subi.w #$20,y_vel(a0) cmpi.w #$180,y_vel(a0) blt.s + move.w #$180,y_vel(a0) + cmpi.w #$4AC,y_pos(a0) blo.s Obj53_Animate move.w #$4AC,y_pos(a0) move.w #$4AC,objoff_2E(a0) move.b #1,objoff_2C(a0) addq.b #2,routine(a0) bsr.w Obj53_FaceLeader ;loc_32BB0 Obj53_Animate: bsr.w + lea (Ani_obj53).l,a1 jsrto (AnimateSprite).l, JmpTo21_AnimateSprite jmpto (DisplaySprite).l, JmpTo40_DisplaySprite ; =========================================================================== + cmpi.b #-2,collision_property(a0) bgt.s + ; rts move.b #$14,mapping_frame(a0) move.b #6,anim(a0) addq.b #2,routine(a0) + rts ; =========================================================================== ;loc_32BDC Obj53_BounceAround: tst.b objoff_32(a0) bmi.s + subq.b #1,objoff_32(a0) bpl.s + move.b #$DA,collision_flags(a0) + bsr.w Obj53_CheckPlayerHit cmpi.b #$B,mapping_frame(a0) bne.s Obj53_Animate move.b objoff_2C(a0),d0 jsr (CalcSine).l neg.w d0 asr.w #2,d0 add.w objoff_2E(a0),d0 cmpi.w #$4AC,d0 bhs.s ++ move.w d0,y_pos(a0) addq.b #1,objoff_2C(a0) btst #0,objoff_2C(a0) beq.w JmpTo40_DisplaySprite moveq #-1,d0 btst #0,render_flags(a0) beq.s + neg.w d0 + add.w d0,x_pos(a0) jmpto (DisplaySprite).l, JmpTo40_DisplaySprite ; =========================================================================== + move.w #$4AC,y_pos(a0) bsr.w Obj53_FaceLeader move.b #1,objoff_2C(a0) jmpto (DisplaySprite).l, JmpTo40_DisplaySprite ; =========================================================================== ;loc_32C4C Obj53_FaceLeader: move.w (MainCharacter+x_pos).w,d0 sub.w x_pos(a0),d0 bpl.s + bclr #0,render_flags(a0) rts ; =========================================================================== + bset #0,render_flags(a0) rts ; =========================================================================== ;loc_32C66 Obj53_CheckPlayerHit: cmpi.b #4,(MainCharacter+routine).w beq.s + cmpi.b #4,(Sidekick+routine).w bne.s ++ + move.b #$14,mapping_frame(a0) move.b #6,anim(a0) + cmpi.b #-2,collision_property(a0) bgt.s + move.b #$14,mapping_frame(a0) move.b #6,anim(a0) + rts ; =========================================================================== ;loc_32C98 Obj53_Burst: move.b #SndID_BossExplosion,d0 jsrto (PlaySound).l, JmpTo10_PlaySound movea.l objoff_34(a0),a1 ; a1=object subi_.b #1,objoff_2C(a1) if removeJmpTos JmpTo61_DeleteObject endif jmpto (DeleteObject).l, JmpTo61_DeleteObject ; =========================================================================== ;loc_32CAE Obj54_Laser: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_32CBC(pc,d0.w),d0 jmp off_32CBC(pc,d0.w) ; =========================================================================== off_32CBC: offsetTable offsetTableEntry.w Obj54_Laser_Init ; 0 offsetTableEntry.w Obj54_Laser_Main ; 2 ; =========================================================================== ;loc_32CC0 Obj54_Laser_Init: move.l #Obj54_MapUnc_32DC6,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_MTZBoss,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #5,priority(a0) move.b #$12,mapping_frame(a0) addq.b #2,routine_secondary(a0) ; => Obj54_Laser_Main movea.l objoff_34(a0),a1 ; a1=object move.b #$50,width_pixels(a0) move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) addi_.w #7,y_pos(a0) subi_.w #4,x_pos(a0) move.w #-$400,d0 btst #0,render_flags(a1) beq.s + neg.w d0 addi_.w #8,x_pos(a0) + move.w d0,x_vel(a0) move.b #$99,collision_flags(a0) move.b #SndID_LaserBurst,d0 jsrto (PlaySound).l, JmpTo10_PlaySound ;loc_32D2C Obj54_Laser_Main: jsrto (ObjectMove).l, JmpTo24_ObjectMove cmpi.w #$2AB0,x_pos(a0) blo.w JmpTo61_DeleteObject cmpi.w #$2BF0,x_pos(a0) bhs.w JmpTo61_DeleteObject jmpto (DisplaySprite).l, JmpTo40_DisplaySprite ; =========================================================================== ;loc_32D48 Obj54_LaserShooter: movea.l objoff_34(a0),a1 ; a1=object cmpi.b #ObjID_MTZBoss,id(a1) bne.w JmpTo61_DeleteObject move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) bclr #0,render_flags(a0) btst #0,render_flags(a1) beq.w JmpTo40_DisplaySprite bset #0,render_flags(a0) if removeJmpTos JmpTo40_DisplaySprite endif jmpto (DisplaySprite).l, JmpTo40_DisplaySprite ; =========================================================================== ; animation script ; off_32D7A: Ani_obj53: offsetTable offsetTableEntry.w byte_32D8A ; 0 offsetTableEntry.w byte_32D8D ; 1 offsetTableEntry.w byte_32D91 ; 2 offsetTableEntry.w byte_32DA6 ; 3 offsetTableEntry.w byte_32DAA ; 4 offsetTableEntry.w byte_32DB5 ; 5 offsetTableEntry.w byte_32DC0 ; 6 offsetTableEntry.w byte_32DC3 ; 7 byte_32D8A: dc.b $F, 2,$FF rev02even byte_32D8D: dc.b 1, 0, 1,$FF rev02even byte_32D91: dc.b 3, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 6, 7, 6, 7, 8 dc.b 9, $A, $B,$FE, 1; 16 rev02even byte_32DA6: dc.b 7, $C, $D,$FF rev02even byte_32DAA: dc.b 7, $E, $F, $E, $F, $E, $F, $E, $F,$FD, 3 rev02even byte_32DB5: dc.b 7,$10,$10,$10,$10,$10,$10,$10,$10,$FD, 3 rev02even byte_32DC0: dc.b 1,$14,$FC rev02even byte_32DC3: dc.b 7,$11,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj54_MapUnc_32DC6: BINCLUDE "mappings/sprite/obj54.bin" if ~~removeJmpTos align 4 endif ; =========================================================================== if ~~removeJmpTos JmpTo40_DisplaySprite jmp (DisplaySprite).l JmpTo61_DeleteObject jmp (DeleteObject).l JmpTo17_SingleObjLoad jmp (SingleObjLoad).l JmpTo10_PlaySound jmp (PlaySound).l JmpTo21_AnimateSprite jmp (AnimateSprite).l JmpTo11_LoadPLC jmp (LoadPLC).l JmpTo8_AddPoints jmp (AddPoints).l JmpTo7_PlayLevelMusic jmp (PlayLevelMusic).l JmpTo7_LoadPLC_AnimalExplosion jmp (LoadPLC_AnimalExplosion).l JmpTo6_ObjectMoveAndFall jmp (ObjectMoveAndFall).l ; loc_32F88: JmpTo24_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 55 - OOZ boss ; ---------------------------------------------------------------------------- ; OST Variables: Obj55_status = objoff_2A ; bitfield Obj55_anim_frame_duration = objoff_2C ; number of frames the laser shooter displays its shooting frame Obj55_shot_count = objoff_38 ; number of lasers the shooter fires during its attack phase Obj55_laser_pos = objoff_3E ; bitfield, each of the first four bits stands for one of the possible y positions a laser can be fired from Obj55_Wave_delay = objoff_32 ; time before the next part of the wave is created Obj55_Wave_parent = objoff_34 ; pointer to main vehicle Obj55_Wave_count = objoff_36 ; number of waves to make ; Sprite_32F90: Obj55: moveq #0,d0 move.b boss_subtype(a0),d0 move.w Obj55_Index(pc,d0.w),d1 jmp Obj55_Index(pc,d1.w) ; =========================================================================== ; off_32F9E: Obj55_Index: offsetTable offsetTableEntry.w Obj55_Init ; 0 - Init offsetTableEntry.w Obj55_Main ; 2 - Main Vehicle offsetTableEntry.w Obj55_LaserShooter ; 4 - Laser Shooter offsetTableEntry.w Obj55_SpikeChain ; 6 - Spiked Chain offsetTableEntry.w Obj55_Laser ; 8 - Laser ; =========================================================================== ; loc_32FA8: Obj55_Init: move.l #Obj55_MapUnc_33756,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_OOZBoss,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #3,priority(a0) bset #6,render_flags(a0) ; object consists of multiple sprites move.b #0,mainspr_childsprites(a0) addq.b #2,boss_subtype(a0) ; => Obj55_Main move.b #$F,collision_flags(a0) move.b #8,boss_hitcount2(a0) move.b #$40,mainspr_width(a0) rts ; =========================================================================== ; loc_32FE6: Obj55_Main: moveq #0,d0 move.b boss_routine(a0),d0 move.w Obj55_Main_Index(pc,d0.w),d1 jmp Obj55_Main_Index(pc,d1.w) ; =========================================================================== ; off_32FF4: Obj55_Main_Index: offsetTable offsetTableEntry.w Obj55_Main_Init ; 0 - boss' initial state offsetTableEntry.w Obj55_Main_Surface ; 2 - moving up offsetTableEntry.w Obj55_Main_Wait ; 4 - stay in place for a while offsetTableEntry.w Obj55_Main_Dive ; 6 - moving down offsetTableEntry.w Obj55_Main_Defeated ; 8 - boss defeated and escaping ; =========================================================================== ; loc_32FFE: Obj55_Main_Init: move.w #$2940,(Boss_X_pos).w bclr #0,render_flags(a0) ; face right move.w (MainCharacter+x_pos).w,d1 cmpi.w #$293A,d1 ; is player on the left side of the arena? bhs.s + ; if not, branch bchg #0,render_flags(a0) ; face left + move.w #$2D0,y_pos(a0) move.w #$2D0,(Boss_Y_pos).w move.b #8,mainspr_mapframe(a0) move.b #1,mainspr_childsprites(a0) addq.b #2,boss_routine(a0) ; => Obj55_Main_Surface move.w #-$80,(Boss_Y_vel).w move.b #$F,collision_flags(a0) move.w x_pos(a0),sub2_x_pos(a0) move.w y_pos(a0),sub2_y_pos(a0) clr.b boss_sine_count(a0) clr.b Obj55_status(a0) move.b #8,sub2_mapframe(a0) lea (Boss_AnimationArray).w,a2 move.b #5,(a2)+ move.b #0,(a2)+ move.b #1,(a2)+ move.b #0,(a2) move.b #0,(Boss_CollisionRoutine).w rts ; =========================================================================== ; loc_33078: Obj55_Main_Surface: bsr.w Boss_MoveObject move.w (Boss_X_pos).w,x_pos(a0) bsr.w Obj55_HoverPos cmpi.w #$290,(Boss_Y_pos).w ; has boss reached its target position? bhs.w Obj55_Main_End ; if not, branch move.w #$290,(Boss_Y_pos).w addq.b #2,boss_routine(a0) ; => Obj55_Main_Wait move.w #$A8,(Boss_Countdown).w btst #7,Obj55_status(a0) ; was boss hit? bne.w Obj55_Main_End ; if yes, branch lea (Boss_AnimationArray).w,a2 move.b #$10,(a2)+ move.b #0,(a2) bra.w Obj55_Main_End ; =========================================================================== ; loc_330BA: Obj55_Main_Wait: btst #7,Obj55_status(a0) ; was boss hit? bne.s + ; if yes, branch bsr.w Obj55_HoverPos subi_.w #1,(Boss_Countdown).w ; hover in place for a while bpl.w Obj55_Main_End lea (Boss_AnimationArray).w,a2 move.b #5,(a2)+ move.b #0,(a2) + addq.b #2,boss_routine(a0) ; => Obj55_Main_Dive move.w #-$40,(Boss_Y_vel).w ; bob up a little before diving bra.w Obj55_Main_End ; =========================================================================== ; does the hovering effect ; loc_330EA: Obj55_HoverPos: move.b boss_sine_count(a0),d0 jsr (CalcSine).l asr.w #7,d1 add.w (Boss_Y_pos).w,d1 move.w d1,y_pos(a0) addq.b #4,boss_sine_count(a0) rts ; =========================================================================== ; loc_33104: Obj55_Main_Dive: bsr.w Boss_MoveObject move.w (Boss_Y_pos).w,y_pos(a0) move.w (Boss_X_pos).w,x_pos(a0) btst #6,Obj55_status(a0) ; is boss done rising? bne.s Obj55_Main_Dive_Part2 ; if yes, branch cmpi.w #$28C,(Boss_Y_pos).w ; has boss reached initial destination (rising before diving)? bhs.w Obj55_Main_End ; if not, branch move.w #$28C,(Boss_Y_pos).w move.w #$80,(Boss_Y_vel).w ori.b #$40,Obj55_status(a0) ; set diving bit bra.w Obj55_Main_End ; =========================================================================== ; loc_3313C: Obj55_Main_Dive_Part2: cmpi.w #$2D0,(Boss_Y_pos).w ; has boss reached its target position? blo.s Obj55_Main_End ; if yes, branch move.w #$2D0,(Boss_Y_pos).w clr.b boss_routine(a0) addq.b #2,boss_subtype(a0) ; => Obj55_LaserShooter btst #7,Obj55_status(a0) ; was boss hit? beq.s Obj55_Main_End ; if not, branch addq.b #2,boss_subtype(a0) ; => Obj55_SpikeChain ; loc_3315E: Obj55_Main_End: bsr.w Obj55_HandleHits lea (Ani_obj55).l,a1 bsr.w AnimateBoss bsr.w Obj55_AlignSprites jmpto (DisplaySprite).l, JmpTo41_DisplaySprite ; =========================================================================== ; loc_33174: Obj55_HandleHits: bsr.w Boss_HandleHits cmpi.b #$1F,boss_invulnerable_time(a0) bne.s return_33192 lea (Boss_AnimationArray).w,a1 andi.b #$F0,(a1) ori.b #3,(a1) ori.b #$80,Obj55_status(a0) ; set boss hit bit return_33192: rts ; =========================================================================== ; loc_33194: Obj55_AlignSprites: move.w x_pos(a0),d0 move.w y_pos(a0),d1 move.w d0,sub2_x_pos(a0) move.w d1,sub2_y_pos(a0) rts ; =========================================================================== ; loc_331A6: Obj55_Main_Defeated: clr.w (Normal_palette_line2+2).w ; set color to black subq.w #1,(Boss_Countdown).w ; wait for a while bmi.s Obj55_Main_Defeated_Part2 ; branch, if wait is over cmpi.w #$1E,(Boss_Countdown).w ; has boss waited for a certain ammount of time? bhs.s Obj55_Explode ; if not, branch move.b #$B,mainspr_mapframe(a0) ; use defeated animation jmpto (DisplaySprite).l, JmpTo41_DisplaySprite ; =========================================================================== ; loc_331C2: Obj55_Explode: bsr.w Boss_LoadExplosion jmpto (DisplaySprite).l, JmpTo41_DisplaySprite ; =========================================================================== ; loc_331CA: Obj55_Main_Defeated_Part2: tst.b (Boss_defeated_flag).w ; has boss been defeated? bne.s Obj55_ReleaseCamera ; if yes, branch jsrto (PlayLevelMusic).l, JmpTo8_PlayLevelMusic jsrto (LoadPLC_AnimalExplosion).l, JmpTo8_LoadPLC_AnimalExplosion move.b #1,(Boss_defeated_flag).w ; loc_331DE: Obj55_ReleaseCamera: cmpi.w #$2A20,(Camera_Max_X_pos).w ; has camera reached its destination? bhs.s Obj55_ChkDelete ; if yes, branch addq.w #2,(Camera_Max_X_pos).w ; else, move camera some more bra.s Obj55_Defeated_Sink ; =========================================================================== ; loc_331EC: Obj55_ChkDelete: move.w #$2A20,(Camera_Max_X_pos).w cmpi.w #$2D0,y_pos(a0) ; has boss reached its target position? bhs.s BranchTo_JmpTo62_DeleteObject ; if yes, branch ; loc_331FA: Obj55_Defeated_Sink: addi_.w #1,y_pos(a0) bsr.s Obj55_AlignSprites jmpto (DisplaySprite).l, JmpTo41_DisplaySprite ; =========================================================================== if removeJmpTos JmpTo62_DeleteObject endif BranchTo_JmpTo62_DeleteObject jmpto (DeleteObject).l, JmpTo62_DeleteObject ; =========================================================================== ; loc_3320A: Obj55_LaserShooter: moveq #0,d0 move.b boss_routine(a0),d0 move.w Obj55_LaserShooter_Index(pc,d0.w),d1 jmp Obj55_LaserShooter_Index(pc,d1.w) ; =========================================================================== ; off_33218: Obj55_LaserShooter_Index: offsetTable offsetTableEntry.w Obj55_LaserShooter_Init ; 0 - laser shooter's initial state offsetTableEntry.w Obj55_LaserShooter_Rise ; 2 - moving up offsetTableEntry.w Obj55_LaserShooter_ChooseTarget ; 4 - stay in place for a while offsetTableEntry.w Obj55_LaserShooter_Aim ; 6 - move towards target and shoot offsetTableEntry.w Obj55_LaserShooter_Lower ; 8 - moving down ; =========================================================================== ; loc_33222: Obj55_LaserShooter_Init: clr.w (Normal_palette_line2+2).w ; reset palette flash move.w #$2940,(Boss_X_pos).w bclr #0,render_flags(a0) move.w (MainCharacter+x_pos).w,d1 cmpi.w #$293A,d1 ; is player left from center? blo.s + ; if yes, branch bchg #0,render_flags(a0) + move.w #$2B0,(Boss_Y_pos).w move.w #$2B0,y_pos(a0) move.b #2,boss_routine(a0) ; => Obj55_LaserShooter_Rise move.b #$8A,collision_flags(a0) move.b #5,mainspr_mapframe(a0) moveq #7,d0 moveq #7,d2 moveq #0,d4 move.w (Boss_Y_pos).w,d5 - ; initialize chain addi.w #$F,d5 move.b d0,sub2_mapframe(a0,d4.w) move.w d5,sub2_y_pos(a0,d4.w) addq.w #next_subspr,d4 dbf d2,- move.b #8,mainspr_childsprites(a0) move.w #-$80,(Boss_Y_vel).w move.b #0,Obj55_laser_pos(a0) move.b #1,(Boss_CollisionRoutine).w rts ; =========================================================================== ; loc_33296: Obj55_LaserShooter_Rise: bsr.w Boss_MoveObject cmpi.w #$240,(Boss_Y_pos).w ; has laser shooter reached its destination? bhs.w Obj55_LaserShooter_End ; if not, branch move.w #$240,(Boss_Y_pos).w move.w #0,(Boss_Y_vel).w addi_.b #2,boss_routine(a0) ; => Obj55_LaserShooter_ChooseTarget move.w #$80,(Boss_Countdown).w move.b #3,Obj55_shot_count(a0) ; prepare to shoot 3 lasers bra.w Obj55_LaserShooter_End ; =========================================================================== ; loc_332C6: Obj55_LaserShooter_ChooseTarget: subq.b #1,Obj55_anim_frame_duration(a0) ; is firing animation finished? bne.s + ; if not, branch move.b #5,mainspr_mapframe(a0) ; reset animation frame to not firing + subi_.w #1,(Boss_Countdown).w ; wait for a while bne.w Obj55_LaserShooter_End ; branch, as long as wait isn't over subi_.b #1,Obj55_shot_count(a0) ; decrement number of shots left bmi.s Obj55_LaserShooter_DoneShooting ; branch, if no shots left jsrto (RandomNumber).l, JmpTo5_RandomNumber - ; find first valid firing position addq.b #1,d0 ; next position andi.w #3,d0 ; limit to 4 possible values btst d0,Obj55_laser_pos(a0) ; was a laser already shot in this position? bne.s - ; if yes, branch bset d0,Obj55_laser_pos(a0) ; set posion as used add.w d0,d0 move.w Obj55_LaserTargets(pc,d0.w),(Boss_Countdown).w ; set target positon addq.b #2,boss_routine(a0) ; => Obj55_LaserShooter_Aim bsr.w Obj55_MoveTowardTarget bra.w Obj55_LaserShooter_End ; =========================================================================== ; loc_3330C: Obj55_LaserShooter_DoneShooting: move.w #$80,(Boss_Y_vel).w move.b #8,boss_routine(a0) ; => Obj55_LaserShooter_Lower bra.w Obj55_LaserShooter_End ; =========================================================================== ; word_3331C: Obj55_LaserTargets: dc.w $238 ; 0 dc.w $230 ; 2 dc.w $240 ; 4 dc.w $25F ; 6 ; =========================================================================== ; loc_33324: Obj55_LaserShooter_Aim: bsr.w Boss_MoveObject move.w (Boss_Countdown).w,d0 tst.w (Boss_Y_vel).w ; is laser shooter moving up? bmi.s Obj55_LaserShooter_Aim_MovingUp ; if yes, branch cmp.w (Boss_Y_pos).w,d0 ; has laser shooter reached its destination? blo.s Obj55_LaserShooter_Fire ; if yes, branch bra.w Obj55_LaserShooter_End ; =========================================================================== ; loc_3333C: Obj55_LaserShooter_Aim_MovingUp: cmp.w (Boss_Y_pos).w,d0 ; has laser shooter reached its destination? blo.s Obj55_LaserShooter_End ; if not, branch ; loc_33342: Obj55_LaserShooter_Fire: move.w #0,(Boss_Y_vel).w move.b #8,Obj55_anim_frame_duration(a0) move.b #6,mainspr_mapframe(a0) ; use firing frame jsrto (SingleObjLoad).l, JmpTo18_SingleObjLoad bne.w Obj55_LaserShooter_End move.b #ObjID_OOZBoss,id(a1) ; load obj55 move.b #8,boss_subtype(a1) ; => Obj55_Laser move.l a0,Obj55_Wave_parent(a1) move.b #SndID_LaserBurst,d0 jsrto (PlaySound).l, JmpTo11_PlaySound move.b #4,boss_routine(a0) ; => Obj55_LaserShooter_ChooseTarget move.w #$28,(Boss_Countdown).w move.w #-$80,(Boss_Y_vel).w bra.w Obj55_LaserShooter_End ; =========================================================================== ; loc_33388: Obj55_LaserShooter_Lower: subq.b #1,Obj55_anim_frame_duration(a0) ; is firing animation finished? bne.s + ; if not, branch move.b #5,mainspr_mapframe(a0) ; reset animation frame to not firing + bsr.w Boss_MoveObject cmpi.w #$2B0,(Boss_Y_pos).w ; has laser shooter reached its destination? blo.s Obj55_LaserShooter_End ; if not, branch move.w #$2B0,(Boss_Y_pos).w move.w #0,(Boss_Y_vel).w move.b #0,boss_routine(a0) move.b #2,boss_subtype(a0) ; => Obj55_Main_Init rts ; =========================================================================== ; loc_333BA: Obj55_LaserShooter_End: bsr.w Obj55_LaserShooter_FacePlayer bsr.w Obj55_LaserShooter_Wind jmpto (DisplaySprite).l, JmpTo41_DisplaySprite ; =========================================================================== ; sets the laser shooter's y velocity so that it moves toward its target ; loc_333C6: Obj55_MoveTowardTarget: move.w (Boss_Countdown).w,d0 sub.w (Boss_Y_pos).w,d0 bpl.s Obj55_LaserShooter_MoveUp ; branch, if laser shooter is below target move.w #-$80,(Boss_Y_vel).w rts ; =========================================================================== ; loc_333D8: Obj55_LaserShooter_MoveUp: move.w #$80,(Boss_Y_vel).w rts ; =========================================================================== ; loc_333E0: Obj55_LaserShooter_FacePlayer: move.w (MainCharacter+x_pos).w,d0 sub.w x_pos(a0),d0 blt.s Obj55_LaserShooter_FaceLeft ; branch, if player is to the left subi_.w #8,d0 ; allow an 8 pixel margin blt.s return_333F6 bset #0,render_flags(a0) return_333F6: rts ; =========================================================================== ; loc_333F8: Obj55_LaserShooter_FaceLeft: addi_.w #8,d0 ; allow an 8 pixel margin bgt.s return_333F6 bclr #0,render_flags(a0) rts ; =========================================================================== ; creates the twisting effect ; loc_33406: Obj55_LaserShooter_Wind: move.w (Boss_X_pos).w,d5 move.w (Boss_Y_pos).w,d6 move.b boss_sine_count(a0),d3 move.b d3,d0 bsr.w Obj55_LaserShooter_CalcSineRelative move.w d1,x_pos(a0) move.w d0,y_pos(a0) addi_.b #2,boss_sine_count(a0) moveq #7,d2 moveq #0,d4 - addi.w #$F,d6 subi.b #$10,d3 bsr.w Obj55_LaserShooter_CalcSineRelative move.w d1,sub2_x_pos(a0,d4.w) move.w d0,sub2_y_pos(a0,d4.w) addq.w #next_subspr,d4 dbf d2,- rts ; =========================================================================== ; loc_33446: Obj55_LaserShooter_CalcSineRelative: move.b d3,d0 jsrto (CalcSine).l, JmpTo13_CalcSine asr.w #4,d1 add.w d5,d1 asr.w #6,d0 add.w d6,d0 rts ; =========================================================================== ; loc_33456: Obj55_SpikeChain: moveq #0,d0 move.b boss_routine(a0),d0 move.w Obj55_SpikeChain_Index(pc,d0.w),d1 jmp Obj55_SpikeChain_Index(pc,d1.w) ; =========================================================================== ; off_33464: Obj55_SpikeChain_Index: offsetTable offsetTableEntry.w Obj55_SpikeChain_Init ; 0 - spiked chain's initial state offsetTableEntry.w Obj55_SpikeChain_Main ; 2 - spiked chain moving at an arc ; =========================================================================== ; loc_33468: Obj55_SpikeChain_Init: clr.w (Normal_palette_line2+2).w ; reset palette flash move.w #$28C0,(Boss_X_pos).w bclr #0,render_flags(a0) move.w (MainCharacter+x_pos).w,d1 cmpi.w #$293A,d1 ; is player on the left side of the arena? blo.s + ; if yes, branch move.w #$29C0,(Boss_X_pos).w bset #0,render_flags(a0) + move.w #$2A0,(Boss_Y_pos).w move.b #2,mainspr_mapframe(a0) move.b #$8A,collision_flags(a0) addq.b #2,boss_routine(a0) ; => Obj55_SpikeChain_Main move.b #$80,mainspr_width(a0) clr.b boss_sine_count(a0) moveq #7,d0 moveq #7,d1 moveq #0,d2 - move.b d1,sub2_mapframe(a0,d2.w) addq.w #next_subspr,d2 dbf d0,- move.b #8,mainspr_childsprites(a0) move.b #2,(Boss_CollisionRoutine).w rts ; =========================================================================== ; loc_334CC: Obj55_SpikeChain_Main: bsr.w Obj55_SpikeChain_Move cmpi.b #$FE,boss_sine_count(a0) ; has chain reached a certain angle? blo.s Obj55_SpikeChain_End ; if not, branch move.b #0,boss_routine(a0) move.b #4,boss_subtype(a0) ; => Obj55_LaserShooter_Init rts ; =========================================================================== ; loc_334E6: Obj55_SpikeChain_End: bsr.w Obj55_SpikeChain_SetAnimFrame jmpto (DisplaySprite).l, JmpTo41_DisplaySprite ; =========================================================================== ; loc_334EE: Obj55_SpikeChain_Move: move.b boss_sine_count(a0),d0 addi.b #$40,d0 move.b d0,d3 bsr.w Obj55_SpikeChain_Rotate move.w d1,x_pos(a0) move.w d0,y_pos(a0) addi_.b #1,boss_sine_count(a0) moveq #7,d2 moveq #0,d4 - subi_.b #6,d3 bsr.w Obj55_SpikeChain_Rotate move.w d1,sub2_x_pos(a0,d4.w) move.w d0,sub2_y_pos(a0,d4.w) addq.w #next_subspr,d4 dbf d2,- rts ; =========================================================================== ; loc_33526: Obj55_SpikeChain_Rotate: move.b d3,d0 jsrto (CalcSine).l, JmpTo13_CalcSine muls.w #$68,d1 asr.l #8,d1 btst #0,render_flags(a0) bne.s + neg.w d1 + add.w (Boss_X_pos).w,d1 muls.w #$68,d0 asr.l #8,d0 add.w (Boss_Y_pos).w,d0 rts ; =========================================================================== ; loc_3354C: Obj55_SpikeChain_SetAnimFrame: move.b boss_sine_count(a0),d0 moveq #$15,d1 cmpi.b #$52,d0 blo.s + moveq #3,d1 cmpi.b #$6B,d0 blo.s + moveq #2,d1 cmpi.b #-$6E,d0 blo.s + moveq #4,d1 + move.b d1,mainspr_mapframe(a0) rts ; =========================================================================== ; loc_33570: Obj55_Laser: moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj55_Laser_Index(pc,d0.w),d0 jmp Obj55_Laser_Index(pc,d0.w) ; =========================================================================== ; off_3357E: Obj55_Laser_Index: offsetTable offsetTableEntry.w Obj55_Laser_Init ; 0 - Init offsetTableEntry.w Obj55_Laser_Main ; 2 - Laser moving horizontally offsetTableEntry.w Obj55_Wave ; 4 - Energy wave that moves along the ground offsetTableEntry.w BranchTo2_JmpTo62_DeleteObject ; 6 - Delete (triggered by an animation) ; =========================================================================== ; loc_33586: Obj55_Laser_Init: addq.b #2,routine_secondary(a0) ; => Obj55_Laser_Main move.l #Obj55_MapUnc_33756,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_OOZBoss,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #4,priority(a0) movea.l Obj55_Wave_parent(a0),a1 ; a1=object move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) move.b #$C,mapping_frame(a0) move.w #-$20,d0 move.w #-$400,x_vel(a0) btst #0,render_flags(a1) beq.s + neg.w d0 neg.w x_vel(a0) + add.w d0,x_pos(a0) move.b #$AF,collision_flags(a0) rts ; =========================================================================== ; loc_335DE: Obj55_Laser_Main: bsr.w Obj55_Laser_ChkGround jsrto (ObjectMove).l, JmpTo25_ObjectMove cmpi.w #$2870,x_pos(a0) ; has laser moved off screen going left? blo.w JmpTo62_DeleteObject ; if yes, branch cmpi.w #$2A10,x_pos(a0) ; has laser moved off screen going right? bhs.w JmpTo62_DeleteObject ; if yes, branch jmpto (DisplaySprite).l, JmpTo41_DisplaySprite ; =========================================================================== ; checks if laser hit the ground ; loc_335FE: Obj55_Laser_ChkGround: cmpi.w #$250,y_pos(a0) ; is laser on ground level? blo.s return_33626 ; if not, branch tst.w x_vel(a0) ; is laser moving left? bmi.w Obj55_Laser_ChkGroundLeft ; if yes, branch move.w x_pos(a0),d0 cmpi.w #$2980,d0 bhs.s return_33626 cmpi.w #$297C,d0 blo.w return_33626 move.w #$2988,d1 ; wave's start position bra.s Obj55_Laser_CreateWave ; =========================================================================== return_33626: rts ; =========================================================================== ; loc_33628: Obj55_Laser_ChkGroundLeft: move.w x_pos(a0),d0 cmpi.w #$2900,d0 blo.s return_3363E cmpi.w #$2904,d0 bhs.s return_3363E move.w #$28F8,d1 ; wave's start position bra.s Obj55_Laser_CreateWave ; =========================================================================== return_3363E: rts ; =========================================================================== ; loc_33640: Obj55_Laser_CreateWave: jsrto (SingleObjLoad).l, JmpTo18_SingleObjLoad bne.s return_336B0 move.b #ObjID_OOZBoss,id(a1) ; load obj55 move.b #8,boss_subtype(a1) move.b #4,routine_secondary(a1) ; => Obj55_Wave move.b #$8B,collision_flags(a1) move.b #2,anim(a1) move.b #$D,mapping_frame(a1) move.w #0,y_vel(a1) move.l #Obj55_MapUnc_33756,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_OOZBoss,0,0),art_tile(a1) jsrto (Adjust2PArtPointer).l, JmpTo63_Adjust2PArtPointer ori.b #4,render_flags(a1) move.b #2,priority(a1) move.w #5,Obj55_Wave_delay(a1) move.b #7,Obj55_Wave_count(a1) move.w x_vel(a0),x_vel(a1) move.w d1,x_pos(a1) move.w #$250,y_pos(a1) move.b #SndID_LaserFloor,d0 jsrto (PlaySound).l, JmpTo11_PlaySound return_336B0: rts ; =========================================================================== ; loc_336B2: Obj55_Wave: subq.w #1,Obj55_Wave_delay(a0) bpl.s Obj55_Wave_End move.w #$C7,Obj55_Wave_delay(a0) subq.b #1,Obj55_Wave_count(a0) bmi.s Obj55_Wave_End jsrto (SingleObjLoad2).l, JmpTo24_SingleObjLoad2 bne.s Obj55_Wave_End moveq #0,d0 move.w #bytesToLcnt(object_size),d1 - move.l (a0,d0.w),(a1,d0.w) ; make new object a copy of this one addq.w #4,d0 dbf d1,- if object_size&3 move.w (a0,d0.w),(a1,d0.w) ; make new object a copy of this one endif move.w #5,Obj55_Wave_delay(a1) move.w #$200,anim(a1) move.w #$10,d0 ; place new wave object 16 pixels next to current one tst.w x_vel(a1) ; is object going left? bpl.s + ; if not, branch neg.w d0 ; flip offset + add.w d0,x_pos(a1) ; set position move.b #SndID_LaserFloor,d0 jsrto (PlaySound).l, JmpTo11_PlaySound Obj55_Wave_End: lea (Ani_obj55).l,a1 jsrto (AnimateSprite).l, JmpTo22_AnimateSprite jmpto (MarkObjGone).l, JmpTo38_MarkObjGone ; =========================================================================== BranchTo2_JmpTo62_DeleteObject bra.w JmpTo62_DeleteObject ; =========================================================================== ; animation script ; off_33712: Ani_obj55: offsetTable offsetTableEntry.w byte_3371E offsetTableEntry.w byte_33738 offsetTableEntry.w byte_3373B offsetTableEntry.w byte_3374D offsetTableEntry.w byte_33750 offsetTableEntry.w byte_33753 byte_3371E: dc.b 9, 8, 8, 8, 8, 9, 9, 9, 9, 8, 8, 8, 8, 9, 9, 9 dc.b 9, 8, 8, 8, 8, 9, 9, 9, 9,$FF; 16 rev02even byte_33738: dc.b $F, 1,$FF rev02even byte_3373B: dc.b 1, $D,$11, $E,$12, $F,$13,$10,$14,$14,$10,$13, $F,$12, $E,$11 dc.b $D,$FA ; 16 rev02even byte_3374D: dc.b $F, $A,$FF rev02even byte_33750: dc.b $F, $B,$FF rev02even byte_33753: dc.b $F, 8,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj55_MapUnc_33756: BINCLUDE "mappings/sprite/obj55.bin" ; =========================================================================== if ~~removeJmpTos JmpTo41_DisplaySprite jmp (DisplaySprite).l JmpTo62_DeleteObject jmp (DeleteObject).l JmpTo18_SingleObjLoad jmp (SingleObjLoad).l JmpTo38_MarkObjGone jmp (MarkObjGone).l JmpTo11_PlaySound jmp (PlaySound).l JmpTo24_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo22_AnimateSprite jmp (AnimateSprite).l JmpTo5_RandomNumber jmp (RandomNumber).l JmpTo63_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo13_CalcSine jmp (CalcSine).l JmpTo8_PlayLevelMusic jmp (PlayLevelMusic).l JmpTo8_LoadPLC_AnimalExplosion jmp (LoadPLC_AnimalExplosion).l ; loc_338E4: JmpTo25_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 09 - Sonic in Special Stage ; ---------------------------------------------------------------------------- ; Sprite_338EC: Obj09: bsr.w loc_33908 moveq #0,d0 move.b routine(a0),d0 move.w Obj09_Index(pc,d0.w),d1 jmp Obj09_Index(pc,d1.w) ; =========================================================================== ; off_338FE: Obj09_Index: offsetTable offsetTableEntry.w Obj09_Init ; 0 offsetTableEntry.w Obj09_MdNormal ; 2 offsetTableEntry.w Obj09_MdJump ; 4 offsetTableEntry.w Obj09_Index ; 6 - invalid offsetTableEntry.w Obj09_MdAir ; 8 ; =========================================================================== loc_33908: lea (SS_Ctrl_Record_Buf_End).w,a1 moveq #(SS_Ctrl_Record_Buf_End-SS_Ctrl_Record_Buf)/2-2,d0 - move.w -4(a1),-(a1) dbf d0,- move.w (Ctrl_1_Logical).w,-(a1) rts ; =========================================================================== ; loc_3391C: Obj09_Init: move.b #2,routine(a0) moveq #0,d0 move.l d0,ss_x_pos(a0) move.w #$80,d1 move.w d1,ss_y_pos(a0) move.w d0,ss_y_sub(a0) add.w (SS_Offset_X).w,d0 move.w d0,x_pos(a0) add.w (SS_Offset_Y).w,d1 move.w d1,y_pos(a0) move.b #$E,y_radius(a0) move.b #7,x_radius(a0) move.l #Obj09_MapUnc_34212,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_SpecialSonic,1,0),art_tile(a0) move.b #4,render_flags(a0) move.b #3,priority(a0) move.w #$6E,ss_z_pos(a0) clr.b (SS_Swap_Positions_Flag).w move.w #$400,ss_init_flip_timer(a0) move.b #$40,angle(a0) move.b #1,(Sonic_LastLoadedDPLC).w clr.b ss_slide_timer(a0) bclr #6,status(a0) clr.b collision_property(a0) clr.b ss_dplc_timer(a0) movea.l #SpecialStageShadow_Sonic,a1 move.b #ObjID_SSShadow,id(a1) ; load obj63 (shadow) at $FFFFB140 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$18,y_pos(a1) move.l #Obj63_MapUnc_34492,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_SpecialFlatShadow,3,0),art_tile(a1) move.b #4,render_flags(a1) move.b #4,priority(a1) move.l a0,ss_parent(a1) bra.w LoadSSSonicDynPLC ; =========================================================================== Obj09_MdNormal: tst.b routine_secondary(a0) bne.s Obj09_Hurt lea (Ctrl_1_Held_Logical).w,a2 bsr.w SSPlayer_Move bsr.w SSPlayer_Traction bsr.w SSPlayerSwapPositions bsr.w SSObjectMove bsr.w SSAnglePos bsr.w SSSonic_Jump bsr.w SSPlayer_SetAnimation lea (off_341E4).l,a1 bsr.w SSPlayer_Animate bsr.w SSPlayer_Collision bra.w LoadSSSonicDynPLC ; =========================================================================== Obj09_Hurt: bsr.w SSHurt_Animation bsr.w SSPlayerSwapPositions bsr.w SSObjectMove bsr.w SSAnglePos bra.w LoadSSSonicDynPLC ; =========================================================================== SSHurt_Animation: moveq #0,d0 move.b ss_hurt_timer(a0),d0 addi_.b #8,d0 move.b d0,ss_hurt_timer(a0) bne.s + move.b #0,routine_secondary(a0) move.b #$1E,ss_dplc_timer(a0) + add.b angle(a0),d0 andi.b #$FC,render_flags(a0) subi.b #$10,d0 lsr.b #5,d0 add.w d0,d0 move.b byte_33A92(pc,d0.w),mapping_frame(a0) move.b byte_33A92+1(pc,d0.w),d0 or.b d0,render_flags(a0) move.b ss_hurt_timer(a0),d0 subi_.b #8,d0 bne.s return_33A90 move.b d0,collision_property(a0) cmpa.l #MainCharacter,a0 bne.s + tst.w (Ring_count).w beq.s return_33A90 bra.s ++ ; =========================================================================== + tst.w (Ring_count_2P).w beq.s return_33A90 + jsrto (SSSingleObjLoad).l, JmpTo_SSSingleObjLoad bne.s return_33A90 move.l a0,ss_parent(a1) move.b #ObjID_SSRingSpill,id(a1) ; load obj5B return_33A90: rts ; =========================================================================== byte_33A92: dc.b 4, 1 dc.b 0, 0 ; 2 dc.b 4, 0 ; 4 dc.b $C, 0 ; 6 dc.b 4, 2 ; 8 dc.b 0, 2 ; 10 dc.b 4, 3 ; 12 dc.b $C, 1 ; 14 dword_33AA2: dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($000) ; Sonic in upright position, $58 tiles dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($058) ; Sonic in diagonal position, $CC tiles dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($124) ; Sonic in horizontal position, $4D tiles dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($171) ; Sonic in ball form, $12 tiles ; =========================================================================== LoadSSSonicDynPLC: move.b ss_dplc_timer(a0),d0 beq.s + subq.b #1,d0 move.b d0,ss_dplc_timer(a0) andi.b #1,d0 beq.s + rts ; =========================================================================== + jsrto (DisplaySprite).l, JmpTo42_DisplaySprite lea dword_33AA2(pc),a3 lea (Sonic_LastLoadedDPLC).w,a4 move.w #tiles_to_bytes(ArtTile_ArtNem_SpecialSonic),d4 moveq #0,d1 LoadSSPlayerDynPLC: moveq #0,d0 move.b mapping_frame(a0),d0 cmp.b (a4),d0 beq.s return_33B3E move.b d0,(a4) moveq #0,d6 cmpi.b #4,d0 blt.s loc_33AFE addq.w #4,d6 cmpi.b #$C,d0 blt.s loc_33AFE addq.w #4,d6 cmpi.b #$10,d0 blt.s loc_33AFE addq.b #4,d6 loc_33AFE: move.l (a3,d6.w),d6 add.w d1,d0 add.w d0,d0 lea (Obj09_MapRUnc_345FA).l,a2 adda.w (a2,d0.w),a2 move.w (a2)+,d5 subq.w #1,d5 bmi.s return_33B3E SSPLC_ReadEntry: moveq #0,d1 move.w (a2)+,d1 move.w d1,d3 lsr.w #8,d3 andi.w #$F0,d3 addi.w #$10,d3 andi.w #$FFF,d1 lsl.w #1,d1 add.l d6,d1 move.w d4,d2 add.w d3,d4 add.w d3,d4 jsr (QueueDMATransfer).l dbf d5,SSPLC_ReadEntry return_33B3E: rts ; =========================================================================== SSSonic_Jump: lea (Ctrl_1_Press_Logical).w,a2 SSPlayer_Jump: move.b (a2),d0 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 beq.w return_33BAC move.w #$780,d2 moveq #0,d0 move.b angle(a0),d0 addi.b #$80,d0 jsr (CalcSine).l muls.w d2,d1 asr.l #8,d1 add.w d1,x_vel(a0) muls.w d2,d0 asr.l #7,d0 add.w d0,y_vel(a0) bset #2,status(a0) move.b #4,routine(a0) move.b #3,anim(a0) moveq #0,d0 move.b d0,anim_frame_duration(a0) move.b d0,anim_frame(a0) move.b d0,collision_property(a0) tst.b (SS_2p_Flag).w bne.s loc_33B9E tst.w (Player_mode).w bne.s loc_33BA2 loc_33B9E: not.b (SS_Swap_Positions_Flag).w loc_33BA2: move.w #SndID_Jump,d0 jsr (PlaySound).l return_33BAC: rts ; =========================================================================== Obj09_MdJump: lea (Ctrl_1_Held_Logical).w,a2 bsr.w SSPlayer_ChgJumpDir bsr.w SSObjectMoveAndFall bsr.w SSPlayer_JumpAngle bsr.w SSPlayer_DoLevelCollision bsr.w SSPlayerSwapPositions bsr.w SSAnglePos lea (off_341E4).l,a1 bsr.w SSPlayer_Animate bra.w LoadSSSonicDynPLC ; =========================================================================== Obj09_MdAir: lea (Ctrl_1_Held_Logical).w,a2 bsr.w SSPlayer_ChgJumpDir bsr.w SSObjectMoveAndFall bsr.w SSPlayer_JumpAngle bsr.w SSPlayer_DoLevelCollision bsr.w SSPlayerSwapPositions bsr.w SSAnglePos bsr.w SSPlayer_SetAnimation lea (off_341E4).l,a1 bsr.w SSPlayer_Animate bra.w LoadSSSonicDynPLC ; =========================================================================== SSObjectMoveAndFall: move.l ss_x_pos(a0),d2 move.l ss_y_pos(a0),d3 move.w x_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d2 move.w y_vel(a0),d0 addi.w #$A8,y_vel(a0) ; Apply gravity ext.l d0 asl.l #8,d0 add.l d0,d3 move.l d2,ss_x_pos(a0) move.l d3,ss_y_pos(a0) rts ; =========================================================================== SSPlayer_ChgJumpDir: move.b (a2),d0 btst #button_left,d0 bne.s + btst #button_right,d0 bne.w ++ rts ; =========================================================================== + subi.w #$40,x_vel(a0) rts ; =========================================================================== + addi.w #$40,x_vel(a0) rts ; =========================================================================== SSPlayer_JumpAngle: moveq #0,d2 moveq #0,d3 move.w ss_y_pos(a0),d2 bmi.s SSPlayer_JumpAngle_above_screen move.w ss_x_pos(a0),d3 bmi.s +++ cmp.w d2,d3 blo.s ++ bne.s + tst.w d3 bne.s + move.b #$40,angle(a0) rts ; =========================================================================== + lsl.l #5,d2 divu.w d3,d2 move.b d2,angle(a0) rts ; =========================================================================== + lsl.l #5,d3 divu.w d2,d3 subi.w #$40,d3 neg.w d3 move.b d3,angle(a0) rts ; =========================================================================== + neg.w d3 cmp.w d2,d3 bhs.s + lsl.l #5,d3 divu.w d2,d3 addi.w #$40,d3 move.b d3,angle(a0) rts ; =========================================================================== + lsl.l #5,d2 divu.w d3,d2 subi.w #$80,d2 neg.w d2 move.b d2,angle(a0) rts ; =========================================================================== SSPlayer_JumpAngle_above_screen: neg.w d2 move.w ss_x_pos(a0),d3 bpl.s ++ neg.w d3 cmp.w d2,d3 blo.s + lsl.l #5,d2 divu.w d3,d2 addi.w #$80,d2 move.b d2,angle(a0) rts ; =========================================================================== + lsl.l #5,d3 divu.w d2,d3 subi.w #$C0,d3 neg.w d3 move.b d3,angle(a0) rts ; =========================================================================== + cmp.w d2,d3 bhs.s + lsl.l #5,d3 divu.w d2,d3 addi.w #$C0,d3 move.b d3,angle(a0) rts ; =========================================================================== + lsl.l #5,d2 divu.w d3,d2 subi.w #$100,d2 neg.w d2 move.b d2,angle(a0) rts ; =========================================================================== loc_33D02: moveq #0,d6 moveq #0,d0 move.w ss_x_pos(a1),d0 bpl.s loc_33D10 st d6 neg.w d0 loc_33D10: lsl.l #7,d0 divu.w ss_z_pos(a1),d0 move.b byte_33D32(pc,d0.w),d0 tst.b d6 bne.s loc_33D24 subi.b #$80,d0 neg.b d0 loc_33D24: tst.w ss_y_pos(a1) bpl.s loc_33D2C neg.b d0 loc_33D2C: move.b d0,angle(a0) rts ; =========================================================================== byte_33D32: dc.b $40,$40,$40,$40,$41,$41,$41,$42,$42,$42,$43,$43,$43,$44,$44,$44 dc.b $45,$45,$45,$46,$46,$46,$47,$47,$47,$48,$48,$48,$48,$49,$49,$49; 16 dc.b $4A,$4A,$4A,$4B,$4B,$4B,$4C,$4C,$4C,$4D,$4D,$4D,$4E,$4E,$4E,$4F; 32 dc.b $4F,$50,$50,$50,$51,$51,$51,$52,$52,$52,$53,$53,$53,$54,$54,$54; 48 dc.b $55,$55,$56,$56,$56,$57,$57,$57,$58,$58,$59,$59,$59,$5A,$5A,$5B; 64 dc.b $5B,$5B,$5C,$5C,$5D,$5D,$5E,$5E,$5E,$5F,$5F,$60,$60,$61,$61,$62; 80 dc.b $62,$63,$63,$64,$64,$65,$65,$66,$66,$67,$67,$68,$68,$69,$6A,$6A; 96 dc.b $6B,$6C,$6C,$6D,$6E,$6E,$6F,$70,$71,$72,$73,$74,$75,$77,$78,$7A; 112 dc.b $80, 0 ; 128 ; =========================================================================== SSPlayer_DoLevelCollision: move.w ss_y_pos(a0),d0 ble.s + muls.w d0,d0 move.w ss_x_pos(a0),d1 muls.w d1,d1 add.w d1,d0 move.w ss_z_pos(a0),d1 mulu.w d1,d1 cmp.l d1,d0 blo.s + move.b #2,routine(a0) bclr #2,status(a0) moveq #0,d0 move.w d0,x_vel(a0) move.w d0,y_vel(a0) move.w d0,inertia(a0) ; This makes player stop on ground move.b d0,ss_slide_timer(a0) bset #6,status(a0) bsr.w SSObjectMove bsr.w SSAnglePos + rts ; =========================================================================== SSPlayer_Collision: tst.b collision_property(a0) beq.s return_33E42 clr.b collision_property(a0) tst.b ss_dplc_timer(a0) bne.s return_33E42 clr.b inertia(a0) ; clears only high byte, leaving a bit of speed cmpa.l #MainCharacter,a0 bne.s + st.b (SS_Swap_Positions_Flag).w tst.w (Ring_count).w beq.s loc_33E38 bra.s ++ ; =========================================================================== + clr.b (SS_Swap_Positions_Flag).w tst.w (Ring_count_2P).w beq.s loc_33E38 + move.w #SndID_RingSpill,d0 jsr (PlaySound).l loc_33E38: move.b #2,routine_secondary(a0) ; hurt state clr.b ss_hurt_timer(a0) return_33E42: rts ; =========================================================================== SSPlayerSwapPositions: tst.w (Player_mode).w bne.s return_33E8E move.w ss_z_pos(a0),d0 cmpa.l #MainCharacter,a0 bne.s loc_33E5E tst.b (SS_Swap_Positions_Flag).w beq.s loc_33E6E bra.s loc_33E64 ; =========================================================================== loc_33E5E: tst.b (SS_Swap_Positions_Flag).w bne.s loc_33E6E loc_33E64: cmpi.w #$80,d0 beq.s return_33E8E addq.w #1,d0 bra.s loc_33E76 ; =========================================================================== loc_33E6E: cmpi.w #$6E,d0 beq.s return_33E8E subq.w #1,d0 loc_33E76: move.w d0,ss_z_pos(a0) cmpi.w #$77,d0 bhs.s loc_33E88 move.b #3,priority(a0) rts ; =========================================================================== loc_33E88: move.b #2,priority(a0) return_33E8E: rts ; =========================================================================== byte_33E90: dc.b 1, 1 dc.b 0, 0 ; 2 dc.b 1, 0 ; 4 dc.b 2, 0 ; 6 dc.b 1, 2 ; 8 dc.b 0, 2 ; 10 dc.b 1, 3 ; 12 dc.b 2, 1 ; 14 ; =========================================================================== SSPlayer_SetAnimation: btst #2,status(a0) beq.s + move.b #3,anim(a0) andi.b #$FC,status(a0) rts ; =========================================================================== + moveq #0,d0 move.b angle(a0),d0 subi.b #$10,d0 lsr.b #5,d0 move.b d0,d1 add.w d0,d0 move.b byte_33E90(pc,d0.w),d2 cmp.b anim(a0),d2 bne.s + cmp.b ss_last_angle_index(a0),d1 beq.s return_33EFE + move.b d1,ss_last_angle_index(a0) move.b d2,anim(a0) move.b byte_33E90+1(pc,d0.w),d0 andi.b #$FC,status(a0) or.b d0,status(a0) cmpi.b #1,d1 beq.s loc_33EF8 cmpi.b #5,d1 bne.s return_33EFE loc_33EF8: move.w #$400,ss_init_flip_timer(a0) return_33EFE: rts ; =========================================================================== SSPlayer_Animate: moveq #0,d0 move.b anim(a0),d0 cmp.b next_anim(a0),d0 beq.s SSAnim_Do move.b #0,anim_frame(a0) move.b d0,next_anim(a0) move.b #0,anim_frame_duration(a0) SSAnim_Do: subq.b #1,anim_frame_duration(a0) bpl.s SSAnim_Delay add.w d0,d0 adda.w (a1,d0.w),a1 move.b (SS_player_anim_frame_timer).w,d0 lsr.b #1,d0 move.b d0,anim_frame_duration(a0) cmpi.b #0,anim(a0) bne.s + subi_.b #1,ss_flip_timer(a0) bgt.s + bchg #0,status(a0) bchg #0,render_flags(a0) move.b ss_init_flip_timer(a0),ss_flip_timer(a0) + moveq #0,d1 move.b anim_frame(a0),d1 move.b 1(a1,d1.w),d0 bpl.s + move.b #0,anim_frame(a0) move.b 1(a1),d0 + andi.b #$7F,d0 move.b d0,mapping_frame(a0) move.b status(a0),d1 andi.b #3,d1 andi.b #$FC,render_flags(a0) or.b d1,render_flags(a0) addq.b #1,anim_frame(a0) SSAnim_Delay: rts ; =========================================================================== SSPlayer_Move: move.w inertia(a0),d2 move.b (a2),d0 btst #button_left,d0 bne.s SSPlayer_MoveLeft btst #button_right,d0 bne.w SSPlayer_MoveRight bset #6,status(a0) bne.s + move.b #$1E,ss_slide_timer(a0) + move.b angle(a0),d0 bmi.s + subi.b #$38,d0 cmpi.b #$10,d0 bhs.s + move.w d2,d1 asr.w #3,d1 sub.w d1,d2 bra.s ++ ; =========================================================================== + move.w d2,d1 asr.w #3,d1 sub.w d1,d2 + move.w d2,inertia(a0) move.b ss_slide_timer(a0),d0 beq.s + subq.b #1,d0 move.b d0,ss_slide_timer(a0) + rts ; =========================================================================== SSPlayer_MoveLeft: addi.w #$60,d2 cmpi.w #$600,d2 ble.s + move.w #$600,d2 bra.s + ; =========================================================================== SSPlayer_MoveRight: subi.w #$60,d2 cmpi.w #-$600,d2 bge.s + move.w #-$600,d2 + move.w d2,inertia(a0) bclr #6,status(a0) clr.b ss_slide_timer(a0) rts ; =========================================================================== SSPlayer_Traction: tst.b ss_slide_timer(a0) bne.s + move.b angle(a0),d0 jsr (CalcSine).l muls.w #$50,d1 asr.l #8,d1 add.w d1,inertia(a0) + move.b angle(a0),d0 bpl.s return_34048 addi_.b #4,d0 cmpi.b #-$78,d0 blo.s return_34048 mvabs.w inertia(a0),d0 cmpi.w #$100,d0 bhs.s return_34048 move.b #8,routine(a0) return_34048: rts ; =========================================================================== SSObjectMove: moveq #0,d0 moveq #0,d1 move.w inertia(a0),d2 bpl.s + neg.w d2 lsr.w #8,d2 sub.b d2,angle(a0) bra.s ++ ; =========================================================================== + lsr.w #8,d2 add.b d2,angle(a0) + move.b angle(a0),d0 jsr (CalcSine).l muls.w ss_z_pos(a0),d1 asr.l #8,d1 move.w d1,ss_x_pos(a0) muls.w ss_z_pos(a0),d0 asr.l #8,d0 move.w d0,ss_y_pos(a0) rts ; =========================================================================== SSAnglePos: move.w ss_x_pos(a0),d0 muls.w #$CC,d0 asr.l #8,d0 add.w (SS_Offset_X).w,d0 move.w d0,x_pos(a0) move.w ss_y_pos(a0),d0 add.w (SS_Offset_Y).w,d0 move.w d0,y_pos(a0) rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 63 - Character shadow from Special Stage ; ---------------------------------------------------------------------------- ; Sprite_340A4: Obj63: movea.l ss_parent(a0),a1 ; a1=object cmpa.l #MainCharacter,a1 bne.s loc_340BC movea.l #MainCharacter,a1 ; a1=character bsr.s loc_340CC jmpto (DisplaySprite).l, JmpTo42_DisplaySprite ; =========================================================================== loc_340BC: movea.l #Sidekick,a1 ; a1=object bsr.s loc_340CC bsr.w loc_341BA jmpto (DisplaySprite).l, JmpTo42_DisplaySprite ; =========================================================================== loc_340CC: cmpi.b #2,routine(a1) beq.w loc_34108 bsr.w loc_33D02 move.b angle(a0),d0 jsr (CalcSine).l muls.w ss_z_pos(a1),d1 muls.w #$CC,d1 swap d1 add.w (SS_Offset_X).w,d1 move.w d1,x_pos(a0) muls.w ss_z_pos(a1),d0 asr.l #8,d0 add.w (SS_Offset_Y).w,d0 move.w d0,y_pos(a0) bra.w loc_3411A ; =========================================================================== loc_34108: move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) move.b angle(a1),angle(a0) loc_3411A: moveq #0,d0 move.b angle(a0),d0 subi.b #$10,d0 lsr.b #5,d0 move.b d0,d1 lsl.w #3,d0 lea word_3417A(pc),a2 adda.w d0,a2 move.w (a2)+,art_tile(a0) move.w (a2)+,d0 add.w d0,x_pos(a0) move.w (a2)+,d0 add.w d0,y_pos(a0) move.b (a2)+,mapping_frame(a0) move.b render_flags(a0),d0 andi.b #$FC,d0 or.b (a2)+,d0 move.b d0,render_flags(a0) tst.b angle(a0) bpl.s return_34178 cmpi.b #3,d1 beq.s loc_34164 cmpi.b #7,d1 bne.s loc_3416A loc_34164: addi_.b #3,mapping_frame(a0) loc_3416A: move.w (SS_Offset_Y).w,d1 sub.w y_pos(a0),d1 add.w d1,d1 add.w d1,y_pos(a0) return_34178: rts ; =========================================================================== word_3417A: dc.w make_art_tile(ArtTile_ArtNem_SpecialDiagShadow,3,0), $14, $14, $101 dc.w make_art_tile(ArtTile_ArtNem_SpecialFlatShadow,3,0), 0, $18, 0; 4 dc.w make_art_tile(ArtTile_ArtNem_SpecialDiagShadow,3,0),$FFEC, $14, $100; 8 dc.w make_art_tile(ArtTile_ArtNem_SpecialSideShadow,3,0),$FFEC, 0, $200; 12 dc.w make_art_tile(ArtTile_ArtNem_SpecialDiagShadow,3,0),$FFEC,$FFEC, $700; 16 dc.w make_art_tile(ArtTile_ArtNem_SpecialFlatShadow,3,0), 0,$FFE8, $900; 20 dc.w make_art_tile(ArtTile_ArtNem_SpecialDiagShadow,3,0), $14,$FFEC, $701; 24 dc.w make_art_tile(ArtTile_ArtNem_SpecialSideShadow,3,0), $14, 0, $201; 28 ; =========================================================================== loc_341BA: cmpi.b #1,anim(a1) bne.s return_341E0 move.b status(a1),d1 andi.w #3,d1 cmpi.b #2,d1 bhs.s return_341E0 move.b byte_341E2(pc,d1.w),d0 ext.w d0 add.w d0,x_pos(a0) subi_.w #4,y_pos(a0) return_341E0: rts ; =========================================================================== ; animation script byte_341E2: dc.b 4, -4 off_341E4: offsetTable offsetTableEntry.w byte_341EE ; 0 offsetTableEntry.w byte_341F4 ; 1 offsetTableEntry.w byte_341FE ; 2 offsetTableEntry.w byte_34204 ; 3 offsetTableEntry.w byte_34208 ; 4 byte_341EE: dc.b 3, 0, 1, 2, 3,$FF byte_341F4: dc.b 3, 4, 5, 6, 7, 8, 9, $A, $B,$FF byte_341FE: dc.b 3, $C, $D, $E, $F,$FF byte_34204: dc.b 1,$10,$11,$FF byte_34208: dc.b 3, 0, 4, $C, 4, 0, 4, $C, 4,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings - uses ArtNem_SpecialSonicAndTails ; ---------------------------------------------------------------------------- Obj09_MapUnc_34212: BINCLUDE "mappings/sprite/obj09.bin" ; ---------------------------------------------------------------------------- ; sprite mappings for special stage shadows ; ---------------------------------------------------------------------------- Obj63_MapUnc_34492: BINCLUDE "mappings/sprite/obj63.bin" ; ---------------------------------------------------------------------------- ; custom dynamic pattern loading cues for special stage Sonic, Tails and ; Tails' tails ; The first $12 frames are for Sonic, and the next $12 frames are for Tails. ; The last $15 frames are for Tails' tails. ; The first $24 frames are almost normal dplcs -- the only difference being ; that the art tile to load is pre-shifted left by 4 bits. ; The same applies to the last $15 frames, but they have yet another difference: ; a small space optimization. These frames only have one dplc per frame ever, ; hence the two-byte dplc count is removed from each frame. ; ---------------------------------------------------------------------------- Obj09_MapRUnc_345FA: BINCLUDE "mappings/spriteDPLC/obj09.bin" ; =========================================================================== if ~~removeJmpTos JmpTo42_DisplaySprite jmp (DisplaySprite).l JmpTo_SSSingleObjLoad jmp (SSSingleObjLoad).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 10 - Tails in Special Stage ; ---------------------------------------------------------------------------- ; Sprite_347EC: Obj10: moveq #0,d0 move.b routine(a0),d0 move.w Obj10_Index(pc,d0.w),d1 jmp Obj10_Index(pc,d1.w) ; =========================================================================== ; off_347FA: Obj10_Index: offsetTable offsetTableEntry.w Obj10_Init ; 0 offsetTableEntry.w Obj10_MdNormal ; 1 offsetTableEntry.w Obj10_MdJump ; 2 offsetTableEntry.w Obj10_Index ; 3 - invalid offsetTableEntry.w Obj10_MdAir ; 4 ; =========================================================================== ; loc_34804: Obj10_Init: addq.b #2,routine(a0) moveq #0,d0 move.w d0,ss_x_pos(a0) move.w #$80,d1 move.w d1,ss_y_pos(a0) add.w (SS_Offset_X).w,d0 move.w d0,x_pos(a0) add.w (SS_Offset_Y).w,d1 move.w d1,y_pos(a0) move.b #$E,y_radius(a0) move.b #7,x_radius(a0) move.l #Obj10_MapUnc_34B3E,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_SpecialTails,2,0),art_tile(a0) move.b #4,render_flags(a0) move.b #2,priority(a0) move.w #$80,ss_z_pos(a0) tst.w (Player_mode).w beq.s loc_34864 move.b #3,priority(a0) move.w #$6E,ss_z_pos(a0) loc_34864: move.w #$400,ss_init_flip_timer(a0) move.b #$40,angle(a0) move.b #1,(Tails_LastLoadedDPLC).w clr.b collision_property(a0) clr.b ss_dplc_timer(a0) bsr.w LoadSSTailsDynPLC movea.l #SpecialStageShadow_Tails,a1 move.b #ObjID_SSShadow,id(a1) ; load obj63 (shadow) at $FFFFB180 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$18,y_pos(a1) move.l #Obj63_MapUnc_34492,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_SpecialFlatShadow,3,0),art_tile(a1) move.b #4,render_flags(a1) move.b #4,priority(a1) move.l a0,ss_parent(a1) movea.l #SpecialStageTails_Tails,a1 move.b #ObjID_SSTailsTails,id(a1) ; load obj88 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.l #Obj88_MapUnc_34DA8,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_SpecialTails_Tails,2,0),art_tile(a1) move.b #4,render_flags(a1) move.b priority(a0),priority(a1) subi_.b #1,priority(a1) move.l a0,ss_parent(a1) movea.l a1,a0 move.b #1,(TailsTails_LastLoadedDPLC).w clr.b ss_dplc_timer(a0) movea.l ss_parent(a0),a0 ; load 0bj address rts ; =========================================================================== Obj10_MdNormal: tst.b routine_secondary(a0) bne.s Obj10_Hurt bsr.w SSTailsCPU_Control lea (Ctrl_2_Held_Logical).w,a2 tst.w (Player_mode).w beq.s + lea (Ctrl_1_Held_Logical).w,a2 + bsr.w SSPlayer_Move bsr.w SSPlayer_Traction moveq #1,d0 bsr.w SSPlayerSwapPositions bsr.w SSObjectMove bsr.w SSAnglePos lea (Ctrl_2_Press_Logical).w,a2 tst.w (Player_mode).w beq.s + lea (Ctrl_1_Press_Logical).w,a2 + bsr.w SSPlayer_Jump bsr.w SSPlayer_SetAnimation lea (off_34B1C).l,a1 bsr.w SSPlayer_Animate bsr.w SSPlayer_Collision bra.w LoadSSTailsDynPLC ; =========================================================================== Obj10_Hurt: bsr.w SSHurt_Animation bsr.w SSPlayerSwapPositions bsr.w SSObjectMove bsr.w SSAnglePos bra.w LoadSSTailsDynPLC ; =========================================================================== SSTailsCPU_Control: tst.b (SS_2p_Flag).w bne.s + tst.w (Player_mode).w beq.s ++ + rts ; =========================================================================== + move.b (Ctrl_2_Held_Logical).w,d0 andi.b #button_up_mask|button_down_mask|button_left_mask|button_right_mask|button_B_mask|button_C_mask|button_A_mask,d0 beq.s + moveq #0,d0 moveq #3,d1 lea (SS_Ctrl_Record_Buf).w,a1 - move.l d0,(a1) move.l d0,(a1) dbf d1,- move.w #$B4,(Tails_control_counter).w rts ; =========================================================================== + tst.w (Tails_control_counter).w beq.s + subq.w #1,(Tails_control_counter).w rts ; =========================================================================== + lea (SS_Last_Ctrl_Record).w,a1 move.w (a1),(Ctrl_2_Logical).w rts ; =========================================================================== dword_349B8: dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($183) ; Tails in upright position, $3D tiles dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($1C0) ; Tails in diagonal position, $A4 tiles dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($264) ; Tails in horizontal position, $3A tiles dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($29E) ; Tails in ball form, $10 tiles ; =========================================================================== LoadSSTailsDynPLC: move.b ss_dplc_timer(a0),d0 beq.s + subq.b #1,d0 move.b d0,ss_dplc_timer(a0) andi.b #1,d0 beq.s + rts ; =========================================================================== + jsrto (DisplaySprite).l, JmpTo43_DisplaySprite lea dword_349B8(pc),a3 lea (Tails_LastLoadedDPLC).w,a4 move.w #tiles_to_bytes(ArtTile_ArtNem_SpecialTails),d4 moveq #$12,d1 bra.w LoadSSPlayerDynPLC ; =========================================================================== Obj10_MdJump: lea (Ctrl_2_Held_Logical).w,a2 tst.w (Player_mode).w beq.s + lea (Ctrl_1_Held_Logical).w,a2 + bsr.w SSPlayer_ChgJumpDir bsr.w SSObjectMoveAndFall bsr.w SSPlayer_DoLevelCollision bsr.w SSPlayerSwapPositions bsr.w SSAnglePos bsr.w SSPlayer_JumpAngle lea (off_34B1C).l,a1 bsr.w SSPlayer_Animate bra.s LoadSSTailsDynPLC ; =========================================================================== Obj10_MdAir: lea (Ctrl_2_Held_Logical).w,a2 tst.w (Player_mode).w beq.s + lea (Ctrl_1_Held_Logical).w,a2 + bsr.w SSPlayer_ChgJumpDir bsr.w SSObjectMoveAndFall bsr.w SSPlayer_JumpAngle bsr.w SSPlayer_DoLevelCollision bsr.w SSPlayerSwapPositions bsr.w SSAnglePos bsr.w SSPlayer_SetAnimation lea (off_34B1C).l,a1 bsr.w SSPlayer_Animate bra.w LoadSSTailsDynPLC ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 88 - Tails' tails in Special Stage ; ---------------------------------------------------------------------------- ; Sprite_34A5C: Obj88: movea.l ss_parent(a0),a1 ; load obj address of Tails move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) move.b render_flags(a1),render_flags(a0) move.b status(a1),status(a0) move.b anim(a1),anim(a0) move.b priority(a1),d0 subq.b #1,d0 move.b d0,priority(a0) cmpi.b #3,anim(a0) bhs.s return_34A9E lea (Ani_obj88).l,a1 jsrto (AnimateSprite).l, JmpTo23_AnimateSprite bra.w LoadSSTailsTailsDynPLC ; =========================================================================== return_34A9E: rts ; =========================================================================== dword_34AA0: dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($2AE) ; Tails' tails when he is in upright position, $35 tiles dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($2E3) ; Tails' tails when he is in diagonal position, $3B tiles dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($31E) ; Tails' tails when he is in horizontal position, $35 tiles ; =========================================================================== LoadSSTailsTailsDynPLC: movea.l ss_parent(a0),a1 ; load obj address of Tails move.b ss_dplc_timer(a1),d0 beq.s + andi.b #1,d0 beq.s + rts ; =========================================================================== + jsrto (DisplaySprite).l, JmpTo43_DisplaySprite moveq #0,d0 move.b mapping_frame(a0),d0 cmp.b (TailsTails_LastLoadedDPLC).w,d0 beq.s return_34B1A move.b d0,(TailsTails_LastLoadedDPLC).w moveq #0,d6 cmpi.b #7,d0 blt.s loc_34AE4 addq.w #4,d6 cmpi.b #$E,d0 blt.s loc_34AE4 addq.w #4,d6 loc_34AE4: move.l dword_34AA0(pc,d6.w),d6 addi.w #$24,d0 add.w d0,d0 lea (Obj09_MapRUnc_345FA).l,a2 adda.w (a2,d0.w),a2 move.w #tiles_to_bytes(ArtTile_ArtNem_SpecialTails_Tails),d2 moveq #0,d1 move.w (a2)+,d1 move.w d1,d3 lsr.w #8,d3 andi.w #$F0,d3 addi.w #$10,d3 andi.w #$FFF,d1 lsl.w #1,d1 add.l d6,d1 jsr (QueueDMATransfer).l return_34B1A: rts ; =========================================================================== off_34B1C: offsetTable offsetTableEntry.w byte_34B24 ; 0 offsetTableEntry.w byte_34B2A ; 1 offsetTableEntry.w byte_34B34 ; 2 offsetTableEntry.w byte_34B3A ; 3 byte_34B24: dc.b 3, 0, 1, 2, 3,$FF byte_34B2A: dc.b 3, 4, 5, 6, 7, 8, 9, $A, $B,$FF byte_34B34: dc.b 3, $C, $D, $E, $F,$FF byte_34B3A: dc.b 1,$10,$11,$FF ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj10_MapUnc_34B3E: BINCLUDE "mappings/sprite/obj10.bin" ; animation script ; off_34D86: Ani_obj88: offsetTable offsetTableEntry.w byte_34D8C ; 0 offsetTableEntry.w byte_34D95 ; 1 offsetTableEntry.w byte_34D9E ; 2 byte_34D8C: dc.b 3, 0, 1, 2, 3, 4, 5, 6,$FF rev02even byte_34D95: dc.b 3, 7, 8, 9, $A, $B, $C, $D,$FF rev02even byte_34D9E: dc.b 3, $E, $F,$10,$11,$12,$13,$14,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings for Tails' tails in special stage ; ---------------------------------------------------------------------------- Obj88_MapUnc_34DA8: BINCLUDE "mappings/sprite/obj88.bin" ; =========================================================================== if ~~removeJmpTos JmpTo43_DisplaySprite jmp (DisplaySprite).l JmpTo23_AnimateSprite jmp (AnimateSprite).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 61 - Bombs from Special Stage ; ---------------------------------------------------------------------------- ; Sprite_34EB0: Obj61: moveq #0,d0 move.b routine(a0),d0 move.w Obj61_Index(pc,d0.w),d1 jmp Obj61_Index(pc,d1.w) ; =========================================================================== ; off_34EBE: Obj61_Index: offsetTable offsetTableEntry.w Obj61_Init ; 0 offsetTableEntry.w loc_34F06 ; 2 offsetTableEntry.w loc_3533A ; 4 offsetTableEntry.w loc_34F6A ; 6 ; =========================================================================== ; loc_34EC6: Obj61_Init: addq.b #2,routine(a0) move.w #$7F,x_pos(a0) move.w #$58,y_pos(a0) move.l #Obj61_MapUnc_36508,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_SpecialBomb,1,0),art_tile(a0) move.b #4,render_flags(a0) move.b #3,priority(a0) move.b #2,collision_flags(a0) move.b #-1,(SS_unk_DB4D).w tst.b angle(a0) bmi.s loc_34F06 bsr.w loc_3529C loc_34F06: bsr.w loc_3512A bsr.w loc_351A0 lea (Ani_obj61).l,a1 bsr.w loc_3539E tst.b render_flags(a0) bpl.s return_34F26 bsr.w loc_34F28 bra.w JmpTo44_DisplaySprite ; =========================================================================== return_34F26: rts ; =========================================================================== loc_34F28: move.w #8,d6 bsr.w loc_350A0 bcc.s return_34F68 move.b #1,collision_property(a1) move.w #SndID_SlowSmash,d0 jsr (PlaySoundStereo).l move.b #6,routine(a0) move.b #0,anim_frame(a0) move.b #0,anim_frame_duration(a0) move.l objoff_34(a0),d0 beq.s return_34F68 move.l #0,objoff_34(a0) movea.l d0,a1 ; a1=object st objoff_2A(a1) return_34F68: rts ; =========================================================================== loc_34F6A: move.b #$A,anim(a0) move.w #make_art_tile(ArtTile_ArtNem_SpecialExplosion,2,0),art_tile(a0) bsr.w loc_34F90 bsr.w loc_3512A bsr.w loc_351A0 lea (Ani_obj61).l,a1 jsrto (AnimateSprite).l, JmpTo24_AnimateSprite bra.w JmpTo44_DisplaySprite ; =========================================================================== loc_34F90: cmpi.w #4,objoff_30(a0) bhs.s return_34F9E move.b #1,priority(a0) return_34F9E: rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 60 - Rings from Special Stage ; ---------------------------------------------------------------------------- ; Sprite_34FA0: Obj60: moveq #0,d0 move.b routine(a0),d0 move.w Obj60_Index(pc,d0.w),d1 jmp Obj60_Index(pc,d1.w) ; =========================================================================== ; off_34FAE: Obj60_Index: offsetTable offsetTableEntry.w Obj60_Init ; 0 offsetTableEntry.w loc_34FF0 ; 1 offsetTableEntry.w loc_3533A ; 2 offsetTableEntry.w loc_35010 ; 3 ; =========================================================================== ; loc_34FB6: Obj60_Init: addq.b #2,routine(a0) move.w #$7F,x_pos(a0) move.w #$58,y_pos(a0) move.l #Obj5A_Obj5B_Obj60_MapUnc_3632A,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_SpecialRings,3,0),art_tile(a0) move.b #4,render_flags(a0) move.b #3,priority(a0) move.b #1,collision_flags(a0) tst.b angle(a0) bmi.s loc_34FF0 bsr.w loc_3529C loc_34FF0: bsr.w loc_3512A bsr.w loc_351A0 bsr.w loc_35036 lea (Ani_obj5B_obj60).l,a1 bsr.w loc_3539E tst.b render_flags(a0) bmi.w JmpTo44_DisplaySprite rts ; =========================================================================== loc_35010: move.b #$A,anim(a0) move.w #make_art_tile(ArtTile_ArtNem_SpecialStars,2,0),art_tile(a0) bsr.w loc_34F90 bsr.w loc_3512A bsr.w loc_351A0 lea (Ani_obj5B_obj60).l,a1 jsrto (AnimateSprite).l, JmpTo24_AnimateSprite bra.w JmpTo44_DisplaySprite ; =========================================================================== loc_35036: move.w #$A,d6 bsr.w loc_350A0 bcc.s return_3509E cmpa.l #MainCharacter,a1 bne.s loc_3504E addq.w #1,(Ring_count).w bra.s loc_35052 ; =========================================================================== loc_3504E: addq.w #1,(Ring_count_2P).w loc_35052: addq.b #1,ss_rings_units(a1) cmpi.b #$A,ss_rings_units(a1) blt.s loc_3507A addq.b #1,ss_rings_tens(a1) move.b #0,ss_rings_units(a1) cmpi.b #$A,ss_rings_tens(a1) blt.s loc_3507A addq.b #1,ss_rings_hundreds(a1) move.b #0,ss_rings_tens(a1) loc_3507A: move.b #6,routine(a0) move.l objoff_34(a0),d0 beq.s loc_35094 move.l #0,objoff_34(a0) movea.l d0,a1 ; a1=object st objoff_2A(a1) loc_35094: move.w #SndID_Ring,d0 jsr (PlaySoundStereo).l return_3509E: rts ; =========================================================================== loc_350A0: cmpi.b #8,anim(a0) bne.s loc_350DC tst.b collision_flags(a0) beq.s loc_350DC lea (MainCharacter).w,a2 ; a2=object (special stage sonic) lea (Sidekick).w,a3 ; a3=object (special stage tails) move.w objoff_34(a2),d0 cmp.w objoff_34(a3),d0 blo.s loc_350CE movea.l a3,a1 bsr.w loc_350E2 bcs.s return_350E0 movea.l a2,a1 bra.w loc_350E2 ; =========================================================================== loc_350CE: movea.l a2,a1 bsr.w loc_350E2 bcs.s return_350E0 movea.l a3,a1 bra.w loc_350E2 ; =========================================================================== loc_350DC: move #0,ccr return_350E0: rts ; =========================================================================== loc_350E2: tst.b (a1) beq.s loc_3511A cmpi.b #2,routine(a1) bne.s loc_3511A tst.b routine_secondary(a1) bne.s loc_3511A move.b angle(a1),d0 move.b angle(a0),d1 move.b d1,d2 add.b d6,d1 bcs.s loc_35110 sub.b d6,d2 bcs.s loc_35112 cmp.b d1,d0 bhs.s loc_3511A cmp.b d2,d0 bhs.s loc_35120 bra.s loc_3511A ; =========================================================================== loc_35110: sub.b d6,d2 loc_35112: cmp.b d1,d0 blo.s loc_35120 cmp.b d2,d0 bhs.s loc_35120 loc_3511A: move #0,ccr rts ; =========================================================================== loc_35120: clr.b collision_flags(a0) move #1,ccr rts ; =========================================================================== loc_3512A: btst #7,status(a0) bne.s loc_3516C cmpi.b #4,(SSTrack_drawing_index).w bne.s loc_35146 subi.l #$CCCC,objoff_30(a0) ble.s loc_3516C bra.s loc_35150 ; =========================================================================== loc_35146: subi.l #$CCCD,objoff_30(a0) ble.s loc_3516C loc_35150: cmpi.b #$A,anim(a0) beq.s return_3516A move.w objoff_30(a0),d0 cmpi.w #$1D,d0 ble.s loc_35164 moveq #$1E,d0 loc_35164: move.b byte_35180(pc,d0.w),anim(a0) return_3516A: rts ; =========================================================================== loc_3516C: move.l (sp)+,d0 move.l objoff_34(a0),d0 beq.w JmpTo63_DeleteObject movea.l d0,a1 ; a1=object st objoff_2A(a1) if removeJmpTos JmpTo63_DeleteObject endif jmpto (DeleteObject).l, JmpTo63_DeleteObject ; =========================================================================== byte_35180: dc.b 9, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 3 dc.b 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0; 16 ; =========================================================================== loc_351A0: move.w d7,-(sp) moveq #0,d2 moveq #0,d3 moveq #0,d4 moveq #0,d5 moveq #0,d6 moveq #0,d7 movea.l (SS_CurrentPerspective).w,a1 move.w objoff_30(a0),d0 beq.w loc_35258 cmp.w (a1)+,d0 bgt.w loc_35258 subq.w #1,d0 add.w d0,d0 move.w d0,d1 add.w d0,d0 add.w d1,d0 tst.b (SSTrack_Orientation).w bne.w loc_35260 move.b 4(a1,d0.w),d6 move.b 5(a1,d0.w),d7 beq.s loc_351E8 move.b angle(a0),d1 cmp.b d6,d1 blo.s loc_351E8 cmp.b d7,d1 blo.s loc_35258 loc_351E8: move.b (a1,d0.w),d2 move.b 2(a1,d0.w),d4 move.b 3(a1,d0.w),d5 move.b 1(a1,d0.w),d3 loc_351F8: bpl.s loc_35202 cmpi.b #$48,d3 blo.s loc_35202 ext.w d3 loc_35202: move.b angle(a0),d0 jsrto (CalcSine).l, JmpTo14_CalcSine muls.w d4,d1 muls.w d5,d0 asr.l #8,d0 asr.l #8,d1 add.w d2,d1 add.w d3,d0 move.w d1,x_pos(a0) move.w d0,y_pos(a0) move.l objoff_34(a0),d0 beq.s loc_3524E movea.l d0,a1 ; a1=object move.b angle(a0),d0 jsrto (CalcSine).l, JmpTo14_CalcSine move.w d4,d7 lsr.w #2,d7 add.w d7,d4 muls.w d4,d1 move.w d5,d7 asr.w #2,d7 add.w d7,d5 muls.w d5,d0 asr.l #8,d0 asr.l #8,d1 add.w d2,d1 add.w d3,d0 move.w d1,x_pos(a1) move.w d0,y_pos(a1) loc_3524E: ori.b #$80,render_flags(a0) loc_35254: move.w (sp)+,d7 rts ; =========================================================================== loc_35258: andi.b #$7F,render_flags(a0) bra.s loc_35254 ; =========================================================================== loc_35260: move.b #$80,d1 move.b 4(a1,d0.w),d6 move.b 5(a1,d0.w),d7 beq.s loc_35282 sub.w d1,d6 sub.w d1,d7 neg.w d6 neg.w d7 move.b angle(a0),d1 cmp.b d7,d1 blo.s loc_35282 cmp.b d6,d1 blo.s loc_35258 loc_35282: move.b (a1,d0.w),d2 move.b 2(a1,d0.w),d4 move.b 3(a1,d0.w),d5 subi.w #$100,d2 neg.w d2 move.b 1(a1,d0.w),d3 bra.w loc_351F8 ; =========================================================================== loc_3529C: jsrto (SSSingleObjLoad2).l, JmpTo_SSSingleObjLoad2 bne.w return_3532C move.l a0,objoff_34(a1) move.b (a0),(a1) move.b #4,routine(a1) move.l #Obj63_MapUnc_34492,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_SpecialFlatShadow,3,0),art_tile(a1) move.b #4,render_flags(a1) move.b #5,priority(a1) move.b angle(a0),d0 cmpi.b #$10,d0 bgt.s loc_352E6 bset #0,render_flags(a1) move.b #2,objoff_2B(a1) move.l a1,objoff_34(a0) rts ; =========================================================================== loc_352E6: cmpi.b #$30,d0 bgt.s loc_352FE bset #0,render_flags(a1) move.b #1,objoff_2B(a1) move.l a1,objoff_34(a0) rts ; =========================================================================== loc_352FE: cmpi.b #$50,d0 bgt.s loc_35310 move.b #0,objoff_2B(a1) move.l a1,objoff_34(a0) rts ; =========================================================================== loc_35310: cmpi.b #$70,d0 bgt.s loc_35322 move.b #1,objoff_2B(a1) move.l a1,objoff_34(a0) rts ; =========================================================================== loc_35322: move.b #2,objoff_2B(a1) move.l a1,objoff_34(a0) return_3532C: rts ; =========================================================================== dc.b 0 dc.b 0 ; 1 dc.b 0 ; 2 dc.b $18 ; 3 dc.b 0 ; 4 dc.b $14 ; 5 dc.b 0 ; 6 dc.b $14 ; 7 dc.b 0 ; 8 dc.b $14 ; 9 dc.b 0 ; 10 dc.b 0 ; 11 ; =========================================================================== loc_3533A: tst.b objoff_2A(a0) bne.w BranchTo_JmpTo63_DeleteObject movea.l objoff_34(a0),a1 ; a1=object tst.b render_flags(a1) bmi.s loc_3534E rts ; =========================================================================== loc_3534E: moveq #9,d0 sub.b anim(a1),d0 addi_.b #1,d0 cmpi.b #$A,d0 bne.s loc_35362 move.w #9,d0 loc_35362: move.w d0,d1 add.w d0,d0 add.w d1,d0 moveq #0,d1 move.b objoff_2B(a0),d1 beq.s loc_3538A cmpi.b #1,d1 beq.s loc_35380 add.w d1,d0 move.w #make_art_tile(ArtTile_ArtNem_SpecialSideShadow,3,0),art_tile(a0) bra.s loc_35392 ; =========================================================================== loc_35380: add.w d1,d0 move.w #make_art_tile(ArtTile_ArtNem_SpecialDiagShadow,3,0),art_tile(a0) bra.s loc_35392 ; =========================================================================== loc_3538A: add.w d1,d0 move.w #make_art_tile(ArtTile_ArtNem_SpecialFlatShadow,3,0),art_tile(a0) loc_35392: move.b d0,mapping_frame(a0) bra.w JmpTo44_DisplaySprite ; =========================================================================== BranchTo_JmpTo63_DeleteObject jmpto (DeleteObject).l, JmpTo63_DeleteObject ; =========================================================================== loc_3539E: subq.b #1,anim_frame_duration(a0) bpl.s return_353E8 moveq #0,d0 move.b anim(a0),d0 add.w d0,d0 adda.w (a1,d0.w),a1 move.b (a1),anim_frame_duration(a0) moveq #0,d1 move.b anim_frame(a0),d1 move.b 1(a1,d1.w),d0 bpl.s loc_353CA move.b #0,anim_frame(a0) move.b 1(a1),d0 loc_353CA: andi.b #$7F,d0 move.b d0,mapping_frame(a0) move.b status(a0),d1 andi.b #3,d1 andi.b #$FC,render_flags(a0) or.b d1,render_flags(a0) addq.b #1,anim_frame(a0) return_353E8: rts ; =========================================================================== byte_353EA: dc.b $38 dc.b $48 ; 1 dc.b $2A ; 2 dc.b $56 ; 3 dc.b $1C ; 4 dc.b $64 ; 5 dc.b $E ; 6 dc.b $72 ; 7 dc.b 0 ; 8 dc.b $80 ; 9 byte_353F4: dc.b $40 dc.b $30 ; 1 dc.b $50 ; 2 dc.b $20 ; 3 dc.b $60 ; 4 dc.b $10 ; 5 dc.b $70 ; 6 dc.b 0 ; 7 dc.b $80 ; 8 dc.b 0 ; 9 ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 5B - Ring spray/spill in Special Stage ; ---------------------------------------------------------------------------- ; Sprite_353FE: Obj5B: moveq #0,d0 move.b routine(a0),d0 move.w Obj5B_Index(pc,d0.w),d1 jmp Obj5B_Index(pc,d1.w) ; =========================================================================== ; off_3540C: Obj5B_Index: offsetTable offsetTableEntry.w Obj5B_Init ; 0 offsetTableEntry.w Obj5B_Main ; 2 ; =========================================================================== ; loc_35410: Obj5B_Init: movea.l ss_parent(a0),a3 moveq #0,d1 move.b ss_rings_tens(a3),d1 beq.s loc_35428 subi_.b #1,ss_rings_tens(a3) move.w #$A,d1 bra.s loc_35458 ; =========================================================================== loc_35428: move.b ss_rings_hundreds(a3),d1 beq.s loc_35440 subi_.b #1,ss_rings_hundreds(a3) move.b #9,ss_rings_tens(a3) move.w #$A,d1 bra.s loc_35458 ; =========================================================================== loc_35440: move.b ss_rings_units(a3),d1 beq.s loc_3545C move.b #0,ss_rings_units(a3) btst #0,d1 beq.s loc_35458 lea_ byte_353F4,a2 bra.s loc_3545C ; =========================================================================== loc_35458: lea_ byte_353EA,a2 loc_3545C: cmpi.b #ObjID_SonicSS,(a3) bne.s loc_35468 sub.w d1,(Ring_count).w bra.s loc_3546C ; =========================================================================== loc_35468: sub.w d1,(Ring_count_2P).w loc_3546C: move.w d1,d2 subq.w #1,d2 bmi.w JmpTo63_DeleteObject movea.l a0,a1 bra.s loc_3547E ; =========================================================================== loc_35478: jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad bne.s loc_354DE loc_3547E: move.b #ObjID_SSRingSpill,id(a1) ; load obj5B move.b #2,routine(a1) move.l #Obj5A_Obj5B_Obj60_MapUnc_3632A,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_SpecialRings,3,0),art_tile(a1) move.b #4,render_flags(a1) move.b #5,priority(a1) move.b #0,collision_flags(a1) move.b #8,anim(a1) move.w x_pos(a3),x_pos(a1) move.w y_pos(a3),y_pos(a1) move.b angle(a3),d0 addi.b #$40,d0 add.b (a2)+,d0 jsr (CalcSine).l muls.w #$400,d1 asr.l #8,d1 move.w d1,x_vel(a1) muls.w #$1000,d0 asr.l #8,d0 move.w d0,y_vel(a1) loc_354DE: dbf d2,loc_35478 rts ; =========================================================================== ; loc_354E4: Obj5B_Main: jsrto (ObjectMoveAndFall).l, JmpTo7_ObjectMoveAndFall addi.w #$80,y_vel(a0) bsr.w loc_3551C tst.w x_pos(a0) bmi.w JmpTo63_DeleteObject cmpi.w #$100,x_pos(a0) bhs.w JmpTo63_DeleteObject cmpi.w #$E0,y_pos(a0) bgt.w JmpTo63_DeleteObject lea (Ani_obj5B_obj60).l,a1 jsrto (AnimateSprite).l, JmpTo24_AnimateSprite bra.w JmpTo44_DisplaySprite ; =========================================================================== loc_3551C: tst.w y_vel(a0) bmi.w + move.b #0,priority(a0) move.b #9,anim(a0) + rts ; =========================================================================== rts ; =========================================================================== SSRainbowPaletteColors: move.w word_35548(pc,d0.w),(Normal_palette_line4+$16).w move.w word_35548+2(pc,d0.w),(Normal_palette_line4+$18).w move.w word_35548+4(pc,d0.w),(Normal_palette_line4+$1A).w rts ; =========================================================================== word_35548: dc.w $EE, $88, $44 dc.w $EE, $CC, $88 ; 3 ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 5A - Messages/checkpoint from Special Stage ; ---------------------------------------------------------------------------- ; Sprite_35554: Obj5A: moveq #0,d0 move.b routine(a0),d0 move.w Obj5A_Index(pc,d0.w),d1 jmp Obj5A_Index(pc,d1.w) ; =========================================================================== ; off_35562: Obj5A_Index: offsetTable offsetTableEntry.w Obj5A_Init ; 0 offsetTableEntry.w Obj5A_CheckpointRainbow ; 2 offsetTableEntry.w Obj5A_TextFlyoutInit ; 4 offsetTableEntry.w Obj5A_Handshake ; 6 offsetTableEntry.w Obj5A_TextFlyout ; 8 offsetTableEntry.w Obj5A_MostRingsWin ; $A offsetTableEntry.w Obj5A_RingCheckTrigger ; $C offsetTableEntry.w Obj5A_RingsNeeded ; $E offsetTableEntry.w Obj5A_FlashMessage ; $10 offsetTableEntry.w Obj5A_MoveAndFlash ; $12 offsetTableEntry.w Obj5A_FlashOnly ; $14 ; =========================================================================== ; loc_35578: Obj5A_Init: tst.b (SS_NoCheckpoint_flag).w bne.s Obj5A_RingsMessageInit movea.l (SSTrack_last_mappings_copy).w,a1 cmpa.l #MapSpec_Straight4,a1 blt.s ++ ; rts cmpa.l #MapSpec_Drop1,a1 bge.s ++ ; rts moveq #6,d0 bsr.s SSRainbowPaletteColors st.b (SS_Checkpoint_Rainbow_flag).w moveq #6,d0 - jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad bne.s + move.b #ObjID_SSMessage,id(a1) ; load obj5A move.b #2,routine(a1) ; => Obj5A_CheckpointRainbow move.l #Obj5A_Obj5B_Obj60_MapUnc_3632A,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_SpecialRings,3,0),art_tile(a1) move.b #4,render_flags(a1) move.b #5,priority(a1) move.b d0,objoff_2A(a1) move.w #0,objoff_30(a1) move.b #-1,mapping_frame(a1) + dbf d0,- bra.w JmpTo63_DeleteObject ; =========================================================================== + rts ; =========================================================================== ;loc_355E0 Obj5A_RingsMessageInit: sf.b (SS_NoCheckpoint_flag).w tst.b (SS_2p_Flag).w bne.w JmpTo63_DeleteObject sf.b (SS_HideRingsToGo).w sf.b (SS_TriggerRingsToGo).w move.w #0,(SS_NoRingsTogoLifetime).w move.b #0,objoff_3A(a0) bra.w JmpTo63_DeleteObject ; =========================================================================== ; temporarily remap characters to title card letter format ; Characters are encoded as Aa, Bb, Cc, etc. through a macro charset 'a','z','A' ; Convert to uppercase charset 'A',"\xD\x11\7\x11\1\x11" charset 'G',0 ; can't have an embedded 0 in a string charset 'H',"\xB\4\x11\x11\9\xF\5\8\xC\x11\3\6\2\xA\x11\x10\x11\xE\x11" charset '!',"\x11" charset '.',"\x12" specialText macro letters dc.b letters dc.b $FF ; output string terminator endm Obj5A_RingsToGoText: specialText "RING" specialText "!OGOT" specialText "S" even Obj5A_ToGoOffsets: dc.w $C0 ; 0 dc.w $B8 ; 1 dc.w $B0 ; 2 dc.w $A0 ; 3 dc.w $98 ; 4 dc.w $88 ; 5 charset ; revert character set ; =========================================================================== ;loc_3561E Obj5A_CreateRingsToGoText: st.b (SS_TriggerRingsToGo).w jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad bne.w return_356E4 move.l #Obj5F_MapUnc_72D2,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_SpecialHUD,2,0),art_tile(a1) move.b #ObjID_SSMessage,id(a1) ; load obj5A move.b #4,render_flags(a1) move.b #1,priority(a1) bset #6,render_flags(a1) move.b #0,mainspr_childsprites(a1) move.b #$E,routine(a1) ; => Obj5A_RingsNeeded lea sub2_x_pos(a1),a2 move.w #$5A,d1 move.w #$38,d2 moveq #0,d0 moveq #2,d3 - move.w d1,(a2)+ ; sub?_x_pos move.w d2,(a2)+ ; sub?_y_pos move.w d0,(a2)+ ; sub?_mapframe subq.w #8,d1 dbf d3,- lea Obj5A_RingsToGoText(pc),a3 move.w #$68,d1 move.w #$38,d2 - move.b (a3)+,d0 bmi.s + jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad bne.s return_356E4 bsr.s Init_Obj5A move.b #$10,routine(a1) move.w d1,x_pos(a1) move.w d2,y_pos(a1) move.b d0,mapping_frame(a1) addq.w #8,d1 bra.s - ; =========================================================================== + lea Obj5A_ToGoOffsets(pc),a2 - move.b (a3)+,d0 bmi.s + jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad bne.s return_356E4 bsr.s Init_Obj5A move.b #$12,routine(a1) ; => Obj5A_MoveAndFlash move.w (a2)+,objoff_2A(a1) move.w d2,y_pos(a1) move.b d0,mapping_frame(a1) bra.s - ; =========================================================================== + move.b (a3)+,d0 jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad bne.s return_356E4 bsr.s Init_Obj5A move.b #$14,routine(a1) ; => Obj5A_FlashOnly move.w (a2)+,x_pos(a1) move.w d2,y_pos(a1) move.b d0,mapping_frame(a1) return_356E4: rts ; =========================================================================== ;loc_356E6 Init_Obj5A: move.b #ObjID_SSMessage,id(a1) ; load obj5A move.l #Obj5A_MapUnc_35E1E,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_SpecialMessages,2,0),art_tile(a1) move.b #4,render_flags(a1) move.b #1,priority(a1) rts ; =========================================================================== ;loc_35706 Obj5A_RingsNeeded: move.b (SS_TriggerRingsToGo).w,(SS_HideRingsToGo).w bne.s + bsr.s ++ bra.w Obj5A_FlashMessage ; =========================================================================== + rts ; =========================================================================== + move.w (Ring_count).w,d0 cmpi.w #1,(Player_mode).w blt.s + beq.s ++ move.w (Ring_count_2P).w,d0 bra.s ++ ; =========================================================================== + add.w (Ring_count_2P).w,d0 + sub.w (SS_Ring_Requirement).w,d0 neg.w d0 bgt.s + moveq #0,d0 moveq #1,d2 addi_.w #1,(SS_NoRingsTogoLifetime).w cmpi.w #$C,(SS_NoRingsTogoLifetime).w blo.s loc_3577A st.b (SS_HideRingsToGo).w bra.s loc_3577A ; =========================================================================== + ; This code converts the remaining rings into binary coded decimal format. moveq #0,d1 move.w d0,d1 moveq #0,d0 cmpi.w #100,d1 blt.s + - addi.w #$100,d0 subi.w #100,d1 bgt.s - + divu.w #$A,d1 lsl.w #4,d1 or.b d1,d0 swap d1 or.b d1,d0 move.w #0,(SS_NoRingsTogoLifetime).w sf.b (SS_HideRingsToGo).w loc_3577A: moveq #1,d2 lea sub2_x_pos(a0),a1 move.w d0,(SS_RingsToGoBCD).w move.w d0,d1 andi.w #$F,d1 move.b d1,sub2_mapframe-sub2_x_pos(a1) lsr.w #4,d0 beq.s + addq.w #1,d2 move.w d0,d1 andi.w #$F,d1 move.b d1,sub3_mapframe-sub2_x_pos(a1) lsr.w #4,d0 beq.s + addq.w #1,d2 andi.w #$F,d0 move.b d0,sub4_mapframe-sub2_x_pos(a1) + move.b d2,mainspr_childsprites(a0) rts ; =========================================================================== ;loc_357B2 Obj5A_FlashMessage: tst.b (SS_NoCheckpointMsg_flag).w bne.w + ; rts tst.b (SS_HideRingsToGo).w bne.s + ; rts move.b (Vint_runcount+3).w,d0 andi.b #7,d0 cmpi.b #6,d0 blo.w JmpTo44_DisplaySprite + rts ; =========================================================================== ;loc_357D2 Obj5A_MoveAndFlash: moveq #0,d0 cmpi.w #2,(SS_RingsToGoBCD).w bhs.s + moveq #-8,d0 + add.w objoff_2A(a0),d0 move.w d0,x_pos(a0) bra.s Obj5A_FlashMessage ; =========================================================================== ;loc_357E8 Obj5A_FlashOnly: moveq #0,d0 cmpi.w #2,(SS_RingsToGoBCD).w bhs.s Obj5A_FlashMessage rts ; =========================================================================== Obj5A_Rainbow_Frames: dc.b 0 dc.b 1 ; 1 dc.b 1 ; 2 dc.b 1 ; 3 dc.b 2 ; 4 dc.b 4 ; 5 dc.b 6 ; 6 dc.b 8 ; 7 dc.b 9 ; 8 dc.b $FF ; 9 ; =========================================================================== ;loc_357FE Obj5A_CheckpointRainbow: cmpi.b #4,(SSTrack_drawing_index).w bne.s + move.w objoff_2C(a0),d0 move.b Obj5A_Rainbow_Frames(pc,d0.w),mapping_frame(a0) bmi.w ++ addi_.w #1,objoff_2C(a0) moveq #0,d0 move.b objoff_2A(a0),d0 add.w d0,d0 add.w objoff_30(a0),d0 move.b Obj5A_Rainbow_Positions(pc,d0.w),1+x_pos(a0) move.b Obj5A_Rainbow_Positions+1(pc,d0.w),1+y_pos(a0) addi.w #$E,objoff_30(a0) bra.w JmpTo44_DisplaySprite ; =========================================================================== + tst.b mapping_frame(a0) bpl.w JmpTo44_DisplaySprite rts ; =========================================================================== Obj5A_Rainbow_Positions: ; x, y dc.b $F6,$F6 dc.b $70,$5E ; 2 dc.b $76,$58 ; 4 dc.b $7E,$56 ; 6 dc.b $88,$58 ; 8 dc.b $8E,$5E ; 10 dc.b $F6,$F6 ; 12 dc.b $F6,$F6 ; 14 dc.b $6D,$5A ; 16 dc.b $74,$54 ; 18 dc.b $7E,$50 ; 20 dc.b $8A,$54 ; 22 dc.b $92,$5A ; 24 dc.b $F6,$F6 ; 26 dc.b $F6,$F6 ; 28 dc.b $6A,$58 ; 30 dc.b $72,$50 ; 32 dc.b $7E,$4C ; 34 dc.b $8C,$50 ; 36 dc.b $94,$58 ; 38 dc.b $F6,$F6 ; 40 dc.b $F6,$F6 ; 42 dc.b $68,$56 ; 44 dc.b $70,$4C ; 46 dc.b $7E,$48 ; 48 dc.b $8E,$4C ; 50 dc.b $96,$56 ; 52 dc.b $F6,$F6 ; 54 dc.b $62,$5E ; 56 dc.b $66,$50 ; 58 dc.b $70,$46 ; 60 dc.b $7E,$42 ; 62 dc.b $8E,$46 ; 64 dc.b $98,$50 ; 66 dc.b $9C,$5E ; 68 dc.b $5C,$5A ; 70 dc.b $62,$4A ; 72 dc.b $70,$3E ; 74 dc.b $7E,$38 ; 76 dc.b $8E,$3E ; 78 dc.b $9C,$4A ; 80 dc.b $A2,$5A ; 82 dc.b $54,$54 ; 84 dc.b $5A,$3E ; 86 dc.b $6A,$30 ; 88 dc.b $7E,$2A ; 90 dc.b $94,$30 ; 92 dc.b $A4,$3E ; 94 dc.b $AA,$54 ; 96 dc.b $42,$4A ; 98 dc.b $4C,$28 ; 100 dc.b $62,$12 ; 102 dc.b $7E, $A ; 104 dc.b $9C,$12 ; 106 dc.b $B2,$28 ; 108 dc.b $BC,$4A ; 110 dc.b $16,$26 ; 112 dc.b $28,$FC ; 114 dc.b $EC,$EC ; 116 dc.b $EC,$EC ; 118 dc.b $EC,$EC ; 120 dc.b $D6,$FC ; 122 dc.b $E8,$26 ; 124 ; =========================================================================== + cmpi.w #$E8,x_pos(a0) bne.w JmpTo63_DeleteObject moveq #0,d0 bsr.w SSRainbowPaletteColors sf.b (SS_Checkpoint_Rainbow_flag).w st.b (SS_NoCheckpointMsg_flag).w tst.b (SS_2p_Flag).w ; Is it VS mode? beq.w loc_35978 ; Branch if not move.w #SndID_Checkpoint,d0 jsr (PlaySound).l addi.b #$10,(SS_2P_BCD_Score).w moveq #0,d6 addi_.b #1,(Current_Special_Act).w move.w #$C,d0 move.w (Ring_count).w,d2 cmp.w (Ring_count_2P).w,d2 bgt.s ++ beq.s +++ subi.b #$10,(SS_2P_BCD_Score).w addi_.b #1,(SS_2P_BCD_Score).w move.w #$E,d0 tst.b (Graphics_Flags).w bpl.s + move.w #$14,d0 + move.w #palette_line_1,d6 + move.w #$80,d3 bsr.w Obj5A_CreateCheckpointWingedHand add.w d6,art_tile(a1) add.w d6,2(a2) bsr.w Obj5A_PrintPhrase bra.w JmpTo63_DeleteObject ; =========================================================================== + subi.b #$10,(SS_2P_BCD_Score).w move.w #$10,d0 bsr.w Obj5A_PrintPhrase cmpi.b #3,(Current_Special_Act).w beq.s + move.w #$46,objoff_2A(a0) move.b #$A,routine(a0) rts ; =========================================================================== + bsr.w Obj5A_VSReset move.w #$46,objoff_2A(a0) move.b #$C,routine(a0) rts ; =========================================================================== loc_35978: move.w #6,d1 move.w #SndID_Error,d0 move.w (Ring_count).w,d2 add.w (Ring_count_2P).w,d2 cmp.w (SS_Ring_Requirement).w,d2 blt.s + move.w #4,d1 move.w #SndID_Checkpoint,d0 + jsr (PlaySound).l move.w d1,d0 bsr.w Obj5A_PrintCheckpointMessage bra.w JmpTo63_DeleteObject ; =========================================================================== ;loc_359A6 Obj5A_MostRingsWin: subi_.w #1,objoff_2A(a0) beq.s + rts ; =========================================================================== + move.w #$A,d0 ; MOST RINGS WINS bsr.w Obj5A_PrintPhrase bra.w JmpTo63_DeleteObject ; =========================================================================== ;loc_359BC Obj5A_RingCheckTrigger: subi_.w #1,objoff_2A(a0) beq.s + rts ; =========================================================================== + st.b (SS_Check_Rings_flag).w bra.w SSClearObjs ; =========================================================================== ;loc_359CE Obj5A_Handshake: cmpi.b #$15,mapping_frame(a0) ; Is this the hand? bne.s ++ ; if not, branch move.w objoff_30(a0),d0 ; Target y position for handshake tst.b objoff_2E(a0) bne.s + subi_.w #1,y_pos(a0) subi_.w #4,d0 cmp.w y_pos(a0),d0 blt.s ++ addi_.w #1,d0 move.w d0,y_pos(a0) st.b objoff_2E(a0) bra.s ++ ; =========================================================================== + addi_.w #1,y_pos(a0) addi_.w #4,d0 cmp.w y_pos(a0),d0 bgt.s + subi_.w #1,d0 move.w d0,y_pos(a0) sf.b objoff_2E(a0) + subi_.w #1,objoff_2A(a0) bne.w JmpTo44_DisplaySprite tst.b objoff_2F(a0) beq.s + - move.w #MusID_FadeOut,d0 jsr (PlayMusic).l move.w #$30,objoff_2A(a0) move.b #$C,routine(a0) ; => Obj5A_RingCheckTrigger rts ; =========================================================================== + cmpi.b #$15,mapping_frame(a0) ; Is this the hand? bne.w JmpTo63_DeleteObject ; Branch if not tst.w objoff_30(a0) beq.w JmpTo63_DeleteObject tst.b (SS_2p_Flag).w ; Is this VS mode? beq.s + ; Branch if not bsr.w Obj5A_VSReset cmpi.b #3,(Current_Special_Act).w beq.s - move.w #$A,d0 bsr.w Obj5A_PrintPhrase bra.w JmpTo63_DeleteObject ; =========================================================================== + bsr.w Obj5A_CreateRingReqMessage bra.w JmpTo63_DeleteObject ; =========================================================================== ;loc_35A7A Obj5A_VSReset: lea (SS2p_RingBuffer).w,a3 moveq #0,d0 move.b (Current_Special_Act).w,d0 subq.w #1,d0 add.w d0,d0 add.w d0,d0 move.w (Ring_count).w,(a3,d0.w) move.w (Ring_count_2P).w,2(a3,d0.w) move.w #0,(Ring_count).w move.w #0,(Ring_count_2P).w moveq #0,d0 move.w d0,(MainCharacter+ss_rings_base).w move.b d0,(MainCharacter+ss_rings_units).w move.w d0,(Sidekick+ss_rings_base).w move.b d0,(Sidekick+ss_rings_units).w rts ; =========================================================================== ;loc_35AB6 Obj5A_CreateCheckpointWingedHand: move.w #$48,d4 tst.b (SS_2p_Flag).w ; Is this VS mode? beq.s + ; Branch if not move.w #$1C,d4 + jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad bne.w + ; rts move.b #ObjID_SSMessage,id(a1) ; load obj5A move.b #6,routine(a1) ; => Obj5A_Handshake move.l #Obj5A_MapUnc_35E1E,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_SpecialMessages,1,0),art_tile(a1) move.b #4,render_flags(a1) move.b #1,priority(a1) move.w d3,x_pos(a1) move.w d4,y_pos(a1) move.w #$46,objoff_2A(a1) move.b #$14,mapping_frame(a1) ; Checkpoint wings movea.l a1,a2 jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad bne.s + ; rts move.b #ObjID_SSMessage,id(a1) ; load obj5A move.b #6,routine(a1) ; => Obj5A_Handshake move.l #Obj5A_MapUnc_35E1E,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_SpecialMessages,1,0),art_tile(a1) move.b #4,render_flags(a1) move.b #0,priority(a1) move.w d3,x_pos(a1) move.w d4,y_pos(a1) move.w d4,objoff_30(a1) ; Target y position for handshake move.w #$46,objoff_2A(a1) move.b #$15,mapping_frame(a1) ; Checkpoint hand cmpi.w #6,d0 ; Does player have enough rings? bne.s + ; If yes, return st.b objoff_2F(a1) ; Flag for failed checkpoint bset #1,render_flags(a1) ; Point thumb down + rts ; =========================================================================== ;loc_35B5A Obj5A_TextFlyoutInit: subi_.w #1,objoff_2A(a0) bne.w JmpTo44_DisplaySprite cmpi.b #$13,mapping_frame(a0) ; Is this the hand or wings? bgt.w JmpTo63_DeleteObject ; If yes, branch move.b #8,routine(a0) ; Obj5A_TextFlyout move.w #8,objoff_14(a0) move.w x_pos(a0),d1 subi.w #$80,d1 move.w y_pos(a0),d2 subi.w #$70,d2 jsrto (CalcAngle).l, JmpTo_CalcAngle move.b d0,angle(a0) bra.w JmpTo44_DisplaySprite ; =========================================================================== ; this makes special stage messages like "most rings wins!" fly off the screen ;loc_35B96 Obj5A_TextFlyout: moveq #0,d0 move.b angle(a0),d0 jsrto (CalcSine).l, JmpTo14_CalcSine muls.w objoff_14(a0),d0 muls.w objoff_14(a0),d1 asr.w #8,d0 asr.w #8,d1 add.w d1,x_pos(a0) add.w d0,y_pos(a0) cmpi.w #0,x_pos(a0) blt.w JmpTo63_DeleteObject cmpi.w #$100,x_pos(a0) bgt.w JmpTo63_DeleteObject cmpi.w #0,y_pos(a0) blt.w JmpTo63_DeleteObject bra.w JmpTo44_DisplaySprite ; =========================================================================== ;loc_35BD6 Obj5A_PrintNumber: jsrto (SSSingleObjLoad2).l, JmpTo_SSSingleObjLoad2 bne.s + ; rts move.b d0,mapping_frame(a1) move.l #Obj5F_MapUnc_72D2,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_SpecialHUD,2,0),art_tile(a1) move.b #ObjID_SSMessage,id(a1) ; load obj5A move.b #4,routine(a1) ; Obj5A_TextFlyoutInit move.b #4,render_flags(a1) move.b #1,priority(a1) move.w d1,x_pos(a1) move.w d2,y_pos(a1) move.w #$46,objoff_2A(a1) + rts ; =========================================================================== ; Subroutine to draw checkpoint or message text ; d0 = text ID ; d1 = x position of first letter ; d2 = y position ;loc_35C14 Obj5A_PrintWord: lea SSMessage_TextFrames(pc),a3 adda.w (a3,d0.w),a3 - move.b (a3)+,d0 bmi.s + ; rts jsrto (SSSingleObjLoad2).l, JmpTo_SSSingleObjLoad2 bne.s + ; rts move.b d0,mapping_frame(a1) move.l #Obj5A_MapUnc_35E1E,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_SpecialMessages,2,0),art_tile(a1) move.b #ObjID_SSMessage,id(a1) ; load obj5A move.b #4,routine(a1) ; Obj5A_TextFlyoutInit move.b #4,render_flags(a1) move.b #1,priority(a1) move.w d1,x_pos(a1) move.w d2,y_pos(a1) move.w #$46,objoff_2A(a1) addq.w #8,d1 bra.s - ; =========================================================================== + rts ; =========================================================================== ; temporarily remap characters to title card letter format ; Characters are encoded as Aa, Bb, Cc, etc. through a macro charset 'a','z','A' ; Convert to uppercase charset 'A',"\xD\x11\7\x11\1\x11" charset 'G',0 ; can't have an embedded 0 in a string charset 'H',"\xB\4\x11\x11\9\xF\5\8\xC\x11\3\6\2\xA\x11\x10\x11\xE\x11" charset '!',"\x11" charset '.',"\x12" ; Text words ;off_35C62 SSMessage_TextFrames: offsetTable offsetTableEntry.w byte_35C86 ; 0 offsetTableEntry.w byte_35C8A ; 2 offsetTableEntry.w byte_35C90 ; 4 offsetTableEntry.w byte_35C96 ; 6 offsetTableEntry.w byte_35C9A ; 8 offsetTableEntry.w byte_35CA1 ; $A offsetTableEntry.w byte_35CA8 ; $C offsetTableEntry.w byte_35CAD ; $E offsetTableEntry.w byte_35CB3 ;$10 offsetTableEntry.w byte_35CB9 ;$12 offsetTableEntry.w byte_35CBF ;$14 offsetTableEntry.w byte_35CC4 ;$16 offsetTableEntry.w byte_35CC8 ;$18 offsetTableEntry.w byte_35CCE ;$1A offsetTableEntry.w byte_35CD3 ;$1C offsetTableEntry.w byte_35CD5 ;$1E offsetTableEntry.w byte_35CD9 ;$20 offsetTableEntry.w byte_35CDB ;$22 byte_35C86: specialText "GET" rev02even byte_35C8A: specialText "RINGS" rev02even byte_35C90: specialText "COOL!" rev02even byte_35C96: specialText "NOT" rev02even byte_35C9A: specialText "ENOUGH" rev02even byte_35CA1: specialText "PLAYER" rev02even byte_35CA8: specialText "MOST" rev02even byte_35CAD: specialText "WINS!" rev02even byte_35CB3: specialText "SONIC" rev02even byte_35CB9: specialText "MILES" rev02even byte_35CBF: specialText "TIE!" rev02even byte_35CC4: specialText "WIN" rev02even byte_35CC8: specialText "TWICE" rev02even byte_35CCE: specialText "ALL!" rev02even byte_35CD3: specialText "!" rev02even byte_35CD5: specialText "..." rev02even byte_35CD9: dc.b $13,$FF ; VS rev02even byte_35CDB: specialText "TAILS" even charset ; revert character set ; =========================================================================== ;loc_35CE2 Obj5A_CreateRingReqMessage: moveq #0,d0 ; GET move.w #$54,d1 ; x move.w #$6C,d2 ; y bsr.w Obj5A_PrintWord jsrto (SSStartNewAct).l, JmpTo_SSStartNewAct move.w d1,d4 ; Binary coded decimal ring requirements move.w d2,d5 ; Digit count - 1 (minumum 2 digits) movea.w d2,a3 ; Copy of above, but in a3. move.w #$80,d1 ; x position of least digit cmpi.w #2,d2 ; Do we need hundreds digit? beq.s + ; if yes, branch subi_.w #8,d1 ; Otherwise, move digits to the left + move.w #$6C,d2 ; y position of digits - move.w d4,d6 ; Copy BCD reuirements lsr.w #4,d4 ; Next BCD digit andi.w #$F,d6 ; Extract least digit move.b d6,d0 swap d5 bsr.w Obj5A_PrintNumber subi_.w #8,d1 ; Set position for next digit swap d5 dbf d5,- moveq #2,d0 ; RINGS! lea (SSMessage_TextPhrases).l,a2 adda.w (a2,d0.w),a2 move.w #$6C,d2 ; y move.w #$84,d1 ; x cmpa.w #2,a3 ; Do we need space for hundreds digit? bne.s + ; Branch if not addi_.w #8,d1 ; Move digits to right / moveq #0,d0 move.b (a2)+,d0 bmi.s + bsr.w Obj5A_PrintWord bra.s - ; =========================================================================== + rts ; =========================================================================== ;loc_35D52 Obj5A_PrintCheckpointMessage: move.w #$80,d3 ; x bsr.w Obj5A_CreateCheckpointWingedHand cmpi.w #1,(Player_mode).w ble.s loc_35D6E addi.w #palette_line_1,art_tile(a1) addi.w #palette_line_1,art_tile(a2) loc_35D6E: move.w #$74,d1 ; x move.w #$68,d2 ; y lea (SSMessage_TextPhrases).l,a2 adda.w (a2,d0.w),a2 ; Fetch phrase cmpi.b #4,d0 ; Is it 'COOL!'? beq.s + ; Branch if yes move.w #$5E,d1 ; Move text otherwise / moveq #0,d0 move.b (a2)+,d0 bmi.s ++ ; rts cmpi.b #2,d0 bne.s + move.w #$5E,d1 ; x move.w #$7E,d2 ; y + bsr.w Obj5A_PrintWord addi_.w #8,d1 bra.s - ; =========================================================================== + rts ; =========================================================================== ;loc_35DAA Obj5A_PrintPhrase: move.w d0,d3 subq.w #8,d3 lsr.w #1,d3 moveq #0,d1 move.b byte_35DD6(pc,d3.w),d1 move.w #$48,d2 lea (SSMessage_TextPhrases).l,a2 adda.w (a2,d0.w),a2 - moveq #0,d0 move.b (a2)+,d0 bmi.s + ; rts bsr.w Obj5A_PrintWord addi_.w #8,d1 bra.s - ; =========================================================================== + rts ; =========================================================================== byte_35DD6: dc.b $48 dc.b $44 ; 1 dc.b $58 ; 2 dc.b $58 ; 3 dc.b $74 ; 4 dc.b $3C ; 5 dc.b $58 ; 6 dc.b 0 ; 7 ; Text phrases ;off_35DDE SSMessage_TextPhrases: offsetTable offsetTableEntry.w byte_35DF6 ; 0 offsetTableEntry.w byte_35DF7 ; 2 offsetTableEntry.w byte_35DFA ; 4 offsetTableEntry.w byte_35DFC ; 6 offsetTableEntry.w byte_35E01 ; 8 offsetTableEntry.w byte_35E05 ; $A offsetTableEntry.w byte_35E09 ; $C offsetTableEntry.w byte_35E0C ; $E offsetTableEntry.w byte_35E0F ;$10 offsetTableEntry.w byte_35E11 ;$12 offsetTableEntry.w byte_35E16 ;$14 offsetTableEntry.w byte_35E19 ;$16 byte_35DF6: dc.b $FF ; (empty) byte_35DF7: dc.b 2,$1C,$FF ; RINGS! byte_35DFA: dc.b 4,$FF ; COOL! byte_35DFC: dc.b 6, 8, 2,$1E,$FF ; NOT ENOUGH RINGS... byte_35E01: dc.b $A,$20, $A,$FF ; PLAYER VS PLAYER byte_35E05: dc.b $C, 2, $E,$FF ; MOST RINGS WINS byte_35E09: dc.b $10, $E,$FF ; SONIC WINS byte_35E0C: dc.b $12, $E,$FF ; MILES WINS byte_35E0F: dc.b $14,$FF ; TIE! byte_35E11: dc.b $16,$18,$16,$1A,$FF ; WIN TWICE WIN ALL! byte_35E16: dc.b $22, $E,$FF ; TAILS WINS byte_35E19: dc.b 2,$24,$26,$1C,$FF ; RINGS ?? ?? ! even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj5A_MapUnc_35E1E: BINCLUDE "mappings/sprite/obj5A.bin" ; =========================================================================== loc_35F76: add.w d0,d0 move.w d0,d1 add.w d0,d0 add.w d1,d0 move.w word_35F92(pc,d0.w),(Normal_palette_line4+$16).w move.w word_35F92+2(pc,d0.w),(Normal_palette_line4+$18).w move.w word_35F92+4(pc,d0.w),(Normal_palette_line4+$1A).w rts ; =========================================================================== ; Special Stage Chaos Emerald palette word_35F92: BINCLUDE "art/palettes/SS Emerald.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 59 - Emerald from Special Stage ; ---------------------------------------------------------------------------- ; Sprite_35FBC: Obj59: moveq #0,d0 move.b routine(a0),d0 move.w Obj59_Index(pc,d0.w),d1 jmp Obj59_Index(pc,d1.w) ; =========================================================================== ; off_35FCA: Obj59_Index: offsetTable offsetTableEntry.w Obj59_Init ; 0 offsetTableEntry.w loc_36022 ; 2 offsetTableEntry.w loc_3533A ; 4 offsetTableEntry.w loc_36160 ; 6 offsetTableEntry.w loc_36172 ; 8 ; =========================================================================== ; loc_35FD4: Obj59_Init: st.b (SS_NoCheckpointMsg_flag).w st.b (SS_Pause_Only_flag).w subi_.w #1,objoff_2A(a0) cmpi.w #-$3C,objoff_2A(a0) beq.s + rts ; --------------------------------------------------------------------------- + moveq #0,d0 move.b (Current_Special_Stage).w,d0 bsr.s loc_35F76 addq.b #2,routine(a0) move.l #Obj59_MapUnc_3625A,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_SpecialEmerald,3,0),art_tile(a0) move.b #4,render_flags(a0) move.b #4,priority(a0) move.w #$36,objoff_30(a0) move.b #$40,angle(a0) bsr.w loc_3529C loc_36022: bsr.w loc_360F0 bsr.w loc_3512A bsr.w loc_3603C lea (off_36228).l,a1 bsr.w loc_3539E bra.w JmpTo44_DisplaySprite ; =========================================================================== loc_3603C: move.w d7,-(sp) moveq #0,d2 moveq #0,d3 moveq #0,d4 moveq #0,d5 moveq #0,d6 moveq #0,d7 movea.l (SS_CurrentPerspective).w,a1 adda_.l #2,a1 move.w objoff_30(a0),d0 subq.w #1,d0 add.w d0,d0 move.w d0,d1 add.w d0,d0 add.w d1,d0 move.b (a1,d0.w),d2 move.b 1(a1,d0.w),d3 move.b 2(a1,d0.w),d4 move.b 3(a1,d0.w),d5 move.w d5,d6 swap d5 move.w d6,d5 move.w d4,d6 swap d4 move.w d6,d4 bpl.s loc_36088 cmpi.b #$48,d3 blo.s loc_36088 ext.w d3 loc_36088: move.w d4,d6 add.w d4,d4 add.w d6,d4 lsr.w #2,d4 move.w d5,d6 add.w d5,d5 add.w d6,d5 lsr.w #2,d5 move.b angle(a0),d0 jsrto (CalcSine).l, JmpTo14_CalcSine muls.w d4,d1 muls.w d5,d0 asr.l #8,d0 asr.l #8,d1 add.w d2,d1 add.w d3,d0 move.w d1,x_pos(a0) move.w d0,y_pos(a0) move.b d1,objoff_3A(a0) move.b d0,objoff_3B(a0) swap d4 swap d5 movea.l objoff_34(a0),a1 ; a1=object move.b angle(a0),d0 jsrto (CalcSine).l, JmpTo14_CalcSine move.w d4,d6 lsr.w #2,d6 add.w d6,d4 muls.w d4,d1 move.w d5,d6 asr.w #2,d6 add.w d6,d5 muls.w d5,d0 asr.l #8,d0 asr.l #8,d1 add.w d2,d1 add.w d3,d0 move.w d1,x_pos(a1) move.w d0,y_pos(a1) move.w (sp)+,d7 rts ; =========================================================================== loc_360F0: cmpi.b #3,anim(a0) blo.s return_36140 tst.b objoff_3E(a0) bne.s loc_3610C move.w #MusID_FadeOut,d0 jsr (PlayMusic).l st objoff_3E(a0) loc_3610C: cmpi.b #6,anim(a0) blo.s return_36140 move.w (Ring_count).w,d2 add.w (Ring_count_2P).w,d2 cmp.w (SS_Ring_Requirement).w,d2 blt.s loc_36142 cmpi.b #9,anim(a0) blo.s return_36140 move.w #$63,objoff_2A(a0) move.b #8,routine(a0) move.w #MusID_Emerald,d0 jsr (PlayMusic).l return_36140: rts ; =========================================================================== loc_36142: move.l #0,(SS_New_Speed_Factor).w move.b #6,routine(a0) move.w #$4F,objoff_2A(a0) move.w #6,d0 bsr.w loc_35D6E rts ; =========================================================================== loc_36160: subi_.w #1,objoff_2A(a0) bpl.w JmpTo44_DisplaySprite st.b (SS_Check_Rings_flag).w bra.w SSClearObjs ; =========================================================================== loc_36172: subi_.w #1,objoff_2A(a0) bpl.s loc_361A4 moveq #0,d0 move.b (Current_Special_Stage).w,d0 lea (Got_Emeralds_array).w,a0 st (a0,d0.w) st (Got_Emerald).w addi_.b #1,(Current_Special_Stage).w addi_.b #1,(Emerald_count).w st.b (SS_Check_Rings_flag).w bsr.w SSClearObjs move.l (sp)+,d0 rts ; =========================================================================== loc_361A4: addi_.b #1,objoff_3C(a0) moveq #0,d0 moveq #0,d2 move.b objoff_3B(a0),d2 move.b objoff_3C(a0),d0 lsr.w #2,d0 andi.w #3,d0 add.b byte_361C8(pc,d0.w),d2 move.w d2,y_pos(a0) bra.w JmpTo44_DisplaySprite ; =========================================================================== byte_361C8: dc.b $FF dc.b 0 ; 1 dc.b 1 ; 2 dc.b 0 ; 3 ; =========================================================================== ;loc_361CC SSClearObjs: movea.l #(SS_Object_RAM&$FFFFFF),a1 move.w #(SS_Object_RAM_End-SS_Object_RAM)/$10-1,d0 moveq #0,d1 loc_361D8: rept $10/4 move.l d1,(a1)+ endm dbf d0,loc_361D8 .c := ((SS_Object_RAM_End-SS_Object_RAM)#$10)/4 if .c rept .c move.l d1,(a1)+ endm endif .c := ((SS_Object_RAM_End-SS_Object_RAM)#$10)&2 if .c rept .c move.w d1,(a1)+ endm endif ; Bug: The '+4' shouldn't be here; clearRAM accidentally clears an additional 4 bytes clearRAM SS_Sprite_Table,SS_Sprite_Table_End+4 rts ; =========================================================================== ; unused/dead code ; a0=object cmpi.b #$B,(SSTrack_drawing_index).w blo.s loc_36208 subi.l #$4445,objoff_30(a0) bra.s loc_36210 ; --------------------------------------------------------------------------- loc_36208: subi.l #$4444,objoff_30(a0) loc_36210: move.w objoff_30(a0),d0 cmpi.w #$1D,d0 ble.s + moveq #$1E,d0 + lea_ byte_35180,a1 move.b (a1,d0.w),anim(a0) rts ; end of unused code ; =========================================================================== ; animation script for object 59 off_36228: offsetTable offsetTableEntry.w byte_3623C ; 0 offsetTableEntry.w byte_3623F ; 1 offsetTableEntry.w byte_36242 ; 2 offsetTableEntry.w byte_36245 ; 3 offsetTableEntry.w byte_36248 ; 4 offsetTableEntry.w byte_3624B ; 5 offsetTableEntry.w byte_3624E ; 6 offsetTableEntry.w byte_36251 ; 7 offsetTableEntry.w byte_36254 ; 8 offsetTableEntry.w byte_36257 ; 9 byte_3623C: dc.b $B, 0,$FF rev02even byte_3623F: dc.b $B, 1,$FF rev02even byte_36242: dc.b $B, 2,$FF rev02even byte_36245: dc.b $B, 3,$FF rev02even byte_36248: dc.b $B, 4,$FF rev02even byte_3624B: dc.b $B, 5,$FF rev02even byte_3624E: dc.b $B, 6,$FF rev02even byte_36251: dc.b $B, 7,$FF rev02even byte_36254: dc.b $B, 8,$FF rev02even byte_36257: dc.b $B, 9,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj59_MapUnc_3625A: BINCLUDE "mappings/sprite/obj59.bin" ; animation script: ; off_362D2: Ani_obj5B_obj60:offsetTable offsetTableEntry.w byte_362E8 ; 0 offsetTableEntry.w byte_362EE ; 1 offsetTableEntry.w byte_362F4 ; 2 offsetTableEntry.w byte_362FA ; 3 offsetTableEntry.w byte_36300 ; 4 offsetTableEntry.w byte_36306 ; 5 offsetTableEntry.w byte_3630C ; 6 offsetTableEntry.w byte_36312 ; 7 offsetTableEntry.w byte_36318 ; 8 offsetTableEntry.w byte_3631E ; 9 offsetTableEntry.w byte_36324 ; $A byte_362E8: dc.b 5, 0, $A,$14, $A,$FF rev02even byte_362EE: dc.b 5, 1, $B,$15, $B,$FF rev02even byte_362F4: dc.b 5, 2, $C,$16, $C,$FF rev02even byte_362FA: dc.b 5, 3, $D,$17, $D,$FF rev02even byte_36300: dc.b 5, 4, $E,$18, $E,$FF rev02even byte_36306: dc.b 5, 5, $F,$19, $F,$FF rev02even byte_3630C: dc.b 5, 6,$10,$1A,$10,$FF rev02even byte_36312: dc.b 5, 7,$11,$1B,$11,$FF rev02even byte_36318: dc.b 5, 8,$12,$1C,$12,$FF rev02even byte_3631E: dc.b 5, 9,$13,$1D,$13,$FF rev02even byte_36324: dc.b 1,$1E,$1F,$20,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj5A_Obj5B_Obj60_MapUnc_3632A: BINCLUDE "mappings/sprite/obj5A_5B_60.bin" ; animation script: ; off_364CE: Ani_obj61: offsetTable offsetTableEntry.w byte_364E4 ; 0 offsetTableEntry.w byte_364E7 ; 1 offsetTableEntry.w byte_364EA ; 2 offsetTableEntry.w byte_364ED ; 3 offsetTableEntry.w byte_364F0 ; 4 offsetTableEntry.w byte_364F3 ; 5 offsetTableEntry.w byte_364F6 ; 6 offsetTableEntry.w byte_364F9 ; 7 offsetTableEntry.w byte_364FC ; 8 offsetTableEntry.w byte_364FF ; 9 offsetTableEntry.w byte_36502 ; $A byte_364E4: dc.b $B, 0,$FF rev02even byte_364E7: dc.b $B, 1,$FF rev02even byte_364EA: dc.b $B, 2,$FF rev02even byte_364ED: dc.b $B, 3,$FF rev02even byte_364F0: dc.b $B, 4,$FF rev02even byte_364F3: dc.b $B, 5,$FF rev02even byte_364F6: dc.b $B, 6,$FF rev02even byte_364F9: dc.b $B, 7,$FF rev02even byte_364FC: dc.b $B, 8,$FF rev02even byte_364FF: dc.b $B, 9,$FF rev02even byte_36502: dc.b 2, $A, $B, $C,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj61_MapUnc_36508: BINCLUDE "mappings/sprite/obj61.bin" ; =========================================================================== JmpTo44_DisplaySprite jmp (DisplaySprite).l ; =========================================================================== if ~~removeJmpTos JmpTo63_DeleteObject jmp (DeleteObject).l JmpTo24_AnimateSprite jmp (AnimateSprite).l JmpTo_SSStartNewAct jmp (SSStartNewAct).l JmpTo_CalcAngle jmp (CalcAngle).l JmpTo14_CalcSine jmp (CalcSine).l JmpTo7_ObjectMoveAndFall jmp (ObjectMoveAndFall).l JmpTo_SSSingleObjLoad2 jmp (SSSingleObjLoad2).l JmpTo2_SSSingleObjLoad jmp (SSSingleObjLoad).l align 4 endif ; =========================================================================== ; --------------------------------------------------------------------------- ; LoadSubObject ; loads information from a sub-object into this object a0 ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_365F4: LoadSubObject: moveq #0,d0 move.b subtype(a0),d0 ; loc_365FA: LoadSubObject_Part2: move.w SubObjData_Index(pc,d0.w),d0 lea SubObjData_Index(pc,d0.w),a1 ; loc_36602: LoadSubObject_Part3: move.l (a1)+,mappings(a0) move.w (a1)+,art_tile(a0) jsr (Adjust2PArtPointer).l move.b (a1)+,d0 or.b d0,render_flags(a0) move.b (a1)+,priority(a0) move.b (a1)+,width_pixels(a0) move.b (a1),collision_flags(a0) addq.b #2,routine(a0) rts ; =========================================================================== ; table that maps from the subtype ID to which address to load the data from ; the format of the data there is ; dc.l Pointer_To_Sprite_Mappings ; dc.w VRAM_Location ; dc.b render_flags, priority, width_pixels, collision_flags ; ; for whatever reason, only Obj8C and later have entries in this table ; off_36628: SubObjData_Index: offsetTable offsetTableEntry.w Obj8C_SubObjData ; $0 offsetTableEntry.w Obj8D_SubObjData ; $2 offsetTableEntry.w Obj90_SubObjData ; $4 offsetTableEntry.w Obj90_SubObjData2 ; $6 offsetTableEntry.w Obj91_SubObjData ; $8 offsetTableEntry.w Obj92_SubObjData ; $A offsetTableEntry.w Invalid_SubObjData ; $C offsetTableEntry.w Obj94_SubObjData ; $E offsetTableEntry.w Obj94_SubObjData2 ; $10 offsetTableEntry.w Obj99_SubObjData2 ; $12 offsetTableEntry.w Obj99_SubObjData ; $14 offsetTableEntry.w Obj9A_SubObjData ; $16 offsetTableEntry.w Obj9B_SubObjData ; $18 offsetTableEntry.w Obj9C_SubObjData ; $1A offsetTableEntry.w Obj9A_SubObjData2 ; $1C offsetTableEntry.w Obj9D_SubObjData ; $1E offsetTableEntry.w Obj9D_SubObjData2 ; $20 offsetTableEntry.w Obj9E_SubObjData ; $22 offsetTableEntry.w Obj9F_SubObjData ; $24 offsetTableEntry.w ObjA0_SubObjData ; $26 offsetTableEntry.w ObjA1_SubObjData ; $28 offsetTableEntry.w ObjA2_SubObjData ; $2A offsetTableEntry.w ObjA3_SubObjData ; $2C offsetTableEntry.w ObjA4_SubObjData ; $2E offsetTableEntry.w ObjA4_SubObjData2 ; $30 offsetTableEntry.w ObjA5_SubObjData ; $32 offsetTableEntry.w ObjA6_SubObjData ; $34 offsetTableEntry.w ObjA7_SubObjData ; $36 offsetTableEntry.w ObjA7_SubObjData2 ; $38 offsetTableEntry.w ObjA8_SubObjData ; $3A offsetTableEntry.w ObjA8_SubObjData2 ; $3C offsetTableEntry.w ObjA7_SubObjData3 ; $3E offsetTableEntry.w ObjAC_SubObjData ; $40 offsetTableEntry.w ObjAD_SubObjData ; $42 offsetTableEntry.w ObjAD_SubObjData2 ; $44 offsetTableEntry.w ObjAD_SubObjData3 ; $46 offsetTableEntry.w ObjAF_SubObjData2 ; $48 offsetTableEntry.w ObjAF_SubObjData ; $4A offsetTableEntry.w ObjB0_SubObjData ; $4C offsetTableEntry.w ObjB1_SubObjData ; $4E offsetTableEntry.w ObjB2_SubObjData ; $50 offsetTableEntry.w ObjB2_SubObjData ; $52 offsetTableEntry.w ObjB2_SubObjData ; $54 offsetTableEntry.w ObjBC_SubObjData2 ; $56 offsetTableEntry.w ObjBC_SubObjData2 ; $58 offsetTableEntry.w ObjB3_SubObjData ; $5A offsetTableEntry.w ObjB2_SubObjData2 ; $5C offsetTableEntry.w ObjB3_SubObjData ; $5E offsetTableEntry.w ObjB3_SubObjData ; $60 offsetTableEntry.w ObjB3_SubObjData ; $62 offsetTableEntry.w ObjB4_SubObjData ; $64 offsetTableEntry.w ObjB5_SubObjData ; $66 offsetTableEntry.w ObjB5_SubObjData ; $68 offsetTableEntry.w ObjB6_SubObjData ; $6A offsetTableEntry.w ObjB6_SubObjData ; $6C offsetTableEntry.w ObjB6_SubObjData ; $6E offsetTableEntry.w ObjB6_SubObjData ; $70 offsetTableEntry.w ObjB7_SubObjData ; $72 offsetTableEntry.w ObjB8_SubObjData ; $74 offsetTableEntry.w ObjB9_SubObjData ; $76 offsetTableEntry.w ObjBA_SubObjData ; $78 offsetTableEntry.w ObjBB_SubObjData ; $7A offsetTableEntry.w ObjBC_SubObjData2 ; $7C offsetTableEntry.w ObjBD_SubObjData ; $7E offsetTableEntry.w ObjBD_SubObjData ; $80 offsetTableEntry.w ObjBE_SubObjData ; $82 offsetTableEntry.w ObjBE_SubObjData2 ; $84 offsetTableEntry.w ObjC0_SubObjData ; $86 offsetTableEntry.w ObjC1_SubObjData ; $88 offsetTableEntry.w ObjC2_SubObjData ; $8A offsetTableEntry.w Invalid_SubObjData2 ; $8C offsetTableEntry.w ObjB8_SubObjData2 ; $8E offsetTableEntry.w ObjC3_SubObjData ; $90 offsetTableEntry.w ObjC5_SubObjData ; $92 offsetTableEntry.w ObjC5_SubObjData2 ; $94 offsetTableEntry.w ObjC5_SubObjData3 ; $96 offsetTableEntry.w ObjC5_SubObjData3 ; $98 offsetTableEntry.w ObjC5_SubObjData3 ; $9A offsetTableEntry.w ObjC5_SubObjData3 ; $9C offsetTableEntry.w ObjC5_SubObjData3 ; $9E offsetTableEntry.w ObjC6_SubObjData2 ; $A0 offsetTableEntry.w ObjC5_SubObjData4 ; $A2 offsetTableEntry.w ObjAF_SubObjData3 ; $A4 offsetTableEntry.w ObjC6_SubObjData3 ; $A6 offsetTableEntry.w ObjC6_SubObjData4 ; $A8 offsetTableEntry.w ObjC6_SubObjData ; $AA offsetTableEntry.w ObjC8_SubObjData ; $AC ; =========================================================================== ; --------------------------------------------------------------------------- ; Get Orientation To Player ; Returns the horizontal and vertical distances of the closest player object. ; ; input variables: ; a0 = object ; ; returns: ; a1 = address of closest player character ; d0 = 0 if player is left from object, 2 if right ; d1 = 0 if player is above object, 2 if below ; d2 = closest character's horizontal distance to object ; d3 = closest character's vertical distance to object ; ; writes: ; d0, d1, d2, d3, d4, d5 ; a1 ; a2 = sidekick ; --------------------------------------------------------------------------- ;loc_366D6: Obj_GetOrientationToPlayer: moveq #0,d0 moveq #0,d1 lea (MainCharacter).w,a1 ; a1=character move.w x_pos(a0),d2 sub.w x_pos(a1),d2 mvabs.w d2,d4 ; absolute horizontal distance to main character lea (Sidekick).w,a2 ; a2=character move.w x_pos(a0),d3 sub.w x_pos(a2),d3 mvabs.w d3,d5 ; absolute horizontal distance to sidekick cmp.w d5,d4 ; get shorter distance bls.s + ; branch, if main character is closer ; if sidekick is closer movea.l a2,a1 move.w d3,d2 + tst.w d2 ; is player to enemy's left? bpl.s + ; if not, branch addq.w #2,d0 + move.w y_pos(a0),d3 sub.w y_pos(a1),d3 ; vertical distance to closest character bhs.s + ; branch, if enemy is under addq.w #2,d1 + rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Cap Object Speed ; Prevents an object from going over a specified speed value. ; ; input variables: ; d0 = max x velocity ; d1 = max y velocity ; ; a0 = object ; ; writes: ; d0, d1, d2, d3 ; --------------------------------------------------------------------------- ; loc_3671A: Obj_CapSpeed: move.w x_vel(a0),d2 bpl.s + ; branch, if object is moving right ; going left neg.w d0 ; set opposite direction cmp.w d0,d2 ; is object's current x velocity lower than max? bhs.s ++ ; if yes, branch move.w d0,d2 ; else, cap speed bra.w ++ ; =========================================================================== + ; going right cmp.w d0,d2 ; is object's current x velocity lower than max? bls.s + ; if yes, branch move.w d0,d2 ; else, cap speed + move.w y_vel(a0),d3 bpl.s + ; branch, if object is moving down ; going up neg.w d1 ; set opposite direction cmp.w d1,d3 ; is object's current y velocity lower than max? bhs.s ++ ; if yes, branch move.w d1,d3 ; else, cap speed bra.w ++ ; =========================================================================== + ; going down cmp.w d1,d3 ; is object's current y velocity lower than max? bls.s + ; if yes, branch move.w d1,d3 ; else, cap speed + ; update speed move.w d2,x_vel(a0) move.w d3,y_vel(a0) rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Movement Stop ; Stops an object's movement. ; ; input variables: ; a0 = object ; ; writes: ; d0 = 0 ; --------------------------------------------------------------------------- ;loc_36754: Obj_MoveStop: moveq #0,d0 move.w d0,x_vel(a0) move.w d0,y_vel(a0) rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Align Child XY ; Moves a referenced object to the position of the current object with ; variable x and y offset. ; ; input variables: ; d0 = x offset ; d1 = y offset ; ; a0 = parent object ; a1 = child object ; ; writes: ; d2 = new x position ; d3 = new y position ; --------------------------------------------------------------------------- ;loc_36760: Obj_AlignChildXY: move.w x_pos(a0),d2 add.w d0,d2 move.w d2,x_pos(a1) move.w y_pos(a0),d3 add.w d1,d3 move.w d3,y_pos(a1) rts ; =========================================================================== loc_36776: move.w (Tornado_Velocity_X).w,d0 add.w d0,x_pos(a0) move.w (Tornado_Velocity_Y).w,d0 add.w d0,y_pos(a0) rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Delete If Behind Screen ; deletes an object if it scrolls off the left side of the screen ; ; input variables: ; a0 = object ; ; writes: ; d0 ; --------------------------------------------------------------------------- ;loc_36788: Obj_DeleteBehindScreen: tst.w (Two_player_mode).w beq.s + jmp (DisplaySprite).l + ; when not in two player mode move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 bmi.w JmpTo64_DeleteObject jmp (DisplaySprite).l ; =========================================================================== loc_367AA: move.b render_flags(a0),d0 if gameRevision<2 andi.b #$FC,d0 move.b status(a0),d2 andi.b #$FC,d2 move.b render_flags(a1),d1 andi.b #3,d1 else ; now causes a bug where some sprites are displayed backwards (Silver Sonic's sparks and Grabber's legs) andi.b #$FD,d0 move.b status(a0),d2 andi.b #$FD,d2 move.b render_flags(a1),d1 andi.b #2,d1 endif or.b d1,d0 or.b d1,d2 move.b d0,render_flags(a0) move.b d2,status(a0) rts ; =========================================================================== ;loc_367D0: LoadChildObject: jsr (SingleObjLoad2).l bne.s + ; rts move.w (a2)+,d0 move.w a1,(a0,d0.w) ; store pointer to child in parent's SST _move.b (a2)+,id(a1) ; load obj move.b (a2)+,subtype(a1) move.w a0,objoff_2C(a1) ; store pointer to parent in child's SST move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) + rts ; =========================================================================== ; unused/dead code ; a0=object bsr.w Obj_GetOrientationToPlayer bclr #0,render_flags(a0) bclr #0,status(a0) tst.w d0 beq.s return_36818 bset #0,render_flags(a0) bset #0,status(a0) return_36818: rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Create Projectiles ; Creates a specified number of generic moving projectiles. ; ; input variables: ; d2 = subtype, used for object initialization (refer to LoadSubObject) ; d6 = number of projectiles to create -1 ; ; a2 = projectile stat list ; format: ; dc.b x_offset, y_offset, x_vel, y_vel, mapping_frame, render_flags ; ; writes: ; d0 ; d1 = index in list ; d6 = num objects ; ; a1 = addres of new projectile ; a3 = movement type (ObjectMove) ; --------------------------------------------------------------------------- ;loc_3681A: Obj_CreateProjectiles: moveq #0,d1 ; loop creates d6+1 projectiles - jsr (SingleObjLoad2).l bne.s return_3686E _move.b #ObjID_Projectile,id(a1) ; load obj98 move.b d2,subtype(a1) ; used for object initialization move.w x_pos(a0),x_pos(a1) ; align objects move.w y_pos(a0),y_pos(a1) lea (ObjectMove).l,a3 ; set movement type move.l a3,objoff_2A(a1) lea (a2,d1.w),a3 ; get address in list move.b (a3)+,d0 ; get x offset ext.w d0 add.w d0,x_pos(a1) move.b (a3)+,d0 ; get y offset ext.w d0 add.w d0,y_pos(a1) move.b (a3)+,x_vel(a1) ; set movement values move.b (a3)+,y_vel(a1) move.b (a3)+,mapping_frame(a1) ; set map frame move.b (a3)+,render_flags(a1) ; set render flags addq.w #6,d1 dbf d6,- return_3686E: rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to animate a sprite using an animation script ; Works like AnimateSprite, except for: ; * this function does not change render flags to match orientation given by ; the status byte; ; * the function returns 0 on d0 if it changed the mapping frame, or 1 if an ; end-of-animation flag was found ($FC to $FF); ; * it is only used by Mecha Sonic; ; * some of the end-of-animation flags work differently. ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_36870: AnimateSprite_Checked: moveq #0,d0 move.b anim(a0),d0 ; move animation number to d0 cmp.b next_anim(a0),d0 ; is animation set to change? beq.s AnimChk_Run ; if not, branch move.b d0,next_anim(a0) ; set next anim to current current move.b #0,anim_frame(a0) ; reset animation move.b #0,anim_frame_duration(a0) ; reset frame duration AnimChk_Run: subq.b #1,anim_frame_duration(a0) ; subtract 1 from frame duration bpl.s AnimChk_Wait ; if time remains, branch add.w d0,d0 adda.w (a1,d0.w),a1 ; calculate address of appropriate animation script move.b (a1),anim_frame_duration(a0) ; load frame duration moveq #0,d1 move.b anim_frame(a0),d1 ; load current frame number move.b 1(a1,d1.w),d0 ; read sprite number from script bmi.s AnimChk_End_FF ; if animation is complete, branch ;loc_368A8 AnimChk_Next: move.b d0,mapping_frame(a0) ; load sprite number addq.b #1,anim_frame(a0) ; next frame number ;loc_368B0 AnimChk_Wait: moveq #0,d0 ; Return 0 rts ; --------------------------------------------------------------------------- ;loc_368B4 AnimChk_End_FF: addq.b #1,d0 ; is the end flag = $FF ? bne.s AnimChk_End_FE ; if not, branch move.b #0,anim_frame(a0) ; restart the animation move.b 1(a1),d0 ; read sprite number bsr.s AnimChk_Next moveq #1,d0 ; Return 1 rts ; --------------------------------------------------------------------------- ;loc_368C8 AnimChk_End_FE: addq.b #1,d0 ; is the end flag = $FE ? bne.s AnimChk_End_FD ; if not, branch addq.b #2,routine(a0) ; jump to next routine move.b #0,anim_frame_duration(a0) addq.b #1,anim_frame(a0) moveq #1,d0 ; Return 1 rts ; --------------------------------------------------------------------------- ;loc_368DE AnimChk_End_FD: addq.b #1,d0 ; is the end flag = $FD ? bne.s AnimChk_End_FC ; if not, branch addq.b #2,routine_secondary(a0) ; jump to next routine moveq #1,d0 ; Return 1 rts ; --------------------------------------------------------------------------- ;loc_368EA AnimChk_End_FC: addq.b #1,d0 ; is the end flag = $FC ? bne.s AnimChk_End ; if not, branch move.b #1,anim_frame_duration(a0) ; Force frame duration to 1 moveq #1,d0 ; Return 1 AnimChk_End: rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Delete If Off-Screen ; deletes an object if it is too far away from the screen ; ; input variables: ; a0 = object ; ; writes: ; d0 ; --------------------------------------------------------------------------- ;loc_368F8: Obj_DeleteOffScreen: tst.w (Two_player_mode).w beq.s + jmp (DisplaySprite).l + ; when not in two player mode move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w JmpTo64_DeleteObject jmp (DisplaySprite).l ; =========================================================================== if removeJmpTos JmpTo65_DeleteObject endif JmpTo64_DeleteObject jmp (DeleteObject).l ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 8C - Whisp (blowfly badnik) from ARZ ; ---------------------------------------------------------------------------- ; Sprite_36924: Obj8C: moveq #0,d0 move.b routine(a0),d0 move.w Obj8C_Index(pc,d0.w),d1 jmp Obj8C_Index(pc,d1.w) ; =========================================================================== ; off_36932: Obj8C_States: Obj8C_Index: offsetTable offsetTableEntry.w Obj8C_Init ; 0 offsetTableEntry.w loc_3694E ; 1 offsetTableEntry.w loc_369A8 ; 2 offsetTableEntry.w loc_36958 ; 3 offsetTableEntry.w loc_36A26 ; 4 ; =========================================================================== ; loc_3693C: Obj8C_Init: bsr.w LoadSubObject move.b #$10,objoff_2A(a0) move.b #4,objoff_2B(a0) rts ; =========================================================================== loc_3694E: tst.b render_flags(a0) bmi.s loc_36970 bra.w Obj8C_Animate ; =========================================================================== loc_36958: subq.b #1,objoff_2A(a0) bmi.s loc_36970 ; loc_3695E: Obj8C_Animate: lea (Ani_obj8C).l,a1 jsr (AnimateSprite).l jmp (MarkObjGone).l ; =========================================================================== loc_36970: subq.b #1,objoff_2B(a0) bpl.s loc_36996 move.b #8,routine(a0) bclr #0,status(a0) clr.w y_vel(a0) move.w #-$200,x_vel(a0) move.w #-$200,y_vel(a0) bra.w loc_36A26 ; =========================================================================== loc_36996: move.b #4,routine(a0) move.w #-$100,y_vel(a0) move.b #$60,objoff_2A(a0) loc_369A8: subq.b #1,objoff_2A(a0) bmi.s loc_369F8 bsr.w Obj_GetOrientationToPlayer bclr #0,status(a0) tst.w d0 beq.s loc_369C2 bset #0,status(a0) loc_369C2: move.w word_369F4(pc,d0.w),d2 add.w d2,x_vel(a0) move.w word_369F4(pc,d1.w),d2 add.w d2,y_vel(a0) move.w #$200,d0 move.w d0,d1 bsr.w Obj_CapSpeed jsr (ObjectMove).l lea (Ani_obj8C).l,a1 jsr (AnimateSprite).l jmp (MarkObjGone).l ; =========================================================================== word_369F4: dc.w -$10 dc.w $10 ; =========================================================================== loc_369F8: move.b #6,routine(a0) jsr (RandomNumber).l move.l (RNG_seed).w,d0 andi.b #$1F,d0 move.b d0,objoff_2A(a0) bsr.w Obj_MoveStop lea (Ani_obj8C).l,a1 jsr (AnimateSprite).l jmp (MarkObjGone).l ; =========================================================================== loc_36A26: jsr (ObjectMove).l lea (Ani_obj8C).l,a1 jsr (AnimateSprite).l jmp (MarkObjGone).l ; =========================================================================== ; off_36A3E: Obj8C_SubObjData: subObjData Obj8C_MapUnc_36A4E,make_art_tile(ArtTile_ArtNem_Whisp,1,1),4,4,$C,$B ; animation script ; off_36A48: Ani_obj8C: offsetTable offsetTableEntry.w + ; 0 + dc.b 1, 0, 1,$FF even ; ------------------------------------------------------------------------ ; sprite mappings ; ------------------------------------------------------------------------ Obj8C_MapUnc_36A4E: BINCLUDE "mappings/sprite/obj8C.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 8D - Grounder in wall, from ARZ ; ---------------------------------------------------------------------------- ; Sprite_36A76: Obj8D: moveq #0,d0 move.b routine(a0),d0 move.w Obj8D_Index(pc,d0.w),d1 jmp Obj8D_Index(pc,d1.w) ; =========================================================================== ; off_36A84: Obj8D_Index: offsetTable offsetTableEntry.w Obj8D_Init ; 0 offsetTableEntry.w loc_36ADC ; 2 offsetTableEntry.w Obj8D_Animate ; 4 offsetTableEntry.w loc_36B0E ; 6 offsetTableEntry.w loc_36B34 ; 8 offsetTableEntry.w loc_36B6A ; $A ; =========================================================================== ; loc_36A90: Obj8D_Init: bsr.w LoadSubObject bclr #1,render_flags(a0) beq.s + bclr #1,status(a0) andi.w #drawing_mask,art_tile(a0) + move.b #$14,y_radius(a0) move.b #$10,x_radius(a0) jsr (ObjCheckFloorDist).l tst.w d1 bpl.s + add.w d1,y_pos(a0) move.w #0,y_vel(a0) + _move.b id(a0),d0 subi.b #ObjID_GrounderInWall,d0 beq.w loc_36C64 move.b #6,routine(a0) rts ; =========================================================================== loc_36ADC: bsr.w Obj_GetOrientationToPlayer abs.w d2 cmpi.w #$60,d2 bls.s + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== + addq.b #2,routine(a0) st objoff_2B(a0) bsr.w loc_36C2C jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_36B00: Obj8D_Animate: lea (Ani_obj8D_b).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_36B0E: addq.b #2,routine(a0) bsr.w Obj_GetOrientationToPlayer move.w Obj8D_Directions(pc,d0.w),x_vel(a0) bclr #0,status(a0) tst.w d0 beq.s + bset #0,status(a0) + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; word_36B30: Obj8D_Directions: dc.w -$100 dc.w $100 ; 1 ; =========================================================================== loc_36B34: jsrto (ObjectMove).l, JmpTo26_ObjectMove jsr (ObjCheckFloorDist).l cmpi.w #-1,d1 blt.s loc_36B5C cmpi.w #$C,d1 bge.s loc_36B5C add.w d1,y_pos(a0) lea (Ani_obj8D_a).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_36B5C: addq.b #2,routine(a0) move.b #$3B,objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_36B6A: subq.b #1,objoff_2A(a0) bmi.s loc_36B74 jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_36B74: move.b #8,routine(a0) neg.w x_vel(a0) bchg #0,status(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 8F - Wall behind which Grounder hides, from ARZ ; ---------------------------------------------------------------------------- ; Sprite_36B88: Obj8F: moveq #0,d0 move.b routine(a0),d0 move.w Obj8F_Index(pc,d0.w),d1 jmp Obj8F_Index(pc,d1.w) ; =========================================================================== ; off_36B96: Obj8F_Index: offsetTable offsetTableEntry.w Obj8F_Init ; 0 offsetTableEntry.w loc_36BA6 ; 2 offsetTableEntry.w Obj8F_Move ; 4 ; =========================================================================== ; loc_36B9C: Obj8F_Init: bsr.w LoadSubObject clr.w art_tile(a0) rts ; =========================================================================== loc_36BA6: movea.w objoff_2C(a0),a1 ; a1=object tst.b objoff_2B(a1) bne.s + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== + addq.b #2,routine(a0) move.w objoff_2E(a0),d0 move.b Obj8F_Directions(pc,d0.w),x_vel(a0) move.b Obj8F_Directions+1(pc,d0.w),y_vel(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; byte_36BCC: Obj8F_Directions: dc.b 1,-2 ; 0 dc.b 1,-1 ; 2 dc.b -1,-2 ; 4 dc.b -1,-1 ; 6 ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 90 - Rocks thrown by Grounder behind wall, from ARZ ; ---------------------------------------------------------------------------- ; Sprite_36BD4: Obj90: moveq #0,d0 move.b routine(a0),d0 move.w Obj90_Index(pc,d0.w),d1 jmp Obj90_Index(pc,d1.w) ; =========================================================================== ; off_36BE2: Obj90_Index: offsetTable offsetTableEntry.w Obj90_Init ; 0 offsetTableEntry.w Obj90_Move ; 2 ; =========================================================================== ; loc_36BE6: Obj90_Init: bsr.w LoadSubObject move.w #make_art_tile(ArtTile_ArtNem_Grounder,2,0),art_tile(a0) move.w objoff_2E(a0),d0 move.b Obj90_Directions(pc,d0.w),x_vel(a0) move.b Obj90_Directions+1(pc,d0.w),y_vel(a0) lsr.w #1,d0 move.b Obj90_Frames(pc,d0.w),mapping_frame(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; byte_36C0C: Obj90_Frames: dc.b 0 dc.b 2 ; 1 dc.b 0 ; 2 dc.b 1 ; 3 dc.b 0 ; 4 dc.b 0 ; 5 ; =========================================================================== ; byte_36C12: Obj90_Directions: dc.b -1, -4 dc.b 4, -3 ; 2 dc.b 2, 0 ; 4 dc.b -3, -1 ; 6 dc.b -3, -3 ; 8 ; =========================================================================== ; loc_36C1C: Obj8F_Move: Obj90_Move: tst.b render_flags(a0) bpl.w JmpTo65_DeleteObject jsrto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_36C2C: moveq #0,d1 moveq #4,d6 - jsrto (SingleObjLoad).l, JmpTo19_SingleObjLoad bne.s + ; rts bsr.w loc_36C40 dbf d6,- + rts ; =========================================================================== loc_36C40: _move.b #ObjID_GrounderRocks,id(a1) ; load obj90 move.b #6,subtype(a1) ; <== Obj90_SubObjData2 move.w a0,objoff_2C(a1) move.w d1,objoff_2E(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addq.w #2,d1 rts ; =========================================================================== loc_36C64: moveq #0,d1 moveq #3,d6 - jsrto (SingleObjLoad).l, JmpTo19_SingleObjLoad bne.s + ; rts bsr.w loc_36C78 dbf d6,- + rts ; =========================================================================== loc_36C78: _move.b #ObjID_GrounderWall,id(a1) ; load obj8F move.b #4,subtype(a1) ; <== Obj90_SubObjData move.w a0,objoff_2C(a1) move.w d1,objoff_2E(a1) move.l x_pos(a0),d0 swap d0 moveq #0,d2 move.b byte_36CBC(pc,d1.w),d2 ext.w d2 add.w d2,d0 swap d0 move.l d0,x_pos(a1) move.l y_pos(a0),d0 swap d0 moveq #0,d2 move.b byte_36CBC+1(pc,d1.w),d2 ext.w d2 add.w d2,d0 swap d0 move.l d0,y_pos(a1) addq.w #2,d1 rts ; =========================================================================== byte_36CBC: dc.b 0,-$14 dc.b $10, -4 ; 2 dc.b 0, $C ; 4 dc.b -$10, -4 ; 6 ; off_36CC4: Obj8D_SubObjData: subObjData Obj8D_MapUnc_36CF0,make_art_tile(ArtTile_ArtNem_Grounder,1,1),4,5,$10,2 ; off_36CCE: Obj90_SubObjData: subObjData Obj90_MapUnc_36D00,make_art_tile(ArtTile_ArtKos_LevelArt,0,0),$84,4,$10,0 ; off_36CD8: Obj90_SubObjData2: subObjData Obj90_MapUnc_36CFA,make_art_tile(ArtTile_ArtNem_Grounder,1,1),$84,4,8,0 ; animation script Ani_obj8D_a: offsetTable offsetTableEntry.w + ; 0 + dc.b 3, 2, 3, 4,$FF even ; animation script ; off_36CEA: Ani_obj8D_b: offsetTable offsetTableEntry.w + + dc.b 7, 0, 1,$FC even ; ----------------------------------------------------------------------------- ; sprite mappings (obj8D) ; ----------------------------------------------------------------------------- Obj8D_MapUnc_36CF0: offsetTable offsetTableEntry.w word_36D02 ; 0 offsetTableEntry.w word_36D24 ; 2 offsetTableEntry.w word_36D46 ; 4 offsetTableEntry.w word_36D58 ; 6 offsetTableEntry.w word_36D6A ; 8 ; ----------------------------------------------------------------------------- ; sprite mappings (obj90) ; ----------------------------------------------------------------------------- Obj90_MapUnc_36CFA: offsetTable offsetTableEntry.w word_36D7C ; 0 offsetTableEntry.w word_36D86 ; 2 offsetTableEntry.w word_36D90 ; 4 ; ----------------------------------------------------------------------------- ; sprite mappings (obj90) ; ----------------------------------------------------------------------------- Obj90_MapUnc_36D00: offsetTable offsetTableEntry.w word_36D9A ; 0 word_36D02: dc.w 4 dc.w $F400, 0, 0,$FFF8 dc.w $FC06, 1, 0,$FFF0 ; 4 dc.w $F400, $800, $800, 0 ; 8 dc.w $FC06, $801, $800, 0 ; 12 word_36D24: dc.w 4 dc.w $EC00, 7, 3,$FFF8 dc.w $F407, 8, 4,$FFF0 ; 4 dc.w $EC00, $807, $803, 0 ; 8 dc.w $F407, $808, $804, 0 ; 12 word_36D46: dc.w 2 dc.w $EC0F, $10, 8,$FFF0 dc.w $C0C, $20, $10,$FFF0 ; 4 word_36D58: dc.w 2 dc.w $EC0F, $10, 8,$FFF0 dc.w $C0C, $24, $12,$FFF0 ; 4 word_36D6A: dc.w 2 dc.w $EC0F, $10, 8,$FFF0 dc.w $C0C, $28, $14,$FFF0 ; 4 word_36D7C: dc.w 1 dc.w $F805, $2C, $16,$FFF8 word_36D86: dc.w 1 dc.w $FC00, $30, $18,$FFFC word_36D90: dc.w 1 dc.w $FC00, $31, $18,$FFFC word_36D9A: dc.w 2 dc.w $F805,$4093,$4049,$FFF0 dc.w $F805,$4097,$404B, 0 ; 4 ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 91 - Chop Chop (piranha/shark badnik) from ARZ ; ---------------------------------------------------------------------------- ; OST Variables: Obj91_move_timer = objoff_2A ; time to wait before turning around Obj91_bubble_timer = objoff_2C ; time to wait before producing a bubble ; Sprite_36DAC: Obj91: moveq #0,d0 move.b routine(a0),d0 move.w Obj91_Index(pc,d0.w),d1 jmp Obj91_Index(pc,d1.w) ; =========================================================================== ; off_36DBA: Obj91_Index: offsetTable offsetTableEntry.w Obj91_Init ; 0 - Initialize object variables offsetTableEntry.w Obj91_Main ; 2 - Moving back and forth until Sonic or Tails approach offsetTableEntry.w Obj91_Waiting ; 4 - Stopped, opening and closing mouth offsetTableEntry.w Obj91_Charge ; 6 - Charging at Sonic or Tails ; =========================================================================== ; loc_36DC2: Obj91_Init: bsr.w LoadSubObject move.w #$200,Obj91_move_timer(a0) move.w #$50,Obj91_bubble_timer(a0) moveq #$40,d0 ; enemy speed btst #0,status(a0) ; is enemy facing left? bne.s + ; if not, branch neg.w d0 ; else reverse movement direction + move.w d0,x_vel(a0) ; set speed rts ; =========================================================================== ; loc_36DE4: Obj91_Main: subq.b #1,Obj91_bubble_timer(a0) bne.s + ; branch, if timer isn't done counting down bsr.w Obj91_MakeBubble + subq.w #1,Obj91_move_timer(a0) bpl.s + ; branch, if timer isn't done counting down move.w #$200,Obj91_move_timer(a0) ; else, reset timer... bchg #0,status(a0) ; ... change direction... bchg #0,render_flags(a0) neg.w x_vel(a0) ; ... and reverse movement + jsrto (ObjectMove).l, JmpTo26_ObjectMove bsr.w Obj_GetOrientationToPlayer move.w d2,d4 move.w d3,d5 bsr.w Obj91_TestCharacterPos ; are Sonic or Tails close enough to attack? bne.s Obj91_PrepareCharge ; if yes, prepare to charge at them jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_36E20 Obj91_PrepareCharge: addq.b #2,routine(a0) ; => Obj91_Waiting move.b #$10,Obj91_move_timer(a0) ; time to wait before charging at the player clr.w x_vel(a0) ; stop movement jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_36E32: Obj91_Waiting: subq.b #1,Obj91_move_timer(a0) bmi.s Obj91_MoveTowardsPlayer ; branch, if wait time is over bra.w Obj91_Animate ; =========================================================================== ; loc_36E3C: Obj91_MoveTowardsPlayer: addq.b #2,routine(a0) ; => Obj91_Charge bsr.w Obj_GetOrientationToPlayer lsr.w #1,d0 ; set speed based on closest character move.b Obj91_HorizontalSpeeds(pc,d0.w),x_vel(a0) ; horizontal addi.w #$10,d3 cmpi.w #$20,d3 ; is closest character withing $10 pixels above or $F pixels below? blo.s + ; if not, branch lsr.w #1,d1 ; set speed based on closest character move.b Obj91_VerticalSpeeds(pc,d1.w),1+y_vel(a0) ; vertical + bra.w Obj91_Animate ; =========================================================================== ; byte_36E62: Obj91_HorizontalSpeeds: dc.b -2 ; 0 - player is left from object -> move left dc.b 2 ; 1 - player is right from object -> move right ; byte_36E64: Obj91_VerticalSpeeds: dc.b $80 ; 0 - player is above object -> ... move down? dc.b $80 ; 1 - player is below object -> move down ; =========================================================================== ; loc_36E66: Obj91_Charge: jsrto (ObjectMove).l, JmpTo26_ObjectMove ; loc_36E6A: Obj91_Animate: lea (Ani_obj91).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_36E78: Obj91_MakeBubble: move.w #$50,Obj91_bubble_timer(a0) ; reset timer jsrto (SingleObjLoad).l, JmpTo19_SingleObjLoad bne.s return_36EB0 _move.b #ObjID_SmallBubbles,id(a1) ; load obj move.b #6,subtype(a1) ; <== Obj90_SubObjData2 move.w x_pos(a0),x_pos(a1) ; align objects horizontally moveq #$14,d0 ; load x-offset btst #0,render_flags(a0) ; is object facing left? beq.s + ; if not, branch neg.w d0 ; else mirror offset + add.w d0,x_pos(a1) ; add horizontal offset move.w y_pos(a0),y_pos(a1) ; align objects vertically addq.w #6,y_pos(a1) ; move object 6 pixels down return_36EB0: rts ; =========================================================================== ; loc_36EB2: Obj91_TestCharacterPos: addi.w #$20,d3 cmpi.w #$40,d3 ; is character too low? bhs.s Obj91_DoNotCharge ; if yes, branch tst.w d2 ; is character to the left? bmi.s Obj91_TestPosLeft ; if yes, branch tst.w x_vel(a0) ; is object moving left, towards character? bpl.s Obj91_DoNotCharge ; if not, branch bra.w Obj91_TestHorizontalDist ; =========================================================================== ; loc_36ECA: Obj91_TestPosLeft: tst.w x_vel(a0) ; is object moving right, towards character? bmi.s Obj91_DoNotCharge ; if not, branch neg.w d2 ; get absolute value ; loc_36ED2: Obj91_TestHorizontalDist: cmpi.w #$20,d2 ; is distance less than $20? blo.s Obj91_DoNotCharge ; if yes, don't attack cmpi.w #$A0,d2 ; is distance less than $A0? blo.s Obj91_PlayerInRange ; if yes, attack ; loc_36EDE: Obj91_DoNotCharge: moveq #0,d2 ; -> don't charge at player rts ; =========================================================================== ; loc_36EE2: Obj91_PlayerInRange: moveq #1,d2 ; -> charge at player rts ; =========================================================================== ; off_36EE6: Obj91_SubObjData: subObjData Obj91_MapUnc_36EF6,make_art_tile(ArtTile_ArtNem_ChopChop,1,0),4,4,$10,2 ; animation script ; off_36EF0: Ani_obj91: offsetTable offsetTableEntry.w + + dc.b 4, 0, 1,$FF ; 0 even ; -------------------------------------------------------------------------- ; sprite mappings ; -------------------------------------------------------------------------- Obj91_MapUnc_36EF6: BINCLUDE "mappings/sprite/obj91.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 92 - Spiker (drill badnik) from HTZ ; ---------------------------------------------------------------------------- ; Sprite_36F0E: Obj92: moveq #0,d0 move.b routine(a0),d0 move.w Obj92_Index(pc,d0.w),d1 jmp Obj92_Index(pc,d1.w) ; =========================================================================== ; off_36F1C: Obj92_Index: offsetTable offsetTableEntry.w Obj92_Init ; 0 offsetTableEntry.w loc_36F3C ; 2 offsetTableEntry.w loc_36F68 ; 4 offsetTableEntry.w loc_36F90 ; 6 ; =========================================================================== ; loc_36F24: Obj92_Init: bsr.w LoadSubObject move.b #$40,objoff_2A(a0) move.w #$80,x_vel(a0) bchg #0,status(a0) rts ; =========================================================================== loc_36F3C: bsr.w loc_3703E bne.s loc_36F48 subq.b #1,objoff_2A(a0) bmi.s loc_36F5A loc_36F48: jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (Ani_obj92).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_36F5A: addq.b #2,routine(a0) move.b #$10,objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_36F68: bsr.w loc_3703E bne.s + subq.b #1,objoff_2A(a0) bmi.s loc_36F78 + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_36F78: subq.b #2,routine(a0) move.b #$40,objoff_2A(a0) neg.w x_vel(a0) bchg #0,status(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_36F90: move.b objoff_2E(a0),d0 cmpi.b #8,d0 beq.s loc_36FA4 subq.b #1,d0 move.b d0,objoff_2E(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_36FA4: jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s loc_36FDC st objoff_2B(a0) _move.b #ObjID_SpikerDrill,id(a1) ; load obj93 move.b subtype(a0),subtype(a1) move.w a0,objoff_2C(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b #4,mapping_frame(a1) move.b #2,mapping_frame(a0) move.b #1,anim(a0) loc_36FDC: move.b objoff_2F(a0),routine(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 93 - Drill thrown by Spiker from HTZ ; ---------------------------------------------------------------------------- ; Sprite_36FE6: Obj93: moveq #0,d0 move.b routine(a0),d0 move.w Obj93_Index(pc,d0.w),d1 jmp Obj93_Index(pc,d1.w) ; =========================================================================== ; off_36FF4: Obj93_Index: offsetTable offsetTableEntry.w Obj93_Init ; 0 offsetTableEntry.w loc_37028 ; 2 ; =========================================================================== ; loc_36FF8: Obj93_Init: bsr.w LoadSubObject ori.b #$80,render_flags(a0) ori.b #$80,collision_flags(a0) movea.w objoff_2C(a0),a1 ; a1=object move.b render_flags(a1),d0 andi.b #3,d0 or.b d0,render_flags(a0) moveq #2,d1 btst #1,d0 bne.s + neg.w d1 + move.b d1,y_vel(a0) rts ; =========================================================================== loc_37028: tst.b render_flags(a0) bpl.w JmpTo65_DeleteObject bchg #0,render_flags(a0) jsrto (ObjectMove).l, JmpTo26_ObjectMove jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3703E: tst.b objoff_2B(a0) bne.s loc_37062 tst.b render_flags(a0) bpl.s loc_37062 bsr.w Obj_GetOrientationToPlayer addi.w #$20,d2 cmpi.w #$40,d2 bhs.s loc_37062 addi.w #$80,d3 cmpi.w #$100,d3 blo.s loc_37066 loc_37062: moveq #0,d0 rts ; =========================================================================== loc_37066: move.b routine(a0),objoff_2F(a0) move.b #6,routine(a0) move.b #$10,objoff_2E(a0) moveq #1,d0 rts ; =========================================================================== ; off_3707C: Obj92_SubObjData: subObjData Obj92_Obj93_MapUnc_37092,make_art_tile(ArtTile_ArtKos_LevelArt,0,0),4,4,$10,$12 ; animation script ; off_37086: Ani_obj92: offsetTable offsetTableEntry.w byte_3708A ; 0 offsetTableEntry.w byte_3708E ; 2 byte_3708A: dc.b 9, 0, 1,$FF byte_3708E: dc.b 9, 2, 3,$FF even ; --------------------------------------------------------------------------- ; sprite mappings ; --------------------------------------------------------------------------- Obj92_Obj93_MapUnc_37092: BINCLUDE "mappings/sprite/obj93.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 95 - Sol (fireball-throwing orbit badnik) from HTZ ; ---------------------------------------------------------------------------- ; Sprite_370FE: Obj95: moveq #0,d0 move.b routine(a0),d0 move.w Obj95_Index(pc,d0.w),d1 jmp Obj95_Index(pc,d1.w) ; =========================================================================== ; off_3710C: Obj95_Index: offsetTable offsetTableEntry.w Obj95_Init ; 0 offsetTableEntry.w Obj95_WaitForPlayer ; 2 offsetTableEntry.w loc_37224 ; 4 offsetTableEntry.w Obj95_FireballUpdate ; 6 offsetTableEntry.w loc_372B8 ; 8 ; =========================================================================== ; loc_37116: Obj95_Init: move.l #Obj95_MapUnc_372E6,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo64_Adjust2PArtPointer ori.b #4,render_flags(a0) move.b #4,priority(a0) move.b #$B,collision_flags(a0) move.b #$C,width_pixels(a0) move.w #-$40,x_vel(a0) moveq #0,d2 lea objoff_37(a0),a2 movea.l a2,a3 addq.w #1,a2 moveq #3,d1 ; loc_37152: Obj95_NextFireball: jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s loc_371AE addq.b #1,(a3) move.w a1,d5 subi.w #MainCharacter,d5 if object_size=$40 lsr.w #6,d5 else divu.w #object_size,d5 endif andi.w #$7F,d5 move.b d5,(a2)+ _move.b id(a0),id(a1) ; load obj95 move.b #6,routine(a1) move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) ori.b #4,render_flags(a1) move.b #4,priority(a1) move.b #8,width_pixels(a1) move.b #3,mapping_frame(a1) move.b #$98,collision_flags(a1) move.b d2,angle(a1) addi.b #$40,d2 move.l a0,objoff_3C(a1) dbf d1,Obj95_NextFireball loc_371AE: moveq #1,d0 btst #0,status(a0) beq.s loc_371BA neg.w d0 loc_371BA: move.b d0,objoff_36(a0) move.b subtype(a0),routine(a0) addq.b #2,routine(a0) move.w #-$40,x_vel(a0) btst #0,status(a0) beq.s return_371DA neg.w x_vel(a0) return_371DA: rts ; =========================================================================== ; loc_371DC: Obj95_WaitForPlayer: move.w (MainCharacter+x_pos).w,d0 sub.w x_pos(a0),d0 bcc.s loc_371E8 neg.w d0 loc_371E8: cmpi.w #$A0,d0 bhs.s loc_3720C move.w (MainCharacter+y_pos).w,d0 sub.w y_pos(a0),d0 bcc.s loc_371FA neg.w d0 loc_371FA: cmpi.w #$50,d0 bhs.s loc_3720C tst.w (Debug_placement_mode).w bne.s loc_3720C move.b #1,anim(a0) loc_3720C: jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (Ani_obj95_a).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite andi.b #3,mapping_frame(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_37224: jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (Ani_obj95_b).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite andi.b #3,mapping_frame(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_3723C: Obj95_FireballUpdate: lea (Ani_obj95_b).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite movea.l objoff_3C(a0),a1 ; a1=object _cmpi.b #ObjID_Sol,id(a1) ; check if parent object is still alive bne.w JmpTo65_DeleteObject cmpi.b #2,mapping_frame(a1) bne.s Obj95_FireballOrbit cmpi.b #$40,angle(a0) bne.s Obj95_FireballOrbit addq.b #2,routine(a0) move.b #0,anim(a0) subq.b #1,objoff_37(a1) bne.s loc_37278 addq.b #2,routine(a1) loc_37278: move.w #-$200,x_vel(a0) btst #0,status(a1) beq.s + neg.w x_vel(a0) + jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; loc_3728E: Obj95_FireballOrbit: move.b angle(a0),d0 jsr (CalcSine).l asr.w #4,d1 add.w x_pos(a1),d1 move.w d1,x_pos(a0) asr.w #4,d0 add.w y_pos(a1),d0 move.w d0,y_pos(a0) move.b objoff_36(a1),d0 add.b d0,angle(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_372B8: jsrto (ObjectMove).l, JmpTo26_ObjectMove tst.b render_flags(a0) bpl.w JmpTo65_DeleteObject lea (Ani_obj95_b).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; animation script ; off_372D2: Ani_obj95_a: offsetTable offsetTableEntry.w byte_372D6 ; 0 offsetTableEntry.w byte_372DA ; 1 byte_372D6: dc.b $F, 0,$FF, 0 byte_372DA: dc.b $F, 1, 2,$FE, 1 even ; animation script ; off_372E0: Ani_obj95_b: offsetTable offsetTableEntry.w + + dc.b 5, 3, 4,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj95_MapUnc_372E6: BINCLUDE "mappings/sprite/obj95.bin" Invalid_SubObjData: ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 94,96 - Rexon (lava snake badnik), from HTZ ; ---------------------------------------------------------------------------- ; Sprite_37322: Obj94: moveq #0,d0 move.b routine(a0),d0 move.w Obj94_Index(pc,d0.w),d1 jmp Obj94_Index(pc,d1.w) ; =========================================================================== ; off_37330: Obj94_Index: offsetTable offsetTableEntry.w Obj94_Init ; 0 offsetTableEntry.w Obj94_WaitForPlayer ; 2 offsetTableEntry.w Obj94_ReadyToCreateHead ; 4 offsetTableEntry.w Obj94_PostCreateHead ; 6 ; =========================================================================== ; loc_37338: Obj94_Init: bsr.w LoadSubObject move.b #2,mapping_frame(a0) move.w #-$20,x_vel(a0) move.b #$80,objoff_2A(a0) rts ; =========================================================================== ; loc_37350: Obj94_WaitForPlayer: bsr.w Obj_GetOrientationToPlayer addi.w #$60,d2 cmpi.w #$100,d2 bhs.s loc_37362 bsr.w Obj94_CreateHead loc_37362: move.w x_pos(a0),-(sp) bsr.w Obj94_CheckTurnAround move.w #$1B,d1 move.w #8,d2 move.w #$11,d3 move.w (sp)+,d4 jsrto (SolidObject).l, JmpTo27_SolidObject jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_37380: Obj94_CheckTurnAround: subq.b #1,objoff_2A(a0) bpl.s loc_37396 move.b #$80,objoff_2A(a0) neg.w x_vel(a0) bchg #0,render_flags(a0) loc_37396: jsrto (ObjectMove).l, JmpTo26_ObjectMove rts ; =========================================================================== ; loc_3739C: Obj94_ReadyToCreateHead: bsr.w Obj_GetOrientationToPlayer addi.w #$60,d2 cmpi.w #$100,d2 bhs.s loc_373AE bsr.w Obj94_CreateHead loc_373AE: bsr.w Obj94_SolidCollision jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_373B6: Obj94_SolidCollision: move.w #$1B,d1 move.w #8,d2 move.w #8,d3 move.w x_pos(a0),d4 jmpto (SolidObject).l, JmpTo27_SolidObject ; =========================================================================== ; loc_373CA: Obj94_PostCreateHead: bsr.s Obj94_SolidCollision jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 97 - Rexon's head, from HTZ ; ---------------------------------------------------------------------------- ; Sprite_373D0: Obj97: moveq #0,d0 move.b routine(a0),d0 move.w Obj97_Index(pc,d0.w),d1 jmp Obj97_Index(pc,d1.w) ; =========================================================================== ; off_373DE: Obj97_Index: offsetTable offsetTableEntry.w Obj97_Init ; 0 offsetTableEntry.w Obj97_InitialWait ; 2 offsetTableEntry.w Obj97_RaiseHead ; 4 offsetTableEntry.w Obj97_Normal ; 6 offsetTableEntry.w Obj97_DeathDrop ; 8 ; =========================================================================== ; loc_373E8: Obj97_Init: bsr.w LoadSubObject move.b #8,width_pixels(a0) moveq #$28,d0 btst #0,render_flags(a0) bne.s + moveq #-$18,d0 + add.w d0,x_pos(a0) addi.w #$10,y_pos(a0) move.b #1,objoff_38(a0) movea.w objoff_2C(a0),a1 ; a1=object lea objoff_2E(a1),a1 move.b #$B,collision_flags(a0) moveq #0,d0 move.w objoff_2E(a0),d0 cmpi.w #8,d0 beq.s + move.b #1,mapping_frame(a0) move.b #$8B,collision_flags(a0) move.w (a1,d0.w),objoff_30(a0) + move.w 6(a1),objoff_32(a0) lsr.w #1,d0 move.b byte_3744E(pc,d0.w),objoff_2A(a0) move.b d0,objoff_39(a0) rts ; =========================================================================== byte_3744E: dc.b $1E dc.b $18 ; 1 dc.b $12 ; 2 dc.b $C ; 3 dc.b 6 ; 4 dc.b 0 ; 5 ; =========================================================================== ; loc_37454: Obj97_InitialWait: if gameRevision<2 bsr.w Obj97_CheckHeadIsAlive subq.b #1,objoff_2A(a0) bmi.s Obj97_StartRaise else ; fixes an occational crash when defeated subq.b #1,objoff_2A(a0) bmi.s Obj97_StartRaise bsr.w Obj97_CheckHeadIsAlive endif jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_37462: Obj97_StartRaise: addq.b #2,routine(a0) move.w #-$120,x_vel(a0) move.w #-$200,y_vel(a0) move.w objoff_2E(a0),d0 subi_.w #8,d0 neg.w d0 lsr.w #1,d0 move.b byte_3744E(pc,d0.w),objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_37488: Obj97_RaiseHead: if gameRevision<2 bsr.w Obj97_CheckHeadIsAlive moveq #$10,d0 add.w d0,x_vel(a0) subq.b #1,objoff_2A(a0) bmi.s Obj97_StartNormalState else ; fixes an occational crash when defeated moveq #$10,d0 add.w d0,x_vel(a0) subq.b #1,objoff_2A(a0) bmi.s Obj97_StartNormalState bsr.w Obj97_CheckHeadIsAlive endif jsrto (ObjectMove).l, JmpTo26_ObjectMove jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_374A0: Obj97_StartNormalState: addq.b #2,routine(a0) bsr.w Obj_MoveStop move.b #$20,objoff_2A(a0) move.w objoff_2E(a0),d0 lsr.w #1,d0 move.b byte_374BE(pc,d0.w),objoff_2B(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== byte_374BE: dc.b $24 dc.b $20 ; 1 dc.b $1C ; 2 dc.b $1A ; 3 ; =========================================================================== ; loc_374C2: Obj97_Normal: bsr.w Obj97_CheckHeadIsAlive cmpi.w #8,objoff_2E(a0) bne.s loc_374D8 subq.b #1,objoff_2A(a0) bpl.s loc_374D8 bsr.w Obj97_FireProjectile loc_374D8: move.b objoff_39(a0),d0 addq.b #1,d0 move.b d0,objoff_39(a0) andi.b #3,d0 bne.s + bsr.w loc_3758A bsr.w Obj97_Oscillate + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_374F4: Obj97_DeathDrop: move.w (Camera_Max_Y_pos_now).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 blo.w JmpTo65_DeleteObject jsrto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_3750C: Obj97_CheckHeadIsAlive: movea.w objoff_32(a0),a1 ; a1=object cmpi.b #ObjID_RexonHead,(a1) beq.s + ; rts move.b #8,routine(a0) move.w objoff_2E(a0),d0 move.w word_37528(pc,d0.w),x_vel(a0) + rts ; =========================================================================== word_37528: dc.w $80 dc.w -$100 ; 1 dc.w $100 ; 2 dc.w -$80 ; 3 dc.w $80 ; 4 ; =========================================================================== ; loc_37532: Obj97_FireProjectile: move.b #$7F,objoff_2A(a0) jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s ++ ; rts _move.b #ObjID_Projectile,id(a1) ; load obj98 move.b #3,mapping_frame(a1) move.b #$10,subtype(a1) ; <== Obj94_SubObjData2 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) lea (ObjectMove).l,a2 move.l a2,objoff_2A(a1) moveq #1,d0 moveq #$10,d1 btst #0,render_flags(a0) bne.s + neg.w d0 neg.w d1 + move.b d0,x_vel(a1) add.w d1,x_pos(a1) addq.w #4,y_pos(a1) move.b #$80,1+y_vel(a1) + rts ; =========================================================================== loc_3758A: move.b objoff_2B(a0),d0 move.b objoff_38(a0),d1 add.b d1,d0 move.b d0,objoff_2B(a0) subi.b #$18,d0 beq.s + bcs.s + cmpi.b #$10,d0 blo.s ++ ; rts + neg.b objoff_38(a0) + rts ; =========================================================================== ; loc_375AC: Obj94_CreateHead: move.b #6,routine(a0) bclr #0,render_flags(a0) tst.w d0 beq.s + bset #0,render_flags(a0) + bsr.w Obj_MoveStop lea objoff_2C(a0),a2 moveq #0,d1 moveq #4,d6 loc_375CE: jsrto (SingleObjLoad).l, JmpTo19_SingleObjLoad bne.s + ; rts _move.b #ObjID_RexonHead,id(a1) ; load obj97 move.b render_flags(a0),render_flags(a1) move.b subtype(a0),subtype(a1) move.w a0,objoff_2C(a1) move.w a1,(a2)+ move.w d1,objoff_2E(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addq.w #2,d1 dbf d6,loc_375CE + rts ; =========================================================================== ; loc_37604: Obj97_Oscillate: move.w objoff_30(a0),d0 beq.s + ; rts movea.w d0,a1 ; a1=object lea byte_376A8(pc),a2 moveq #0,d0 move.b objoff_2B(a0),d0 andi.b #$7F,d0 move.w d0,d1 andi.w #$1F,d0 add.w d0,d0 move.b (a2,d0.w),d2 ext.w d2 move.b 1(a2,d0.w),d3 ext.w d3 lsr.w #4,d1 andi.w #6,d1 move.w off_37652(pc,d1.w),d1 jsr off_37652(pc,d1.w) move.w x_pos(a0),d4 add.w d2,d4 move.w d4,x_pos(a1) move.b 1+y_pos(a0),d5 add.b d3,d5 move.b d5,1+y_pos(a1) + rts ; =========================================================================== off_37652: offsetTable offsetTableEntry.w return_3765A ; 0 offsetTableEntry.w loc_3765C ; $20 offsetTableEntry.w loc_37662 ; $40 offsetTableEntry.w loc_37668 ; $60 ; =========================================================================== return_3765A: rts ; =========================================================================== loc_3765C: exg d2,d3 neg.w d3 rts ; =========================================================================== loc_37662: neg.w d2 neg.w d3 rts ; =========================================================================== loc_37668: exg d2,d3 neg.w d2 rts ; =========================================================================== ; off_3766E: Obj94_SubObjData: subObjData Obj94_Obj98_MapUnc_37678,make_art_tile(ArtTile_ArtNem_Rexon,3,0),4,4,$10,0 ; ------------------------------------------------------------------------ ; sprite mappings ; ------------------------------------------------------------------------ Obj94_Obj98_MapUnc_37678: BINCLUDE "mappings/sprite/obj97.bin" ; seems to be a lookup table for oscillating horizontal position offset byte_376A8: dc.b $F, 0 dc.b $F,$FF ; 1 dc.b $F,$FF ; 2 dc.b $F,$FE ; 3 dc.b $F,$FD ; 4 dc.b $F,$FC ; 5 dc.b $E,$FC ; 6 dc.b $E,$FB ; 7 dc.b $E,$FA ; 8 dc.b $E,$FA ; 9 dc.b $D,$F9 ; 10 dc.b $D,$F8 ; 11 dc.b $C,$F8 ; 12 dc.b $C,$F7 ; 13 dc.b $C,$F6 ; 14 dc.b $B,$F6 ; 15 dc.b $B,$F5 ; 16 dc.b $A,$F5 ; 17 dc.b $A,$F4 ; 18 dc.b 9,$F4 ; 19 dc.b 8,$F4 ; 20 dc.b 8,$F3 ; 21 dc.b 7,$F3 ; 22 dc.b 6,$F2 ; 23 dc.b 6,$F2 ; 24 dc.b 5,$F2 ; 25 dc.b 4,$F2 ; 26 dc.b 4,$F1 ; 27 dc.b 3,$F1 ; 28 dc.b 2,$F1 ; 29 dc.b 1,$F1 ; 30 dc.b 1,$F1 ; 31 ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 98 - Projectile with optional gravity (EHZ coconut, CPZ spiny, etc.) ; ---------------------------------------------------------------------------- ; Sprite_376E8: Obj98: moveq #0,d0 move.b routine(a0),d0 move.w Obj98_Index(pc,d0.w),d1 jmp Obj98_Index(pc,d1.w) ; =========================================================================== ; off_376F6: Obj98_States: Obj98_Index: offsetTable offsetTableEntry.w Obj98_Init ; 0 offsetTableEntry.w Obj98_Main ; 2 ; =========================================================================== ; loc_376FA: Obj98_Init: ;; bra.w LoadSubObject ; =========================================================================== ; loc_376FE: Obj98_Main: tst.b render_flags(a0) bpl.w JmpTo65_DeleteObject movea.l objoff_2A(a0),a1 jsr (a1) ; dynamic call! to Obj98_NebulaBombFall, Obj98_TurtloidShotMove, Obj98_CoconutFall, Obj98_CluckerShotMove, Obj98_SpinyShotFall, or Obj98_WallTurretShotMove, assuming the code hasn't been changed jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; for obj99 ; loc_37710: Obj98_NebulaBombFall: bchg #palette_bit_0,art_tile(a0) ; bypass the animation system and make it blink jmpto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall ; =========================================================================== ; for obj9A ; loc_3771A: Obj98_TurtloidShotMove: jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (Ani_TurtloidShot).l,a1 jmpto (AnimateSprite).l, JmpTo25_AnimateSprite ; =========================================================================== ; for obj9D ; loc_37728: Obj98_CoconutFall: addi.w #$20,y_vel(a0) ; apply gravity (less than normal) jsrto (ObjectMove).l, JmpTo26_ObjectMove rts ; =========================================================================== ; for objAE ; loc_37734: Obj98_CluckerShotMove: jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (Ani_CluckerShot).l,a1 jmpto (AnimateSprite).l, JmpTo25_AnimateSprite ; =========================================================================== ; for objA6 ; loc_37742: Obj98_SpinyShotFall: addi.w #$20,y_vel(a0) ; apply gravity (less than normal) jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (Ani_SpinyShot).l,a1 jmpto (AnimateSprite).l, JmpTo25_AnimateSprite ; =========================================================================== ; for objB8 ; loc_37756: Obj98_WallTurretShotMove: jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (Ani_WallTurretShot).l,a1 jmpto (AnimateSprite).l, JmpTo25_AnimateSprite ; =========================================================================== ; off_37764: Obj94_SubObjData2: subObjData Obj94_Obj98_MapUnc_37678,make_art_tile(ArtTile_ArtNem_Rexon,1,0),$84,4,4,$98 ; off_3776E: Obj99_SubObjData: subObjData Obj99_Obj98_MapUnc_3789A,make_art_tile(ArtTile_ArtNem_Nebula,1,1),$84,4,8,$8B ; off_37778: Obj9A_SubObjData2: subObjData Obj9A_Obj98_MapUnc_37B62,make_art_tile(ArtTile_ArtNem_Turtloid,0,0),$84,4,4,$98 ; off_37782: Obj9D_SubObjData2: subObjData Obj9D_Obj98_MapUnc_37D96,make_art_tile(ArtTile_ArtNem_Coconuts,0,0),$84,4,8,$8B ; off_3778C: ObjA4_SubObjData2: subObjData ObjA4_Obj98_MapUnc_38A96,make_art_tile(ArtTile_ArtNem_MtzSupernova,0,1),$84,5,4,$98 ; off_37796: ObjA6_SubObjData: subObjData ObjA5_ObjA6_Obj98_MapUnc_38CCA,make_art_tile(ArtTile_ArtNem_Spiny,1,0),$84,5,4,$98 ; off_377A0: ObjA7_SubObjData3: subObjData ObjA7_ObjA8_ObjA9_Obj98_MapUnc_3921A,make_art_tile(ArtTile_ArtNem_Grabber,1,1),$84,4,4,$98 ; off_377AA: ObjAD_SubObjData3: subObjData ObjAD_Obj98_MapUnc_395B4,make_art_tile(ArtTile_ArtNem_WfzScratch,0,0),$84,5,4,$98 ; off_377B4: ObjAF_SubObjData: subObjData ObjAF_Obj98_MapUnc_39E68,make_art_tile(ArtTile_ArtNem_CNZBonusSpike,1,0),$84,5,4,$98 ; off_377BE: ObjB8_SubObjData2: subObjData ObjB8_Obj98_MapUnc_3BA46,make_art_tile(ArtTile_ArtNem_WfzWallTurret,0,0),$84,3,4,$98 ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 99 - Nebula (bomber badnik) from SCZ ; ---------------------------------------------------------------------------- ; Sprite_377C8: Obj99: moveq #0,d0 move.b routine(a0),d0 move.w Obj99_Index(pc,d0.w),d1 jmp Obj99_Index(pc,d1.w) ; =========================================================================== ; off_377D6: Obj99_Index: offsetTable offsetTableEntry.w Obj99_Init offsetTableEntry.w loc_377E8 offsetTableEntry.w loc_3781C ; =========================================================================== ; loc_377DC: Obj99_Init: bsr.w LoadSubObject move.w #-$C0,x_vel(a0) rts ; =========================================================================== loc_377E8: bsr.w Obj_GetOrientationToPlayer tst.w d0 bne.s loc_377FA cmpi.w #$80,d2 bhs.s loc_377FA bsr.w loc_37810 loc_377FA: jsrto (ObjectMove).l, JmpTo26_ObjectMove bsr.w loc_36776 lea (Ani_obj99).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite bra.w Obj_DeleteBehindScreen ; =========================================================================== loc_37810: addq.b #2,routine(a0) move.w #-$A0,y_vel(a0) rts ; =========================================================================== loc_3781C: tst.b objoff_2A(a0) bne.s loc_37834 bsr.w Obj_GetOrientationToPlayer addi_.w #8,d2 cmpi.w #$10,d2 bhs.s loc_37834 bsr.w loc_37850 loc_37834: addi_.w #1,y_vel(a0) jsrto (ObjectMove).l, JmpTo26_ObjectMove bsr.w loc_36776 lea (Ani_obj99).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite bra.w Obj_DeleteBehindScreen ; =========================================================================== loc_37850: st objoff_2A(a0) jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s return_37886 _move.b #ObjID_Projectile,id(a1) ; load obj98 move.b #4,mapping_frame(a1) move.b #$14,subtype(a1) ; <== Obj99_SubObjData move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$18,y_pos(a1) lea_ Obj98_NebulaBombFall,a2 move.l a2,objoff_2A(a1) return_37886: rts ; =========================================================================== ; off_37888: Obj99_SubObjData2: subObjData Obj99_Obj98_MapUnc_3789A,make_art_tile(ArtTile_ArtNem_Nebula,1,1),4,4,$10,6 ; animation script ; off_37892: Ani_obj99: offsetTable offsetTableEntry.w + ; 0 + dc.b 3, 0, 1, 2, 3,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj99_Obj98_MapUnc_3789A: BINCLUDE "mappings/sprite/obj99.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 9A - Turtloid (turtle badnik) from Sky Chase Zone ; ---------------------------------------------------------------------------- ; Sprite_37936: Obj9A: moveq #0,d0 move.b routine(a0),d0 move.w Obj9A_Index(pc,d0.w),d1 jmp Obj9A_Index(pc,d1.w) ; =========================================================================== ; off_37944: Obj9A_Index: offsetTable offsetTableEntry.w Obj9A_Init ; 0 offsetTableEntry.w Obj9A_Main ; 2 ; =========================================================================== ; loc_37948: Obj9A_Init: bsr.w LoadSubObject move.w #-$80,x_vel(a0) bsr.w loc_37A4A lea (Ani_obj9A).l,a1 move.l a1,objoff_2E(a0) bra.w loc_37ABE ; =========================================================================== ; loc_37964: Obj9A_Main: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3797A(pc,d0.w),d1 jsr off_3797A(pc,d1.w) bsr.w loc_37982 bra.w Obj_DeleteBehindScreen ; =========================================================================== off_3797A: offsetTable offsetTableEntry.w loc_379A0 ; 0 offsetTableEntry.w loc_379CA ; 2 offsetTableEntry.w loc_379EA ; 4 offsetTableEntry.w return_37A04 ; 6 ; =========================================================================== loc_37982: move.w x_pos(a0),-(sp) jsrto (ObjectMove).l, JmpTo26_ObjectMove bsr.w loc_36776 move.w #$18,d1 move.w #8,d2 move.w #$E,d3 move.w (sp)+,d4 jmpto (PlatformObject).l, JmpTo9_PlatformObject ; =========================================================================== loc_379A0: bsr.w Obj_GetOrientationToPlayer tst.w d0 bmi.w return_37A48 cmpi.w #$80,d2 bhs.w return_37A48 addq.b #2,routine_secondary(a0) move.w #0,x_vel(a0) move.b #4,objoff_2A(a0) move.b #1,mapping_frame(a0) rts ; =========================================================================== loc_379CA: subq.b #1,objoff_2A(a0) bpl.w return_37A48 addq.b #2,routine_secondary(a0) move.b #8,objoff_2A(a0) movea.w objoff_2C(a0),a1 ; a1=object move.b #3,mapping_frame(a1) bra.w loc_37AF2 ; =========================================================================== loc_379EA: subq.b #1,objoff_2A(a0) bpl.s return_37A02 addq.b #2,routine_secondary(a0) move.w #-$80,x_vel(a0) clr.b mapping_frame(a0) movea.w objoff_2C(a0),a1 ; a1=object return_37A02: rts ; =========================================================================== return_37A04: rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 9B - Turtloid rider from Sky Chase Zone ; ---------------------------------------------------------------------------- ; Sprite_37A06: Obj9B: moveq #0,d0 move.b routine(a0),d0 move.w Obj9B_Index(pc,d0.w),d1 jmp Obj9B_Index(pc,d1.w) ; =========================================================================== ; off_37A14: Obj9B_Index: offsetTable offsetTableEntry.w Obj9B_Init ; 0 offsetTableEntry.w Obj9B_Main ; 2 ; =========================================================================== ; BranchTo_LoadSubObject Obj9B_Init: bra.w LoadSubObject ; =========================================================================== ; loc_37A1C: Obj9B_Main: movea.w objoff_2C(a0),a1 ; a1=object lea word_37A2C(pc),a2 bsr.w loc_37A30 bra.w Obj_DeleteBehindScreen ; =========================================================================== word_37A2C: dc.w 4 ; 0 dc.w -$18 ; 1 ; =========================================================================== loc_37A30: move.l x_pos(a1),x_pos(a0) move.l y_pos(a1),y_pos(a0) move.w (a2)+,d0 add.w d0,x_pos(a0) move.w (a2)+,d0 add.w d0,y_pos(a0) return_37A48: rts ; =========================================================================== loc_37A4A: jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s return_37A80 _move.b #ObjID_TurtloidRider,id(a1) ; load obj9B move.b #2,mapping_frame(a1) move.b #$18,subtype(a1) ; <== Obj9B_SubObjData move.w a0,objoff_2C(a1) move.w a1,objoff_2C(a0) move.w x_pos(a0),x_pos(a1) addq.w #4,x_pos(a1) move.w y_pos(a0),y_pos(a1) subi.w #$18,y_pos(a1) return_37A80: rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 9C - Balkiry's jet from Sky Chase Zone ; ---------------------------------------------------------------------------- ; Sprite_37A82: Obj9C: moveq #0,d0 move.b routine(a0),d0 move.w Obj9C_Index(pc,d0.w),d1 jmp Obj9C_Index(pc,d1.w) ; =========================================================================== ; off_37A90: Obj9C_Index: offsetTable offsetTableEntry.w Obj9C_Init offsetTableEntry.w Obj9C_Main ; =========================================================================== ; BranchTo2_LoadSubObject Obj9C_Init: bra.w LoadSubObject ; =========================================================================== ; loc_37A98: Obj9C_Main: movea.w objoff_2C(a0),a1 ; a1=object move.b objoff_32(a0),d0 cmp.b (a1),d0 bne.w JmpTo65_DeleteObject move.l x_pos(a1),x_pos(a0) move.l y_pos(a1),y_pos(a0) movea.l objoff_2E(a0),a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite bra.w Obj_DeleteBehindScreen ; =========================================================================== loc_37ABE: jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s + ; rts _move.b #ObjID_BalkiryJet,id(a1) ; load obj9C move.b #6,mapping_frame(a1) move.b #$1A,subtype(a1) ; <== Obj9C_SubObjData move.w a0,objoff_2C(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.l objoff_2E(a0),objoff_2E(a1) move.b (a0),objoff_32(a1) + rts ; =========================================================================== ; this code is for Obj9A loc_37AF2: jsrto (SingleObjLoad).l, JmpTo19_SingleObjLoad bne.s + ; rts _move.b #ObjID_Projectile,id(a1) ; load obj98 move.b #6,mapping_frame(a1) move.b #$1C,subtype(a1) ; <== Obj9A_SubObjData2 move.w x_pos(a0),x_pos(a1) subi.w #$14,x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$A,y_pos(a1) move.w #-$100,x_vel(a1) lea_ Obj98_TurtloidShotMove,a2 move.l a2,objoff_2A(a1) + rts ; =========================================================================== ; off_37B32: Obj9A_SubObjData: subObjData Obj9A_Obj98_MapUnc_37B62,make_art_tile(ArtTile_ArtNem_Turtloid,0,0),4,5,$18,0 ; off_37B3C: Obj9B_SubObjData: subObjData Obj9A_Obj98_MapUnc_37B62,make_art_tile(ArtTile_ArtNem_Turtloid,0,0),4,4,$C,$1A ; off_37B46: Obj9C_SubObjData: subObjData Obj9A_Obj98_MapUnc_37B62,make_art_tile(ArtTile_ArtNem_Turtloid,0,0),4,5,8,0 ; animation script ; off_37B50: TurtloidShotAniData: Ani_TurtloidShot: offsetTable offsetTableEntry.w + + dc.b 1, 4, 5,$FF even ; animation script ; off_37B56: Ani_obj9A: offsetTable offsetTableEntry.w + + dc.b 1, 6, 7,$FF even ; animation script ; off_37B5C: Ani_obj9C: offsetTable offsetTableEntry.w + + dc.b 1, 8, 9,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj9A_Obj98_MapUnc_37B62: BINCLUDE "mappings/sprite/obj9C.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 9D - Coconuts (monkey badnik) from EHZ ; ---------------------------------------------------------------------------- ; OST Variables: Obj9D_timer = objoff_2A ; byte Obj9D_climb_table_index = objoff_2C ; word Obj9D_attack_timer = objoff_2E ; byte ; time player needs to spend close to object before it attacks ; Sprite_37BFA: Obj9D: moveq #0,d0 move.b routine(a0),d0 move.w Obj9D_Index(pc,d0.w),d1 jmp Obj9D_Index(pc,d1.w) ; =========================================================================== ; off_37C08: Obj9D_Index: offsetTable offsetTableEntry.w Obj9D_Init ; 0 offsetTableEntry.w Obj9D_Idle ; 2 offsetTableEntry.w Obj9D_Climbing ; 4 offsetTableEntry.w Obj9D_Throwing ; 6 ; =========================================================================== ; loc_37C10: Obj9D_Init: bsr.w LoadSubObject move.b #$10,Obj9D_timer(a0) rts ; =========================================================================== ; loc_37C1C: Obj9D_Main: Obj9D_Idle: bsr.w Obj_GetOrientationToPlayer bclr #0,render_flags(a0) ; face right bclr #0,status(a0) tst.w d0 ; is player to object's left? beq.s + ; if not, branch bset #0,render_flags(a0) ; face left bset #0,status(a0) + addi.w #$60,d2 cmpi.w #$C0,d2 bcc.s + ; branch, if distance to player is greater than 60 in either direction tst.b Obj9D_attack_timer(a0) ; wait for a bit before attacking beq.s Obj9D_StartThrowing ; branch, when done waiting subq.b #1,Obj9D_attack_timer(a0) + subq.b #1,Obj9D_timer(a0) ; wait for a bit... bmi.s Obj9D_StartClimbing ; branch, when done waiting jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; --------------------------------------------------------------------------- Obj9D_StartClimbing: addq.b #2,routine(a0) ; => Obj9D_Climbing bsr.w Obj9D_SetClimbingDirection jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; --------------------------------------------------------------------------- ; loc_37C66: Obj9D_StartThrowing: move.b #6,routine(a0) ; => Obj9D_Throwing move.b #1,mapping_frame(a0) ; display first throwing frame move.b #8,Obj9D_timer(a0) ; set time to display frame move.b #$20,Obj9D_attack_timer(a0) ; reset timer jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; --------------------------------------------------------------------------- ; loc_37C82: Obj9D_SetClimbingDirection: move.w Obj9D_climb_table_index(a0),d0 cmpi.w #$C,d0 blo.s + ; branch, if index is less than $C moveq #0,d0 ; otherwise, reset to 0 + lea Obj9D_ClimbData(pc,d0.w),a1 addq.w #2,d0 move.w d0,Obj9D_climb_table_index(a0) move.b (a1)+,y_vel(a0) ; climbing speed move.b (a1)+,Obj9D_timer(a0) ; time to spend moving at this speed rts ; =========================================================================== ; byte_37CA2: Obj9D_ClimbData: dc.b -1,$20 dc.b 1,$18 ; 2 dc.b -1,$10 ; 4 dc.b 1,$28 ; 6 dc.b -1,$20 ; 8 dc.b 1,$10 ; 10 ; =========================================================================== ; loc_37CAE: Obj09_Climbing: Obj9D_Climbing: subq.b #1,Obj9D_timer(a0) beq.s Obj9D_StopClimbing ; branch, if done moving jsrto (ObjectMove).l, JmpTo26_ObjectMove ; else, keep moving lea (Ani_obj09).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_37CC6: Obj9D_StopClimbing: subq.b #2,routine(a0) ; => Obj9D_Idle move.b #$10,Obj9D_timer(a0) ; time to remain idle jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_37CD4: Obj09_Throwing: Obj9D_Throwing: moveq #0,d0 move.b routine_secondary(a0),d0 move.w Obj9D_ThrowingStates(pc,d0.w),d1 jsr Obj9D_ThrowingStates(pc,d1.w) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; off_37CE6: Obj9D_ThrowingStates: offsetTable offsetTableEntry.w Obj9D_ThrowingHandRaised ; 0 offsetTableEntry.w Obj9D_ThrowingHandLowered ; 2 ; =========================================================================== ; loc_37CEA: Obj9D_ThrowingHandRaised: subq.b #1,Obj9D_timer(a0) ; wait for a bit... bmi.s + rts ; --------------------------------------------------------------------------- + addq.b #2,routine_secondary(a0) ; => Obj9D_ThrowingHandLowered move.b #8,Obj9D_timer(a0) move.b #2,mapping_frame(a0) ; display second throwing frame bra.w Obj9D_CreateCoconut ; =========================================================================== ; loc_37D06: Obj9D_ThrowingHandLowered: subq.b #1,Obj9D_timer(a0) ; wait for a bit... bmi.s + rts ; --------------------------------------------------------------------------- + clr.b routine_secondary(a0) ; reset routine counter for next time move.b #4,routine(a0) ; => Obj9D_Climbing move.b #8,Obj9D_timer(a0) ; this gets overwrittten by the next subroutine... bra.w Obj9D_SetClimbingDirection ; =========================================================================== ; loc_37D22: Obj9D_CreateCoconut: jsrto (SingleObjLoad).l, JmpTo19_SingleObjLoad bne.s return_37D74 ; branch, if no free slots _move.b #ObjID_Projectile,id(a1) ; load obj98 move.b #3,mapping_frame(a1) move.b #$20,subtype(a1) ; <== Obj9D_SubObjData2 move.w x_pos(a0),x_pos(a1) ; align with parent object move.w y_pos(a0),y_pos(a1) addi.w #-$D,y_pos(a1) ; offset slightly upward moveq #0,d0 ; use rightfacing data btst #0,render_flags(a0) ; is object facing left? bne.s + ; if yes, branch moveq #4,d0 ; use leftfacing data + lea Obj9D_ThrowData(pc,d0.w),a2 move.w (a2)+,d0 add.w d0,x_pos(a1) ; offset slightly left or right depending on object's direction move.w (a2)+,x_vel(a1) ; set projectile speed move.w #-$100,y_vel(a1) lea_ Obj98_CoconutFall,a2 ; set the routine used to move the projectile move.l a2,objoff_2A(a1) return_37D74: rts ; =========================================================================== ; word_37D76: Obj9D_ThrowData: dc.w -$B, $100 ; 0 dc.w $B, -$100 ; 4 ; off_37D7E: Obj9D_SubObjData: subObjData Obj9D_Obj98_MapUnc_37D96,make_art_tile(ArtTile_ArtNem_Coconuts,0,0),4,5,$C,9 ; animation script ; off_37D88: Ani_obj09: offsetTable offsetTableEntry.w byte_37D8C ; 0 offsetTableEntry.w byte_37D90 ; 1 byte_37D8C: dc.b 5, 0, 1,$FF byte_37D90: dc.b 9, 1, 2, 1,$FF even ; ------------------------------------------------------------------------ ; sprite mappings ; ------------------------------------------------------------------------ Obj9D_Obj98_MapUnc_37D96: BINCLUDE "mappings/sprite/obj9D.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 9E - Crawlton (snake badnik) from MCZ ; ---------------------------------------------------------------------------- ; Sprite_37E16: Obj9E: moveq #0,d0 move.b objoff_3B(a0),d0 move.w Obj9E_Index(pc,d0.w),d1 jmp Obj9E_Index(pc,d1.w) ; =========================================================================== ; off_37E24: Obj9E_Index: offsetTable offsetTableEntry.w Obj9E_Init ; 0 offsetTableEntry.w loc_37E42 ; 2 offsetTableEntry.w loc_37E98 ; 4 offsetTableEntry.w loc_37EB6 ; 6 offsetTableEntry.w loc_37ED4 ; 8 offsetTableEntry.w loc_37EFC ; $A ; =========================================================================== ; loc_37E30: Obj9E_Init: bsr.w LoadSubObject move.b #$80,y_radius(a0) addq.b #2,objoff_3B(a0) bra.w loc_37F74 ; =========================================================================== loc_37E42: bsr.w Obj_GetOrientationToPlayer move.w d2,d4 move.w d3,d5 addi.w #$80,d2 cmpi.w #$100,d2 bhs.s + addi.w #$80,d3 cmpi.w #$100,d3 blo.s loc_37E62 + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_37E62: addq.b #2,objoff_3B(a0) move.b #$10,objoff_3A(a0) bclr #0,render_flags(a0) tst.w d0 beq.s + bset #0,render_flags(a0) + neg.w d4 lsl.w #3,d4 andi.w #$FF00,d4 move.w d4,x_vel(a0) neg.w d5 lsl.w #3,d5 andi.w #$FF00,d5 move.w d5,y_vel(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_37E98: subq.b #1,objoff_3A(a0) bmi.s + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; --------------------------------------------------------------------------- + addq.b #2,objoff_3B(a0) move.b #8,objoff_39(a0) move.b #$1C,objoff_3A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_37EB6: subq.b #1,objoff_3A(a0) beq.s + jsrto (ObjectMove).l, JmpTo26_ObjectMove jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; --------------------------------------------------------------------------- + move.b objoff_39(a0),objoff_3B(a0) move.b #$20,objoff_3A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_37ED4: subq.b #1,objoff_3A(a0) beq.s + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; --------------------------------------------------------------------------- + move.b #6,objoff_3B(a0) move.b #2,objoff_39(a0) move.b #$1C,objoff_3A(a0) neg.w x_vel(a0) neg.w y_vel(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_37EFC: movea.w parent(a0),a1 ; a1=object cmpi.b #ObjID_Crawlton,id(a1) bne.w JmpTo65_DeleteObject bclr #0,render_flags(a0) btst #0,render_flags(a1) beq.s + bset #0,render_flags(a0) + move.b #$80,objoff_14(a0) move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) cmpi.b #6,objoff_3B(a1) bne.s loc_37F6C move.w x_vel(a1),d2 asr.w #8,d2 move.w y_vel(a1),d3 asr.w #8,d3 lea sub2_x_pos(a0),a2 move.b objoff_3A(a1),d0 moveq #$18,d1 moveq #6,d6 - move.w (a2),d4 ; sub?_x_pos move.w 2(a2),d5 ; sub?_y_pos cmp.b d1,d0 bhs.s + add.w d2,d4 add.w d3,d5 + move.w d4,(a2)+ ; sub?_x_pos move.w d5,(a2)+ ; sub?_y_pos subi_.b #4,d1 bcs.s loc_37F6C addq.w #next_subspr-4,a2 dbf d6,- loc_37F6C: move.w #$280,d0 jmpto (DisplaySprite3).l, JmpTo5_DisplaySprite3 ; =========================================================================== loc_37F74: jsrto (SingleObjLoad).l, JmpTo19_SingleObjLoad bne.s + ; rts _move.b #ObjID_Crawlton,id(a1) ; load obj9E move.b render_flags(a0),render_flags(a1) bset #6,render_flags(a1) move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) move.b #$A,objoff_3B(a1) move.b #0,mainspr_mapframe(a1) move.b #$80,mainspr_width(a1) move.b #7,mainspr_childsprites(a1) move.w a0,parent(a1) move.w x_pos(a0),d2 move.w d2,x_pos(a1) move.w y_pos(a0),d3 move.w d3,y_pos(a1) move.b #$80,objoff_14(a1) bset #4,render_flags(a1) lea sub2_x_pos(a1),a2 moveq #6,d6 - move.w d2,(a2)+ ; sub?_x_pos move.w d3,(a2)+ ; sub?_y_pos move.w #2,(a2)+ ; sub?_mapframe addi.w #$10,d1 dbf d6,- + rts ; =========================================================================== ; off_37FE8: Obj9E_SubObjData: subObjData Obj9E_MapUnc_37FF2,make_art_tile(ArtTile_ArtNem_Crawlton,1,0),4,4,$80,$B ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- Obj9E_MapUnc_37FF2: BINCLUDE "mappings/sprite/obj9E.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 9F - Shellcraker (crab badnik) from MTZ ; ---------------------------------------------------------------------------- ; Sprite_3800C: Obj9F: moveq #0,d0 move.b routine(a0),d0 move.w Obj9F_Index(pc,d0.w),d1 jmp Obj9F_Index(pc,d1.w) ; =========================================================================== ; off_3801A: Obj9F_Index: offsetTable offsetTableEntry.w Obj9F_Init ; 0 offsetTableEntry.w loc_3804E ; 2 offsetTableEntry.w loc_380C4 ; 4 offsetTableEntry.w loc_380FC ; 6 ; =========================================================================== ; loc_38022: Obj9F_Init: bsr.w LoadSubObject btst #0,render_flags(a0) beq.s + bset #0,status(a0) + move.w #-$40,x_vel(a0) move.b #$C,y_radius(a0) move.b #$18,x_radius(a0) move.w #$140,objoff_2A(a0) rts ; =========================================================================== loc_3804E: bsr.w Obj_GetOrientationToPlayer tst.w d0 beq.s loc_3805E btst #0,render_flags(a0) beq.s loc_38068 loc_3805E: addi.w #$60,d2 cmpi.w #$C0,d2 blo.s loc_380AE loc_38068: jsrto (ObjectMove).l, JmpTo26_ObjectMove jsr (ObjCheckFloorDist).l cmpi.w #-8,d1 blt.s loc_38096 cmpi.w #$C,d1 bge.s loc_38096 add.w d1,y_pos(a0) subq.w #1,objoff_2A(a0) bmi.s loc_3809A lea (Ani_obj9F).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38096: neg.w x_vel(a0) loc_3809A: addq.b #2,routine(a0) move.b #0,mapping_frame(a0) move.w #$3B,objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_380AE: move.b #6,routine(a0) move.b #0,mapping_frame(a0) move.w #8,objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_380C4: tst.b render_flags(a0) bpl.s loc_380E4 bsr.w Obj_GetOrientationToPlayer tst.w d0 beq.s loc_380DA btst #0,render_flags(a0) beq.s loc_380E4 loc_380DA: addi.w #$60,d2 cmpi.w #$C0,d2 blo.s loc_380AE loc_380E4: subq.w #1,objoff_2A(a0) bmi.s loc_380EE jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_380EE: subq.b #2,routine(a0) move.w #$140,objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_380FC: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3810E(pc,d0.w),d1 jsr off_3810E(pc,d1.w) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== off_3810E: offsetTable offsetTableEntry.w loc_38114 ; 0 offsetTableEntry.w loc_3812A ; 2 offsetTableEntry.w loc_3813E ; 4 ; =========================================================================== loc_38114: subq.w #1,objoff_2A(a0) bmi.s loc_3811C rts ; =========================================================================== loc_3811C: addq.b #2,routine_secondary(a0) move.b #3,mapping_frame(a0) bra.w loc_38292 ; =========================================================================== loc_3812A: tst.b objoff_2C(a0) bne.s loc_38132 rts ; =========================================================================== loc_38132: addq.b #2,routine_secondary(a0) move.w #$20,objoff_2A(a0) rts ; =========================================================================== loc_3813E: subq.w #1,objoff_2A(a0) bmi.s loc_38146 rts ; =========================================================================== loc_38146: clr.b routine_secondary(a0) clr.b objoff_2C(a0) move.b #2,routine(a0) move.w #$140,objoff_2A(a0) rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object A0 - Shellcracker's claw from MTZ ; ---------------------------------------------------------------------------- ; Sprite_3815C: ObjA0: moveq #0,d0 move.b routine(a0),d0 move.w ObjA0_Index(pc,d0.w),d1 jmp ObjA0_Index(pc,d1.w) ; =========================================================================== ; off_3816A: ObjA0_Index: offsetTable offsetTableEntry.w ObjA0_Init ; 0 offsetTableEntry.w loc_381AC ; 2 offsetTableEntry.w loc_38280 ; 4 ; =========================================================================== ; loc_38170: ObjA0_Init: bsr.w LoadSubObject movea.w objoff_2C(a0),a1 ; a1=object move.b render_flags(a1),d0 andi.b #1,d0 or.b d0,render_flags(a0) move.w objoff_2E(a0),d0 beq.s loc_38198 move.b #4,mapping_frame(a0) addq.w #6,x_pos(a0) addq.w #6,y_pos(a0) loc_38198: lsr.w #1,d0 move.b byte_381A4(pc,d0.w),objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== byte_381A4: dc.b 0 ; 0 dc.b 3 ; 1 dc.b 5 ; 2 dc.b 7 ; 3 dc.b 9 ; 4 dc.b $B ; 5 dc.b $D ; 6 dc.b $F ; 7 ; =========================================================================== loc_381AC: movea.w objoff_2C(a0),a1 ; a1=object cmpi.b #ObjID_Shellcracker,id(a1) bne.s loc_381D0 moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_381C8(pc,d0.w),d1 jsr off_381C8(pc,d1.w) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== off_381C8: offsetTable offsetTableEntry.w loc_381E0 ; 0 offsetTableEntry.w loc_3822A ; 2 offsetTableEntry.w loc_38244 ; 4 offsetTableEntry.w loc_38258 ; 6 ; =========================================================================== loc_381D0: move.b #4,routine(a0) move.w #$40,objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_381E0: subq.b #1,objoff_2A(a0) beq.s loc_381EA bmi.s loc_381EA rts ; =========================================================================== loc_381EA: addq.b #2,routine_secondary(a0) move.w objoff_2E(a0),d0 cmpi.w #$E,d0 bhs.s loc_3821A move.w #-$400,d2 btst #0,render_flags(a0) beq.s loc_38206 neg.w d2 loc_38206: move.w d2,x_vel(a0) lsr.w #1,d0 move.b byte_38222(pc,d0.w),d1 move.b d1,objoff_2A(a0) move.b d1,objoff_2B(a0) rts ; =========================================================================== loc_3821A: move.w #$B,objoff_2A(a0) rts ; =========================================================================== byte_38222: dc.b $D ; 0 dc.b $C ; 1 dc.b $A ; 2 dc.b 8 ; 3 dc.b 6 ; 4 dc.b 4 ; 5 dc.b 2 ; 6 dc.b 0 ; 7 ; =========================================================================== loc_3822A: jsrto (ObjectMove).l, JmpTo26_ObjectMove subq.b #1,objoff_2A(a0) beq.s loc_38238 bmi.s loc_38238 rts ; =========================================================================== loc_38238: addq.b #2,routine_secondary(a0) move.b #8,objoff_2A(a0) rts ; =========================================================================== loc_38244: subq.b #1,objoff_2A(a0) beq.s loc_3824E bmi.s loc_3824E rts ; =========================================================================== loc_3824E: addq.b #2,routine_secondary(a0) neg.w x_vel(a0) rts ; =========================================================================== loc_38258: jsrto (ObjectMove).l, JmpTo26_ObjectMove subq.b #1,objoff_2B(a0) beq.s loc_38266 bmi.s loc_38266 rts ; =========================================================================== loc_38266: tst.w objoff_2E(a0) bne.s loc_3827A movea.w objoff_2C(a0),a1 ; a1=object move.b #0,mapping_frame(a1) st objoff_2C(a1) loc_3827A: addq.w #4,sp bra.w JmpTo65_DeleteObject ; =========================================================================== loc_38280: jsrto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall subi_.w #1,objoff_2A(a0) bmi.w JmpTo65_DeleteObject jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38292: moveq #0,d1 moveq #7,d6 loc_38296: jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s return_382EE _move.b #ObjID_ShellcrackerClaw,id(a1) ; load objA0 move.b #$26,subtype(a1) ; <== ObjA0_SubObjData move.b #5,mapping_frame(a1) move.b #4,priority(a1) move.w a0,objoff_2C(a1) move.w d1,objoff_2E(a1) move.w x_pos(a0),x_pos(a1) move.w #-$14,d2 btst #0,render_flags(a0) beq.s loc_382D8 neg.w d2 tst.w d1 beq.s loc_382D8 subi.w #$C,d2 loc_382D8: add.w d2,x_pos(a1) move.w y_pos(a0),y_pos(a1) subi_.w #8,y_pos(a1) addq.w #2,d1 dbf d6,loc_38296 return_382EE: rts ; =========================================================================== ; off_382F0: Obj9F_SubObjData: subObjData Obj9F_MapUnc_38314,make_art_tile(ArtTile_ArtNem_Crabmeat,0,0),4,5,$18,$A ; off_382FA: ObjA0_SubObjData: subObjData Obj9F_MapUnc_38314,make_art_tile(ArtTile_ArtNem_Crabmeat,0,0),4,4,$C,$9A ; animation script ; off_38304: Ani_obj9F: offsetTable offsetTableEntry.w byte_38308 ; 0 offsetTableEntry.w byte_3830E ; 1 byte_38308: dc.b $E, 0, 1, 2,$FF, 0 byte_3830E: dc.b $E, 0, 2, 1,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj9F_MapUnc_38314: BINCLUDE "mappings/sprite/objA0.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object A1 - Slicer (praying mantis dude) from MTZ ; ---------------------------------------------------------------------------- ; Sprite_383B4: ObjA1: moveq #0,d0 move.b routine(a0),d0 move.w ObjA1_Index(pc,d0.w),d1 jmp ObjA1_Index(pc,d1.w) ; =========================================================================== ; off_383C2: ObjA1_Index: offsetTable offsetTableEntry.w ObjA1_Init ; 0 offsetTableEntry.w ObjA1_Main ; 2 offsetTableEntry.w loc_38466 ; 4 offsetTableEntry.w loc_38482 ; 6 offsetTableEntry.w BranchTo5_JmpTo39_MarkObjGone ; 8 ; =========================================================================== ; loc_383CC: ObjA1_Init: bsr.w LoadSubObject move.w #-$40,d0 btst #0,render_flags(a0) beq.s loc_383DE neg.w d0 loc_383DE: move.w d0,x_vel(a0) move.b #$10,y_radius(a0) move.b #$10,x_radius(a0) rts ; =========================================================================== ObjA1_Main: tst.b render_flags(a0) bpl.s loc_3841C bsr.w Obj_GetOrientationToPlayer btst #0,render_flags(a0) beq.s loc_38404 subq.w #2,d0 loc_38404: tst.w d0 bne.s loc_3841C addi.w #$80,d2 cmpi.w #$100,d2 bhs.s loc_3841C addi.w #$40,d3 cmpi.w #$80,d3 blo.s loc_38452 loc_3841C: jsrto (ObjectMove).l, JmpTo26_ObjectMove jsr (ObjCheckFloorDist).l cmpi.w #-8,d1 blt.s loc_38444 cmpi.w #$C,d1 bge.s loc_38444 add.w d1,y_pos(a0) lea (Ani_objA1).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38444: addq.b #2,routine(a0) move.b #$3B,objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38452: addq.b #4,routine(a0) move.b #3,mapping_frame(a0) move.b #8,objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38466: subq.b #1,objoff_2A(a0) bmi.s loc_38470 jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38470: subq.b #2,routine(a0) neg.w x_vel(a0) bchg #0,status(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38482: subq.b #1,objoff_2A(a0) bmi.s loc_3848C jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3848C: addq.b #2,routine(a0) move.b #4,mapping_frame(a0) bsr.w ObjA1_LoadPincers jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== BranchTo5_JmpTo39_MarkObjGone jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object A2 - Slicer's pincers from MTZ ; ---------------------------------------------------------------------------- ; Sprite_384A2: ObjA2: moveq #0,d0 move.b routine(a0),d0 move.w ObjA2_Index(pc,d0.w),d1 jmp ObjA2_Index(pc,d1.w) ; =========================================================================== ; off_384B0: ObjA2_Index: offsetTable offsetTableEntry.w ObjA2_Init ; 0 offsetTableEntry.w ObjA2_Main ; 2 offsetTableEntry.w ObjA2_Main2 ; 4 ; =========================================================================== ; loc_384B6: ObjA2_Init: bsr.w LoadSubObject jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ObjA2_Main: tst.b render_flags(a0) bpl.w JmpTo65_DeleteObject subq.w #1,objoff_2A(a0) bmi.s loc_3851A movea.w objoff_2C(a0),a1 ; a1=object cmpi.b #ObjID_Slicer,(a1) bne.s loc_3851A moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_384F6(pc,d0.w),d1 jsr off_384F6(pc,d1.w) jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (Ani_objA2).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== off_384F6: offsetTable offsetTableEntry.w + ; =========================================================================== + bsr.w Obj_GetOrientationToPlayer move.w ObjA2_acceleration(pc,d0.w),d2 add.w d2,x_vel(a0) move.w ObjA2_acceleration(pc,d1.w),d2 add.w d2,y_vel(a0) move.w #$200,d0 move.w d0,d1 bra.w Obj_CapSpeed ; =========================================================================== ObjA2_acceleration: dc.w -$10, $10 ; =========================================================================== loc_3851A: addq.b #2,routine(a0) move.w #$60,objoff_2A(a0) ObjA2_Main2: subq.w #1,objoff_2A(a0) bmi.w JmpTo65_DeleteObject jsrto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall lea (Ani_objA2).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ObjA1_LoadPincers: lea objoff_3C(a0),a2 ; a2=object moveq #0,d1 moveq #1,d6 loc_38546: jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s return_385BA _move.b #ObjID_SlicerPincers,id(a1) ; load objA2 move.b #$2A,subtype(a1) ; <== ObjA2_SubObjData move.b render_flags(a0),render_flags(a1) move.b #5,mapping_frame(a1) move.b #4,priority(a1) move.w #$78,objoff_2A(a1) move.w a0,objoff_2C(a1) move.w a1,(a2)+ move.w #-$200,d0 btst #0,render_flags(a1) beq.s loc_3858A neg.w d0 bset #0,status(a1) loc_3858A: move.w d0,x_vel(a1) lea ObjA1_Pincer_Offsets(pc,d1.w),a3 move.b (a3)+,d0 ext.w d0 btst #0,render_flags(a1) beq.s loc_385A0 neg.w d0 loc_385A0: add.w x_pos(a0),d0 move.w d0,x_pos(a1) move.b (a3)+,d0 ext.w d0 add.w y_pos(a0),d0 move.w d0,y_pos(a1) addq.w #2,d1 dbf d6,loc_38546 return_385BA: rts ; =========================================================================== ObjA1_Pincer_Offsets: dc.b 6, 0 ; 0 dc.b -$10, 0 ; 3 ; off_385C0 ObjA1_SubObjData: subObjData ObjA1_MapUnc_385E2,make_art_tile(ArtTile_ArtNem_MtzMantis,1,0),4,5,$10,6 ; off_385CA: ObjA2_SubObjData: subObjData ObjA1_MapUnc_385E2,make_art_tile(ArtTile_ArtNem_MtzMantis,1,0),4,4,$10,$9A ; animation script ; off_385D4: Ani_objA1: offsetTable offsetTableEntry.w + ; 0 + dc.b $13, 0, 2,$FF even ; animation script ; off_385DA: Ani_objA2: offsetTable offsetTableEntry.w + ; 0 + dc.b 3, 5, 6, 7, 8,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjA1_MapUnc_385E2: BINCLUDE "mappings/sprite/objA2.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object A3 - Flasher (firefly/glowbug badnik) from MCZ ; ---------------------------------------------------------------------------- ; Sprite_3873E: ObjA3: moveq #0,d0 move.b routine(a0),d0 move.w ObjA3_Index(pc,d0.w),d1 jmp ObjA3_Index(pc,d1.w) ; =========================================================================== ; off_3874C: ObjA3_Index: offsetTable offsetTableEntry.w loc_3875A ; 0 offsetTableEntry.w loc_38766 ; 2 offsetTableEntry.w loc_38794 ; 4 offsetTableEntry.w loc_38832 ; 6 offsetTableEntry.w loc_3885C ; 8 offsetTableEntry.w loc_38880 ; $A offsetTableEntry.w loc_3888E ; $C ; =========================================================================== loc_3875A: bsr.w LoadSubObject move.w #$40,objoff_2A(a0) rts ; =========================================================================== loc_38766: subq.w #1,objoff_2A(a0) bmi.s loc_38770 jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1 ; =========================================================================== loc_38770: addq.b #2,routine(a0) move.w #-$100,x_vel(a0) move.w #$40,y_vel(a0) move.w #2,objoff_2E(a0) clr.w objoff_2A(a0) move.w #$80,objoff_30(a0) jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1 ; =========================================================================== loc_38794: subq.w #1,objoff_30(a0) bmi.s loc_387FC move.w objoff_2A(a0),d0 bmi.w JmpTo65_DeleteObject bclr #0,render_flags(a0) bclr #0,status(a0) tst.w x_vel(a0) bmi.s loc_387C0 bset #0,render_flags(a0) bset #0,status(a0) loc_387C0: addq.w #1,d0 move.w d0,objoff_2A(a0) move.w objoff_2C(a0),d1 move.w word_38810(pc,d1.w),d2 cmp.w d2,d0 blo.s loc_387EC addq.w #2,d1 move.w d1,objoff_2C(a0) lea byte_38820(pc,d1.w),a1 tst.b (a1)+ beq.s loc_387E4 neg.w objoff_2E(a0) loc_387E4: tst.b (a1)+ beq.s loc_387EC neg.w y_vel(a0) loc_387EC: move.w objoff_2E(a0),d0 add.w d0,x_vel(a0) jsrto (ObjectMove).l, JmpTo26_ObjectMove jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1 ; =========================================================================== loc_387FC: addq.b #2,routine(a0) move.w #$80,objoff_30(a0) ori.b #$80,collision_flags(a0) jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1 ; =========================================================================== word_38810: dc.w $100 dc.w $1A0 ; 1 dc.w $208 ; 2 dc.w $285 ; 3 dc.w $300 ; 4 dc.w $340 ; 5 dc.w $390 ; 6 dc.w $440 ; 7 byte_38820: dc.b $F0 dc.b 0 ; 1 dc.b 1 ; 2 dc.b 1 ; 3 dc.b 0 ; 4 dc.b 1 ; 5 dc.b 1 ; 6 dc.b 1 ; 7 dc.b 0 ; 8 dc.b 1 ; 9 dc.b 0 ; 10 dc.b 1 ; 11 dc.b 1 ; 12 dc.b 0 ; 13 dc.b 0 ; 14 dc.b 1 ; 15 dc.b 0 ; 16 dc.b 1 ; 17 ; =========================================================================== loc_38832: move.b routine(a0),d2 lea (Ani_objA3_a).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite cmp.b routine(a0),d2 bne.s loc_3884A jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1 ; =========================================================================== loc_3884A: clr.l mapping_frame(a0) clr.w anim_frame_duration(a0) move.b #3,mapping_frame(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3885C: subq.w #1,objoff_30(a0) bmi.s loc_38870 lea (Ani_objA3_b).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1 ; =========================================================================== loc_38870: addq.b #2,routine(a0) clr.l mapping_frame(a0) clr.w anim_frame_duration(a0) jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1 ; =========================================================================== loc_38880: lea (Ani_objA3_c).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1 ; =========================================================================== loc_3888E: move.b #4,routine(a0) move.w #$80,objoff_30(a0) andi.b #$7F,collision_flags(a0) clr.l mapping_frame(a0) clr.w anim_frame_duration(a0) jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1 ; =========================================================================== ; off_388AC: ObjA3_SubObjData: subObjData ObjA3_MapUnc_388F0,make_art_tile(ArtTile_ArtNem_Flasher,0,1),4,4,$10,6 ; animation script ; off_388B6: Ani_objA3_a: offsetTable offsetTableEntry.w + ; 0 + dc.b 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1 dc.b 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 2, 3, 4, $FC even ; animation script ; off_388DA: Ani_objA3_b: offsetTable offsetTableEntry.w + ; 0 + dc.b 0, 2, 0, 3, 0, 4, 0, 3, 0,$FF even ; animation script ; off_388E6: Ani_objA3_c: offsetTable offsetTableEntry.w + ; 0 + dc.b 3, 4, 3, 2, 1, 0,$FC even ; ------------------------------------------------------------------------------- ; sprite mappings ; ------------------------------------------------------------------------------- ObjA3_MapUnc_388F0: BINCLUDE "mappings/sprite/objA3.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object A4 - Asteron (exploding starfish badnik) from MTZ ; ---------------------------------------------------------------------------- ; Sprite_3899C: ObjA4: moveq #0,d0 move.b routine(a0),d0 move.w ObjA4_Index(pc,d0.w),d1 jmp ObjA4_Index(pc,d1.w) ; =========================================================================== ; off_389AA: ObjA4_Index: offsetTable offsetTableEntry.w ObjA4_Init ; 0 offsetTableEntry.w loc_389B6 ; 2 offsetTableEntry.w loc_389DA ; 4 offsetTableEntry.w loc_38A2C ; 6 ; =========================================================================== ; BranchTo3_LoadSubObject ObjA4_Init: bra.w LoadSubObject ; =========================================================================== loc_389B6: bsr.w Obj_GetOrientationToPlayer addi.w #$60,d2 cmpi.w #$C0,d2 bhs.s BranchTo6_JmpTo39_MarkObjGone addi.w #$40,d3 cmpi.w #$80,d3 blo.s loc_389D2 BranchTo6_JmpTo39_MarkObjGone jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_389D2: addq.b #2,routine(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_389DA: bsr.w Obj_GetOrientationToPlayer abs.w d2 cmpi.w #$10,d2 blo.s loc_389FA cmpi.w #$60,d2 bhs.s loc_389FA move.w word_38A1A(pc,d0.w),x_vel(a0) bsr.w loc_38A1E loc_389FA: abs.w d3 cmpi.w #$10,d3 blo.s BranchTo7_JmpTo39_MarkObjGone cmpi.w #$60,d3 bhs.s BranchTo7_JmpTo39_MarkObjGone move.w word_38A1A(pc,d1.w),y_vel(a0) bsr.w loc_38A1E BranchTo7_JmpTo39_MarkObjGone jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== word_38A1A: dc.w -$40 ; 0 dc.w $40 ; 1 ; =========================================================================== loc_38A1E: move.b #6,routine(a0) move.b #$40,objoff_2A(a0) rts ; =========================================================================== loc_38A2C: subq.b #1,objoff_2A(a0) bmi.s loc_38A44 jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (Ani_objA4).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38A44: _move.b #ObjID_Explosion,id(a0) ; load 0bj27 move.b #2,routine(a0) bsr.w loc_38A58 jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38A58: move.b #$30,d2 moveq #4,d6 lea (word_38A68).l,a2 bra.w Obj_CreateProjectiles ; =========================================================================== word_38A68: dc.w $F8 dc.w $FC dc.w $200 dc.w $8FC dc.w $3FF dc.w $301 dc.w $808 dc.w $303 dc.w $401 dc.w $F808 dc.w $FD03 dc.w $400 dc.w $F8FC dc.w $FDFF dc.w $300 ; off_38A86: ObjA4_SubObjData: subObjData ObjA4_Obj98_MapUnc_38A96,make_art_tile(ArtTile_ArtNem_MtzSupernova,0,1),4,4,$10,$B ; animation script ; off_38A90: Ani_objA4: offsetTable offsetTableEntry.w + ; 0 + dc.b 1, 0, 1,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjA4_Obj98_MapUnc_38A96: BINCLUDE "mappings/sprite/objA4.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object A5 - Spiny (crawling badnik) from CPZ ; ---------------------------------------------------------------------------- ; Sprite_38AEA: ObjA5: moveq #0,d0 move.b routine(a0),d0 move.w ObjA5_Index(pc,d0.w),d1 jmp ObjA5_Index(pc,d1.w) ; =========================================================================== ; off_38AF8: ObjA5_Index: offsetTable offsetTableEntry.w ObjA5_Init ; 0 offsetTableEntry.w loc_38B10 ; 2 offsetTableEntry.w loc_38B62 ; 4 ; =========================================================================== ; loc_38AFE: ObjA5_Init: bsr.w LoadSubObject move.w #-$40,x_vel(a0) move.w #$80,objoff_2A(a0) rts ; =========================================================================== loc_38B10: tst.b objoff_2B(a0) beq.s loc_38B1E subq.b #1,objoff_2B(a0) bra.w loc_38B2C ; =========================================================================== loc_38B1E: bsr.w Obj_GetOrientationToPlayer addi.w #$60,d2 cmpi.w #$C0,d2 blo.s loc_38B4E loc_38B2C: subq.b #1,objoff_2A(a0) bne.s loc_38B3C move.w #$80,objoff_2A(a0) neg.w x_vel(a0) loc_38B3C: jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (Ani_objA5).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38B4E: addq.b #2,routine(a0) move.b #$28,objoff_2B(a0) move.b #2,mapping_frame(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38B62: subq.b #1,objoff_2B(a0) bmi.s loc_38B78 cmpi.b #$14,objoff_2B(a0) bne.s + bsr.w loc_38C22 + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38B78: subq.b #2,routine(a0) move.b #$40,objoff_2B(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object A6 - Spiny (on wall) from CPZ ; ---------------------------------------------------------------------------- ; Sprite_38B86: ObjA6: moveq #0,d0 move.b routine(a0),d0 move.w ObjA6_Index(pc,d0.w),d1 jmp ObjA6_Index(pc,d1.w) ; =========================================================================== ; off_38B94: ObjA6_Index: offsetTable offsetTableEntry.w ObjA6_Init ; 0 offsetTableEntry.w loc_38BAC ; 2 offsetTableEntry.w loc_38BFE ; 4 ; =========================================================================== ; loc_38B9A: ObjA6_Init: bsr.w LoadSubObject move.w #-$40,y_vel(a0) move.w #$80,objoff_2A(a0) rts ; =========================================================================== loc_38BAC: tst.b objoff_2B(a0) beq.s loc_38BBA subq.b #1,objoff_2B(a0) bra.w loc_38BC8 ; =========================================================================== loc_38BBA: bsr.w Obj_GetOrientationToPlayer addi.w #$60,d2 cmpi.w #$C0,d2 blo.s loc_38BEA loc_38BC8: subq.b #1,objoff_2A(a0) bne.s + move.w #$80,objoff_2A(a0) neg.w y_vel(a0) + jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (Ani_objA6).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38BEA: addq.b #2,routine(a0) move.b #$28,objoff_2B(a0) move.b #5,mapping_frame(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38BFE: subq.b #1,objoff_2B(a0) bmi.s loc_38C14 cmpi.b #$14,objoff_2B(a0) bne.s + bsr.w loc_38C6E + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38C14: subq.b #2,routine(a0) move.b #$40,objoff_2B(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_38C22: jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s ++ ; rts _move.b #ObjID_Projectile,id(a1) ; load obj98 move.b #6,mapping_frame(a1) move.b #$34,subtype(a1) ; <== ObjA6_SubObjData move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w #-$300,y_vel(a1) move.w #$100,d1 lea (MainCharacter).w,a2 ; a2=character move.w x_pos(a0),d0 cmp.w x_pos(a2),d0 blo.s + neg.w d1 + move.w d1,x_vel(a1) lea_ Obj98_SpinyShotFall,a2 move.l a2,objoff_2A(a1) + rts ; =========================================================================== loc_38C6E: jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s ++ ; rts _move.b #ObjID_Projectile,id(a1) ; load obj98 move.b #6,mapping_frame(a1) move.b #$34,subtype(a1) ; <== ObjA6_SubObjData move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w #$300,d1 btst #0,render_flags(a0) beq.s + neg.w d1 + move.w d1,x_vel(a1) lea_ Obj98_SpinyShotFall,a2 move.l a2,objoff_2A(a1) + rts ; =========================================================================== ; off_38CAE: ObjA5_SubObjData: subObjData ObjA5_ObjA6_Obj98_MapUnc_38CCA,make_art_tile(ArtTile_ArtNem_Spiny,1,0),4,4,8,$B ; animation scripts ; off_38CB8 Ani_objA5: offsetTable offsetTableEntry.w + ; 0 + dc.b 9, 0, 1,$FF even ; off_38CBE Ani_objA6: offsetTable offsetTableEntry.w + ; 0 + dc.b 9, 3, 4,$FF even ; off_38CC4 Ani_SpinyShot: offsetTable offsetTableEntry.w + ; 0 + dc.b 3, 6, 7,$FF even ; ------------------------------------------------------------------------------ ; sprite mappings ; ------------------------------------------------------------------------------ ObjA5_ObjA6_Obj98_MapUnc_38CCA: BINCLUDE "mappings/sprite/objA6.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object A7 - Grabber (spider badnik) from CPZ ; ---------------------------------------------------------------------------- ; Sprite_38DBA: ObjA7: moveq #0,d0 move.b routine(a0),d0 move.w ObjA7_Index(pc,d0.w),d1 jmp ObjA7_Index(pc,d1.w) ; =========================================================================== ; off_38DC8: ObjA7_Index: offsetTable offsetTableEntry.w ObjA7_Init ; 0 offsetTableEntry.w ObjA7_Main ; 2 ; =========================================================================== ; loc_38DCC: ObjA7_Init: bsr.w LoadSubObject move.w #-$40,d0 btst #0,render_flags(a0) beq.s + neg.w d0 + move.w d0,x_vel(a0) move.w #$FF,objoff_2A(a0) move.b #2,objoff_2D(a0) lea (word_391E0).l,a2 bsr.w LoadChildObject lea (word_391E4).l,a2 bsr.w LoadChildObject lea (word_391E8).l,a2 bra.w LoadChildObject ; =========================================================================== ; loc_38E0C: ObjA7_Main: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_38E46(pc,d0.w),d1 jsr off_38E46(pc,d1.w) jsrto (ObjectMove).l, JmpTo26_ObjectMove moveq #0,d0 moveq #$10,d1 movea.w objoff_3C(a0),a1 ; a1=object bsr.w Obj_AlignChildXY movea.w parent(a0),a1 ; a1=object move.w x_pos(a0),x_pos(a1) movea.w objoff_3A(a0),a1 ; a1=object move.w x_pos(a0),x_pos(a1) lea objoff_3A(a0),a2 ; a2=object bra.w loc_39182 ; =========================================================================== off_38E46: offsetTable offsetTableEntry.w loc_38E52 ; 0 offsetTableEntry.w loc_38E9A ; 2 offsetTableEntry.w loc_38EB4 ; 4 offsetTableEntry.w loc_38F3E ; 6 offsetTableEntry.w loc_38F58 ; 8 offsetTableEntry.w BranchTo_ObjA7_CheckExplode ; $A ; =========================================================================== loc_38E52: bsr.w Obj_GetOrientationToPlayer addi.w #$40,d2 cmpi.w #$80,d2 bhs.s loc_38E66 cmpi.w #-$80,d3 bhi.s loc_38E84 loc_38E66: subq.w #1,objoff_2A(a0) bpl.s return_38E82 move.w #$FF,objoff_2A(a0) neg.w x_vel(a0) bchg #0,render_flags(a0) bchg #0,status(a0) return_38E82: rts ; =========================================================================== loc_38E84: addq.b #2,routine_secondary(a0) move.w x_vel(a0),objoff_2E(a0) clr.w x_vel(a0) move.b #$10,objoff_2C(a0) rts ; =========================================================================== loc_38E9A: subq.b #1,objoff_2C(a0) bmi.s loc_38EA2 rts ; =========================================================================== loc_38EA2: addq.b #2,routine_secondary(a0) move.w #$200,y_vel(a0) move.b #$40,objoff_2C(a0) rts ; =========================================================================== loc_38EB4: tst.b objoff_30(a0) bne.s ObjA7_GrabCharacter subq.b #1,objoff_2C(a0) beq.s loc_38ED6 cmpi.b #$20,objoff_2C(a0) bne.s loc_38ECC neg.w y_vel(a0) loc_38ECC: lea (Ani_objA7).l,a1 jmpto (AnimateSprite).l, JmpTo25_AnimateSprite ; =========================================================================== loc_38ED6: move.b #0,routine_secondary(a0) clr.w y_vel(a0) move.w objoff_2E(a0),x_vel(a0) move.b #0,mapping_frame(a0) rts ; =========================================================================== ;loc_38EEE: ObjA7_GrabCharacter: addq.b #2,routine_secondary(a0) movea.w objoff_32(a0),a1 move.b #$81,obj_control(a1) clr.w x_vel(a1) clr.w y_vel(a1) move.b #AniIDSonAni_Float,anim(a1) move.b #1,mapping_frame(a0) tst.w y_vel(a0) bmi.s loc_38F2A neg.w y_vel(a0) move.b objoff_2C(a0),d0 subi.b #$40,d0 neg.w d0 addq.b #1,d0 move.b d0,objoff_2C(a0) loc_38F2A: move.b #1,objoff_2A(a0) move.b #$10,objoff_2B(a0) move.b #$20,objoff_37(a0) rts ; =========================================================================== loc_38F3E: bsr.w ObjA7_CheckExplode bsr.w loc_390BC subq.b #1,objoff_2C(a0) beq.s loc_38F4E rts ; =========================================================================== loc_38F4E: addq.b #2,routine_secondary(a0) clr.w y_vel(a0) rts ; =========================================================================== loc_38F58: bsr.w ObjA7_CheckExplode bra.w loc_390BC ; =========================================================================== rts ; =========================================================================== BranchTo_ObjA7_CheckExplode bra.w ObjA7_CheckExplode ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object A8 - Grabber's legs from CPZ ; ---------------------------------------------------------------------------- ; Sprite_38F66: ObjA8: moveq #0,d0 move.b routine(a0),d0 move.w ObjA8_Index(pc,d0.w),d1 jmp ObjA8_Index(pc,d1.w) ; =========================================================================== ; off_38F74: ObjA8_Index: offsetTable offsetTableEntry.w ObjA8_Init ; 0 offsetTableEntry.w loc_38F88 ; 2 offsetTableEntry.w loc_38FE8 ; 4 offsetTableEntry.w loc_39022 ; 6 ; =========================================================================== ; loc_38F7C: ObjA8_Init: bsr.w LoadSubObject move.b #3,mapping_frame(a0) rts ; =========================================================================== loc_38F88: movea.w objoff_2C(a0),a1 ; a1=object cmpi.b #ObjID_Grabber,id(a1) bne.w JmpTo65_DeleteObject bsr.w loc_367AA movea.w objoff_2C(a0),a1 ; a1=object move.b mapping_frame(a1),d0 addq.b #3,d0 move.b d0,mapping_frame(a0) move.b collision_property(a0),d0 beq.s BranchTo2_JmpTo45_DisplaySprite clr.b collision_property(a0) cmpi.b #4,routine_secondary(a1) bne.s BranchTo2_JmpTo45_DisplaySprite andi.b #3,d0 beq.s BranchTo2_JmpTo45_DisplaySprite clr.b collision_flags(a0) addq.b #2,routine(a0) add.w d0,d0 st objoff_30(a1) move.w word_38FE0-6(pc,d0.w),objoff_32(a1) move.w word_38FE0(pc,d0.w),objoff_34(a1) BranchTo2_JmpTo45_DisplaySprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== dc.w MainCharacter ; -2 dc.w Sidekick ; -1 word_38FE0: dc.w MainCharacter ; 0 dc.w Ctrl_1_Held ; 1 dc.w Ctrl_2_Held ; 2 dc.w Ctrl_1_Held ; 3 ; =========================================================================== loc_38FE8: movea.w objoff_2C(a0),a1 ; a1=object move.w objoff_32(a1),d0 beq.s loc_3901A movea.w d0,a2 ; a2=object cmpi.b #ObjID_Grabber,id(a1) bne.s loc_3900A move.w x_pos(a0),x_pos(a2) move.w y_pos(a0),y_pos(a2) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3900A: move.b #0,obj_control(a2) bset #1,status(a2) bra.w JmpTo65_DeleteObject ; =========================================================================== loc_3901A: addq.b #2,routine(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_39022: movea.w objoff_2C(a0),a1 ; a1=object cmpi.b #ObjID_Grabber,id(a1) ; compare to objA7 bne.w JmpTo65_DeleteObject jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object A9 - The little hanger box thing a Grabber's string comes out of ; ---------------------------------------------------------------------------- ; Sprite_39032: ObjA9: moveq #0,d0 move.b routine(a0),d0 move.w ObjA9_Index(pc,d0.w),d1 jmp ObjA9_Index(pc,d1.w) ; =========================================================================== ; off_39040: ObjA9_Index: offsetTable offsetTableEntry.w ObjA9_Init ; 0 offsetTableEntry.w ObjA9_Main ; 2 ; =========================================================================== ; loc_39044: ObjA9_Init: bsr.w LoadSubObject move.b #2,mapping_frame(a0) subi.w #$C,y_pos(a0) rts ; =========================================================================== ; loc_39056: ObjA9_Main: movea.w objoff_2C(a0),a1 ; a1=object cmpi.b #ObjID_Grabber,id(a1) ; compare to objA7 (grabber badnik) bne.w JmpTo65_DeleteObject jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object AA - The thin white string a Grabber hangs from ; ---------------------------------------------------------------------------- ; Sprite_39066: ObjAA: moveq #0,d0 move.b routine(a0),d0 move.w ObjAA_Index(pc,d0.w),d1 jmp ObjAA_Index(pc,d1.w) ; =========================================================================== ; off_39074: ObjAA_Index: offsetTable offsetTableEntry.w ObjAA_Init ; 0 offsetTableEntry.w ObjAA_Main ; 2 ; =========================================================================== ; loc_39078: ObjAA_Init: bsr.w LoadSubObject subq.w #8,y_pos(a0) rts ; =========================================================================== ; loc_39082: ObjAA_Main: movea.w objoff_2C(a0),a1 ; a1=object cmpi.b #ObjID_Grabber,id(a1) ; compare to objA7 (grabber badnik) bne.w JmpTo65_DeleteObject move.w y_pos(a1),d0 sub.w y_pos(a0),d0 bmi.s + lsr.w #4,d0 move.b d0,mapping_frame(a0) + jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object AB - Removed object (unknown, unused) ; ---------------------------------------------------------------------------- ; Sprite_390A2: ObjAB: moveq #0,d0 move.b routine(a0),d0 move.w ObjAB_Index(pc,d0.w),d1 jmp ObjAB_Index(pc,d1.w) ; =========================================================================== ; off_390B0: ObjAB_Index: offsetTable offsetTableEntry.w ObjAB_Init offsetTableEntry.w ObjAB_Main ; =========================================================================== ; BranchTo4_LoadSubObject ObjAB_Init: bra.w LoadSubObject ; =========================================================================== ; BranchTo10_JmpTo39_MarkObjGone ObjAB_Main: jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; END OF OBJECT AB ; --------------------------------------------------------------------------- ; Some subroutine for the Grabber badnik ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| loc_390BC: movea.w objoff_34(a0),a1 ; a1=object move.w (a1),d0 tst.b objoff_31(a0) beq.s loc_390E6 subq.b #1,objoff_37(a0) beq.s loc_390FA move.b objoff_36(a0),d1 andi.b #$C,d0 beq.s return_390E4 cmp.b d1,d0 beq.s return_390E4 move.b d0,objoff_36(a0) addq.b #1,objoff_38(a0) return_390E4: rts ; --------------------------------------------------------------------------- loc_390E6: andi.b #$C,d0 beq.s return_390E4 nop st objoff_31(a0) move.b d0,objoff_36(a0) nop rts ; --------------------------------------------------------------------------- loc_390FA: cmpi.b #4,objoff_38(a0) blo.s + move.b #$A,routine_secondary(a0) clr.w y_vel(a0) clr.b collision_flags(a0) movea.w objoff_32(a0),a2 ; a2=object move.b #0,obj_control(a2) bset #1,status(a2) move.b #AniIDSonAni_Walk,anim(a2) clr.w objoff_32(a0) + move.b #$20,objoff_37(a0) clr.b objoff_31(a0) clr.b objoff_38(a0) rts ; End of subroutine loc_390BC ; --------------------------------------------------------------------------- ; Grabber death check subroutine ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_3913A: ObjA7_CheckExplode: subq.b #1,objoff_2A(a0) bne.s + move.b objoff_2B(a0),objoff_2A(a0) subq.b #1,objoff_2B(a0) beq.s ObjA7_Poof bchg #palette_bit_0,art_tile(a0) + rts ; --------------------------------------------------------------------------- ; loc_39154: ObjA7_Poof: _move.b #ObjID_Explosion,id(a0) ; load 0bj27 (transform into explosion) move.b #2,routine(a0) bset #palette_bit_0,art_tile(a0) move.w objoff_32(a0),d0 beq.s + movea.w d0,a2 ; a2=object move.b #0,objoff_2A(a2) bset #1,status(a2) move.b #$B,collision_flags(a0) + rts ; End of subroutine ObjA7_CheckExplode ; =========================================================================== ; --------------------------------------------------------------------------- ; Yet another subroutine for the Grabber badnik ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| loc_39182: tst.w (Two_player_mode).w beq.s + jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; --------------------------------------------------------------------------- + move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse).w,d0 cmpi.w #$280,d0 bhi.w + jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; --------------------------------------------------------------------------- + lea (Object_Respawn_Table).w,a3 moveq #0,d0 move.b respawn_index(a0),d0 beq.s + bclr #7,2(a3,d0.w) + tst.b objoff_30(a0) beq.s + movea.w objoff_32(a0),a3 move.b #0,$2A(a3) bset #1,$22(a3) + moveq #0,d6 move.b objoff_2D(a0),d6 - movea.w (a2)+,a1 jsrto (DeleteObject2).l, JmpTo6_DeleteObject2 dbf d6,- bra.w JmpTo65_DeleteObject ; End of subroutine loc_39182 ; =========================================================================== word_391E0: dc.w objoff_3E dc.b ObjID_GrabberBox dc.b $3A word_391E4: dc.w objoff_3C dc.b ObjID_GrabberLegs dc.b $38 word_391E8: dc.w objoff_3A dc.b ObjID_GrabberString dc.b $3C ; off_391EC: ObjA7_SubObjData: subObjData ObjA7_ObjA8_ObjA9_Obj98_MapUnc_3921A,make_art_tile(ArtTile_ArtNem_Grabber,1,1),4,4,$10,$B ; off_391F6: ObjA7_SubObjData2: subObjData ObjA7_ObjA8_ObjA9_Obj98_MapUnc_3921A,make_art_tile(ArtTile_ArtNem_Grabber,1,1),4,1,$10,$D7 ; off_39200: ObjA8_SubObjData: subObjData ObjA7_ObjA8_ObjA9_Obj98_MapUnc_3921A,make_art_tile(ArtTile_ArtNem_Grabber,1,1),4,4,4,0 ; off_3920A: ObjA8_SubObjData2: subObjData ObjAA_MapUnc_39228,make_art_tile(ArtTile_ArtNem_Grabber,1,1),4,5,4,0 ; animation script ; off_39214: Ani_objA7: offsetTable offsetTableEntry.w byte_39216 ; 0 byte_39216: dc.b 7, 0, 1,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings - objA7,objA8,objA9 ; ---------------------------------------------------------------------------- ObjA7_ObjA8_ObjA9_Obj98_MapUnc_3921A: offsetTable offsetTableEntry.w word_3923A ; 0 offsetTableEntry.w word_39254 ; 1 offsetTableEntry.w word_3926E ; 2 offsetTableEntry.w word_39278 ; 3 offsetTableEntry.w word_39282 ; 4 offsetTableEntry.w word_3928C ; 5 offsetTableEntry.w word_39296 ; 6 ; ------------------------------------------------------------------------------- ; sprite mappings - objAA (string of various lengths) ; ------------------------------------------------------------------------------- ObjAA_MapUnc_39228: offsetTable offsetTableEntry.w word_392A0 ; 0 offsetTableEntry.w word_392AA ; 1 offsetTableEntry.w word_392B4 ; 2 offsetTableEntry.w word_392C6 ; 3 offsetTableEntry.w word_392D8 ; 4 ; Unused - The spider badnik never goes down enough for these to appear offsetTableEntry.w word_3930C ; 5 ; This is in the wrong place - this should be frame 6 offsetTableEntry.w word_392F2 ; 6 ; This is in the wrong place - this should be frame 5 offsetTableEntry.w word_3932E ; 7 offsetTableEntry.w word_3932E ; 8 ; This should point to word_39350 word_3923A: dc.w 3 dc.w $F801, 0, 0,$FFE5 dc.w $F80D, 2, 1,$FFED; 4 dc.w $809, $1D, $E,$FFF1; 8 word_39254: dc.w 3 dc.w $F801, 0, 0,$FFE5 dc.w $F80D, 2, 1,$FFED; 4 dc.w $80D, $23, $11,$FFF1; 8 word_3926E: dc.w 1 dc.w $FC00, $A, 5,$FFFC word_39278: dc.w 1 dc.w $F809, $F, 7,$FFF9 word_39282: dc.w 1 dc.w $F80D, $15, $A,$FFF9 word_3928C: dc.w 1 dc.w $FC00, $2B, $15,$FFFC word_39296: dc.w 1 dc.w $FC00, $2C, $16,$FFFC word_392A0: dc.w 1 dc.w 1, $B, 5,$FFFC word_392AA: dc.w 1 dc.w 3, $B, 5,$FFFC word_392B4: dc.w 2 dc.w 1, $B, 5,$FFFC dc.w $1003, $B, 5,$FFFC; 4 word_392C6: dc.w 2 dc.w 3, $B, 5,$FFFC dc.w $2003, $B, 5,$FFFC; 4 word_392D8: dc.w 3 dc.w 1, $B, 5,$FFFC dc.w $1003, $B, 5,$FFFC; 4 dc.w $3003, $B, 5,$FFFC; 8 word_392F2: dc.w 3 dc.w 3, $B, 5,$FFFC dc.w $2003, $B, 5,$FFFC; 4 dc.w $4003, $B, 5,$FFFC; 8 word_3930C: dc.w 4 dc.w 1, $B, 5,$FFFC dc.w $1003, $B, 5,$FFFC; 4 dc.w $3003, $B, 5,$FFFC; 8 dc.w $5003, $B, 5,$FFFC; 12 word_3932E: dc.w 4 dc.w 3, $B, 5,$FFFC dc.w $2003, $B, 5,$FFFC; 4 dc.w $4003, $B, 5,$FFFC; 8 dc.w $6003, $B, 5,$FFFC; 12 ; Unused frame ;word_39350: dc.w 5 dc.w 1, $B, 5,$FFFC dc.w $1003, $B, 5,$FFFC; 4 dc.w $3003, $B, 5,$FFFC; 8 dc.w $5003, $B, 5,$FFFC; 12 dc.w $7003, $B, 5,$FFFC; 16 ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object AC - Balkiry (jet badnik) from SCZ ; ---------------------------------------------------------------------------- ; Sprite_3937A: ObjAC: moveq #0,d0 move.b routine(a0),d0 move.w ObjAC_Index(pc,d0.w),d1 jmp ObjAC_Index(pc,d1.w) ; =========================================================================== ; off_39388: ObjAC_Index: offsetTable offsetTableEntry.w ObjAC_Init ; 0 offsetTableEntry.w ObjAC_Main ; 2 ; =========================================================================== ; loc_3938C: ObjAC_Init: bsr.w LoadSubObject move.b #1,mapping_frame(a0) move.w #-$300,x_vel(a0) bclr #1,render_flags(a0) beq.s + move.w #-$500,x_vel(a0) + lea_ Ani_obj9C,a1 move.l a1,objoff_2E(a0) bra.w loc_37ABE ; =========================================================================== ; loc_393B6: ObjAC_Main: jsrto (ObjectMove).l, JmpTo26_ObjectMove bsr.w loc_36776 bra.w Obj_DeleteBehindScreen ; =========================================================================== ; off_393C2: ObjAC_SubObjData: subObjData ObjAC_MapUnc_393CC,make_art_tile(ArtTile_ArtNem_Balkrie,0,0),4,4,$20,8 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjAC_MapUnc_393CC: BINCLUDE "mappings/sprite/objAC.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object AD - Clucker's base from WFZ ; ---------------------------------------------------------------------------- ; Sprite_3941C: ObjAD: moveq #0,d0 move.b routine(a0),d0 move.w ObjAD_Index(pc,d0.w),d1 jmp ObjAD_Index(pc,d1.w) ; =========================================================================== ; off_3942A: ObjAD_Index: offsetTable offsetTableEntry.w ObjAD_Init ; 0 offsetTableEntry.w ObjAD_Main ; 2 ; =========================================================================== ; loc_3942E: ObjAD_Init: bsr.w LoadSubObject move.b #$C,mapping_frame(a0) rts ; =========================================================================== ; loc_3943A: ObjAD_Main: move.w #$1B,d1 move.w #8,d2 move.w #8,d3 move.w x_pos(a0),d4 jsrto (SolidObject).l, JmpTo27_SolidObject jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object AE - Clucker (chicken badnik) from WFZ ; ---------------------------------------------------------------------------- ; Sprite_39452: ObjAE: moveq #0,d0 move.b routine(a0),d0 move.w ObjAE_Index(pc,d0.w),d1 jmp ObjAE_Index(pc,d1.w) ; =========================================================================== ; off_39460: ObjAE_Index: offsetTable offsetTableEntry.w ObjAE_Init ; 0 offsetTableEntry.w loc_39488 ; 2 offsetTableEntry.w loc_394A2 ; 4 offsetTableEntry.w loc_394D2 ; 6 offsetTableEntry.w loc_394E0 ; 8 offsetTableEntry.w loc_39508 ; $A offsetTableEntry.w loc_39516 ; $C ; =========================================================================== ; loc_3946E: ObjAE_Init: bsr.w LoadSubObject move.b #$15,mapping_frame(a0) btst #0,render_flags(a0) beq.s + bset #0,status(a0) + rts ; =========================================================================== loc_39488: bsr.w Obj_GetOrientationToPlayer addi.w #$80,d2 cmpi.w #$100,d2 blo.s + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== + addq.b #2,routine(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_394A2: move.b routine(a0),d2 lea (Ani_objAE_a).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite cmp.b routine(a0),d2 bne.s + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== + lea mapping_frame(a0),a1 clr.l (a1) clr.w anim_frame_duration-mapping_frame(a1) move.b #8,(a1) move.b #6,collision_flags(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_394D2: lea (Ani_objAE_b).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_394E0: tst.b objoff_2A(a0) beq.s + subq.b #1,objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== + addq.b #2,routine(a0) lea mapping_frame(a0),a1 clr.l (a1) clr.w anim_frame_duration-mapping_frame(a1) move.b #$B,(a1) bsr.w loc_39526 jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_39508: lea (Ani_objAE_c).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_39516: move.b #8,routine(a0) move.b #$40,objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_39526: jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s ++ ; rts _move.b #ObjID_Projectile,id(a1) ; load obj98 move.b #$D,mapping_frame(a1) move.b #$46,subtype(a1) ; <== ObjAD_SubObjData3 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$B,y_pos(a1) move.w #-$200,d0 move.w #-8,d1 btst #0,render_flags(a0) beq.s + neg.w d0 neg.w d1 + move.w d0,x_vel(a1) add.w d1,x_pos(a1) lea_ Obj98_CluckerShotMove,a2 move.l a2,objoff_2A(a1) + rts ; =========================================================================== ObjAD_SubObjData: subObjData ObjAD_Obj98_MapUnc_395B4,make_art_tile(ArtTile_ArtNem_WfzScratch,0,0),4,4,$18,0 ObjAD_SubObjData2: subObjData ObjAD_Obj98_MapUnc_395B4,make_art_tile(ArtTile_ArtNem_WfzScratch,0,0),4,5,$10,0 ; animation script ; off_3958A Ani_objAE_a: offsetTable offsetTableEntry.w + ; 0 + dc.b 1, 0, 1, 2, 3, 4, 5, 6, 7,$FC even ; animation script ; off_39596 Ani_objAE_b: offsetTable offsetTableEntry.w + ; 0 + dc.b 1, 8, 9, $A, $B, $B, $B, $B,$FC even ; animation script ; off_395A2 Ani_objAE_c: offsetTable offsetTableEntry.w + ; 0 + dc.b 3, $A, $B,$FC even ; animation script ; off_395A8 Ani_CluckerShot:offsetTable offsetTableEntry.w + ; 0 + dc.b 3, $D, $E, $F,$10,$11,$12,$13,$14,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjAD_Obj98_MapUnc_395B4: BINCLUDE "mappings/sprite/objAE.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object AF - Mecha Sonic / Silver Sonic from DEZ ; (also handles Eggman's remote-control window) ; ---------------------------------------------------------------------------- ; Sprite_3972C: ObjAF: moveq #0,d0 move.b routine(a0),d0 move.w ObjAF_Index(pc,d0.w),d1 jmp ObjAF_Index(pc,d1.w) ; =========================================================================== ; off_3973A: ObjAF_Index: offsetTable offsetTableEntry.w ObjAF_Init ; 0 offsetTableEntry.w loc_397AC ; 2 offsetTableEntry.w loc_397E6 ; 4 offsetTableEntry.w loc_397FE ; 6 offsetTableEntry.w loc_3984A ; 8 offsetTableEntry.w loc_398C0 ; $A offsetTableEntry.w loc_39B92 ; $C offsetTableEntry.w loc_39BBA ; $E offsetTableEntry.w loc_39BCC ; $10 offsetTableEntry.w loc_39BE2 ; $12 offsetTableEntry.w loc_39BEA ; $14 offsetTableEntry.w loc_39C02 ; $16 offsetTableEntry.w loc_39C0A ; $18 offsetTableEntry.w loc_39C12 ; $1A offsetTableEntry.w loc_39C2A ; $1C offsetTableEntry.w loc_39C42 ; $1E offsetTableEntry.w loc_39C50 ; $20 offsetTableEntry.w loc_39CA0 ; $22 ; =========================================================================== ; loc_3975E: ObjAF_Init: bsr.w LoadSubObject move.b #$1B,y_radius(a0) move.b #$10,x_radius(a0) move.b #0,collision_flags(a0) move.b #8,collision_property(a0) lea (word_39DC2).l,a2 bsr.w LoadChildObject move.b #$E,routine(a1) lea (word_39DC6).l,a2 bsr.w LoadChildObject move.b #$14,routine(a1) lea (word_39DCA).l,a2 bsr.w LoadChildObject move.b #$1A,routine(a1) rts ; =========================================================================== loc_397AC: move.w (Camera_X_pos).w,d0 cmpi.w #$224,d0 bhs.s loc_397BA jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_397BA: addq.b #2,routine(a0) move.w #$3C,objoff_2A(a0) move.w #$100,y_vel(a0) move.w #$224,d0 move.w d0,(Camera_Min_X_pos).w move.w d0,(Camera_Max_X_pos).w move.b #9,(Current_Boss_ID).w moveq #MusID_FadeOut,d0 jsrto (PlaySound).l, JmpTo12_PlaySound jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_397E6: subq.w #1,objoff_2A(a0) bmi.s loc_397F0 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_397F0: addq.b #2,routine(a0) moveq #MusID_Boss,d0 jsrto (PlayMusic).l, JmpTo5_PlayMusic jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_397FE: move.b (Vint_runcount+3).w,d0 andi.b #$1F,d0 bne.s loc_3980E moveq #SndID_Fire,d0 jsrto (PlaySound).l, JmpTo12_PlaySound loc_3980E: jsr (ObjCheckFloorDist).l tst.w d1 bmi.s loc_39830 jsrto (ObjectMove).l, JmpTo26_ObjectMove moveq #0,d0 moveq #0,d1 movea.w parent(a0),a1 ; a1=object bsr.w Obj_AlignChildXY bsr.w loc_39D4A jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_39830: add.w d1,y_pos(a0) move.w #0,y_vel(a0) move.b #$1A,collision_flags(a0) bset #1,status(a0) bra.w loc_399D6 ; =========================================================================== loc_3984A: bsr.w loc_39CAE bsr.w loc_39D1C subq.b #1,objoff_2A(a0) beq.s loc_39886 cmpi.b #$32,objoff_2A(a0) bne.s loc_3986A moveq #SndID_MechaSonicBuzz,d0 jsrto (PlaySound).l, JmpTo12_PlaySound jsrto (DisplaySprite).l, JmpTo45_DisplaySprite loc_3986A: jsr (ObjCheckFloorDist).l add.w d1,y_pos(a0) lea (off_39DE2).l,a1 bsr.w AnimateSprite_Checked bsr.w loc_39D4A jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_39886: addq.b #2,routine(a0) moveq #0,d0 move.b objoff_2F(a0),d0 andi.b #$F,d0 move.b byte_398B0(pc,d0.w),routine_secondary(a0) addq.b #1,objoff_2F(a0) clr.b objoff_2E(a0) movea.w objoff_3C(a0),a1 ; a1=object move.b #$16,routine(a1) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== byte_398B0: dc.b 6 dc.b 0 ; 1 dc.b $10 ; 2 dc.b 6 ; 3 dc.b 6 ; 4 dc.b $1E ; 5 dc.b 0 ; 6 dc.b $10 ; 7 dc.b 6 ; 8 dc.b 6 ; 9 dc.b $10 ; 10 dc.b 6 ; 11 dc.b 0 ; 12 dc.b 6 ; 13 dc.b $10 ; 14 dc.b $1E ; 15 ; =========================================================================== loc_398C0: bsr.w loc_39CAE bsr.w loc_39D1C moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_398F2(pc,d0.w),d1 jsr off_398F2(pc,d1.w) moveq #0,d0 moveq #0,d1 movea.w parent(a0),a1 ; a1=object bsr.w Obj_AlignChildXY bsr.w loc_39D4A bsr.w Obj_AlignChildXY jsrto (ObjectMove).l, JmpTo26_ObjectMove jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== off_398F2: offsetTable offsetTableEntry.w loc_3991E ; 0 offsetTableEntry.w loc_39946 ; 2 offsetTableEntry.w loc_39976 ; 4 offsetTableEntry.w loc_39A0A ; 6 offsetTableEntry.w loc_39A1C ; 8 offsetTableEntry.w loc_39A44 ; $A offsetTableEntry.w loc_39A68 ; $C offsetTableEntry.w loc_39A96 ; $E offsetTableEntry.w loc_39A0A ; $10 offsetTableEntry.w loc_39A1C ; $12 offsetTableEntry.w loc_39AAA ; $14 offsetTableEntry.w loc_39ACE ; $16 offsetTableEntry.w loc_39AF4 ; $18 offsetTableEntry.w loc_39B28 ; $1A offsetTableEntry.w loc_39A96 ; $1C offsetTableEntry.w loc_39A0A ; $1E offsetTableEntry.w loc_39A1C ; $20 offsetTableEntry.w loc_39AAA ; $22 offsetTableEntry.w loc_39ACE ; $24 offsetTableEntry.w loc_39B44 ; $26 offsetTableEntry.w loc_39B28 ; $28 offsetTableEntry.w loc_39A96 ; $2A ; =========================================================================== loc_3991E: addq.b #2,routine_secondary(a0) move.b #3,mapping_frame(a0) move.b #2,objoff_2C(a0) loc_3992E: move.b #$20,objoff_2A(a0) movea.w parent(a0),a1 ; a1=object move.b #$10,routine(a1) move.b #1,anim(a1) rts ; =========================================================================== loc_39946: subq.b #1,objoff_2A(a0) bmi.s loc_3994E rts ; =========================================================================== loc_3994E: addq.b #2,routine_secondary(a0) move.b #$40,objoff_2A(a0) move.b #1,anim(a0) move.w #$800,d0 bsr.w loc_39D60 movea.w parent(a0),a1 ; a1=object move.b #2,anim(a1) moveq #SndID_SpindashRelease,d0 jmpto (PlaySound).l, JmpTo12_PlaySound ; =========================================================================== loc_39976: subq.b #1,objoff_2A(a0) bmi.s loc_399C2 cmpi.b #$20,objoff_2A(a0) bne.s loc_39994 move.b #2,anim(a0) movea.w parent(a0),a1 ; a1=object move.b #$12,routine(a1) loc_39994: bsr.w loc_39D72 lea (off_39DE2).l,a1 bsr.w AnimateSprite_Checked cmpi.b #2,anim(a0) bne.s return_399C0 cmpi.b #2,anim_frame(a0) bne.s return_399C0 cmpi.b #3,anim_frame_duration(a0) bne.s return_399C0 bchg #0,render_flags(a0) return_399C0: rts ; =========================================================================== loc_399C2: subq.b #1,objoff_2C(a0) beq.s loc_399D6 move.b #2,routine_secondary(a0) clr.w x_vel(a0) bra.w loc_3992E ; =========================================================================== loc_399D6: move.b #8,routine(a0) move.b #0,anim(a0) move.b #$64,objoff_2A(a0) clr.w x_vel(a0) movea.w parent(a0),a1 ; a1=object move.b #$12,routine(a1) movea.w objoff_3C(a0),a1 ; a1=object move.b #$18,routine(a1) moveq #SndID_MechaSonicBuzz,d0 jsrto (PlaySound).l, JmpTo12_PlaySound jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_39A0A: addq.b #2,routine_secondary(a0) move.b #3,mapping_frame(a0) move.b #3,anim(a0) rts ; =========================================================================== loc_39A1C: lea (off_39DE2).l,a1 bsr.w AnimateSprite_Checked bne.s loc_39A2A rts ; =========================================================================== loc_39A2A: addq.b #2,routine_secondary(a0) move.b #$20,objoff_2A(a0) move.b #4,anim(a0) moveq #SndID_LaserBeam,d0 jsrto (PlaySound).l, JmpTo12_PlaySound jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_39A44: subq.b #1,objoff_2A(a0) bmi.s loc_39A56 lea (off_39DE2).l,a1 bsr.w AnimateSprite_Checked rts ; =========================================================================== loc_39A56: addq.b #2,routine_secondary(a0) move.b #$40,objoff_2A(a0) move.w #$800,d0 bra.w loc_39D60 ; =========================================================================== loc_39A68: subq.b #1,objoff_2A(a0) bmi.s loc_39A7C bsr.w loc_39D72 lea (off_39DE2).l,a1 bra.w AnimateSprite_Checked ; =========================================================================== loc_39A7C: addq.b #2,routine_secondary(a0) move.b #5,anim(a0) bchg #0,render_flags(a0) clr.w x_vel(a0) clr.w y_vel(a0) rts ; =========================================================================== loc_39A96: lea (off_39DE2).l,a1 bsr.w AnimateSprite_Checked bne.w BranchTo_loc_399D6 rts ; =========================================================================== BranchTo_loc_399D6 bra.w loc_399D6 ; =========================================================================== loc_39AAA: subq.b #1,objoff_2A(a0) bmi.s loc_39ABC lea (off_39DE2).l,a1 bsr.w AnimateSprite_Checked rts ; =========================================================================== loc_39ABC: addq.b #2,routine_secondary(a0) move.b #$40,objoff_2A(a0) move.w #$400,d0 bra.w loc_39D60 ; =========================================================================== loc_39ACE: subq.b #1,objoff_2A(a0) cmpi.b #$3C,objoff_2A(a0) bne.s loc_39ADE bsr.w loc_39AE8 loc_39ADE: lea (off_39DE2).l,a1 bra.w AnimateSprite_Checked ; =========================================================================== loc_39AE8: addq.b #2,routine_secondary(a0) move.w #-$600,y_vel(a0) rts ; =========================================================================== loc_39AF4: subq.b #1,objoff_2A(a0) bmi.w loc_39A7C jsr (ObjCheckFloorDist).l tst.w d1 bpl.s loc_39B0A bsr.w loc_39B1A loc_39B0A: addi.w #$38,y_vel(a0) lea (off_39DE2).l,a1 bra.w AnimateSprite_Checked ; =========================================================================== loc_39B1A: addq.b #2,routine_secondary(a0) add.w d1,y_pos(a0) clr.w y_vel(a0) rts ; =========================================================================== loc_39B28: subq.b #1,objoff_2A(a0) bmi.w loc_39A7C jsr (ObjCheckFloorDist).l add.w d1,y_pos(a0) lea (off_39DE2).l,a1 bra.w AnimateSprite_Checked ; =========================================================================== loc_39B44: subq.b #1,objoff_2A(a0) bmi.w loc_39A7C tst.b objoff_2E(a0) bne.s loc_39B66 tst.w y_vel(a0) bmi.s loc_39B66 st objoff_2E(a0) bsr.w loc_39D82 moveq #SndID_SpikeSwitch,d0 jsrto (PlaySound).l, JmpTo12_PlaySound loc_39B66: jsr (ObjCheckFloorDist).l tst.w d1 bpl.s loc_39B74 bsr.w loc_39B84 loc_39B74: addi.w #$38,y_vel(a0) lea (off_39DE2).l,a1 bra.w AnimateSprite_Checked ; =========================================================================== loc_39B84: addq.b #2,routine_secondary(a0) add.w d1,y_pos(a0) clr.w y_vel(a0) rts ; =========================================================================== loc_39B92: clr.b collision_flags(a0) subq.w #1,objoff_32(a0) bmi.s loc_39BA4 jsrto (Boss_LoadExplosion).l, JmpTo_Boss_LoadExplosion jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_39BA4: move.w #$1000,(Camera_Max_X_pos).w addq.b #2,(Dynamic_Resize_Routine).w move.b (Level_Music).w,d0 jsrto (PlayMusic).l, JmpTo5_PlayMusic bra.w JmpTo65_DeleteObject ; =========================================================================== loc_39BBA: bsr.w LoadSubObject move.b #8,width_pixels(a0) move.b #0,collision_flags(a0) rts ; =========================================================================== loc_39BCC: movea.w objoff_2C(a0),a1 ; a1=object bsr.w loc_367AA lea (off_39E30).l,a1 bsr.w AnimateSprite_Checked jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_39BE2: andi.b #$7F,render_flags(a0) rts ; =========================================================================== loc_39BEA: bsr.w LoadSubObject move.b #8,width_pixels(a0) move.b #$B,mapping_frame(a0) move.b #3,priority(a0) rts ; =========================================================================== loc_39C02: move.b #0,collision_flags(a0) rts ; =========================================================================== loc_39C0A: move.b #$98,collision_flags(a0) rts ; =========================================================================== loc_39C12: bsr.w LoadSubObject move.b #4,mapping_frame(a0) move.w #$2C0,x_pos(a0) move.w #$139,y_pos(a0) rts ; =========================================================================== loc_39C2A: movea.w objoff_2C(a0),a1 ; a1=object bclr #1,status(a1) bne.s loc_39C3A jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_39C3A: addq.b #2,routine(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_39C42: lea (Ani_objAF_c).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_39C50: movea.w objoff_2C(a0),a1 ; a1=object lea (MainCharacter).w,a2 ; a2=character btst #2,status(a1) bne.s loc_39C92 move.b #2,anim(a0) cmpi.b #4,routine(a2) bne.s loc_39C78 move.b #3,anim(a0) bra.w loc_39C84 ; =========================================================================== loc_39C78: tst.b collision_flags(a1) bne.s loc_39C84 move.b #4,anim(a0) loc_39C84: lea (Ani_objAF_c).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_39C92: addq.b #2,routine(a0) move.b #1,anim(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_39CA0: lea (Ani_objAF_c).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_39CAE: tst.b collision_property(a0) beq.s loc_39CF0 tst.b collision_flags(a0) bne.s return_39CEE tst.b objoff_30(a0) bne.s loc_39CD0 move.b #$20,objoff_30(a0) move.w #SndID_BossHit,d0 jsr (PlaySound).l loc_39CD0: lea (Normal_palette_line2+2).w,a1 moveq #0,d0 tst.w (a1) bne.s loc_39CDE move.w #$EEE,d0 loc_39CDE: move.w d0,(a1) subq.b #1,objoff_30(a0) bne.s return_39CEE clr.w (Normal_palette_line2+2).w bsr.w loc_39D24 return_39CEE: rts ; =========================================================================== loc_39CF0: moveq #100,d0 bsr.w AddPoints move.w #$FF,objoff_32(a0) move.b #$C,routine(a0) clr.b collision_flags(a0) bset #2,status(a0) movea.w objoff_3C(a0),a1 ; a1=object jsrto (DeleteObject2).l, JmpTo6_DeleteObject2 movea.w parent(a0),a1 ; a1=object jmpto (DeleteObject2).l, JmpTo6_DeleteObject2 ; =========================================================================== loc_39D1C: tst.b collision_flags(a0) beq.w return_37A48 loc_39D24: move.b mapping_frame(a0),d0 cmpi.b #6,d0 beq.s loc_39D42 cmpi.b #7,d0 beq.s loc_39D42 cmpi.b #8,d0 beq.s loc_39D42 move.b #$1A,collision_flags(a0) rts ; =========================================================================== loc_39D42: move.b #$9A,collision_flags(a0) rts ; =========================================================================== loc_39D4A: moveq #$C,d0 moveq #-$C,d1 btst #0,render_flags(a0) beq.s loc_39D58 neg.w d0 loc_39D58: movea.w objoff_3C(a0),a1 ; a1=object bra.w Obj_AlignChildXY ; =========================================================================== loc_39D60: tst.b objoff_2D(a0) bne.s loc_39D68 neg.w d0 loc_39D68: not.b objoff_2D(a0) move.w d0,x_vel(a0) rts ; =========================================================================== loc_39D72: moveq #$20,d0 tst.w x_vel(a0) bmi.s loc_39D7C neg.w d0 loc_39D7C: add.w d0,x_vel(a0) rts ; =========================================================================== loc_39D82: move.b #$4A,d2 moveq #7,d6 lea (byte_39D92).l,a2 bra.w Obj_CreateProjectiles ; =========================================================================== byte_39D92: dc.b 0,$E8, 0,$FD, $F, 0,$F0,$F0,$FE,$FE,$10, 0,$E8, 0,$FD, 0 dc.b $11, 0,$F0,$10,$FE, 2,$12, 0, 0,$18, 0, 3,$13, 0,$10,$10; 16 dc.b 2, 2,$14, 0,$18, 0, 3, 0,$15, 0,$10,$F0, 2,$FE,$16, 0; 32 word_39DC2: dc.w objoff_3E dc.b ObjID_MechaSonic dc.b $48 word_39DC6: dc.w objoff_3C dc.b ObjID_MechaSonic dc.b $48 word_39DCA: dc.w objoff_3A dc.b ObjID_MechaSonic dc.b $A4 ; off_39DCE: ObjAF_SubObjData2: subObjData ObjAF_Obj98_MapUnc_39E68,make_art_tile(ArtTile_ArtNem_SilverSonic,1,0),4,4,$10,$1A ; off_39DD8: ObjAF_SubObjData3: subObjData ObjAF_MapUnc_3A08C,make_art_tile(ArtTile_ArtNem_DEZWindow,0,0),4,6,$10,0 ; animation script off_39DE2: offsetTable offsetTableEntry.w byte_39DEE ; 0 offsetTableEntry.w byte_39DF4 ; 1 offsetTableEntry.w byte_39DF8 ; 2 offsetTableEntry.w byte_39DFE ; 3 offsetTableEntry.w byte_39E14 ; 4 offsetTableEntry.w byte_39E1A ; 5 byte_39DEE: dc.b 2, 0, 1, 2,$FF, 0 byte_39DF4: dc.b $45, 3,$FD, 0 byte_39DF8: dc.b 3, 4, 5, 4, 3,$FC byte_39DFE: dc.b 3, 3, 3, 6, 6, 6, 7, 7, 7, 8, 8, 8, 6, 6, 7, 7 dc.b 8, 8, 6, 7, 8,$FC; 16 byte_39E14: dc.b 2, 6, 7, 8,$FF, 0 byte_39E1A: dc.b 3, 8, 7, 6, 8, 8, 7, 7, 6, 6, 8, 8, 8, 7, 7, 7 dc.b 6, 6, 6, 3, 3,$FC; 16 even ; animation script off_39E30: offsetTable offsetTableEntry.w byte_39E36 ; 0 offsetTableEntry.w byte_39E3A ; 1 offsetTableEntry.w byte_39E3E ; 2 byte_39E36: dc.b 1, $B, $C,$FF byte_39E3A: dc.b 1, $D, $E,$FF byte_39E3E: dc.b 1, 9, $A,$FF even ; animation script ; off_39E42: Ani_objAF_c: offsetTable offsetTableEntry.w byte_39E4C ; 0 offsetTableEntry.w byte_39E54 ; 1 offsetTableEntry.w byte_39E5C ; 2 offsetTableEntry.w byte_39E60 ; 3 offsetTableEntry.w byte_39E64 ; 4 byte_39E4C: dc.b 3, 4, 3, 2, 1, 0,$FC, 0 byte_39E54: dc.b 3, 0, 1, 2, 3, 4,$FA, 0 byte_39E5C: dc.b 3, 5, 5,$FF byte_39E60: dc.b 3, 5, 6,$FF byte_39E64: dc.b 3, 7, 7,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjAF_Obj98_MapUnc_39E68: BINCLUDE "mappings/sprite/objAF_a.bin" ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjAF_MapUnc_3A08C: BINCLUDE "mappings/sprite/objAF_b.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object B0 - Sonic on the Sega screen ; ---------------------------------------------------------------------------- ; Sprite_3A1DC: ObjB0: moveq #0,d0 move.b routine(a0),d0 move.w ObjB0_Index(pc,d0.w),d1 jmp ObjB0_Index(pc,d1.w) ; =========================================================================== ; off_3A1EA: ObjB0_Index: offsetTable offsetTableEntry.w ObjB0_Init ; 0 offsetTableEntry.w ObjB0_RunLeft ; 2 offsetTableEntry.w ObjB0_MidWipe ; 4 offsetTableEntry.w ObjB0_RunRight ; 6 offsetTableEntry.w ObjB0_EndWipe ; 8 offsetTableEntry.w return_3A3F6 ; $A ; =========================================================================== ObjB0_Init: bsr.w LoadSubObject move.w #$1E8,x_pixel(a0) move.w #$F0,y_pixel(a0) move.w #$B,objoff_2A(a0) move.w #2,(SegaScr_VInt_Subrout).w bset #0,render_flags(a0) bset #0,status(a0) ; Initialize streak horizontal offsets for Sonic going left. ; 9 full lines (8 pixels) + 6 pixels, 2-byte interleaved entries for PNT A and PNT B lea (Horiz_Scroll_Buf + 2 * 2 * (9 * 8 + 6)).w,a1 lea Streak_Horizontal_offsets(pc),a2 moveq #0,d0 moveq #$22,d6 ; Number of streaks-1 - move.b (a2)+,d0 add.w d0,(a1) addq.w #2 * 2 * 2,a1 ; Advance to next streak 2 pixels down dbf d6,- lea off_3A294(pc),a1 ; pointers to mapping DPLC data lea (ArtUnc_Sonic).l,a3 lea (Chunk_Table).l,a5 moveq #4-1,d5 ; there are 4 mapping frames to loop over ; this copies the tiles that we want to scale up from ROM to RAM ;loc_3A246: ;CopySpriteTilesToRAMForSegaScreen: - movea.l (a1)+,a2 move.w (a2)+,d6 ; get the number of pieces in this mapping frame subq.w #1,d6 - move.w (a2)+,d0 move.w d0,d1 ; Depending on the exact location (and size) of the art being used, ; you may encounter an overflow in the original code which garbles ; the enlarged Sonic. The following code fixes this: if 1==0 andi.l #$FFF,d0 lsl.l #5,d0 lea (a3,d0.l),a4 ; source ROM address of tiles to copy else andi.w #$FFF,d0 lsl.w #5,d0 lea (a3,d0.w),a4 ; source ROM address of tiles to copy endif andi.w #$F000,d1 ; abcd000000000000 rol.w #4,d1 ; (this calculation can be done smaller and faster addq.w #1,d1 ; by doing rol.w #7,d1 addq.w #7,d1 lsl.w #3,d1 ; instead of these 4 lines) subq.w #1,d1 ; 000000000abcd111 ; number of dwords to copy minus 1 - move.l (a4)+,(a5)+ dbf d1,- ; copy all of the pixels in this piece into the temp buffer dbf d6,-- ; loop per piece in the frame dbf d5,--- ; loop per mapping frame ; this scales up the tiles by 2 ;ScaleUpSpriteTiles: move.w d7,-(sp) moveq #0,d0 moveq #0,d1 lea SonicRunningSpriteScaleData(pc),a6 moveq #4*2-1,d7 ; there are 4 sprite mapping frames with 2 pieces each - movea.l (a6)+,a1 ; source in RAM of tile graphics to enlarge movea.l (a6)+,a2 ; destination in RAM of enlarged graphics move.b (a6)+,d0 ; width of the sprite piece to enlarge (minus 1) move.b (a6)+,d1 ; height of the sprite piece to enlarge (minus 1) bsr.w Scale_2x dbf d7,- ; loop over each piece move.w (sp)+,d7 rts ; =========================================================================== ; These next four things are pointers to Sonic's dereferenced ; DPLC entries of his "running animation" frames for the SEGA screen. ; I want that DPLC data split into a binary file for use with editors, ; but unfortunately there's no way to refer to BINCLUDE'd bytes ; from within AS, so I put an educated guess (default) here and ; run an external program (fixpointer.exe) to fix it later. ; WARNING: the build script needs editing if you rename this label off_3A294: dc.l (MapRUnc_Sonic+$33A) ;dc.l word_7181A dc.l (MapRUnc_Sonic+$340) ;dc.l word_71820 dc.l (MapRUnc_Sonic+$346) ;dc.l word_71826 dc.l (MapRUnc_Sonic+$34C) ;dc.l word_7182C map_piece macro width,height dc.l copysrc,copydst dc.b width-1,height-1 copysrc := copysrc + tiles_to_bytes(width * height) copydst := copydst + tiles_to_bytes(width * height) * 2 * 2 endm ;word_3A2A4: SonicRunningSpriteScaleData: copysrc := Chunk_Table copydst := Chunk_Table + $B00 SegaScreenScaledSpriteDataStart = copydst rept 4 ; repeat 4 times since there are 4 frames to scale up ; piece 1 of each frame (the smaller top piece): map_piece 3,2 ; piece 2 of each frame (the larger bottom piece): map_piece 4,4 endm SegaScreenScaledSpriteDataEnd = copydst if copysrc > SegaScreenScaledSpriteDataStart fatal "Scale copy source overran allocated size. Try changing the initial value of copydst to Chunk_Table+$\{copysrc-Chunk_Table}" endif ; =========================================================================== ObjB0_RunLeft: subi.w #$20,x_pos(a0) subq.w #1,objoff_2A(a0) bmi.s loc_3A312 bsr.w ObjB0_Move_Streaks_Left lea (Ani_objB0).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3A312: addq.b #2,routine(a0) move.w #$C,objoff_2A(a0) move.b #1,objoff_2C(a0) move.b #-1,objoff_2D(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjB0_MidWipe: tst.w objoff_2A(a0) beq.s loc_3A33A subq.w #1,objoff_2A(a0) bsr.w ObjB0_Move_Streaks_Left loc_3A33A: lea word_3A49E(pc),a1 bsr.w loc_3A44E bne.s loc_3A346 rts ; =========================================================================== loc_3A346: addq.b #2,routine(a0) bchg #0,render_flags(a0) move.w #$B,objoff_2A(a0) move.w #4,(SegaScr_VInt_Subrout).w subi.w #$28,x_pos(a0) bchg #0,render_flags(a0) bchg #0,status(a0) ; This clears a lot more than the horizontal scroll buffer, which is $400 bytes. ; This is because the loop counter is erroneously set to $400, instead of ($400/4)-1. clearRAM Horiz_Scroll_Buf,Horiz_Scroll_Buf_End+$C04 ; Bug: That '+$C04' shouldn't be there; accidentally clears an additional $C04 bytes ; Initialize streak horizontal offsets for Sonic going right. ; 9 full lines (8 pixels) + 7 pixels, 2-byte interleaved entries for PNT A and PNT B lea (Horiz_Scroll_Buf + 2 * 2 * (9 * 8 + 7)).w,a1 lea Streak_Horizontal_offsets(pc),a2 moveq #0,d0 moveq #$22,d6 ; Number of streaks-1 loc_3A38A: move.b (a2)+,d0 sub.w d0,(a1) addq.w #2 * 2 * 2,a1 ; Advance to next streak 2 pixels down dbf d6,loc_3A38A rts ; =========================================================================== ObjB0_RunRight: subq.w #1,objoff_2A(a0) bmi.s loc_3A3B4 addi.w #$20,x_pos(a0) bsr.w ObjB0_Move_Streaks_Right lea (Ani_objB0).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3A3B4: addq.b #2,routine(a0) move.w #$C,objoff_2A(a0) move.b #1,objoff_2C(a0) move.b #-1,objoff_2D(a0) rts ; =========================================================================== ObjB0_EndWipe: tst.w objoff_2A(a0) beq.s loc_3A3DA subq.w #1,objoff_2A(a0) bsr.w ObjB0_Move_Streaks_Right loc_3A3DA: lea word_3A514(pc),a1 bsr.w loc_3A44E bne.s loc_3A3E6 rts ; =========================================================================== loc_3A3E6: addq.b #2,routine(a0) st (SegaScr_PalDone_Flag).w move.b #SndID_SegaSound,d0 jsrto (PlaySound).l, JmpTo12_PlaySound return_3A3F6: rts ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object B1 - Object that hides TM symbol on JP region ; ---------------------------------------------------------------------------- ; Sprite_3A3F8: ObjB1: moveq #0,d0 move.b routine(a0),d0 move.w ObjB1_Index(pc,d0.w),d1 jmp ObjB1_Index(pc,d1.w) ; =========================================================================== ; off_3A406: ObjB1_Index: offsetTable offsetTableEntry.w ObjB1_Init ; 0 offsetTableEntry.w ObjB1_Main ; 2 ; =========================================================================== ; loc_3A40A: ObjB1_Init: bsr.w LoadSubObject move.b #4,mapping_frame(a0) move.w #$174,x_pixel(a0) move.w #$D8,y_pixel(a0) rts ; =========================================================================== ; BranchTo4_JmpTo45_DisplaySprite ObjB1_Main: jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjB0_Move_Streaks_Left: ; 9 full lines (8 pixels) + 6 pixels, 2-byte interleaved entries for PNT A and PNT B lea (Horiz_Scroll_Buf + 2 * 2 * (9 * 8 + 6)).w,a1 move.w #$22,d6 ; Number of streaks-1 - subi.w #$20,(a1) addq.w #2 * 2 * 2,a1 ; Advance to next streak 2 pixels down dbf d6,- rts ; =========================================================================== ObjB0_Move_Streaks_Right: ; 9 full lines (8 pixels) + 7 pixels, 2-byte interleaved entries for PNT A and PNT B lea (Horiz_Scroll_Buf + 2 * 2 * (9 * 8 + 7)).w,a1 move.w #$22,d6 ; Number of streaks-1 - addi.w #$20,(a1) addq.w #2 * 2 * 2,a1 ; Advance to next streak 2 pixels down dbf d6,- rts ; =========================================================================== loc_3A44E: subq.b #1,objoff_2C(a0) bne.s loc_3A496 moveq #0,d0 move.b objoff_2D(a0),d0 addq.b #1,d0 cmp.b 1(a1),d0 blo.s loc_3A468 tst.b 3(a1) bne.s loc_3A49A loc_3A468: move.b d0,objoff_2D(a0) _move.b 0(a1),objoff_2C(a0) lea 6(a1),a2 ; This loads a palette: Sega Screen 2.bin or Sega Screen 3.bin moveq #0,d1 move.b 2(a1),d1 move.w d1,d2 tst.w d0 beq.s loc_3A48C loc_3A482: subq.b #1,d0 beq.s loc_3A48A add.w d2,d1 bra.s loc_3A482 ; =========================================================================== loc_3A48A: adda.w d1,a2 loc_3A48C: movea.w 4(a1),a3 loc_3A490: move.w (a2)+,(a3)+ subq.w #2,d2 bne.s loc_3A490 loc_3A496: moveq #0,d0 rts ; =========================================================================== loc_3A49A: moveq #1,d0 rts ; =========================================================================== ; probably some sort of description of how to use the following palette word_3A49E: dc.b 4 ; 0 ; How many frames before each iteration dc.b 7 ; 1 ; How many iterations dc.b $10 ; 2 ; Number of colors * 2 to skip each iteration dc.b $FF ; 3 ; Some sort of flag dc.w Normal_palette+$10 ; 4 ; First target palette entry ; Palette for the SEGA screen (background and pre-wipe foreground) (7 frames) ;pal_3A4A4: BINCLUDE "art/palettes/Sega Screen 2.bin" ; probably some sort of description of how to use the following palette word_3A514: dc.b 4 ; 0 ; How many frames before each iteration dc.b 7 ; 1 ; How many iterations dc.b $10 ; 2 ; Number of colors * 2 to skip each iteration dc.b $FF ; 3 ; Some sort of flag dc.w Normal_palette ; 4 ; First target palette entry ; Palette for the SEGA screen (wiping and post-wipe foreground) (7 frames) ;pal_3A51A: BINCLUDE "art/palettes/Sega Screen 3.bin" ; off_3A58A: ObjB0_SubObjData: subObjData ObjB1_MapUnc_3A5A6,make_art_tile(ArtTile_ArtUnc_Giant_Sonic,2,1),0,1,$10,0 ; off_3A594: ObjB1_SubObjData: subObjData ObjB1_MapUnc_3A5A6,make_art_tile(ArtTile_ArtNem_Sega_Logo+2,0,0),0,2,8,0 ; animation script ; off_3A59E: Ani_objB0: offsetTable offsetTableEntry.w + ; 0 + dc.b 0, 0, 1, 2, 3,$FF even ; ------------------------------------------------------------------------------ ; sprite mappings ; Gigantic Sonic (2x size) mappings for the SEGA screen ; also has the "trademark hider" mappings ; ------------------------------------------------------------------------------ ObjB1_MapUnc_3A5A6: BINCLUDE "mappings/sprite/objB1.bin" ; =========================================================================== ;loc_3A68A SegaScr_VInt: move.w (SegaScr_VInt_Subrout).w,d0 beq.w return_37A48 clr.w (SegaScr_VInt_Subrout).w move.w off_3A69E-2(pc,d0.w),d0 jmp off_3A69E(pc,d0.w) ; =========================================================================== off_3A69E: offsetTable offsetTableEntry.w loc_3A6A2 ; 0 offsetTableEntry.w loc_3A6D4 ; 2 ; =========================================================================== loc_3A6A2: dma68kToVDP SegaScreenScaledSpriteDataStart,tiles_to_bytes(ArtTile_ArtUnc_Giant_Sonic),\ SegaScreenScaledSpriteDataEnd-SegaScreenScaledSpriteDataStart,VRAM lea ObjB1_Streak_fade_to_right(pc),a1 ; 9 full lines ($100 bytes each) plus $28 8-pixel cells move.l #vdpComm(VRAM_SegaScr_Plane_A_Name_Table + planeLocH80($28,9),VRAM,WRITE),d0 ; $49500003 bra.w loc_3A710 ; =========================================================================== loc_3A6D4: dmaFillVRAM 0,VRAM_SegaScr_Plane_A_Name_Table,VRAM_SegaScr_Plane_Table_Size ; clear Plane A pattern name table lea ObjB1_Streak_fade_to_left(pc),a1 ; $49A00003; 9 full lines ($100 bytes each) plus $50 8-pixel cells move.l #vdpComm(VRAM_SegaScr_Plane_A_Name_Table + planeLocH80($50,9),VRAM,WRITE),d0 bra.w loc_3A710 loc_3A710: lea (VDP_data_port).l,a6 ; This is the line delta; for each line, the code below ; writes $30 entries, leaving $50 untouched. move.l #vdpCommDelta(planeLocH80(0,1)),d6 ; $1000000 moveq #7,d1 ; Inner loop: repeat 8 times moveq #9,d2 ; Outer loop: repeat $A times - move.l d0,4(a6) ; Send command to VDP: set address to write to move.w d1,d3 ; Reset inner loop counter movea.l a1,a2 ; Reset data pointer - move.w (a2)+,d4 ; Read one pattern name table entry bclr #$A,d4 ; Test bit $A and clear (flag for end of line) beq.s + ; Branch if bit was clear bsr.w loc_3A742 ; Fill rest of line with this set of pixels + move.w d4,(a6) ; Write PNT entry dbf d3,- add.l d6,d0 ; Point to the next VRAM area to be written to dbf d2,-- rts ; =========================================================================== loc_3A742: moveq #$28,d5 ; Fill next $29 entries... - move.w d4,(a6) ; ... using the PNT entry that had bit $A set dbf d5,- rts ; =========================================================================== ; Pattern A name table entries, with special flag detailed below ; These are used for the streaks, and point to VRAM in the $1000-$10FF range ObjB1_Streak_fade_to_right: dc.w make_block_tile(ArtTile_ArtNem_Trails+0,0,0,1,1) ; 0 dc.w make_block_tile(ArtTile_ArtNem_Trails+1,0,0,1,1) ; 2 dc.w make_block_tile(ArtTile_ArtNem_Trails+2,0,0,1,1) ; 4 dc.w make_block_tile(ArtTile_ArtNem_Trails+3,0,0,1,1) ; 6 dc.w make_block_tile(ArtTile_ArtNem_Trails+4,0,0,1,1) ; 8 dc.w make_block_tile(ArtTile_ArtNem_Trails+5,0,0,1,1) ; 10 dc.w make_block_tile(ArtTile_ArtNem_Trails+6,0,0,1,1) ; 12 dc.w make_block_tile(ArtTile_ArtNem_Trails+7,0,0,1,1) | (1 << $A) ; 14 ; Bit $A is used as a flag to use this tile $29 times ObjB1_Streak_fade_to_left: dc.w make_block_tile(ArtTile_ArtNem_Trails+7,0,0,1,1) | (1 << $A) ; 0 ; Bit $A is used as a flag to use this tile $29 times dc.w make_block_tile(ArtTile_ArtNem_Trails+6,0,0,1,1) ; 2 dc.w make_block_tile(ArtTile_ArtNem_Trails+5,0,0,1,1) ; 4 dc.w make_block_tile(ArtTile_ArtNem_Trails+4,0,0,1,1) ; 6 dc.w make_block_tile(ArtTile_ArtNem_Trails+3,0,0,1,1) ; 8 dc.w make_block_tile(ArtTile_ArtNem_Trails+2,0,0,1,1) ; 10 dc.w make_block_tile(ArtTile_ArtNem_Trails+1,0,0,1,1) ; 12 dc.w make_block_tile(ArtTile_ArtNem_Trails+0,0,0,1,1) ; 14 Streak_Horizontal_offsets: dc.b $12 dc.b 4 ; 1 dc.b 4 ; 2 dc.b 2 ; 3 dc.b 2 ; 4 dc.b 2 ; 5 dc.b 2 ; 6 dc.b 0 ; 7 dc.b 0 ; 8 dc.b 0 ; 9 dc.b 0 ; 10 dc.b 0 ; 11 dc.b 0 ; 12 dc.b 0 ; 13 dc.b 0 ; 14 dc.b 4 ; 15 dc.b 4 ; 16 dc.b 6 ; 17 dc.b $A ; 18 dc.b 8 ; 19 dc.b 6 ; 20 dc.b 4 ; 21 dc.b 4 ; 22 dc.b 4 ; 23 dc.b 4 ; 24 dc.b 6 ; 25 dc.b 6 ; 26 dc.b 8 ; 27 dc.b 8 ; 28 dc.b $A ; 29 dc.b $A ; 30 dc.b $C ; 31 dc.b $E ; 32 dc.b $10 ; 33 dc.b $16 ; 34 dc.b 0 ; 35 ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object B2 - The Tornado (Tails' plane) ; ---------------------------------------------------------------------------- ; Sprite_3A790: ObjB2: moveq #0,d0 move.b routine(a0),d0 move.w ObjB2_Index(pc,d0.w),d1 jmp ObjB2_Index(pc,d1.w) ; =========================================================================== ; off_3A79E: ObjB2_Index: offsetTable offsetTableEntry.w ObjB2_Init ; 0 offsetTableEntry.w ObjB2_Main_SCZ ; 2 offsetTableEntry.w ObjB2_Main_WFZ_Start ; 4 offsetTableEntry.w ObjB2_Main_WFZ_End ; 6 offsetTableEntry.w ObjB2_Invisible_grabber ; 8 offsetTableEntry.w loc_3AD0C ; $A offsetTableEntry.w loc_3AD2A ; $C offsetTableEntry.w loc_3AD42 ; $E ; =========================================================================== ; loc_3A7AE: ObjB2_Init: bsr.w LoadSubObject moveq #0,d0 move.b subtype(a0),d0 subi.b #$4E,d0 move.b d0,routine(a0) cmpi.w #2,(Player_mode).w bne.s + cmpi.b #8,d0 bhs.s + move.b #4,mapping_frame(a0) move.b #1,anim(a0) + ; BranchTo5_JmpTo45_DisplaySprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; loc_3A7DE: ObjB2_Main_SCZ: bsr.w ObjB2_Animate_Pilot tst.w (Debug_placement_mode).w bne.w ObjB2_animate lea (MainCharacter).w,a1 ; a1=character move.w art_tile(a1),d0 andi.w #high_priority,d0 move.w art_tile(a0),d1 andi.w #drawing_mask,d1 or.w d0,d1 move.w d1,art_tile(a0) move.w x_pos(a0),-(sp) bsr.w ObjB2_Move_with_player move.b status(a0),objoff_2E(a0) move.w #$1B,d1 move.w #8,d2 move.w #9,d3 move.w (sp)+,d4 jsrto (SolidObject).l, JmpTo27_SolidObject bsr.w ObjB2_Move_obbey_player move.b objoff_2E(a0),d0 move.b status(a0),d1 if gameRevision<2 andi.b #p1_standing,d0 ; 'on object' bit andi.b #p1_standing,d1 ; 'on object' bit else ; 'fixes' the player being able to spin dash off the Tornado andi.b #1,d0 ; 'in air' bit andi.b #1,d1 ; 'in air' bit endif eor.b d0,d1 move.b d1,objoff_2E(a0) lea (MainCharacter).w,a1 ; a1=character move.w x_pos(a1),d1 move.w (Camera_X_pos).w,d0 move.w d0,(Camera_Min_X_pos).w move.w d0,d2 addi.w #$11,d2 cmp.w d2,d1 bhi.s + addq.w #1,d1 move.w d1,x_pos(a1) + ; loc_3A85E: cmpi.w #$1400,d0 blo.s loc_3A878 cmpi.w #$1568,d1 bhs.s ObjB2_SCZ_Finished st (Control_Locked).w move.w #(button_right_mask<<8)|button_right_mask,(Ctrl_1_Logical).w bra.w loc_3A87C ; =========================================================================== loc_3A878: subi.w #$40,d0 loc_3A87C: move.w d0,(Camera_Max_X_pos).w ; loc_3A880: ObjB2_animate: lea (Ani_objB2_a).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; loc_3A88E: ObjB2_SCZ_Finished: bsr.w ObjB2_Deactivate_level move.w #wing_fortress_zone_act_1,(Current_ZoneAndAct).w bra.s ObjB2_animate ; =========================================================================== ; loc_3A89A: ObjB2_Main_WFZ_Start: bsr.w ObjB2_Animate_Pilot moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3A8BA(pc,d0.w),d1 jsr off_3A8BA(pc,d1.w) lea (Ani_objB2_a).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (Obj_DeleteOffScreen).l, Obj_DeleteOffScreen ; =========================================================================== off_3A8BA: offsetTable offsetTableEntry.w ObjB2_Main_WFZ_Start_init ; 0 offsetTableEntry.w ObjB2_Main_WFZ_Start_main ; 2 offsetTableEntry.w ObjB2_Main_WFZ_Start_shot_down ; 4 offsetTableEntry.w ObjB2_Main_WFZ_Start_fall_down ; 6 ; =========================================================================== ; loc_3A8C2: ObjB2_Main_WFZ_Start_init: addq.b #2,routine_secondary(a0) move.w #$C0,objoff_32(a0) move.w #$100,x_vel(a0) rts ; =========================================================================== ; loc_3A8D4: ObjB2_Main_WFZ_Start_main: subq.w #1,objoff_32(a0) bmi.s + move.w x_pos(a0),-(sp) jsrto (ObjectMove).l, JmpTo26_ObjectMove bsr.w loc_36776 move.w #$1B,d1 move.w #8,d2 move.w #9,d3 move.w (sp)+,d4 jsrto (SolidObject).l, JmpTo27_SolidObject bra.w ObjB2_Horizontal_limit ; =========================================================================== + ; loc_3A8FC: addq.b #2,routine_secondary(a0) move.w #$60,objoff_2A(a0) move.w #1,objoff_32(a0) move.w #$100,x_vel(a0) move.w #$100,y_vel(a0) rts ; =========================================================================== ; loc_3A91A: ObjB2_Main_WFZ_Start_shot_down: move.b (Vint_runcount+3).w,d0 andi.b #$1F,d0 bne.s + moveq #SndID_Scatter,d0 jsrto (PlaySound).l, JmpTo12_PlaySound + ; loc_3A92A: subq.w #1,objoff_2A(a0) bmi.s + - ; loc_3A930: bsr.w ObjB2_Align_plane subq.w #1,objoff_32(a0) bne.w return_37A48 move.w #$E,objoff_32(a0) bra.w ObjB2_Main_WFZ_Start_load_smoke ; =========================================================================== + ; loc_3A946: addq.b #2,routine_secondary(a0) bra.w loc_3B7BC ; =========================================================================== ; loc_3A94E: ObjB2_Main_WFZ_Start_fall_down: jsrto (ObjectMove).l, JmpTo26_ObjectMove bra.s - ; =========================================================================== ; loc_3A954: ObjB2_Main_WFZ_End: bsr.w ObjB2_Animate_Pilot moveq #0,d0 move.b routine_secondary(a0),d0 move.w ObjB2_Main_WFZ_states(pc,d0.w),d1 jsr ObjB2_Main_WFZ_states(pc,d1.w) lea (Ani_objB2_a).l,a1 jmpto (AnimateSprite).l, JmpTo25_AnimateSprite ; =========================================================================== ; off_3A970: ObjB2_Main_WFZ_states: offsetTable offsetTableEntry.w ObjB2_Wait_Leader_position ; 0 offsetTableEntry.w ObjB2_Move_Leader_edge ; 2 offsetTableEntry.w ObjB2_Wait_for_plane ; 4 offsetTableEntry.w ObjB2_Prepare_to_jump ; 6 offsetTableEntry.w ObjB2_Jump_to_plane ; 8 offsetTableEntry.w ObjB2_Landed_on_plane ; $A offsetTableEntry.w ObjB2_Approaching_ship ; $C offsetTableEntry.w ObjB2_Jump_to_ship ; $E offsetTableEntry.w ObjB2_Dock_on_DEZ ; $10 ; =========================================================================== ; loc_3A982: ObjB2_Wait_Leader_position: lea (MainCharacter).w,a1 ; a1=character cmpi.w #$5EC,y_pos(a1) blo.s + ; rts clr.w (Ctrl_1_Logical).w addq.w #1,objoff_2E(a0) cmpi.w #$40,objoff_2E(a0) bhs.s ++ + ; return_3A99E: rts ; =========================================================================== + ; loc_3A9A0: addq.b #2,routine_secondary(a0) move.w #$2E58,x_pos(a0) move.w #$66C,y_pos(a0) lea (MainCharacter).w,a1 ; a1=character bsr.w ObjB2_Waiting_animation lea (word_3AFBC).l,a2 bsr.w LoadChildObject move.w #$3118,x_pos(a1) move.w #$3F0,y_pos(a1) lea (word_3AFB8).l,a2 bsr.w LoadChildObject move.w #$3070,x_pos(a1) move.w #$3B0,y_pos(a1) lea (word_3AFB8).l,a2 bsr.w LoadChildObject move.w #$3070,x_pos(a1) move.w #$430,y_pos(a1) lea (word_3AFC0).l,a2 bsr.w LoadChildObject clr.w x_pos(a1) clr.w y_pos(a1) rts ; =========================================================================== ; loc_3AA0E: ObjB2_Move_Leader_egde: ObjB2_Move_Leader_edge: lea (MainCharacter).w,a1 ; a1=character cmpi.w #$2E30,x_pos(a1) bhs.s + move.w #(button_right_mask<<8)|button_right_mask,(Ctrl_1_Logical).w rts ; =========================================================================== + ; loc_3AA22: addq.b #2,routine_secondary(a0) clr.w (Ctrl_1_Logical).w clr.w x_vel(a1) clr.w y_vel(a1) clr.w inertia(a1) move.w #$600,(Sonic_top_speed).w move.w #$C,(Sonic_acceleration).w move.w #$80,(Sonic_deceleration).w bra.w ObjB2_Waiting_animation ; =========================================================================== ; loc_3AA4C: ObjB2_Wait_for_plane: cmpi.w #$380,(Camera_BG_X_offset).w bhs.s + clr.w (Ctrl_1_Logical).w bra.w ObjB2_Waiting_animation ; =========================================================================== + ; loc_3AA5C: addq.b #2,routine_secondary(a0) move.w #$100,x_vel(a0) move.w #-$100,y_vel(a0) clr.w objoff_2A(a0) bra.w ObjB2_Waiting_animation ; =========================================================================== ; loc_3AA74: ObjB2_Prepare_to_jump: bsr.w ObjB2_Waiting_animation addq.w #1,objoff_2A(a0) cmpi.w #$30,objoff_2A(a0) bne.s + addq.b #2,routine_secondary(a0) move.w #(button_A_mask<<8)|button_A_mask,(Ctrl_1_Logical).w move.w #$38,objoff_2E(a0) tst.b (Super_Sonic_flag).w beq.s + move.w #$28,objoff_2E(a0) + ; loc_3AAA0: bsr.w ObjB2_Align_plane jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; loc_3AAA8: ObjB2_Jump_to_plane: clr.w (Ctrl_1_Logical).w addq.w #1,objoff_2A(a0) subq.w #1,objoff_2E(a0) bmi.s + move.w #((button_right_mask|button_A_mask)<<8)|button_right_mask|button_A_mask,(Ctrl_1_Logical).w + ; loc_3AABC: bsr.w ObjB2_Align_plane btst #p1_standing_bit,status(a0) beq.s + addq.b #2,routine_secondary(a0) move.w #$20,objoff_2E(a0) lea (Level_Layout+$0D2).w,a1 move.l #$501F0025,(a1)+ lea (Level_Layout+$1D2).w,a1 move.l #$25001F50,(a1)+ lea (Level_Layout+$BD6).w,a1 move.l #$501F0025,(a1)+ lea (Level_Layout+$CD6).w,a1 move.l #$25001F50,(a1)+ + ; BranchTo6_JmpTo45_DisplaySprite: jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; loc_3AAFE: ObjB2_Landed_on_plane: addq.w #1,objoff_2A(a0) cmpi.w #$100,objoff_2A(a0) blo.s loc_3AB18 addq.b #2,routine_secondary(a0) movea.w objoff_3A(a0),a1 ; a1=object ?? move.b #2,routine_secondary(a1) loc_3AB18: clr.w (Ctrl_1_Logical).w lea (MainCharacter).w,a1 ; a1=character move.w x_pos(a0),x_pos(a1) clr.w x_vel(a1) clr.w y_vel(a1) clr.w inertia(a1) bclr #1,status(a1) bclr #2,status(a1) move.l #$1000505,mapping_frame(a1) move.w #$100,anim_frame_duration(a1) move.b #$13,y_radius(a1) cmpi.w #2,(Player_mode).w bne.s + move.b #$F,y_radius(a1) + ; loc_3AB60: bsr.w ObjB2_Align_plane jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; loc_3AB68: ObjB2_Approaching_ship: clr.w (Ctrl_1_Logical).w bsr.w ObjB2_Waiting_animation cmpi.w #$437,objoff_2A(a0) blo.s loc_3AB8A addq.b #2,routine_secondary(a0) ; loc_3AB7C: ObjB2_Jump_to_ship: cmpi.w #$447,objoff_2A(a0) bhs.s loc_3AB8A move.w #(button_A_mask<<8)|button_A_mask,(Ctrl_1_Logical).w loc_3AB8A: cmpi.w #$460,objoff_2A(a0) blo.s ObjB2_Dock_on_DEZ move.b #6,(Dynamic_Resize_Routine).w ; => LevEvents_WFZ_Routine4 addq.b #2,routine_secondary(a0) lea (word_3AFB8).l,a2 bsr.w LoadChildObject move.w #$3090,x_pos(a1) move.w #$3D0,y_pos(a1) lea (word_3AFB8).l,a2 bsr.w LoadChildObject move.w #$30C0,x_pos(a1) move.w #$3F0,y_pos(a1) lea (word_3AFB8).l,a2 bsr.w LoadChildObject move.w #$3090,x_pos(a1) move.w #$410,y_pos(a1) ; loc_3ABDE: ObjB2_Dock_on_DEZ: cmpi.w #$9C0,objoff_2A(a0) bhs.s ObjB2_Start_DEZ move.w objoff_2A(a0),d0 addq.w #1,d0 move.w d0,objoff_2A(a0) move.w objoff_34(a0),d1 move.w word_3AC16(pc,d1.w),d2 cmp.w d2,d0 blo.s loc_3AC0E addq.w #2,d1 move.w d1,objoff_34(a0) lea byte_3AC2A(pc,d1.w),a1 move.b (a1)+,x_vel(a0) move.b (a1)+,y_vel(a0) loc_3AC0E: bsr.w ObjB2_Align_plane jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== word_3AC16: dc.w $1E0 dc.w $260 ; 1 dc.w $2A0 ; 2 dc.w $2C0 ; 3 dc.w $300 ; 4 dc.w $3A0 ; 5 dc.w $3F0 ; 6 dc.w $460 ; 7 dc.w $4A0 ; 8 dc.w $580 ; 9 byte_3AC2A: dc.b $FF dc.b $FF ; 1 dc.b 1 ; 2 dc.b 0 ; 3 dc.b 0 ; 4 dc.b 1 ; 5 dc.b 1 ; 6 dc.b $FF ; 7 dc.b 1 ; 8 dc.b 1 ; 9 dc.b 1 ; 10 dc.b $FF ; 11 dc.b $FF ; 12 dc.b 1 ; 13 dc.b $FF ; 14 dc.b $FF ; 15 dc.b $FF ; 16 dc.b 1 ; 17 dc.b $FE ; 18 dc.b 0 ; 19 dc.b 0 ; 20 dc.b 0 ; 21 ; =========================================================================== ; loc_3AC40: ObjB2_Start_DEZ: move.w #death_egg_zone_act_1,(Current_ZoneAndAct).w ; loc_3AC46: ObjB2_Deactivate_level: move.w #1,(Level_Inactive_flag).w clr.b (Last_star_pole_hit).w clr.b (Last_star_pole_hit_2P).w rts ; =========================================================================== ; loc_3AC56: ObjB2_Waiting_animation: lea (MainCharacter).w,a1 ; a1=character move.l #$1000505,mapping_frame(a1) move.w #$100,anim_frame_duration(a1) rts ; =========================================================================== ; loc_3AC6A: ObjB2_Invisible_grabber: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3AC78(pc,d0.w),d1 jmp off_3AC78(pc,d1.w) ; =========================================================================== off_3AC78: offsetTable offsetTableEntry.w loc_3AC7E ; 0 offsetTableEntry.w loc_3AC84 ; 2 offsetTableEntry.w loc_3ACF2 ; 4 ; =========================================================================== loc_3AC7E: move.b #$C7,collision_flags(a0) loc_3AC84: tst.b collision_property(a0) beq.s return_3ACF0 addq.b #2,routine_secondary(a0) clr.b collision_flags(a0) move.w #(224/2)+8,(Camera_Y_pos_bias).w movea.w objoff_2C(a0),a1 ; a1=object bset #6,status(a1) lea (MainCharacter).w,a1 ; a1=character clr.w x_vel(a1) clr.w y_vel(a1) move.w x_pos(a0),d0 subi.w #$10,d0 move.w d0,x_pos(a1) cmpi.w #2,(Player_mode).w bne.s loc_3ACC8 subi.w #$10,y_pos(a1) loc_3ACC8: bset #0,status(a1) bclr #1,status(a1) bclr #2,status(a1) move.b #AniIDSonAni_Hang,anim(a1) move.b #1,(MainCharacter+obj_control).w move.b #1,(WindTunnel_holding_flag).w clr.w (Ctrl_1_Logical).w return_3ACF0: rts ; =========================================================================== loc_3ACF2: lea (MainCharacter).w,a1 ; a1=character clr.w x_vel(a1) clr.w y_vel(a1) move.w x_pos(a0),d0 subi.w #$10,d0 move.w d0,x_pos(a1) rts ; =========================================================================== loc_3AD0C: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3AD1A(pc,d0.w),d1 jmp off_3AD1A(pc,d1.w) ; =========================================================================== off_3AD1A: offsetTable offsetTableEntry.w + ; 0 ; =========================================================================== + ; loc_3AD1C: bchg #2,status(a0) bne.w return_37A48 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3AD2A: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3AD38(pc,d0.w),d1 jmp off_3AD38(pc,d1.w) ; =========================================================================== off_3AD38: offsetTable offsetTableEntry.w + ; 0 ; =========================================================================== + ; loc_3AD3A: jsrto (ObjectMove).l, JmpTo26_ObjectMove jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3AD42: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3AD50(pc,d0.w),d1 jmp off_3AD50(pc,d1.w) ; =========================================================================== off_3AD50: offsetTable offsetTableEntry.w loc_3AD54 ; 0 offsetTableEntry.w loc_3AD5C ; 2 ; =========================================================================== loc_3AD54: bsr.w loc_3AD6E jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3AD5C: bsr.w loc_3AD6E lea (Ani_objB2_b).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3AD6E: movea.w objoff_2C(a0),a1 ; a1=object move.w x_pos(a1),d0 subi.w #$C,d0 move.w d0,x_pos(a0) move.w y_pos(a1),d0 addi.w #$28,d0 move.w d0,y_pos(a0) rts ; =========================================================================== ; loc_3AD8C: ObjB2_Align_plane: move.w x_pos(a0),-(sp) jsrto (ObjectMove).l, JmpTo26_ObjectMove bsr.w loc_36776 move.w #$1B,d1 move.w #8,d2 move.w #9,d3 move.w (sp)+,d4 jmpto (SolidObject).l, JmpTo27_SolidObject ; =========================================================================== ; loc_3ADAA: ObjB2_Move_with_player: lea (MainCharacter).w,a1 ; a1=character btst #3,status(a1) beq.s ObjB2_Move_below_player bsr.w ObjB2_Move_vert bsr.w ObjB2_Vertical_limit jsrto (ObjectMove).l, JmpTo26_ObjectMove bra.w loc_36776 ; =========================================================================== ; loc_3ADC6: ObjB2_Move_below_player: tst.b objoff_2E(a0) beq.s loc_3ADD4 bsr.w Obj_GetOrientationToPlayer move.w d2,objoff_38(a0) loc_3ADD4: move.w #1,d0 move.w objoff_38(a0),d3 beq.s loc_3ADE8 bmi.s loc_3ADE2 neg.w d0 loc_3ADE2: add.w d0,d3 move.w d3,objoff_38(a0) loc_3ADE8: move.w x_pos(a1),d1 add.w d3,d1 move.w d1,x_pos(a0) bra.w loc_36776 ; =========================================================================== ; loc_3ADF6: ObjB2_Move_vert: tst.b objoff_2F(a0) bne.s loc_3AE16 tst.b objoff_2E(a0) beq.s return_3AE38 st objoff_2F(a0) clr.b objoff_30(a0) move.w #$200,y_vel(a0) move.b #$14,objoff_31(a0) loc_3AE16: subq.b #1,objoff_31(a0) bpl.s loc_3AE26 clr.b objoff_2F(a0) clr.w y_vel(a0) rts ; =========================================================================== loc_3AE26: move.w y_vel(a0),d0 cmpi.w #-$100,d0 ble.s loc_3AE34 addi.w #-$20,d0 loc_3AE34: move.w d0,y_vel(a0) return_3AE38: rts ; =========================================================================== ; loc_3AE3A: ObjB2_Move_obbey_player: lea (MainCharacter).w,a1 ; a1=character btst #3,status(a1) beq.s ObjB2_Move_vert2 tst.b objoff_2F(a0) bne.s loc_3AE72 clr.w y_vel(a0) move.w (Ctrl_1).w,d2 move.w #$80,d3 andi.w #(button_up_mask|button_down_mask)<<8,d2 beq.s loc_3AE72 andi.w #button_down_mask<<8,d2 bne.s loc_3AE66 neg.w d3 loc_3AE66: move.w d3,y_vel(a0) bsr.w ObjB2_Vertical_limit jsrto (ObjectMove).l, JmpTo26_ObjectMove loc_3AE72: bsr.w Obj_GetOrientationToPlayer moveq #$10,d3 add.w d3,d2 cmpi.w #$20,d2 blo.s return_3AE9E mvabs.w inertia(a1),d2 cmpi.w #$900,d2 bhs.s return_3AE9E tst.w d0 beq.s loc_3AE94 neg.w d3 loc_3AE94: move.w x_pos(a1),d1 add.w d3,d1 move.w d1,x_pos(a0) return_3AE9E: rts ; =========================================================================== ; loc_3AEA0: ObjB2_Move_vert2: tst.b objoff_30(a0) bne.s loc_3AEC0 tst.b objoff_2E(a0) beq.s return_3AE9E st objoff_30(a0) clr.b objoff_2F(a0) move.w #$200,y_vel(a0) move.b #$2B,objoff_31(a0) loc_3AEC0: subq.b #1,objoff_31(a0) bpl.s loc_3AED0 clr.b objoff_30(a0) clr.w y_vel(a0) rts ; =========================================================================== loc_3AED0: move.w y_vel(a0),d0 cmpi.w #-$100,d0 ble.s loc_3AEDE addi.w #-$20,d0 loc_3AEDE: move.w d0,y_vel(a0) bsr.w ObjB2_Vertical_limit jsrto (ObjectMove).l, JmpTo26_ObjectMove rts ; =========================================================================== ; loc_3AEEC: ObjB2_Horizontal_limit: bsr.w Obj_GetOrientationToPlayer moveq #$10,d3 add.w d3,d2 cmpi.w #$20,d2 blo.s return_3AF0A tst.w d0 beq.s loc_3AF00 neg.w d3 loc_3AF00: move.w x_pos(a0),d1 sub.w d3,d1 move.w d1,x_pos(a1) return_3AF0A: rts ; =========================================================================== ; loc_3AF0C: ObjB2_Vertical_limit: move.w (Camera_Y_pos).w,d0 move.w y_pos(a0),d1 move.w y_vel(a0),d2 beq.s return_3AF32 bpl.s loc_3AF26 addi.w #$34,d0 cmp.w d0,d1 blo.s loc_3AF2E rts ; =========================================================================== loc_3AF26: addi.w #$A8,d0 cmp.w d0,d1 blo.s return_3AF32 loc_3AF2E: clr.w y_vel(a0) return_3AF32: rts ; =========================================================================== ; loc_3AF34: ObjB2_Main_WFZ_Start_load_smoke: jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s + _move.b #ObjID_TornadoSmoke2,id(a1) ; load objC3 move.b #$90,subtype(a1) ; <== ObjC3_SubObjData move.w a0,objoff_2C(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) + ; return_3AF56: rts ; =========================================================================== ; loc_3AF58: ObjB2_Animate_Pilot: subq.b #1,objoff_37(a0) bmi.s + rts ; =========================================================================== + ; loc_3AF60: move.b #8,objoff_37(a0) moveq #0,d0 move.b objoff_36(a0),d0 moveq #Tails_pilot_frames_end-Tails_pilot_frames,d1 cmpi.w #2,(Player_mode).w bne.s + moveq #Sonic_pilot_frames_end-Sonic_pilot_frames,d1 + ; loc_3AF78: addq.b #1,d0 cmp.w d1,d0 blo.s + moveq #0,d0 + ; loc_3AF80: move.b d0,objoff_36(a0) cmpi.w #2,(Player_mode).w bne.s + move.b Sonic_pilot_frames(pc,d0.w),d0 jmpto (LoadSonicDynPLC_Part2).l, JmpTo_LoadSonicDynPLC_Part2 ; =========================================================================== + ; loc_3AF94: move.b Tails_pilot_frames(pc,d0.w),d0 jmpto (LoadTailsDynPLC_Part2).l, JmpTo_LoadTailsDynPLC_Part2 ; =========================================================================== ; byte_3AF9C: Sonic_pilot_frames: dc.b $2D dc.b $2E ; 1 dc.b $2F ; 2 dc.b $30 ; 3 Sonic_pilot_frames_end: ; byte_3AFA0: Tails_pilot_frames: dc.b $10 dc.b $10 ; 1 dc.b $10 ; 2 dc.b $10 ; 3 dc.b 1 ; 4 dc.b 2 ; 5 dc.b 3 ; 6 dc.b 2 ; 7 dc.b 1 ; 8 dc.b 1 ; 9 dc.b $10 ; 10 dc.b $10 ; 11 dc.b $10 ; 12 dc.b $10 ; 13 dc.b 1 ; 14 dc.b 2 ; 15 dc.b 3 ; 16 dc.b 2 ; 17 dc.b 1 ; 18 dc.b 1 ; 19 dc.b 4 ; 20 dc.b 4 ; 21 dc.b 1 ; 22 dc.b 1 ; 23 Tails_pilot_frames_end: word_3AFB8: dc.w objoff_3E dc.b ObjID_Tornado dc.b $58 word_3AFBC: dc.w objoff_3C dc.b ObjID_Tornado dc.b $56 word_3AFC0: dc.w objoff_3A dc.b ObjID_Tornado dc.b $5C ; seems unused dc.w objoff_3E dc.b ObjID_Tornado dc.b $5A ; off_3AFC8: ObjB2_SubObjData: subObjData ObjB2_MapUnc_3AFF2,make_art_tile(ArtTile_ArtNem_Tornado,0,1),4,4,$60,0 ; off_3AFD2: ObjB2_SubObjData2: subObjData ObjB2_MapUnc_3B292,make_art_tile(ArtTile_ArtNem_TornadoThruster,0,0),4,3,$40,0 ; animation script ; off_3AFDC: Ani_objB2_a: offsetTable offsetTableEntry.w byte_3AFE0 ; 0 offsetTableEntry.w byte_3AFE6 ; 1 byte_3AFE0: dc.b 0, 0, 1, 2, 3,$FF byte_3AFE6: dc.b 0, 4, 5, 6, 7,$FF even ; animation script ; off_3AFEC: Ani_objB2_b: offsetTable offsetTableEntry.w + ; 0 ; byte_3AFEE: + dc.b 0, 1, 2,$FF even ; ----------------------------------------------------------------------------- ; sprite mappings ; ----------------------------------------------------------------------------- ObjB2_MapUnc_3AFF2: BINCLUDE "mappings/sprite/objB2_a.bin" ; ----------------------------------------------------------------------------- ; sprite mappings ; ----------------------------------------------------------------------------- ObjB2_MapUnc_3B292: BINCLUDE "mappings/sprite/objB2_b.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object B3 - Clouds (placeable object) from SCZ ; ---------------------------------------------------------------------------- ; Sprite_3B2DE: ObjB3: moveq #0,d0 move.b routine(a0),d0 move.w ObjB3_Index(pc,d0.w),d1 jmp ObjB3_Index(pc,d1.w) ; =========================================================================== ; off_3B2EC: ObjB3_Index: offsetTable offsetTableEntry.w ObjB3_Init ; 0 offsetTableEntry.w ObjB3_Main ; 2 ; =========================================================================== ; loc_3B2F0: ObjB3_Init: bsr.w LoadSubObject moveq #0,d0 move.b subtype(a0),d0 subi.b #$5E,d0 move.w word_3B30C(pc,d0.w),x_vel(a0) lsr.w #1,d0 move.b d0,mapping_frame(a0) rts ; =========================================================================== word_3B30C: dc.w -$80 dc.w -$40 ; 1 dc.w -$20 ; 2 ; =========================================================================== ; loc_3B312: ObjB3_Main: jsrto (ObjectMove).l, JmpTo26_ObjectMove move.w (Tornado_Velocity_X).w,d0 add.w d0,x_pos(a0) bra.w Obj_DeleteBehindScreen ; =========================================================================== ; off_3B322: ObjB3_SubObjData: subObjData ObjB3_MapUnc_3B32C,make_art_tile(ArtTile_ArtNem_Clouds,2,0),4,6,$30,0 ; ----------------------------------------------------------------------------- ; sprite mappings ; ----------------------------------------------------------------------------- ObjB3_MapUnc_3B32C: BINCLUDE "mappings/sprite/objB3.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object B4 - Vertical propeller from WFZ ; ---------------------------------------------------------------------------- ; Sprite_3B36A: ObjB4: moveq #0,d0 move.b routine(a0),d0 move.w ObjB4_Index(pc,d0.w),d1 jmp ObjB4_Index(pc,d1.w) ; =========================================================================== ; off_3B378: ObjB4_Index: offsetTable offsetTableEntry.w ObjB4_Init ; 0 offsetTableEntry.w ObjB4_Main ; 2 ; =========================================================================== ; loc_3B37C: ObjB4_Init: bsr.w LoadSubObject bclr #1,render_flags(a0) beq.s + clr.b collision_flags(a0) + rts ; =========================================================================== ; loc_3B38E: ObjB4_Main: lea (Ani_objB4).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite move.b (Vint_runcount+3).w,d0 andi.b #$1F,d0 bne.s + moveq #SndID_Helicopter,d0 jsrto (PlaySoundLocal).l, JmpTo_PlaySoundLocal + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; off_3B3AC: ObjB4_SubObjData: subObjData ObjB4_MapUnc_3B3BE,make_art_tile(ArtTile_ArtNem_WfzVrtclPrpllr,1,1),4,4,4,$A8 ; animation script ; off_3B3B6: Ani_objB4: offsetTable offsetTableEntry.w + ; 0 + dc.b 1, 0, 1, 2,$FF, 0 even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjB4_MapUnc_3B3BE: BINCLUDE "mappings/sprite/objB4.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object B5 - Horizontal propeller from WFZ ; ---------------------------------------------------------------------------- ; Sprite_3B3FA: ObjB5: moveq #0,d0 move.b routine(a0),d0 move.w ObjB5_Index(pc,d0.w),d1 jmp ObjB5_Index(pc,d1.w) ; =========================================================================== ; off_3B408: ObjB5_Index: offsetTable offsetTableEntry.w ObjB5_Init ; 0 offsetTableEntry.w ObjB5_Main ; 2 - used in WFZ offsetTableEntry.w ObjB5_Animate ; 4 - used in SCZ, no effect on players ; =========================================================================== ; loc_3B40E: ObjB5_Init: bsr.w LoadSubObject move.b #4,anim(a0) move.b subtype(a0),d0 subi.b #$64,d0 move.b d0,routine(a0) rts ; =========================================================================== ; loc_3B426: ObjB5_Main: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3B442(pc,d0.w),d1 jsr off_3B442(pc,d1.w) lea (Ani_objB5).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== off_3B442: offsetTable offsetTableEntry.w + ; 0 ; =========================================================================== + bra.w ObjB5_CheckPlayers ; =========================================================================== ; loc_3B448: ObjB5_Animate: lea (Ani_objB5).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_3B456: ObjB5_CheckPlayers: cmpi.b #4,anim(a0) bne.s ++ ; rts lea (MainCharacter).w,a1 ; a1=character bsr.w ObjB5_CheckPlayer lea (Sidekick).w,a1 ; a1=character ; loc_3B46A: ObjB5_CheckPlayer: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 addi.w #$40,d0 cmpi.w #$80,d0 bhs.s ++ ; rts moveq #0,d1 move.b (Oscillating_Data+$14).w,d1 add.w y_pos(a1),d1 addi.w #$60,d1 sub.w y_pos(a0),d1 bcs.s ++ ; rts cmpi.w #$90,d1 bhs.s ++ ; rts subi.w #$60,d1 bcs.s + not.w d1 add.w d1,d1 + addi.w #$60,d1 neg.w d1 asr.w #4,d1 add.w d1,y_pos(a1) bset #1,status(a1) move.w #0,y_vel(a1) move.w #1,inertia(a1) tst.b flip_angle(a1) bne.s + ; rts move.b #1,flip_angle(a1) move.b #AniIDSonAni_Float2,anim(a1) move.b #$7F,flips_remaining(a1) move.b #8,flip_speed(a1) + rts ; =========================================================================== ; off_3B4DE: ObjB5_SubObjData: subObjData ObjB5_MapUnc_3B548,make_art_tile(ArtTile_ArtNem_WfzHrzntlPrpllr,1,1),4,4,$40,0 ; animation script ; off_3B4E8: Ani_objB5: offsetTable offsetTableEntry.w byte_3B4FC ; 0 offsetTableEntry.w byte_3B506 ; 1 offsetTableEntry.w byte_3B50E ; 2 offsetTableEntry.w byte_3B516 ; 3 offsetTableEntry.w byte_3B51C ; 4 offsetTableEntry.w byte_3B524 ; 5 offsetTableEntry.w byte_3B52A ; 6 offsetTableEntry.w byte_3B532 ; 7 offsetTableEntry.w byte_3B53A ; 8 offsetTableEntry.w byte_3B544 ; 9 byte_3B4FC: dc.b 7, 0, 1, 2, 3, 4, 5,$FD, 1, 0 byte_3B506: dc.b 4, 0, 1, 2, 3, 4,$FD, 2 byte_3B50E: dc.b 3, 5, 0, 1, 2,$FD, 3, 0 byte_3B516: dc.b 2, 3, 4, 5,$FD, 4 byte_3B51C: dc.b 1, 0, 1, 2, 3, 4, 5,$FF byte_3B524: dc.b 2, 5, 4, 3,$FD, 6 byte_3B52A: dc.b 3, 2, 1, 0, 5,$FD, 7, 0 byte_3B532: dc.b 4, 4, 3, 2, 1, 0,$FD, 8 byte_3B53A: dc.b 7, 5, 4, 3, 2, 1, 0,$FD, 9, 0 byte_3B544: dc.b $7E, 0,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjB5_MapUnc_3B548: BINCLUDE "mappings/sprite/objB5.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object B6 - Tilting platform from WFZ ; ---------------------------------------------------------------------------- ; Sprite_3B5D0: ObjB6: moveq #0,d0 move.b routine(a0),d0 move.w ObjB6_Index(pc,d0.w),d1 jmp ObjB6_Index(pc,d1.w) ; =========================================================================== ; off_3B5DE: ObjB6_Index: offsetTable offsetTableEntry.w ObjB6_Init ; 0 offsetTableEntry.w loc_3B602 ; 2 offsetTableEntry.w loc_3B65C ; 4 offsetTableEntry.w loc_3B6C8 ; 6 offsetTableEntry.w loc_3B73C ; 8 ; =========================================================================== ; loc_3B5E8: ObjB6_Init: moveq #0,d0 move.b #($35<<1),d0 bsr.w LoadSubObject_Part2 move.b subtype(a0),d0 andi.b #6,d0 addq.b #2,d0 move.b d0,routine(a0) rts ; =========================================================================== loc_3B602: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3B614(pc,d0.w),d1 jsr off_3B614(pc,d1.w) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== off_3B614: offsetTable offsetTableEntry.w loc_3B61C ; 0 offsetTableEntry.w loc_3B624 ; 2 offsetTableEntry.w loc_3B644 ; 4 offsetTableEntry.w loc_3B64E ; 6 ; =========================================================================== loc_3B61C: addq.b #2,routine_secondary(a0) bra.w loc_3B77E ; =========================================================================== loc_3B624: bsr.w loc_3B790 move.b (Vint_runcount+3).w,d0 andi.b #$F0,d0 cmp.b subtype(a0),d0 beq.s loc_3B638 rts ; =========================================================================== loc_3B638: addq.b #2,routine_secondary(a0) clr.b anim(a0) bra.w loc_3B7BC ; =========================================================================== loc_3B644: lea (Ani_objB6).l,a1 jmpto (AnimateSprite).l, JmpTo25_AnimateSprite ; =========================================================================== loc_3B64E: move.b #2,routine_secondary(a0) move.w #$C0,objoff_2A(a0) rts ; =========================================================================== loc_3B65C: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3B66E(pc,d0.w),d1 jsr off_3B66E(pc,d1.w) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== off_3B66E: offsetTable offsetTableEntry.w loc_3B61C offsetTableEntry.w loc_3B674 offsetTableEntry.w loc_3B6A6 ; =========================================================================== loc_3B674: bsr.w loc_3B790 subq.w #1,objoff_2A(a0) bmi.s + rts ; =========================================================================== + addq.b #2,routine_secondary(a0) move.b #$20,objoff_2A(a0) move.b #3,anim(a0) clr.b anim_frame(a0) clr.b anim_frame_duration(a0) bsr.w loc_3B7BC bsr.w loc_3B7F8 moveq #SndID_Fire,d0 jmpto (PlaySound).l, JmpTo12_PlaySound ; =========================================================================== loc_3B6A6: subq.b #1,objoff_2A(a0) bmi.s + lea (Ani_objB6).l,a1 jmpto (AnimateSprite).l, JmpTo25_AnimateSprite ; =========================================================================== + move.b #2,routine_secondary(a0) clr.b mapping_frame(a0) move.w #$C0,objoff_2A(a0) rts ; =========================================================================== loc_3B6C8: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3B6DA(pc,d0.w),d1 jsr off_3B6DA(pc,d1.w) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== off_3B6DA: offsetTable offsetTableEntry.w loc_3B6E2 ; 0 offsetTableEntry.w loc_3B6FE ; 2 offsetTableEntry.w loc_3B72C ; 4 offsetTableEntry.w loc_3B736 ; 6 ; =========================================================================== loc_3B6E2: bsr.w loc_3B790 move.b status(a0),d0 andi.b #standing_mask,d0 bne.s + rts ; =========================================================================== + addq.b #2,routine_secondary(a0) move.w #$10,objoff_2A(a0) rts ; =========================================================================== loc_3B6FE: bsr.w loc_3B790 subq.w #1,objoff_2A(a0) bmi.s + rts ; =========================================================================== + addq.b #2,routine_secondary(a0) move.b #0,anim(a0) bsr.w Obj_GetOrientationToPlayer bclr #0,status(a0) tst.w d0 bne.s + bset #0,status(a0) + bra.w loc_3B7BC ; =========================================================================== loc_3B72C: lea (Ani_objB6).l,a1 jmpto (AnimateSprite).l, JmpTo25_AnimateSprite ; =========================================================================== loc_3B736: clr.b routine_secondary(a0) rts ; =========================================================================== loc_3B73C: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3B74E(pc,d0.w),d1 jsr off_3B74E(pc,d1.w) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== off_3B74E: offsetTable offsetTableEntry.w loc_3B756 ; 0 offsetTableEntry.w loc_3B764 ; 2 offsetTableEntry.w loc_3B644 ; 4 offsetTableEntry.w loc_3B64E ; 6 ; =========================================================================== loc_3B756: addq.b #2,routine_secondary(a0) move.b #2,mapping_frame(a0) bra.w loc_3B77E ; =========================================================================== loc_3B764: bsr.w loc_3B7A6 subq.w #1,objoff_2A(a0) bmi.s loc_3B770 rts ; =========================================================================== loc_3B770: addq.b #2,routine_secondary(a0) move.b #4,anim(a0) bra.w loc_3B7BC ; =========================================================================== loc_3B77E: move.b subtype(a0),d0 andi.w #$F0,d0 move.b d0,subtype(a0) move.w d0,objoff_2A(a0) rts ; =========================================================================== loc_3B790: move.w x_pos(a0),-(sp) move.w #$23,d1 move.w #4,d2 move.w #4,d3 move.w (sp)+,d4 jmpto (SolidObject).l, JmpTo27_SolidObject ; =========================================================================== loc_3B7A6: move.w x_pos(a0),-(sp) move.w #$F,d1 move.w #$18,d2 move.w #$18,d3 move.w (sp)+,d4 jmpto (SolidObject).l, JmpTo27_SolidObject ; =========================================================================== loc_3B7BC: move.b status(a0),d0 if gameRevision<2 andi.b #standing_mask,d0 else ; I don't know what this change was meant to do, but it causes ; Sonic to not fall off ObjBD's ascending platforms when they retract, ; making him hover. andi.b #2,d0 endif beq.s return_3B7F6 bclr #p1_standing_bit,status(a0) beq.s loc_3B7DE lea (MainCharacter).w,a1 ; a1=character bclr #3,status(a1) bset #1,status(a1) loc_3B7DE: bclr #p2_standing_bit,status(a0) beq.s return_3B7F6 lea (Sidekick).w,a1 ; a1=character bclr #4,status(a1) bset #1,status(a1) return_3B7F6: rts ; =========================================================================== loc_3B7F8: jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s + _move.b #ObjID_VerticalLaser,id(a1) ; load objB7 (huge unused vertical laser!) move.b #$72,subtype(a1) ; <== ObjB7_SubObjData move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) + rts ; =========================================================================== ; off_3B818: ObjB6_SubObjData: subObjData ObjB6_MapUnc_3B856,make_art_tile(ArtTile_ArtNem_WfzTiltPlatforms,1,1),4,4,$10,0 ; animation script ; off_3B822: Ani_objB6: offsetTable offsetTableEntry.w byte_3B830 ; 0 offsetTableEntry.w byte_3B836 ; 1 offsetTableEntry.w byte_3B83A ; 2 offsetTableEntry.w byte_3B840 ; 3 offsetTableEntry.w byte_3B846 ; 4 offsetTableEntry.w byte_3B84C ; 5 offsetTableEntry.w byte_3B850 ; 6 byte_3B830: dc.b 3, 1, 2,$FD, 1, 0 byte_3B836: dc.b $3F, 2,$FD, 2 byte_3B83A: dc.b 3, 2, 1, 0,$FA, 0 byte_3B840: dc.b 1, 0, 1, 2, 3,$FF byte_3B846: dc.b 3, 1, 0,$FD, 5, 0 byte_3B84C: dc.b $3F, 0,$FD, 6 byte_3B850: dc.b 3, 0, 1, 2,$FA, 0 even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjB6_MapUnc_3B856: BINCLUDE "mappings/sprite/objB6.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object B7 - Unused huge vertical laser from WFZ ; ---------------------------------------------------------------------------- ; Sprite_3B8A6: ObjB7: moveq #0,d0 move.b routine(a0),d0 move.w ObjB7_Index(pc,d0.w),d1 jmp ObjB7_Index(pc,d1.w) ; =========================================================================== ; off_3B8B4: ObjB7_Index: offsetTable offsetTableEntry.w ObjB7_Init ; 0 offsetTableEntry.w ObjB7_Main ; 2 ; =========================================================================== ; loc_3B8B8: ObjB7_Init: bsr.w LoadSubObject move.b #$20,objoff_2A(a0) rts ; =========================================================================== ; loc_3B8C4: ObjB7_Main: subq.b #1,objoff_2A(a0) beq.w JmpTo65_DeleteObject bchg #0,objoff_2B(a0) beq.w return_37A48 jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; off_3B8DA: ObjB7_SubObjData: subObjData ObjB7_MapUnc_3B8E4,make_art_tile(ArtTile_ArtNem_WfzVrtclLazer,2,1),4,4,$18,$A9 ObjB7_MapUnc_3B8E4: BINCLUDE "mappings/sprite/objB7.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object B8 - Wall turret from WFZ ; ---------------------------------------------------------------------------- ; Sprite_3B968: ObjB8: moveq #0,d0 move.b routine(a0),d0 move.w ObjB8_Index(pc,d0.w),d1 jmp ObjB8_Index(pc,d1.w) ; =========================================================================== ; off_3B976: ObjB8_Index: offsetTable offsetTableEntry.w ObjB8_Init ; 0 offsetTableEntry.w loc_3B980 ; 2 offsetTableEntry.w loc_3B9AA ; 4 ; =========================================================================== ; BranchTo5_LoadSubObject ObjB8_Init: bra.w LoadSubObject ; =========================================================================== loc_3B980: tst.b render_flags(a0) bpl.s + bsr.w Obj_GetOrientationToPlayer tst.w d1 beq.s + addi.w #$60,d2 cmpi.w #$C0,d2 blo.s ++ + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== + addq.b #2,routine(a0) move.w #2,objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3B9AA: bsr.w Obj_GetOrientationToPlayer moveq #0,d6 addi.w #$20,d2 cmpi.w #$40,d2 blo.s loc_3B9C0 move.w d0,d6 lsr.w #1,d6 addq.w #1,d6 loc_3B9C0: move.b d6,mapping_frame(a0) subq.w #1,objoff_2A(a0) bne.s + move.w #$60,objoff_2A(a0) bsr.w loc_3B9D8 + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3B9D8: jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s + ; rts _move.b #ObjID_Projectile,id(a1) ; load obj98 move.b #3,mapping_frame(a1) move.b #$8E,subtype(a1) ; <== ObjB8_SubObjData2 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) lea_ Obj98_WallTurretShotMove,a2 move.l a2,objoff_2A(a1) moveq #0,d0 move.b mapping_frame(a0),d0 lsl.w #2,d0 lea byte_3BA2A(pc,d0.w),a2 move.b (a2)+,d0 ext.w d0 add.w d0,x_pos(a1) move.b (a2)+,d0 ext.w d0 add.w d0,y_pos(a1) move.b (a2)+,x_vel(a1) move.b (a2)+,y_vel(a1) + rts ; =========================================================================== byte_3BA2A: dc.b 0 dc.b $18 ; 1 dc.b 0 ; 2 dc.b 1 ; 3 dc.b $EF ; 4 dc.b $10 ; 5 dc.b $FF ; 6 dc.b 1 ; 7 dc.b $11 ; 8 dc.b $10 ; 9 dc.b 1 ; 10 dc.b 1 ; 11 ; off_3BA36: ObjB8_SubObjData: subObjData ObjB8_Obj98_MapUnc_3BA46,make_art_tile(ArtTile_ArtNem_WfzWallTurret,0,0),4,4,$10,0 ; animation script ; off_3BA40: Ani_WallTurretShot: offsetTable offsetTableEntry.w + ; 0 + dc.b 2, 3, 4,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjB8_Obj98_MapUnc_3BA46: BINCLUDE "mappings/sprite/objB8.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object B9 - Laser from WFZ that shoots down the Tornado ; ---------------------------------------------------------------------------- ; Sprite_3BABA: ObjB9: moveq #0,d0 move.b routine(a0),d0 move.w ObjB9_Index(pc,d0.w),d1 jmp ObjB9_Index(pc,d1.w) ; =========================================================================== ; off_3BAC8: ObjB9_Index: offsetTable offsetTableEntry.w ObjB9_Init offsetTableEntry.w loc_3BAD2 offsetTableEntry.w loc_3BAF0 ; =========================================================================== ; BranchTo6_LoadSubObject ObjB9_Init: bra.w LoadSubObject ; =========================================================================== loc_3BAD2: tst.b render_flags(a0) bmi.s + bra.w loc_3BAF8 ; =========================================================================== + addq.b #2,routine(a0) move.w #-$1000,x_vel(a0) moveq #SndID_LargeLaser,d0 jsrto (PlaySound).l, JmpTo12_PlaySound bra.w loc_3BAF8 ; =========================================================================== loc_3BAF0: jsrto (ObjectMove).l, JmpTo26_ObjectMove bra.w loc_3BAF8 loc_3BAF8: move.w x_pos(a0),d0 move.w (Camera_X_pos).w,d1 subi.w #$40,d1 cmp.w d1,d0 blt.w JmpTo65_DeleteObject jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; off_3BB0E: ObjB9_SubObjData: subObjData ObjB9_MapUnc_3BB18,make_art_tile(ArtTile_ArtNem_WfzHrzntlLazer,2,1),4,1,$60,0 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjB9_MapUnc_3BB18: BINCLUDE "mappings/sprite/objB9.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object BA - Wheel from WFZ ; ---------------------------------------------------------------------------- ; Sprite_3BB4C: ObjBA: moveq #0,d0 move.b routine(a0),d0 move.w ObjBA_Index(pc,d0.w),d1 jmp ObjBA_Index(pc,d1.w) ; =========================================================================== ; off_3BB5A: ObjBA_Index: offsetTable offsetTableEntry.w ObjBA_Init ; 0 offsetTableEntry.w ObjBA_Main ; 2 ; =========================================================================== ; BranchTo7_LoadSubObject ObjBA_Init: bra.w LoadSubObject ; =========================================================================== ; BranchTo14_JmpTo39_MarkObjGone ObjBA_Main: jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; off_3BB66: ObjBA_SubObjData: subObjData ObjBA_MapUnc_3BB70,make_art_tile(ArtTile_ArtNem_WfzConveyorBeltWheel,2,1),4,4,$10,0 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjBA_MapUnc_3BB70: BINCLUDE "mappings/sprite/objBA.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object BB - Removed object (unknown, unused) ; ---------------------------------------------------------------------------- ; Sprite_3BB7C: ObjBB: moveq #0,d0 move.b routine(a0),d0 move.w ObjBB_Index(pc,d0.w),d1 jmp ObjBB_Index(pc,d1.w) ; =========================================================================== ; off_3BB8A: ObjBB_Index: offsetTable offsetTableEntry.w ObjBB_Init ; 0 offsetTableEntry.w ObjBB_Main ; 2 ; =========================================================================== ; BranchTo8_LoadSubObject ObjBB_Init: bra.w LoadSubObject ; =========================================================================== ; BranchTo15_JmpTo39_MarkObjGone ObjBB_Main: jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; off_3BB96: ObjBB_SubObjData: subObjData ObjBB_MapUnc_3BBA0,make_art_tile(ArtTile_ArtNem_Unknown,1,0),4,4,$C,9 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjBB_MapUnc_3BBA0: BINCLUDE "mappings/sprite/objBB.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object BC - Fire coming out of Robotnik's ship in WFZ ; ---------------------------------------------------------------------------- ; Sprite_3BBBC: ObjBC: moveq #0,d0 move.b routine(a0),d0 move.w ObjBC_Index(pc,d0.w),d1 jmp ObjBC_Index(pc,d1.w) ; =========================================================================== ; off_3BBCA: ObjBC_Index: offsetTable offsetTableEntry.w ObjBC_Init offsetTableEntry.w ObjBC_Main ; =========================================================================== ; loc_3BBCE: ObjBC_Init: bsr.w LoadSubObject move.w x_pos(a0),objoff_2C(a0) rts ; =========================================================================== ; loc_3BBDA: ObjBC_Main: move.w objoff_2C(a0),d0 move.w (Camera_BG_X_offset).w,d1 cmpi.w #$380,d1 bhs.w JmpTo65_DeleteObject add.w d1,d0 move.w d0,x_pos(a0) bchg #0,objoff_2A(a0) beq.w return_37A48 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; off_3BBFE: ObjBC_SubObjData2: subObjData ObjBC_MapUnc_3BC08,make_art_tile(ArtTile_ArtNem_WfzThrust,2,0),4,4,$10,0 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjBC_MapUnc_3BC08: BINCLUDE "mappings/sprite/objBC.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object BD - Ascending/descending metal platforms from WFZ ; ---------------------------------------------------------------------------- ; Sprite_3BC1C: ObjBD: moveq #0,d0 move.b routine(a0),d0 move.w ObjBD_Index(pc,d0.w),d1 jmp ObjBD_Index(pc,d1.w) ; =========================================================================== ; off_3BC2A: ObjBD_Index: offsetTable offsetTableEntry.w ObjBD_Init ; 0 offsetTableEntry.w loc_3BC3C ; 2 offsetTableEntry.w loc_3BC50 ; 4 ; =========================================================================== ; loc_3BC30: ObjBD_Init: addq.b #2,routine(a0) move.w #1,objoff_2A(a0) rts ; =========================================================================== loc_3BC3C: subq.w #1,objoff_2A(a0) bne.s + move.w #$40,objoff_2A(a0) bsr.w loc_3BCF8 + jmpto (MarkObjGone3).l, JmpTo8_MarkObjGone3 ; =========================================================================== loc_3BC50: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3BC62(pc,d0.w),d1 jsr off_3BC62(pc,d1.w) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== off_3BC62: offsetTable offsetTableEntry.w loc_3BC6C ; 0 offsetTableEntry.w loc_3BCAC ; 2 offsetTableEntry.w loc_3BCB6 ; 4 offsetTableEntry.w loc_3BCCC ; 6 offsetTableEntry.w loc_3BCD6 ; 8 ; =========================================================================== loc_3BC6C: bsr.w LoadSubObject move.b #2,mapping_frame(a0) subq.b #2,routine(a0) addq.b #2,routine_secondary(a0) move.w #$C7,objoff_2A(a0) btst #0,render_flags(a0) beq.s loc_3BC92 move.w #$1C7,objoff_2A(a0) loc_3BC92: moveq #0,d0 move.b subtype(a0),d0 subi.b #$7E,d0 move.b d0,subtype(a0) move.w word_3BCA8(pc,d0.w),y_vel(a0) rts ; =========================================================================== word_3BCA8: dc.w -$100 dc.w $100 ; 1 ; =========================================================================== loc_3BCAC: lea (Ani_objBD).l,a1 jmpto (AnimateSprite).l, JmpTo25_AnimateSprite ; =========================================================================== loc_3BCB6: subq.w #1,objoff_2A(a0) bmi.s loc_3BCC0 bra.w loc_3BCDE ; =========================================================================== loc_3BCC0: addq.b #2,routine_secondary(a0) move.b #1,anim(a0) rts ; =========================================================================== loc_3BCCC: lea (Ani_objBD).l,a1 jmpto (AnimateSprite).l, JmpTo25_AnimateSprite ; =========================================================================== loc_3BCD6: bsr.w loc_3B7BC bra.w JmpTo65_DeleteObject ; =========================================================================== loc_3BCDE: move.w x_pos(a0),-(sp) jsrto (ObjectMove).l, JmpTo26_ObjectMove move.w #$23,d1 move.w #4,d2 move.w #5,d3 move.w (sp)+,d4 jmpto (PlatformObject).l, JmpTo9_PlatformObject ; =========================================================================== loc_3BCF8: jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s + ; rts _move.b #ObjID_SmallMetalPform,id(a1) ; load objBD move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b #4,routine(a1) move.b subtype(a0),subtype(a1) move.b render_flags(a0),render_flags(a1) + rts ; =========================================================================== ; off_3BD24: ObjBD_SubObjData: subObjData ObjBD_MapUnc_3BD3E,make_art_tile(ArtTile_ArtNem_WfzBeltPlatform,3,1),4,4,$18,0 ; animation script ; off_3BD2E: Ani_objBD: offsetTable offsetTableEntry.w byte_3BD32 ; 0 offsetTableEntry.w byte_3BD38 ; 1 byte_3BD32: dc.b 3, 2, 1, 0,$FA, 0 byte_3BD38: dc.b 1, 0, 1, 2,$FA even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjBD_MapUnc_3BD3E: BINCLUDE "mappings/sprite/objBD.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object BE - Lateral cannon (temporary platform that pops in/out) from WFZ ; ---------------------------------------------------------------------------- ; Sprite_3BD7A: ObjBE: moveq #0,d0 move.b routine(a0),d0 move.w ObjBE_Index(pc,d0.w),d1 jmp ObjBE_Index(pc,d1.w) ; =========================================================================== ; off_3BD88: ObjBE_Index: offsetTable offsetTableEntry.w ObjBE_Init ; 0 offsetTableEntry.w loc_3BDA2 ; 2 offsetTableEntry.w loc_3BDC6 ; 4 offsetTableEntry.w loc_3BDD4 ; 6 offsetTableEntry.w loc_3BDC6 ; 8 offsetTableEntry.w loc_3BDF4 ; $A ; =========================================================================== ; loc_3BD94: ObjBE_Init: moveq #0,d0 move.b #($41<<1),d0 bsr.w LoadSubObject_Part2 bra.w loc_3B77E ; =========================================================================== loc_3BDA2: move.b (Vint_runcount+3).w,d0 andi.b #$F0,d0 cmp.b subtype(a0),d0 beq.s + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; --------------------------------------------------------------------------- + addq.b #2,routine(a0) clr.b anim(a0) move.w #$A0,objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3BDC6: lea (Ani_objBE).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3BDD4: subq.w #1,objoff_2A(a0) beq.s + bsr.w loc_3BE04 jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; --------------------------------------------------------------------------- + addq.b #2,routine(a0) move.b #1,anim(a0) bsr.w loc_3B7BC jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3BDF4: move.b #2,routine(a0) move.w #$40,objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3BE04: move.b mapping_frame(a0),d0 cmpi.b #3,d0 beq.s + cmpi.b #4,d0 bne.w loc_3B7BC + move.w x_pos(a0),-(sp) move.w #$23,d1 move.w #$18,d2 move.w #$19,d3 move.w (sp)+,d4 jmpto (PlatformObject).l, JmpTo9_PlatformObject ; =========================================================================== ; off_3BE2C: ObjBE_SubObjData: subObjData ObjBE_MapUnc_3BE46,make_art_tile(ArtTile_ArtNem_WfzGunPlatform,3,1),4,4,$18,0 ; animation script ; off_3BE36: Ani_objBE: offsetTable offsetTableEntry.w byte_3BE3A ; 0 offsetTableEntry.w byte_3BE40 ; 1 byte_3BE3A: dc.b 5, 0, 1, 2, 3,$FC byte_3BE40: dc.b 5, 3, 2, 1, 0,$FC even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjBE_MapUnc_3BE46: BINCLUDE "mappings/sprite/objBE.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object BF - Rotaty-stick badnik from WFZ ; ---------------------------------------------------------------------------- ; Sprite_3BEAA: ObjBF: moveq #0,d0 move.b routine(a0),d0 move.w ObjBF_Index(pc,d0.w),d1 jmp ObjBF_Index(pc,d1.w) ; =========================================================================== ; off_3BEB8: ObjBF_Index: offsetTable offsetTableEntry.w ObjBF_Init ; 0 offsetTableEntry.w ObjBF_Animate ; 2 ; =========================================================================== ; BranchTo9_LoadSubObject ObjBF_Init: bra.w LoadSubObject ; =========================================================================== ; loc_3BEC0: ObjBF_Animate: lea (Ani_objBF).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; off_3BECE: ObjBE_SubObjData2: subObjData ObjBF_MapUnc_3BEE0,make_art_tile(ArtTile_ArtNem_WfzUnusedBadnik,3,1),4,4,4,4 ; animation script ; off_3BED8: Ani_objBF: offsetTable offsetTableEntry.w + ; 0 + dc.b 1, 0, 1, 2,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjBF_MapUnc_3BEE0: BINCLUDE "mappings/sprite/objBF.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object C0 - Speed launcher from WFZ ; ---------------------------------------------------------------------------- ; Sprite_3BF04: ObjC0: moveq #0,d0 move.b routine(a0),d0 move.w ObjC0_Index(pc,d0.w),d1 jmp ObjC0_Index(pc,d1.w) ; =========================================================================== ; off_3BF12: ObjC0_Index: offsetTable offsetTableEntry.w ObjC0_Init ; 0 offsetTableEntry.w ObjC0_Main ; 2 ; =========================================================================== ; loc_3BF16: ObjC0_Init: move.w #($43<<1),d0 bsr.w LoadSubObject_Part2 moveq #0,d0 move.b subtype(a0),d0 lsl.w #4,d0 btst #0,status(a0) bne.s + neg.w d0 + move.w x_pos(a0),d1 move.w d1,objoff_34(a0) add.w d1,d0 move.w d0,objoff_32(a0) ; loc_3BF3E: ObjC0_Main: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3BF60(pc,d0.w),d1 jsr off_3BF60(pc,d1.w) move.w #$10,d1 move.w #$11,d3 move.w x_pos(a0),d4 jsrto (PlatformObject).l, JmpTo9_PlatformObject jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== off_3BF60: offsetTable offsetTableEntry.w loc_3BF66 offsetTableEntry.w loc_3BFD8 offsetTableEntry.w loc_3C062 ; =========================================================================== loc_3BF66: move.b status(a0),d0 andi.b #standing_mask,d0 beq.s +++ ; rts addq.b #2,routine_secondary(a0) move.w #$C00,x_vel(a0) move.w #$80,objoff_30(a0) btst #0,status(a0) bne.s + neg.w x_vel(a0) neg.w objoff_30(a0) + jsrto (ObjectMove).l, JmpTo26_ObjectMove move.b status(a0),d0 move.b d0,d1 andi.b #p1_standing,d1 beq.s + lea (MainCharacter).w,a1 ; a1=character bsr.s loc_3BFB4 + andi.b #p2_standing,d0 beq.s + ; rts lea (Sidekick).w,a1 ; a1=character bsr.s loc_3BFB4 + rts ; =========================================================================== loc_3BFB4: clr.w inertia(a1) clr.w x_vel(a1) move.w x_pos(a0),x_pos(a1) bclr #0,status(a1) btst #0,status(a0) bne.s + bset #0,status(a1) + rts ; =========================================================================== loc_3BFD8: move.w objoff_30(a0),d0 add.w d0,x_vel(a0) jsrto (ObjectMove).l, JmpTo26_ObjectMove move.w objoff_32(a0),d0 sub.w x_pos(a0),d0 btst #0,status(a0) beq.s + neg.w d0 + tst.w d0 bpl.s loc_3C034 move.b status(a0),d0 andi.b #standing_mask,d0 beq.s return_3C01E move.b d0,d1 andi.b #p1_standing,d1 beq.s + lea (MainCharacter).w,a1 ; a1=character bsr.s loc_3BFB4 + andi.b #p2_standing,d0 beq.s return_3C01E lea (Sidekick).w,a1 ; a1=character bsr.s loc_3BFB4 return_3C01E: rts ; =========================================================================== loc_3C020: move.w x_vel(a0),x_vel(a1) move.w #-$400,y_vel(a1) bset #1,status(a1) rts ; =========================================================================== loc_3C034: addq.b #2,routine_secondary(a0) move.w objoff_32(a0),x_pos(a0) move.b status(a0),d0 andi.b #standing_mask,d0 beq.s loc_3C062 move.b d0,d1 andi.b #p1_standing,d1 beq.s loc_3C056 lea (MainCharacter).w,a1 ; a1=character bsr.s loc_3C020 loc_3C056: andi.b #p2_standing,d0 beq.s loc_3C062 lea (Sidekick).w,a1 ; a1=character bsr.s loc_3C020 loc_3C062: move.w x_pos(a0),d0 moveq #4,d1 tst.w objoff_30(a0) ; if objoff_30(a0) is positive, spl d2 ; then set d2 to $FF, else set d2 to $00 bmi.s + neg.w d1 + add.w d1,d0 cmp.w objoff_34(a0),d0 bhs.s + not.b d2 + tst.b d2 bne.s + clr.b routine_secondary(a0) move.w objoff_34(a0),d0 + move.w d0,x_pos(a0) rts ; =========================================================================== ; off_3C08E: ObjC0_SubObjData: subObjData ObjC0_MapUnc_3C098,make_art_tile(ArtTile_ArtNem_WfzLaunchCatapult,1,0),4,4,$10,0 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjC0_MapUnc_3C098: BINCLUDE "mappings/sprite/objC0.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object C1 - Breakable plating from WFZ ; (and what sonic hangs onto on the back of Robotnic's getaway ship) ; ---------------------------------------------------------------------------- ; Sprite_3C0AC: ObjC1: moveq #0,d0 move.b routine(a0),d0 move.w ObjC1_Index(pc,d0.w),d1 jmp ObjC1_Index(pc,d1.w) ; =========================================================================== ; off_3C0BA: ObjC1_Index: offsetTable offsetTableEntry.w ObjC1_Init ; 0 offsetTableEntry.w ObjC1_Main ; 2 offsetTableEntry.w ObjC1_Breakup ; 4 ; =========================================================================== ; loc_3C0C0: ObjC1_Init: move.w #($44<<1),d0 bsr.w LoadSubObject_Part2 moveq #0,d0 move.b subtype(a0),d0 mulu.w #$3C,d0 move.w d0,objoff_30(a0) ObjC1_Main: tst.b objoff_32(a0) beq.s loc_3C140 tst.w objoff_30(a0) beq.s + subq.w #1,objoff_30(a0) beq.s loc_3C12E + lea (MainCharacter).w,a1 ; a1=character move.w y_pos(a0),d0 subi.w #$18,d0 btst #button_up,(Ctrl_1_Held).w beq.s + subq.w #1,y_pos(a1) cmp.w y_pos(a1),d0 blo.s + move.w d0,y_pos(a1) + addi.w #$30,d0 btst #button_down,(Ctrl_1_Held).w beq.s + addq.w #1,y_pos(a1) cmp.w y_pos(a1),d0 bhs.s + move.w d0,y_pos(a1) + move.b (Ctrl_1_Press_Logical).w,d0 andi.w #button_B_mask|button_C_mask|button_A_mask,d0 beq.s BranchTo16_JmpTo39_MarkObjGone loc_3C12E: clr.b collision_flags(a0) clr.b (MainCharacter+obj_control).w clr.b (WindTunnel_holding_flag).w clr.b objoff_32(a0) bra.s loc_3C19A ; =========================================================================== loc_3C140: tst.b collision_property(a0) beq.s BranchTo16_JmpTo39_MarkObjGone lea (MainCharacter).w,a1 ; a1=character move.w x_pos(a0),d0 subi.w #$14,d0 cmp.w x_pos(a1),d0 bhs.s BranchTo16_JmpTo39_MarkObjGone clr.b collision_property(a0) cmpi.b #4,routine(a1) bhs.s BranchTo16_JmpTo39_MarkObjGone clr.w x_vel(a1) clr.w y_vel(a1) move.w x_pos(a0),d0 subi.w #$14,d0 move.w d0,x_pos(a1) bset #0,status(a1) move.b #AniIDSonAni_Hang,anim(a1) move.b #1,(MainCharacter+obj_control).w move.b #1,(WindTunnel_holding_flag).w move.b #1,objoff_32(a0) BranchTo16_JmpTo39_MarkObjGone jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3C19A: lea (byte_3C1E4).l,a4 lea (byte_3C1E0).l,a2 bsr.w loc_3C1F4 ObjC1_Breakup: tst.b objoff_3F(a0) beq.s + subq.b #1,objoff_3F(a0) bra.s ++ ; =========================================================================== + jsrto (ObjectMove).l, JmpTo26_ObjectMove addi_.w #8,y_vel(a0) lea (Ani_objC1).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite + tst.b render_flags(a0) bpl.w JmpTo65_DeleteObject jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; animation script ; off_3C1D6: Ani_objC1: offsetTable offsetTableEntry.w + ; 0 + dc.b 3, 2, 3, 4, 5, 1,$FF even ; unknown byte_3C1E0: dc.b 0 dc.b 4 ; 1 dc.b $18 ; 2 dc.b $20 ; 3 byte_3C1E4: dc.w -$10 dc.w -$10 ; 2 dc.w -$10 ; 4 dc.w $10 ; 6 dc.w -$30 ; 8 dc.w -$10 ; 10 dc.w -$30 ; 12 dc.w $10 ; 14 ; =========================================================================== loc_3C1F4: move.w x_pos(a0),d2 move.w y_pos(a0),d3 move.b priority(a0),d4 subq.b #1,d4 moveq #3,d1 movea.l a0,a1 bra.s loc_3C20E ; =========================================================================== loc_3C208: jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2 bne.s loc_3C26C loc_3C20E: move.b #4,routine(a1) _move.b id(a0),id(a1) ; load obj move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) move.b #$84,render_flags(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w (a4)+,d0 add.w d2,d0 move.w d0,x_pos(a1) move.w (a4)+,d0 add.w d3,d0 move.w d0,y_pos(a1) move.b d4,priority(a1) move.b #$10,width_pixels(a1) move.b #1,mapping_frame(a1) move.w #-$400,x_vel(a1) move.w #0,y_vel(a1) move.b (a2)+,objoff_3F(a1) dbf d1,loc_3C208 loc_3C26C: move.w #SndID_SlowSmash,d0 jmp (PlaySound).l ; =========================================================================== ; off_3C276: ObjC1_SubObjData: subObjData ObjC1_MapUnc_3C280,make_art_tile(ArtTile_ArtNem_BreakPanels,3,1),4,4,$40,$E1 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjC1_MapUnc_3C280: BINCLUDE "mappings/sprite/objC1.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object C2 - Rivet thing you bust to get into ship at the end of WFZ ; ---------------------------------------------------------------------------- ; Sprite_3C328: ObjC2: moveq #0,d0 move.b routine(a0),d0 move.w ObjC2_Index(pc,d0.w),d1 jmp ObjC2_Index(pc,d1.w) ; =========================================================================== ; off_3C336: ObjC2_Index: offsetTable offsetTableEntry.w ObjC2_Init ; 0 offsetTableEntry.w ObjC2_Main ; 2 ; =========================================================================== ; BranchTo10_LoadSubObject ObjC2_Init: bra.w LoadSubObject ; =========================================================================== ; loc_3C33E: ObjC2_Main: move.b (MainCharacter+anim).w,objoff_30(a0) move.w x_pos(a0),-(sp) move.w #$1B,d1 move.w #8,d2 move.w #9,d3 move.w (sp)+,d4 jsrto (SolidObject).l, JmpTo27_SolidObject btst #p1_standing_bit,status(a0) bne.s ObjC2_Bust jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; loc_3C366: ObjC2_Bust: cmpi.b #2,objoff_30(a0) bne.s + move.w #$2880,(Camera_Min_X_pos).w bclr #p1_standing_bit,status(a0) _move.b #ObjID_Explosion,id(a0) ; load 0bj27 (transform into explosion) move.b #2,routine(a0) bset #1,(MainCharacter+status).w bclr #3,(MainCharacter+status).w lea (Level_Layout+$850).w,a1 ; alter the level layout move.l #$8A707172,(a1)+ move.w #$7374,(a1)+ lea (Level_Layout+$950).w,a1 move.l #$6E787978,(a1)+ move.w #$787A,(a1)+ move.b #1,(Screen_redraw_flag).w + jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; off_3C3B8: ObjC2_SubObjData: subObjData ObjC2_MapUnc_3C3C2,make_art_tile(ArtTile_ArtNem_WfzSwitch,1,1),4,4,$10,0 ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjC2_MapUnc_3C3C2: BINCLUDE "mappings/sprite/objC2.bin" Invalid_SubObjData2: ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object C3,C4 - Plane's smoke from WFZ ; ---------------------------------------------------------------------------- ; Sprite_3C3D6: ObjC3: moveq #0,d0 move.b routine(a0),d0 move.w ObjC3_Index(pc,d0.w),d1 jmp ObjC3_Index(pc,d1.w) ; =========================================================================== ; off_3C3E4: ObjC3_Index: offsetTable offsetTableEntry.w ObjC3_Init offsetTableEntry.w ObjC3_Main ; =========================================================================== ; loc_3C3E8: ObjC3_Init: bsr.w LoadSubObject move.b #7,anim_frame_duration(a0) jsrto (RandomNumber).l, JmpTo6_RandomNumber move.w (RNG_seed).w,d0 andi.w #$1C,d0 sub.w d0,x_pos(a0) addi.w #$10,y_pos(a0) move.w #-$100,y_vel(a0) move.w #-$100,x_vel(a0) rts ; =========================================================================== ; loc_3C416: ObjC3_Main: jsrto (ObjectMove).l, JmpTo26_ObjectMove subq.b #1,anim_frame_duration(a0) bpl.s + move.b #7,anim_frame_duration(a0) addq.b #1,mapping_frame(a0) cmpi.b #5,mapping_frame(a0) beq.w JmpTo65_DeleteObject + jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; off_3C438: ObjC3_SubObjData: subObjData Obj27_MapUnc_21120,make_art_tile(ArtTile_ArtNem_Explosion,0,0),4,5,$C,0 ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object C5 - WFZ boss ; ---------------------------------------------------------------------------- ; Sprite_3C442: ObjC5: moveq #0,d0 move.b routine(a0),d0 move.w ObjC5_Index(pc,d0.w),d1 jmp ObjC5_Index(pc,d1.w) ; =========================================================================== ObjC5_Index: offsetTable offsetTableEntry.w ObjC5_Init ; 0 - Main loading sequence offsetTableEntry.w ObjC5_LaserCase ; 2 - Laser case (inside is laser) offsetTableEntry.w ObjC5_LaserWall ; 4 - Laser wall offsetTableEntry.w ObjC5_PlatformReleaser ; 6 - Platform releaser offsetTableEntry.w ObjC5_Platform ; 8 - Platform offsetTableEntry.w ObjC5_PlatformHurt ; $A - Invisible object that gets the platform's spikes to hurt sonic offsetTableEntry.w ObjC5_LaserShooter ; $C - Laser shooter offsetTableEntry.w ObjC5_Laser ; $E - Laser offsetTableEntry.w ObjC5_Robotnik ; $10 - Robotnik offsetTableEntry.w ObjC5_RobotnikPlatform ; $12 - Platform Robotnik's on ; =========================================================================== ObjC5_Init: bsr.w LoadSubObject move.b subtype(a0),d0 subi.b #$90,d0 move.b d0,routine(a0) rts ; =========================================================================== ObjC5_LaserCase: ; also the "mother" object moveq #0,d0 move.b routine_secondary(a0),d0 move.w ObjC5_CaseIndex(pc,d0.w),d1 jsr ObjC5_CaseIndex(pc,d1.w) bra.w ObjC5_HandleHits ; =========================================================================== ObjC5_CaseIndex:offsetTable offsetTableEntry.w ObjC5_CaseBoundary ; 0 - Sets up boundaries for movement and basic things offsetTableEntry.w ObjC5_CaseWaitStart ; 2 - Waits for sonic to start offsetTableEntry.w ObjC5_CaseWaitDown ; 4 - Waits to make the laser go down offsetTableEntry.w ObjC5_CaseDown ; 6 - Moves the case down offsetTableEntry.w ObjC5_CaseXSpeed ; 8 - Sets an X speed for the case offsetTableEntry.w ObjC5_CaseBoundaryChk ; $A - Checks to make sure the case doesn't go through the boundaries offsetTableEntry.w ObjC5_CaseAnimate ; $C - Animates the case (opening and closing) offsetTableEntry.w ObjC5_CaseLSLoad ; $E - Laser shooter loading offsetTableEntry.w ObjC5_CaseLSDown ; $10 - Moves the laser shooter down offsetTableEntry.w ObjC5_CaseWaitLoadLaser ; $12 - Waits to load the laser offsetTableEntry.w ObjC5_CaseWaitMove ; $14 - Waits to move (checks if laser is completely loaded (as big as it gets)) offsetTableEntry.w ObjC5_CaseBoundaryLaserChk ; $16 - Checks boundaries when moving with the laser offsetTableEntry.w ObjC5_CaseLSUp ; $18 - wait for laser shooter to go back up offsetTableEntry.w ObjC5_CaseAnimate ; $1A - Animates the case (opening and closing) offsetTableEntry.w ObjC5_CaseStartOver ; $1C - Sets secondary routine to 8 offsetTableEntry.w ObjC5_CaseDefeated ; $1E - When defeated goes here (explosions and stuff) ; =========================================================================== ObjC5_CaseBoundary: addq.b #2,routine_secondary(a0) move.b #0,collision_flags(a0) move.b #8,collision_property(a0) ; Hit points move.w #$442,d0 move.w d0,(Camera_Max_Y_pos_now).w move.w d0,(Camera_Max_Y_pos).w move.w x_pos(a0),d0 subi.w #$60,d0 ; Max Left position move.w d0,objoff_34(a0) addi.w #$C0,d0 ; Max Right Position move.w d0,objoff_36(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseWaitStart: bsr.w Obj_GetOrientationToPlayer addi.w #$20,d2 cmpi.w #$40,d2 ; How far away sonic is to start the boss blo.s ObjC5_CaseStart jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseStart: addq.b #2,routine_secondary(a0) move.w #$40,y_vel(a0) ; Speed at which the laser carrier goes down lea (ObjC5_LaserWallData).l,a2 bsr.w LoadChildObject subi.w #$88,x_pos(a1) ; where to load the left laser wall (x) addi.w #$60,y_pos(a1) ; left laser wall (y) lea (ObjC5_LaserWallData).l,a2 bsr.w LoadChildObject addi.w #$88,x_pos(a1) ; right laser wall (x) addi.w #$60,y_pos(a1) ; right laser wall (y) lea (ObjC5_LaserShooterData).l,a2 bsr.w LoadChildObject lea (ObjC5_PlatformReleaserData).l,a2 bsr.w LoadChildObject lea (ObjC5_RobotnikData).l,a2 bsr.w LoadChildObject move.w #$5A,objoff_2A(a0) ; How long for the boss music to start playing and the boss to start moveq #MusID_FadeOut,d0 jsrto (PlaySound).l, JmpTo12_PlaySound jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseWaitDown: subq.w #1,objoff_2A(a0) bmi.s ObjC5_CaseSpeedDown jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseSpeedDown: addq.b #2,routine_secondary(a0) move.w #$60,objoff_2A(a0) ; How long the laser carrier goes down moveq #MusID_Boss,d0 jsrto (PlayMusic).l, JmpTo5_PlayMusic jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseDown: subq.w #1,objoff_2A(a0) beq.s ObjC5_CaseStopDown jsrto (ObjectMove).l, JmpTo26_ObjectMove jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseStopDown: addq.b #2,routine_secondary(a0) clr.w y_vel(a0) ; stop the laser carrier from going down jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseXSpeed: addq.b #2,routine_secondary(a0) bsr.w Obj_GetOrientationToPlayer move.w #$100,d1 ; Speed of carrier (when going back and forth before sending out laser) tst.w d0 bne.s ObjC5_CasePMLoader neg.w d1 ObjC5_CasePMLoader: move.w d1,x_vel(a0) bset #2,status(a0) ; makes the platform maker load move.w #$70,objoff_2A(a0) ; how long to go back and forth before letting out laser jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseBoundaryChk: ; waits and makes sure the carrier does not go beyond the limit subq.w #1,objoff_2A(a0) bmi.s ObjC5_CaseOpeningAnim move.w x_pos(a0),d0 tst.w x_vel(a0) bmi.s ObjC5_CaseBoundaryChk2 cmp.w objoff_36(a0),d0 bhs.s ObjC5_CaseNegSpeed bra.w ObjC5_CaseMoveDisplay ; =========================================================================== ObjC5_CaseBoundaryChk2: cmp.w objoff_34(a0),d0 bhs.s ObjC5_CaseMoveDisplay ObjC5_CaseNegSpeed: neg.w x_vel(a0) ObjC5_CaseMoveDisplay: jsrto (ObjectMove).l, JmpTo26_ObjectMove jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseOpeningAnim: addq.b #2,routine_secondary(a0) clr.b anim(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseAnimate: lea (Ani_objC5).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseLSLoad: ; loads up the laser shooter (LS) addq.b #2,routine_secondary(a0) move.w #$E,objoff_2A(a0) ; Time the laser shooter moves down movea.w objoff_3C(a0),a1 ; a1=object (laser shooter) move.b #4,routine_secondary(a1) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseLSDown: subq.w #1,objoff_2A(a0) beq.s ObjC5_CaseAddCollision movea.w objoff_3C(a0),a1 ; a1=object (laser shooter) addq.w #1,y_pos(a1) ; laser shooter down speed jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseAddCollision: addq.b #2,routine_secondary(a0) move.w #$40,objoff_2A(a0) ; Length before shooting laser bset #4,status(a0) ; makes the hit sound and flashes happen only once when you hit it bset #6,status(a0) ; makes sure collision gets restored move.b #6,collision_flags(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseWaitLoadLaser: subq.w #1,objoff_2A(a0) bmi.s ObjC5_CaseLoadLaser jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseLoadLaser: addq.b #2,routine_secondary(a0) lea (ObjC5_LaserData).l,a2 bsr.w LoadChildObject ; loads laser jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseWaitMove: movea.w parent(a0),a1 ; a1=object btst #2,status(a1) ; waits to check if laser fired bne.s ObjC5_CaseLaserSpeed jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseLaserSpeed: addq.b #2,routine_secondary(a0) move.w #$80,objoff_2A(a0) ; how long to move the laser bsr.w Obj_GetOrientationToPlayer ; tests if sonic is to the right or left move.w #$80,d1 ; Speed when moving with laser tst.w d0 bne.s ObjC5_CaseLaserSpeedSet neg.w d1 ObjC5_CaseLaserSpeedSet: move.w d1,x_vel(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseBoundaryLaserChk: ; make sure you stay in range when firing laser subq.w #1,objoff_2A(a0) bmi.s ObjC5_CaseStopLaserDelete move.w x_pos(a0),d0 tst.w x_vel(a0) bmi.s ObjC5_CaseBoundaryLaserChk2 cmp.w objoff_36(a0),d0 bhs.s ObjC5_CaseLaserStopMove bra.w ObjC5_CaseLaserMoveDisplay ; =========================================================================== ObjC5_CaseBoundaryLaserChk2: cmp.w objoff_34(a0),d0 bhs.s ObjC5_CaseLaserMoveDisplay ObjC5_CaseLaserStopMove: clr.w x_vel(a0) ; stop moving ObjC5_CaseLaserMoveDisplay: jsrto (ObjectMove).l, JmpTo26_ObjectMove jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseStopLaserDelete: ; stops collision and deletes laser addq.b #2,routine_secondary(a0) move.w #$E,objoff_2A(a0) ; time for laser shooter to move back up bclr #3,status(a0) bclr #4,status(a0) bclr #6,status(a0) clr.b collision_flags(a0) ; no more collision movea.w parent(a0),a1 ; a1=object (laser) jsrto (DeleteObject2).l, JmpTo6_DeleteObject2 ; delete the laser jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseLSUp: subq.w #1,objoff_2A(a0) beq.s ObjC5_CaseClosingAnim movea.w objoff_3C(a0),a1 ; a1=object (laser shooter) subq.w #1,y_pos(a1) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseClosingAnim: ;sets which animation to do addq.b #2,routine_secondary(a0) move.b #1,anim(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseStartOver: move.b #8,routine_secondary(a0) bsr.w ObjC5_CaseXSpeed jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_CaseDefeated: clr.b collision_flags(a0) st collision_property(a0) bclr #6,status(a0) subq.w #1,objoff_30(a0) ; timer bmi.s ObjC5_End jsrto (Boss_LoadExplosion).l, JmpTo_Boss_LoadExplosion jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_End: ; play music and change camera speed moveq #MusID_WFZ,d0 jsrto (PlayMusic).l, JmpTo5_PlayMusic move.w #$720,d0 move.w d0,(Camera_Max_Y_pos_now).w move.w d0,(Camera_Max_Y_pos).w bsr.w JmpTo65_DeleteObject addq.w #4,sp rts ; =========================================================================== ObjC5_LaserWall: moveq #0,d0 move.b routine_secondary(a0),d0 move.w ObjC5_LaserWallIndex(pc,d0.w),d1 jsr ObjC5_LaserWallIndex(pc,d1.w) tst.b (a0) beq.w return_37A48 move.w x_pos(a0),-(sp) move.w #$13,d1 move.w #$40,d2 move.w #$80,d3 move.w (sp)+,d4 jmpto (SolidObject).l, JmpTo27_SolidObject ; =========================================================================== ObjC5_LaserWallIndex: offsetTable offsetTableEntry.w ObjC5_LaserWallMappings ; 0 - selects the mappings offsetTableEntry.w ObjC5_LaserWallWaitDelete ; 2 - Waits till set to delete (when the boss is defeated) offsetTableEntry.w ObjC5_LaserWallDelete ; 4 - After a little time it deletes ; =========================================================================== ObjC5_LaserWallMappings: addq.b #2,routine_secondary(a0) move.b #$C,mapping_frame(a0) ; loads the laser wall from the WFZ boss art jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_LaserWallWaitDelete: movea.w objoff_2C(a0),a1 ; a1=object btst #5,status(a1) bne.s ObjC5_LaserWallTimerSet bchg #0,objoff_2F(a0) ; makes it "flash" if set it won't flash bne.w return_37A48 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_LaserWallTimerSet: ; sets a small timer addq.b #2,routine_secondary(a0) move.b #4,objoff_30(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_LaserWallDelete: subq.b #1,anim_frame_duration(a0) bpl.w return_37A48 move.b anim_frame_duration(a0),d0 move.b anim_frame(a0),d1 addq.b #2,d0 bpl.s ObjC5_LaserWallDisplay move.b d1,anim_frame_duration(a0) subq.b #1,objoff_30(a0) bpl.s ObjC5_LaserWallDisplay move.b #$10,objoff_30(a0) addq.b #1,d1 cmpi.b #5,d1 bhs.w JmpTo65_DeleteObject move.b d1,anim_frame(a0) move.b d1,anim_frame_duration(a0) ObjC5_LaserWallDisplay: bclr #0,objoff_2F(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_PlatformReleaser: moveq #0,d0 move.b routine_secondary(a0),d0 move.w ObjC5_PlatformReleaserIndex(pc,d0.w),d1 jmp ObjC5_PlatformReleaserIndex(pc,d1.w) ; =========================================================================== ObjC5_PlatformReleaserIndex: offsetTable offsetTableEntry.w ObjC5_PlatformReleaserInit ; 0 - Load mappings and position offsetTableEntry.w ObjC5_PlatformReleaserWaitDown ; 2 - Waits for laser case to move down offsetTableEntry.w ObjC5_PlatformReleaserDown ; 4 - Goes down until time limit is up offsetTableEntry.w ObjC5_PlatformReleaserLoadWait ; 6 - Waits to load the platforms (the interval of time between each is from this) and makes sure only 3 are loaded offsetTableEntry.w ObjC5_PlatformReleaserDelete ; 8 - Explodes then deletes ; =========================================================================== ObjC5_PlatformReleaserInit: addq.b #2,routine_secondary(a0) move.b #5,mapping_frame(a0) addq.w #8,y_pos(a0) ; Move down a little jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_PlatformReleaserWaitDown: movea.w objoff_2C(a0),a1 ; a1=object laser case btst #2,status(a1) ; checks if laser case is done moving down (so it starts loading the platforms) bne.s ObjC5_PlatformReleaserSetDown jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_PlatformReleaserSetDown: addq.b #2,routine_secondary(a0) move.w #$40,objoff_2A(a0) ; time to go down move.w #$40,y_vel(a0) ; speed to go down jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_PlatformReleaserDown: subq.w #1,objoff_2A(a0) beq.s ObjC5_PlatformReleaserStop jsrto (ObjectMove).l, JmpTo26_ObjectMove jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_PlatformReleaserStop: addq.b #2,routine_secondary(a0) clr.w y_vel(a0) move.w #$10,objoff_2A(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_PlatformReleaserLoadWait: movea.w objoff_2C(a0),a1 ; a1=object btst #5,status(a1) bne.s ObjC5_PlatformReleaserDestroyP subq.w #1,objoff_2A(a0) bne.s BranchTo8_JmpTo45_DisplaySprite move.w #$80,objoff_2A(a0) ; Time between loading platforms moveq #0,d0 move.b objoff_2E(a0),d0 addq.b #1,d0 cmpi.b #3,d0 ; How many platforms to load blo.s ObjC5_PlatformReleaserLoadP moveq #0,d0 ObjC5_PlatformReleaserLoadP: ; P=Platforms move.b d0,objoff_2E(a0) tst.b objoff_30(a0,d0.w) bne.s BranchTo8_JmpTo45_DisplaySprite st objoff_30(a0,d0.w) lea (ObjC5_PlatformData).l,a2 bsr.w LoadChildObject move.b objoff_2E(a0),objoff_2E(a1) BranchTo8_JmpTo45_DisplaySprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_PlatformReleaserDestroyP: ; P=Platforms addq.b #2,routine_secondary(a0) bset #5,status(a0) ; destroy platforms jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_PlatformReleaserDelete: movea.w objoff_2C(a0),a1 ; a1=object cmpi.b #ObjID_WFZBoss,id(a1) bne.w JmpTo65_DeleteObject jsrto (Boss_LoadExplosion).l, JmpTo_Boss_LoadExplosion jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_Platform: moveq #0,d0 move.b routine_secondary(a0),d0 move.w ObjC5_PlatformIndex(pc,d0.w),d1 jsr ObjC5_PlatformIndex(pc,d1.w) lea (Ani_objC5).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite tst.b (a0) beq.w return_37A48 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_PlatformIndex: offsetTable offsetTableEntry.w ObjC5_PlatformInit ; 0 - Selects mappings, anim ation, y speed and loads the object that hurts sonic (by spiky area) offsetTableEntry.w ObjC5_PlatformDownWait ; 2 - Wait till the platform goes down some offsetTableEntry.w ObjC5_PlatformTestChangeDirection ; 4 - checks if time limit is over and if so to change direction ; =========================================================================== ObjC5_PlatformInit: addq.b #2,routine_secondary(a0) move.b #3,anim(a0) move.b #7,mapping_frame(a0) move.w #$100,y_vel(a0) ; Y speed move.w #$60,objoff_2A(a0) lea (ObjC5_PlatformHurtData).l,a2 ; loads the invisible object that hurts sonic bra.w LoadChildObject ; =========================================================================== ObjC5_PlatformDownWait: ; waits for it to go down some bsr.w ObjC5_PlatformCheckExplode subq.w #1,objoff_2A(a0) beq.s ObjC5_PlatformLeft bra.w ObjC5_PlatformMakeSolid ; =========================================================================== ObjC5_PlatformLeft: ; goes left and makes a time limit (for going left) addq.b #2,routine_secondary(a0) move.w #$60,objoff_2A(a0) move.w #-$100,x_vel(a0) ; X speed move.w y_pos(a0),objoff_34(a0) bra.w ObjC5_PlatformMakeSolid ; =========================================================================== ObjC5_PlatformTestChangeDirection: bsr.w ObjC5_PlatformCheckExplode subq.w #1,objoff_2A(a0) bne.s ObjC5_PlatformTestLeftRight move.w #$C0,objoff_2A(a0) neg.w x_vel(a0) ObjC5_PlatformTestLeftRight: ; tests to see if a value should be added to go left or right moveq #4,d0 move.w y_pos(a0),d1 cmp.w objoff_34(a0),d1 blo.s ObjC5_PlatformChangeY neg.w d0 ObjC5_PlatformChangeY: ; give it that curving feel add.w d0,y_vel(a0) bra.w ObjC5_PlatformMakeSolid ObjC5_PlatformMakeSolid: ; makes into a platform and moves move.w x_pos(a0),-(sp) jsrto (ObjectMove).l, JmpTo26_ObjectMove move.w #$10,d1 move.w #8,d2 move.w #8,d3 move.w (sp)+,d4 jmpto (PlatformObject).l, JmpTo9_PlatformObject ; =========================================================================== ObjC5_PlatformCheckExplode: ; checks to see if platforms should explode movea.w objoff_2C(a0),a1 ; a1=object btst #5,status(a1) bne.w ObjC5_PlatformExplode rts ; =========================================================================== ObjC5_PlatformExplode: bsr.w loc_3B7BC move.b #ObjID_BossExplosion,id(a0) ; load 0bj58 (explosion) clr.b routine(a0) movea.w objoff_3C(a0),a1 ; a1=object (invisible hurting thing) jsrto (DeleteObject2).l, JmpTo6_DeleteObject2 addq.w #4,sp rts ; =========================================================================== ObjC5_PlatformHurt: moveq #0,d0 move.b routine_secondary(a0),d0 move.w ObjC5_PlatformHurtIndex(pc,d0.w),d1 jmp ObjC5_PlatformHurtIndex(pc,d1.w) ; =========================================================================== ObjC5_PlatformHurtIndex: offsetTable offsetTableEntry.w ObjC5_PlatformHurtCollision ; 0 - Gives collision that hurts sonic offsetTableEntry.w ObjC5_PlatformHurtFollowPlatform ; 2 - Follows around the platform and waits to be deleted ; =========================================================================== ObjC5_PlatformHurtCollision: addq.b #2,routine_secondary(a0) move.b #$98,collision_flags(a0) rts ; =========================================================================== ObjC5_PlatformHurtFollowPlatform: movea.w objoff_2C(a0),a1 ; a1=object (platform) btst #5,status(a1) bne.w JmpTo65_DeleteObject move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),d0 addi.w #$C,d0 move.w d0,y_pos(a0) rts ; =========================================================================== ObjC5_LaserShooter: movea.w objoff_2C(a0),a1 ; a1=object (laser case) btst #5,status(a1) bne.w JmpTo65_DeleteObject moveq #0,d0 move.b routine_secondary(a0),d0 move.w ObjC5_LaserShooterIndex(pc,d0.w),d1 jmp ObjC5_LaserShooterIndex(pc,d1.w) ; =========================================================================== ObjC5_LaserShooterIndex: offsetTable offsetTableEntry.w ObjC5_LaserShooterInit ; 0 - Loads up mappings offsetTableEntry.w ObjC5_LaserShooterFollow ; 2 - Goes back and forth with the laser case offsetTableEntry.w ObjC5_LaserShooterDown ; 4 - Laser case sets it to this routine which then makes it go down ; =========================================================================== ObjC5_LaserShooterInit: addq.b #2,routine_secondary(a0) move.b #4,mapping_frame(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_LaserShooterFollow: movea.w objoff_2C(a0),a1 ; a1=object (laser case) move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_LaserShooterDown: movea.w objoff_2C(a0),a1 ; a1=object (laser case) move.w x_pos(a1),x_pos(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_Laser: movea.w objoff_2C(a0),a1 ; a1=object btst #5,status(a1) bne.w JmpTo65_DeleteObject moveq #0,d0 move.b routine_secondary(a0),d0 move.w ObjC5_LaserIndex(pc,d0.w),d1 jsr ObjC5_LaserIndex(pc,d1.w) bchg #0,objoff_2F(a0) bne.w return_37A48 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_LaserIndex: offsetTable offsetTableEntry.w ObjC5_LaserInit ; 0 - Loads mappings and collision and such offsetTableEntry.w ObjC5_LaserFlash ; 2 - Makes the laser flash (gives the charging up effect) offsetTableEntry.w ObjC5_LaseWaitShoot ; 4 - Waits a little to launch the laser when it's done flickering (charging) offsetTableEntry.w ObjC5_LaserShoot ; 6 - Shoots down the laser untill it's fully shot out offsetTableEntry.w ObjC5_LaserMove ; 8 - Moves with laser case and shooter ; =========================================================================== ObjC5_LaserInit: addq.b #2,routine_secondary(a0) move.b #$D,mapping_frame(a0) move.b #4,priority(a0) move.b #0,collision_flags(a0) addi.w #$10,y_pos(a0) move.b #$C,anim_frame(a0) subq.w #3,y_pos(a0) rts ; =========================================================================== ObjC5_LaserFlash: bset #0,objoff_2F(a0) subq.b #1,anim_frame_duration(a0) bpl.s ObjC5_LaserNoLaser move.b anim_frame_duration(a0),d0 addq.b #2,d0 bpl.s ObjC5_LaserFlicker move.b anim_frame(a0),d0 subq.b #1,d0 beq.s ObjC5_LaseNext move.b d0,anim_frame(a0) move.b d0,anim_frame_duration(a0) ObjC5_LaserFlicker: ; this is what makes the laser flicker before being fully loaded (covering laser shooter) bclr #0,objoff_2F(a0) ObjC5_LaserNoLaser: ; without this the laser would just stay on the shooter not going down rts ; =========================================================================== ObjC5_LaseNext: ; just sets up a time to wait for the laser to shoot when it's loaded and done flickering addq.b #2,routine_secondary(a0) move.w #$40,objoff_2A(a0) rts ; =========================================================================== ObjC5_LaseWaitShoot: subq.w #1,objoff_2A(a0) bmi.s ObjC5_LaseStartShooting rts ; =========================================================================== ObjC5_LaseStartShooting: addq.b #2,routine_secondary(a0) addi.w #$10,y_pos(a0) rts ; =========================================================================== ObjC5_LaserShoot: moveq #0,d0 move.b objoff_2E(a0),d0 addq.b #1,d0 cmpi.b #5,d0 bhs.s ObjC5_LaseShotOut addi.w #$10,y_pos(a0) move.b d0,objoff_2E(a0) move.b ObjC5_LaserMappingsData(pc,d0.w),mapping_frame(a0) move.b ObjC5_LaserCollisionData(pc,d0.w),collision_flags(a0) rts ; =========================================================================== ObjC5_LaseShotOut: ; laser is fully shot out and lets the laser case know so it moves addq.b #2,routine_secondary(a0) move.w #$80,objoff_2A(a0) bset #2,status(a0) movea.w objoff_2C(a0),a1 ; a1=object (laser case) bset #3,status(a1) rts ; =========================================================================== ObjC5_LaserMappingsData: dc.b $E dc.b $F ; 1 dc.b $10 ; 2 dc.b $11 ; 3 dc.b $12 ; 4 dc.b 0 ; 5 ObjC5_LaserCollisionData: dc.b $86 dc.b $AB ; 1 dc.b $AC ; 2 dc.b $AD ; 3 dc.b $AE ; 4 dc.b 0 ; 5 ; =========================================================================== ObjC5_LaserMove: movea.w objoff_2C(a0),a1 ; a1=object move.w x_pos(a1),x_pos(a0) rts ; =========================================================================== ObjC5_Robotnik: moveq #0,d0 move.b routine_secondary(a0),d0 move.w ObjC5_RobotnikIndex(pc,d0.w),d1 jmp ObjC5_RobotnikIndex(pc,d1.w) ; =========================================================================== ObjC5_RobotnikIndex: offsetTable offsetTableEntry.w ObjC5_RobotnikInit ; 0 - Loads art, animation and position offsetTableEntry.w ObjC5_RobotnikAnimate ; 2 - Animates Robotnik and waits till the case is defeated offsetTableEntry.w ObjC5_RobotnikDown ; 4 - Goes down until timer is up ; =========================================================================== ObjC5_RobotnikInit: addq.b #2,routine_secondary(a0) move.b #0,mapping_frame(a0) move.b #1,anim(a0) move.w #$2C60,x_pos(a0) move.w #$4E6,y_pos(a0) lea (ObjC5_RobotnikPlatformData).l,a2 bsr.w LoadChildObject jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_RobotnikAnimate: movea.w objoff_2C(a0),a1 ; a1=object (laser case) btst #5,status(a1) bne.s ObjC5_RobotnikTimer lea (Ani_objC5_objC6).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_RobotnikTimer: ; Increase routine and set timer addq.b #2,routine_secondary(a0) move.w #$C0,objoff_2A(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_RobotnikDown: subq.w #1,objoff_2A(a0) bmi.s ObjC5_RobotnikDelete addq.w #1,y_pos(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ObjC5_RobotnikDelete: ; Deletes robotnik and the platform he's on movea.w parent(a0),a1 ; a1=object (Robotnik Platform) jsrto (DeleteObject2).l, JmpTo6_DeleteObject2 bra.w JmpTo65_DeleteObject ; =========================================================================== ObjC5_RobotnikPlatform: ; Just displays the platform and move accordingly to the robotnik object movea.w objoff_2C(a0),a1 ; a1=object (robotnik) move.w y_pos(a1),d0 addi.w #$26,d0 move.w d0,y_pos(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; some unused/dead code, At one point it appears a section of the platform was solid move.w x_pos(a0),-(sp) jsrto (ObjectMove).l, JmpTo26_ObjectMove move.w #$F,d1 move.w #8,d2 move.w #8,d3 move.w (sp)+,d4 jmpto (PlatformObject).l, JmpTo9_PlatformObject ; =========================================================================== ObjC5_HandleHits: tst.b collision_property(a0) beq.s ObjC5_NoHitPointsLeft tst.b collision_flags(a0) bne.s return_3CC3A tst.b objoff_30(a0) bne.s ObjC5_FlashSetUp btst #6,status(a0) beq.s return_3CC3A move.b #$20,objoff_30(a0) move.w #SndID_BossHit,d0 jsr (PlaySound).l ObjC5_FlashSetUp: lea (Normal_palette_line2+2).w,a1 moveq #0,d0 tst.w (a1) bne.s ObjC5_FlashCollisionRestore move.w #$EEE,d0 ObjC5_FlashCollisionRestore: move.w d0,(a1) subq.b #1,objoff_30(a0) bne.s return_3CC3A btst #4,status(a0) ; makes sure the boss doesn't need collision beq.s return_3CC3A move.b #6,collision_flags(a0) ; restore collision return_3CC3A: rts ; =========================================================================== ObjC5_NoHitPointsLeft: ; when the boss is defeated this tells it what to do moveq #100,d0 bsr.w AddPoints clr.b collision_flags(a0) move.w #$EF,objoff_30(a0) move.b #$1E,routine_secondary(a0) bset #5,status(a0) bclr #6,status(a0) rts ; =========================================================================== ObjC5_LaserWallData: dc.w objoff_2A dc.b ObjID_WFZBoss dc.b $94 ObjC5_PlatformData: dc.w objoff_3E dc.b ObjID_WFZBoss dc.b $98 ObjC5_PlatformHurtData: dc.w objoff_3C dc.b ObjID_WFZBoss dc.b $9A ObjC5_LaserShooterData: dc.w objoff_3C dc.b ObjID_WFZBoss dc.b $9C ObjC5_PlatformReleaserData: dc.w objoff_3A dc.b ObjID_WFZBoss dc.b $96 ObjC5_LaserData: dc.w objoff_3E dc.b ObjID_WFZBoss dc.b $9E ObjC5_RobotnikData: dc.w objoff_38 dc.b ObjID_WFZBoss dc.b $A0 ObjC5_RobotnikPlatformData: dc.w objoff_3E dc.b ObjID_WFZBoss dc.b $A2 ; off_3CC80: ObjC5_SubObjData: ; Laser Case subObjData ObjC5_MapUnc_3CCD8,make_art_tile(ArtTile_ArtNem_WFZBoss,0,0),4,4,$20,0 ; off_3CC8A: ObjC5_SubObjData2: ; Laser Walls subObjData ObjC5_MapUnc_3CCD8,make_art_tile(ArtTile_ArtNem_WFZBoss,0,0),4,1,8,0 ; off_3CC94: ObjC5_SubObjData3: ; Platforms, platform releaser, laser and laser shooter subObjData ObjC5_MapUnc_3CCD8,make_art_tile(ArtTile_ArtNem_WFZBoss,0,0),4,5,$10,0 ; off_3CC9E: ObjC6_SubObjData2: ; Robotnik subObjData ObjC6_MapUnc_3D0EE,make_art_tile(ArtTile_ArtKos_LevelArt,0,0),4,5,$20,0 ; off_3CCA8: ObjC5_SubObjData4: ; Robotnik platform subObjData ObjC5_MapUnc_3CEBC,make_art_tile(ArtTile_ArtNem_WfzFloatingPlatform,1,1),4,5,$20,0 ; animation script ; off_3CCB2: Ani_objC5: offsetTable offsetTableEntry.w byte_3CCBA ; 0 offsetTableEntry.w byte_3CCC4 ; 1 offsetTableEntry.w byte_3CCCC ; 2 offsetTableEntry.w byte_3CCD0 ; 3 byte_3CCBA: dc.b 5, 0, 1, 2, 3, 3, 3, 3,$FA, 0 byte_3CCC4: dc.b 3, 3, 2, 1, 0, 0,$FA, 0 byte_3CCCC: dc.b 3, 5, 6,$FF byte_3CCD0: dc.b 3, 7, 8, 9, $A, $B,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjC5_MapUnc_3CCD8: BINCLUDE "mappings/sprite/objC5_a.bin" ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjC5_MapUnc_3CEBC: BINCLUDE "mappings/sprite/objC5_b.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object C6 - Eggman ; ---------------------------------------------------------------------------- ; Sprite_3CED0: ObjC6: moveq #0,d0 move.b routine(a0),d0 move.w ObjC6_Index(pc,d0.w),d1 jmp ObjC6_Index(pc,d1.w) ; =========================================================================== ; off_3CEDE: ObjC6_States: ObjC6_Index: offsetTable offsetTableEntry.w ObjC6_Init ; 0 offsetTableEntry.w ObjC6_State2 ; 2 offsetTableEntry.w ObjC6_State3 ; 4 offsetTableEntry.w ObjC6_State4 ; 6 ; =========================================================================== ; loc_3CEE6: ObjC6_Init: bsr.w LoadSubObject move.b subtype(a0),d0 subi.b #$A4,d0 move.b d0,routine(a0) ; => ObjC6_State2, ObjC6_State3, or ObjC6_State4 ?? rts ; =========================================================================== ; loc_3CEF8: ObjC6_State2: moveq #0,d0 move.b routine_secondary(a0),d0 move.w ObjC6_State2_States(pc,d0.w),d1 jmp ObjC6_State2_States(pc,d1.w) ; =========================================================================== ; off_3CF06: ObjC6_State2_States: offsetTable offsetTableEntry.w ObjC6_State2_State1 ; 0 offsetTableEntry.w ObjC6_State2_State2 ; 2 offsetTableEntry.w ObjC6_State2_State3 ; 4 offsetTableEntry.w ObjC6_State2_State4 ; 6 offsetTableEntry.w ObjC6_State2_State5 ; 8 ; =========================================================================== ; loc_3CF10: ObjC6_State2_State1: ; a1=object (set in loc_3D94C) addq.b #2,routine_secondary(a0) ; => ObjC6_State2_State2 lea (word_3D0D0).l,a2 bsr.w LoadChildObject move.w #$3F8,x_pos(a1) move.w #$160,y_pos(a1) move.w a0,(DEZ_Eggman).w jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; loc_3CF32: ObjC6_State2_State2: bsr.w Obj_GetOrientationToPlayer addi.w #$5C,d2 cmpi.w #$B8,d2 blo.s loc_3CF44 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; --------------------------------------------------------------------------- loc_3CF44: addq.b #2,routine_secondary(a0) ; => ObjC6_State2_State3 move.w #$18,objoff_2A(a0) move.b #1,mapping_frame(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; loc_3CF58: ObjC6_State2_State3: subq.w #1,objoff_2A(a0) bmi.s loc_3CF62 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; --------------------------------------------------------------------------- loc_3CF62: addq.b #2,routine_secondary(a0) ; => ObjC6_State2_State4 bset #2,status(a0) move.w #$200,x_vel(a0) move.w #$10,objoff_2A(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; loc_3CF7C: ObjC6_State2_State4: cmpi.w #$810,x_pos(a0) bhs.s loc_3CFC0 bsr.w Obj_GetOrientationToPlayer addi.w #$50,d2 cmpi.w #$A0,d2 bhs.s + move.w x_pos(a1),d0 addi.w #$50,d0 move.w d0,x_pos(a0) + subq.w #1,objoff_2A(a0) bpl.s + move.w #$20,objoff_2A(a0) bsr.w loc_3D00C + jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (Ani_objC5_objC6).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3CFC0: move.b #2,mapping_frame(a0) clr.w x_vel(a0) tst.b render_flags(a0) bpl.s + addq.b #2,routine_secondary(a0) ; => ObjC6_State2_State5 move.w #$80,x_vel(a0) move.w #-$200,y_vel(a0) move.b #2,mapping_frame(a0) move.w #$50,objoff_2A(a0) bset #3,status(a0) + jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; loc_3CFF6: ObjC6_State2_State5: subq.w #1,objoff_2A(a0) bmi.w JmpTo65_DeleteObject addi.w #$10,y_vel(a0) jsrto (ObjectMove).l, JmpTo26_ObjectMove jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3D00C: lea (word_3D0D4).l,a2 bsr.w LoadChildObject move.b #$AA,subtype(a1) ; <== ObjC6_SubObjData move.b #5,mapping_frame(a1) move.w #-$100,x_vel(a1) subi.w #$18,y_pos(a1) move.w #8,objoff_2A(a1) rts ; =========================================================================== ; loc_3D036: ObjC6_State3: moveq #0,d0 move.b routine_secondary(a0),d0 move.w ObjC6_State3_States(pc,d0.w),d1 jmp ObjC6_State3_States(pc,d1.w) ; =========================================================================== ; off_3D044: ObjC6_State3_States: offsetTable offsetTableEntry.w ObjC6_State3_State1 ; 0 offsetTableEntry.w ObjC6_State3_State2 ; 2 offsetTableEntry.w ObjC6_State3_State3 ; 4 ; =========================================================================== ; loc_3D04A: ObjC6_State3_State1: movea.w objoff_2C(a0),a1 ; a1=object btst #2,status(a1) bne.s loc_3D05E bsr.w loc_3D086 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; --------------------------------------------------------------------------- loc_3D05E: addq.b #2,routine_secondary(a0) ; => ObjC6_State3_State2 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; loc_3D066: ObjC6_State3_State2: bsr.w loc_3D086 lea (Ani_objC6).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ; loc_3D078: ObjC6_State3_State3: lea (MainCharacter).w,a1 ; a1=character bclr #5,status(a1) bra.w JmpTo65_DeleteObject ; =========================================================================== loc_3D086: move.w x_pos(a0),-(sp) move.w #$13,d1 move.w #$20,d2 move.w #$20,d3 move.w (sp)+,d4 jmpto (SolidObject).l, JmpTo27_SolidObject ; =========================================================================== ; loc_3D09C: ObjC6_State4: subq.w #1,objoff_2A(a0) bmi.w JmpTo65_DeleteObject addi.w #$10,y_vel(a0) jsrto (ObjectMove).l, JmpTo26_ObjectMove jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== ; off_3D0B2: ObjC6_SubObjData3: subObjData ObjC6_MapUnc_3D0EE,make_art_tile(ArtTile_ArtKos_LevelArt,0,0),4,5,$18,0 ; off_3D0BC: ObjC6_SubObjData4: subObjData ObjC6_MapUnc_3D1DE,make_art_tile(ArtTile_ArtNem_ConstructionStripes_1,1,0),4,1,8,0 ; off_3D0C6: ObjC6_SubObjData: subObjData ObjC6_MapUnc_3D0EE,make_art_tile(ArtTile_ArtKos_LevelArt,0,0),4,5,4,0 word_3D0D0: dc.w objoff_3E dc.b ObjID_Eggman dc.b $A8 word_3D0D4: dc.w objoff_3C dc.b ObjID_Eggman dc.b $AA ; animation script ; off_3D0D8: Ani_objC5_objC6:offsetTable offsetTableEntry.w byte_3D0DC ; 0 offsetTableEntry.w byte_3D0E2 ; 1 byte_3D0DC: dc.b 5, 2, 3, 4,$FF, 0 byte_3D0E2: dc.b 5, 6, 7,$FF even ; animation script ; off_3D0E6: Ani_objC6: offsetTable offsetTableEntry.w + ; 0 + dc.b 1, 0, 1, 2, 3,$FA even ; ---------------------------------------------------------------------------- ; sprite mappings ; Robotnik running ; ---------------------------------------------------------------------------- ObjC6_MapUnc_3D0EE: BINCLUDE "mappings/sprite/objC6_a.bin" ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- ObjC6_MapUnc_3D1DE: BINCLUDE "mappings/sprite/objC6_b.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object C8 - Crawl (shield badnik) from CNZ ; ---------------------------------------------------------------------------- ; Sprite_3D23E: ObjC8: moveq #0,d0 move.b routine(a0),d0 move.w ObjC8_Index(pc,d0.w),d1 jmp ObjC8_Index(pc,d1.w) ; =========================================================================== ; off_3D24C: ObjC8_Index: offsetTable offsetTableEntry.w ObjC8_Init ; 0 offsetTableEntry.w loc_3D27C ; 2 offsetTableEntry.w loc_3D2A6 ; 4 offsetTableEntry.w loc_3D2D4 ; 6 ; =========================================================================== ; loc_3D254: ObjC8_Init: bsr.w LoadSubObject move.w #$200,objoff_2A(a0) moveq #$20,d0 btst #0,render_flags(a0) bne.s + neg.w d0 + move.w d0,x_vel(a0) move.b #$F,y_radius(a0) move.b #$10,x_radius(a0) rts ; =========================================================================== loc_3D27C: subq.w #1,objoff_2A(a0) beq.s + jsrto (ObjectMove).l, JmpTo26_ObjectMove bsr.w loc_3D416 lea (Ani_objC8).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== + addq.b #2,routine(a0) move.w #$3B,objoff_2A(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3D2A6: subq.w #1,objoff_2A(a0) bmi.s + bsr.w loc_3D416 jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== + move.b #2,routine(a0) move.w #$200,objoff_2A(a0) neg.w x_vel(a0) bchg #0,render_flags(a0) bchg #0,status(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3D2D4: move.b #$D7,collision_flags(a0) bsr.w Obj_GetOrientationToPlayer move.w d2,d4 addi.w #$40,d2 cmpi.w #$80,d2 bhs.w loc_3D39A addi.w #$40,d3 cmpi.w #$80,d3 bhs.w loc_3D39A bclr #3,status(a0) bne.w loc_3D386 move.b collision_property(a0),d0 beq.s BranchTo18_JmpTo39_MarkObjGone bclr #0,collision_property(a0) beq.s +++ cmpi.b #AniIDSonAni_Roll,anim(a1) bne.s loc_3D36C btst #1,status(a1) bne.s ++ bsr.w Obj_GetOrientationToPlayer btst #0,render_flags(a0) beq.s + subq.w #2,d0 + tst.w d0 bne.s loc_3D390 + bsr.s loc_3D3A4 + lea (Sidekick).w,a1 ; a1=character bclr #1,collision_property(a0) beq.s +++ cmpi.b #AniIDTailsAni_Roll,anim(a1) bne.s loc_3D36C btst #1,status(a1) bne.s ++ bsr.w Obj_GetOrientationToPlayer btst #0,render_flags(a0) beq.s + subq.w #2,d0 + tst.w d0 bne.s loc_3D390 + bsr.s loc_3D3A4 + clr.b collision_property(a0) BranchTo18_JmpTo39_MarkObjGone jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3D36C: move.b #$97,collision_flags(a0) btst #status_sec_isInvincible,status_secondary(a1) beq.s + move.b #$17,collision_flags(a0) + bset #3,status(a0) loc_3D386: move.b #1,mapping_frame(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3D390: move.b #$17,collision_flags(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3D39A: move.b objoff_2C(a0),routine(a0) jmpto (MarkObjGone).l, JmpTo39_MarkObjGone ; =========================================================================== loc_3D3A4: move.b #2,mapping_frame(a0) btst #1,status(a1) beq.s + move.b #3,mapping_frame(a0) + move.w x_pos(a0),d1 move.w y_pos(a0),d2 sub.w x_pos(a1),d1 sub.w y_pos(a1),d2 jsr (CalcAngle).l move.b (Timer_frames).w,d1 andi.w #3,d1 add.w d1,d0 jsr (CalcSine).l muls.w #-$700,d1 asr.l #8,d1 move.w d1,x_vel(a1) muls.w #-$700,d0 asr.l #8,d0 move.w d0,y_vel(a1) bset #1,status(a1) bclr #4,status(a1) bclr #5,status(a1) clr.b jumping(a1) move.w #SndID_Bumper,d0 jsr (PlaySound).l rts ; =========================================================================== ; unused rts ; =========================================================================== loc_3D416: bsr.w Obj_GetOrientationToPlayer addi.w #$40,d2 cmpi.w #$80,d2 bhs.s + ; rts addi.w #$40,d3 cmpi.w #$80,d3 bhs.s + ; rts move.b routine(a0),objoff_2C(a0) move.b #6,routine(a0) clr.b mapping_frame(a0) + rts ; =========================================================================== ; off_3D440: ObjC8_SubObjData: subObjData ObjC8_MapUnc_3D450,make_art_tile(ArtTile_ArtNem_Crawl,0,1),4,3,$10,$D7 ; animation script ; off_3D44A: Ani_objC8: offsetTable offsetTableEntry.w + ; 0 + dc.b $13, 0, 1,$FF even ; ---------------------------------------------------------------------------- ; sprite mappings ; Crawl CNZ ; ---------------------------------------------------------------------------- ObjC8_MapUnc_3D450: BINCLUDE "mappings/sprite/objC8.bin" ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object C7 - Eggrobo (final boss) from Death Egg ; ---------------------------------------------------------------------------- ; Sprite_3D4C8: ObjC7: moveq #0,d0 move.b routine(a0),d0 move.w ObjC7_Index(pc,d0.w),d1 jmp ObjC7_Index(pc,d1.w) ; =========================================================================== ; off_3D4D6: ObjC7_Index: offsetTable offsetTableEntry.w ObjC7_Init ; 0 offsetTableEntry.w ObjC7_Body ; 2 offsetTableEntry.w ObjC7_Shoulder ; 4 offsetTableEntry.w ObjC7_FrontLowerLeg ; 6 offsetTableEntry.w ObjC7_FrontForearm ; 8 offsetTableEntry.w ObjC7_Arm ; $A offsetTableEntry.w ObjC7_FrontThigh ; $C offsetTableEntry.w ObjC7_Head ; $E offsetTableEntry.w ObjC7_Jet ; $10 offsetTableEntry.w ObjC7_BackLowerLeg ; $12 offsetTableEntry.w ObjC7_BackForearm ; $14 offsetTableEntry.w ObjC7_BackThigh ; $16 offsetTableEntry.w ObjC7_TargettingSensor ; $18 offsetTableEntry.w ObjC7_TargettingLock ; $1A offsetTableEntry.w ObjC7_EggmanBomb ; $1C offsetTableEntry.w ObjC7_FallingPieces ; $1E offsetTableEntry.w ObjC7_SetupEnding ; $20 ; =========================================================================== ; loc_3D4F8: ObjC7_Init: lea ObjC7_SubObjData(pc),a1 bsr.w LoadSubObject_Part3 move.b subtype(a0),routine(a0) rts ; =========================================================================== ;loc_3D508 ObjC7_Body: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3D51A(pc,d0.w),d1 jsr off_3D51A(pc,d1.w) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== off_3D51A: offsetTable offsetTableEntry.w loc_3D52A ; 0 offsetTableEntry.w loc_3D5A8 ; 2 offsetTableEntry.w loc_3D5C2 ; 4 offsetTableEntry.w loc_3D5EA ; 6 offsetTableEntry.w loc_3D62E ; 8 offsetTableEntry.w loc_3D640 ; $A offsetTableEntry.w loc_3D684 ; $C offsetTableEntry.w loc_3D8D2 ; $E ; =========================================================================== loc_3D52A: addq.b #2,routine_secondary(a0) move.b #3,mapping_frame(a0) move.b #5,priority(a0) lea (ChildObjC7_Shoulder).l,a2 bsr.w LoadChildObject lea (ChildObjC7_FrontForearm).l,a2 bsr.w LoadChildObject lea (ChildObjC7_FrontLowerLeg).l,a2 bsr.w LoadChildObject lea (ChildObjC7_Arm).l,a2 bsr.w LoadChildObject lea (ChildObjC7_FrontThigh).l,a2 bsr.w LoadChildObject lea (ChildObjC7_Head).l,a2 bsr.w LoadChildObject lea (ChildObjC7_Jet).l,a2 bsr.w LoadChildObject lea (ChildObjC7_BackLowerLeg).l,a2 bsr.w LoadChildObject lea (ChildObjC7_BackForearm).l,a2 bsr.w LoadChildObject lea (ChildObjC7_BackThigh).l,a2 bsr.w LoadChildObject lea (ObjC7_ChildDeltas).l,a1 bra.w ObjC7_PositionChildren ; =========================================================================== loc_3D5A8: btst #2,status(a0) bne.s + rts ; --------------------------------------------------------------------------- + addq.b #2,routine_secondary(a0) move.b #$3C,anim_frame_duration(a0) moveq #MusID_FadeOut,d0 jmpto (PlaySound).l, JmpTo12_PlaySound ; =========================================================================== loc_3D5C2: subq.b #1,anim_frame_duration(a0) bmi.s + rts ; --------------------------------------------------------------------------- + addq.b #2,routine_secondary(a0) move.b #$79,anim_frame_duration(a0) move.w #-$100,y_vel(a0) movea.w objoff_38(a0),a1 ; a1=object move.b #4,routine_secondary(a1) moveq #MusID_EndBoss,d0 jmpto (PlayMusic).l, JmpTo5_PlayMusic ; =========================================================================== loc_3D5EA: subq.b #1,anim_frame_duration(a0) beq.s + moveq #SndID_Rumbling,d0 jsrto (PlaySound).l, JmpTo12_PlaySound jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (ObjC7_ChildDeltas).l,a1 bra.w ObjC7_PositionChildren ; --------------------------------------------------------------------------- + addq.b #2,routine_secondary(a0) clr.w y_vel(a0) move.b #$1F,anim_frame_duration(a0) move.b #$16,collision_flags(a0) move.b #$C,collision_property(a0) bsr.w ObjC7_InitCollision movea.w objoff_38(a0),a1 ; a1=object move.b #6,routine_secondary(a1) rts ; =========================================================================== loc_3D62E: bsr.w ObjC7_CheckHit subq.b #1,anim_frame_duration(a0) bmi.s + rts ; --------------------------------------------------------------------------- + addq.b #2,routine_secondary(a0) rts ; =========================================================================== loc_3D640: bsr.w ObjC7_CheckHit addq.b #2,routine_secondary(a0) move.b #$20,anim_frame_duration(a0) move.b angle(a0),d0 addq.b #1,d0 move.b d0,angle(a0) andi.w #3,d0 move.b byte_3D680(pc,d0.w),d0 move.b d0,anim(a0) clr.b next_anim(a0) cmpi.b #2,d0 bne.s + ; rts movea.w objoff_38(a0),a1 ; a1=object move.b #4,routine_secondary(a1) move.b #2,anim(a1) + rts ; =========================================================================== byte_3D680: dc.b 2 dc.b 0 ; 1 dc.b 2 ; 2 dc.b 4 ; 3 ; =========================================================================== loc_3D684: bsr.w ObjC7_CheckHit moveq #0,d0 move.b anim(a0),d0 move.w off_3D696(pc,d0.w),d1 jmp off_3D696(pc,d1.w) ; =========================================================================== off_3D696: offsetTable offsetTableEntry.w loc_3D6AA ; 0 offsetTableEntry.w loc_3D702 ; 2 offsetTableEntry.w loc_3D83C ; 4 ; =========================================================================== subq.b #1,anim_frame_duration(a0) bmi.s + rts ; --------------------------------------------------------------------------- + addq.b #2,anim(a0) rts ; =========================================================================== loc_3D6AA: moveq #0,d0 move.b next_anim(a0),d0 move.w off_3D6B8(pc,d0.w),d1 jmp off_3D6B8(pc,d1.w) ; =========================================================================== off_3D6B8: offsetTable offsetTableEntry.w loc_3D6C0 ; 0 offsetTableEntry.w loc_3D6CE ; 2 offsetTableEntry.w loc_3D6C0 ; 4 offsetTableEntry.w loc_3D6E8 ; 6 ; =========================================================================== loc_3D6C0: subq.b #1,anim_frame_duration(a0) bmi.s + rts ; --------------------------------------------------------------------------- + addq.b #2,next_anim(a0) rts ; =========================================================================== loc_3D6CE: lea (off_3E40C).l,a1 bsr.w loc_3E1AA bne.s + rts ; --------------------------------------------------------------------------- + addq.b #2,next_anim(a0) move.b #$40,anim_frame_duration(a0) rts ; =========================================================================== loc_3D6E8: lea (off_3E42C).l,a1 bsr.w loc_3E1AA bne.s + rts ; --------------------------------------------------------------------------- + subq.b #2,routine_secondary(a0) move.b #$40,anim_frame_duration(a0) rts ; =========================================================================== loc_3D702: moveq #0,d0 move.b next_anim(a0),d0 move.w off_3D710(pc,d0.w),d1 jmp off_3D710(pc,d1.w) ; =========================================================================== off_3D710: offsetTable offsetTableEntry.w loc_3D6C0 ; 0 offsetTableEntry.w loc_3D720 ; 2 offsetTableEntry.w loc_3D744 ; 4 offsetTableEntry.w loc_3D6C0 ; 6 offsetTableEntry.w loc_3D784 ; 8 offsetTableEntry.w loc_3D7B8 ; $A offsetTableEntry.w loc_3D7F0 ; $C offsetTableEntry.w loc_3D82E ; $C ; =========================================================================== loc_3D720: lea (off_3E3D0).l,a1 bsr.w loc_3E1AA bne.s + rts ; --------------------------------------------------------------------------- + addq.b #2,next_anim(a0) move.b #$80,anim_frame_duration(a0) clr.w x_vel(a0) move.w #-$200,y_vel(a0) rts ; =========================================================================== loc_3D744: subq.b #1,anim_frame_duration(a0) bmi.s ++ move.b (Vint_runcount+3).w,d0 andi.b #$1F,d0 bne.s + moveq #SndID_Fire,d0 jsrto (PlaySoundLocal).l, JmpTo_PlaySoundLocal + jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (ObjC7_ChildDeltas).l,a1 bra.w ObjC7_PositionChildren ; --------------------------------------------------------------------------- + addq.b #2,next_anim(a0) clr.w y_vel(a0) lea (ChildObjC7_TargettingSensor).l,a2 bsr.w LoadChildObject clr.w x_vel(a0) clr.w objoff_28(a0) rts ; =========================================================================== loc_3D784: move.w objoff_28(a0),d0 bne.s + rts ; --------------------------------------------------------------------------- + addq.b #2,next_anim(a0) move.w d0,x_pos(a0) bclr #0,render_flags(a0) cmpi.w #$780,d0 bhs.s + bset #0,render_flags(a0) + bsr.w loc_3E168 move.w #$800,y_vel(a0) move.b #$20,anim_frame_duration(a0) rts ; =========================================================================== loc_3D7B8: subq.b #1,anim_frame_duration(a0) bmi.s + jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (ObjC7_ChildDeltas).l,a1 bra.w ObjC7_PositionChildren ; --------------------------------------------------------------------------- + addq.b #2,next_anim(a0) clr.w y_vel(a0) move.b #1,(Screen_Shaking_Flag).w move.w #$40,(DEZ_Shake_Timer).w movea.w objoff_38(a0),a1 ; a1=object move.b #6,routine_secondary(a1) moveq #SndID_Smash,d0 jmpto (PlaySound).l, JmpTo12_PlaySound ; =========================================================================== loc_3D7F0: lea (off_3E30A).l,a1 bsr.w loc_3E1AA bne.s + rts ; --------------------------------------------------------------------------- + lea (ObjC7_ChildDeltas).l,a1 bsr.w ObjC7_PositionChildren bsr.w Obj_GetOrientationToPlayer btst #0,render_flags(a0) beq.s + subq.w #2,d0 + tst.w d0 bne.s + subq.b #2,routine_secondary(a0) rts ; --------------------------------------------------------------------------- + addq.b #2,next_anim(a0) move.b #$60,anim_frame_duration(a0) bra.w CreateEggmanBombs ; =========================================================================== loc_3D82E: subq.b #1,anim_frame_duration(a0) bmi.s + rts ; --------------------------------------------------------------------------- + subq.b #2,routine_secondary(a0) rts ; =========================================================================== loc_3D83C: moveq #0,d0 move.b next_anim(a0),d0 move.w off_3D84A(pc,d0.w),d1 jmp off_3D84A(pc,d1.w) ; =========================================================================== off_3D84A: offsetTable offsetTableEntry.w loc_3D6C0 ; 0 offsetTableEntry.w loc_3D856 ; 2 offsetTableEntry.w loc_3D6C0 ; 4 offsetTableEntry.w loc_3D89E ; 6 offsetTableEntry.w loc_3D6C0 ; 8 offsetTableEntry.w loc_3D8B8 ; $A ; =========================================================================== loc_3D856: bset #6,status(a0) lea (off_3E2F6).l,a1 bsr.w loc_3E1AA bne.s + rts ; --------------------------------------------------------------------------- + bsr.w Obj_GetOrientationToPlayer btst #0,render_flags(a0) beq.s + subq.w #2,d0 + tst.w d0 bne.s + addq.b #2,next_anim(a0) move.b #$40,anim_frame_duration(a0) bset #4,status(a0) rts ; --------------------------------------------------------------------------- + move.b #8,next_anim(a0) move.b #$20,anim_frame_duration(a0) bra.w CreateEggmanBombs ; =========================================================================== loc_3D89E: subq.b #1,anim_frame_duration(a0) bmi.s + rts ; --------------------------------------------------------------------------- + addq.b #2,next_anim(a0) bset #5,status(a0) move.b #$40,anim_frame_duration(a0) rts ; =========================================================================== loc_3D8B8: lea (off_3E300).l,a1 bsr.w loc_3E1AA bne.s + rts ; --------------------------------------------------------------------------- + subq.b #2,routine_secondary(a0) bclr #6,status(a0) rts ; =========================================================================== loc_3D8D2: moveq #0,d0 move.b anim(a0),d0 move.w off_3D8E0(pc,d0.w),d1 jmp off_3D8E0(pc,d1.w) ; =========================================================================== off_3D8E0: offsetTable offsetTableEntry.w loc_3D8E6 ; 0 offsetTableEntry.w loc_3D922 ; 2 offsetTableEntry.w loc_3D93C ; 4 ; =========================================================================== loc_3D8E6: jsrto (Boss_LoadExplosion).l, JmpTo_Boss_LoadExplosion jsrto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall move.w y_pos(a0),d0 cmpi.w #$15C,d0 bhs.s + rts ; --------------------------------------------------------------------------- + move.w #$15C,y_pos(a0) move.w y_vel(a0),d0 bmi.s + lsr.w #2,d0 cmpi.w #$100,d0 blo.s + neg.w d0 move.w d0,y_vel(a0) rts ; --------------------------------------------------------------------------- + addq.b #2,anim(a0) move.b #$40,anim_frame_duration(a0) rts ; =========================================================================== loc_3D922: subq.b #1,anim_frame_duration(a0) bmi.s + jmpto (Boss_LoadExplosion).l, JmpTo_Boss_LoadExplosion ; --------------------------------------------------------------------------- + addq.b #2,anim(a0) st (Control_Locked).w move.w #$1000,(Camera_Max_X_pos).w rts ; =========================================================================== loc_3D93C: move.w #(button_right_mask<<8)|button_right_mask,(Ctrl_1_Logical).w cmpi.w #$840,(Camera_X_pos).w bhs.s + rts ; --------------------------------------------------------------------------- + move.b #$20,routine(a0) clr.b routine_secondary(a0) move.w #$20,objoff_2A(a0) move.b #1,(Screen_Shaking_Flag).w move.w #$1000,(DEZ_Shake_Timer).w movea.w objoff_36(a0),a1 ; a1=object jmpto (DeleteObject2).l, JmpTo6_DeleteObject2 ; =========================================================================== ;loc_3D970 ObjC7_SetupEnding: move.b (Vint_runcount+3).w,d0 andi.b #$1F,d0 bne.s + moveq #SndID_Rumbling2,d0 jsrto (PlaySound).l, JmpTo12_PlaySound subq.w #1,objoff_2A(a0) + lea (MainCharacter).w,a1 ; a1=character move.w x_pos(a1),d0 sub.w objoff_2A(a0),d0 move.w d0,x_pos(a0) move.w y_pos(a1),y_pos(a0) bsr.w loc_3DFBA moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3D9AC(pc,d0.w),d1 jmp off_3D9AC(pc,d1.w) ; =========================================================================== off_3D9AC: offsetTable offsetTableEntry.w loc_3D9B0 ; 0 offsetTableEntry.w loc_3D9D6 ; 2 ; =========================================================================== loc_3D9B0: lea (MainCharacter).w,a1 ; a1=character cmpi.w #$EC0,x_pos(a1) bhs.s loc_3D9BE rts ; =========================================================================== loc_3D9BE: addq.b #2,routine_secondary(a0) move.w #$3F,(Palette_fade_range).w move.b #$16,anim_frame_duration(a0) move.w #$7FFF,(PalCycle_Timer).w rts ; =========================================================================== loc_3D9D6: subq.b #1,anim_frame_duration(a0) beq.w + movea.l a0,a1 lea (Normal_palette).w,a0 moveq #$3F,d0 - jsrto (Pal_FadeToWhite.UpdateColour).l, JmpTo_Pal_FadeToWhite_UpdateColour dbf d0,- movea.l a1,a0 rts ; --------------------------------------------------------------------------- + move.l #$EEE0EEE,d0 lea (Normal_palette).w,a1 moveq #$1F,d6 - move.l d0,(a1)+ dbf d6,- moveq #MusID_FadeOut,d0 jsrto (PlaySound).l, JmpTo12_PlaySound move.b #GameModeID_EndingSequence,(Game_Mode).w ; => EndingSequence bra.w JmpTo65_DeleteObject ; =========================================================================== ObjC7_Shoulder: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3DA34(pc,d0.w),d1 jsr off_3DA34(pc,d1.w) lea byte_3DA38(pc),a1 bsr.w loc_3E282 tst.b (a0) beq.w return_37A48 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== off_3DA34: offsetTable offsetTableEntry.w loc_3DA3C ; 0 offsetTableEntry.w return_3DA48 ; 2 ; =========================================================================== byte_3DA38: dc.b 0 dc.b $C ; 1 dc.b $FF ; 2 dc.b $EC ; 3 ; =========================================================================== loc_3DA3C: addq.b #2,routine_secondary(a0) move.b #4,mapping_frame(a0) rts ; =========================================================================== return_3DA48: rts ; =========================================================================== ;loc_3DA4A ObjC7_FrontLowerLeg: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3DA62(pc,d0.w),d1 jsr off_3DA62(pc,d1.w) tst.b (a0) beq.w return_37A48 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== off_3DA62: offsetTable offsetTableEntry.w loc_3DA66 ; 0 offsetTableEntry.w return_3DA72 ; 2 ; =========================================================================== loc_3DA66: addq.b #2,routine_secondary(a0) move.b #$B,mapping_frame(a0) rts ; =========================================================================== return_3DA72: rts ; =========================================================================== ;loc_3DA74 ObjC7_FrontForearm: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3DA96(pc,d0.w),d1 jsr off_3DA96(pc,d1.w) tst.b (a0) beq.w return_37A48 btst #6,status(a0) bne.w return_37A48 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== off_3DA96: offsetTable offsetTableEntry.w loc_3DAA0 ; 0 offsetTableEntry.w loc_3DAAC ; 2 offsetTableEntry.w loc_3DACC ; 4 offsetTableEntry.w loc_3DB32 ; 6 offsetTableEntry.w loc_3DB5A ; 8 ; =========================================================================== loc_3DAA0: addq.b #2,routine_secondary(a0) move.b #6,mapping_frame(a0) rts ; =========================================================================== loc_3DAAC: movea.w objoff_2C(a0),a1 ; a1=object bclr #4,status(a1) bne.s + rts ; --------------------------------------------------------------------------- + addq.b #2,routine_secondary(a0) move.w #$10,objoff_2A(a0) move.w y_pos(a0),objoff_2E(a0) rts ; =========================================================================== loc_3DACC: subq.w #1,objoff_2A(a0) bmi.s + addi.w #$20,y_vel(a0) jmpto (ObjectMove).l, JmpTo26_ObjectMove ; --------------------------------------------------------------------------- + addq.b #2,routine_secondary(a0) move.w #$20,objoff_2A(a0) bsr.w Obj_GetOrientationToPlayer abs.w d2 cmpi.w #$100,d2 blo.s + move.w #$FF,d2 + andi.w #$C0,d2 lsr.w #5,d2 move.w word_3DB2A(pc,d2.w),d2 tst.w d1 bne.s + neg.w d2 + move.w d2,y_vel(a0) move.w #$800,d2 movea.w objoff_2C(a0),a1 ; a1=object btst #0,render_flags(a0) bne.s + neg.w d2 + move.w d2,x_vel(a0) moveq #SndID_SpindashRelease,d0 jmpto (PlaySound).l, JmpTo12_PlaySound ; =========================================================================== word_3DB2A: dc.w $200 dc.w $100 ; 1 dc.w $80 ; 2 dc.w 0 ; 3 ; =========================================================================== loc_3DB32: subq.w #1,objoff_2A(a0) bmi.s + jmpto (ObjectMove).l, JmpTo26_ObjectMove ; --------------------------------------------------------------------------- + addq.b #2,routine_secondary(a0) neg.w x_vel(a0) move.w #$20,objoff_2A(a0) move.w objoff_2E(a0),d0 sub.w y_pos(a0),d0 asl.w #3,d0 move.w d0,y_vel(a0) rts ; =========================================================================== loc_3DB5A: subq.w #1,objoff_2A(a0) bmi.s + jmpto (ObjectMove).l, JmpTo26_ObjectMove ; --------------------------------------------------------------------------- + move.b #2,routine_secondary(a0) clr.w x_vel(a0) clr.w y_vel(a0) rts ; =========================================================================== ;loc_3DB74 ObjC7_Arm: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3DB8C(pc,d0.w),d1 jsr off_3DB8C(pc,d1.w) tst.b (a0) beq.w return_37A48 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== off_3DB8C: offsetTable offsetTableEntry.w loc_3DB90 ; 0 offsetTableEntry.w return_3DB9C ; 2 ; =========================================================================== loc_3DB90: addq.b #2,routine_secondary(a0) move.b #5,mapping_frame(a0) rts ; =========================================================================== return_3DB9C: rts ; =========================================================================== ;loc_3DB9E ObjC7_FrontThigh: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3DBB6(pc,d0.w),d1 jsr off_3DBB6(pc,d1.w) tst.b (a0) beq.w return_37A48 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== off_3DBB6: offsetTable offsetTableEntry.w loc_3DBBA ; 0 offsetTableEntry.w return_3DBC6 ; 2 ; =========================================================================== loc_3DBBA: addq.b #2,routine_secondary(a0) move.b #$A,mapping_frame(a0) rts ; =========================================================================== return_3DBC6: rts ; =========================================================================== ;loc_3DBC8 ObjC7_Head: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3DBE8(pc,d0.w),d1 jsr off_3DBE8(pc,d1.w) lea byte_3DBF2(pc),a1 bsr.w loc_3E282 tst.b (a0) beq.w return_37A48 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== off_3DBE8: offsetTable offsetTableEntry.w loc_3DBF6 ; 0 offsetTableEntry.w loc_3DC02 ; 2 offsetTableEntry.w loc_3DC1C ; 4 offsetTableEntry.w loc_3DC2A ; 6 offsetTableEntry.w loc_3DC46 ; 8 ; =========================================================================== byte_3DBF2: dc.b 0 dc.b 0 ; 1 dc.b $FF ; 2 dc.b $CC ; 3 ; =========================================================================== loc_3DBF6: addq.b #2,routine_secondary(a0) move.b #$15,mapping_frame(a0) rts ; =========================================================================== loc_3DC02: movea.w (DEZ_Eggman).w,a1 btst #3,$22(a1) bne.s + rts ; --------------------------------------------------------------------------- + addq.b #2,routine_secondary(a0) move.w #$40,objoff_2A(a0) rts ; =========================================================================== loc_3DC1C: lea (Ani_objC7_a).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3DC2A: subq.w #1,objoff_2A(a0) bmi.s + jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; --------------------------------------------------------------------------- + addq.b #2,routine_secondary(a0) movea.w objoff_2C(a0),a1 ; a1=object bset #2,status(a1) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3DC46: move.b #-1,collision_property(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ;loc_3DC50 ObjC7_Jet: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3DC66(pc,d0.w),d1 jsr off_3DC66(pc,d1.w) lea byte_3DC70(pc),a1 bra.w loc_3E282 ; =========================================================================== off_3DC66: offsetTable offsetTableEntry.w loc_3DC74 offsetTableEntry.w loc_3DC80 offsetTableEntry.w loc_3DC86 offsetTableEntry.w loc_3DC94 offsetTableEntry.w loc_3DC80 ; =========================================================================== byte_3DC70: dc.b 0 dc.b $38 ; 1 dc.b 0 ; 2 dc.b $18 ; 3 ; =========================================================================== loc_3DC74: addq.b #2,routine_secondary(a0) move.b #$C,mapping_frame(a0) rts ; =========================================================================== loc_3DC80: move.b #3,anim(a0) loc_3DC86: lea (Ani_objC7_b).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3DC94: move.b #1,anim(a0) bra.s loc_3DC86 ; =========================================================================== ;loc_3DC9C ObjC7_BackLowerLeg: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3DCB4(pc,d0.w),d1 jsr off_3DCB4(pc,d1.w) tst.b (a0) beq.w return_37A48 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== off_3DCB4: offsetTable offsetTableEntry.w loc_3DCB8 ; 0 offsetTableEntry.w return_3DCCA ; 2 ; =========================================================================== loc_3DCB8: addq.b #2,routine_secondary(a0) move.b #$B,mapping_frame(a0) move.b #5,priority(a0) rts ; =========================================================================== return_3DCCA: rts ; =========================================================================== ;loc_3DCCC ObjC7_BackForearm: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3DCE4(pc,d0.w),d1 jsr off_3DCE4(pc,d1.w) tst.b (a0) beq.w return_37A48 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== off_3DCE4: offsetTable offsetTableEntry.w loc_3DCEE ; 0 offsetTableEntry.w loc_3DD00 ; 2 offsetTableEntry.w loc_3DACC ; 4 offsetTableEntry.w loc_3DB32 ; 6 offsetTableEntry.w loc_3DB5A ; 8 ; =========================================================================== loc_3DCEE: addq.b #2,routine_secondary(a0) move.b #6,mapping_frame(a0) move.b #5,priority(a0) rts ; =========================================================================== loc_3DD00: movea.w objoff_2C(a0),a1 ; a1=object bclr #5,status(a1) bne.s + rts ; --------------------------------------------------------------------------- + addq.b #2,routine_secondary(a0) move.w #$10,objoff_2A(a0) move.w y_pos(a0),objoff_2E(a0) rts ; =========================================================================== ;loc_3DD20 ObjC7_BackThigh: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3DD38(pc,d0.w),d1 jsr off_3DD38(pc,d1.w) tst.b (a0) beq.w return_37A48 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== off_3DD38: offsetTable offsetTableEntry.w loc_3DD3C ; 0 offsetTableEntry.w return_3DD4E ; 2 ; =========================================================================== loc_3DD3C: addq.b #2,routine_secondary(a0) move.b #$A,mapping_frame(a0) move.b #5,priority(a0) rts ; =========================================================================== return_3DD4E: rts ; =========================================================================== ;loc_3DD50 ObjC7_TargettingSensor: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3DD5E(pc,d0.w),d1 jmp off_3DD5E(pc,d1.w) ; =========================================================================== off_3DD5E: offsetTable offsetTableEntry.w loc_3DD64 ; 0 offsetTableEntry.w loc_3DDA6 ; 2 offsetTableEntry.w loc_3DE3C ; 4 ; =========================================================================== loc_3DD64: addq.b #2,routine_secondary(a0) move.b #$10,mapping_frame(a0) ori.w #high_priority,art_tile(a0) move.b #1,priority(a0) move.w #$A0,objoff_2A(a0) lea (MainCharacter).w,a1 ; a1=character move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) move.w x_vel(a1),objoff_30(a0) move.w y_vel(a1),objoff_32(a0) move.w #$18,angle(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3DDA6: subq.w #1,objoff_2A(a0) bmi.s loc_3DE0A lea next_object(a0),a1 ; a1=object movea.l a1,a2 move.w -(a1),y_vel(a0) move.w -(a1),x_vel(a0) moveq #2,d6 - move.l -(a1),-(a2) dbf d6,- lea (MainCharacter).w,a2 ; a2=character move.w x_vel(a2),d0 bne.s + move.w x_pos(a2),x_pos(a0) + move.w d0,(a1)+ move.w y_vel(a2),d0 bne.s + move.w y_pos(a2),y_pos(a0) + move.w d0,(a1)+ jsrto (ObjectMove).l, JmpTo26_ObjectMove lea (Ani_objC7_c).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite subq.b #1,angle(a0) bpl.s + subq.b #1,objoff_27(a0) move.b objoff_27(a0),angle(a0) moveq #SndID_Beep,d0 jsrto (PlaySound).l, JmpTo12_PlaySound + jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3DE0A: addq.b #2,routine_secondary(a0) move.w #$40,objoff_2A(a0) move.b #4,angle(a0) lea (MainCharacter).w,a1 ; a1=character move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) lea (ChildObjC7_TargettingLock).l,a2 bsr.w LoadChildObject clr.w x_vel(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3DE3C: subq.w #1,objoff_2A(a0) bmi.s loc_3DE62 lea (Ani_objC7_c).l,a1 jsrto (AnimateSprite).l, JmpTo25_AnimateSprite subq.b #1,angle(a0) bpl.s + move.b #4,angle(a0) moveq #SndID_Beep,d0 jsrto (PlaySound).l, JmpTo12_PlaySound + jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3DE62: movea.w objoff_2C(a0),a1 ; a1=object move.w x_pos(a0),objoff_28(a1) bra.w JmpTo65_DeleteObject ; =========================================================================== ;loc_3DE70 ObjC7_TargettingLock: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3DE7E(pc,d0.w),d1 jmp off_3DE7E(pc,d1.w) ; =========================================================================== off_3DE7E: offsetTable offsetTableEntry.w loc_3DE82 ; 0 offsetTableEntry.w loc_3DEA2 ; 2 ; =========================================================================== loc_3DE82: addq.b #2,routine_secondary(a0) move.b #$14,mapping_frame(a0) move.b #1,priority(a0) ori.w #high_priority,art_tile(a0) move.w #4,objoff_2A(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3DEA2: movea.w objoff_2C(a0),a1 ; a1=object tst.b (a1) beq.w JmpTo65_DeleteObject subq.w #1,objoff_2A(a0) bne.s + move.w #4,objoff_2A(a0) bchg #palette_bit_0,art_tile(a0) + jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ;loc_3DEC2 ObjC7_EggmanBomb: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3DED0(pc,d0.w),d1 jmp off_3DED0(pc,d1.w) ; =========================================================================== off_3DED0: offsetTable offsetTableEntry.w loc_3DED8 offsetTableEntry.w loc_3DF04 offsetTableEntry.w loc_3DF36 offsetTableEntry.w loc_3DF80 ; =========================================================================== loc_3DED8: addq.b #2,routine_secondary(a0) move.b #$E,mapping_frame(a0) move.b #$89,collision_flags(a0) move.b #5,priority(a0) move.b #$C,width_pixels(a0) lea byte_3DF00(pc),a1 bsr.w loc_3E282 jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== byte_3DF00: dc.b 0 dc.b $38 ; 1 dc.b $FF ; 2 dc.b $EC ; 3 ; =========================================================================== loc_3DF04: movea.w objoff_2C(a0),a1 ; a1=object btst #7,status(a1) bne.s loc_3DF4C jsrto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall move.w y_pos(a0),d0 cmpi.w #$170,d0 bhs.s + jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== + addq.b #2,routine_secondary(a0) move.w #$170,y_pos(a0) move.w #$40,objoff_2A(a0) jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3DF36: movea.w objoff_2C(a0),a1 ; a1=object btst #7,status(a1) bne.s loc_3DF4C subq.w #1,objoff_2A(a0) bmi.s loc_3DF4C jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3DF4C: move.b #6,routine_secondary(a0) move.l #Obj58_MapUnc_2D50A,mappings(a0) move.w #make_art_tile(ArtTile_ArtNem_FieryExplosion,0,0),art_tile(a0) move.b #1,priority(a0) move.b #7,anim_frame_duration(a0) move.b #0,mapping_frame(a0) move.w #SndID_BossExplosion,d0 jsr (PlaySound).l jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3DF80: subq.b #1,anim_frame_duration(a0) bpl.s + move.b #7,anim_frame_duration(a0) addq.b #1,mapping_frame(a0) cmpi.b #5,mapping_frame(a0) blo.s + clr.b collision_flags(a0) cmpi.b #7,mapping_frame(a0) beq.w JmpTo65_DeleteObject + jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== ;loc_3DFAA ObjC7_FallingPieces: subq.w #1,objoff_2A(a0) bmi.w JmpTo65_DeleteObject jsrto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall jmpto (DisplaySprite).l, JmpTo45_DisplaySprite ; =========================================================================== loc_3DFBA: jsr (SingleObjLoad).l bne.s + ; rts _move.b #ObjID_BossExplosion,id(a1) ; load obj move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) jsr (RandomNumber).l move.w d0,d1 moveq #0,d1 move.b d0,d1 lsr.b #2,d1 subi.w #$30,d1 add.w d1,x_pos(a1) lsr.w #8,d0 lsr.b #2,d0 subi.w #$30,d0 add.w d0,y_pos(a1) + rts ; =========================================================================== ;loc_3DFF8 ObjC7_CheckHit: tst.b collision_property(a0) beq.s ObjC7_Beaten tst.b objoff_2A(a0) bne.s ObjC7_Flashing tst.b collision_flags(a0) beq.s + movea.w objoff_36(a0),a1 ; a1=object tst.b collision_flags(a1) bne.s +++ ; rts clr.b collision_flags(a0) subq.b #1,collision_property(a0) beq.s ObjC7_Beaten + move.b #$3C,objoff_2A(a0) move.w #SndID_BossHit,d0 jsr (PlaySound).l ;loc_3E02E ObjC7_Flashing: lea (Normal_palette_line2+2).w,a1 moveq #0,d0 tst.w (a1) bne.s + move.w #$EEE,d0 + move.w d0,(a1) subq.b #1,objoff_2A(a0) bne.s + clr.w (Normal_palette_line2+2).w move.b #$16,collision_flags(a0) movea.w objoff_36(a0),a1 ; a1=object move.b #$2A,collision_flags(a1) + rts ; =========================================================================== ;loc_3E05A ObjC7_Beaten: moveq #100,d0 bsr.w AddPoints clr.b anim_frame_duration(a0) move.b #$E,routine_secondary(a0) bset #7,status(a0) clr.b anim(a0) clr.b collision_flags(a0) clr.w x_vel(a0) clr.w y_vel(a0) bsr.w ObjC7_RemoveCollision bsr.w ObjC7_Break movea.w objoff_38(a0),a1 ; a1=object jsrto (DeleteObject2).l, JmpTo6_DeleteObject2 addq.w #4,sp rts ; =========================================================================== ;loc_3E094 ObjC7_Break: lea (ObjC7_BreakOffsets).l,a1 lea ObjC7_BreakSpeeds(pc),a2 moveq #0,d0 moveq #ObjC7_BreakOffsets_End-ObjC7_BreakOffsets-1,d6 - move.b (a1)+,d0 movea.w (a0,d0.w),a3 ; a3=object move.b #$1E,routine(a3) clr.b routine_secondary(a3) move.w #$80,objoff_2A(a3) move.w (a2)+,x_vel(a3) move.w (a2)+,y_vel(a3) dbf d6,- rts ; =========================================================================== ;word_3E0C6 ObjC7_BreakSpeeds: dc.w $200,-$400 dc.w -$100,-$100 ; 2 dc.w $300,-$300 ; 4 dc.w -$100,-$400 ; 6 dc.w $180,-$200 ; 8 dc.w -$200,-$300 ; 10 dc.w 0,-$400 ; 12 dc.w $100,-$300 ; 14 ObjC7_BreakSpeeds_End ;byte_3E0E6 ObjC7_BreakOffsets: dc.b objoff_2C dc.b objoff_2E ; 1 dc.b objoff_30 ; 2 dc.b objoff_32 ; 3 dc.b objoff_34 ; 4 dc.b objoff_3A ; 5 dc.b objoff_3C ; 6 dc.b objoff_3E ; 7 ObjC7_BreakOffsets_End ; =========================================================================== ;loc_3E0EE ObjC7_InitCollision: lea ObjC7_ChildOffsets(pc),a1 lea ObjC7_ChildCollision(pc),a2 moveq #0,d0 moveq #ObjC7_ChildCollision_End-ObjC7_ChildCollision-1,d6 - move.b (a1)+,d0 movea.w (a0,d0.w),a3 ; a3=object move.b (a2)+,collision_flags(a3) dbf d6,- rts ; =========================================================================== ;byte_3E10A ObjC7_ChildCollision: dc.b 0 dc.b $8F ; 1 dc.b $9C ; 2 dc.b 0 ; 3 dc.b $86 ; 4 dc.b $2A ; 5 dc.b $8B ; 6 dc.b $8F ; 7 dc.b $9C ; 8 dc.b $8B ; 9 ObjC7_ChildCollision_End ;byte_3E114 ObjC7_ChildOffsets: dc.b objoff_2C dc.b objoff_2E ; 1 dc.b objoff_30 ; 2 dc.b objoff_32 ; 3 dc.b objoff_34 ; 4 dc.b objoff_36 ; 5 dc.b objoff_38 ; 6 dc.b objoff_3A ; 7 dc.b objoff_3C ; 8 dc.b objoff_3E ; 9 ObjC7_ChildOffsets_End ; =========================================================================== ;loc_3E11E ObjC7_RemoveCollision: lea ObjC7_ChildOffsets(pc),a1 moveq #0,d0 moveq #ObjC7_ChildOffsets_End-ObjC7_ChildOffsets-1,d6 - move.b (a1)+,d0 movea.w (a0,d0.w),a3 ; a3=object clr.b collision_flags(a3) dbf d6,- rts ; =========================================================================== ;loc_3E136 CreateEggmanBombs: lea EggmanBomb_InitSpeeds(pc),a3 moveq #1,d6 - lea (ChildObjC7_EggmanBomb).l,a2 bsr.w LoadChildObject move.w (a3)+,d0 btst #0,render_flags(a0) beq.s + neg.w d0 + move.w d0,x_vel(a1) move.w (a3)+,y_vel(a1) dbf d6,- rts ; =========================================================================== ;word_3E160 EggmanBomb_InitSpeeds: dc.w $60,-$800 dc.w $C0,-$A00 ; =========================================================================== loc_3E168: move.b render_flags(a0),d0 andi.b #1,d0 moveq #0,d1 lea byte_3E19E(pc),a1 - move.b (a1)+,d1 beq.w return_37A48 movea.w (a0,d1.w),a2 ; a2=object move.b render_flags(a2),d2 andi.b #$FE,d2 or.b d0,d2 move.b d2,render_flags(a2) move.b status(a2),d2 andi.b #$FE,d2 or.b d0,d2 move.b d2,status(a2) bra.s - ; =========================================================================== byte_3E19E: dc.b $2C dc.b $2E ; 1 dc.b $30 ; 2 dc.b $32 ; 3 dc.b $34 ; 4 dc.b $36 ; 5 dc.b $38 ; 6 dc.b $3A ; 7 dc.b $3C ; 8 dc.b $3E ; 9 dc.b 0 ; 10 dc.b 0 ; 11 ; =========================================================================== loc_3E1AA: movea.l (a1)+,a2 moveq #0,d0 move.b anim_frame(a0),d0 move.b (a1,d0.w),d0 move.b d0,d1 moveq #0,d4 andi.w #$C0,d1 beq.s + bsr.w loc_3E23E + add.w d0,d0 adda.w (a2,d0.w),a2 move.b (a2)+,d0 move.b (a2)+,d3 move.b objoff_1F(a0),d2 addq.b #1,d2 cmp.b d3,d2 blo.s + addq.b #1,anim_frame(a0) moveq #0,d2 + move.b d2,objoff_1F(a0) moveq #0,d5 - move.b (a2)+,d5 movea.w (a0,d5.w),a3 ; a3=object tst.w d5 bne.s + movea.l a0,a3 + move.l x_pos(a3),d2 move.b (a2)+,d1 ext.w d1 asl.w #4,d1 btst #0,render_flags(a0) beq.s + neg.w d1 + tst.w d4 beq.s + neg.w d1 + ext.l d1 asl.l #8,d1 add.l d1,d2 move.l d2,x_pos(a3) move.l y_pos(a3),d3 move.b (a2)+,d1 ext.w d1 asl.w #4,d1 tst.w d4 beq.s + neg.w d1 + ext.l d1 asl.l #8,d1 add.l d1,d3 move.l d3,y_pos(a3) dbf d0,- moveq #0,d1 rts ; =========================================================================== loc_3E236: clr.b anim_frame(a0) moveq #1,d1 return_3E23C: rts ; =========================================================================== loc_3E23E: andi.b #$3F,d0 rol.b #3,d1 move.w off_3E24C-2(pc,d1.w),d1 jmp off_3E24C(pc,d1.w) ; =========================================================================== off_3E24C: offsetTable offsetTableEntry.w loc_3E252 offsetTableEntry.w loc_3E27A offsetTableEntry.w loc_3E27E ; =========================================================================== loc_3E252: tst.b objoff_1F(a0) bne.s return_3E23C move.b anim_frame(a0),d1 addq.b #1,d1 move.b (a1,d1.w),d0 jsrto (PlaySound).l, JmpTo12_PlaySound ; sound id most likely came from off_3E40C or off_3E42C addq.b #1,d1 move.b d1,anim_frame(a0) move.b (a1,d1.w),d0 move.b d0,d1 andi.b #$C0,d1 bne.s loc_3E23E rts ; =========================================================================== loc_3E27A: moveq #1,d4 rts ; =========================================================================== loc_3E27E: addq.w #4,sp bra.s loc_3E236 ; =========================================================================== loc_3E282: movea.w objoff_2C(a0),a2 ; a2=object move.w x_pos(a2),d0 move.w (a1)+,d1 btst #0,render_flags(a2) beq.s + neg.w d1 + add.w d1,d0 move.w d0,x_pos(a0) move.w y_pos(a2),d0 add.w (a1)+,d0 move.w d0,y_pos(a0) rts ; =========================================================================== ;loc_3E2A8 ObjC7_PositionChildren: moveq #0,d0 moveq #0,d6 move.b (a1)+,d6 - move.b (a1)+,d0 movea.w (a0,d0.w),a2 ; a2=object move.w x_pos(a0),d1 move.b (a1)+,d2 ext.w d2 btst #0,render_flags(a0) beq.s + neg.w d2 + add.w d2,d1 move.w d1,x_pos(a2) move.w y_pos(a0),d1 move.b (a1)+,d2 ext.w d2 add.w d2,d1 move.w d1,y_pos(a2) dbf d6,- rts ; =========================================================================== ;byte_3E2E0 ObjC7_ChildDeltas: dc.b 6 dc.b $2E ; 1 dc.b $FC ; 2 dc.b $3C ; 3 dc.b $30 ; 4 dc.b $F4 ; 5 dc.b 8 ; 6 dc.b $32 ; 7 dc.b $C ; 8 dc.b $F8 ; 9 dc.b $34 ; 10 dc.b 4 ; 11 dc.b $24 ; 12 dc.b $3A ; 13 dc.b $FC ; 14 dc.b $3C ; 15 dc.b $3C ; 16 dc.b $F4 ; 17 dc.b 8 ; 18 dc.b $3E ; 19 dc.b 4 ; 20 dc.b $24 ; 21 off_3E2F6: dc.l ObjC7_GroupAni_3E318 dc.b 0, 1, 2, 3, $FF, 0 off_3E300: dc.l ObjC7_GroupAni_3E318 dc.b 5, 6, 7, 8, $FF, 0 off_3E30A: dc.l ObjC7_GroupAni_3E318 dc.b 0, 1, 2, 3, 4, 5, 6, 7, 8, $C0 ; ----------------------------------------------------------------------------- ; Custom animation ; ----------------------------------------------------------------------------- ; must be on the same line as a label that has a corresponding _End label later c7anilistheader macro maxframe,{INTLABEL} __LABEL__ label * dc.b ((__LABEL___End - __LABEL__ - 2) / 3) - 1,maxframe endm ; macro for a animation data c7ani macro pieceOffset,deltax,deltay dc.b pieceOffset,deltax,deltay endm ObjC7_GroupAni_3E318: offsetTable ;BINCLUDE "mappings/sprite/objC7_a.bin" offsetTableEntry.w byte_3E32A offsetTableEntry.w byte_3E33E offsetTableEntry.w byte_3E352 offsetTableEntry.w byte_3E366 offsetTableEntry.w byte_3E37A offsetTableEntry.w byte_3E380 offsetTableEntry.w byte_3E394 offsetTableEntry.w byte_3E3A8 offsetTableEntry.w byte_3E3BC byte_3E32A: c7anilistheader 8 c7ani $00, $E0, $0C c7ani objoff_30, $E0, $0C c7ani objoff_32, $E0, $0C c7ani objoff_3C, $E0, $0C c7ani objoff_34, $F8, $04 c7ani objoff_3E, $F8, $04 byte_3E32A_End byte_3E33E: c7anilistheader 8 c7ani $00, $EC, $14 c7ani objoff_30, $EC, $14 c7ani objoff_32, $EC, $14 c7ani objoff_3C, $EC, $14 c7ani objoff_34, $FA, $06 c7ani objoff_3E, $FA, $06 byte_3E33E_End byte_3E352: c7anilistheader 8 c7ani $00, $F8, $14 c7ani objoff_30, $F8, $14 c7ani objoff_32, $F8, $14 c7ani objoff_3C, $F8, $14 c7ani objoff_34, $FE, $04 c7ani objoff_3E, $FE, $04 byte_3E352_End byte_3E366: c7anilistheader 8 c7ani $00, $FC, $0C c7ani objoff_30, $FC, $0C c7ani objoff_32, $FC, $0C c7ani objoff_3C, $FC, $0c c7ani objoff_34, $00, $02 c7ani objoff_3E, $00, $02 byte_3E366_End byte_3E37A: c7anilistheader 8 c7ani $00, $00, $00 byte_3E37A_End even byte_3E380: c7anilistheader 8 c7ani $00, $04, $E8 c7ani objoff_30, $04, $E8 c7ani objoff_32, $04, $E8 c7ani objoff_3C, $04, $E8 c7ani objoff_34, $02, $FA c7ani objoff_3E, $02, $FA byte_3E380_End byte_3E394: c7anilistheader 8 c7ani $00, $0C, $E8 c7ani objoff_30, $0C, $E8 c7ani objoff_32, $0C, $E8 c7ani objoff_3C, $0C, $E8 c7ani objoff_34, $04, $FC c7ani objoff_3E, $04, $FC byte_3E394_End byte_3E3A8: c7anilistheader 8 c7ani $00, $18, $F4 c7ani objoff_30, $18, $F4 c7ani objoff_32, $18, $F4 c7ani objoff_3C, $18, $F4 c7ani objoff_34, $04, $FC c7ani objoff_3E, $04, $FC byte_3E3A8_End byte_3E3BC: c7anilistheader 8 c7ani $00, $18, $FC c7ani objoff_30, $18, $FC c7ani objoff_32, $18, $FC c7ani objoff_3C, $18, $FC c7ani objoff_34, $06, $FE c7ani objoff_3E, $06, $FE byte_3E3BC_End off_3E3D0: dc.l ObjC7_GroupAni_3E3D8 dc.b 0, 1, 2, $C0 ; ----------------------------------------------------------------------------- ; Custom animation ; ----------------------------------------------------------------------------- ObjC7_GroupAni_3E3D8: offsetTable ;BINCLUDE "mappings/sprite/objC7_b.bin" offsetTableEntry.w byte_3E3DE offsetTableEntry.w byte_3E3F2 offsetTableEntry.w byte_3E3F8 byte_3E3DE: c7anilistheader $10 c7ani $00, $00, $04 c7ani objoff_30, $00, $04 c7ani objoff_32, $00, $04 c7ani objoff_3C, $00, $04 c7ani objoff_34, $00, $04 c7ani objoff_3E, $00, $04 byte_3E3DE_End byte_3E3F2: c7anilistheader $10 c7ani $00, $00, $00 byte_3E3F2_End even byte_3E3F8: c7anilistheader 8 c7ani $00, $00, $F8 c7ani objoff_30, $00, $F8 c7ani objoff_32, $00, $F8 c7ani objoff_3C, $00, $F8 c7ani objoff_34, $00, $F8 c7ani objoff_3E, $00, $F8 byte_3E3F8_End off_3E40C: dc.l ObjC7_GroupAni_3E438 dc.b 0, 1, 2, 3, $40, SndID_Hammer dc.b 4, 5, 6, 7, 8, $40, SndID_Hammer dc.b 9, $A, 1, 2, 3, $40, SndID_Hammer dc.b 4, 5, 6, 7, 8, $40, SndID_Hammer, $C0 off_3E42C: dc.l ObjC7_GroupAni_3E438 dc.b $88, $87, $86, $85, $B, $40, SndID_Hammer, $C0 ; ----------------------------------------------------------------------------- ; Custom animation ; ----------------------------------------------------------------------------- ObjC7_GroupAni_3E438: offsetTable ;BINCLUDE "mappings/sprite/objC7_c.bin" offsetTableEntry.w byte_3E450 offsetTableEntry.w byte_3E468 offsetTableEntry.w byte_3E480 offsetTableEntry.w byte_3E494 offsetTableEntry.w byte_3E4AC offsetTableEntry.w byte_3E4C4 offsetTableEntry.w byte_3E4D6 offsetTableEntry.w byte_3E4EE offsetTableEntry.w byte_3E502 offsetTableEntry.w byte_3E51A offsetTableEntry.w byte_3E532 offsetTableEntry.w byte_3E544 byte_3E450: c7anilistheader $20 c7ani objoff_34, $F8, $F8 c7ani objoff_2E, $F8, $F8 c7ani $00, $00, $FC c7ani objoff_30, $04, $FB c7ani objoff_32, $03, $FB c7ani objoff_3C, $FC, $FB c7ani objoff_3E, $00, $FE byte_3E450_End even byte_3E468: c7anilistheader $10 c7ani objoff_34, $F0, $FC c7ani objoff_2E, $F0, $FC c7ani $00, $F0, $FC c7ani objoff_30, $F4, $FB c7ani objoff_32, $F3, $FB c7ani objoff_3C, $EC, $FB c7ani objoff_3E, $F8, $00 byte_3E468_End even byte_3E480: c7anilistheader $10 c7ani objoff_34, $F8, $04 c7ani objoff_2E, $F8, $04 c7ani $00, $F8, $04 c7ani objoff_30, $FC, $03 c7ani objoff_32, $FB, $03 c7ani objoff_3C, $F4, $03 byte_3E480_End byte_3E494: c7anilistheader $10 c7ani objoff_34, $FC, $10 c7ani objoff_2E, $F8, $10 c7ani $00, $00, $08 c7ani objoff_30, $F8, $0A c7ani objoff_32, $FA, $0A c7ani objoff_3C, $08, $0A c7ani objoff_3E, $00, $08 byte_3E494_End even byte_3E4AC: c7anilistheader $20 c7ani objoff_34, $FE, $FE c7ani $00, $F4, $FC c7ani objoff_30, $F0, $FD c7ani objoff_32, $F1, $FD c7ani objoff_3C, $F8, $FD c7ani objoff_3E, $EC, $FA c7ani objoff_3A, $E8, $FC byte_3E4AC_End even byte_3E4C4: c7anilistheader $20 c7ani objoff_3E, $F8, $FC c7ani objoff_3A, $F8, $FC c7ani objoff_30, $FC, $FF c7ani objoff_32, $FD, $FF c7ani objoff_3C, $04, $FF byte_3E4C4_End even byte_3E4D6: c7anilistheader $10 c7ani objoff_3E, $F0, $FC c7ani objoff_3A, $F0, $FC c7ani $00, $F0, $FC c7ani objoff_30, $EC, $FB c7ani objoff_32, $ED, $FB c7ani objoff_3C, $F4, $FB c7ani objoff_34, $F8, $00 byte_3E4D6_End even byte_3E4EE: c7anilistheader $10 c7ani objoff_3E, $F8, $04 c7ani objoff_3A, $F8, $04 c7ani $00, $F8, $04 c7ani objoff_30, $F4, $03 c7ani objoff_32, $F5, $03 c7ani objoff_3C, $FC, $03 byte_3E4EE_End byte_3E502: c7anilistheader $10 c7ani objoff_3E, $FC, $10 c7ani objoff_3A, $F8, $10 c7ani $00, $00, $08 c7ani objoff_30, $08, $0A c7ani objoff_32, $06, $0A c7ani objoff_3C, $F8, $0A c7ani objoff_34, $00, $08 byte_3E502_End even byte_3E51A: c7anilistheader $20 c7ani objoff_3E, $FE, $FE c7ani $00, $F4, $FC c7ani objoff_30, $F8, $FD c7ani objoff_32, $F7, $FD c7ani objoff_3C, $F1, $FD c7ani objoff_34, $EC, $FA c7ani objoff_2E, $E8, $FC byte_3E51A_End even byte_3E532: c7anilistheader $20 c7ani objoff_34, $F8, $FC c7ani objoff_2E, $F8, $FC c7ani objoff_30, $04, $FF c7ani objoff_32, $03, $FF c7ani objoff_3C, $FC, $FF byte_3E532_End even byte_3E544: c7anilistheader $10 c7ani objoff_3E, $00, $08 c7ani objoff_3A, $00, $08 c7ani $00, $00, $08 c7ani objoff_30, $00, $08 c7ani objoff_32, $00, $08 c7ani objoff_3C, $00, $08 c7ani objoff_34, $00, $08 byte_3E544_End even ;word_3E55C ChildObjC7_Shoulder: dc.w objoff_2C dc.b ObjID_Eggrobo dc.b 4 ;word_3E560 ChildObjC7_FrontLowerLeg: dc.w objoff_2E dc.b ObjID_Eggrobo dc.b 6 ;word_3E564 ChildObjC7_FrontForearm: dc.w objoff_30 dc.b ObjID_Eggrobo dc.b 8 ;word_3E568 ChildObjC7_Arm: dc.w objoff_32 dc.b ObjID_Eggrobo dc.b $A ;word_3E56C ChildObjC7_FrontThigh: dc.w objoff_34 dc.b ObjID_Eggrobo dc.b $C ;word_3E570 ChildObjC7_Head: dc.w objoff_36 dc.b ObjID_Eggrobo dc.b $E ;word_3E574 ChildObjC7_Jet: dc.w objoff_38 dc.b ObjID_Eggrobo dc.b $10 ;word_3E578 ChildObjC7_BackLowerLeg: dc.w objoff_3A dc.b ObjID_Eggrobo dc.b $12 ;word_3E57C ChildObjC7_BackForearm: dc.w objoff_3C dc.b ObjID_Eggrobo dc.b $14 ;word_3E580 ChildObjC7_BackThigh: dc.w objoff_3E dc.b ObjID_Eggrobo dc.b $16 ;word_3E584 ChildObjC7_TargettingSensor: dc.w objoff_10 dc.b ObjID_Eggrobo dc.b $18 ;word_3E588 ChildObjC7_TargettingLock: dc.w objoff_10 dc.b ObjID_Eggrobo dc.b $1A ;word_3E58C ChildObjC7_EggmanBomb: dc.w objoff_10 dc.b ObjID_Eggrobo dc.b $1C ;off_3E590 ObjC7_SubObjData: subObjData ObjC7_MapUnc_3E5F8,make_art_tile(ArtTile_ArtNem_DEZBoss,0,0),4,4,$38,$00 ; animation script ; off_3E59A: Ani_objC7_a: offsetTable offsetTableEntry.w + + dc.b 7,$15,$15,$15,$15,$15,$15,$15,$15, 0, 1, 2,$FA even ; animation script ; off_3E5AA: Ani_objC7_b: offsetTable offsetTableEntry.w byte_3E5B2 offsetTableEntry.w byte_3E5B6 offsetTableEntry.w byte_3E5D0 offsetTableEntry.w byte_3E5EA byte_3E5B2: dc.b 1, $C, $D,$FF byte_3E5B6: dc.b 1, $C, $D, $C, $C, $D, $D, $C, $C, $C, $D, $D, $D, $C, $C, $C dc.b $C, $C, $D, $D, $D, $D, $D, $D,$FA, 0; 16 byte_3E5D0: dc.b 1, $D, $D, $D, $D, $D, $D, $C, $C, $C, $C, $C, $D, $D, $D, $C dc.b $C, $C, $D, $D, $C, $C, $D, $C,$FD, 0; 16 byte_3E5EA: dc.b 0, $D,$15,$FF even ; animation script ; off_3E5EE: Ani_objC7_c: offsetTable offsetTableEntry.w byte_3E5F0 byte_3E5F0: dc.b 3,$13,$12,$11,$10,$16,$FF even ; ------------------------------------------------------------------------------ ; sprite mappings ; ------------------------------------------------------------------------------ ObjC7_MapUnc_3E5F8: BINCLUDE "mappings/sprite/objC7.bin" ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to upscale graphics by a factor of 2x, based on given mappings ; data for correct positioning of tiles. ; ; This code is awfully structured and planned: whenever a 3-column sprite piece ; is scaled, it scales the next tiles that were copied to RAM as if the piece ; had 4 columns; this will then be promptly overwritten by the next piece. If ; this happens near the end of the buffer, you will get a buffer overrun. ; Moreover, when the number of rows in the sprite piece is also 3 or 4, the code ; will make an incorrect computation for the output of the next subpiece, which ; causes the output to overwrite art from the previous subpiece. Thus, this code ; fails if there is a 3x3 or a 3x4 sprite piece in the source mappings. Sadly, ; this issue is basically unfixable without rewriting the code entirely. ; ; Input: ; a1 Location of tiles to be enlarged ; a2 Destination buffer for enlarged tiles ; d0 Width-1 of sprite piece ; d1 Height-1 of sprite piece ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ;loc_3E89E Scale_2x: move.w d1,d2 ; Copy piece height-1 andi.w #1,d2 ; Want only low bit -- this is 1 for Wx2 or Wx4 pieces, 0 otherwise addq.w #1,d2 ; Make it into 2 for Wx2 or Wx4 pieces, 1 otherwise lsl.w #6,d2 ; This is now $80 (4 tiles) for Wx2 or Wx4 pieces, $40 (2 tiles) otherwise swap d2 ; Save it to high word move.w d1,d3 ; Copy piece height-1 again lsr.w #1,d3 ; This time, want high bit (1 for Wx3 or Wx4, 0 for Wx2 or Wx1) addq.w #1,d3 ; Make it into 2 for Wx3 or Wx4 pieces, 1 otherwise lsl.w #6,d3 ; This is now $80 (4 tiles) for Wx3 or Wx4 pieces, $40 (2 tiles) otherwise swap d3 ; Save it to high word bsr.w .upscale_part1 ; Scale the first line???; sets a3 = ???, a5 = ??? btst #1,d0 ; Is this a 1xH or a 2xH piece? beq.w return_37A48 ; Return if yes btst #1,d1 ; Is this a Wx3 or a Wx4 piece? bne.s .set_dest ; Branch if yes movea.l a3,a5 ; Advance to next column instead .set_dest: movea.l a5,a2 ; Set new output location .upscale_part1: movea.l a2,a4 ; Copy destination to a4 swap d2 ; Get height offset lea (a2,d2.w),a3 ; Output location for next tile swap d2 ; Save height offset again move.w d1,d5 ; Copy height-1 andi.w #1,d5 ; How many tiles we want to do-1 -- this is 1 for Wx2 or Wx4 pieces, 0 otherwise bsr.w Scale2x_SingleTile btst #1,d1 ; Are we upscaling a Wx3 or Wx4 piece? beq.s .done_cols ; Branch if not swap d2 ; Get height offset move.w d2,d4 ; Copy it to d4 swap d2 ; Save height offset again add.w d4,d4 ; This is now $100 (8 tiles) for Wx4 pieces, $80 (4 tiles) for Wx3 pieces move.w d0,d3 ; Copy piece width-1 andi.w #1,d3 ; Want only low bit -- this is 1 for 2xH or 4xH pieces, 0 otherwise lsl.w d3,d4 ; This is now: $200 (16 tiles) for 2x4 or 4x4 pieces; $100 (8 tiles) for 2x3, 4x3, 1x4 or 3x4 pieces; $80 (4 tiles) for 1x3 or 3x3 pieces adda.w d4,a4 ; Advance to this location move.w d1,d5 ; Copy height-1 lsr.w #1,d5 ; How many tiles we want to do-1 -- this is 1 for Wx4 pieces, 0 for Wx3 pieces swap d3 ; Get height offset lea (a4,d3.w),a5 ; Output location for next tile swap d3 ; Save height offset again bsr.w Scale2x_SingleTile2 .done_cols: btst #0,d0 ; Is this a 1xH or 3xH piece? bne.s .keep_upscaling ; Branch if not btst #1,d0 ; Was this a single column piece? beq.s .done ; Return if so .keep_upscaling: swap d2 ; Get height offset lea (a2,d2.w),a2 ; Output location for next tile lea (a2,d2.w),a3 ; Output location for next tile swap d2 ; Save height offset again move.w d1,d5 ; Copy height-1 andi.w #1,d5 ; How many tiles we want to do -- this is 1 for Wx2 or Wx4 pieces, 0 otherwise bsr.w Scale2x_SingleTile btst #1,d1 ; Are we upscaling a Wx3 or Wx4 piece? beq.s .done ; Branch if not move.w d1,d5 ; Copy height-1 lsr.w #1,d5 ; How many tiles we want to do-1 -- this is 1 for Wx4 or Wx3 pieces, 0 otherwise swap d3 ; Get height offset lea (a4,d3.w),a4 ; Output location for next tile lea (a4,d3.w),a5 ; Output location for next tile swap d3 ; Save height offset again bsr.w Scale2x_SingleTile2 .done: rts ; =========================================================================== ; Upscales the given tile to the pair of tiles on the output pointers. ; ; Input: ; a1 Pixel source ; d5 Number of tiles-1 to upscale ; a2 Location of output tiles for left pixels ; a3 Location of output tiles for right pixels ; Output: ; a1 Pixel source after processed tiles ; a2 Location of output tiles for left pixels after scaled tiles ; a3 Location of output tiles for right pixels after scaled tiles ;loc_3E944 Scale2x_SingleTile: moveq #7,d6 ; 8 rows per tile .loop: bsr.w Scale_2x_LeftPixels ; Upscale pixels 0-3 of current row addq.w #4,a2 ; Advance write destination by one row (8 pixels) bsr.w Scale_2x_RightPixels ; Upscale pixels 4-7 of current row addq.w #4,a3 ; Advance write destination by one row (8 pixels) dbf d6,.loop dbf d5,Scale2x_SingleTile rts ; =========================================================================== ; Upscales the given tile to the pair of tiles on the output pointers. ; ; Input: ; a1 Pixel source ; d5 Number of tiles-1 to upscale ; a4 Location of output tiles for left pixels ; a5 Location of output tiles for right pixels ; Output: ; a1 Pixel source after processed tiles ; a4 Location of output tiles for left pixels after scaled tiles ; a5 Location of output tiles for right pixels after scaled tiles ;loc_3E95C Scale2x_SingleTile2: moveq #7,d6 ; 8 rows per tile .loop: bsr.w Scale_2x_LeftPixels2 ; Upscale pixels 0-3 of current row addq.w #4,a4 ; Advance write destination by one row (8 pixels) bsr.w Scale_2x_RightPixels2 ; Upscale pixels 4-7 of current row addq.w #4,a5 ; Advance write destination by one row (8 pixels) dbf d6,.loop dbf d5,Scale2x_SingleTile2 rts ; =========================================================================== ; Upscales the leftmost 4 pixels on the current row into the corresponding two ; rows of the output tile ;loc_3E974 Scale_2x_LeftPixels: bsr.w .upscale_pixel_pair .upscale_pixel_pair: move.b (a1)+,d2 ; Read two pixels move.b d2,d3 ; Save them andi.b #$F0,d2 ; Get left pixel move.b d2,d4 ; Copy it... lsr.b #4,d4 ; ... shift it down into place... or.b d2,d4 ; ... and make it into two pixels of the same color move.b d4,(a2)+ ; Save to top tile, both on one row... move.b d4,3(a2) ; ... and on the row below andi.b #$F,d3 ; Get saved right pixel move.b d3,d4 ; Copy it... lsl.b #4,d4 ; ... shift it up into place... or.b d3,d4 ; ... and make it into two pixels of the same color move.b d4,(a2)+ ; Save to top tile, both on one row... move.b d4,3(a2) ; ... and on the row below rts ; =========================================================================== ; Upscales the rightmost 4 pixels on the current row into the corresponding two ; rows of the output tile ;loc_3E99E Scale_2x_RightPixels: bsr.w .upscale_pixel_pair .upscale_pixel_pair: move.b (a1)+,d2 ; Read two pixels move.b d2,d3 ; Save them andi.b #$F0,d2 ; Get left pixel move.b d2,d4 ; Copy it... lsr.b #4,d4 ; ... shift it down into place... or.b d2,d4 ; ... and make it into two pixels of the same color move.b d4,(a3)+ ; Save to bottom tile, both on one row... move.b d4,3(a3) ; ... and on the row below andi.b #$F,d3 ; Get saved right pixel move.b d3,d4 ; Copy it... lsl.b #4,d4 ; ... shift it up into place... or.b d3,d4 ; ... and make it into two pixels of the same color move.b d4,(a3)+ ; Save to bottom tile, both on one row... move.b d4,3(a3) ; ... and on the row below rts ; =========================================================================== ; Upscales the leftmost 4 pixels on the current row into the corresponding two ; rows of the output tile ;loc_3E9C8 Scale_2x_LeftPixels2: bsr.w .upscale_pixel_pair .upscale_pixel_pair: move.b (a1)+,d2 ; Read two pixels move.b d2,d3 ; Save them andi.b #$F0,d2 ; Get left pixel move.b d2,d4 ; Copy it... lsr.b #4,d4 ; ... shift it down into place... or.b d2,d4 ; ... and make it into two pixels of the same color move.b d4,(a4)+ ; Save to top tile, both on one row... move.b d4,3(a4) ; ... and on the row below andi.b #$F,d3 ; Get saved right pixel move.b d3,d4 ; Copy it... lsl.b #4,d4 ; ... shift it up into place... or.b d3,d4 ; ... and make it into two pixels of the same color move.b d4,(a4)+ ; Save to top tile, both on one row... move.b d4,3(a4) ; ... and on the row below rts ; =========================================================================== ; Upscales the rightmost 4 pixels on the current row into the corresponding two ; rows of the output tile ;loc_3E9F2 Scale_2x_RightPixels2: bsr.w .upscale_pixel_pair .upscale_pixel_pair: move.b (a1)+,d2 ; Read two pixels move.b d2,d3 ; Save them andi.b #$F0,d2 ; Get left pixel move.b d2,d4 ; Copy it... lsr.b #4,d4 ; ... shift it down into place... or.b d2,d4 ; ... and make it into two pixels of the same color move.b d4,(a5)+ ; Save to bottom tile, both on one row... move.b d4,3(a5) ; ... and on the row below andi.b #$F,d3 ; Get saved right pixel move.b d3,d4 ; Copy it... lsl.b #4,d4 ; ... shift it up into place... or.b d3,d4 ; ... and make it into two pixels of the same color move.b d4,(a5)+ ; Save to bottom tile, both on one row... move.b d4,3(a5) ; ... and on the row below rts ; =========================================================================== ; this data seems to be unused dc.b $12,$34,$56,$78 dc.b $12,$34,$56,$78 ; 4 dc.b $12,$34,$56,$78 ; 8 dc.b $12,$34,$56,$78 ; 12 dc.b $12,$34,$56,$78 ; 16 dc.b $12,$34,$56,$78 ; 20 dc.b $12,$34,$56,$78 ; 24 dc.b $12,$34,$56,$78 ; 28 ; =========================================================================== if ~~removeJmpTos JmpTo5_DisplaySprite3 jmp (DisplaySprite3).l JmpTo45_DisplaySprite jmp (DisplaySprite).l JmpTo65_DeleteObject jmp (DeleteObject).l JmpTo19_SingleObjLoad jmp (SingleObjLoad).l JmpTo39_MarkObjGone jmp (MarkObjGone).l JmpTo6_DeleteObject2 jmp (DeleteObject2).l JmpTo12_PlaySound jmp (PlaySound).l JmpTo25_SingleObjLoad2 jmp (SingleObjLoad2).l JmpTo25_AnimateSprite jmp (AnimateSprite).l JmpTo_PlaySoundLocal jmp (PlaySoundLocal).l JmpTo6_RandomNumber jmp (RandomNumber).l JmpTo2_MarkObjGone_P1 jmp (MarkObjGone_P1).l JmpTo_Pal_FadeToWhite_UpdateColour jmp (Pal_FadeToWhite.UpdateColour).l JmpTo_LoadTailsDynPLC_Part2 jmp (LoadTailsDynPLC_Part2).l JmpTo_LoadSonicDynPLC_Part2 jmp (LoadSonicDynPLC_Part2).l JmpTo8_MarkObjGone3 jmp (MarkObjGone3).l JmpTo64_Adjust2PArtPointer jmp (Adjust2PArtPointer).l JmpTo5_PlayMusic jmp (PlayMusic).l JmpTo_Boss_LoadExplosion jmp (Boss_LoadExplosion).l JmpTo9_PlatformObject jmp (PlatformObject).l JmpTo27_SolidObject jmp (SolidObject).l JmpTo8_ObjectMoveAndFall jmp (ObjectMoveAndFall).l ; loc_3EAC0: JmpTo26_ObjectMove jmp (ObjectMove).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 8A - Sonic Team Presents/Credits (leftover from S1) (seemingly unused) ; ---------------------------------------------------------------------------- ; Sprite_3EAC8: Obj8A: ; (screen-space obj) moveq #0,d0 move.b routine(a0),d0 move.w Obj8A_Index(pc,d0.w),d1 jmp Obj8A_Index(pc,d1.w) ; =========================================================================== ; off_3EAD6: Obj8A_Index: offsetTable offsetTableEntry.w Obj8A_Init offsetTableEntry.w Obj8A_Display ; =========================================================================== ; loc_3EADA: Obj8A_Init: addq.b #2,routine(a0) move.w #$120,x_pixel(a0) move.w #$F0,y_pixel(a0) move.l #Obj8A_MapUnc_3EB4E,mappings(a0) move.w #make_art_tile($05A0,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo65_Adjust2PArtPointer move.w (Ending_demo_number).w,d0 move.b d0,mapping_frame(a0) move.b #0,render_flags(a0) move.b #0,priority(a0) cmpi.b #GameModeID_TitleScreen,(Game_Mode).w ; title screen?? bne.s Obj8A_Display ; if not, branch move.w #make_art_tile($0300,0,0),art_tile(a0) jsrto (Adjust2PArtPointer).l, JmpTo65_Adjust2PArtPointer move.b #$A,mapping_frame(a0) tst.b ($FFFFFFD3).w beq.s Obj8A_Display cmpi.b #button_down_mask|button_B_mask|button_C_mask|button_A_mask,(Ctrl_1_Held).w bne.s Obj8A_Display move.w #$EEE,(Target_palette_line3).w move.w #$880,(Target_palette_line3+2).w jmp (DeleteObject).l ; =========================================================================== ; JmpTo46_DisplaySprite Obj8A_Display: jmp (DisplaySprite).l ; =========================================================================== ; ---------------------------------------------------------------------------- ; sprite mappings (unused?) ; ---------------------------------------------------------------------------- Obj8A_MapUnc_3EB4E: BINCLUDE "mappings/sprite/obj8A.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo65_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; =========================================================================== ; ---------------------------------------------------------------------------- ; Object 3E - Egg prison ; ---------------------------------------------------------------------------- ; Sprite_3F1E4: Obj3E: moveq #0,d0 move.b routine(a0),d0 move.w Obj3E_Index(pc,d0.w),d1 jmp Obj3E_Index(pc,d1.w) ; =========================================================================== ; off_3F1F2: Obj3E_Index: offsetTable offsetTableEntry.w loc_3F212 ; 0 offsetTableEntry.w loc_3F278 ; 2 offsetTableEntry.w loc_3F354 ; 4 offsetTableEntry.w loc_3F38E ; 6 offsetTableEntry.w loc_3F3A8 ; 8 offsetTableEntry.w loc_3F406 ; $A ; ---------------------------------------------------------------------------- ; byte_3F1FE: Obj3E_ObjLoadData: dc.b 0, 2,$20, 4, 0 dc.b $28, 4,$10, 5, 4 ; 5 dc.b $18, 6, 8, 3, 5 ; 10 dc.b 0, 8,$20, 4, 0 ; 15 ; =========================================================================== loc_3F212: movea.l a0,a1 lea objoff_38(a0),a3 lea Obj3E_ObjLoadData(pc),a2 moveq #3,d1 bra.s loc_3F228 ; =========================================================================== loc_3F220: jsrto (SingleObjLoad).l, JmpTo20_SingleObjLoad bne.s loc_3F272 move.w a1,(a3)+ loc_3F228: _move.b id(a0),id(a1) ; load obj move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w y_pos(a0),objoff_30(a1) move.l #Obj3E_MapUnc_3F436,mappings(a1) move.w #make_art_tile(ArtTile_ArtNem_Capsule,1,0),art_tile(a1) move.b #$84,render_flags(a1) moveq #0,d0 move.b (a2)+,d0 sub.w d0,y_pos(a1) move.w y_pos(a1),objoff_30(a1) move.b (a2)+,routine(a1) move.b (a2)+,width_pixels(a1) move.b (a2)+,priority(a1) move.b (a2)+,mapping_frame(a1) loc_3F272: dbf d1,loc_3F220 rts ; =========================================================================== loc_3F278: moveq #0,d0 move.b routine_secondary(a0),d0 move.w off_3F2AE(pc,d0.w),d1 jsr off_3F2AE(pc,d1.w) move.w #$2B,d1 move.w #$18,d2 move.w #$18,d3 move.w x_pos(a0),d4 jsr (SolidObject).l lea (Ani_obj3E).l,a1 jsr (AnimateSprite).l jmp (MarkObjGone).l ; =========================================================================== off_3F2AE: offsetTable offsetTableEntry.w loc_3F2B4 ; 0 offsetTableEntry.w loc_3F2FC ; 2 offsetTableEntry.w return_3F352 ; 4 ; =========================================================================== loc_3F2B4: movea.w objoff_38(a0),a1 ; a1=object tst.w objoff_32(a1) beq.s ++ ; rts movea.w objoff_3A(a0),a2 ; a2=object jsr (SingleObjLoad).l bne.s + _move.b #ObjID_Explosion,id(a1) ; load obj addq.b #2,routine(a1) move.w x_pos(a2),x_pos(a1) move.w y_pos(a2),y_pos(a1) + move.w #-$400,y_vel(a2) move.w #$800,x_vel(a2) addq.b #2,routine_secondary(a2) move.w #$1D,objoff_34(a0) addq.b #2,routine_secondary(a0) + rts ; =========================================================================== loc_3F2FC: subq.w #1,objoff_34(a0) bpl.s return_3F352 move.b #1,anim(a0) moveq #7,d6 move.w #$9A,d5 moveq #-$1C,d4 - jsr (SingleObjLoad).l bne.s + _move.b #ObjID_Animal,id(a1) ; load obj move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) add.w d4,x_pos(a1) move.b #1,objoff_38(a1) addq.w #7,d4 move.w d5,objoff_36(a1) subq.w #8,d5 dbf d6,- + movea.w objoff_3C(a0),a2 ; a2=object move.w #$B4,anim_frame_duration(a2) addq.b #2,routine_secondary(a2) addq.b #2,routine_secondary(a0) return_3F352: rts ; =========================================================================== loc_3F354: move.w #$1B,d1 move.w #8,d2 move.w #8,d3 move.w x_pos(a0),d4 jsr (SolidObject).l move.w objoff_30(a0),y_pos(a0) move.b status(a0),d0 andi.b #standing_mask,d0 beq.s + addq.w #8,y_pos(a0) clr.b (Update_HUD_timer).w move.w #1,objoff_32(a0) + jmp (MarkObjGone).l ; =========================================================================== loc_3F38E: tst.b routine_secondary(a0) beq.s + tst.b render_flags(a0) bpl.w JmpTo66_DeleteObject jsr (ObjectMoveAndFall).l + jmp (MarkObjGone).l if removeJmpTos JmpTo66_DeleteObject jmp (DeleteObject).l endif ; =========================================================================== loc_3F3A8: tst.b routine_secondary(a0) beq.s return_3F404 move.b (Vint_runcount+3).w,d0 andi.b #7,d0 bne.s loc_3F3F4 jsr (SingleObjLoad).l bne.s loc_3F3F4 _move.b #ObjID_Animal,id(a1) ; load obj move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) jsr (RandomNumber).l andi.w #$1F,d0 subq.w #6,d0 tst.w d1 bpl.s + neg.w d0 + add.w d0,x_pos(a1) move.b #1,objoff_38(a1) move.w #$C,objoff_36(a1) loc_3F3F4: subq.w #1,anim_frame_duration(a0) bne.s return_3F404 addq.b #2,routine(a0) move.w #$B4,anim_frame_duration(a0) return_3F404: rts ; =========================================================================== loc_3F406: moveq #(Dynamic_Object_RAM_End-Dynamic_Object_RAM)/object_size-1,d0 moveq #ObjID_Animal,d1 lea (Dynamic_Object_RAM).w,a1 - cmp.b id(a1),d1 beq.s + ; rts lea next_object(a1),a1 ; a1=object dbf d0,- jsr (Load_EndOfAct).l jmp (DeleteObject).l ; =========================================================================== + rts ; =========================================================================== ; animation script ; off_3F428: Ani_obj3E: offsetTable offsetTableEntry.w byte_3F42C ; 0 offsetTableEntry.w byte_3F42F ; 1 byte_3F42C: dc.b $F, 0,$FF rev02even byte_3F42F: dc.b 3, 0, 1, 2, 3,$FE, 1 even ; ---------------------------------------------------------------------------- ; sprite mappings ; ---------------------------------------------------------------------------- Obj3E_MapUnc_3F436: BINCLUDE "mappings/sprite/obj3E.bin" ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo66_DeleteObject jmp (DeleteObject).l JmpTo20_SingleObjLoad jmp (SingleObjLoad).l align 4 endif ; --------------------------------------------------------------------------- ; Object touch response subroutine - $20(a0) in the object RAM ; collides Sonic with most objects (enemies, rings, monitors...) in the level ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_3F554: TouchResponse: nop jsrto (Touch_Rings).l, JmpTo_Touch_Rings ; Bumpers in CNZ cmpi.b #casino_night_zone,(Current_Zone).w bne.s + jsrto (Check_CNZ_bumpers).l, JmpTo_Check_CNZ_bumpers + tst.b (Current_Boss_ID).w bne.w Touch_Boss move.w x_pos(a0),d2 ; load Sonic's position into d2,d3 move.w y_pos(a0),d3 subi_.w #8,d2 moveq #0,d5 move.b y_radius(a0),d5 subq.b #3,d5 sub.w d5,d3 cmpi.b #$4D,mapping_frame(a0) ; is Sonic ducking? bne.s Touch_NoDuck ; if not, branch addi.w #$C,d3 moveq #$A,d5 ; loc_3F592: Touch_NoDuck: move.w #$10,d4 add.w d5,d5 lea (Dynamic_Object_RAM).w,a1 move.w #(Dynamic_Object_RAM_End-Dynamic_Object_RAM)/object_size-1,d6 ; loc_3F5A0: Touch_Loop: move.b collision_flags(a1),d0 bne.w Touch_Width ; loc_3F5A8: Touch_NextObj: lea next_object(a1),a1 ; load obj address ; goto next object dbf d6,Touch_Loop ; repeat 6F more times moveq #0,d0 rts ; =========================================================================== ; loc_3F5B4: Touch_Height: Touch_Width: andi.w #$3F,d0 add.w d0,d0 lea Touch_Sizes(pc,d0.w),a2 moveq #0,d1 move.b (a2)+,d1 move.w x_pos(a1),d0 sub.w d1,d0 sub.w d2,d0 bcc.s loc_3F5D6 add.w d1,d1 add.w d1,d0 bcs.s Touch_Height bra.w Touch_NextObj ; =========================================================================== loc_3F5D6: cmp.w d4,d0 bhi.w Touch_NextObj ; loc_3F5DC: Touch_Width: Touch_Height: moveq #0,d1 move.b (a2)+,d1 move.w y_pos(a1),d0 sub.w d1,d0 sub.w d3,d0 bcc.s loc_3F5F6 add.w d1,d1 add.w d1,d0 bcs.w Touch_ChkValue bra.w Touch_NextObj ; =========================================================================== loc_3F5F6: cmp.w d5,d0 bhi.w Touch_NextObj bra.w Touch_ChkValue ; =========================================================================== ; collision sizes (width,height) ; byte_3F600: Touch_Sizes: dc.b 4, 4 ; 0 dc.b $14,$14 ; 1 dc.b $C,$14 ; 2 dc.b $14, $C ; 3 dc.b 4,$10 ; 4 dc.b $C,$12 ; 5 dc.b $10,$10 ; 6 - monitors dc.b 6, 6 ; 7 - rings dc.b $18, $C ; 8 dc.b $C,$10 ; 9 dc.b $10, 8 ; $A dc.b 8, 8 ; $B dc.b $14,$10 ; $C dc.b $14, 8 ; $D dc.b $E, $E ; $E dc.b $18,$18 ; $F dc.b $28,$10 ; $10 dc.b $10,$18 ; $11 dc.b 8,$10 ; $12 dc.b $20,$70 ; $13 dc.b $40,$20 ; $14 dc.b $80,$20 ; $15 dc.b $20,$20 ; $16 dc.b 8, 8 ; $17 dc.b 4, 4 ; $18 dc.b $20, 8 ; $19 dc.b $C, $C ; $1A dc.b 8, 4 ; $1B dc.b $18, 4 ; $1C dc.b $28, 4 ; $1D dc.b 4, 8 ; $1E dc.b 4,$18 ; $1F dc.b 4,$28 ; $20 dc.b 4,$10 ; $21 dc.b $18,$18 ; $22 dc.b $C,$18 ; $23 dc.b $48, 8 ; $24 dc.b $18,$28 ; $25 dc.b $10, 4 ; $26 dc.b $20, 2 ; $27 dc.b 4,$40 ; $28 dc.b $18,$80 ; $29 dc.b $20,$10 ; $2A dc.b $10,$20 ; $2B dc.b $10,$30 ; $2C dc.b $10,$40 ; $2D dc.b $10,$50 ; $2E dc.b $10, 2 ; $2F dc.b $10, 1 ; $30 dc.b 2, 8 ; $31 dc.b $20,$1C ; $32 ; =========================================================================== ; loc_3F666: Touch_Boss: lea Touch_Sizes(pc),a3 move.w x_pos(a0),d2 move.w y_pos(a0),d3 subi_.w #8,d2 moveq #0,d5 move.b y_radius(a0),d5 subq.b #3,d5 sub.w d5,d3 cmpi.b #$4D,mapping_frame(a0) bne.s + addi.w #$C,d3 moveq #$A,d5 + move.w #$10,d4 add.w d5,d5 lea (Dynamic_Object_RAM).w,a1 move.w #(Dynamic_Object_RAM_End-Dynamic_Object_RAM)/object_size-1,d6 loc_3F69C: move.b collision_flags(a1),d0 bne.s loc_3F6AE loc_3F6A2: lea next_object(a1),a1 ; a1=object dbf d6,loc_3F69C moveq #0,d0 rts ; =========================================================================== loc_3F6AE: bsr.w BossSpecificCollision andi.w #$3F,d0 beq.s loc_3F6A2 add.w d0,d0 lea (a3,d0.w),a2 moveq #0,d1 move.b (a2)+,d1 move.w x_pos(a1),d0 sub.w d1,d0 sub.w d2,d0 bcc.s loc_3F6D4 add.w d1,d1 add.w d1,d0 bcs.s loc_3F6D8 bra.s loc_3F6A2 ; =========================================================================== loc_3F6D4: cmp.w d4,d0 bhi.s loc_3F6A2 loc_3F6D8: moveq #0,d1 move.b (a2)+,d1 move.w y_pos(a1),d0 sub.w d1,d0 sub.w d3,d0 bcc.s loc_3F6EE add.w d1,d1 add.w d1,d0 bcs.s Touch_ChkValue bra.s loc_3F6A2 ; =========================================================================== loc_3F6EE: cmp.w d5,d0 bhi.s loc_3F6A2 ; loc_3F6F2: Touch_ChkValue: move.b collision_flags(a1),d1 ; load touch response number andi.b #$C0,d1 ; is touch response $40 or higher? beq.w Touch_Enemy ; if not, branch cmpi.b #$C0,d1 ; is touch response $C0 or higher? beq.w Touch_Special ; if yes, branch tst.b d1 ; is touch response $80-$BF ? bmi.w Touch_ChkHurt ; if yes, branch ; touch response is $40-$7F move.b collision_flags(a1),d0 andi.b #$3F,d0 cmpi.b #6,d0 ; is touch response $46 ? beq.s Touch_Monitor ; if yes, branch move.w (MainCharacter+invulnerable_time).w,d0 tst.w (Two_player_mode).w beq.s + move.w invulnerable_time(a0),d0 + cmpi.w #90,d0 bhs.w + move.b #4,routine(a1) ; set the object's routine counter move.w a0,parent(a1) + rts ; =========================================================================== ; loc_3F73C: Touch_Monitor: tst.w y_vel(a0) ; is Sonic moving upwards? bpl.s loc_3F768 ; if not, branch move.w y_pos(a0),d0 subi.w #$10,d0 cmp.w y_pos(a1),d0 blo.s return_3F78A neg.w y_vel(a0) ; reverse Sonic's y-motion move.w #-$180,y_vel(a1) tst.b routine_secondary(a1) bne.s return_3F78A move.b #4,routine_secondary(a1) ; set the monitor's routine counter rts ; =========================================================================== loc_3F768: cmpa.w #MainCharacter,a0 beq.s + tst.w (Two_player_mode).w beq.s return_3F78A + cmpi.b #AniIDSonAni_Roll,anim(a0) bne.s return_3F78A neg.w y_vel(a0) ; reverse Sonic's y-motion move.b #4,routine(a1) move.w a0,parent(a1) return_3F78A: rts ; =========================================================================== ; loc_3F78C: Touch_Enemy: btst #status_sec_isInvincible,status_secondary(a0) ; is Sonic invincible? bne.s + ; if yes, branch cmpi.b #AniIDSonAni_Spindash,anim(a0) beq.s + cmpi.b #AniIDSonAni_Roll,anim(a0) ; is Sonic rolling? bne.w Touch_ChkHurt ; if not, branch + btst #6,render_flags(a1) beq.s Touch_Enemy_Part2 tst.b boss_hitcount2(a1) beq.s return_3F7C6 neg.w x_vel(a0) neg.w y_vel(a0) move.b #0,collision_flags(a1) subq.b #1,boss_hitcount2(a1) return_3F7C6: rts ; --------------------------------------------------------------------------- ; loc_3F7C8: Touch_Enemy_Part2: tst.b collision_property(a1) beq.s Touch_KillEnemy neg.w x_vel(a0) neg.w y_vel(a0) move.b #0,collision_flags(a1) subq.b #1,collision_property(a1) bne.s return_3F7E8 bset #7,status(a1) return_3F7E8: rts ; =========================================================================== ; loc_3F7EA: Touch_KillEnemy: bset #7,status(a1) moveq #0,d0 move.w (Chain_Bonus_counter).w,d0 addq.w #2,(Chain_Bonus_counter).w ; add 2 to chain bonus counter cmpi.w #6,d0 blo.s loc_3F802 moveq #6,d0 loc_3F802: move.w d0,objoff_3E(a1) move.w Enemy_Points(pc,d0.w),d0 cmpi.w #$20,(Chain_Bonus_counter).w ; have 16 enemies been destroyed? blo.s loc_3F81C ; if not, branch move.w #1000,d0 ; fix bonus to 10000 points move.w #$A,objoff_3E(a1) loc_3F81C: movea.w a0,a3 bsr.w AddPoints2 _move.b #ObjID_Explosion,id(a1) ; load obj move.b #0,routine(a1) tst.w y_vel(a0) bmi.s loc_3F844 move.w y_pos(a0),d0 cmp.w y_pos(a1),d0 bhs.s loc_3F84C neg.w y_vel(a0) rts ; =========================================================================== loc_3F844: addi.w #$100,y_vel(a0) rts ; =========================================================================== loc_3F84C: subi.w #$100,y_vel(a0) rts ; =========================================================================== ; byte_3F854: Enemy_Points: dc.w 10, 20, 50, 100 ; =========================================================================== loc_3F85C: bset #7,status(a1) ; --------------------------------------------------------------------------- ; Subroutine for checking if Sonic/Tails should be hurt and hurting them if so ; note: sonic or tails must be at a0 ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_3F862: Touch_ChkHurt: btst #status_sec_isInvincible,status_secondary(a0) ; is Sonic invincible? beq.s Touch_Hurt ; if not, branch ; loc_3F86A: Touch_NoHurt: moveq #-1,d0 rts ; --------------------------------------------------------------------------- ; loc_3F86E: Touch_Hurt: nop tst.w invulnerable_time(a0) bne.s Touch_NoHurt movea.l a1,a2 ; End of function TouchResponse ; continue straight to HurtCharacter ; --------------------------------------------------------------------------- ; Hurting Sonic/Tails subroutine ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_3F878: HurtSonic: HurtCharacter: move.w (Ring_count).w,d0 cmpa.w #MainCharacter,a0 beq.s loc_3F88C tst.w (Two_player_mode).w beq.s Hurt_Sidekick move.w (Ring_count_2P).w,d0 loc_3F88C: btst #status_sec_hasShield,status_secondary(a0) bne.s Hurt_Shield tst.w d0 beq.w KillCharacter jsr (SingleObjLoad).l bne.s Hurt_Shield _move.b #ObjID_LostRings,id(a1) ; load obj move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w a0,parent(a1) ; loc_3F8B8: Hurt_Shield: bclr #status_sec_hasShield,status_secondary(a0) ; remove shield ; loc_3F8BE: Hurt_Sidekick: move.b #4,routine(a0) jsrto (Sonic_ResetOnFloor_Part2).l, JmpTo_Sonic_ResetOnFloor_Part2 bset #1,status(a0) move.w #-$400,y_vel(a0) ; make Sonic bounce away from the object move.w #-$200,x_vel(a0) btst #6,status(a0) ; underwater? beq.s Hurt_Reverse ; if not, branch move.w #-$200,y_vel(a0) ; bounce slower move.w #-$100,x_vel(a0) ; loc_3F8EE: Hurt_Reverse: move.w x_pos(a0),d0 cmp.w x_pos(a2),d0 blo.s Hurt_ChkSpikes ; if Sonic is left of the object, branch neg.w x_vel(a0) ; if Sonic is right of the object, reverse ; loc_3F8FC: Hurt_ChkSpikes: move.w #0,inertia(a0) move.b #AniIDSonAni_Hurt2,anim(a0) move.w #$78,invulnerable_time(a0) move.w #SndID_Hurt,d0 ; load normal damage sound cmpi.b #ObjID_Spikes,(a2) ; was damage caused by spikes? bne.s Hurt_Sound ; if not, branch move.w #SndID_HurtBySpikes,d0 ; load spikes damage sound ; loc_3F91C: Hurt_Sound: jsr (PlaySound).l moveq #-1,d0 rts ; =========================================================================== ; --------------------------------------------------------------------------- ; Subroutine to kill Sonic or Tails ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_3F926: KillSonic: KillCharacter: tst.w (Debug_placement_mode).w bne.s ++ clr.b status_secondary(a0) move.b #6,routine(a0) jsrto (Sonic_ResetOnFloor_Part2).l, JmpTo_Sonic_ResetOnFloor_Part2 bset #1,status(a0) move.w #-$700,y_vel(a0) move.w #0,x_vel(a0) move.w #0,inertia(a0) move.b #AniIDSonAni_Death,anim(a0) bset #high_priority_bit,art_tile(a0) move.w #SndID_Hurt,d0 cmpi.b #ObjID_Spikes,id(a2) bne.s + move.w #SndID_HurtBySpikes,d0 + jsr (PlaySound).l + moveq #-1,d0 rts ; =========================================================================== ;loc_3F976: Touch_Special: move.b collision_flags(a1),d1 andi.b #$3F,d1 cmpi.b #6,d1 beq.s loc_3FA00 cmpi.b #7,d1 beq.w loc_3FA18 cmpi.b #$B,d1 beq.s BranchTo_loc_3F85C cmpi.b #$A,d1 beq.s loc_3FA00 cmpi.b #$C,d1 beq.s loc_3F9CE cmpi.b #$14,d1 beq.s loc_3FA00 cmpi.b #$15,d1 beq.s loc_3FA00 cmpi.b #$16,d1 beq.s loc_3FA00 cmpi.b #$17,d1 beq.s loc_3FA00 cmpi.b #$18,d1 beq.s loc_3FA00 cmpi.b #$1A,d1 beq.s loc_3FA22 cmpi.b #$21,d1 beq.s loc_3FA12 rts ; =========================================================================== BranchTo_loc_3F85C bra.w loc_3F85C ; =========================================================================== loc_3F9CE: sub.w d0,d5 cmpi.w #8,d5 bhs.s BranchTo_Touch_Enemy move.w x_pos(a1),d0 subq.w #4,d0 btst #0,status(a1) beq.s loc_3F9E8 subi.w #$10,d0 loc_3F9E8: sub.w d2,d0 bcc.s loc_3F9F4 addi.w #$18,d0 bcs.s BranchTo_Touch_ChkHurt bra.s BranchTo_Touch_Enemy ; =========================================================================== loc_3F9F4: cmp.w d4,d0 bhi.s BranchTo_Touch_Enemy BranchTo_Touch_ChkHurt bra.w Touch_ChkHurt ; =========================================================================== BranchTo_Touch_Enemy bra.w Touch_Enemy ; =========================================================================== loc_3FA00: move.w a0,d1 subi.w #Object_RAM,d1 beq.s + addq.b #1,collision_property(a1) + addq.b #1,collision_property(a1) rts ; =========================================================================== loc_3FA12: addq.b #1,collision_property(a1) rts ; =========================================================================== loc_3FA18: move.b #2,collision_property(a1) bra.w Touch_Enemy ; =========================================================================== loc_3FA22: move.b #-1,collision_property(a1) bra.w Touch_Enemy ; =========================================================================== ; loc_3FA2C: BossSpecificCollision: cmpi.b #$F,d0 bne.s + ; rts moveq #0,d0 move.b (Current_Boss_ID).w,d0 beq.s + ; rts subq.w #1,d0 add.w d0,d0 move.w BossCollision_Index(pc,d0.w),d0 jmp BossCollision_Index(pc,d0.w) ; =========================================================================== + rts ; =========================================================================== ; off_3FA48: BossCollision_Index:offsetTable ; jump depending on boss ID offsetTableEntry.w BossCollision_EHZ_CPZ offsetTableEntry.w BossCollision_EHZ_CPZ offsetTableEntry.w BossCollision_HTZ offsetTableEntry.w BossCollision_ARZ offsetTableEntry.w BossCollision_MCZ offsetTableEntry.w BossCollision_CNZ offsetTableEntry.w BossCollision_MTZ offsetTableEntry.w BossCollision_OOZ offsetTableEntry.w return_3FA5E ; =========================================================================== ;loc_3FA5A: BossCollision_EHZ_CPZ: move.b collision_flags(a1),d0 return_3FA5E: rts ; =========================================================================== ;loc_3FA60: BossCollision_HTZ: tst.b (Boss_CollisionRoutine).w bne.s + rts ; --------------------------------------------------------------------------- + move.w d7,-(sp) moveq #0,d1 move.b objoff_15(a1),d1 subq.b #2,d1 cmpi.b #7,d1 bgt.s loc_3FAA8 move.w d1,d7 add.w d7,d7 move.w x_pos(a1),d0 btst #0,render_flags(a1) beq.s loc_3FA8E add.w word_3FAB0(pc,d7.w),d0 bra.s loc_3FA92 ; =========================================================================== loc_3FA8E: sub.w word_3FAB0(pc,d7.w),d0 loc_3FA92: move.b byte_3FAC0(pc,d1.w),d1 ori.l #$40000,d1 move.w y_pos(a1),d7 subi.w #$1C,d7 bsr.w Boss_DoCollision loc_3FAA8: move.w (sp)+,d7 move.b collision_flags(a1),d0 rts ; =========================================================================== word_3FAB0: dc.w $1C dc.w $20 ; 1 dc.w $28 ; 2 dc.w $34 ; 3 dc.w $3C ; 4 dc.w $44 ; 5 dc.w $60 ; 6 dc.w $70 ; 7 byte_3FAC0: dc.b 4 dc.b 4 ; 1 dc.b 8 ; 2 dc.b $C ; 3 dc.b $14 ; 4 dc.b $1C ; 5 dc.b $24 ; 6 dc.b 8 ; 7 ; =========================================================================== ;loc_3FAC8: BossCollision_ARZ: move.w d7,-(sp) move.w x_pos(a1),d0 move.w y_pos(a1),d7 tst.b (Boss_CollisionRoutine).w beq.s ++ addi_.w #4,d7 subi.w #$50,d0 btst #0,render_flags(a1) beq.s + addi.w #$A0,d0 + move.l #$140010,d1 bsr.w Boss_DoCollision + move.w (sp)+,d7 move.b collision_flags(a1),d0 rts ; =========================================================================== ;loc_3FAFE: BossCollision_MCZ: sf boss_hurt_sonic(a1) cmpi.b #1,(Boss_CollisionRoutine).w blt.s BossCollision_MCZ2 ; Boss_CollisionRoutine = 1, i.e. diggers pointing to the side move.w d7,-(sp) move.w x_pos(a1),d0 move.w y_pos(a1),d7 addi_.w #4,d7 subi.w #$30,d0 btst #0,render_flags(a1) ; left or right? beq.s + addi.w #$60,d0 ; x+$30, otherwise x-$30 + move.l #$40004,d1 ; heigth 4, width 4 bsr.w Boss_DoCollision move.w (sp)+,d7 move.b collision_flags(a1),d0 cmpi.w #$78,invulnerable_time(a0) bne.s + ; rts st boss_hurt_sonic(a1) ; sonic has just been hurt flag + rts ; =========================================================================== ; Boss_CollisionRoutine = 0, i.e. diggers pointing towards top ;loc_3FB46: BossCollision_MCZ2: move.w d7,-(sp) movea.w #$14,a5 movea.w #0,a4 - move.w x_pos(a1),d0 move.w y_pos(a1),d7 subi.w #$20,d7 add.w a5,d0 ; first check x+$14, second x-$14 move.l #$100004,d1 ; heigth $10, width 4 bsr.w Boss_DoCollision movea.w #-$14,a5 adda_.w #1,a4 cmpa.w #1,a4 beq.s - ; jump back once for second check move.w (sp)+,d7 move.b collision_flags(a1),d0 cmpi.w #$78,invulnerable_time(a0) bne.s + ; rts st boss_hurt_sonic(a1) ; sonic has just been hurt flag + rts ; =========================================================================== ;loc_3FB8A: BossCollision_CNZ: tst.b (Boss_CollisionRoutine).w beq.s ++ move.w d7,-(sp) move.w x_pos(a1),d0 move.w y_pos(a1),d7 addi.w #$28,d7 move.l #$80010,d1 cmpi.b #1,(Boss_CollisionRoutine).w beq.s + move.w #$20,d1 subi_.w #8,d7 addi_.w #4,d0 + bsr.w Boss_DoCollision move.w (sp)+,d7 + move.b collision_flags(a1),d0 rts ; =========================================================================== ;loc_3FBC4: BossCollision_MTZ: move.b collision_flags(a1),d0 rts ; =========================================================================== ;loc_3FBCA: BossCollision_OOZ: cmpi.b #1,(Boss_CollisionRoutine).w blt.s loc_3FC46 beq.s loc_3FC1C move.w d7,-(sp) move.w x_pos(a1),d0 move.w y_pos(a1),d7 moveq #0,d1 move.b mainspr_mapframe(a1),d1 subq.b #2,d1 add.w d1,d1 btst #0,render_flags(a1) beq.s loc_3FBF6 add.w word_3FC10(pc,d1.w),d0 bra.s loc_3FBFA ; =========================================================================== loc_3FBF6: sub.w word_3FC10(pc,d1.w),d0 loc_3FBFA: sub.w word_3FC10+2(pc,d1.w),d7 move.l #$60008,d1 bsr.w Boss_DoCollision move.w (sp)+,d7 move.w #0,d0 rts ; =========================================================================== word_3FC10: dc.w $14, 0 dc.w $10, $10 dc.w $10, -$10 ; =========================================================================== loc_3FC1C: move.w d7,-(sp) move.w x_pos(a1),d0 move.w y_pos(a1),d7 moveq #$10,d1 btst #0,render_flags(a1) beq.s + neg.w d1 + sub.w d1,d0 move.l #$8000C,d1 bsr.w loc_3FC7A move.w (sp)+,d7 move.b #0,d0 rts ; =========================================================================== loc_3FC46: move.b collision_flags(a1),d0 rts ; =========================================================================== ;loc_3FC4C: ; d7 = y_boss, d3 = y_sonic, d1 (high word) = heigth ; d0 = x_boss, d2 = x_sonic, d1 (low word) = width Boss_DoCollision: sub.w d1,d0 sub.w d2,d0 bcc.s loc_3FC5A add.w d1,d1 add.w d1,d0 bcs.s loc_3FC5E return_3FC58: rts ; =========================================================================== loc_3FC5A: cmp.w d4,d0 bhi.s return_3FC58 loc_3FC5E: swap d1 sub.w d1,d7 sub.w d3,d7 bcc.s loc_3FC70 add.w d1,d1 add.w d1,d7 bcs.w Touch_ChkHurt bra.s return_3FC58 ; =========================================================================== loc_3FC70: cmp.w d5,d7 bhi.w return_3FC58 bra.w Touch_ChkHurt ; =========================================================================== loc_3FC7A: sub.w d1,d0 sub.w d2,d0 bcc.s loc_3FC88 add.w d1,d1 add.w d1,d0 bcs.s loc_3FC8C return_3FC86: rts ; =========================================================================== loc_3FC88: cmp.w d4,d0 bhi.s return_3FC86 loc_3FC8C: swap d1 sub.w d1,d7 sub.w d3,d7 bcc.s loc_3FC9E add.w d1,d1 add.w d1,d7 bcs.w loc_3FCA4 bra.s return_3FC86 ; =========================================================================== loc_3FC9E: cmp.w d5,d7 bhi.w return_3FC86 loc_3FCA4: neg.w x_vel(a0) neg.w y_vel(a0) rts ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo_Sonic_ResetOnFloor_Part2 jmp (Sonic_ResetOnFloor_Part2).l JmpTo_Check_CNZ_bumpers jmp (Check_CNZ_bumpers).l JmpTo_Touch_Rings jmp (Touch_Rings).l align 4 endif ; =========================================================================== ;loc_3FCC4: AniArt_Load: moveq #0,d0 move.b (Current_Zone).w,d0 add.w d0,d0 add.w d0,d0 move.w PLC_DYNANM+2(pc,d0.w),d1 lea PLC_DYNANM(pc,d1.w),a2 move.w PLC_DYNANM(pc,d0.w),d0 jmp PLC_DYNANM(pc,d0.w) ; =========================================================================== rts ; =========================================================================== ; --------------------------------------------------------------------------- ; ZONE ANIMATION PROCEDURES AND SCRIPTS ; ; Each zone gets two entries in this jump table. The first entry points to the ; zone's animation procedure (usually Dynamic_Normal, but some zones have special ; procedures for complicated animations). The second points to the zone's animation ; script. ; ; Note that Animated_Null is not a valid animation script, so don't pair it up ; with anything except Dynamic_Null, or bad things will happen (for example, a bus error exception). ; --------------------------------------------------------------------------- PLC_DYNANM: zoneOrderedOffsetTable 2,2 ; Zone ID zoneOffsetTableEntry.w Dynamic_Normal ; $00 zoneOffsetTableEntry.w Animated_EHZ zoneOffsetTableEntry.w Dynamic_Null ; $01 zoneOffsetTableEntry.w Animated_Null zoneOffsetTableEntry.w Dynamic_Null ; $02 zoneOffsetTableEntry.w Animated_Null zoneOffsetTableEntry.w Dynamic_Null ; $03 zoneOffsetTableEntry.w Animated_Null zoneOffsetTableEntry.w Dynamic_Normal ; $04 zoneOffsetTableEntry.w Animated_MTZ zoneOffsetTableEntry.w Dynamic_Normal ; $05 zoneOffsetTableEntry.w Animated_MTZ zoneOffsetTableEntry.w Dynamic_Null ; $06 zoneOffsetTableEntry.w Animated_Null zoneOffsetTableEntry.w Dynamic_HTZ ; $07 zoneOffsetTableEntry.w Animated_HTZ zoneOffsetTableEntry.w Dynamic_Normal ; $08 zoneOffsetTableEntry.w Animated_HPZ zoneOffsetTableEntry.w Dynamic_Null ; $09 zoneOffsetTableEntry.w Animated_Null zoneOffsetTableEntry.w Dynamic_Normal ; $0A zoneOffsetTableEntry.w Animated_OOZ zoneOffsetTableEntry.w Dynamic_Null ; $0B zoneOffsetTableEntry.w Animated_Null zoneOffsetTableEntry.w Dynamic_CNZ ; $0C zoneOffsetTableEntry.w Animated_CNZ zoneOffsetTableEntry.w Dynamic_Normal ; $0D zoneOffsetTableEntry.w Animated_CPZ zoneOffsetTableEntry.w Dynamic_Normal ; $0E zoneOffsetTableEntry.w Animated_DEZ zoneOffsetTableEntry.w Dynamic_ARZ ; $0F zoneOffsetTableEntry.w Animated_ARZ zoneOffsetTableEntry.w Dynamic_Null ; $10 zoneOffsetTableEntry.w Animated_Null zoneTableEnd ; =========================================================================== Dynamic_Null: rts ; =========================================================================== Dynamic_HTZ: tst.w (Two_player_mode).w bne.w Dynamic_Normal lea (Anim_Counters).w,a3 moveq #0,d0 move.w (Camera_X_pos).w,d1 neg.w d1 asr.w #3,d1 move.w (Camera_X_pos).w,d0 lsr.w #4,d0 add.w d1,d0 subi.w #$10,d0 divu.w #$30,d0 swap d0 cmp.b 1(a3),d0 beq.s BranchTo_loc_3FE5C move.b d0,1(a3) move.w d0,d2 andi.w #7,d0 add.w d0,d0 add.w d0,d0 add.w d0,d0 move.w d0,d1 add.w d0,d0 add.w d1,d0 andi.w #$38,d2 lsr.w #2,d2 add.w d2,d0 lea word_3FD9C(pc,d0.w),a4 moveq #5,d5 move.w #tiles_to_bytes(ArtTile_ArtUnc_HTZMountains),d4 loc_3FD7C: moveq #-1,d1 move.w (a4)+,d1 andi.l #$FFFFFF,d1 move.w d4,d2 moveq #$40,d3 jsr (QueueDMATransfer).l addi.w #$80,d4 dbf d5,loc_3FD7C BranchTo_loc_3FE5C bra.w loc_3FE5C ; =========================================================================== ; HTZ mountain art main RAM addresses? word_3FD9C: dc.w $80, $180, $280, $580, $600, $700 ; 6 dc.w $80, $180, $280, $580, $600, $700 ; 12 dc.w $980, $A80, $B80, $C80, $D00, $D80 ; 18 dc.w $980, $A80, $B80, $C80, $D00, $D80 ; 24 dc.w $E80,$1180,$1200,$1280,$1300,$1380 ; 30 dc.w $E80,$1180,$1200,$1280,$1300,$1380 ; 36 dc.w $1400,$1480,$1500,$1580,$1600,$1900 ; 42 dc.w $1400,$1480,$1500,$1580,$1600,$1900 ; 48 dc.w $1D00,$1D80,$1E00,$1F80,$2400,$2580 ; 54 dc.w $1D00,$1D80,$1E00,$1F80,$2400,$2580 ; 60 dc.w $2600,$2680,$2780,$2B00,$2F00,$3280 ; 66 dc.w $2600,$2680,$2780,$2B00,$2F00,$3280 ; 72 dc.w $3600,$3680,$3780,$3C80,$3D00,$3F00 ; 78 dc.w $3600,$3680,$3780,$3C80,$3D00,$3F00 ; 84 dc.w $3F80,$4080,$4480,$4580,$4880,$4900 ; 90 dc.w $3F80,$4080,$4480,$4580,$4880,$4900 ; 96 ; =========================================================================== loc_3FE5C: lea (TempArray_LayerDef).w,a1 move.w (Camera_X_pos).w,d2 neg.w d2 asr.w #3,d2 move.l a2,-(sp) lea (ArtUnc_HTZClouds).l,a0 lea (Chunk_Table+$7C00).l,a2 moveq #$F,d1 loc_3FE78: move.w (a1)+,d0 neg.w d0 add.w d2,d0 andi.w #$1F,d0 lsr.w #1,d0 bcc.s loc_3FE8A addi.w #$200,d0 loc_3FE8A: lea (a0,d0.w),a4 lsr.w #1,d0 bcs.s loc_3FEB4 move.l (a4)+,(a2)+ adda.w #$3C,a2 move.l (a4)+,(a2)+ adda.w #$3C,a2 move.l (a4)+,(a2)+ adda.w #$3C,a2 move.l (a4)+,(a2)+ suba.w #$C0,a2 adda.w #$20,a0 dbf d1,loc_3FE78 bra.s loc_3FEEC ; =========================================================================== loc_3FEB4: rept 3 rept 4 move.b (a4)+,(a2)+ endm adda.w #$3C,a2 endm rept 4 move.b (a4)+,(a2)+ endm suba.w #$C0,a2 adda.w #$20,a0 dbf d1,loc_3FE78 loc_3FEEC: move.l #(Chunk_Table+$7C00) & $FFFFFF,d1 move.w #tiles_to_bytes(ArtTile_ArtUnc_HTZClouds),d2 move.w #$80,d3 jsr (QueueDMATransfer).l movea.l (sp)+,a2 addq.w #2,a3 bra.w loc_3FF30 ; =========================================================================== Dynamic_CNZ: tst.b (Current_Boss_ID).w beq.s + rts ; --------------------------------------------------------------------------- + lea (Animated_CNZ).l,a2 tst.w (Two_player_mode).w beq.s Dynamic_Normal lea (Animated_CNZ_2P).l,a2 bra.s Dynamic_Normal ; =========================================================================== Dynamic_ARZ: tst.b (Current_Boss_ID).w beq.s Dynamic_Normal rts ; =========================================================================== Dynamic_Normal: lea (Anim_Counters).w,a3 loc_3FF30: move.w (a2)+,d6 ; Get number of scripts in list ; S&K checks for empty lists, here ; bpl.s .listnotempty ; If there are any, continue ; rts ;.listnotempty: ; loc_3FF32: .loop: subq.b #1,(a3) ; Tick down frame duration bcc.s .nextscript ; If frame isn't over, move on to next script ;.nextframe: moveq #0,d0 move.b 1(a3),d0 ; Get current frame cmp.b 6(a2),d0 ; Have we processed the last frame in the script? blo.s .notlastframe moveq #0,d0 ; If so, reset to first frame move.b d0,1(a3) ; '' ; loc_3FF48: .notlastframe: addq.b #1,1(a3) ; Consider this frame processed; set counter to next frame move.b (a2),(a3) ; Set frame duration to global duration value bpl.s .globalduration ; If script uses per-frame durations, use those instead add.w d0,d0 move.b 9(a2,d0.w),(a3) ; Set frame duration to current frame's duration value ; loc_3FF56: .globalduration: ; Prepare for DMA transfer ; Get relative address of frame's art move.b 8(a2,d0.w),d0 ; Get tile ID lsl.w #5,d0 ; Turn it into an offset ; Get VRAM destination address move.w 4(a2),d2 ; Get ROM source address move.l (a2),d1 ; Get start address of animated tile art andi.l #$FFFFFF,d1 add.l d0,d1 ; Offset into art, to get the address of new frame ; Get size of art to be transferred moveq #0,d3 move.b 7(a2),d3 lsl.w #4,d3 ; Turn it into actual size (in words) ; Use d1, d2 and d3 to queue art for transfer jsr (QueueDMATransfer).l ; loc_3FF78: .nextscript: move.b 6(a2),d0 ; Get total size of frame data tst.b (a2) ; Is per-frame duration data present? bpl.s .globalduration2; If not, keep the current size; it's correct add.b d0,d0 ; Double size to account for the additional frame duration data ; loc_3FF82: .globalduration2: addq.b #1,d0 andi.w #$FE,d0 ; Round to next even address, if it isn't already lea 8(a2,d0.w),a2 ; Advance to next script in list addq.w #2,a3 ; Advance to next script's slot in a3 (usually Anim_Counters) dbf d6,.loop rts ; =========================================================================== ; ZONE ANIMATION SCRIPTS ; ; The Dynamic_Normal subroutine uses these scripts to reload certain tiles, ; thus animating them. All the relevant art must be uncompressed, because ; otherwise the subroutine would spend so much time waiting for the art to be ; decompressed that the VBLANK window would close before all the animating was done. ; zoneanimdecl -1, ArtUnc_Flowers1, ArtTile_ArtUnc_Flowers1, 6, 2 ; -1 Global frame duration. If -1, then each frame will use its own duration, instead ; ArtUnc_Flowers1 Source address ; ArtTile_ArtUnc_Flowers1 Destination VRAM address ; 6 Number of frames ; 2 Number of tiles to load into VRAM for each frame ; dc.b 0,$7F ; Start of the script proper ; 0 Tile ID of first tile in ArtUnc_Flowers1 to transfer ; $7F Frame duration. Only here if global duration is -1 ; loc_3FF94: Animated_EHZ: zoneanimstart ; Flowers zoneanimdecl -1, ArtUnc_Flowers1, ArtTile_ArtUnc_Flowers1, 6, 2 dc.b 0,$7F ; Start of the script proper dc.b 2,$13 dc.b 0, 7 dc.b 2, 7 dc.b 0, 7 dc.b 2, 7 even ; Flowers zoneanimdecl -1, ArtUnc_Flowers2, ArtTile_ArtUnc_Flowers2, 8, 2 dc.b 2,$7F dc.b 0, $B dc.b 2, $B dc.b 0, $B dc.b 2, 5 dc.b 0, 5 dc.b 2, 5 dc.b 0, 5 even ; Flowers zoneanimdecl 7, ArtUnc_Flowers3, ArtTile_ArtUnc_Flowers3, 2, 2 dc.b 0 dc.b 2 even ; Flowers zoneanimdecl -1, ArtUnc_Flowers4, ArtTile_ArtUnc_Flowers4, 8, 2 dc.b 0,$7F dc.b 2, 7 dc.b 0, 7 dc.b 2, 7 dc.b 0, 7 dc.b 2, $B dc.b 0, $B dc.b 2, $B even ; Pulsing thing against checkered background zoneanimdecl -1, ArtUnc_EHZPulseBall, ArtTile_ArtUnc_EHZPulseBall, 6, 2 dc.b 0,$17 dc.b 2, 9 dc.b 4, $B dc.b 6,$17 dc.b 4, $B dc.b 2, 9 even zoneanimend Animated_MTZ: zoneanimstart ; Spinning metal cylinder zoneanimdecl 0, ArtUnc_MTZCylinder, ArtTile_ArtUnc_MTZCylinder, 8,$10 dc.b 0 dc.b $10 dc.b $20 dc.b $30 dc.b $40 dc.b $50 dc.b $60 dc.b $70 even ; lava zoneanimdecl $D, ArtUnc_Lava, ArtTile_ArtUnc_Lava, 6,$C dc.b 0 dc.b $C dc.b $18 dc.b $24 dc.b $18 dc.b $C even ; MTZ background animated section zoneanimdecl -1, ArtUnc_MTZAnimBack, ArtTile_ArtUnc_MTZAnimBack_1, 4, 6 dc.b 0,$13 dc.b 6, 7 dc.b $C,$13 dc.b 6, 7 even ; MTZ background animated section zoneanimdecl -1, ArtUnc_MTZAnimBack, ArtTile_ArtUnc_MTZAnimBack_2, 4, 6 dc.b $C,$13 dc.b 6, 7 dc.b 0,$13 dc.b 6, 7 even zoneanimend Animated_HTZ: zoneanimstart ; Flowers zoneanimdecl -1, ArtUnc_Flowers1, ArtTile_ArtUnc_Flowers1, 6, 2 dc.b 0,$7F dc.b 2,$13 dc.b 0, 7 dc.b 2, 7 dc.b 0, 7 dc.b 2, 7 even ; Flowers zoneanimdecl -1, ArtUnc_Flowers2, ArtTile_ArtUnc_Flowers2, 8, 2 dc.b 2,$7F dc.b 0, $B dc.b 2, $B dc.b 0, $B dc.b 2, 5 dc.b 0, 5 dc.b 2, 5 dc.b 0, 5 even ; Flowers zoneanimdecl 7, ArtUnc_Flowers3, ArtTile_ArtUnc_Flowers3, 2, 2 dc.b 0 dc.b 2 even ; Flowers zoneanimdecl -1, ArtUnc_Flowers4, ArtTile_ArtUnc_Flowers4, 8, 2 dc.b 0,$7F dc.b 2, 7 dc.b 0, 7 dc.b 2, 7 dc.b 0, 7 dc.b 2, $B dc.b 0, $B dc.b 2, $B even ; Pulsing thing against checkered background zoneanimdecl -1, ArtUnc_EHZPulseBall, ArtTile_ArtUnc_EHZPulseBall, 6, 2 dc.b 0,$17 dc.b 2, 9 dc.b 4, $B dc.b 6,$17 dc.b 4, $B dc.b 2, 9 even zoneanimend ; word_4009C: Animated_OOZ: Animated_HPZ: zoneanimstart ; Supposed to be the pulsing orb from HPZ, but uses OOZ's pulsing ball art zoneanimdecl 8, ArtUnc_HPZPulseOrb, ArtTile_ArtUnc_HPZPulseOrb_1, 6, 8 dc.b 0 dc.b 0 dc.b 8 dc.b $10 dc.b $10 dc.b 8 even ; Supposed to be the pulsing orb from HPZ, but uses OOZ's pulsing ball art zoneanimdecl 8, ArtUnc_HPZPulseOrb, ArtTile_ArtUnc_HPZPulseOrb_2, 6, 8 dc.b 8 dc.b $10 dc.b $10 dc.b 8 dc.b 0 dc.b 0 even ; Supposed to be the pulsing orb from HPZ, but uses OOZ's pulsing ball art zoneanimdecl 8, ArtUnc_HPZPulseOrb, ArtTile_ArtUnc_HPZPulseOrb_3, 6, 8 dc.b $10 dc.b 8 dc.b 0 dc.b 0 dc.b 8 dc.b $10 even zoneanimend ; word_400C8: Animated_OOZ2: Animated_OOZ: zoneanimstart ; Pulsing ball from OOZ zoneanimdecl -1, ArtUnc_OOZPulseBall, ArtTile_ArtUnc_OOZPulseBall, 4, 4 dc.b 0, $B dc.b 4, 5 dc.b 8, 9 dc.b 4, 3 even ; Square rotating around ball in OOZ zoneanimdecl 6, ArtUnc_OOZSquareBall1, ArtTile_ArtUnc_OOZSquareBall1, 4, 4 dc.b 0 dc.b 4 dc.b 8 dc.b $C even ; Square rotating around ball zoneanimdecl 6, ArtUnc_OOZSquareBall2, ArtTile_ArtUnc_OOZSquareBall2, 4, 4 dc.b 0 dc.b 4 dc.b 8 dc.b $C even ; Oil zoneanimdecl $11, ArtUnc_Oil1, ArtTile_ArtUnc_Oil1, 6,$10 dc.b 0 dc.b $10 dc.b $20 dc.b $30 dc.b $20 dc.b $10 even ; Oil zoneanimdecl $11, ArtUnc_Oil2, ArtTile_ArtUnc_Oil2, 6,$10 dc.b 0 dc.b $10 dc.b $20 dc.b $30 dc.b $20 dc.b $10 even zoneanimend Animated_CNZ: zoneanimstart ; Flipping foreground section in CNZ zoneanimdecl -1, ArtUnc_CNZFlipTiles, ArtTile_ArtUnc_CNZFlipTiles_2, $10,$10 dc.b 0,$C7 dc.b $10, 5 dc.b $20, 5 dc.b $30, 5 dc.b $40,$C7 dc.b $50, 5 dc.b $20, 5 dc.b $60, 5 dc.b 0, 5 dc.b $10, 5 dc.b $20, 5 dc.b $30, 5 dc.b $40, 5 dc.b $50, 5 dc.b $20, 5 dc.b $60, 5 even ; Flipping foreground section in CNZ zoneanimdecl -1, ArtUnc_CNZFlipTiles, ArtTile_ArtUnc_CNZFlipTiles_1, $10,$10 dc.b $70, 5 dc.b $80, 5 dc.b $20, 5 dc.b $90, 5 dc.b $A0, 5 dc.b $B0, 5 dc.b $20, 5 dc.b $C0, 5 dc.b $70,$C7 dc.b $80, 5 dc.b $20, 5 dc.b $90, 5 dc.b $A0,$C7 dc.b $B0, 5 dc.b $20, 5 dc.b $C0, 5 even zoneanimend ; word_40160: Animated_CNZ_2P: zoneanimstart ; Flipping foreground section in CNZ zoneanimdecl -1, ArtUnc_CNZFlipTiles, ArtTile_ArtUnc_CNZFlipTiles_2_2p, $10,$10 dc.b 0,$C7 dc.b $10, 5 dc.b $20, 5 dc.b $30, 5 dc.b $40,$C7 dc.b $50, 5 dc.b $20, 5 dc.b $60, 5 dc.b 0, 5 dc.b $10, 5 dc.b $20, 5 dc.b $30, 5 dc.b $40, 5 dc.b $50, 5 dc.b $20, 5 dc.b $60, 5 even ; Flipping foreground section in CNZ zoneanimdecl -1, ArtUnc_CNZFlipTiles, ArtTile_ArtUnc_CNZFlipTiles_1_2p, $10,$10 dc.b $70, 5 dc.b $80, 5 dc.b $20, 5 dc.b $90, 5 dc.b $A0, 5 dc.b $B0, 5 dc.b $20, 5 dc.b $C0, 5 dc.b $70,$C7 dc.b $80, 5 dc.b $20, 5 dc.b $90, 5 dc.b $A0,$C7 dc.b $B0, 5 dc.b $20, 5 dc.b $C0, 5 even zoneanimend Animated_CPZ: zoneanimstart ; Animated background section in CPZ and DEZ zoneanimdecl 4, ArtUnc_CPZAnimBack, ArtTile_ArtUnc_CPZAnimBack, 8, 2 dc.b 0 dc.b 2 dc.b 4 dc.b 6 dc.b 8 dc.b $A dc.b $C dc.b $E even zoneanimend Animated_DEZ: zoneanimstart ; Animated background section in CPZ and DEZ zoneanimdecl 4, ArtUnc_CPZAnimBack, ArtTile_ArtUnc_DEZAnimBack, 8, 2 dc.b 0 dc.b 2 dc.b 4 dc.b 6 dc.b 8 dc.b $A dc.b $C dc.b $E even zoneanimend Animated_ARZ: zoneanimstart ; Waterfall patterns zoneanimdecl 5, ArtUnc_Waterfall1, ArtTile_ArtUnc_Waterfall1_2, 2, 4 dc.b 0 dc.b 4 even ; Waterfall patterns zoneanimdecl 5, ArtUnc_Waterfall1, ArtTile_ArtUnc_Waterfall1_1, 2, 4 dc.b 4 dc.b 0 even ; Waterfall patterns zoneanimdecl 5, ArtUnc_Waterfall2, ArtTile_ArtUnc_Waterfall2, 2, 4 dc.b 0 dc.b 4 even ; Waterfall patterns zoneanimdecl 5, ArtUnc_Waterfall3, ArtTile_ArtUnc_Waterfall3, 2, 4 dc.b 0 dc.b 4 even zoneanimend Animated_Null: ; invalid ; =========================================================================== ; --------------------------------------------------------------------------- ; Unused mystery function ; In CPZ, within a certain range of camera X coordinates spanning ; exactly 2 screens (a boss fight or cutscene?), ; once every 8 frames, make the entire screen refresh and do... SOMETHING... ; (in 2 separate 512-byte blocks of memory, move around a bunch of bytes) ; Maybe some abandoned scrolling effect? ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_40200: cmpi.b #chemical_plant_zone,(Current_Zone).w beq.s + - rts ; =========================================================================== ; this shifts all blocks of the chunks $EA-$ED and $FA-$FD one block to the ; left and the last block in each row (chunk $ED/$FD) to the beginning ; i.e. rotates the blocks to the left by one + move.w (Camera_X_pos).w,d0 cmpi.w #$1940,d0 blo.s - ; rts cmpi.w #$1F80,d0 bhs.s - ; rts subq.b #1,(CPZ_UnkScroll_Timer).w bpl.s - ; rts ; do it every 8th frame move.b #7,(CPZ_UnkScroll_Timer).w move.b #1,(Screen_redraw_flag).w lea (Chunk_Table+$7500).l,a1 ; chunks $EA-$ED, $FFFF7500 - $FFFF7700 bsr.s + lea (Chunk_Table+$7D00).l,a1 ; chunks $FA-$FD, $FFFF7D00 - $FFFF7F00 + move.w #7,d1 - move.w (a1),d0 rept 3 ; do this for 3 chunks rept 7 move.w 2(a1),(a1)+ ; shift 1st line of chunk by 1 block to the left (+3*14 bytes) endm move.w $72(a1),(a1)+ ; first block of next chunk to the left into previous chunk (+3*2 bytes) adda.w #$70,a1 ; go to next chunk (+336 bytes) endm rept 7 ; now do it for the 4th chunk move.w 2(a1),(a1)+ ; shift 1st line of chunk by 1 block to the left (+14 bytes) endm move.w d0,(a1)+ ; move 1st block of 1st chunk to last block of last chunk (+2 bytes, subsubtotal = 400 bytes) suba.w #$180,a1 ; go to the next row in the first chunk (-384 bytes, subtotal = -16 bytes) dbf d1,- ; now do this again for rows 2-8 in these chunks ; 400 + 7 * (-16) = 512 byte range was affected rts ; =========================================================================== loc_402D4: cmpi.b #hill_top_zone,(Current_Zone).w bne.s + bsr.w PatchHTZTiles move.b #-1,(Anim_Counters+1).w move.w #-1,(TempArray_LayerDef+$20).w + cmpi.b #chemical_plant_zone,(Current_Zone).w bne.s + move.b #-1,(Anim_Counters+1).w + moveq #0,d0 move.b (Current_Zone).w,d0 add.w d0,d0 move.w AnimPatMaps(pc,d0.w),d0 lea AnimPatMaps(pc,d0.w),a0 tst.w (Two_player_mode).w beq.s + cmpi.b #casino_night_zone,(Current_Zone).w bne.s + lea (APM_CNZ2P).l,a0 + tst.w (a0) beq.s + ; rts lea (Block_Table).w,a1 adda.w (a0)+,a1 move.w (a0)+,d1 tst.w (Two_player_mode).w bne.s LoadLevelBlocks_2P ; loc_40330: LoadLevelBlocks: move.w (a0)+,(a1)+ ; copy blocks to RAM dbf d1,LoadLevelBlocks ; loop using d1 + rts ; =========================================================================== ; loc_40338: LoadLevelBlocks_2P: ; There's a bug in here, where d1, the loop counter, ; is overwritten with VRAM data move.w (a0)+,d0 move.w d0,d1 andi.w #nontile_mask,d0 ; d0 holds the preserved non-tile data andi.w #tile_mask,d1 ; d1 holds the tile index (overwrites loop counter!) lsr.w #1,d1 ; half tile index or.w d1,d0 ; put them back together move.w d0,(a1)+ dbf d1,LoadLevelBlocks_2P ; loop using d1, which we just overwrote rts ; =========================================================================== ; -------------------------------------------------------------------------------------- ; Animated Pattern Mappings (16x16) ; -------------------------------------------------------------------------------------- ; off_40350: AnimPatMaps: zoneOrderedOffsetTable 2,1 zoneOffsetTableEntry.w APM_EHZ ; 0 zoneOffsetTableEntry.w APM_Null ; 1 zoneOffsetTableEntry.w APM_Null ; 2 zoneOffsetTableEntry.w APM_Null ; 3 zoneOffsetTableEntry.w APM_MTZ ; 4 zoneOffsetTableEntry.w APM_MTZ ; 5 zoneOffsetTableEntry.w APM_Null ; 6 zoneOffsetTableEntry.w APM_EHZ ; 7 zoneOffsetTableEntry.w APM_HPZ ; 8 zoneOffsetTableEntry.w APM_Null ; 9 zoneOffsetTableEntry.w APM_OOZ ; $A zoneOffsetTableEntry.w APM_Null ; $B zoneOffsetTableEntry.w APM_CNZ ; $C zoneOffsetTableEntry.w APM_CPZ ; $D zoneOffsetTableEntry.w APM_DEZ ; $E zoneOffsetTableEntry.w APM_ARZ ; $F zoneOffsetTableEntry.w APM_Null ;$10 zoneTableEnd begin_animpat macro {INTLABEL} __LABEL__ label * __LABEL___Len := __LABEL___End - __LABEL___Blocks dc.w $1800 - __LABEL___Len dc.w bytesToWcnt(__LABEL___Len) __LABEL___Blocks: endm ; byte_40372: APM_EHZ: begin_animpat dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$0 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$4 ,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$1 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$5 ,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$8 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$C ,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$9 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$D ,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$10,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$14,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$11,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$15,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$2 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$6 ,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$3 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$7 ,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$A ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$E ,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$B ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$F ,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$12,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$16,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$13,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$17,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$18,0,0,3,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$1A,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$19,0,0,3,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$1B,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$1C,0,0,3,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$1E,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$1D,0,0,3,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$1F,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$0,1,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$1,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$1,1,0,2,0) dc.w make_block_tile(ArtTile_ArtKos_Checkers+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$0,0,0,2,0) dc.w make_block_tile(ArtTile_ArtKos_Checkers+$1,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$1,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$0,1,0,2,0),make_block_tile(ArtTile_ArtKos_Checkers+$0,1,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$1,1,0,2,0),make_block_tile(ArtTile_ArtKos_Checkers+$1,1,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_Flowers1+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_Flowers1+$0,1,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_Flowers1+$1,0,0,3,0),make_block_tile(ArtTile_ArtUnc_Flowers1+$1,1,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_Flowers2+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_Flowers2+$0,1,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_Flowers2+$1,0,0,3,1),make_block_tile(ArtTile_ArtUnc_Flowers2+$1,1,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_Flowers3+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_Flowers3+$0,1,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_Flowers3+$1,0,0,3,0),make_block_tile(ArtTile_ArtUnc_Flowers3+$1,1,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_Flowers4+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_Flowers4+$0,1,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_Flowers4+$1,0,0,3,1),make_block_tile(ArtTile_ArtUnc_Flowers4+$1,1,0,3,1) APM_EHZ_End: ; byte_403EE: APM_MTZ: begin_animpat dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$0,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$0,1,0,1,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$1,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$1,1,0,1,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$2,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$2,1,0,1,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$3,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$3,1,0,1,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$E,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$E,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$F,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$F,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$C,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$C,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$D,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$D,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$A,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$A,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$B,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$B,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$8,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$8,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$9,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$9,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$6,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$6,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$7,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$7,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$4,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$4,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$5,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$5,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$2,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$2,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$3,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$3,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$1,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$1,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$4,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$4,1,0,1,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$5,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$5,1,0,1,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$0,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$0,1,0,1,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$1,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$1,1,0,1,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$2,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$2,1,0,1,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$3,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$3,1,0,1,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$4,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$4,1,0,1,0) dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$5,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$5,1,0,1,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,1),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Lava+$0 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Lava+$1 ,0,0,2,1) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,1),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Lava+$2 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Lava+$3 ,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Lava+$4 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Lava+$5 ,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Lava+$8 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Lava+$9 ,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Lava+$6 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Lava+$7 ,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Lava+$A ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Lava+$B ,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$E,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$E,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$F,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$F,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$C,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$C,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$D,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$D,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$A,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$A,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$B,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$B,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$8,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$8,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$9,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$9,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$6,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$6,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$7,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$7,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$4,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$4,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$5,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$5,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$2,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$2,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$3,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$3,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$0,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$1,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$1,0,0,3,1) APM_MTZ_End: ; byte_404C2: APM_HPZ: begin_animpat dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$1,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$2,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$3,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$4,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$5,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$6,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$7,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$1,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$2,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$3,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$4,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$5,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$6,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$7,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$1,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$2,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$3,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$4,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$5,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$6,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$7,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$1,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$2,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$3,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$4,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$5,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$6,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$7,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$1,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$2,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$3,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$4,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$5,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$6,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$7,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$1,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$2,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$3,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$4,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$5,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$6,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$7,0,0,2,0) if gameRevision<2 dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$2,0,0,3,0) else dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$2,0,0,3,0) endif dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$1,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$4,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$3,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$6,0,0,3,0) if gameRevision<2 dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$5,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$7,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$2,0,0,3,0) else dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$5,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$7,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$2,0,0,3,0) endif dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$1,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$4,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$3,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$6,0,0,3,0) if gameRevision<2 dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$5,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$7,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$2,0,0,3,0) else dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$5,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$7,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$2,0,0,3,0) endif dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$1,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$4,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$3,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$6,0,0,3,0) if gameRevision<2 dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$5,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$7,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$0,0,0,2,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$2,0,0,2,0) else dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$5,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$7,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$0,0,0,2,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$2,0,0,2,0) endif dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$1,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$4,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$3,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$6,0,0,2,0) if gameRevision<2 dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$5,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$7,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$0,0,0,2,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$2,0,0,2,0) else dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$5,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$7,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$0,0,0,2,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$2,0,0,2,0) endif dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$1,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$4,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$3,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$6,0,0,2,0) if gameRevision<2 dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$5,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$7,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$0,0,0,2,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$2,0,0,2,0) else dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$5,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$7,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$0,0,0,2,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$2,0,0,2,0) endif dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$1,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$4,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$3,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$6,0,0,2,0) if gameRevision<2 dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$5,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$7,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0) else dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$5,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$7,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0) endif APM_HPZ_End: ; byte_405B6: APM_OOZ: begin_animpat dc.w make_block_tile(ArtTile_ArtUnc_OOZPulseBall+$0,0,0,0,1),make_block_tile(ArtTile_ArtUnc_OOZPulseBall+$2,0,0,0,1) dc.w make_block_tile(ArtTile_ArtUnc_OOZPulseBall+$1,0,0,0,1),make_block_tile(ArtTile_ArtUnc_OOZPulseBall+$3,0,0,0,1) dc.w make_block_tile(ArtTile_ArtUnc_OOZSquareBall1+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_OOZSquareBall1+$1,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_OOZSquareBall1+$2,0,0,3,1),make_block_tile(ArtTile_ArtUnc_OOZSquareBall1+$3,0,0,3,1) if gameRevision<2 dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$2,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$1,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$3,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0) else dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$0,0,0,3,0) dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$2,0,0,3,0) dc.w make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$1,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$3,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0) endif dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$0,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$1,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$8,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$9,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$2,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$3,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$A,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$B,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$4,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$5,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$C,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$D,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$6,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$7,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$E,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$F,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$0,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$1,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$8,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$9,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$2,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$3,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$A,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$B,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$4,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$5,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$C,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$D,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$6,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$7,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$E,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$F,0,0,2,1) APM_OOZ_End: ; byte_4061A: APM_CNZ: begin_animpat dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$4,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$1,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$5,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$8,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$C,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$9,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$D,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$2,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$6,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$3,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$7,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$A,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$E,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$B,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$F,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$4,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$1,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$5,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$8,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$C,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$9,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$D,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$2,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$6,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$3,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$7,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$A,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$E,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$B,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$F,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$4,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$1,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$5,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$8,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$C,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$9,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$D,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$2,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$6,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$3,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$7,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$A,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$E,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$B,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$F,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$4,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$1,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$5,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$8,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$C,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$9,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$D,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$2,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$6,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$3,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$7,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$A,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$E,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$B,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$F,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$4,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$1,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$5,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$8,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$C,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$9,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$D,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$2,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$6,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$3,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$7,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$A,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$E,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$B,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$F,0,0,3,1) APM_CNZ_End: ; byte_406BE: APM_CNZ2P: begin_animpat dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$4,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$1,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$5,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$8,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$C,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$9,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$D,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$2,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$6,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$3,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$7,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$A,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$E,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$B,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$F,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$4,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$1,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$5,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$8,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$C,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$9,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$D,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$2,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$6,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$3,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$7,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$A,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$E,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$B,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$F,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$4,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$1,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$5,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$8,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$C,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$9,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$D,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$2,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$6,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$3,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$7,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$A,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$E,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$B,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$F,0,0,0,0) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$4,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$1,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$5,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$8,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$C,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$9,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$D,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$2,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$6,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$3,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$7,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$A,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$E,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$B,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$F,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$4,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$1,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$5,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$8,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$C,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$9,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$D,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$2,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$6,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$3,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$7,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$A,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$E,0,0,3,1) dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$B,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$F,0,0,3,1) APM_CNZ2P_End: ; byte_40762: APM_CPZ: begin_animpat dc.w make_block_tile(ArtTile_ArtUnc_CPZAnimBack+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_CPZAnimBack+$1,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_CPZAnimBack+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_CPZAnimBack+$1,0,0,2,0) APM_CPZ_End: ; byte_4076E: APM_DEZ: begin_animpat dc.w make_block_tile(ArtTile_ArtUnc_DEZAnimBack+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_DEZAnimBack+$1,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_DEZAnimBack+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_DEZAnimBack+$1,0,0,2,0) APM_DEZ_End: ; byte_4077A: APM_ARZ: begin_animpat dc.w make_block_tile(ArtTile_ArtUnc_Waterfall3+$0 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall3+$1 ,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Waterfall3+$2 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall3+$3 ,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Waterfall2+$0 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall2+$1 ,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Waterfall2+$2 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall2+$3 ,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$0,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$1,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$2,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$3,0,0,2,1) ;These are invalid animation entries for waterfalls (bug in original game): if 1==1 dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$C,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$D,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$E,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$F,0,0,2,1) else dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$0,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$1,0,0,2,1) dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$2,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$3,0,0,2,1) endif dc.w make_block_tile(ArtTile_ArtUnc_Waterfall3+$0 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall3+$1 ,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_Waterfall3+$2 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall3+$3 ,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_Waterfall2+$0 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall2+$1 ,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_Waterfall2+$2 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall2+$3 ,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$1,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$2,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$3,0,0,2,0) ;These are invalid animation entries for waterfalls (bug in original game): if 1==1 dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$C,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$D,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$E,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$F,0,0,2,0) else dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$1,0,0,2,0) dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$2,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$3,0,0,2,0) endif APM_ARZ_End: ; byte_407BE: APM_Null: dc.w 0 ; =========================================================================== ; loc_407C0: PatchHTZTiles: lea (ArtNem_HTZCliffs).l,a0 lea (Object_RAM+$800).w,a4 jsrto (NemDecToRAM).l, JmpTo2_NemDecToRAM lea (Object_RAM+$800).w,a1 lea_ word_3FD9C,a4 moveq #0,d2 moveq #7,d4 loc_407DA: moveq #5,d3 loc_407DC: moveq #-1,d0 move.w (a4)+,d0 movea.l d0,a2 moveq #$1F,d1 loc_407E4: move.l (a1),(a2)+ move.l d2,(a1)+ dbf d1,loc_407E4 dbf d3,loc_407DC adda.w #$C,a4 dbf d4,loc_407DA rts ; =========================================================================== if gameRevision<2 nop endif if ~~removeJmpTos JmpTo2_NemDecToRAM jmp (NemDecToRAM).l align 4 endif ; --------------------------------------------------------------------------- ; Subroutine to draw the HUD ; --------------------------------------------------------------------------- hud_letter_num_tiles = 2 hud_letter_vdp_delta = vdpCommDelta(tiles_to_bytes(hud_letter_num_tiles)) ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_40804: BuildHUD: tst.w (Ring_count).w beq.s ++ ; blink ring count if it's 0 moveq #0,d1 btst #3,(Timer_frames+1).w bne.s + ; only blink on certain frames cmpi.b #9,(Timer_minute).w ; should the minutes counter blink? bne.s + ; if not, branch addq.w #2,d1 ; set mapping frame time counter blink + bra.s ++ + moveq #0,d1 btst #3,(Timer_frames+1).w bne.s + ; only blink on certain frames addq.w #1,d1 ; set mapping frame for ring count blink cmpi.b #9,(Timer_minute).w bne.s + addq.w #2,d1 ; set mapping frame for double blink + move.w #128+16,d3 ; set X pos move.w #128+136,d2 ; set Y pos lea (HUD_MapUnc_40A9A).l,a1 movea.w #make_art_tile(ArtTile_ArtNem_HUD,0,1),a3 ; set art tile and flags add.w d1,d1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 bmi.s + jsrto (DrawSprite_Loop).l, JmpTo_DrawSprite_Loop ; draw frame + rts ; End of function BuildHUD ; =========================================================================== BuildHUD_P1: tst.w (Ring_count).w beq.s BuildHUD_P1_NoRings moveq #0,d1 btst #3,(Timer_frames+1).w bne.s + cmpi.b #9,(Timer_minute).w bne.s + addq.w #2,d1 ; make TIME flash + bra.s BuildHUD_P1_Continued ; =========================================================================== ; loc_40876: BuildHUD_P1_NoRings: moveq #0,d1 btst #3,(Timer_frames+1).w bne.s BuildHUD_P1_Continued addq.w #1,d1 ; make RINGS flash cmpi.b #9,(Timer_minute).w bne.s BuildHUD_P1_Continued addq.w #2,d1 ; make TIME flash ; loc_4088C: BuildHUD_P1_Continued: move.w #$90,d3 move.w #$188,d2 lea (HUD_MapUnc_40BEA).l,a1 movea.w #make_art_tile_2p(ArtTile_Art_HUD_Text_2P,0,1),a3 add.w d1,d1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 jsrto (DrawSprite_2P_Loop).l, JmpTo_DrawSprite_2P_Loop move.w #$B8,d3 move.w #$108,d2 movea.w #make_art_tile_2p(ArtTile_Art_HUD_Numbers_2P,0,1),a3 moveq #0,d7 move.b (Timer_minute).w,d7 bsr.w sub_4092E bsr.w sub_4096A moveq #0,d7 move.b (Timer_second).w,d7 bsr.w loc_40938 move.w #$C0,d3 move.w #$118,d2 movea.w #make_art_tile_2p(ArtTile_Art_HUD_Numbers_2P,0,1),a3 moveq #0,d7 move.w (Ring_count).w,d7 bsr.w sub_40984 tst.b (Update_HUD_timer_2P).w bne.s + tst.b (Update_HUD_timer).w beq.s + move.w #$110,d3 move.w #$1B8,d2 movea.w #make_art_tile_2p(ArtTile_Art_HUD_Numbers_2P,0,1),a3 moveq #0,d7 move.b (Loser_Time_Left).w,d7 bsr.w loc_40938 + moveq #4,d1 move.w #$90,d3 move.w #$188,d2 lea (HUD_MapUnc_40BEA).l,a1 movea.w #make_art_tile_2p(ArtTile_Art_HUD_Text_2P,0,1),a3 add.w d1,d1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 jsrto (DrawSprite_2P_Loop).l, JmpTo_DrawSprite_2P_Loop moveq #0,d4 rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_4092E: lea (Hud_1).l,a4 moveq #0,d6 bra.s loc_40940 ; =========================================================================== loc_40938: lea (Hud_10).l,a4 moveq #1,d6 loc_40940: moveq #0,d1 move.l (a4)+,d4 loc_40944: sub.l d4,d7 bcs.s loc_4094C addq.w #1,d1 bra.s loc_40944 ; =========================================================================== loc_4094C: add.l d4,d7 lea (HUD_MapUnc_40C82).l,a1 add.w d1,d1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 jsrto (DrawSprite_2P_Loop).l, JmpTo_DrawSprite_2P_Loop addq.w #8,d3 dbf d6,loc_40940 rts ; End of function sub_4092E ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_4096A: moveq #$A,d1 lea (HUD_MapUnc_40C82).l,a1 add.w d1,d1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 jsrto (DrawSprite_2P_Loop).l, JmpTo_DrawSprite_2P_Loop addq.w #8,d3 rts ; End of function sub_4096A ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_40984: lea (Hud_100).l,a4 moveq #2,d6 loc_4098C: moveq #0,d1 move.l (a4)+,d4 loc_40990: sub.l d4,d7 bcs.s loc_40998 addq.w #1,d1 bra.s loc_40990 ; =========================================================================== loc_40998: add.l d4,d7 tst.w d6 beq.s loc_409AA tst.w d1 beq.s loc_409A6 bset #$1F,d6 loc_409A6: tst.l d6 bpl.s loc_409BE loc_409AA: lea (HUD_MapUnc_40C82).l,a1 add.w d1,d1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 jsrto (DrawSprite_2P_Loop).l, JmpTo_DrawSprite_2P_Loop loc_409BE: addq.w #8,d3 dbf d6,loc_4098C rts ; End of function sub_40984 ; =========================================================================== BuildHUD_P2: tst.w (Ring_count_2P).w beq.s BuildHUD_P2_NoRings moveq #0,d1 btst #3,(Timer_frames+1).w bne.s + cmpi.b #9,(Timer_minute_2P).w bne.s + addq.w #2,d1 + bra.s BuildHUD_P2_Continued ; =========================================================================== ; loc_409E2: BuildHUD_P2_NoRings: moveq #0,d1 btst #3,(Timer_frames+1).w bne.s BuildHUD_P2_Continued addq.w #1,d1 cmpi.b #9,(Timer_minute_2P).w bne.s BuildHUD_P2_Continued addq.w #2,d1 ; loc_409F8: BuildHUD_P2_Continued: move.w #$90,d3 move.w #$268,d2 lea (HUD_MapUnc_40BEA).l,a1 movea.w #make_art_tile_2p(ArtTile_Art_HUD_Text_2P,0,1),a3 add.w d1,d1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 jsrto (DrawSprite_2P_Loop).l, JmpTo_DrawSprite_2P_Loop move.w #$B8,d3 move.w #$1E8,d2 movea.w #make_art_tile_2p(ArtTile_Art_HUD_Numbers_2P,0,1),a3 moveq #0,d7 move.b (Timer_minute_2P).w,d7 bsr.w sub_4092E bsr.w sub_4096A moveq #0,d7 move.b (Timer_second_2P).w,d7 bsr.w loc_40938 move.w #$C0,d3 move.w #$1F8,d2 movea.w #make_art_tile_2p(ArtTile_Art_HUD_Numbers_2P,0,1),a3 moveq #0,d7 move.w (Ring_count_2P).w,d7 bsr.w sub_40984 tst.b (Update_HUD_timer).w bne.s + tst.b (Update_HUD_timer_2P).w beq.s + move.w #$110,d3 move.w #$298,d2 movea.w #make_art_tile_2p(ArtTile_Art_HUD_Numbers_2P,0,1),a3 moveq #0,d7 move.b (Loser_Time_Left).w,d7 bsr.w loc_40938 + moveq #5,d1 move.w #$90,d3 move.w #$268,d2 lea (HUD_MapUnc_40BEA).l,a1 movea.w #make_art_tile_2p(ArtTile_ArtNem_Powerups,0,1),a3 add.w d1,d1 adda.w (a1,d1.w),a1 move.w (a1)+,d1 subq.w #1,d1 jsrto (DrawSprite_2P_Loop).l, JmpTo_DrawSprite_2P_Loop moveq #0,d4 rts ; =========================================================================== ; sprite mappings for the HUD ; uses the art in VRAM from $D940 - $FC00 HUD_MapUnc_40A9A: BINCLUDE "mappings/sprite/hud_a.bin" HUD_MapUnc_40BEA: BINCLUDE "mappings/sprite/hud_b.bin" HUD_MapUnc_40C82: BINCLUDE "mappings/sprite/hud_c.bin" ; --------------------------------------------------------------------------- ; Add points subroutine ; subroutine to add to Player 1's score ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_40D06: AddPoints: move.b #1,(Update_HUD_score).w lea (Score).w,a3 add.l d0,(a3) ; add d0*10 to the score move.l #999999,d1 cmp.l (a3),d1 ; is #999999 higher than the score? bhi.s + ; if yes, branch move.l d1,(a3) ; set score to #999999 + move.l (a3),d0 cmp.l (Next_Extra_life_score).w,d0 blo.s + ; rts addi.l #5000,(Next_Extra_life_score).w addq.b #1,(Life_count).w addq.b #1,(Update_HUD_lives).w move.w #MusID_ExtraLife,d0 jmp (PlayMusic).l ; =========================================================================== + rts ; End of function AddPoints ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; --------------------------------------------------------------------------- ; Add points subroutine ; subroutine to add to Player 2's score ; (goes to AddPoints to add to Player 1's score instead if this is not Player 2) ; --------------------------------------------------------------------------- ; sub_40D42: AddPoints2: tst.w (Two_player_mode).w beq.s AddPoints cmpa.w #MainCharacter,a3 beq.s AddPoints move.b #1,(Update_HUD_score_2P).w lea (Score_2P).w,a3 add.l d0,(a3) ; add d0*10 to the score move.l #999999,d1 cmp.l (a3),d1 ; is #999999 higher than the score? bhi.s + ; if yes, branch move.l d1,(a3) ; set score to #999999 + move.l (a3),d0 cmp.l (Next_Extra_life_score_2P).w,d0 blo.s + ; rts addi.l #5000,(Next_Extra_life_score_2P).w addq.b #1,(Life_count_2P).w addq.b #1,(Update_HUD_lives_2P).w move.w #MusID_ExtraLife,d0 jmp (PlayMusic).l ; =========================================================================== + rts ; End of function AddPoints2 ; --------------------------------------------------------------------------- ; Subroutine to update the HUD ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_40D8A: HudUpdate: nop lea (VDP_data_port).l,a6 tst.w (Two_player_mode).w bne.w loc_40F50 tst.w (Debug_mode_flag).w ; is debug mode on? bne.w loc_40E9A ; if yes, branch tst.b (Update_HUD_score).w ; does the score need updating? beq.s Hud_ChkRings ; if not, branch clr.b (Update_HUD_score).w move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Score),VRAM,WRITE),d0 ; set VRAM address move.l (Score).w,d1 ; load score bsr.w Hud_Score ; loc_40DBA: Hud_ChkRings: tst.b (Update_HUD_rings).w ; does the ring counter need updating? beq.s Hud_ChkTime ; if not, branch bpl.s loc_40DC6 bsr.w Hud_InitRings loc_40DC6: clr.b (Update_HUD_rings).w move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Rings),VRAM,WRITE),d0 moveq #0,d1 move.w (Ring_count).w,d1 bsr.w Hud_Rings ; loc_40DDA: Hud_ChkTime: tst.b (Update_HUD_timer).w ; does the time need updating? beq.s Hud_ChkLives ; if not, branch tst.w (Game_paused).w ; is the game paused? bne.s Hud_ChkLives ; if yes, branch lea (Timer).w,a1 cmpi.l #$93B3B,(a1)+ ; is the time 9.59? beq.w loc_40E84 ; if yes, branch addq.b #1,-(a1) cmpi.b #60,(a1) blo.s Hud_ChkLives move.b #0,(a1) addq.b #1,-(a1) cmpi.b #60,(a1) blo.s + move.b #0,(a1) addq.b #1,-(a1) cmpi.b #9,(a1) blo.s + move.b #9,(a1) + move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Minutes),VRAM,WRITE),d0 moveq #0,d1 move.b (Timer_minute).w,d1 bsr.w Hud_Mins move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Seconds),VRAM,WRITE),d0 moveq #0,d1 move.b (Timer_second).w,d1 bsr.w Hud_Secs ; loc_40E38: Hud_ChkLives: tst.b (Update_HUD_lives).w ; does the lives counter need updating? beq.s Hud_ChkBonus ; if not, branch clr.b (Update_HUD_lives).w bsr.w Hud_Lives ; loc_40E46: Hud_ChkBonus: tst.b (Update_Bonus_score).w ; do time/ring bonus counters need updating? beq.s Hud_End ; if not, branch clr.b (Update_Bonus_score).w move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Bonus_Score),VRAM,WRITE),(VDP_control_port).l moveq #0,d1 move.w (Total_Bonus_Countdown).w,d1 bsr.w Hud_TimeRingBonus moveq #0,d1 move.w (Bonus_Countdown_1).w,d1 ; load time bonus bsr.w Hud_TimeRingBonus moveq #0,d1 move.w (Bonus_Countdown_2).w,d1 ; load ring bonus bsr.w Hud_TimeRingBonus moveq #0,d1 move.w (Bonus_Countdown_3).w,d1 ; load perfect bonus bsr.w Hud_TimeRingBonus ; return_40E82: Hud_End: rts ; =========================================================================== loc_40E84: clr.b (Update_HUD_timer).w lea (MainCharacter).w,a0 ; a0=character movea.l a0,a2 bsr.w KillCharacter move.b #1,(Time_Over_flag).w rts ; =========================================================================== loc_40E9A: bsr.w HudDb_XY tst.b (Update_HUD_rings).w beq.s loc_40EBE bpl.s loc_40EAA bsr.w Hud_InitRings loc_40EAA: clr.b (Update_HUD_rings).w move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Rings),VRAM,WRITE),d0 moveq #0,d1 move.w (Ring_count).w,d1 bsr.w Hud_Rings loc_40EBE: move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Seconds),VRAM,WRITE),d0 moveq #0,d1 move.b (Sprite_count).w,d1 bsr.w Hud_Secs tst.b (Update_HUD_lives).w beq.s loc_40EDC clr.b (Update_HUD_lives).w bsr.w Hud_Lives loc_40EDC: tst.b (Update_Bonus_score).w beq.s loc_40F18 clr.b (Update_Bonus_score).w move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Bonus_Score),VRAM,WRITE),(VDP_control_port).l moveq #0,d1 move.w (Total_Bonus_Countdown).w,d1 bsr.w Hud_TimeRingBonus moveq #0,d1 move.w (Bonus_Countdown_1).w,d1 bsr.w Hud_TimeRingBonus moveq #0,d1 move.w (Bonus_Countdown_2).w,d1 bsr.w Hud_TimeRingBonus moveq #0,d1 move.w (Bonus_Countdown_3).w,d1 bsr.w Hud_TimeRingBonus loc_40F18: tst.w (Game_paused).w bne.s return_40F4E lea (Timer).w,a1 cmpi.l #$93B3B,(a1)+ nop addq.b #1,-(a1) cmpi.b #$3C,(a1) blo.s return_40F4E move.b #0,(a1) addq.b #1,-(a1) cmpi.b #$3C,(a1) blo.s return_40F4E move.b #0,(a1) addq.b #1,-(a1) cmpi.b #9,(a1) blo.s return_40F4E move.b #9,(a1) return_40F4E: rts ; =========================================================================== loc_40F50: tst.w (Game_paused).w bne.w return_4101A tst.b (Update_HUD_timer).w beq.s loc_40F90 lea (Timer).w,a1 cmpi.l #$93B3B,(a1)+ beq.w TimeOver addq.b #1,-(a1) cmpi.b #$3C,(a1) blo.s loc_40F90 move.b #0,(a1) addq.b #1,-(a1) cmpi.b #$3C,(a1) blo.s loc_40F90 move.b #0,(a1) addq.b #1,-(a1) cmpi.b #9,(a1) blo.s loc_40F90 move.b #9,(a1) loc_40F90: tst.b (Update_HUD_timer_2P).w beq.s loc_40FC8 lea (Timer_2P).w,a1 cmpi.l #$93B3B,(a1)+ beq.w TimeOver2 addq.b #1,-(a1) cmpi.b #$3C,(a1) blo.s loc_40FC8 move.b #0,(a1) addq.b #1,-(a1) cmpi.b #$3C,(a1) blo.s loc_40FC8 move.b #0,(a1) addq.b #1,-(a1) cmpi.b #9,(a1) blo.s loc_40FC8 move.b #9,(a1) loc_40FC8: tst.b (Update_HUD_lives).w beq.s loc_40FD6 clr.b (Update_HUD_lives).w bsr.w Hud_Lives loc_40FD6: tst.b (Update_HUD_lives_2P).w beq.s loc_40FE4 clr.b (Update_HUD_lives_2P).w bsr.w Hud_Lives2 loc_40FE4: move.b (Update_HUD_timer).w,d0 or.b (Update_HUD_timer_2P).w,d0 beq.s return_4101A lea (Loser_Time_Left).w,a1 tst.w (a1)+ beq.s return_4101A subq.b #1,-(a1) bhi.s return_4101A move.b #$3C,(a1) cmpi.b #$C,-1(a1) bne.s loc_41010 move.w #MusID_Countdown,d0 jsr (PlayMusic).l loc_41010: subq.b #1,-(a1) bcc.s return_4101A move.w #0,(a1) bsr.s TimeOver0 return_4101A: rts ; End of function HudUpdate ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_4101C: TimeOver0: tst.b (Update_HUD_timer).w bne.s TimeOver tst.b (Update_HUD_timer_2P).w bne.s TimeOver2 rts ; =========================================================================== ; loc_4102A: TimeOver: clr.b (Update_HUD_timer).w lea (MainCharacter).w,a0 ; a0=character movea.l a0,a2 bsr.w KillCharacter move.b #1,(Time_Over_flag).w tst.b (Update_HUD_timer_2P).w beq.s + ; rts ; loc_41044: TimeOver2: clr.b (Update_HUD_timer_2P).w lea (Sidekick).w,a0 ; a0=character movea.l a0,a2 bsr.w KillCharacter move.b #1,(Time_Over_flag_2P).w + rts ; End of function TimeOver0 ; --------------------------------------------------------------------------- ; Subroutine to initialize ring counter on the HUD ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_4105A: ; Hud_LoadZero: Hud_InitRings: move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Rings),VRAM,WRITE),(VDP_control_port).l lea Hud_TilesRings(pc),a2 move.w #(Hud_TilesBase_End-Hud_TilesRings)-1,d2 bra.s loc_41090 ; --------------------------------------------------------------------------- ; Subroutine to load uncompressed HUD patterns ("E", "0", colon) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; loc_4106E: Hud_Base: lea (VDP_data_port).l,a6 bsr.w Hud_Lives tst.w (Two_player_mode).w bne.s loc_410BC move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Score_E),VRAM,WRITE),(VDP_control_port).l lea Hud_TilesBase(pc),a2 move.w #(Hud_TilesBase_End-Hud_TilesBase)-1,d2 loc_41090: lea Art_Hud(pc),a1 loc_41094: move.w #8*hud_letter_num_tiles-1,d1 move.b (a2)+,d0 bmi.s loc_410B0 ext.w d0 lsl.w #5,d0 lea (a1,d0.w),a3 loc_410A4: move.l (a3)+,(a6) dbf d1,loc_410A4 loc_410AA: dbf d2,loc_41094 rts ; =========================================================================== loc_410B0: move.l #0,(a6) dbf d1,loc_410B0 bra.s loc_410AA ; End of function Hud_Base ; =========================================================================== loc_410BC: bsr.w Hud_Lives2 move.l #Art_Hud,d1 ; source addreses move.w #tiles_to_bytes(ArtTile_Art_HUD_Numbers_2P),d2 ; destination VRAM address move.w #$160,d3 ; DMA transfer length jmp (QueueDMATransfer).l ; =========================================================================== charset ' ',$FF charset '0',0 charset '1',2 charset '2',4 charset '3',6 charset '4',8 charset '5',$A charset '6',$C charset '7',$E charset '8',$10 charset '9',$12 charset ':',$14 charset 'E',$16 ; byte_410D4: Hud_TilesBase: dc.b "E 0" dc.b "0:00" ; byte_410E0: ; Hud_TilesZero: Hud_TilesRings: dc.b " 0" Hud_TilesBase_End charset even ; --------------------------------------------------------------------------- ; Subroutine to load debug mode numbers patterns ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_410E4: HudDb_XY: move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Score_E),VRAM,WRITE),(VDP_control_port).l move.w (Camera_X_pos).w,d1 swap d1 move.w (MainCharacter+x_pos).w,d1 bsr.s HudDb_XY2 move.w (Camera_Y_pos).w,d1 swap d1 move.w (MainCharacter+y_pos).w,d1 ; loc_41104: HudDb_XY2: moveq #7,d6 lea (Art_Text).l,a1 ; loc_4110C: HudDb_XYLoop: rol.w #4,d1 move.w d1,d2 andi.w #$F,d2 cmpi.w #$A,d2 blo.s loc_4111E addi_.w #7,d2 loc_4111E: lsl.w #5,d2 lea (a1,d2.w),a3 rept 8 move.l (a3)+,(a6) endm swap d1 dbf d6,HudDb_XYLoop rts ; End of function HudDb_XY ; --------------------------------------------------------------------------- ; Subroutine to load rings numbers patterns ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_4113C: Hud_Rings: lea (Hud_100).l,a2 moveq #2,d6 bra.s Hud_LoadArt ; End of function Hud_Rings ; --------------------------------------------------------------------------- ; Subroutine to load score numbers patterns ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_41146: Hud_Score: lea (Hud_100000).l,a2 moveq #5,d6 ; loc_4114E: Hud_LoadArt: moveq #0,d4 lea Art_Hud(pc),a1 ; loc_41154: Hud_ScoreLoop: moveq #0,d2 move.l (a2)+,d3 loc_41158: sub.l d3,d1 bcs.s loc_41160 addq.w #1,d2 bra.s loc_41158 ; =========================================================================== loc_41160: add.l d3,d1 tst.w d2 beq.s loc_4116A move.w #1,d4 loc_4116A: tst.w d4 beq.s loc_41198 lsl.w #6,d2 move.l d0,4(a6) lea (a1,d2.w),a3 rept 8*hud_letter_num_tiles move.l (a3)+,(a6) endm loc_41198: addi.l #hud_letter_vdp_delta,d0 dbf d6,Hud_ScoreLoop rts ; End of function Hud_Score ; --------------------------------------------------------------------------- ; Subroutine to load countdown numbers on the continue screen ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_411A4: ContScrCounter: move.l #vdpComm(tiles_to_bytes(ArtTile_ContinueCountdown),VRAM,WRITE),(VDP_control_port).l lea (VDP_data_port).l,a6 lea (Hud_10).l,a2 moveq #1,d6 moveq #0,d4 lea Art_Hud(pc),a1 ; loc_411C2: ContScr_Loop: moveq #0,d2 move.l (a2)+,d3 loc_411C6: sub.l d3,d1 bcs.s loc_411CE addq.w #1,d2 bra.s loc_411C6 ; =========================================================================== loc_411CE: add.l d3,d1 lsl.w #6,d2 lea (a1,d2.w),a3 rept 16 move.l (a3)+,(a6) endm dbf d6,ContScr_Loop ; repeat 1 more time rts ; End of function ContScrCounter ; =========================================================================== ; --------------------------------------------------------------------------- ; for HUD counter ; --------------------------------------------------------------------------- ; byte_411FC: Hud_100000: dc.l 100000 ; byte_41200: ; Hud_10000: dc.l 10000 ; byte_41204: Hud_1000: dc.l 1000 ; byte_41208: Hud_100: dc.l 100 ; byte_4120C: Hud_10: dc.l 10 ; byte_41210: Hud_1: dc.l 1 ; --------------------------------------------------------------------------- ; Subroutine to load time numbers patterns ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_41214: Hud_Mins: lea_ Hud_1,a2 moveq #0,d6 bra.s loc_41222 ; =========================================================================== ; loc_4121C: Hud_Secs: lea_ Hud_10,a2 moveq #1,d6 loc_41222: moveq #0,d4 lea Art_Hud(pc),a1 ; loc_41228: Hud_TimeLoop: moveq #0,d2 move.l (a2)+,d3 loc_4122C: sub.l d3,d1 bcs.s loc_41234 addq.w #1,d2 bra.s loc_4122C ; =========================================================================== loc_41234: add.l d3,d1 tst.w d2 beq.s loc_4123E move.w #1,d4 loc_4123E: lsl.w #6,d2 move.l d0,4(a6) lea (a1,d2.w),a3 rept 8*hud_letter_num_tiles move.l (a3)+,(a6) endm addi.l #hud_letter_vdp_delta,d0 dbf d6,Hud_TimeLoop rts ; End of function Hud_Mins ; --------------------------------------------------------------------------- ; Subroutine to load time/ring bonus numbers patterns ; --------------------------------------------------------------------------- ; =========================================================================== ; loc_41274: Hud_TimeRingBonus: lea_ Hud_1000,a2 moveq #3,d6 moveq #0,d4 lea Art_Hud(pc),a1 ; loc_41280: Hud_BonusLoop: moveq #0,d2 move.l (a2)+,d3 loc_41284: sub.l d3,d1 bcs.s loc_4128C addq.w #1,d2 bra.s loc_41284 ; =========================================================================== loc_4128C: add.l d3,d1 tst.w d2 beq.s loc_41296 move.w #1,d4 loc_41296: tst.w d4 beq.s Hud_ClrBonus lsl.w #6,d2 lea (a1,d2.w),a3 rept 8*hud_letter_num_tiles move.l (a3)+,(a6) endm loc_412C0: dbf d6,Hud_BonusLoop ; repeat 3 more times rts ; =========================================================================== ; loc_412C6: Hud_ClrBonus: moveq #8*hud_letter_num_tiles-1,d5 ; loc_412C8: Hud_ClrBonusLoop: move.l #0,(a6) dbf d5,Hud_ClrBonusLoop bra.s loc_412C0 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; --------------------------------------------------------------------------- ; Subroutine to load uncompressed lives counter patterns (Sonic) ; --------------------------------------------------------------------------- ; sub_412D4: Hud_Lives2: move.l #vdpComm(tiles_to_bytes(ArtTile_ArtUnc_2p_life_counter_lives),VRAM,WRITE),d0 moveq #0,d1 move.b (Life_count_2P).w,d1 bra.s loc_412EE ; End of function Hud_Lives2 ; --------------------------------------------------------------------------- ; Subroutine to load uncompressed lives counter patterns (Tails) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_412E2: Hud_Lives: move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_life_counter_lives),VRAM,WRITE),d0 moveq #0,d1 move.b (Life_count).w,d1 loc_412EE: lea_ Hud_10,a2 moveq #1,d6 moveq #0,d4 lea Art_LivesNums(pc),a1 ; loc_412FA: Hud_LivesLoop: move.l d0,4(a6) moveq #0,d2 move.l (a2)+,d3 - sub.l d3,d1 bcs.s loc_4130A addq.w #1,d2 bra.s - ; =========================================================================== loc_4130A: add.l d3,d1 tst.w d2 beq.s loc_41314 move.w #1,d4 loc_41314: tst.w d4 beq.s Hud_ClrLives loc_41318: lsl.w #5,d2 lea (a1,d2.w),a3 rept 8 move.l (a3)+,(a6) endm loc_4132E: addi.l #hud_letter_vdp_delta,d0 dbf d6,Hud_LivesLoop ; repeat 1 more time rts ; =========================================================================== ; loc_4133A: Hud_ClrLives: tst.w d6 beq.s loc_41318 moveq #7,d5 ; loc_41340: Hud_ClrLivesLoop: move.l #0,(a6) dbf d5,Hud_ClrLivesLoop bra.s loc_4132E ; End of function Hud_Lives ; =========================================================================== ; ArtUnc_4134C: Art_Hud: BINCLUDE "art/uncompressed/Big and small numbers used on counters - 1.bin" ; ArtUnc_4164C: Art_LivesNums: BINCLUDE "art/uncompressed/Big and small numbers used on counters - 2.bin" ; ArtUnc_4178C: Art_Text: BINCLUDE "art/uncompressed/Big and small numbers used on counters - 3.bin" if ~~removeJmpTos JmpTo_DrawSprite_2P_Loop jmp (DrawSprite_2P_Loop).l JmpTo_DrawSprite_Loop jmp (DrawSprite_Loop).l align 4 endif ; =========================================================================== ; --------------------------------------------------------------------------- ; When debug mode is currently in use ; --------------------------------------------------------------------------- ; loc_41A78: DebugMode: moveq #0,d0 move.b (Debug_placement_mode).w,d0 move.w Debug_Index(pc,d0.w),d1 jmp Debug_Index(pc,d1.w) ; =========================================================================== ; off_41A86: Debug_Index: offsetTable offsetTableEntry.w Debug_Init ; 0 offsetTableEntry.w Debug_Main ; 2 ; =========================================================================== ; loc_41A8A: Debug_Main: Debug_Init: addq.b #2,(Debug_placement_mode).w move.w (Camera_Min_Y_pos).w,(Camera_Min_Y_pos_Debug_Copy).w move.w (Camera_Max_Y_pos).w,(Camera_Max_Y_pos_Debug_Copy).w cmpi.b #sky_chase_zone,(Current_Zone).w bne.s + move.w #0,(Camera_Min_X_pos).w move.w #$3FFF,(Camera_Max_X_pos).w + andi.w #$7FF,(MainCharacter+y_pos).w andi.w #$7FF,(Camera_Y_pos).w andi.w #$7FF,(Camera_BG_Y_pos).w clr.b (Scroll_lock).w move.b #0,mapping_frame(a0) move.b #AniIDSonAni_Walk,anim(a0) ; S1 leftover cmpi.b #GameModeID_SpecialStage,(Game_Mode).w ; special stage mode? (you can't enter debug mode in S2's special stage) bne.s .islevel ; if not, branch moveq #6,d0 ; force zone 6's debug object list (was the ending in S1) bra.s .selectlist ; =========================================================================== .islevel: moveq #0,d0 move.b (Current_Zone).w,d0 .selectlist: lea (JmpTbl_DbgObjLists).l,a2 add.w d0,d0 adda.w (a2,d0.w),a2 move.w (a2)+,d6 cmp.b (Debug_object).w,d6 bhi.s + move.b #0,(Debug_object).w + bsr.w LoadDebugObjectSprite move.b #$C,(Debug_Accel_Timer).w move.b #1,(Debug_Speed).w ; loc_41B0C: Debug_Main: ; S1 leftover moveq #6,d0 ; force zone 6's debug object list (was the ending in S1) cmpi.b #GameModeID_SpecialStage,(Game_Mode).w ; special stage mode? (you can't enter debug mode in S2's special stage) beq.s .isntlevel ; if yes, branch moveq #0,d0 move.b (Current_Zone).w,d0 .isntlevel: lea (JmpTbl_DbgObjLists).l,a2 add.w d0,d0 adda.w (a2,d0.w),a2 move.w (a2)+,d6 bsr.w Debug_Control jmp (DisplaySprite).l ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_41B34: Debug_Control: ;Debug_ControlMovement: moveq #0,d4 move.w #1,d1 move.b (Ctrl_1_Press).w,d4 andi.w #button_up_mask|button_down_mask|button_left_mask|button_right_mask,d4 bne.s Debug_Move move.b (Ctrl_1_Held).w,d0 andi.w #button_up_mask|button_down_mask|button_left_mask|button_right_mask,d0 bne.s Debug_ContinueMoving move.b #$C,(Debug_Accel_Timer).w move.b #$F,(Debug_Speed).w bra.w Debug_ControlObjects ; =========================================================================== ; loc_41B5E: Debug_ContinueMoving: subq.b #1,(Debug_Accel_Timer).w bne.s Debug_TimerNotOver move.b #1,(Debug_Accel_Timer).w addq.b #1,(Debug_Speed).w bne.s Debug_Move move.b #-1,(Debug_Speed).w ; loc_41B76: Debug_Move: move.b (Ctrl_1_Held).w,d4 ; loc_41B7A: Debug_TimerNotOver: moveq #0,d1 move.b (Debug_Speed).w,d1 addq.w #1,d1 swap d1 asr.l #4,d1 move.l y_pos(a0),d2 move.l x_pos(a0),d3 ; Move up btst #button_up,d4 beq.s .upNotHeld sub.l d1,d2 moveq #0,d0 move.w (Camera_Min_Y_pos).w,d0 swap d0 cmp.l d0,d2 bge.s .minYPosNotReached move.l d0,d2 .minYPosNotReached: ; loc_41BA4: .upNotHeld: ; Move down btst #button_down,d4 beq.s .downNotHeld add.l d1,d2 moveq #0,d0 move.w (Camera_Max_Y_pos).w,d0 addi.w #224-1,d0 swap d0 cmp.l d0,d2 blt.s .maxYPosNotReached move.l d0,d2 .maxYPosNotReached: ; loc_41BBE: .downNotHeld: ; Move left btst #button_left,d4 beq.s .leftNotHeld sub.l d1,d3 bcc.s .minXPosNotReached moveq #0,d3 .minXPosNotReached: ; loc_41BCA: .leftNotHeld: ; Move right btst #button_right,d4 beq.s .rightNotHeld add.l d1,d3 ; loc_41BD2: .rightNotHeld: move.l d2,y_pos(a0) move.l d3,x_pos(a0) ; loc_41BDA: Debug_ControlObjects: ;Debug_CycleObjectsBackwards: btst #button_A,(Ctrl_1_Held).w beq.s Debug_SpawnObject btst #button_C,(Ctrl_1_Press).w beq.s Debug_CycleObjects ; Cycle backwards though object list subq.b #1,(Debug_object).w bcc.s BranchTo_LoadDebugObjectSprite add.b d6,(Debug_object).w bra.s BranchTo_LoadDebugObjectSprite ; =========================================================================== ; loc_41BF6: Debug_CycleObjects: btst #button_A,(Ctrl_1_Press).w beq.s Debug_SpawnObject ; Cycle forwards though object list addq.b #1,(Debug_object).w cmp.b (Debug_object).w,d6 bhi.s BranchTo_LoadDebugObjectSprite move.b #0,(Debug_object).w BranchTo_LoadDebugObjectSprite bra.w LoadDebugObjectSprite ; =========================================================================== ; loc_41C12: Debug_SpawnObject: btst #button_C,(Ctrl_1_Press).w beq.s Debug_ExitDebugMode ; Spawn object jsr (SingleObjLoad).l bne.s Debug_ExitDebugMode move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) _move.b mappings(a0),id(a1) ; load obj move.b render_flags(a0),render_flags(a1) move.b render_flags(a0),status(a1) andi.b #$7F,status(a1) moveq #0,d0 move.b (Debug_object).w,d0 lsl.w #3,d0 move.b 4(a2,d0.w),subtype(a1) rts ; =========================================================================== ; loc_41C56: Debug_ExitDebugMode: btst #button_B,(Ctrl_1_Press).w beq.s return_41CB6 ; Exit debug mode moveq #0,d0 move.w d0,(Debug_placement_mode).w lea (MainCharacter).w,a1 ; a1=character move.l #Mapunc_Sonic,mappings(a1) move.w #make_art_tile(ArtTile_ArtUnc_Sonic,0,0),art_tile(a1) tst.w (Two_player_mode).w beq.s .notTwoPlayerMode move.w #make_art_tile_2p(ArtTile_ArtUnc_Sonic,0,0),art_tile(a1) ; loc_41C82: .notTwoPlayerMode: bsr.s sub_41CB8 move.b #$13,y_radius(a1) move.b #9,x_radius(a1) move.w (Camera_Min_Y_pos_Debug_Copy).w,(Camera_Min_Y_pos).w move.w (Camera_Max_Y_pos_Debug_Copy).w,(Camera_Max_Y_pos).w ; useless leftover; this is for S1's special stage cmpi.b #GameModeID_SpecialStage,(Game_Mode).w ; special stage mode? bne.s return_41CB6 ; if not, branch move.b #AniIDSonAni_Roll,(MainCharacter+anim).w bset #2,(MainCharacter+status).w bset #1,(MainCharacter+status).w return_41CB6: rts ; End of function Debug_Control ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_41CB8: move.b d0,anim(a1) move.w d0,2+x_pos(a1) ; subpixel x move.w d0,2+y_pos(a1) ; subpixel y move.b d0,obj_control(a1) move.b d0,spindash_flag(a1) move.w d0,x_vel(a1) move.w d0,y_vel(a1) move.w d0,inertia(a1) move.b #2,status(a1) move.b #2,routine(a1) move.b #0,routine_secondary(a1) rts ; End of function sub_41CB8 ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; sub_41CEC: LoadDebugObjectSprite: moveq #0,d0 move.b (Debug_object).w,d0 lsl.w #3,d0 move.l (a2,d0.w),mappings(a0) move.w 6(a2,d0.w),art_tile(a0) move.b 5(a2,d0.w),mapping_frame(a0) jsrto (Adjust2PArtPointer).l, JmpTo66_Adjust2PArtPointer rts ; End of function LoadDebugObjectSprite ; =========================================================================== ; --------------------------------------------------------------------------- ; OBJECT DEBUG LISTS ; The jump table goes by level ID, so Metropolis Zone's list is repeated to ; account for its third act. Hidden Palace Zone uses Oil Ocean Zone's list. ; --------------------------------------------------------------------------- JmpTbl_DbgObjLists: zoneOrderedOffsetTable 2,1 zoneOffsetTableEntry.w DbgObjList_EHZ ; 0 zoneOffsetTableEntry.w DbgObjList_Def ; 1 zoneOffsetTableEntry.w DbgObjList_Def ; 2 zoneOffsetTableEntry.w DbgObjList_Def ; 3 zoneOffsetTableEntry.w DbgObjList_MTZ ; 4 zoneOffsetTableEntry.w DbgObjList_MTZ ; 5 zoneOffsetTableEntry.w DbgObjList_WFZ ; 6 zoneOffsetTableEntry.w DbgObjList_HTZ ; 7 zoneOffsetTableEntry.w DbgObjList_HPZ ; 8 zoneOffsetTableEntry.w DbgObjList_Def ; 9 zoneOffsetTableEntry.w DbgObjList_OOZ ; $A zoneOffsetTableEntry.w DbgObjList_MCZ ; $B zoneOffsetTableEntry.w DbgObjList_CNZ ; $C zoneOffsetTableEntry.w DbgObjList_CPZ ; $D zoneOffsetTableEntry.w DbgObjList_Def ; $E zoneOffsetTableEntry.w DbgObjList_ARZ ; $F zoneOffsetTableEntry.w DbgObjList_SCZ ; $10 zoneTableEnd ; macro for a debug object list header ; must be on the same line as a label that has a corresponding _End label later dbglistheader macro {INTLABEL} __LABEL__ label * dc.w ((__LABEL___End - __LABEL__ - 2) >> 3) endm ; macro to define debug list object data dbglistobj macro obj, mapaddr, subtype, frame, vram dc.l obj<<24|mapaddr dc.b subtype,frame dc.w vram endm DbgObjList_Def: dbglistheader dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) ; obj25 = ring dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0) ; obj26 = monitor DbgObjList_Def_End DbgObjList_EHZ: dbglistheader dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0) dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0) dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, 9, 1, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_EHZWaterfall, Obj49_MapUnc_20C50, 0, 0, make_art_tile(ArtTile_ArtNem_Waterfall,1,0) dbglistobj ObjID_EHZWaterfall, Obj49_MapUnc_20C50, 2, 3, make_art_tile(ArtTile_ArtNem_Waterfall,1,0) dbglistobj ObjID_EHZWaterfall, Obj49_MapUnc_20C50, 4, 5, make_art_tile(ArtTile_ArtNem_Waterfall,1,0) dbglistobj ObjID_EHZPlatform, Obj18_MapUnc_107F6, 1, 0, make_art_tile(ArtTile_ArtKos_LevelArt,2,0) dbglistobj ObjID_EHZPlatform, Obj18_MapUnc_107F6, $9A, 1, make_art_tile(ArtTile_ArtKos_LevelArt,2,0) dbglistobj ObjID_Spikes, Obj36_MapUnc_15B68, 0, 0, make_art_tile(ArtTile_ArtNem_Spikes,1,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $81, 0, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $90, 3, make_art_tile(ArtTile_ArtNem_HrzntlSprng,0,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $A0, 6, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $30, 7, make_art_tile(ArtTile_ArtNem_DignlSprng,0,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $40, $A, make_art_tile(ArtTile_ArtNem_DignlSprng,0,0) dbglistobj ObjID_Buzzer, Obj4B_MapUnc_2D2EA, 0, 0, make_art_tile(ArtTile_ArtNem_Buzzer,0,0) dbglistobj ObjID_Masher, Obj5C_MapUnc_2D442, 0, 0, make_art_tile(ArtTile_ArtNem_Masher,0,0) dbglistobj ObjID_Coconuts, Obj9D_Obj98_MapUnc_37D96, $1E, 0, make_art_tile(ArtTile_ArtNem_Coconuts,0,0) dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0) DbgObjList_EHZ_End DbgObjList_MTZ: dbglistheader dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0) dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0) dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, 9, 1, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_SteamSpring, Obj42_MapUnc_2686C, 1, 7, make_art_tile(ArtTile_ArtKos_LevelArt,3,0) dbglistobj ObjID_MTZTwinStompers, Obj64_MapUnc_26A5C, 1, 0, make_art_tile(ArtTile_ArtKos_LevelArt,1,0) dbglistobj ObjID_MTZTwinStompers, Obj64_MapUnc_26A5C, $11, 1, make_art_tile(ArtTile_ArtKos_LevelArt,1,0) dbglistobj ObjID_MTZLongPlatform, Obj65_Obj6A_Obj6B_MapUnc_26EC8, $80, 0, make_art_tile(ArtTile_ArtKos_LevelArt,3,0) dbglistobj ObjID_MTZLongPlatform, Obj65_Obj6A_Obj6B_MapUnc_26EC8, $13, 1, make_art_tile(ArtTile_ArtKos_LevelArt,3,0) dbglistobj ObjID_Button, Obj47_MapUnc_24D96, 0, 2, make_art_tile(ArtTile_ArtNem_Button,0,0) dbglistobj ObjID_Barrier, Obj2D_MapUnc_11822, 1, 1, make_art_tile(ArtTile_ArtKos_LevelArt,3,0) dbglistobj ObjID_MTZSpringWall, Obj66_MapUnc_27120, 1, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,1) dbglistobj ObjID_MTZSpringWall, Obj66_MapUnc_27120, $11, 1, make_art_tile(ArtTile_ArtNem_Powerups,0,1) dbglistobj ObjID_SpikyBlock, Obj68_Obj6D_MapUnc_27750, 0, 4, make_art_tile(ArtTile_ArtNem_MtzSpikeBlock,3,0) dbglistobj ObjID_Nut, Obj69_MapUnc_27A26, 4, 0, make_art_tile(ArtTile_ArtNem_MtzAsstBlocks,1,0) dbglistobj ObjID_MTZMovingPforms, Obj65_Obj6A_Obj6B_MapUnc_26EC8, 0, 1, make_art_tile(ArtTile_ArtKos_LevelArt,3,0) dbglistobj ObjID_MTZPlatform, Obj65_Obj6A_Obj6B_MapUnc_26EC8, 7, 1, make_art_tile(ArtTile_ArtKos_LevelArt,3,0) dbglistobj ObjID_FloorSpike, Obj68_Obj6D_MapUnc_27750, 0, 0, make_art_tile(ArtTile_ArtNem_MtzSpike,1,0) dbglistobj ObjID_LargeRotPform, Obj6E_MapUnc_2852C, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,3,0) dbglistobj ObjID_LargeRotPform, Obj6E_MapUnc_2852C, $10, 1, make_art_tile(ArtTile_ArtKos_LevelArt,3,0) dbglistobj ObjID_LargeRotPform, Obj6E_MapUnc_2852C, $20, 2, make_art_tile(ArtTile_ArtKos_LevelArt,3,0) dbglistobj ObjID_Cog, Obj70_MapUnc_28786, $10, 0, make_art_tile(ArtTile_ArtNem_MtzWheel,3,1) dbglistobj ObjID_MTZLavaBubble, Obj71_MapUnc_11576, $22, 5, make_art_tile(ArtTile_ArtNem_MtzLavaBubble,2,0) dbglistobj ObjID_Scenery, Obj1C_MapUnc_11552, 0, 0, make_art_tile(ArtTile_ArtNem_BoltEnd_Rope,2,0) dbglistobj ObjID_Scenery, Obj1C_MapUnc_11552, 1, 1, make_art_tile(ArtTile_ArtNem_BoltEnd_Rope,2,0) dbglistobj ObjID_Scenery, Obj1C_MapUnc_11552, 3, 2, make_art_tile(ArtTile_ArtNem_BoltEnd_Rope,1,0) dbglistobj ObjID_MTZLongPlatform, Obj65_Obj6A_Obj6B_MapUnc_26EC8, $B0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,3,0) dbglistobj ObjID_Shellcracker, Obj9F_MapUnc_38314, $24, 0, make_art_tile(ArtTile_ArtNem_Crabmeat,0,0) dbglistobj ObjID_Asteron, ObjA4_Obj98_MapUnc_38A96, $2E, 0, make_art_tile(ArtTile_ArtNem_MtzSupernova,0,1) dbglistobj ObjID_Slicer, ObjA1_MapUnc_385E2, $28, 0, make_art_tile(ArtTile_ArtNem_MtzMantis,1,0) dbglistobj ObjID_LavaMarker, Obj31_MapUnc_20E74, 0, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,1) dbglistobj ObjID_LavaMarker, Obj31_MapUnc_20E74, 1, 1, make_art_tile(ArtTile_ArtNem_Powerups,0,1) dbglistobj ObjID_LavaMarker, Obj31_MapUnc_20E74, 2, 2, make_art_tile(ArtTile_ArtNem_Powerups,0,1) dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0) DbgObjList_MTZ_End DbgObjList_WFZ: dbglistheader dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0) dbglistobj ObjID_WFZPalSwitcher, Obj03_MapUnc_1FFB8, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,0,0) dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0) dbglistobj ObjID_Cloud, ObjB3_MapUnc_3B32C, $5E, 0, make_art_tile(ArtTile_ArtNem_Clouds,2,0) dbglistobj ObjID_Cloud, ObjB3_MapUnc_3B32C, $60, 1, make_art_tile(ArtTile_ArtNem_Clouds,2,0) dbglistobj ObjID_Cloud, ObjB3_MapUnc_3B32C, $62, 2, make_art_tile(ArtTile_ArtNem_Clouds,2,0) dbglistobj ObjID_VPropeller, ObjB4_MapUnc_3B3BE, $64, 0, make_art_tile(ArtTile_ArtNem_WfzVrtclPrpllr,1,1) dbglistobj ObjID_HPropeller, ObjB5_MapUnc_3B548, $66, 0, make_art_tile(ArtTile_ArtNem_WfzHrzntlPrpllr,1,1) dbglistobj ObjID_HPropeller, ObjB5_MapUnc_3B548, $68, 0, make_art_tile(ArtTile_ArtNem_WfzHrzntlPrpllr,1,1) dbglistobj ObjID_CluckerBase, ObjAD_Obj98_MapUnc_395B4, $42, $C, make_art_tile(ArtTile_ArtNem_WfzScratch,0,0) dbglistobj ObjID_Clucker, ObjAD_Obj98_MapUnc_395B4, $44, $B, make_art_tile(ArtTile_ArtNem_WfzScratch,0,0) dbglistobj ObjID_TiltingPlatform, ObjB6_MapUnc_3B856, $6A, 0, make_art_tile(ArtTile_ArtNem_WfzTiltPlatforms,1,1) dbglistobj ObjID_TiltingPlatform, ObjB6_MapUnc_3B856, $6C, 0, make_art_tile(ArtTile_ArtNem_WfzTiltPlatforms,1,1) dbglistobj ObjID_TiltingPlatform, ObjB6_MapUnc_3B856, $6E, 0, make_art_tile(ArtTile_ArtNem_WfzTiltPlatforms,1,1) dbglistobj ObjID_TiltingPlatform, ObjB6_MapUnc_3B856, $70, 0, make_art_tile(ArtTile_ArtNem_WfzTiltPlatforms,1,1) dbglistobj ObjID_VerticalLaser, ObjB7_MapUnc_3B8E4, $72, 0, make_art_tile(ArtTile_ArtNem_WfzVrtclLazer,2,1) dbglistobj ObjID_WallTurret, ObjB8_Obj98_MapUnc_3BA46, $74, 0, make_art_tile(ArtTile_ArtNem_WfzWallTurret,0,0) dbglistobj ObjID_Laser, ObjB9_MapUnc_3BB18, $76, 0, make_art_tile(ArtTile_ArtNem_WfzHrzntlLazer,2,1) dbglistobj ObjID_WFZWheel, ObjBA_MapUnc_3BB70, $78, 0, make_art_tile(ArtTile_ArtNem_WfzConveyorBeltWheel,2,1) dbglistobj ObjID_WFZShipFire, ObjBC_MapUnc_3BC08, $7C, 0, make_art_tile(ArtTile_ArtNem_WfzThrust,2,0) dbglistobj ObjID_SmallMetalPform, ObjBD_MapUnc_3BD3E, $7E, 0, make_art_tile(ArtTile_ArtNem_WfzBeltPlatform,3,1) dbglistobj ObjID_SmallMetalPform, ObjBD_MapUnc_3BD3E, $80, 0, make_art_tile(ArtTile_ArtNem_WfzBeltPlatform,3,1) dbglistobj ObjID_LateralCannon, ObjBE_MapUnc_3BE46, $82, 0, make_art_tile(ArtTile_ArtNem_WfzGunPlatform,3,1) dbglistobj ObjID_WFZStick, ObjBF_MapUnc_3BEE0, $84, 0, make_art_tile(ArtTile_ArtNem_WfzUnusedBadnik,3,1) dbglistobj ObjID_SpeedLauncher, ObjC0_MapUnc_3C098, 8, 0, make_art_tile(ArtTile_ArtNem_WfzLaunchCatapult,1,0) dbglistobj ObjID_BreakablePlating, ObjC1_MapUnc_3C280, $88, 0, make_art_tile(ArtTile_ArtNem_BreakPanels,3,1) dbglistobj ObjID_Rivet, ObjC2_MapUnc_3C3C2, $8A, 0, make_art_tile(ArtTile_ArtNem_WfzSwitch,1,1) dbglistobj ObjID_WFZPlatform, Obj19_MapUnc_2222A, $38, 3, make_art_tile(ArtTile_ArtNem_WfzFloatingPlatform,1,1) dbglistobj ObjID_Grab, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_MovingVine, Obj80_MapUnc_29DD0, 0, 0, make_art_tile(ArtTile_ArtNem_WfzHook_Fudge,1,0) dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0) DbgObjList_WFZ_End DbgObjList_HTZ: dbglistheader dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0) dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0) dbglistobj ObjID_ForcedSpin, Obj03_MapUnc_1FFB8, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,0,0) dbglistobj ObjID_ForcedSpin, Obj03_MapUnc_1FFB8, 4, 4, make_art_tile(ArtTile_ArtNem_Ring,0,0) dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, 9, 1, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_EHZPlatform, Obj18_MapUnc_107F6, 1, 0, make_art_tile(ArtTile_ArtKos_LevelArt,2,0) dbglistobj ObjID_EHZPlatform, Obj18_MapUnc_107F6, $9A, 1, make_art_tile(ArtTile_ArtKos_LevelArt,2,0) dbglistobj ObjID_Spikes, Obj36_MapUnc_15B68, 0, 0, make_art_tile(ArtTile_ArtNem_Spikes,1,0) dbglistobj ObjID_Seesaw, Obj14_MapUnc_21CF0, 0, 0, make_art_tile(ArtTile_ArtNem_HtzSeeSaw,0,0) dbglistobj ObjID_Barrier, Obj2D_MapUnc_11822, 0, 0, make_art_tile(ArtTile_ArtNem_HtzValveBarrier,1,0) dbglistobj ObjID_SmashableGround, Obj2F_MapUnc_236FA, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,2,1) dbglistobj ObjID_LavaBubble, Obj20_MapUnc_23254, $44, 2, make_art_tile(ArtTile_ArtNem_HtzFireball,0,1) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $81, 0, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $90, 3, make_art_tile(ArtTile_ArtNem_HrzntlSprng,0,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $A0, 6, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $30, 7, make_art_tile(ArtTile_ArtNem_DignlSprng,0,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $40, $A, make_art_tile(ArtTile_ArtNem_DignlSprng,0,0) dbglistobj ObjID_HTZLift, Obj16_MapUnc_21F14, 0, 0, make_art_tile(ArtTile_ArtNem_HtzZipline,2,0) dbglistobj ObjID_BridgeStake, Obj16_MapUnc_21F14, 4, 3, make_art_tile(ArtTile_ArtNem_HtzZipline,2,0) dbglistobj ObjID_BridgeStake, Obj16_MapUnc_21F14, 5, 4, make_art_tile(ArtTile_ArtNem_HtzZipline,2,0) dbglistobj ObjID_Scenery, Obj1C_MapUnc_113D6, 7, 0, make_art_tile(ArtTile_ArtKos_LevelArt,2,0) dbglistobj ObjID_Scenery, Obj1C_MapUnc_113D6, 8, 1, make_art_tile(ArtTile_ArtKos_LevelArt,2,0) dbglistobj ObjID_BreakableRock, Obj32_MapUnc_23852, 0, 0, make_art_tile(ArtTile_ArtNem_HtzRock,2,0) dbglistobj ObjID_LavaMarker, Obj31_MapUnc_20E74, 0, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,1) dbglistobj ObjID_LavaMarker, Obj31_MapUnc_20E74, 1, 1, make_art_tile(ArtTile_ArtNem_Powerups,0,1) dbglistobj ObjID_LavaMarker, Obj31_MapUnc_20E74, 2, 2, make_art_tile(ArtTile_ArtNem_Powerups,0,1) dbglistobj ObjID_Rexon2, Obj94_Obj98_MapUnc_37678, $E, 2, make_art_tile(ArtTile_ArtNem_Rexon,3,0) dbglistobj ObjID_Spiker, Obj92_Obj93_MapUnc_37092, $A, 0, make_art_tile(ArtTile_ArtKos_LevelArt,0,0) dbglistobj ObjID_Sol, Obj95_MapUnc_372E6, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,0,0) dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0) DbgObjList_HTZ_End DbgObjList_HPZ:; dbglistheader ; dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) ; dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0) ;DbgObjList_HPZ_End DbgObjList_OOZ: dbglistheader dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0) dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0) dbglistobj ObjID_OOZPoppingPform, Obj33_MapUnc_23DDC, 1, 0, make_art_tile(ArtTile_ArtNem_BurnerLid,3,0) dbglistobj ObjID_SlidingSpike, Obj43_MapUnc_23FE0, 0, 0, make_art_tile(ArtTile_ArtNem_SpikyThing,2,1) dbglistobj ObjID_OOZMovingPform, Obj19_MapUnc_2222A, $23, 2, make_art_tile(ArtTile_ArtNem_OOZElevator,3,0) dbglistobj ObjID_OOZSpring, Obj45_MapUnc_2451A, 2, 0, make_art_tile(ArtTile_ArtNem_PushSpring,2,0) dbglistobj ObjID_OOZSpring, Obj45_MapUnc_2451A, $12, $A, make_art_tile(ArtTile_ArtNem_PushSpring,2,0) dbglistobj ObjID_OOZBall, Obj46_MapUnc_24C52, 0, 1, make_art_tile(ArtTile_ArtNem_BallThing,3,0) dbglistobj ObjID_Button, Obj47_MapUnc_24D96, 0, 2, make_art_tile(ArtTile_ArtNem_Button,0,0) dbglistobj ObjID_SwingingPlatform, Obj15_MapUnc_101E8, $88, 1, make_art_tile(ArtTile_ArtNem_OOZSwingPlat,2,0) dbglistobj ObjID_OOZLauncher, Obj3D_MapUnc_250BA, 0, 0, make_art_tile(ArtTile_ArtNem_StripedBlocksVert,3,0) dbglistobj ObjID_LauncherBall, Obj48_MapUnc_254FE, $80, 0, make_art_tile(ArtTile_ArtNem_LaunchBall,3,0) dbglistobj ObjID_LauncherBall, Obj48_MapUnc_254FE, $81, 1, make_art_tile(ArtTile_ArtNem_LaunchBall,3,0) dbglistobj ObjID_LauncherBall, Obj48_MapUnc_254FE, $82, 2, make_art_tile(ArtTile_ArtNem_LaunchBall,3,0) dbglistobj ObjID_LauncherBall, Obj48_MapUnc_254FE, $83, 3, make_art_tile(ArtTile_ArtNem_LaunchBall,3,0) dbglistobj ObjID_CollapsPform, Obj1F_MapUnc_110C6, 0, 0, make_art_tile(ArtTile_ArtNem_OOZPlatform,3,0) dbglistobj ObjID_Fan, Obj3F_MapUnc_2AA12, 0, 0, make_art_tile(ArtTile_ArtNem_OOZFanHoriz,3,0) dbglistobj ObjID_Fan, Obj3F_MapUnc_2AAC4, $80, 0, make_art_tile(ArtTile_ArtNem_OOZFanHoriz,3,0) dbglistobj ObjID_Aquis, Obj50_MapUnc_2CF94, 0, 0, make_art_tile(ArtTile_ArtNem_Aquis,1,0) dbglistobj ObjID_Octus, Obj4A_MapUnc_2CBFE, 0, 0, make_art_tile(ArtTile_ArtNem_Octus,1,0) dbglistobj ObjID_FallingOil, Obj1C_MapUnc_11406, $A, 0, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0) dbglistobj ObjID_FallingOil, Obj1C_MapUnc_11406, $B, 1, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0) dbglistobj ObjID_FallingOil, Obj1C_MapUnc_11406, $C, 2, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0) dbglistobj ObjID_FallingOil, Obj1C_MapUnc_11406, $D, 3, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0) dbglistobj ObjID_FallingOil, Obj1C_MapUnc_11406, $E, 4, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0) dbglistobj ObjID_FallingOil, Obj1C_MapUnc_11406, $F, 5, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0) dbglistobj ObjID_FallingOil, Obj1C_MapUnc_114AE, $10, 0, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0) dbglistobj ObjID_FallingOil, Obj1C_MapUnc_114AE, $11, 1, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0) dbglistobj ObjID_FallingOil, Obj1C_MapUnc_114AE, $12, 2, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0) dbglistobj ObjID_FallingOil, Obj1C_MapUnc_114AE, $13, 3, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0) dbglistobj ObjID_FallingOil, Obj1C_MapUnc_114AE, $14, 4, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0) dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0) DbgObjList_OOZ_End DbgObjList_MCZ: dbglistheader dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0) dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0) dbglistobj ObjID_SwingingPlatform, Obj15_Obj7A_MapUnc_10256, $48, 2, make_art_tile(ArtTile_ArtKos_LevelArt,0,0) dbglistobj ObjID_CollapsPform, Obj1F_MapUnc_11106, 0, 0, make_art_tile(ArtTile_ArtNem_MCZCollapsePlat,3,0) dbglistobj ObjID_RotatingRings, Obj73_MapUnc_28B9C, $F5, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_MCZRotPforms, Obj6A_MapUnc_27D30, $18, 0, make_art_tile(ArtTile_ArtNem_Crate,3,0) dbglistobj ObjID_Stomper, Obj2A_MapUnc_11666, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,2,0) dbglistobj ObjID_Spikes, Obj36_MapUnc_15B68, 0, 0, make_art_tile(ArtTile_ArtNem_Spikes,1,0) dbglistobj ObjID_Spikes, Obj36_MapUnc_15B68, $40, 4, make_art_tile(ArtTile_ArtNem_HorizSpike,1,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $81, 0, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $90, 3, make_art_tile(ArtTile_ArtNem_HrzntlSprng,0,0) dbglistobj ObjID_Springboard, Obj40_MapUnc_265F4, 1, 0, make_art_tile(ArtTile_ArtNem_LeverSpring,0,0) dbglistobj ObjID_InvisibleBlock, Obj74_MapUnc_20F66, $11, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,1) dbglistobj ObjID_MCZBrick, Obj75_MapUnc_28D8A, $18, 2, make_art_tile(ArtTile_ArtKos_LevelArt,1,0) dbglistobj ObjID_SlidingSpikes, Obj76_MapUnc_28F3A, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,0,0) dbglistobj ObjID_MCZBridge, Obj77_MapUnc_29064, 1, 0, make_art_tile(ArtTile_ArtNem_MCZGateLog,3,0) dbglistobj ObjID_VineSwitch, Obj7F_MapUnc_29938, 0, 0, make_art_tile(ArtTile_ArtNem_VineSwitch,3,0) dbglistobj ObjID_MovingVine, Obj80_MapUnc_29C64, 0, 0, make_art_tile(ArtTile_ArtNem_VinePulley,3,0) dbglistobj ObjID_MCZDrawbridge, Obj81_MapUnc_2A24E, 0, 1, make_art_tile(ArtTile_ArtNem_MCZGateLog,3,0) dbglistobj ObjID_SidewaysPform, Obj15_Obj7A_MapUnc_10256, $12, 0, make_art_tile(ArtTile_ArtKos_LevelArt,0,0) dbglistobj ObjID_Flasher, ObjA3_MapUnc_388F0, $2C, 0, make_art_tile(ArtTile_ArtNem_Flasher,0,1) dbglistobj ObjID_Crawlton, Obj9E_MapUnc_37FF2, $22, 0, make_art_tile(ArtTile_ArtNem_Crawlton,1,0) dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0) DbgObjList_MCZ_End DbgObjList_CNZ: dbglistheader dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0) dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0) dbglistobj ObjID_PinballMode, Obj03_MapUnc_1FFB8, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,0,0) dbglistobj ObjID_PinballMode, Obj03_MapUnc_1FFB8, 4, 4, make_art_tile(ArtTile_ArtNem_Ring,0,0) dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, 9, 1, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, $D, 5, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_RoundBumper, Obj44_MapUnc_1F85A, 0, 0, make_art_tile(ArtTile_ArtNem_CNZRoundBumper,2,0) dbglistobj ObjID_LauncherSpring, Obj85_MapUnc_2B07E, 0, 0, make_art_tile(ArtTile_ArtNem_CNZVertPlunger,0,0) dbglistobj ObjID_LauncherSpring, Obj85_MapUnc_2B0EC, $81, 0, make_art_tile(ArtTile_ArtNem_CNZDiagPlunger,0,0) dbglistobj ObjID_Flipper, Obj86_MapUnc_2B45A, 0, 0, make_art_tile(ArtTile_ArtNem_CNZFlipper,2,0) dbglistobj ObjID_Flipper, Obj86_MapUnc_2B45A, 1, 4, make_art_tile(ArtTile_ArtNem_CNZFlipper,2,0) dbglistobj ObjID_CNZRectBlocks, ObjD2_MapUnc_2B694, 1, 0, make_art_tile(ArtTile_ArtNem_CNZSnake,2,0) dbglistobj ObjID_BombPrize, ObjD3_MapUnc_2B8D4, 0, 0, make_art_tile(ArtTile_ArtNem_CNZBonusSpike,0,0) dbglistobj ObjID_CNZBigBlock, ObjD4_MapUnc_2B9CA, 0, 0, make_art_tile(ArtTile_ArtNem_BigMovingBlock,2,0) dbglistobj ObjID_CNZBigBlock, ObjD4_MapUnc_2B9CA, 2, 0, make_art_tile(ArtTile_ArtNem_BigMovingBlock,2,0) dbglistobj ObjID_Elevator, ObjD5_MapUnc_2BB40, $18, 0, make_art_tile(ArtTile_ArtNem_CNZElevator,2,0) dbglistobj ObjID_PointPokey, ObjD6_MapUnc_2BEBC, 1, 0, make_art_tile(ArtTile_ArtNem_CNZCage,0,0) dbglistobj ObjID_Bumper, ObjD7_MapUnc_2C626, 0, 0, make_art_tile(ArtTile_ArtNem_CNZHexBumper,2,0) dbglistobj ObjID_BonusBlock, ObjD8_MapUnc_2C8C4, 0, 0, make_art_tile(ArtTile_ArtNem_CNZMiniBumper,2,0) dbglistobj ObjID_BonusBlock, ObjD8_MapUnc_2C8C4, $40, 1, make_art_tile(ArtTile_ArtNem_CNZMiniBumper,2,0) dbglistobj ObjID_BonusBlock, ObjD8_MapUnc_2C8C4, $80, 2, make_art_tile(ArtTile_ArtNem_CNZMiniBumper,2,0) dbglistobj ObjID_Crawl, ObjC8_MapUnc_3D450, $AC, 0, make_art_tile(ArtTile_ArtNem_Crawl,0,1) dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0) DbgObjList_CNZ_End DbgObjList_CPZ: dbglistheader dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0) dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0) dbglistobj ObjID_TippingFloor, Obj0B_MapUnc_201A0, $70, 0, make_art_tile(ArtTile_ArtNem_CPZAnimatedBits,3,1) dbglistobj ObjID_SpeedBooster, Obj1B_MapUnc_223E2, 0, 0, make_art_tile(ArtTile_ArtNem_CPZBooster,3,1) dbglistobj ObjID_BlueBalls, Obj1D_MapUnc_22576, 5, 0, make_art_tile(ArtTile_ArtNem_CPZDroplet,3,1) dbglistobj ObjID_CPZPlatform, Obj19_MapUnc_2222A, 6, 0, make_art_tile(ArtTile_ArtNem_CPZElevator,3,0) dbglistobj ObjID_Barrier, Obj2D_MapUnc_11822, 2, 2, make_art_tile(ArtTile_ArtNem_ConstructionStripes_2,1,0) dbglistobj ObjID_BreakableBlock, Obj32_MapUnc_23886, 0, 0, make_art_tile(ArtTile_ArtNem_CPZMetalBlock,3,0) dbglistobj ObjID_CPZSquarePform, Obj6B_MapUnc_2800E, $10, 0, make_art_tile(ArtTile_ArtNem_CPZStairBlock,3,0) dbglistobj ObjID_CPZStaircase, Obj6B_MapUnc_2800E, 0, 0, make_art_tile(ArtTile_ArtNem_CPZStairBlock,3,0) dbglistobj ObjID_SidewaysPform, Obj7A_MapUnc_29564, 0, 0, make_art_tile(ArtTile_ArtNem_CPZStairBlock,3,1) dbglistobj ObjID_PipeExitSpring, Obj7B_MapUnc_29780, 2, 0, make_art_tile(ArtTile_ArtNem_CPZTubeSpring,0,0) dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, 9, 1, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, $D, 5, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_Spikes, Obj36_MapUnc_15B68, 0, 0, make_art_tile(ArtTile_ArtNem_Spikes,1,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $81, 0, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $90, 3, make_art_tile(ArtTile_ArtNem_HrzntlSprng,0,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $A0, 6, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0) dbglistobj ObjID_Springboard, Obj40_MapUnc_265F4, 1, 0, make_art_tile(ArtTile_ArtNem_LeverSpring,0,0) dbglistobj ObjID_Spiny, ObjA5_ObjA6_Obj98_MapUnc_38CCA, $32, 0, make_art_tile(ArtTile_ArtNem_Spiny,1,0) dbglistobj ObjID_SpinyOnWall, ObjA5_ObjA6_Obj98_MapUnc_38CCA, $32, 3, make_art_tile(ArtTile_ArtNem_Spiny,1,0) dbglistobj ObjID_Grabber, ObjA7_ObjA8_ObjA9_Obj98_MapUnc_3921A, $36, 0, make_art_tile(ArtTile_ArtNem_Grabber,1,1) dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0) DbgObjList_CPZ_End DbgObjList_ARZ: dbglistheader dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0) dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0) dbglistobj ObjID_SwingingPlatform, Obj15_Obj83_MapUnc_1021E, $88, 2, make_art_tile(ArtTile_ArtKos_LevelArt,0,0) dbglistobj ObjID_ARZPlatform, Obj18_MapUnc_1084E, 1, 0, make_art_tile(ArtTile_ArtKos_LevelArt,2,0) dbglistobj ObjID_ARZPlatform, Obj18_MapUnc_1084E, $9A, 1, make_art_tile(ArtTile_ArtKos_LevelArt,2,0) dbglistobj ObjID_ArrowShooter, Obj22_MapUnc_25804, 0, 1, make_art_tile(ArtTile_ArtNem_ArrowAndShooter,0,0) dbglistobj ObjID_FallingPillar, Obj23_MapUnc_259E6, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,1,0) dbglistobj ObjID_RisingPillar, Obj2B_MapUnc_25C6E, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,1,0) dbglistobj ObjID_LeavesGenerator, Obj31_MapUnc_20E74, 0, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,1) dbglistobj ObjID_LeavesGenerator, Obj31_MapUnc_20E74, 1, 1, make_art_tile(ArtTile_ArtNem_Powerups,0,1) dbglistobj ObjID_LeavesGenerator, Obj31_MapUnc_20E74, 2, 2, make_art_tile(ArtTile_ArtNem_Powerups,0,1) dbglistobj ObjID_Springboard, Obj40_MapUnc_265F4, 1, 0, make_art_tile(ArtTile_ArtNem_LeverSpring,0,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $81, 0, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $90, 3, make_art_tile(ArtTile_ArtNem_HrzntlSprng,0,0) dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $A0, 6, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0) dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, 9, 1, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_Spikes, Obj36_MapUnc_15B68, 0, 0, make_art_tile(ArtTile_ArtNem_Spikes,1,0) dbglistobj ObjID_Barrier, Obj2D_MapUnc_11822, 3, 3, make_art_tile(ArtTile_ArtNem_ARZBarrierThing,1,0) dbglistobj ObjID_CollapsPform, Obj1F_MapUnc_1115E, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,2,0) dbglistobj ObjID_SwingingPform, Obj82_MapUnc_2A476, 3, 0, make_art_tile(ArtTile_ArtKos_LevelArt,0,0) dbglistobj ObjID_SwingingPform, Obj82_MapUnc_2A476, $11, 1, make_art_tile(ArtTile_ArtKos_LevelArt,0,0) dbglistobj ObjID_ARZRotPforms, Obj15_Obj83_MapUnc_1021E, $10, 1, make_art_tile(ArtTile_ArtKos_LevelArt,0,0) dbglistobj ObjID_ARZBubbles, Obj24_MapUnc_1FBF6, $81, $E, make_art_tile(ArtTile_ArtNem_BigBubbles,0,1) dbglistobj ObjID_ChopChop, Obj91_MapUnc_36EF6, 8, 0, make_art_tile(ArtTile_ArtNem_ChopChop,1,0) dbglistobj ObjID_Whisp, Obj8C_MapUnc_36A4E, 0, 0, make_art_tile(ArtTile_ArtNem_Whisp,1,1) dbglistobj ObjID_GrounderInWall, Obj8D_MapUnc_36CF0, 2, 0, make_art_tile(ArtTile_ArtNem_Grounder,1,1) dbglistobj ObjID_GrounderInWall2, Obj8D_MapUnc_36CF0, 2, 0, make_art_tile(ArtTile_ArtNem_Grounder,1,1) dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0) DbgObjList_ARZ_End DbgObjList_SCZ: dbglistheader dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0) dbglistobj ObjID_WFZPalSwitcher, Obj03_MapUnc_1FFB8, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,0,0) dbglistobj ObjID_Cloud, ObjB3_MapUnc_3B32C, $5E, 0, make_art_tile(ArtTile_ArtNem_Clouds,2,0) dbglistobj ObjID_Cloud, ObjB3_MapUnc_3B32C, $60, 1, make_art_tile(ArtTile_ArtNem_Clouds,2,0) dbglistobj ObjID_Cloud, ObjB3_MapUnc_3B32C, $62, 2, make_art_tile(ArtTile_ArtNem_Clouds,2,0) dbglistobj ObjID_VPropeller, ObjB4_MapUnc_3B3BE, $64, 0, make_art_tile(ArtTile_ArtNem_WfzVrtclPrpllr,1,1) dbglistobj ObjID_HPropeller, ObjB5_MapUnc_3B548, $66, 0, make_art_tile(ArtTile_ArtNem_WfzHrzntlPrpllr,1,1) dbglistobj ObjID_HPropeller, ObjB5_MapUnc_3B548, $68, 0, make_art_tile(ArtTile_ArtNem_WfzHrzntlPrpllr,1,1) dbglistobj ObjID_Turtloid, Obj9A_Obj98_MapUnc_37B62, $16, 0, make_art_tile(ArtTile_ArtNem_Turtloid,0,0) dbglistobj ObjID_Balkiry, ObjAC_MapUnc_393CC, $40, 0, make_art_tile(ArtTile_ArtNem_Balkrie,0,0) dbglistobj ObjID_Nebula, Obj99_Obj98_MapUnc_3789A, $12, 0, make_art_tile(ArtTile_ArtNem_Nebula,1,1) dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0) DbgObjList_SCZ_End if ~~removeJmpTos JmpTo66_Adjust2PArtPointer jmp (Adjust2PArtPointer).l align 4 endif ; --------------------------------------------------------------------------- ; "MAIN LEVEL LOAD BLOCK" (after Nemesis) ; ; This struct array tells the engine where to find all the art associated with ; a particular zone. Each zone gets three longwords, in which it stores three ; pointers (in the lower 24 bits) and three jump table indeces (in the upper eight ; bits). The assembled data looks something like this: ; ; aaBBBBBB ; ccDDDDDD ; eeFFFFFF ; ; aa = index for primary pattern load request list ; BBBBBB = pointer to level art ; cc = index for secondary pattern load request list ; DDDDDD = pointer to 16x16 block mappings ; ee = index for palette ; FFFFFF = pointer to 128x128 block mappings ; ; Nemesis refers to this as the "main level load block". However, that name implies ; that this is code (obviously, it isn't), or at least that it points to the level's ; collision, object and ring placement arrays (it only points to art... ; although the 128x128 mappings do affect the actual level layout and collision) ; --------------------------------------------------------------------------- ; declare some global variables to be used by the levartptrs macro cur_zone_id := 0 cur_zone_str := "0" ; macro for declaring a "main level load block" (MLLB) levartptrs macro plc1,plc2,palette,art,map16x16,map128x128 !org LevelArtPointers+zone_id_{cur_zone_str}*12 dc.l (plc1<<24)|art dc.l (plc2<<24)|map16x16 dc.l (palette<<24)|map128x128 cur_zone_id := cur_zone_id+1 cur_zone_str := "\{cur_zone_id}" endm ; BEGIN SArt_Ptrs Art_Ptrs_Array[17] ; dword_42594: MainLoadBlocks: saArtPtrs: LevelArtPointers: levartptrs PLCID_Ehz1, PLCID_Ehz2, PalID_EHZ, ArtKos_EHZ, BM16_EHZ, BM128_EHZ ; 0 ; EHZ ; EMERALD HILL ZONE levartptrs PLCID_Miles1up, PLCID_MilesLife, PalID_EHZ2, ArtKos_EHZ, BM16_EHZ, BM128_EHZ ; 1 ; LEV1 ; LEVEL 1 (UNUSED) levartptrs PLCID_Tails1up, PLCID_TailsLife, PalID_WZ, ArtKos_EHZ, BM16_EHZ, BM128_EHZ ; 2 ; LEV2 ; LEVEL 2 (UNUSED) levartptrs PLCID_Unused1, PLCID_Unused2, PalID_EHZ3, ArtKos_EHZ, BM16_EHZ, BM128_EHZ ; 3 ; LEV3 ; LEVEL 3 (UNUSED) levartptrs PLCID_Mtz1, PLCID_Mtz2, PalID_MTZ, ArtKos_MTZ, BM16_MTZ, BM128_MTZ ; 4 ; MTZ ; METROPOLIS ZONE ACTS 1 & 2 levartptrs PLCID_Mtz1, PLCID_Mtz2, PalID_MTZ, ArtKos_MTZ, BM16_MTZ, BM128_MTZ ; 5 ; MTZ3 ; METROPOLIS ZONE ACT 3 levartptrs PLCID_Wfz1, PLCID_Wfz2, PalID_WFZ, ArtKos_SCZ, BM16_WFZ, BM128_WFZ ; 6 ; WFZ ; WING FORTRESS ZONE levartptrs PLCID_Htz1, PLCID_Htz2, PalID_HTZ, ArtKos_EHZ, BM16_EHZ, BM128_EHZ ; 7 ; HTZ ; HILL TOP ZONE levartptrs PLCID_Hpz1, PLCID_Hpz2, PalID_HPZ, ArtKos_HPZ, BM16_HPZ, BM128_HPZ ; 8 ; HPZ ; HIDDEN PALACE ZONE (UNUSED) levartptrs PLCID_Unused3, PLCID_Unused4, PalID_EHZ4, ArtKos_EHZ, BM16_EHZ, BM128_EHZ ; 9 ; LEV9 ; LEVEL 9 (UNUSED) levartptrs PLCID_Ooz1, PLCID_Ooz2, PalID_OOZ, ArtKos_OOZ, BM16_OOZ, BM128_OOZ ; $A ; OOZ ; OIL OCEAN ZONE levartptrs PLCID_Mcz1, PLCID_Mcz2, PalID_MCZ, ArtKos_MCZ, BM16_MCZ, BM128_MCZ ; $B ; MCZ ; MYSTIC CAVE ZONE levartptrs PLCID_Cnz1, PLCID_Cnz2, PalID_CNZ, ArtKos_CNZ, BM16_CNZ, BM128_CNZ ; $C ; CNZ ; CASINO NIGHT ZONE levartptrs PLCID_Cpz1, PLCID_Cpz2, PalID_CPZ, ArtKos_CPZ, BM16_CPZ, BM128_CPZ ; $D ; CPZ ; CHEMICAL PLANT ZONE levartptrs PLCID_Dez1, PLCID_Dez2, PalID_DEZ, ArtKos_CPZ, BM16_CPZ, BM128_CPZ ; $E ; DEZ ; DEATH EGG ZONE levartptrs PLCID_Arz1, PLCID_Arz2, PalID_ARZ, ArtKos_ARZ, BM16_ARZ, BM128_ARZ ; $F ; ARZ ; AQUATIC RUIN ZONE levartptrs PLCID_Scz1, PLCID_Scz2, PalID_SCZ, ArtKos_SCZ, BM16_WFZ, BM128_WFZ ; $10 ; SCZ ; SKY CHASE ZONE if (cur_zone_id<>no_of_zones)&&(MOMPASS=1) message "Warning: Table LevelArtPointers has \{cur_zone_id/1.0} entries, but it should have \{no_of_zones/1.0} entries" endif !org LevelArtPointers+cur_zone_id*12 ; --------------------------------------------------------------------------- ; END Art_Ptrs_Array[17] ; --------------------------------------------------------------------------- ; PATTERN LOAD REQUEST LISTS ; ; Pattern load request lists are simple structures used to load ; Nemesis-compressed art for sprites. ; ; The decompressor predictably moves down the list, so request 0 is processed first, etc. ; This only matters if your addresses are bad and you overwrite art loaded in a previous request. ; ; NOTICE: The load queue buffer can only hold $10 (16) load requests. None of the routines ; that load PLRs into the queue do any bounds checking, so it's possible to create a buffer ; overflow and completely screw up the variables stored directly after the queue buffer. ; (in my experience this is a guaranteed crash or hang) ; ; Many levels queue more than 16 items overall, ; but they don't exceed the limit because ; their PLRs are split into multiple parts (like PlrList_Mtz1 and PlrList_Mtz2) ; and they fully process the first part before requesting the rest. ; ; If you can find some extra RAM for it (which is easy in Sonic 2), ; you can increase this limit by increasing the size of Plc_Buffer. ; --------------------------------------------------------------------------- ;--------------------------------------------------------------------------------------- ; Table of pattern load request lists. Remember to use word-length data when adding lists ; otherwise you'll break the array. ;--------------------------------------------------------------------------------------- ; word_42660 ; OffInd_PlrLists: ArtLoadCues: offsetTable PLCptr_Std1: offsetTableEntry.w PlrList_Std1 ; 0 PLCptr_Std2: offsetTableEntry.w PlrList_Std2 ; 1 PLCptr_StdWtr: offsetTableEntry.w PlrList_StdWtr ; 2 PLCptr_GameOver: offsetTableEntry.w PlrList_GameOver ; 3 PLCptr_Ehz1: offsetTableEntry.w PlrList_Ehz1 ; 4 PLCptr_Ehz2: offsetTableEntry.w PlrList_Ehz2 ; 5 PLCptr_Miles1up: offsetTableEntry.w PlrList_Miles1up ; 6 PLCptr_MilesLife: offsetTableEntry.w PlrList_MilesLifeCounter ; 7 PLCptr_Tails1up: offsetTableEntry.w PlrList_Tails1up ; 8 PLCptr_TailsLife: offsetTableEntry.w PlrList_TailsLifeCounter ; 9 PLCptr_Unused1: offsetTableEntry.w PlrList_Mtz1 ; 10 PLCptr_Unused2: offsetTableEntry.w PlrList_Mtz1 ; 11 PLCptr_Mtz1: offsetTableEntry.w PlrList_Mtz1 ; 12 PLCptr_Mtz2: offsetTableEntry.w PlrList_Mtz2 ; 13 offsetTableEntry.w PlrList_Wfz1 ; 14 offsetTableEntry.w PlrList_Wfz1 ; 15 PLCptr_Wfz1: offsetTableEntry.w PlrList_Wfz1 ; 16 PLCptr_Wfz2: offsetTableEntry.w PlrList_Wfz2 ; 17 PLCptr_Htz1: offsetTableEntry.w PlrList_Htz1 ; 18 PLCptr_Htz2: offsetTableEntry.w PlrList_Htz2 ; 19 PLCptr_Hpz1: offsetTableEntry.w PlrList_Hpz1 ; 20 PLCptr_Hpz2: offsetTableEntry.w PlrList_Hpz2 ; 21 PLCptr_Unused3: offsetTableEntry.w PlrList_Ooz1 ; 22 PLCptr_Unused4: offsetTableEntry.w PlrList_Ooz1 ; 23 PLCptr_Ooz1: offsetTableEntry.w PlrList_Ooz1 ; 24 PLCptr_Ooz2: offsetTableEntry.w PlrList_Ooz2 ; 25 PLCptr_Mcz1: offsetTableEntry.w PlrList_Mcz1 ; 26 PLCptr_Mcz2: offsetTableEntry.w PlrList_Mcz2 ; 27 PLCptr_Cnz1: offsetTableEntry.w PlrList_Cnz1 ; 28 PLCptr_Cnz2: offsetTableEntry.w PlrList_Cnz2 ; 29 PLCptr_Cpz1: offsetTableEntry.w PlrList_Cpz1 ; 30 PLCptr_Cpz2: offsetTableEntry.w PlrList_Cpz2 ; 31 PLCptr_Dez1: offsetTableEntry.w PlrList_Dez1 ; 32 PLCptr_Dez2: offsetTableEntry.w PlrList_Dez2 ; 33 PLCptr_Arz1: offsetTableEntry.w PlrList_Arz1 ; 34 PLCptr_Arz2: offsetTableEntry.w PlrList_Arz2 ; 35 PLCptr_Scz1: offsetTableEntry.w PlrList_Scz1 ; 36 PLCptr_Scz2: offsetTableEntry.w PlrList_Scz2 ; 37 PLCptr_Results: offsetTableEntry.w PlrList_Results ; 38 PLCptr_Signpost: offsetTableEntry.w PlrList_Signpost ; 39 PLCptr_CpzBoss: offsetTableEntry.w PlrList_CpzBoss ; 40 PLCptr_EhzBoss: offsetTableEntry.w PlrList_EhzBoss ; 41 PLCptr_HtzBoss: offsetTableEntry.w PlrList_HtzBoss ; 42 PLCptr_ArzBoss: offsetTableEntry.w PlrList_ArzBoss ; 43 PLCptr_MczBoss: offsetTableEntry.w PlrList_MczBoss ; 44 PLCptr_CnzBoss: offsetTableEntry.w PlrList_CnzBoss ; 45 PLCptr_MtzBoss: offsetTableEntry.w PlrList_MtzBoss ; 46 PLCptr_OozBoss: offsetTableEntry.w PlrList_OozBoss ; 47 PLCptr_FieryExplosion: offsetTableEntry.w PlrList_FieryExplosion ; 48 PLCptr_DezBoss: offsetTableEntry.w PlrList_DezBoss ; 49 PLCptr_EhzAnimals: offsetTableEntry.w PlrList_EhzAnimals ; 50 PLCptr_MczAnimals: offsetTableEntry.w PlrList_MczAnimals ; 51 PLCptr_HtzAnimals: PLCptr_MtzAnimals: PLCptr_WfzAnimals: offsetTableEntry.w PlrList_WfzAnimals ; 52 PLCptr_DezAnimals: offsetTableEntry.w PlrList_DezAnimals ; 53 PLCptr_HpzAnimals: offsetTableEntry.w PlrList_HpzAnimals ; 54 PLCptr_OozAnimals: offsetTableEntry.w PlrList_OozAnimals ; 55 PLCptr_SczAnimals: offsetTableEntry.w PlrList_SczAnimals ; 56 PLCptr_CnzAnimals: offsetTableEntry.w PlrList_CnzAnimals ; 57 PLCptr_CpzAnimals: offsetTableEntry.w PlrList_CpzAnimals ; 58 PLCptr_ArzAnimals: offsetTableEntry.w PlrList_ArzAnimals ; 59 PLCptr_SpecialStage: offsetTableEntry.w PlrList_SpecialStage ; 60 PLCptr_SpecStageBombs: offsetTableEntry.w PlrList_SpecStageBombs ; 61 PLCptr_WfzBoss: offsetTableEntry.w PlrList_WfzBoss ; 62 PLCptr_Tornado: offsetTableEntry.w PlrList_Tornado ; 63 PLCptr_Capsule: offsetTableEntry.w PlrList_Capsule ; 64 PLCptr_Explosion: offsetTableEntry.w PlrList_Explosion ; 65 PLCptr_ResultsTails: offsetTableEntry.w PlrList_ResultsTails ; 66 ; macro for a pattern load request list header ; must be on the same line as a label that has a corresponding _End label later plrlistheader macro {INTLABEL} __LABEL__ label * dc.w (((__LABEL___End - __LABEL__Plc) / 6) - 1) __LABEL__Plc: endm ; macro for a pattern load request plreq macro toVRAMaddr,fromROMaddr dc.l fromROMaddr dc.w tiles_to_bytes(toVRAMaddr) endm ;--------------------------------------------------------------------------------------- ; PATTERN LOAD REQUEST LIST ; Standard 1 - loaded for every level ;--------------------------------------------------------------------------------------- PlrList_Std1: plrlistheader plreq ArtTile_ArtNem_HUD, ArtNem_HUD plreq ArtTile_ArtNem_life_counter, ArtNem_Sonic_life_counter plreq ArtTile_ArtNem_Ring, ArtNem_Ring plreq ArtTile_ArtNem_Numbers, ArtNem_Numbers PlrList_Std1_End ;--------------------------------------------------------------------------------------- ; PATTERN LOAD REQUEST LIST ; Standard 2 - loaded for every level ;--------------------------------------------------------------------------------------- PlrList_Std2: plrlistheader plreq ArtTile_ArtNem_Checkpoint, ArtNem_Checkpoint plreq ArtTile_ArtNem_Powerups, ArtNem_Powerups plreq ArtTile_ArtNem_Shield, ArtNem_Shield plreq ArtTile_ArtNem_Invincible_stars, ArtNem_Invincible_stars PlrList_Std2_End ;--------------------------------------------------------------------------------------- ; PATTERN LOAD REQUEST LIST ; Aquatic level standard ;--------------------------------------------------------------------------------------- PlrList_StdWtr: plrlistheader plreq ArtTile_ArtNem_Explosion, ArtNem_Explosion plreq ArtTile_ArtNem_SuperSonic_stars, ArtNem_SuperSonic_stars plreq ArtTile_ArtNem_Bubbles, ArtNem_Bubbles PlrList_StdWtr_End ;--------------------------------------------------------------------------------------- ; PATTERN LOAD REQUEST LIST ; Game/Time over ;--------------------------------------------------------------------------------------- PlrList_GameOver: plrlistheader plreq ArtTile_ArtNem_Game_Over, ArtNem_Game_Over PlrList_GameOver_End ;--------------------------------------------------------------------------------------- ; PATTERN LOAD REQUEST LIST ; Emerald Hill Zone primary ;--------------------------------------------------------------------------------------- PlrList_Ehz1: plrlistheader plreq ArtTile_ArtNem_Waterfall, ArtNem_Waterfall plreq ArtTile_ArtNem_EHZ_Bridge, ArtNem_EHZ_Bridge plreq ArtTile_ArtNem_Buzzer_Fireball_2, ArtNem_Buzzer_Fireball plreq ArtTile_ArtNem_Buzzer, ArtNem_Buzzer plreq ArtTile_ArtNem_Coconuts, ArtNem_Coconuts plreq ArtTile_ArtNem_Masher, ArtNem_Masher PlrList_Ehz1_End ;--------------------------------------------------------------------------------------- ; PATTERN LOAD REQUEST LIST ; Emerald Hill Zone secondary ;--------------------------------------------------------------------------------------- PlrList_Ehz2: plrlistheader plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes plreq ArtTile_ArtNem_DignlSprng, ArtNem_DignlSprng plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng PlrList_Ehz2_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; Miles 1up patch ;--------------------------------------------------------------------------------------- PlrList_Miles1up: plrlistheader plreq ArtTile_ArtUnc_2p_life_counter, ArtUnc_MilesLife PlrList_Miles1up_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; Miles life counter ;--------------------------------------------------------------------------------------- PlrList_MilesLifeCounter: plrlistheader plreq ArtTile_ArtNem_life_counter, ArtUnc_MilesLife PlrList_MilesLifeCounter_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; Tails 1up patch ;--------------------------------------------------------------------------------------- PlrList_Tails1up: plrlistheader plreq ArtTile_ArtUnc_2p_life_counter, ArtNem_TailsLife PlrList_Tails1up_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; Tails life counter ;--------------------------------------------------------------------------------------- PlrList_TailsLifeCounter: plrlistheader plreq ArtTile_ArtNem_life_counter, ArtNem_TailsLife PlrList_TailsLifeCounter_End ;--------------------------------------------------------------------------------------- ; PATTERN LOAD REQUEST LIST ; Metropolis Zone primary ;--------------------------------------------------------------------------------------- PlrList_Mtz1: plrlistheader plreq ArtTile_ArtNem_MtzWheel, ArtNem_MtzWheel plreq ArtTile_ArtNem_MtzWheelIndent, ArtNem_MtzWheelIndent plreq ArtTile_ArtNem_LavaCup, ArtNem_LavaCup plreq ArtTile_ArtNem_BoltEnd_Rope, ArtNem_BoltEnd_Rope plreq ArtTile_ArtNem_MtzSteam, ArtNem_MtzSteam plreq ArtTile_ArtNem_MtzSpikeBlock, ArtNem_MtzSpikeBlock plreq ArtTile_ArtNem_MtzSpike, ArtNem_MtzSpike plreq ArtTile_ArtNem_Crabmeat, ArtNem_Crabmeat plreq ArtTile_ArtNem_MtzSupernova, ArtNem_MtzSupernova PlrList_Mtz1_End ;--------------------------------------------------------------------------------------- ; PATTERN LOAD REQUEST LIST ; Metropolis Zone secondary ;--------------------------------------------------------------------------------------- PlrList_Mtz2: plrlistheader plreq ArtTile_ArtNem_Button, ArtNem_Button plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes plreq ArtTile_ArtNem_MtzMantis, ArtNem_MtzMantis plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng plreq ArtTile_ArtNem_MtzAsstBlocks, ArtNem_MtzAsstBlocks plreq ArtTile_ArtNem_MtzLavaBubble, ArtNem_MtzLavaBubble plreq ArtTile_ArtNem_MtzCog, ArtNem_MtzCog plreq ArtTile_ArtNem_MtzSpinTubeFlash, ArtNem_MtzSpinTubeFlash PlrList_Mtz2_End ;--------------------------------------------------------------------------------------- ; PATTERN LOAD REQUEST LIST ; Wing Fortress Zone primary ;--------------------------------------------------------------------------------------- PlrList_Wfz1: plrlistheader plreq ArtTile_ArtNem_Tornado, ArtNem_Tornado plreq ArtTile_ArtNem_Clouds, ArtNem_Clouds plreq ArtTile_ArtNem_WfzVrtclPrpllr, ArtNem_WfzVrtclPrpllr plreq ArtTile_ArtNem_WfzHrzntlPrpllr, ArtNem_WfzHrzntlPrpllr plreq ArtTile_ArtNem_Balkrie, ArtNem_Balkrie plreq ArtTile_ArtNem_BreakPanels, ArtNem_BreakPanels plreq ArtTile_ArtNem_WfzScratch, ArtNem_WfzScratch plreq ArtTile_ArtNem_WfzTiltPlatforms, ArtNem_WfzTiltPlatforms ; These two are already in the list, so this is redundant plreq ArtTile_ArtNem_Tornado, ArtNem_Tornado plreq ArtTile_ArtNem_Clouds, ArtNem_Clouds PlrList_Wfz1_End ;--------------------------------------------------------------------------------------- ; PATTERN LOAD REQUEST LIST ; Wing Fortress Zone secondary ;--------------------------------------------------------------------------------------- PlrList_Wfz2: plrlistheader plreq ArtTile_ArtNem_WfzVrtclPrpllr, ArtNem_WfzVrtclPrpllr plreq ArtTile_ArtNem_WfzHrzntlPrpllr, ArtNem_WfzHrzntlPrpllr plreq ArtTile_ArtNem_WfzVrtclLazer, ArtNem_WfzVrtclLazer plreq ArtTile_ArtNem_WfzWallTurret, ArtNem_WfzWallTurret plreq ArtTile_ArtNem_WfzHrzntlLazer, ArtNem_WfzHrzntlLazer plreq ArtTile_ArtNem_WfzConveyorBeltWheel, ArtNem_WfzConveyorBeltWheel plreq ArtTile_ArtNem_WfzHook, ArtNem_WfzHook plreq ArtTile_ArtNem_WfzThrust, ArtNem_WfzThrust plreq ArtTile_ArtNem_WfzBeltPlatform, ArtNem_WfzBeltPlatform plreq ArtTile_ArtNem_WfzGunPlatform, ArtNem_WfzGunPlatform plreq ArtTile_ArtNem_WfzUnusedBadnik, ArtNem_WfzUnusedBadnik plreq ArtTile_ArtNem_WfzLaunchCatapult, ArtNem_WfzLaunchCatapult plreq ArtTile_ArtNem_WfzSwitch, ArtNem_WfzSwitch plreq ArtTile_ArtNem_WfzFloatingPlatform, ArtNem_WfzFloatingPlatform PlrList_Wfz2_End ;--------------------------------------------------------------------------------------- ; PATTERN LOAD REQUEST LIST ; Hill Top Zone primary ;--------------------------------------------------------------------------------------- PlrList_Htz1: plrlistheader plreq ArtTile_ArtNem_Buzzer_Fireball_1, ArtNem_Buzzer_Fireball plreq ArtTile_ArtNem_HtzRock, ArtNem_HtzRock plreq ArtTile_ArtNem_HtzSeeSaw, ArtNem_HtzSeeSaw plreq ArtTile_ArtNem_Sol, ArtNem_Sol plreq ArtTile_ArtNem_Rexon, ArtNem_Rexon plreq ArtTile_ArtNem_Spiker, ArtNem_Spiker plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes plreq ArtTile_ArtNem_DignlSprng, ArtNem_DignlSprng plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng PlrList_Htz1_End ;--------------------------------------------------------------------------------------- ; PATTERN LOAD REQUEST LIST ; Hill Top Zone secondary ;--------------------------------------------------------------------------------------- PlrList_Htz2: plrlistheader plreq ArtTile_ArtNem_HtzZipline, ArtNem_HtzZipline plreq ArtTile_ArtNem_HtzFireball, ArtNem_HtzFireball plreq ArtTile_ArtNem_HtzValveBarrier, ArtNem_HtzValveBarrier PlrList_Htz2_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; HPZ Primary ;--------------------------------------------------------------------------------------- PlrList_Hpz1: ;plrlistheader ; plreq ArtTile_ArtNem_WaterSurface, ArtNem_WaterSurface ;PlrList_Hpz1_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; HPZ Secondary ;--------------------------------------------------------------------------------------- PlrList_Hpz2: ;plrlistheader ;PlrList_Hpz2_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; OOZ Primary ;--------------------------------------------------------------------------------------- PlrList_Ooz1: plrlistheader plreq ArtTile_ArtNem_OOZBurn, ArtNem_OOZBurn plreq ArtTile_ArtNem_OOZElevator, ArtNem_OOZElevator plreq ArtTile_ArtNem_SpikyThing, ArtNem_SpikyThing plreq ArtTile_ArtNem_BurnerLid, ArtNem_BurnerLid plreq ArtTile_ArtNem_StripedBlocksVert, ArtNem_StripedBlocksVert plreq ArtTile_ArtNem_Oilfall, ArtNem_Oilfall plreq ArtTile_ArtNem_Oilfall2, ArtNem_Oilfall2 plreq ArtTile_ArtNem_BallThing, ArtNem_BallThing plreq ArtTile_ArtNem_LaunchBall, ArtNem_LaunchBall PlrList_Ooz1_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; OOZ Secondary ;--------------------------------------------------------------------------------------- PlrList_Ooz2: plrlistheader plreq ArtTile_ArtNem_OOZPlatform, ArtNem_OOZPlatform plreq ArtTile_ArtNem_PushSpring, ArtNem_PushSpring plreq ArtTile_ArtNem_OOZSwingPlat, ArtNem_OOZSwingPlat plreq ArtTile_ArtNem_StripedBlocksHoriz, ArtNem_StripedBlocksHoriz plreq ArtTile_ArtNem_OOZFanHoriz, ArtNem_OOZFanHoriz plreq ArtTile_ArtNem_Button, ArtNem_Button plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes plreq ArtTile_ArtNem_DignlSprng, ArtNem_DignlSprng plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng plreq ArtTile_ArtNem_Aquis, ArtNem_Aquis plreq ArtTile_ArtNem_Octus, ArtNem_Octus PlrList_Ooz2_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; MCZ Primary ;--------------------------------------------------------------------------------------- PlrList_Mcz1: plrlistheader plreq ArtTile_ArtNem_Crate, ArtNem_Crate plreq ArtTile_ArtNem_MCZCollapsePlat, ArtNem_MCZCollapsePlat plreq ArtTile_ArtNem_VineSwitch, ArtNem_VineSwitch plreq ArtTile_ArtNem_VinePulley, ArtNem_VinePulley plreq ArtTile_ArtNem_Flasher, ArtNem_Flasher plreq ArtTile_ArtNem_Crawlton, ArtNem_Crawlton PlrList_Mcz1_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; MCZ Secondary ;--------------------------------------------------------------------------------------- PlrList_Mcz2: plrlistheader plreq ArtTile_ArtNem_HorizSpike, ArtNem_HorizSpike plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes plreq ArtTile_ArtNem_MCZGateLog, ArtNem_MCZGateLog plreq ArtTile_ArtNem_LeverSpring, ArtNem_LeverSpring plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng PlrList_Mcz2_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; CNZ Primary ;--------------------------------------------------------------------------------------- PlrList_Cnz1: plrlistheader plreq ArtTile_ArtNem_Crawl, ArtNem_Crawl plreq ArtTile_ArtNem_BigMovingBlock, ArtNem_BigMovingBlock plreq ArtTile_ArtNem_CNZSnake, ArtNem_CNZSnake plreq ArtTile_ArtNem_CNZBonusSpike, ArtNem_CNZBonusSpike plreq ArtTile_ArtNem_CNZElevator, ArtNem_CNZElevator plreq ArtTile_ArtNem_CNZCage, ArtNem_CNZCage plreq ArtTile_ArtNem_CNZHexBumper, ArtNem_CNZHexBumper plreq ArtTile_ArtNem_CNZRoundBumper, ArtNem_CNZRoundBumper plreq ArtTile_ArtNem_CNZFlipper, ArtNem_CNZFlipper plreq ArtTile_ArtNem_CNZMiniBumper, ArtNem_CNZMiniBumper PlrList_Cnz1_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; CNZ Secondary ;--------------------------------------------------------------------------------------- PlrList_Cnz2: plrlistheader plreq ArtTile_ArtNem_CNZDiagPlunger, ArtNem_CNZDiagPlunger plreq ArtTile_ArtNem_CNZVertPlunger, ArtNem_CNZVertPlunger plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes plreq ArtTile_ArtNem_DignlSprng, ArtNem_DignlSprng plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng PlrList_Cnz2_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; CPZ Primary ;--------------------------------------------------------------------------------------- PlrList_Cpz1: plrlistheader plreq ArtTile_ArtNem_CPZMetalThings, ArtNem_CPZMetalThings plreq ArtTile_ArtNem_ConstructionStripes_2, ArtNem_ConstructionStripes plreq ArtTile_ArtNem_CPZBooster, ArtNem_CPZBooster plreq ArtTile_ArtNem_CPZElevator, ArtNem_CPZElevator plreq ArtTile_ArtNem_CPZAnimatedBits, ArtNem_CPZAnimatedBits plreq ArtTile_ArtNem_CPZTubeSpring, ArtNem_CPZTubeSpring plreq ArtTile_ArtNem_WaterSurface, ArtNem_WaterSurface plreq ArtTile_ArtNem_CPZStairBlock, ArtNem_CPZStairBlock plreq ArtTile_ArtNem_CPZMetalBlock, ArtNem_CPZMetalBlock PlrList_Cpz1_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; CPZ Secondary ;--------------------------------------------------------------------------------------- PlrList_Cpz2: plrlistheader plreq ArtTile_ArtNem_Grabber, ArtNem_Grabber plreq ArtTile_ArtNem_Spiny, ArtNem_Spiny plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes plreq ArtTile_ArtNem_DignlSprng, ArtNem_CPZDroplet plreq ArtTile_ArtNem_LeverSpring, ArtNem_LeverSpring plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng PlrList_Cpz2_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; DEZ Primary ;--------------------------------------------------------------------------------------- PlrList_Dez1: plrlistheader plreq ArtTile_ArtNem_ConstructionStripes_1, ArtNem_ConstructionStripes PlrList_Dez1_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; DEZ Secondary ;--------------------------------------------------------------------------------------- PlrList_Dez2: plrlistheader plreq ArtTile_ArtNem_SilverSonic, ArtNem_SilverSonic plreq ArtTile_ArtNem_DEZWindow, ArtNem_DEZWindow plreq ArtTile_ArtNem_RobotnikRunning, ArtNem_RobotnikRunning plreq ArtTile_ArtNem_RobotnikUpper, ArtNem_RobotnikUpper plreq ArtTile_ArtNem_RobotnikLower, ArtNem_RobotnikLower PlrList_Dez2_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; ARZ Primary ;--------------------------------------------------------------------------------------- PlrList_Arz1: plrlistheader plreq ArtTile_ArtNem_ARZBarrierThing, ArtNem_ARZBarrierThing plreq ArtTile_ArtNem_WaterSurface, ArtNem_WaterSurface2 plreq ArtTile_ArtNem_Leaves, ArtNem_Leaves plreq ArtTile_ArtNem_ArrowAndShooter, ArtNem_ArrowAndShooter PlrList_Arz1_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; ARZ Secondary ;--------------------------------------------------------------------------------------- PlrList_Arz2: plrlistheader plreq ArtTile_ArtNem_ChopChop, ArtNem_ChopChop plreq ArtTile_ArtNem_Whisp, ArtNem_Whisp plreq ArtTile_ArtNem_Grounder, ArtNem_Grounder plreq ArtTile_ArtNem_BigBubbles, ArtNem_BigBubbles plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes plreq ArtTile_ArtNem_LeverSpring, ArtNem_LeverSpring plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng PlrList_Arz2_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; SCZ Primary ;--------------------------------------------------------------------------------------- PlrList_Scz1: plrlistheader plreq ArtTile_ArtNem_Tornado, ArtNem_Tornado PlrList_Scz1_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; SCZ Secondary ;--------------------------------------------------------------------------------------- PlrList_Scz2: plrlistheader plreq ArtTile_ArtNem_Clouds, ArtNem_Clouds plreq ArtTile_ArtNem_WfzVrtclPrpllr, ArtNem_WfzVrtclPrpllr plreq ArtTile_ArtNem_WfzHrzntlPrpllr, ArtNem_WfzHrzntlPrpllr plreq ArtTile_ArtNem_Balkrie, ArtNem_Balkrie plreq ArtTile_ArtNem_Turtloid, ArtNem_Turtloid plreq ArtTile_ArtNem_Nebula, ArtNem_Nebula PlrList_Scz2_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; Sonic end of level results screen ;--------------------------------------------------------------------------------------- PlrList_Results: plrlistheader plreq ArtTile_ArtNem_TitleCard, ArtNem_TitleCard plreq ArtTile_ArtNem_ResultsText, ArtNem_ResultsText plreq ArtTile_ArtNem_MiniCharacter, ArtNem_MiniSonic plreq ArtTile_ArtNem_Perfect, ArtNem_Perfect PlrList_Results_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; End of level signpost ;--------------------------------------------------------------------------------------- PlrList_Signpost: plrlistheader plreq ArtTile_ArtNem_Signpost, ArtNem_Signpost PlrList_Signpost_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; CPZ Boss ;--------------------------------------------------------------------------------------- PlrList_CpzBoss: plrlistheader plreq ArtTile_ArtNem_Eggpod_3, ArtNem_Eggpod plreq ArtTile_ArtNem_CPZBoss, ArtNem_CPZBoss plreq ArtTile_ArtNem_EggpodJets_1, ArtNem_EggpodJets plreq ArtTile_ArtNem_BossSmoke_1, ArtNem_BossSmoke plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_CpzBoss_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; EHZ Boss ;--------------------------------------------------------------------------------------- PlrList_EhzBoss: plrlistheader plreq ArtTile_ArtNem_Eggpod_1, ArtNem_Eggpod plreq ArtTile_ArtNem_EHZBoss, ArtNem_EHZBoss plreq ArtTile_ArtNem_EggChoppers, ArtNem_EggChoppers plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_EhzBoss_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; HTZ Boss ;--------------------------------------------------------------------------------------- PlrList_HtzBoss: plrlistheader plreq ArtTile_ArtNem_Eggpod_2, ArtNem_Eggpod plreq ArtTile_ArtNem_HTZBoss, ArtNem_HTZBoss plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion plreq ArtTile_ArtNem_BossSmoke_2, ArtNem_BossSmoke PlrList_HtzBoss_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; ARZ Boss ;--------------------------------------------------------------------------------------- PlrList_ArzBoss: plrlistheader plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod plreq ArtTile_ArtNem_ARZBoss, ArtNem_ARZBoss plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_ArzBoss_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; MCZ Boss ;--------------------------------------------------------------------------------------- PlrList_MczBoss: plrlistheader plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod plreq ArtTile_ArtNem_MCZBoss, ArtNem_MCZBoss plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_MczBoss_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; CNZ Boss ;--------------------------------------------------------------------------------------- PlrList_CnzBoss: plrlistheader plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod plreq ArtTile_ArtNem_CNZBoss, ArtNem_CNZBoss plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_CnzBoss_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; MTZ Boss ;--------------------------------------------------------------------------------------- PlrList_MtzBoss: plrlistheader plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod plreq ArtTile_ArtNem_MTZBoss, ArtNem_MTZBoss plreq ArtTile_ArtNem_EggpodJets_2, ArtNem_EggpodJets plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_MtzBoss_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; OOZ Boss ;--------------------------------------------------------------------------------------- PlrList_OozBoss: plrlistheader plreq ArtTile_ArtNem_OOZBoss, ArtNem_OOZBoss plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_OozBoss_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; Fiery Explosion ;--------------------------------------------------------------------------------------- PlrList_FieryExplosion: plrlistheader plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_FieryExplosion_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; Death Egg ;--------------------------------------------------------------------------------------- PlrList_DezBoss: plrlistheader plreq ArtTile_ArtNem_DEZBoss, ArtNem_DEZBoss PlrList_DezBoss_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; EHZ Animals ;--------------------------------------------------------------------------------------- PlrList_EhzAnimals: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Squirrel plreq ArtTile_ArtNem_Animal_2, ArtNem_Bird PlrList_EhzAnimals_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; MCZ Animals ;--------------------------------------------------------------------------------------- PlrList_MczAnimals: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Mouse plreq ArtTile_ArtNem_Animal_2, ArtNem_Chicken PlrList_MczAnimals_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; HTZ/MTZ/WFZ animals ;--------------------------------------------------------------------------------------- PlrList_HtzAnimals: PlrList_MtzAnimals: PlrList_WfzAnimals: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Beaver plreq ArtTile_ArtNem_Animal_2, ArtNem_Eagle PlrList_HtzAnimals_End PlrList_MtzAnimals_End PlrList_WfzAnimals_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; DEZ Animals ;--------------------------------------------------------------------------------------- PlrList_DezAnimals: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Pig plreq ArtTile_ArtNem_Animal_2, ArtNem_Chicken PlrList_DezAnimals_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; HPZ animals ;--------------------------------------------------------------------------------------- PlrList_HpzAnimals: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Mouse plreq ArtTile_ArtNem_Animal_2, ArtNem_Seal PlrList_HpzAnimals_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; OOZ Animals ;--------------------------------------------------------------------------------------- PlrList_OozAnimals: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Penguin plreq ArtTile_ArtNem_Animal_2, ArtNem_Seal PlrList_OozAnimals_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; SCZ Animals ;--------------------------------------------------------------------------------------- PlrList_SczAnimals: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Turtle plreq ArtTile_ArtNem_Animal_2, ArtNem_Chicken PlrList_SczAnimals_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; CNZ Animals ;--------------------------------------------------------------------------------------- PlrList_CnzAnimals: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Bear plreq ArtTile_ArtNem_Animal_2, ArtNem_Bird PlrList_CnzAnimals_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; CPZ Animals ;--------------------------------------------------------------------------------------- PlrList_CpzAnimals: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Rabbit plreq ArtTile_ArtNem_Animal_2, ArtNem_Eagle PlrList_CpzAnimals_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; ARZ Animals ;--------------------------------------------------------------------------------------- PlrList_ArzAnimals: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Penguin plreq ArtTile_ArtNem_Animal_2, ArtNem_Bird PlrList_ArzAnimals_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; Special Stage ;--------------------------------------------------------------------------------------- PlrList_SpecialStage: plrlistheader plreq ArtTile_ArtNem_SpecialEmerald, ArtNem_SpecialEmerald plreq ArtTile_ArtNem_SpecialMessages, ArtNem_SpecialMessages plreq ArtTile_ArtNem_SpecialHUD, ArtNem_SpecialHUD plreq ArtTile_ArtNem_SpecialFlatShadow, ArtNem_SpecialFlatShadow plreq ArtTile_ArtNem_SpecialDiagShadow, ArtNem_SpecialDiagShadow plreq ArtTile_ArtNem_SpecialSideShadow, ArtNem_SpecialSideShadow plreq ArtTile_ArtNem_SpecialExplosion, ArtNem_SpecialExplosion plreq ArtTile_ArtNem_SpecialRings, ArtNem_SpecialRings plreq ArtTile_ArtNem_SpecialStart, ArtNem_SpecialStart plreq ArtTile_ArtNem_SpecialPlayerVSPlayer, ArtNem_SpecialPlayerVSPlayer plreq ArtTile_ArtNem_SpecialBack, ArtNem_SpecialBack plreq ArtTile_ArtNem_SpecialStars, ArtNem_SpecialStars plreq ArtTile_ArtNem_SpecialTailsText, ArtNem_SpecialTailsText PlrList_SpecialStage_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; Special Stage Bombs ;--------------------------------------------------------------------------------------- PlrList_SpecStageBombs: plrlistheader plreq ArtTile_ArtNem_SpecialBomb, ArtNem_SpecialBomb PlrList_SpecStageBombs_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; WFZ Boss ;--------------------------------------------------------------------------------------- PlrList_WfzBoss: plrlistheader plreq ArtTile_ArtNem_WFZBoss, ArtNem_WFZBoss plreq ArtTile_ArtNem_RobotnikRunning, ArtNem_RobotnikRunning plreq ArtTile_ArtNem_RobotnikUpper, ArtNem_RobotnikUpper plreq ArtTile_ArtNem_RobotnikLower, ArtNem_RobotnikLower plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_WfzBoss_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; Tornado ;--------------------------------------------------------------------------------------- PlrList_Tornado: plrlistheader plreq ArtTile_ArtNem_Tornado, ArtNem_Tornado plreq ArtTile_ArtNem_TornadoThruster, ArtNem_TornadoThruster plreq ArtTile_ArtNem_Clouds, ArtNem_Clouds PlrList_Tornado_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; Capsule/Egg Prison ;--------------------------------------------------------------------------------------- PlrList_Capsule: plrlistheader plreq ArtTile_ArtNem_Capsule, ArtNem_Capsule PlrList_Capsule_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; Normal explosion ;--------------------------------------------------------------------------------------- PlrList_Explosion: plrlistheader plreq ArtTile_ArtNem_Explosion, ArtNem_Explosion PlrList_Explosion_End ;--------------------------------------------------------------------------------------- ; Pattern load queue ; Tails end of level results screen ;--------------------------------------------------------------------------------------- PlrList_ResultsTails: plrlistheader plreq ArtTile_ArtNem_TitleCard, ArtNem_TitleCard plreq ArtTile_ArtNem_ResultsText, ArtNem_ResultsText plreq ArtTile_ArtNem_MiniCharacter, ArtNem_MiniTails plreq ArtTile_ArtNem_Perfect, ArtNem_Perfect PlrList_ResultsTails_End ;--------------------------------------------------------------------------------------- ; Weird revision-specific duplicates of portions of the PLR lists (unused) ;--------------------------------------------------------------------------------------- if gameRevision=0 ; half of PlrList_ResultsTails plreq ArtTile_ArtNem_MiniCharacter, ArtNem_MiniTails plreq ArtTile_ArtNem_Perfect, ArtNem_Perfect PlrList_ResultsTails_Dup_End dc.l 0 elseif gameRevision=2 ; half of the second ARZ PLR list ;plreq ArtTile_ArtNem_Grounder, ArtNem_Grounder ; cut in half ;dc.l ArtNem_Grounder dc.w tiles_to_bytes(ArtTile_ArtNem_Grounder) plreq ArtTile_ArtNem_BigBubbles, ArtNem_BigBubbles plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes plreq ArtTile_ArtNem_LeverSpring, ArtNem_LeverSpring plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng PlrList_Arz2_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; SCZ Primary ;--------------------------------------------------------------------------------------- PlrList_Scz1_Dup: plrlistheader plreq ArtTile_ArtNem_Tornado, ArtNem_Tornado PlrList_Scz1_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; SCZ Secondary ;--------------------------------------------------------------------------------------- PlrList_Scz2_Dup: plrlistheader plreq ArtTile_ArtNem_Clouds, ArtNem_Clouds plreq ArtTile_ArtNem_WfzVrtclPrpllr, ArtNem_WfzVrtclPrpllr plreq ArtTile_ArtNem_WfzHrzntlPrpllr, ArtNem_WfzHrzntlPrpllr plreq ArtTile_ArtNem_Balkrie, ArtNem_Balkrie plreq ArtTile_ArtNem_Turtloid, ArtNem_Turtloid plreq ArtTile_ArtNem_Nebula, ArtNem_Nebula PlrList_Scz2_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; Sonic end of level results screen ;--------------------------------------------------------------------------------------- PlrList_Results_Dup: plrlistheader plreq ArtTile_ArtNem_TitleCard, ArtNem_TitleCard plreq ArtTile_ArtNem_ResultsText, ArtNem_ResultsText plreq ArtTile_ArtNem_MiniCharacter, ArtNem_MiniSonic plreq ArtTile_ArtNem_Perfect, ArtNem_Perfect PlrList_Results_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; End of level signpost ;--------------------------------------------------------------------------------------- PlrList_Signpost_Dup: plrlistheader plreq ArtTile_ArtNem_Signpost, ArtNem_Signpost PlrList_Signpost_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; CPZ Boss ;--------------------------------------------------------------------------------------- PlrList_CpzBoss_Dup: plrlistheader plreq ArtTile_ArtNem_Eggpod_3, ArtNem_Eggpod plreq ArtTile_ArtNem_CPZBoss, ArtNem_CPZBoss plreq ArtTile_ArtNem_EggpodJets_1, ArtNem_EggpodJets plreq ArtTile_ArtNem_BossSmoke_1, ArtNem_BossSmoke plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_CpzBoss_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; EHZ Boss ;--------------------------------------------------------------------------------------- PlrList_EhzBoss_Dup: plrlistheader plreq ArtTile_ArtNem_Eggpod_1, ArtNem_Eggpod plreq ArtTile_ArtNem_EHZBoss, ArtNem_EHZBoss plreq ArtTile_ArtNem_EggChoppers, ArtNem_EggChoppers plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_EhzBoss_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; HTZ Boss ;--------------------------------------------------------------------------------------- PlrList_HtzBoss_Dup: plrlistheader plreq ArtTile_ArtNem_Eggpod_2, ArtNem_Eggpod plreq ArtTile_ArtNem_HTZBoss, ArtNem_HTZBoss plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion plreq ArtTile_ArtNem_BossSmoke_2, ArtNem_BossSmoke PlrList_HtzBoss_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; ARZ Boss ;--------------------------------------------------------------------------------------- PlrList_ArzBoss_Dup: plrlistheader plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod plreq ArtTile_ArtNem_ARZBoss, ArtNem_ARZBoss plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_ArzBoss_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; MCZ Boss ;--------------------------------------------------------------------------------------- PlrList_MczBoss_Dup: plrlistheader plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod plreq ArtTile_ArtNem_MCZBoss, ArtNem_MCZBoss plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_MczBoss_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; CNZ Boss ;--------------------------------------------------------------------------------------- PlrList_CnzBoss_Dup: plrlistheader plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod plreq ArtTile_ArtNem_CNZBoss, ArtNem_CNZBoss plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_CnzBoss_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; MTZ Boss ;--------------------------------------------------------------------------------------- PlrList_MtzBoss_Dup: plrlistheader plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod plreq ArtTile_ArtNem_MTZBoss, ArtNem_MTZBoss plreq ArtTile_ArtNem_EggpodJets_2, ArtNem_EggpodJets plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_MtzBoss_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; OOZ Boss ;--------------------------------------------------------------------------------------- PlrList_OozBoss_Dup: plrlistheader plreq ArtTile_ArtNem_OOZBoss, ArtNem_OOZBoss plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_OozBoss_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; Fiery Explosion ;--------------------------------------------------------------------------------------- PlrList_FieryExplosion_Dup: plrlistheader plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_FieryExplosion_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; Death Egg ;--------------------------------------------------------------------------------------- PlrList_DezBoss_Dup: plrlistheader plreq ArtTile_ArtNem_DEZBoss, ArtNem_DEZBoss PlrList_DezBoss_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; EHZ Animals ;--------------------------------------------------------------------------------------- PlrList_EhzAnimals_Dup: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Squirrel plreq ArtTile_ArtNem_Animal_2, ArtNem_Bird PlrList_EhzAnimals_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; MCZ Animals ;--------------------------------------------------------------------------------------- PlrList_MczAnimals_Dup: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Mouse plreq ArtTile_ArtNem_Animal_2, ArtNem_Chicken PlrList_MczAnimals_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; HTZ/MTZ/WFZ animals ;--------------------------------------------------------------------------------------- PlrList_HtzAnimals_Dup: PlrList_MtzAnimals_Dup: PlrList_WfzAnimals_Dup: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Beaver plreq ArtTile_ArtNem_Animal_2, ArtNem_Eagle PlrList_HtzAnimals_Dup_End PlrList_MtzAnimals_Dup_End PlrList_WfzAnimals_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; DEZ Animals ;--------------------------------------------------------------------------------------- PlrList_DezAnimals_Dup: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Pig plreq ArtTile_ArtNem_Animal_2, ArtNem_Chicken PlrList_DezAnimals_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; HPZ animals ;--------------------------------------------------------------------------------------- PlrList_HpzAnimals_Dup: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Mouse plreq ArtTile_ArtNem_Animal_2, ArtNem_Seal PlrList_HpzAnimals_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; OOZ Animals ;--------------------------------------------------------------------------------------- PlrList_OozAnimals_Dup: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Penguin plreq ArtTile_ArtNem_Animal_2, ArtNem_Seal PlrList_OozAnimals_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; SCZ Animals ;--------------------------------------------------------------------------------------- PlrList_SczAnimals_Dup: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Turtle plreq ArtTile_ArtNem_Animal_2, ArtNem_Chicken PlrList_SczAnimals_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; CNZ Animals ;--------------------------------------------------------------------------------------- PlrList_CnzAnimals_Dup: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Bear plreq ArtTile_ArtNem_Animal_2, ArtNem_Bird PlrList_CnzAnimals_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; CPZ Animals ;--------------------------------------------------------------------------------------- PlrList_CpzAnimals_Dup: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Rabbit plreq ArtTile_ArtNem_Animal_2, ArtNem_Eagle PlrList_CpzAnimals_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; ARZ Animals ;--------------------------------------------------------------------------------------- PlrList_ArzAnimals_Dup: plrlistheader plreq ArtTile_ArtNem_Animal_1, ArtNem_Penguin plreq ArtTile_ArtNem_Animal_2, ArtNem_Bird PlrList_ArzAnimals_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; Special Stage ;--------------------------------------------------------------------------------------- PlrList_SpecialStage_Dup: plrlistheader plreq ArtTile_ArtNem_SpecialEmerald, ArtNem_SpecialEmerald plreq ArtTile_ArtNem_SpecialMessages, ArtNem_SpecialMessages plreq ArtTile_ArtNem_SpecialHUD, ArtNem_SpecialHUD plreq ArtTile_ArtNem_SpecialFlatShadow, ArtNem_SpecialFlatShadow plreq ArtTile_ArtNem_SpecialDiagShadow, ArtNem_SpecialDiagShadow plreq ArtTile_ArtNem_SpecialSideShadow, ArtNem_SpecialSideShadow plreq ArtTile_ArtNem_SpecialExplosion, ArtNem_SpecialExplosion plreq ArtTile_ArtNem_SpecialRings, ArtNem_SpecialRings plreq ArtTile_ArtNem_SpecialStart, ArtNem_SpecialStart plreq ArtTile_ArtNem_SpecialPlayerVSPlayer, ArtNem_SpecialPlayerVSPlayer plreq ArtTile_ArtNem_SpecialBack, ArtNem_SpecialBack plreq ArtTile_ArtNem_SpecialStars, ArtNem_SpecialStars plreq ArtTile_ArtNem_SpecialTailsText, ArtNem_SpecialTailsText PlrList_SpecialStage_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; Special Stage Bombs ;--------------------------------------------------------------------------------------- PlrList_SpecStageBombs_Dup: plrlistheader plreq ArtTile_ArtNem_SpecialBomb, ArtNem_SpecialBomb PlrList_SpecStageBombs_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; WFZ Boss ;--------------------------------------------------------------------------------------- PlrList_WfzBoss_Dup: plrlistheader plreq ArtTile_ArtNem_WFZBoss, ArtNem_WFZBoss plreq ArtTile_ArtNem_RobotnikRunning, ArtNem_RobotnikRunning plreq ArtTile_ArtNem_RobotnikUpper, ArtNem_RobotnikUpper plreq ArtTile_ArtNem_RobotnikLower, ArtNem_RobotnikLower plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion PlrList_WfzBoss_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; Tornado ;--------------------------------------------------------------------------------------- PlrList_Tornado_Dup: plrlistheader plreq ArtTile_ArtNem_Tornado, ArtNem_Tornado plreq ArtTile_ArtNem_TornadoThruster, ArtNem_TornadoThruster plreq ArtTile_ArtNem_Clouds, ArtNem_Clouds PlrList_Tornado_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; Capsule/Egg Prison ;--------------------------------------------------------------------------------------- PlrList_Capsule_Dup: plrlistheader plreq ArtTile_ArtNem_Capsule, ArtNem_Capsule PlrList_Capsule_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; Normal explosion ;--------------------------------------------------------------------------------------- PlrList_Explosion_Dup: plrlistheader plreq ArtTile_ArtNem_Explosion, ArtNem_Explosion PlrList_Explosion_Dup_End ;--------------------------------------------------------------------------------------- ; Pattern load queue (duplicate) ; Tails end of level results screen ;--------------------------------------------------------------------------------------- PlrList_ResultsTails_Dup: plrlistheader plreq ArtTile_ArtNem_TitleCard, ArtNem_TitleCard plreq ArtTile_ArtNem_ResultsText, ArtNem_ResultsText plreq ArtTile_ArtNem_MiniCharacter, ArtNem_MiniTails plreq ArtTile_ArtNem_Perfect, ArtNem_Perfect PlrList_ResultsTails_Dup_End endif ;--------------------------------------------------------------------------------------- ; Curve and resistance mapping ;--------------------------------------------------------------------------------------- ColCurveMap: BINCLUDE "collision/Curve and resistance mapping.bin" even ;-------------------------------------------------------------------------------------- ; Collision arrays ;-------------------------------------------------------------------------------------- ColArray: BINCLUDE "collision/Collision array 1.bin" ColArray2: BINCLUDE "collision/Collision array 2.bin" even ;--------------------------------------------------------------------------------------- ; EHZ and HTZ primary 16x16 collision index (Kosinski compression) ColP_EHZHTZ: BINCLUDE "collision/EHZ and HTZ primary 16x16 collision index.bin" even ;--------------------------------------------------------------------------------------- ; EHZ and HTZ secondary 16x16 collision index (Kosinski compression) ColS_EHZHTZ: BINCLUDE "collision/EHZ and HTZ secondary 16x16 collision index.bin" even ;--------------------------------------------------------------------------------------- ; MTZ primary 16x16 collision index (Kosinski compression) ColP_MTZ: BINCLUDE "collision/MTZ primary 16x16 collision index.bin" even ;--------------------------------------------------------------------------------------- ; HPZ primary 16x16 collision index (Kosinski compression) ColP_HPZ: ;BINCLUDE "collision/HPZ primary 16x16 collision index.bin" ;even ;--------------------------------------------------------------------------------------- ; HPZ secondary 16x16 collision index (Kosinski compression) ColS_HPZ: ;BINCLUDE "collision/HPZ secondary 16x16 collision index.bin" ;even ;--------------------------------------------------------------------------------------- ; OOZ primary 16x16 collision index (Kosinski compression) ColP_OOZ: BINCLUDE "collision/OOZ primary 16x16 collision index.bin" even ;--------------------------------------------------------------------------------------- ; MCZ primary 16x16 collision index (Kosinski compression) ColP_MCZ: BINCLUDE "collision/MCZ primary 16x16 collision index.bin" even ;--------------------------------------------------------------------------------------- ; CNZ primary 16x16 collision index (Kosinski compression) ColP_CNZ: BINCLUDE "collision/CNZ primary 16x16 collision index.bin" even ;--------------------------------------------------------------------------------------- ; CNZ secondary 16x16 collision index (Kosinski compression) ColS_CNZ: BINCLUDE "collision/CNZ secondary 16x16 collision index.bin" even ;--------------------------------------------------------------------------------------- ; CPZ and DEZ primary 16x16 collision index (Kosinski compression) ColP_CPZDEZ: BINCLUDE "collision/CPZ and DEZ primary 16x16 collision index.bin" even ;--------------------------------------------------------------------------------------- ; CPZ and DEZ secondary 16x16 collision index (Kosinski compression) ColS_CPZDEZ: BINCLUDE "collision/CPZ and DEZ secondary 16x16 collision index.bin" even ;--------------------------------------------------------------------------------------- ; ARZ primary 16x16 collision index (Kosinski compression) ColP_ARZ: BINCLUDE "collision/ARZ primary 16x16 collision index.bin" even ;--------------------------------------------------------------------------------------- ; ARZ secondary 16x16 collision index (Kosinski compression) ColS_ARZ: BINCLUDE "collision/ARZ secondary 16x16 collision index.bin" even ;--------------------------------------------------------------------------------------- ; WFZ/SCZ primary 16x16 collision index (Kosinski compression) ColP_WFZSCZ: BINCLUDE "collision/WFZ and SCZ primary 16x16 collision index.bin" even ;--------------------------------------------------------------------------------------- ; WFZ/SCZ secondary 16x16 collision index (Kosinski compression) ColS_WFZSCZ: BINCLUDE "collision/WFZ and SCZ secondary 16x16 collision index.bin" even ;--------------------------------------------------------------------------------------- ColP_Invalid: ;--------------------------------------------------------------------------------------- ; Offset index of level layouts ; Two entries per zone, pointing to the level layouts for acts 1 and 2 of each zone ; respectively. ;--------------------------------------------------------------------------------------- Off_Level: zoneOrderedOffsetTable 2,2 zoneOffsetTableEntry.w Level_EHZ1 zoneOffsetTableEntry.w Level_EHZ2 ; 1 zoneOffsetTableEntry.w Level_EHZ1 ; 2 zoneOffsetTableEntry.w Level_EHZ1 ; 3 zoneOffsetTableEntry.w Level_EHZ1 ; 4 zoneOffsetTableEntry.w Level_EHZ1 ; 5 zoneOffsetTableEntry.w Level_EHZ1 ; 6 zoneOffsetTableEntry.w Level_EHZ1 ; 7 zoneOffsetTableEntry.w Level_MTZ1 ; 8 zoneOffsetTableEntry.w Level_MTZ2 ; 9 zoneOffsetTableEntry.w Level_MTZ3 ; 10 zoneOffsetTableEntry.w Level_MTZ3 ; 11 zoneOffsetTableEntry.w Level_WFZ ; 12 zoneOffsetTableEntry.w Level_WFZ ; 13 zoneOffsetTableEntry.w Level_HTZ1 ; 14 zoneOffsetTableEntry.w Level_HTZ2 ; 15 zoneOffsetTableEntry.w Level_HPZ1 ; 16 zoneOffsetTableEntry.w Level_HPZ1 ; 17 zoneOffsetTableEntry.w Level_EHZ1 ; 18 zoneOffsetTableEntry.w Level_EHZ1 ; 19 zoneOffsetTableEntry.w Level_OOZ1 ; 20 zoneOffsetTableEntry.w Level_OOZ2 ; 21 zoneOffsetTableEntry.w Level_MCZ1 ; 22 zoneOffsetTableEntry.w Level_MCZ2 ; 23 zoneOffsetTableEntry.w Level_CNZ1 ; 24 zoneOffsetTableEntry.w Level_CNZ2 ; 25 zoneOffsetTableEntry.w Level_CPZ1 ; 26 zoneOffsetTableEntry.w Level_CPZ2 ; 27 zoneOffsetTableEntry.w Level_DEZ ; 28 zoneOffsetTableEntry.w Level_DEZ ; 29 zoneOffsetTableEntry.w Level_ARZ1 ; 30 zoneOffsetTableEntry.w Level_ARZ2 ; 31 zoneOffsetTableEntry.w Level_SCZ ; 32 zoneOffsetTableEntry.w Level_SCZ ; 33 zoneTableEnd ;--------------------------------------------------------------------------------------- ; EHZ act 1 level layout (Kosinski compression) Level_EHZ1: BINCLUDE "level/layout/EHZ_1.bin" even ;--------------------------------------------------------------------------------------- ; EHZ act 2 level layout (Kosinski compression) Level_EHZ2: BINCLUDE "level/layout/EHZ_2.bin" even ;--------------------------------------------------------------------------------------- ; MTZ act 1 level layout (Kosinski compression) Level_MTZ1: BINCLUDE "level/layout/MTZ_1.bin" even ;--------------------------------------------------------------------------------------- ; MTZ act 2 level layout (Kosinski compression) Level_MTZ2: BINCLUDE "level/layout/MTZ_2.bin" even ;--------------------------------------------------------------------------------------- ; MTZ act 3 level layout (Kosinski compression) Level_MTZ3: BINCLUDE "level/layout/MTZ_3.bin" even ;--------------------------------------------------------------------------------------- ; WFZ level layout (Kosinski compression) Level_WFZ: BINCLUDE "level/layout/WFZ.bin" even ;--------------------------------------------------------------------------------------- ; HTZ act 1 level layout (Kosinski compression) Level_HTZ1: BINCLUDE "level/layout/HTZ_1.bin" even ;--------------------------------------------------------------------------------------- ; HTZ act 2 level layout (Kosinski compression) Level_HTZ2: BINCLUDE "level/layout/HTZ_2.bin" even ;--------------------------------------------------------------------------------------- ; HPZ act 1 level layout (Kosinski compression) Level_HPZ1: ;BINCLUDE "level/layout/HPZ_1.bin" ;even ;--------------------------------------------------------------------------------------- ; OOZ act 1 level layout (Kosinski compression) Level_OOZ1: BINCLUDE "level/layout/OOZ_1.bin" even ;--------------------------------------------------------------------------------------- ; OOZ act 2 level layout (Kosinski compression) Level_OOZ2: BINCLUDE "level/layout/OOZ_2.bin" even ;--------------------------------------------------------------------------------------- ; MCZ act 1 level layout (Kosinski compression) Level_MCZ1: BINCLUDE "level/layout/MCZ_1.bin" even ;--------------------------------------------------------------------------------------- ; MCZ act 2 level layout (Kosinski compression) Level_MCZ2: BINCLUDE "level/layout/MCZ_2.bin" even ;--------------------------------------------------------------------------------------- ; CNZ act 1 level layout (Kosinski compression) Level_CNZ1: BINCLUDE "level/layout/CNZ_1.bin" even ;--------------------------------------------------------------------------------------- ; CNZ act 2 level layout (Kosinski compression) Level_CNZ2: BINCLUDE "level/layout/CNZ_2.bin" even ;--------------------------------------------------------------------------------------- ; CPZ act 1 level layout (Kosinski compression) Level_CPZ1: BINCLUDE "level/layout/CPZ_1.bin" even ;--------------------------------------------------------------------------------------- ; CPZ act 2 level layout (Kosinski compression) Level_CPZ2: BINCLUDE "level/layout/CPZ_2.bin" even ;--------------------------------------------------------------------------------------- ; DEZ level layout (Kosinski compression) Level_DEZ: BINCLUDE "level/layout/DEZ.bin" even ;--------------------------------------------------------------------------------------- ; ARZ act 1 level layout (Kosinski compression) Level_ARZ1: BINCLUDE "level/layout/ARZ_1.bin" even ;--------------------------------------------------------------------------------------- ; ARZ act 2 level layout (Kosinski compression) Level_ARZ2: BINCLUDE "level/layout/ARZ_2.bin" even ;--------------------------------------------------------------------------------------- ; SCZ level layout (Kosinski compression) Level_SCZ: BINCLUDE "level/layout/SCZ.bin" even ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Animated flowers in EHZ and HTZ ; ArtUnc_49714: ArtUnc_49794: ArtUnc_49814: ArtUnc_49894: ;--------------------------------------------------------------------------------------- ArtUnc_Flowers1: BINCLUDE "art/uncompressed/EHZ and HTZ flowers - 1.bin" ArtUnc_Flowers2: BINCLUDE "art/uncompressed/EHZ and HTZ flowers - 2.bin" ArtUnc_Flowers3: BINCLUDE "art/uncompressed/EHZ and HTZ flowers - 3.bin" ArtUnc_Flowers4: BINCLUDE "art/uncompressed/EHZ and HTZ flowers - 4.bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Pulsing thing against checkered backing from EHZ ; ArtUnc_49914: ArtUnc_EHZPulseBall: BINCLUDE "art/uncompressed/Pulsing ball against checkered background (EHZ).bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (192 blocks) ; Dynamically reloaded cliffs in background from HTZ ; ArtNem_49A14: ArtUnc_HTZCliffs: ArtNem_HTZCliffs: BINCLUDE "art/nemesis/Dynamically reloaded cliffs in HTZ background.bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Dynamically reloaded clouds in background from HTZ ; ArtUnc_4A33E: ArtUnc_HTZClouds: BINCLUDE "art/uncompressed/Background clouds (HTZ).bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Spinning metal cylinder patterns in MTZ ; ArtUnc_4A73E: ArtUnc_MTZCylinder: BINCLUDE "art/uncompressed/Spinning metal cylinder (MTZ).bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Lava patterns in MTZ and HTZ ; ArtUnc_4B73E: ArtUnc_Lava: BINCLUDE "art/uncompressed/Lava.bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Animated section of MTZ background ; ArtUnc_4BD3E: ArtUnc_MTZAnimBack: BINCLUDE "art/uncompressed/Animated section of MTZ background.bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Pulsing orb in HPZ ArtUnc_HPZPulseOrb: ;BINCLUDE "art/uncompressed/Pulsing orb (HPZ).bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Pulsing ball in OOZ ; ArtUnc_4BF7E: ArtUnc_OOZPulseBall: BINCLUDE "art/uncompressed/Pulsing ball (OOZ).bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Square rotating around ball in OOZ ; ArtUnc_4C0FE: ArtUnc_4C2FE: ArtUnc_OOZSquareBall1: BINCLUDE "art/uncompressed/Square rotating around ball in OOZ - 1.bin" ArtUnc_OOZSquareBall2: BINCLUDE "art/uncompressed/Square rotating around ball in OOZ - 2.bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Oil in OOZ ; ArtUnc_4C4FE: ArtUnc_4CCFE: ArtUnc_Oil1: BINCLUDE "art/uncompressed/Oil - 1.bin" ArtUnc_Oil2: BINCLUDE "art/uncompressed/Oil - 2.bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Flipping foreground section in CNZ ; ArtUnc_4D4FE: ArtUnc_CNZFlipTiles: BINCLUDE "art/uncompressed/Flipping foreground section (CNZ).bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Bonus pictures for slots in CNZ ; ArtUnc_4EEFE: ArtUnc_CNZSlotPics: BINCLUDE "art/uncompressed/Slot pictures.bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Animated background section in CPZ and DEZ ; ArtUnc_4FAFE: ArtUnc_CPZAnimBack: BINCLUDE "art/uncompressed/Animated background section (CPZ and DEZ).bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Waterfall patterns from ARZ ; ArtUnc_4FCFE: ArtUnc_4FDFE: ArtUnc_4FEFE: ArtUnc_Waterfall1: BINCLUDE "art/uncompressed/ARZ waterfall patterns - 1.bin" ArtUnc_Waterfall2: BINCLUDE "art/uncompressed/ARZ waterfall patterns - 2.bin" ArtUnc_Waterfall3: BINCLUDE "art/uncompressed/ARZ waterfall patterns - 3.bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Patterns for Sonic ; ArtUnc_50000: ;--------------------------------------------------------------------------------------- align $20 ArtUnc_Sonic: BINCLUDE "art/uncompressed/Sonic's art.bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Patterns for Tails ; ArtUnc_64320: ;--------------------------------------------------------------------------------------- align $20 ArtUnc_Tails: BINCLUDE "art/uncompressed/Tails's art.bin" ;-------------------------------------------------------------------------------------- ; Sprite Mappings ; Sonic ; MapUnc_6FBE0: SprTbl_Sonic: ;-------------------------------------------------------------------------------------- Mapunc_Sonic: BINCLUDE "mappings/sprite/Sonic.bin" ;-------------------------------------------------------------------------------------- ; Sprite Dynamic Pattern Reloading ; Sonic DPLCs ; MapRUnc_714E0: ;-------------------------------------------------------------------------------------- ; WARNING: the build script needs editing if you rename this label ; or if you move Sonic's running frame to somewhere else than frame $2D MapRUnc_Sonic: BINCLUDE "mappings/spriteDPLC/Sonic.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (32 blocks) ; Shield ; ArtNem_71D8E: ArtNem_Shield: BINCLUDE "art/nemesis/Shield.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (34 blocks) ; Invincibility stars ; ArtNem_71F14: ArtNem_Invincible_stars: BINCLUDE "art/nemesis/Invincibility stars.bin" ;-------------------------------------------------------------------------------------- ; Uncompressed art ; Splash in water ; ArtUnc_71FFC: ArtUnc_Splash: BINCLUDE "art/uncompressed/Splash.bin" ;-------------------------------------------------------------------------------------- ; Uncompressed art ; Smoke from Skidding ; ArtUnc_7373C: ArtUnc_SkidDust: BINCLUDE "art/uncompressed/Skid smoke.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (14 blocks) ; Supersonic stars ; ArtNem_7393C: ArtNem_SuperSonic_stars: BINCLUDE "art/nemesis/Super Sonic stars.bin" ;-------------------------------------------------------------------------------------- ; Sprite Mappings ; Tails ; MapUnc_739E2: ;-------------------------------------------------------------------------------------- MapUnc_Tails: BINCLUDE "mappings/sprite/Tails.bin" ;-------------------------------------------------------------------------------------- ; Sprite Dynamic Pattern Reloading ; Tails DPLCs ; MapRUnc_7446C: ;-------------------------------------------------------------------------------------- MapRUnc_Tails: BINCLUDE "mappings/spriteDPLC/Tails.bin" ;------------------------------------------------------------------------------------- ; Nemesis compressed art (127 blocks) ; "SEGA" Patterns ; ArtNem_74876: ArtNem_SEGA: BINCLUDE "art/nemesis/SEGA.bin" ;------------------------------------------------------------------------------------- ; Nemesis compressed art (9 blocks) ; Shaded blocks from intro ; ArtNem_74CF6: ArtNem_IntroTrails: BINCLUDE "art/nemesis/Shaded blocks from intro.bin" ;--------------------------------------------------------------------------------------- ; Enigma compressed art mappings ; "SEGA" mappings ; MapEng_74D0E: MapEng_SEGA: BINCLUDE "mappings/misc/SEGA mappings.bin" ;--------------------------------------------------------------------------------------- ; Enigma compressed art mappings ; Mappings for title screen background ; ArtNem_74DC6: MapEng_TitleScreen: BINCLUDE "mappings/misc/Mappings for title screen background.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed art mappings ; Mappings for title screen background (smaller part, water/horizon) ; MapEng_74E3A: MapEng_TitleBack: BINCLUDE "mappings/misc/Mappings for title screen background 2.bin" ;--------------------------------------------------------------------------------------- ; Enigma compressed art mappings ; "Sonic the Hedgehog 2" title screen logo mappings ; MapEng_74E86: MapEng_TitleLogo: BINCLUDE "mappings/misc/Sonic the Hedgehog 2 title screen logo mappings.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (336 blocks) ; Main patterns from title screen ; ArtNem_74F6C: even ArtNem_Title: BINCLUDE "art/nemesis/Main patterns from title screen.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (674 blocks) ; Sonic and tails from title screen ; ArtNem_7667A: even ArtNem_TitleSprites: BINCLUDE "art/nemesis/Sonic and Tails from title screen.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (10 blocks) ; A few menu patterns ; ArtNem_78CBC: even ArtNem_MenuJunk: BINCLUDE "art/nemesis/A few menu blocks.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (16 blocks) ; Button ArtNem_78DAC: even ArtNem_Button: BINCLUDE "art/nemesis/Button.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (20 blocks) ; Vertical Spring ArtNem_78E84: even ArtNem_VrtclSprng: BINCLUDE "art/nemesis/Vertical spring.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (12 blocks) ; Horizontal spring ArtNem_78FA0: even ArtNem_HrzntlSprng: BINCLUDE "art/nemesis/Horizontal spring.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (32 blocks) ; Diagonal spring ArtNem_7906A: even ArtNem_DignlSprng: BINCLUDE "art/nemesis/Diagonal spring.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (24 blocks) ; Score, Rings, Time patterns ArtNem_7923E: even ArtNem_HUD: BINCLUDE "art/nemesis/HUD.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (12 blocks) ; Sonic lives counter ArtNem_79346: even ArtNem_Sonic_life_counter: BINCLUDE "art/nemesis/Sonic lives counter.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (14 blocks) ; Ring ArtNem_7945C: even ArtNem_Ring: BINCLUDE "art/nemesis/Ring.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (60 blocks) ; Monitors and contents ArtNem_79550: even ArtNem_Powerups: BINCLUDE "art/nemesis/Monitor and contents.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (8 blocks) ; Spikes 7995C: even ArtNem_Spikes: BINCLUDE "art/nemesis/Spikes.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (18 blocks) ; Numbers 799AC: even ArtNem_Numbers: BINCLUDE "art/nemesis/Numbers.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (16 blocks) ; Star pole 79A86: even ArtNem_Checkpoint: BINCLUDE "art/nemesis/Star pole.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (78 blocks) ; Signpost ; ArtNem_79BDE: even ArtNem_Signpost: BINCLUDE "art/nemesis/Signpost.bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Signpost ; ArtUnc_7A18A: ; Yep, it's in the ROM twice: once compressed and once uncompressed even ArtUnc_Signpost: BINCLUDE "art/uncompressed/Signpost.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (28 blocks) ; Lever spring ; ArtNem_7AB4A: even ArtNem_LeverSpring: BINCLUDE "art/nemesis/Lever spring.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (8 blocks) ; Long horizontal spike ; ArtNem_7AC9A: even ArtNem_HorizSpike: BINCLUDE "art/nemesis/Long horizontal spike.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (24 blocks) ; Bubble thing from underwater ; ArtNem_7AD16: even ArtNem_BigBubbles: BINCLUDE "art/nemesis/Bubble generator.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (10 blocks) ; Bubbles from character 7AEE2: even ArtNem_Bubbles: BINCLUDE "art/nemesis/Bubbles.bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Countdown text for drowning ; ArtUnc_7AF80: even ArtUnc_Countdown: BINCLUDE "art/uncompressed/Numbers for drowning countdown.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (34 blocks) ; Game/Time over text 7B400: even ArtNem_Game_Over: BINCLUDE "art/nemesis/Game and Time Over text.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (68 blocks) ; Explosion 7B592: even ArtNem_Explosion: BINCLUDE "art/nemesis/Explosion.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (12 blocks) ; Miles life counter ; ArtNem_7B946: even ArtUnc_MilesLife: BINCLUDE "art/nemesis/Miles life counter.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (49 blocks) ; Egg prison ; ArtNem_7BA32: even ArtNem_Capsule: BINCLUDE "art/nemesis/Egg Prison.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (36 blocks) ; Tails on the continue screen (nagging Sonic) ; ArtNem_7BDBE: even ArtNem_ContinueTails: BINCLUDE "art/nemesis/Tails on continue screen.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (12 blocks) ; Sonic extra continue icon ; ArtNem_7C0AA: even ArtNem_MiniSonic: BINCLUDE "art/nemesis/Sonic continue.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (12 blocks) ; Tails life counter ; ArtNem_7C20C: even ArtNem_TailsLife: BINCLUDE "art/nemesis/Tails life counter.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (12 blocks) ; Tails extra continue icon ; ArtNem_7C2F2: even ArtNem_MiniTails: BINCLUDE "art/nemesis/Tails continue.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (88 blocks) ; Standard font ; ArtNem_7C43A: even ArtNem_FontStuff: BINCLUDE "art/nemesis/Standard font.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (38 blocks) ; 1P/2P wins text from 2P mode ; ArtNem_7C9AE: even ArtNem_1P2PWins: BINCLUDE "art/nemesis/1P and 2P wins text from 2P mode.bin" ;--------------------------------------------------------------------------------------- ; Enigma compressed art mappings ; Sonic/Miles animated background mappings ; MapEng_7CB80: MapEng_MenuBack: BINCLUDE "mappings/misc/Sonic and Miles animated background.bin" ;--------------------------------------------------------------------------------------- ; Uncompressed art ; Sonic/Miles animated background patterns ; ArtUnc_7CD2C: even ArtUnc_MenuBack: BINCLUDE "art/uncompressed/Sonic and Miles animated background.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (94 blocks) ; Title card patterns ; ArtNem_7D22C: even ArtNem_TitleCard: BINCLUDE "art/nemesis/Title card.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (92 blocks) ; Alphabet for font using large broken letters ; ArtNem_7D58A: even ArtNem_TitleCard2: BINCLUDE "art/nemesis/Font using large broken letters.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (21 blocks) ; A menu box with a shadow ; ArtNem_7D990: even ArtNem_MenuBox: BINCLUDE "art/nemesis/A menu box with a shadow.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (170 blocks) ; Pictures in level preview box in level select ; ArtNem_7DA10: even ArtNem_LevelSelectPics: BINCLUDE "art/nemesis/Pictures in level preview box from level select.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (68 blocks) ; Text for Sonic or Tails Got Through Act and Bonus/Perfect ; ArtNem_7E86A: even ArtNem_ResultsText: BINCLUDE "art/nemesis/End of level results text.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (72 blocks) ; Text for end of special stage, along with patterns for 3 emeralds. ; ArtNem_7EB58: even ArtNem_SpecialStageResults: BINCLUDE "art/nemesis/Special stage results screen art and some emeralds.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (14 blocks) ; "Perfect" text ; ArtNem_7EEBE: even ArtNem_Perfect: BINCLUDE "art/nemesis/Perfect text.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (16 blocks) ; Flicky ; ArtNem_7EF60: even ArtNem_Bird: BINCLUDE "art/nemesis/Flicky.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (20 blocks) ; Squirrel ; ArtNem_7F0A2: even ArtNem_Squirrel: BINCLUDE "art/nemesis/Squirrel.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (16 blocks) ; Mouse ; ArtNem_7F206: even ArtNem_Mouse: BINCLUDE "art/nemesis/Mouse.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (16 blocks) ; Chicken ; ArtNem_7F340: even ArtNem_Chicken: BINCLUDE "art/nemesis/Chicken.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (20 blocks) ; Beaver ; ArtNem_7F4A2: even ArtNem_Beaver: BINCLUDE "art/nemesis/Beaver.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (16 blocks) ; Some bird ; ArtNem_7F5E2: even ArtNem_Eagle: BINCLUDE "art/nemesis/Penguin.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (10 blocks) ; Pig ; ArtNem_7F710: even ArtNem_Pig: BINCLUDE "art/nemesis/Pig.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (14 blocks) ; Seal ; ArtNem_7F846: even ArtNem_Seal: BINCLUDE "art/nemesis/Seal.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (18 blocks) ; Penguin ; ArtNem_7F962: even ArtNem_Penguin: BINCLUDE "art/nemesis/Penguin 2.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (20 blocks) ; Turtle ; ArtNem_7FADE: even ArtNem_Turtle: BINCLUDE "art/nemesis/Turtle.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (20 blocks) ; Bear ; ArtNem_7FC90: even ArtNem_Bear: BINCLUDE "art/nemesis/Bear.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (18 blocks) ; Splats ; ArtNem_7FDD2: even ArtNem_Rabbit: BINCLUDE "art/nemesis/Rabbit.bin" ;--------------------------------------------------------------------------------------- ; Nemesis compressed art (4 blocks) ; Rivet thing that you bust to get inside ship at the end of WFZ ; ArtNem_7FF2A: even ArtNem_WfzSwitch: BINCLUDE "art/nemesis/WFZ boss chamber switch.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (15 blocks) ; Breakaway panels in WFZ ; ArtNem_7FF98: even ArtNem_BreakPanels: BINCLUDE "art/nemesis/Breakaway panels from WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (32 blocks) ; Spiked thing from OOZ ; ArtNem_8007C: even ArtNem_SpikyThing: BINCLUDE "art/nemesis/Spiked ball from OOZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (6 blocks) ; Green platform over the burners in OOZ ; ArtNem_80274: even ArtNem_BurnerLid: BINCLUDE "art/nemesis/Burner Platform from OOZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (4 blocks) ; Striped blocks from OOZ ; ArtNem_8030A: even ArtNem_StripedBlocksVert: BINCLUDE "art/nemesis/Striped blocks from CPZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (16 blocks) ; Oil splashing into oil in OOZ ; ArtNem_80376: even ArtNem_Oilfall: BINCLUDE "art/nemesis/Cascading oil hitting oil from OOZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (13 blocks) ; Cascading oil from OOZ ; ArtNem_804F2: even ArtNem_Oilfall2: BINCLUDE "art/nemesis/Cascading oil from OOZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (20 blocks) ; Ball thing (unused?) from OOZ ; ArtNem_805C0: even ArtNem_BallThing: BINCLUDE "art/nemesis/Ball on spring from OOZ (beta holdovers).bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (53 blocks) ; Spinball from OOZ ; ArtNem_806E0: even ArtNem_LaunchBall: BINCLUDE "art/nemesis/Transporter ball from OOZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (40 blocks) ; Collapsing platform from OOZ ; ArtNem_809D0: even ArtNem_OOZPlatform: BINCLUDE "art/nemesis/OOZ collapsing platform.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (30 blocks) ; Diagonal and vertical weird spring from OOZ ; ArtNem_80C64: even ArtNem_PushSpring: BINCLUDE "art/nemesis/Push spring from OOZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (28 blocks) ; Swinging platform from OOZ ; ArtNem_80E26: even ArtNem_OOZSwingPlat: BINCLUDE "art/nemesis/Swinging platform from OOZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (4 blocks) ; 4 stripy blocks from OOZ ; ArtNem_81048: even ArtNem_StripedBlocksHoriz: BINCLUDE "art/nemesis/4 stripy blocks from OOZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (24 blocks) ; Raising platform from OOZ ; ArtNem_810B8: even ArtNem_OOZElevator: BINCLUDE "art/nemesis/Rising platform from OOZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (30 blocks) ; Fan in OOZ ; ArtNem_81254: even ArtNem_OOZFanHoriz: BINCLUDE "art/nemesis/Fan from OOZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (18 blocks) ; Green flame thing that shoots platform up in OOZ ; ArtNem_81514: even ArtNem_OOZBurn: BINCLUDE "art/nemesis/Green flame from OOZ burners.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (4 blocks) ; Patterns for appearing and disappearing string of platforms in CNZ ; ArtNem_81600: even ArtNem_CNZSnake: BINCLUDE "art/nemesis/Caterpiller platforms from CNZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (4 blocks) ; Spikey ball from pokie in CNZ ; ArtNem_81668: even ArtNem_CNZBonusSpike: BINCLUDE "art/nemesis/Spikey ball from CNZ slots.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (16 blocks) ; Moving cube from either CNZ or CPZ ; ArtNem_816C8: even ArtNem_BigMovingBlock: BINCLUDE "art/nemesis/Moving block from CNZ and CPZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (4 blocks) ; Elevator in CNZ ; ArtNem_817B4: even ArtNem_CNZElevator: BINCLUDE "art/nemesis/CNZ elevator.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (12 blocks) ; Bars from pokies in CNZ ; ArtNem_81826: even ArtNem_CNZCage: BINCLUDE "art/nemesis/CNZ slot machine bars.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (6 blocks) ; Hexagonal bumper in CNZ ; ArtNem_81894: even ArtNem_CNZHexBumper: BINCLUDE "art/nemesis/Hexagonal bumper from CNZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (24 blocks) ; Normal round bumper from CNZ ; ArtNem_8191E: even ArtNem_CNZRoundBumper: BINCLUDE "art/nemesis/Round bumper from CNZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (32 blocks) ; Diagonal spring from CNZ that you charge up ; ArtNem_81AB0: even ArtNem_CNZDiagPlunger: BINCLUDE "art/nemesis/Diagonal impulse spring from CNZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (18 blocks) ; Vertical red spring ; ArtNem_81C96: even ArtNem_CNZVertPlunger: BINCLUDE "art/nemesis/Vertical impulse spring.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (28 blocks) ; Weird blocks from CNZ that you hit 3 times to get rid of ; ArtNem_81DCC: even ArtNem_CNZMiniBumper: BINCLUDE "art/nemesis/Drop target from CNZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (52 blocks) ; Flippers from CNZ ; ArtNem_81EF2: even ArtNem_CNZFlipper: BINCLUDE "art/nemesis/Flippers.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (16 blocks) ; Large moving platform from CPZ ; ArtNem_82216: even ArtNem_CPZElevator: BINCLUDE "art/nemesis/Large moving platform from CNZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (24 blocks) ; Top of water in HPZ and CPZ ; ArtNem_82364: even ArtNem_WaterSurface: BINCLUDE "art/nemesis/Top of water in HPZ and CNZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (4 blocks) ; Booster things in CPZ ; ArtNem_824D4: even ArtNem_CPZBooster: BINCLUDE "art/nemesis/Speed booster from CPZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (4 blocks) ; CPZ droplet chain enemy ; ArtNem_8253C: even ArtNem_CPZDroplet: BINCLUDE "art/nemesis/CPZ worm enemy.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (33 blocks) ; CPZ metal things (girder, cylinders) ; ArtNem_825AE: even ArtNem_CPZMetalThings: BINCLUDE "art/nemesis/CPZ metal things.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (4 blocks) ; CPZ metal block ; ArtNem_827B8: even ArtNem_CPZMetalBlock: BINCLUDE "art/nemesis/CPZ large moving platform blocks.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (8 blocks) ; Yellow and black stripy tiles from DEZ ; ArtNem_827F8: even ArtNem_ConstructionStripes: BINCLUDE "art/nemesis/Stripy blocks from CPZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (48 blocks) ; Yellow flipping platforms and stuff CPZ ; ArtNem_82864: even ArtNem_CPZAnimatedBits: BINCLUDE "art/nemesis/Small yellow moving platform from CPZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (24 blocks) ; Moving block from CPZ ; ArtNem_82A46: even ArtNem_CPZStairBlock: BINCLUDE "art/nemesis/Moving block from CPZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (32 blocks) ; Spring that covers tube in CPZ ; ArtNem_82C06: even ArtNem_CPZTubeSpring: BINCLUDE "art/nemesis/CPZ spintube exit cover.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (16 blocks) ; Top of water in ARZ ; ArtNem_82E02: even ArtNem_WaterSurface2: BINCLUDE "art/nemesis/Top of water in ARZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (7 blocks) ; Leaves from ARZ ; ArtNem_82EE8: even ArtNem_Leaves: BINCLUDE "art/nemesis/Leaves in ARZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (17 blocks) ; Arrow shooter and arrow from ARZ ; ArtNem_82F74: even ArtNem_ArrowAndShooter: BINCLUDE "art/nemesis/Arrow shooter and arrow from ARZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (8 blocks) ; One way barrier from ARZ (unused?) ; ArtNem_830D2: even ArtNem_ARZBarrierThing: BINCLUDE "art/nemesis/One way barrier from ARZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (28 blocks) ; Buzz bomber ; ArtNem_8316A: even ArtNem_Buzzer: BINCLUDE "art/nemesis/Buzzer enemy.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (58 blocks) ; Octopus badnik from OOZ ; ArtNem_8336A: even ArtNem_Octus: BINCLUDE "art/nemesis/Octopus badnik from OOZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (56 blocks) ; Flying badnik from OOZ ; ArtNem_8368A: even ArtNem_Aquis: BINCLUDE "art/nemesis/Seahorse from OOZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (22 blocks) ; Fish badnik from EHZ ; ArtNem_839EA: ArtNem_Pirahna: even ArtNem_Masher: BINCLUDE "art/nemesis/EHZ Pirahna badnik.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (96 blocks) ; Robotnik's main ship ; ArtNem_83BF6: even ArtNem_Eggpod: BINCLUDE "art/nemesis/Eggpod.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (111 blocks) ; CPZ Boss ; ArtNem_84332: even ArtNem_CPZBoss: BINCLUDE "art/nemesis/CPZ boss.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (100 blocks) ; Large explosion ; ArtNem_84890: even ArtNem_FieryExplosion: BINCLUDE "art/nemesis/Large explosion.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (8 blocks) ; Horizontal jet ; ArtNem_84F18: even ArtNem_EggpodJets: BINCLUDE "art/nemesis/Horizontal jet.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (16 blocks) ; Smoke trail from CPZ and HTZ bosses ; ArtNem_84F96: even ArtNem_BossSmoke: BINCLUDE "art/nemesis/Smoke trail from CPZ and HTZ bosses.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (128 blocks) ; EHZ Boss ; ArtNem_8507C: even ArtNem_EHZBoss: BINCLUDE "art/nemesis/EHZ boss.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (20 blocks) ; Helicopter blades for EHZ boss ; ArtNem_85868: even ArtNem_EggChoppers: BINCLUDE "art/nemesis/Chopper blades for EHZ boss.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (107 blocks) ; HTZ boss ; ArtNem_8595C: even ArtNem_HTZBoss: BINCLUDE "art/nemesis/HTZ boss.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (166 blocks) ; ARZ boss ; ArtNem_86128: even ArtNem_ARZBoss: BINCLUDE "art/nemesis/ARZ boss.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (204 blocks) ; MCZ boss ; ArtNem_86B6E: even ArtNem_MCZBoss: BINCLUDE "art/nemesis/MCZ boss.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (133 blocks) ; CNZ boss ; ArtNem_87AAC: even ArtNem_CNZBoss: BINCLUDE "art/nemesis/CNZ boss.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (181 blocks) ; OOZ boss ; ArtNem_882D6: even ArtNem_OOZBoss: BINCLUDE "art/nemesis/OOZ boss.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (124 blocks) ; MTZ boss ; ArtNem_88DA6: even ArtNem_MTZBoss: BINCLUDE "art/nemesis/MTZ boss.bin" ;-------------------------------------------------------------------------------------- ; Uncompressed art (8 blocks) ; Falling rocks and stalactites from MCZ ; ArtUnc_894E4: even ArtUnc_FallingRocks: BINCLUDE "art/uncompressed/Falling rocks and stalactites from MCZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (9 blocks) ; Blowfly from ARZ ; ArtNem_895E4: even ArtNem_Whisp: BINCLUDE "art/nemesis/Blowfly from ARZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (50 blocks) ; Grounder from ARZ ; ArtNem_8970E: even ArtNem_Grounder: BINCLUDE "art/nemesis/Grounder from ARZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (24 blocks) ; Fish from ARZ ; ArtNem_89B9A: even ArtNem_ChopChop: BINCLUDE "art/nemesis/Shark from ARZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (19 blocks) ; Lava snake from HTZ 89DEC: ArtNem_HtzRexxon: even ArtNem_Rexon: BINCLUDE "art/nemesis/Rexxon (lava snake) from HTZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (20 blocks) ; Enemy with spike cone on top from HTZ 89FAA: ArtNem_HtzDriller: even ArtNem_Spiker: BINCLUDE "art/nemesis/Driller badnik from HTZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (28 blocks) ; Bomber badnik from SCZ ; ArtNem_8A142: even ArtNem_Nebula: BINCLUDE "art/nemesis/Bomber badnik from SCZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (57 blocks) ; Turtle badnik from SCZ ; ArtNem_8A362: even ArtNem_Turtloid: BINCLUDE "art/nemesis/Turtle badnik from SCZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (38 blocks) ; Coconuts monkey badnik from EHZ even ArtNem_Coconuts: BINCLUDE "art/nemesis/Coconuts badnik from EHZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (10 blocks) ; Snake badnik from MCZ ; ArtNem_8AB36: even ArtNem_Crawlton: BINCLUDE "art/nemesis/Snake badnik from MCZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (20 blocks) ; Firefly from MCZ ; ArtNem_8AC5E: even ArtNem_Flasher: BINCLUDE "art/nemesis/Firefly from MCZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (32 blocks) ; Praying mantis badnik from MTZ 8AD80: even ArtNem_MtzMantis: BINCLUDE "art/nemesis/Praying mantis badnik from MTZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (36 blocks) ; Crab badnik from MCZ 8B058: even ArtNem_Crabmeat: BINCLUDE "art/nemesis/Crabmeat badnik from MCZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (15 blocks) ; Exploding star badnik from MTZ 8B300: even ArtNem_MtzSupernova: BINCLUDE "art/nemesis/Exploding star badnik from MTZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (32 blocks) ; Weird crawling badnik from CPZ ; ArtNem_8B430: even ArtNem_Spiny: BINCLUDE "art/nemesis/Weird crawling badnik from CPZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (45 blocks) ; Spider badnik from CPZ ArtNem_8B6B4: even ArtNem_Grabber: BINCLUDE "art/nemesis/Spider badnik from CPZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (26 blocks) ; Chicken badnik from WFZ 8B9DC: even ArtNem_WfzScratch: BINCLUDE "art/nemesis/Scratch from WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (25 blocks) ; Jet like badnik from SCZ 8BC16: even ArtNem_Balkrie: BINCLUDE "art/nemesis/Balkrie (jet badnik) from SCZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (217 blocks) ; Silver Sonic ; ArtNem_8BE12: even ArtNem_SilverSonic: BINCLUDE "art/nemesis/Silver Sonic.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (79 blocks) ; The Tornado 8CC44: even ArtNem_Tornado: BINCLUDE "art/nemesis/The Tornado.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (24 blocks) ; Wall turret from WFZ 8D1A0: even ArtNem_WfzWallTurret: BINCLUDE "art/nemesis/Wall turret from WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (20 blocks) ; Hook on chain in WFZ 8D388: even ArtNem_WfzHook: BINCLUDE "art/nemesis/Hook on chain from WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (54 blocks) ; Retracting platform from WFZ 8D540: even ArtNem_WfzGunPlatform: BINCLUDE "art/nemesis/Retracting platform from WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (16 blocks) ; Wheel for belt in WFZ 8D7D8: even ArtNem_WfzConveyorBeltWheel: BINCLUDE "art/nemesis/Wheel for belt in WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (12 blocks) ; Moving platform in WFZ 8D96E: even ArtNem_WfzFloatingPlatform: BINCLUDE "art/nemesis/Moving platform from WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (12 blocks) ; Giant unused vertical red laser in WFZ 8DA6E: even ArtNem_WfzVrtclLazer: BINCLUDE "art/nemesis/Unused vertical laser in WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (18 blocks) ; Clouds 8DAFC: even ArtNem_Clouds: BINCLUDE "art/nemesis/Clouds.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (10 blocks) ; Red horizontal laser in WFZ 8DC42: even ArtNem_WfzHrzntlLazer: BINCLUDE "art/nemesis/Red horizontal laser from WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (5 blocks) ; Catapult that shoots sonic across quickly in WFZ 8DCA2: even ArtNem_WfzLaunchCatapult: BINCLUDE "art/nemesis/Catapult that shoots Sonic to the side from WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (12 blocks) ; Rising platforms on belt from WFZ 8DD0C: even ArtNem_WfzBeltPlatform: BINCLUDE "art/nemesis/Platform on belt in WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (12 blocks) ; Unused badnik in WFZ 8DDF6: even ArtNem_WfzUnusedBadnik: BINCLUDE "art/nemesis/Unused badnik from WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (4 blocks) ; Vertical spinning blades from WFZ 8DEB8: even ArtNem_WfzVrtclPrpllr: BINCLUDE "art/nemesis/Vertical spinning blades in WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (29 blocks) ; Horizontal spinning blades from WFZ 8DEE8: even ArtNem_WfzHrzntlPrpllr: BINCLUDE "art/nemesis/Horizontal spinning blades in WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (12 blocks) ; Platforms that tilt in WFZ 8E010: even ArtNem_WfzTiltPlatforms: BINCLUDE "art/nemesis/Tilting plaforms in WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (8 blocks) ; Thrust from Robotnic's getaway ship in WFZ 8E0C4: even ArtNem_WfzThrust: BINCLUDE "art/nemesis/Thrust from Robotnik's getaway ship in WFZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (117 blocks) ; Laser boss from WFZ ; ArtNem_8E138: even ArtNem_WFZBoss: BINCLUDE "art/nemesis/WFZ boss.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (24 blocks) ; Robotnik's head ; ArtNem_8E886: even ArtNem_RobotnikUpper: BINCLUDE "art/nemesis/Robotnik's head.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (76 blocks) ; Robotnik ; ArtNem_8EA5A: even ArtNem_RobotnikRunning: BINCLUDE "art/nemesis/Robotnik.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (28 blocks) ; Robotnik's lower half ; ArtNem_8EE52: even ArtNem_RobotnikLower: BINCLUDE "art/nemesis/Robotnik's lover half.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (8 blocks) ; Window in back that Robotnic looks through in DEZ ; ArtNem_8EF96: even ArtNem_DEZWindow: BINCLUDE "art/nemesis/Window in back that Robotnik looks through in DEZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (327 blocks) ; Eggrobo ; ArtNem_8F024: even ArtNem_DEZBoss: BINCLUDE "art/nemesis/Eggrobo.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (42 blocks) ; Bouncer badnik from CNZ ; ArtNem_901A4: even ArtNem_Crawl: BINCLUDE "art/nemesis/Bouncer badnik from CNZ.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (26 blocks) ; Rocket thruster for Tornado ; ArtNem_90520: even ArtNem_TornadoThruster: BINCLUDE "art/nemesis/Rocket thruster for Tornado.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Frame 1 of end of game sequence ; MapEng_906E0: MapEng_Ending1: BINCLUDE "mappings/misc/End of game sequence frame 1.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Frame 2 of end of game sequence ; MapEng_906F8: MapEng_Ending2: BINCLUDE "mappings/misc/End of game sequence frame 2.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Frame 3 of end of game sequence ; MapEng_90722: MapEng_Ending3: BINCLUDE "mappings/misc/End of game sequence frame 3.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Frame 4 of end of game sequence ; MapEng_9073C: MapEng_Ending4: BINCLUDE "mappings/misc/End of game sequence frame 4.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Closeup of Tails flying plane in ending sequence ; MapEng_9076E: MapEng_EndingTailsPlane: BINCLUDE "mappings/misc/Closeup of Tails flying plane in ending sequence.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Closeup of Sonic flying plane in ending sequence ; MapEng_907C0: MapEng_EndingSonicPlane: BINCLUDE "mappings/misc/Closeup of Sonic flying plane in ending sequence.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Strange unused mappings (duplicate of MapEng_EndGameLogo) ; MapEng_9082A: BINCLUDE "mappings/misc/Strange unused mappings 1 - 1.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Strange unused mappings (same as above) ; MapEng_90852: BINCLUDE "mappings/misc/Strange unused mappings 1 - 2.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Strange unused mappings (same as above) ; MapEng_9087A: BINCLUDE "mappings/misc/Strange unused mappings 1 - 3.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Strange unused mappings (same as above) ; MapEng_908A2: BINCLUDE "mappings/misc/Strange unused mappings 1 - 4.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Strange unused mappings (same as above) ; MapEng_908CA: BINCLUDE "mappings/misc/Strange unused mappings 1 - 5.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Strange unused mappings (same as above) ; MapEng_908F2: BINCLUDE "mappings/misc/Strange unused mappings 1 - 6.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Strange unused mappings (same as above) ; MapEng_9091A: BINCLUDE "mappings/misc/Strange unused mappings 1 - 7.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Strange unused mappings (same as above) ; MapEng_90942: BINCLUDE "mappings/misc/Strange unused mappings 1 - 8.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed sprite mappings ; Strange unused mappings (same as above) ; MapEng_9096A: BINCLUDE "mappings/misc/Strange unused mappings 2.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (363 blocks) ; Movie sequence at end of game ; ArtNem_90992: even ArtNem_EndingPics: BINCLUDE "art/nemesis/Movie sequence at end of game.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (127 blocks) ; Final image of Tornado with it and Sonic facing screen ; ArtNem_91F3C: even ArtNem_EndingFinalTornado: BINCLUDE "art/nemesis/Final image of Tornado with it and Sonic facing screen.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (109 blocks) ; Mini pictures of Tornado in final ending sequence ; ArtNem_927E0: even ArtNem_EndingMiniTornado: BINCLUDE "art/nemesis/Small pictures of Tornado in final ending sequence.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (135 blocks) ; Mini pictures of Sonic and final image of Sonic even ArtNem_EndingSonic: BINCLUDE "art/nemesis/Small pictures of Sonic and final image of Sonic.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (117 blocks) ; Mini pictures of Sonic and final image of Sonic in supersonic mode ; ArtNem_93848: even ArtNem_EndingSuperSonic: BINCLUDE "art/nemesis/Small pictures of Sonic and final image of Sonic in Super Sonic mode.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (181 blocks) ; Final image of Tails ; ArtNem_93F3C: even ArtNem_EndingTails: BINCLUDE "art/nemesis/Final image of Tails.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (72 blocks) ; Sonic the Hedgehog 2 image at end of credits ; ArtNem_94B28: even ArtNem_EndingTitle: BINCLUDE "art/nemesis/Sonic the Hedgehog 2 image at end of credits.bin" ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; LEVEL ART AND BLOCK MAPPINGS (16x16 and 128x128) ; ; #define BLOCK_TBL_LEN // table length unknown ; #define BIGBLOCK_TBL_LEN // table length unknown ; typedef uint16_t uword ; ; struct blockMapElement { ; uword unk : 5; // u ; uword patternIndex : 11; }; // i ; // uuuu uiii iiii iiii ; ; blockMapElement (*blockMapTable)[BLOCK_TBL_LEN][4] = 0xFFFF9000 ; ; struct bigBlockMapElement { ; uword : 4 ; uword blockMapIndex : 12; }; //I ; // 0000 IIII IIII IIII ; ; bigBlockMapElement (*bigBlockMapTable)[BIGBLOCK_TBL_LEN][64] = 0xFFFF0000 ; ; /* ; This data determines how the level blocks will be constructed graphically. There are ; two kinds of block mappings: 16x16 and 128x128. ; ; 16x16 blocks are made up of four cells arranged in a square (thus, 16x16 pixels). ; Two bytes are used to define each cell, so the block is 8 bytes long. It can be ; represented by the bitmap blockMapElement, of which the members are: ; ; unk ; These bits have to do with pattern orientation. I do not know their exact ; meaning. ; patternIndex ; The pattern's address divided by $20. Otherwise said: an index into the ; pattern array. ; ; Each mapping can be expressed as an array of four blockMapElements, while the ; whole table is expressed as a two-dimensional array of blockMapElements (blockMapTable). ; The maps are read in left-to-right, top-to-bottom order. ; ; 128x128 maps are basically lists of indices into blockMapTable. The levels are built ; out of these "big blocks", rather than the "small" 16x16 blocks. bigBlockMapTable is, ; predictably, the table of big block mappings. ; Each big block is 8 16x16 blocks, or 16 cells, square. This produces a total of 16 ; blocks or 64 cells. ; As noted earlier, each element of the table provides 'i' for blockMapTable[i][j]. ; */ ;---------------------------------------------------------------------------------- ; EHZ 16x16 block mappings (Kosinski compression) ; was: (Kozinski compression) BM16_EHZ: BINCLUDE "mappings/16x16/EHZ.bin" ;----------------------------------------------------------------------------------- ; EHZ/HTZ main level patterns (Kosinski compression) ; ArtKoz_95C24: ArtKos_EHZ: BINCLUDE "art/kosinski/EHZ_HTZ.bin" ;----------------------------------------------------------------------------------- ; HTZ 16x16 block mappings (Kosinski compression) BM16_HTZ: BINCLUDE "mappings/16x16/HTZ.bin" ;----------------------------------------------------------------------------------- ; HTZ pattern suppliment to EHZ level patterns (Kosinski compression) ; ArtKoz_98AB4: ArtKos_HTZ: BINCLUDE "art/kosinski/HTZ_Supp.bin" ;----------------------------------------------------------------------------------- ; EHZ/HTZ 128x128 block mappings (Kosinski compression) BM128_EHZ: BINCLUDE "mappings/128x128/EHZ_HTZ.bin" ;----------------------------------------------------------------------------------- ; MTZ 16x16 block mappings (Kosinski compression) BM16_MTZ: BINCLUDE "mappings/16x16/MTZ.bin" ;----------------------------------------------------------------------------------- ; MTZ main level patterns (Kosinski compression) ; ArtKoz_9DB64: ArtKos_MTZ: BINCLUDE "art/kosinski/MTZ.bin" ;----------------------------------------------------------------------------------- ; MTZ 128x128 block mappings (Kosinski compression) BM128_MTZ: BINCLUDE "mappings/128x128/MTZ.bin" ;----------------------------------------------------------------------------------- ; HPZ 16x16 block mappings (Kosinski compression) BM16_HPZ: ;BINCLUDE "mappings/16x16/HPZ.bin" ;----------------------------------------------------------------------------------- ; HPZ main level patterns (Kosinski compression) ArtKos_HPZ: ;BINCLUDE "art/kosinski/HPZ.bin" ;----------------------------------------------------------------------------------- ; HPZ 128x128 block mappings (Kosinski compression) BM128_HPZ: ;BINCLUDE "mappings/128x128/HPZ.bin" ;----------------------------------------------------------------------------------- ; OOZ 16x16 block mappings (Kosinski compression) BM16_OOZ: BINCLUDE "mappings/16x16/OOZ.bin" ;----------------------------------------------------------------------------------- ; OOZ main level patterns (Kosinski compression) ; ArtKoz_A4204: ArtKos_OOZ: BINCLUDE "art/kosinski/OOZ.bin" ;----------------------------------------------------------------------------------- ; OOZ 128x128 block mappings (Kosinski compression) BM128_OOZ: BINCLUDE "mappings/128x128/OOZ.bin" ;----------------------------------------------------------------------------------- ; MCZ 16x16 block mappings (Kosinski compression) BM16_MCZ: BINCLUDE "mappings/16x16/MCZ.bin" ;----------------------------------------------------------------------------------- ; MCZ main level patterns (Kosinski compression) ; ArtKoz_A9D74: ArtKos_MCZ: BINCLUDE "art/kosinski/MCZ.bin" ;----------------------------------------------------------------------------------- ; MCZ 128x128 block mappings (Kosinski compression) BM128_MCZ: BINCLUDE "mappings/128x128/MCZ.bin" ;----------------------------------------------------------------------------------- ; CNZ 16x16 block mappings (Kosinski compression) BM16_CNZ: BINCLUDE "mappings/16x16/CNZ.bin" ;----------------------------------------------------------------------------------- ; CNZ main level patterns (Kosinski compression) ; ArtKoz_B0894: ArtKos_CNZ: BINCLUDE "art/kosinski/CNZ.bin" ;----------------------------------------------------------------------------------- ; CNZ 128x128 block mappings (Kosinski compression) BM128_CNZ: BINCLUDE "mappings/128x128/CNZ.bin" ;----------------------------------------------------------------------------------- ; CPZ/DEZ 16x16 block mappings (Kosinski compression) BM16_CPZ: BINCLUDE "mappings/16x16/CPZ_DEZ.bin" ;----------------------------------------------------------------------------------- ; CPZ/DEZ main level patterns (Kosinski compression) ; ArtKoz_B6174: ArtKos_CPZ: BINCLUDE "art/kosinski/CPZ_DEZ.bin" ;----------------------------------------------------------------------------------- ; CPZ/DEZ 128x128 block mappings (Kosinski compression) BM128_CPZ: BINCLUDE "mappings/128x128/CPZ_DEZ.bin" ;----------------------------------------------------------------------------------- ; ARZ 16x16 block mappings (Kosinski compression) BM16_ARZ: BINCLUDE "mappings/16x16/ARZ.bin" ;----------------------------------------------------------------------------------- ; ARZ main level patterns (Kosinski compression) ; ArtKoz_BCC24: ArtKos_ARZ: BINCLUDE "art/kosinski/ARZ.bin" ;----------------------------------------------------------------------------------- ; ARZ 128x128 block mappings (Kosinski compression) BM128_ARZ: BINCLUDE "mappings/128x128/ARZ.bin" ;----------------------------------------------------------------------------------- ; WFZ/SCZ 16x16 block mappings (Kosinski compression) BM16_WFZ: BINCLUDE "mappings/16x16/WFZ_SCZ.bin" ;----------------------------------------------------------------------------------- ; WFZ/SCZ main level patterns (Kosinski compression) ; ArtKoz_C5004: ArtKos_SCZ: BINCLUDE "art/kosinski/WFZ_SCZ.bin" ;----------------------------------------------------------------------------------- ; WFZ pattern suppliment to SCZ tiles (Kosinski compression) ; ArtKoz_C7EC4: ArtKos_WFZ: BINCLUDE "art/kosinski/WFZ_Supp.bin" ;----------------------------------------------------------------------------------- ; WFZ/SCZ 128x128 block mappings (Kosinski compression) BM128_WFZ: BINCLUDE "mappings/128x128/WFZ_SCZ.bin" ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ;----------------------------------------------------------------------------------- ; Exit curve + slope up ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CA904: MapSpec_Rise1: BINCLUDE "mappings/special stage/Slope up - Frame 1.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CADA8: MapSpec_Rise2: BINCLUDE "mappings/special stage/Slope up - Frame 2.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CB376: MapSpec_Rise3: BINCLUDE "mappings/special stage/Slope up - Frame 3.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CB92E: MapSpec_Rise4: BINCLUDE "mappings/special stage/Slope up - Frame 4.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CBF92: MapSpec_Rise5: BINCLUDE "mappings/special stage/Slope up - Frame 5.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CC5BE: MapSpec_Rise6: BINCLUDE "mappings/special stage/Slope up - Frame 6.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CCC7A: MapSpec_Rise7: BINCLUDE "mappings/special stage/Slope up - Frame 7.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CD282: MapSpec_Rise8: BINCLUDE "mappings/special stage/Slope up - Frame 8.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CD7C0: MapSpec_Rise9: BINCLUDE "mappings/special stage/Slope up - Frame 9.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CDD44: MapSpec_Rise10: BINCLUDE "mappings/special stage/Slope up - Frame 10.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CE2BE: MapSpec_Rise11: BINCLUDE "mappings/special stage/Slope up - Frame 11.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CE7DE: MapSpec_Rise12: BINCLUDE "mappings/special stage/Slope up - Frame 12.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CEC52: MapSpec_Rise13: BINCLUDE "mappings/special stage/Slope up - Frame 13.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CF0BC: MapSpec_Rise14: BINCLUDE "mappings/special stage/Slope up - Frame 14.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CF580: MapSpec_Rise15: BINCLUDE "mappings/special stage/Slope up - Frame 15.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CFA00: MapSpec_Rise16: BINCLUDE "mappings/special stage/Slope up - Frame 16.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_CFE4A: MapSpec_Rise17: BINCLUDE "mappings/special stage/Slope up - Frame 17.bin" ;----------------------------------------------------------------------------------- ; Straight path ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D028C: MapSpec_Straight1: BINCLUDE "mappings/special stage/Straight path - Frame 1.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D090A: MapSpec_Straight2: BINCLUDE "mappings/special stage/Straight path - Frame 2.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D0EA6: MapSpec_Straight3: BINCLUDE "mappings/special stage/Straight path - Frame 3.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D1400: MapSpec_Straight4: BINCLUDE "mappings/special stage/Straight path - Frame 4.bin" ;----------------------------------------------------------------------------------- ; Exit curve + slope down ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D19FC: MapSpec_Drop1: BINCLUDE "mappings/special stage/Slope down - Frame 1.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D1EAC: MapSpec_Drop2: BINCLUDE "mappings/special stage/Slope down - Frame 2.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D23AE: MapSpec_Drop3: BINCLUDE "mappings/special stage/Slope down - Frame 3.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D27C6: MapSpec_Drop4: BINCLUDE "mappings/special stage/Slope down - Frame 4.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D2C14: MapSpec_Drop5: BINCLUDE "mappings/special stage/Slope down - Frame 5.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D3092: MapSpec_Drop6: BINCLUDE "mappings/special stage/Slope down - Frame 6.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D3522: MapSpec_Drop7: BINCLUDE "mappings/special stage/Slope down - Frame 7.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D39EC: MapSpec_Drop8: BINCLUDE "mappings/special stage/Slope down - Frame 8.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D3F78: MapSpec_Drop9: BINCLUDE "mappings/special stage/Slope down - Frame 9.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D4660: MapSpec_Drop10: BINCLUDE "mappings/special stage/Slope down - Frame 10.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D4DA6: MapSpec_Drop11: BINCLUDE "mappings/special stage/Slope down - Frame 11.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D53FC: MapSpec_Drop12: BINCLUDE "mappings/special stage/Slope down - Frame 12.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D5958: MapSpec_Drop13: BINCLUDE "mappings/special stage/Slope down - Frame 13.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D5F02: MapSpec_Drop14: BINCLUDE "mappings/special stage/Slope down - Frame 14.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D6596: MapSpec_Drop15: BINCLUDE "mappings/special stage/Slope down - Frame 15.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D6BAA: MapSpec_Drop16: BINCLUDE "mappings/special stage/Slope down - Frame 16.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D702E: MapSpec_Drop17: BINCLUDE "mappings/special stage/Slope down - Frame 17.bin" ;----------------------------------------------------------------------------------- ; Curved path ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D749C: MapSpec_Turning1: BINCLUDE "mappings/special stage/Curve right - Frame 1.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D7912: MapSpec_Turning2: BINCLUDE "mappings/special stage/Curve right - Frame 2.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D7DAA: MapSpec_Turning3: BINCLUDE "mappings/special stage/Curve right - Frame 3.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D8250: MapSpec_Turning4: BINCLUDE "mappings/special stage/Curve right - Frame 4.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D85F8: MapSpec_Turning5: BINCLUDE "mappings/special stage/Curve right - Frame 5.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; MapSpec_D89EC: MapSpec_Turning6: BINCLUDE "mappings/special stage/Curve right - Frame 6.bin" ;----------------------------------------------------------------------------------- ; Exit curve ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; Exit curve ; MapSpec_D8E24: MapSpec_Unturn1: BINCLUDE "mappings/special stage/Curve right - Frame 7.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; Exit curve ; MapSpec_D92B6: MapSpec_Unturn2: BINCLUDE "mappings/special stage/Curve right - Frame 8.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; Exit curve ; MapSpec_D9778: MapSpec_Unturn3: BINCLUDE "mappings/special stage/Curve right - Frame 9.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; Exit curve ; MapSpec_D9B80: MapSpec_Unturn4: BINCLUDE "mappings/special stage/Curve right - Frame 10.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; Exit curve ; MapSpec_DA016: MapSpec_Unturn5: BINCLUDE "mappings/special stage/Curve right - Frame 11.bin" ;----------------------------------------------------------------------------------- ; Enter curve ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; Begin curve right ; MapSpec_DA4CE: MapSpec_Turn1: BINCLUDE "mappings/special stage/Begin curve right - Frame 1.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; Begin curve right ; MapSpec_DAB20: MapSpec_Turn2: BINCLUDE "mappings/special stage/Begin curve right - Frame 2.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; Begin curve right ; MapSpec_DB086: MapSpec_Turn3: BINCLUDE "mappings/special stage/Begin curve right - Frame 3.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; Begin curve right ; MapSpec_DB5AE: MapSpec_Turn4: BINCLUDE "mappings/special stage/Begin curve right - Frame 4.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; Begin curve right ; MapSpec_DBB62: MapSpec_Turn5: BINCLUDE "mappings/special stage/Begin curve right - Frame 5.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; Begin curve right ; MapSpec_DC154: MapSpec_Turn6: BINCLUDE "mappings/special stage/Begin curve right - Frame 6.bin" ;----------------------------------------------------------------------------------- ; Special stage tube mappings ; Begin curve right ; MapSpec_DC5E8: MapSpec_Turn7: BINCLUDE "mappings/special stage/Begin curve right - Frame 7.bin" ;-------------------------------------------------------------------------------------- ; Kosinski compressed art ; Special stage level patterns ; Note: Only one line of each tile is stored in this archive. The other 7 lines are ; the same as this one line, so to get the full tiles, each line needs to be ; duplicated 7 times over. ; ArtKoz_DCA38: ;-------------------------------------------------------------------------------------- ArtKos_Special: BINCLUDE "art/kosinski/SpecStag.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (127 blocks) ; Background patterns for special stage ; ArtNem_DCD68: even ArtNem_SpecialBack: BINCLUDE "art/nemesis/Background art for special stage.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed tile mappings ; Main background mappings for special stage ; MapEng_DD1DE: MapEng_SpecialBack: BINCLUDE "mappings/misc/Main background mappings for special stage.bin" ;-------------------------------------------------------------------------------------- ; Enigma compressed tile mappings ; Lower background mappings for special stage ; MapEng_DD30C: MapEng_SpecialBackBottom: BINCLUDE "mappings/misc/Lower background mappings for special stage.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (62 blocks) ; Sonic/Miles and number text from special stage ; ArtNem_DD48A: even ArtNem_SpecialHUD: BINCLUDE "art/nemesis/Sonic and Miles number text from special stage.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (48 blocks) ; "Start" and checkered flag patterns in special stage ; ArtNem_DD790: even ArtNem_SpecialStart: BINCLUDE "art/nemesis/Start text from special stage.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (37 blocks) ; Stars in special stage ; ArtNem_DD8CE: even ArtNem_SpecialStars: BINCLUDE "art/nemesis/Stars in special stage.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (13 blocks) ; Text for most of the "Player VS Player" message in 2P special stage ; ArtNem_DD9C8: even ArtNem_SpecialPlayerVSPlayer: BINCLUDE "art/nemesis/Special stage Player VS Player text.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (104 blocks) ; Ring patterns in special stage ; ArtNem_DDA7E: even ArtNem_SpecialRings: BINCLUDE "art/nemesis/Special stage ring art.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (38 blocks) ; Horizontal shadow patterns in special stage ; ArtNem_DDFA4: even ArtNem_SpecialFlatShadow: BINCLUDE "art/nemesis/Horizontal shadow from special stage.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (58 blocks) ; Diagonal shadow patterns in special stage ; ArtNem_DE05A: even ArtNem_SpecialDiagShadow: BINCLUDE "art/nemesis/Diagonal shadow from special stage.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (25 blocks) ; Vertical shadow patterns in special stage ; ArtNem_DE120: even ArtNem_SpecialSideShadow: BINCLUDE "art/nemesis/Vertical shadow from special stage.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (48 blocks) ; Explosion patterns in special stage ; ArtNem_DE188: even ArtNem_SpecialExplosion: BINCLUDE "art/nemesis/Explosion from special stage.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (80 blocks) ; Bomb patterns in special stage ; ArtNem_DE4BC: even ArtNem_SpecialBomb: BINCLUDE "art/nemesis/Bomb from special stage.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (46 blocks) ; Emerald patterns in special stage ; ArtNem_DE8AC: even ArtNem_SpecialEmerald: BINCLUDE "art/nemesis/Emerald from special stage.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (99 blocks) ; Text for the messages and thumbs up/down icon in special stage ; ArtNem_DEAF4: even ArtNem_SpecialMessages: BINCLUDE "art/nemesis/Special stage messages and icons.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (851 blocks) ; Sonic and Tails animation frames from special stage ; Art for Obj09 and Obj10 and Obj88 ; ArtNem_DEEAE: even ArtNem_SpecialSonicAndTails: BINCLUDE "art/nemesis/Sonic and Tails animation frames in special stage.bin" ;-------------------------------------------------------------------------------------- ; Nemesis compressed art (5 blocks) ; "Tails" patterns from special stage ; ArtNem_E247E: even ArtNem_SpecialTailsText: BINCLUDE "art/nemesis/Tails text patterns from special stage.bin" ;-------------------------------------------------------------------------------------- ; Special stage object perspective data (Kosinski compression) ; MiscKoz_E24FE: ;-------------------------------------------------------------------------------------- MiscKoz_SpecialPerspective: BINCLUDE "misc/Special stage object perspective data (Kosinski compression).bin" ;-------------------------------------------------------------------------------------- ; Special stage level layout (Nemesis compression) ; MiscNem_E34EE: ;-------------------------------------------------------------------------------------- MiscKoz_SpecialLevelLayout: BINCLUDE "misc/Special stage level layouts (Nemesis compression).bin" ;-------------------------------------------------------------------------------------- ; Special stage object location list (Kosinski compression) ; MiscKoz_E35F2: ;-------------------------------------------------------------------------------------- MiscKoz_SpecialObjectLocations: BINCLUDE "misc/Special stage object location lists (Kosinski compression).bin" ;-------------------------------------------------------------------------------------- ; Filler (free space) (unnecessary; could be replaced with "even") ;-------------------------------------------------------------------------------------- align $100 ;-------------------------------------------------------------------------------------- ; Offset index of ring locations ; The first commented number on each line is an array index; the second is the ; associated zone. ;-------------------------------------------------------------------------------------- Off_Rings: zoneOrderedOffsetTable 2,2 zoneOffsetTableEntry.w Rings_EHZ_1 ; 0 $00 zoneOffsetTableEntry.w Rings_EHZ_2 ; 1 zoneOffsetTableEntry.w Rings_Lev1_1 ; 2 $01 zoneOffsetTableEntry.w Rings_Lev1_2 ; 3 zoneOffsetTableEntry.w Rings_Lev2_1 ; 4 $02 zoneOffsetTableEntry.w Rings_Lev2_2 ; 5 zoneOffsetTableEntry.w Rings_Lev3_1 ; 6 $03 zoneOffsetTableEntry.w Rings_Lev3_2 ; 7 zoneOffsetTableEntry.w Rings_MTZ_1 ; 8 $04 zoneOffsetTableEntry.w Rings_MTZ_2 ; 9 zoneOffsetTableEntry.w Rings_MTZ_3 ; 10 $05 zoneOffsetTableEntry.w Rings_MTZ_4 ; 11 zoneOffsetTableEntry.w Rings_WFZ_1 ; 12 $06 zoneOffsetTableEntry.w Rings_WFZ_2 ; 13 zoneOffsetTableEntry.w Rings_HTZ_1 ; 14 $07 zoneOffsetTableEntry.w Rings_HTZ_2 ; 15 zoneOffsetTableEntry.w Rings_HPZ_1 ; 16 $08 zoneOffsetTableEntry.w Rings_HPZ_2 ; 17 zoneOffsetTableEntry.w Rings_Lev9_1 ; 18 $09 zoneOffsetTableEntry.w Rings_Lev9_2 ; 19 zoneOffsetTableEntry.w Rings_OOZ_1 ; 20 $0A zoneOffsetTableEntry.w Rings_OOZ_2 ; 21 zoneOffsetTableEntry.w Rings_MCZ_1 ; 22 $0B zoneOffsetTableEntry.w Rings_MCZ_2 ; 23 zoneOffsetTableEntry.w Rings_CNZ_1 ; 24 $0C zoneOffsetTableEntry.w Rings_CNZ_2 ; 25 zoneOffsetTableEntry.w Rings_CPZ_1 ; 26 $0D zoneOffsetTableEntry.w Rings_CPZ_2 ; 27 zoneOffsetTableEntry.w Rings_DEZ_1 ; 28 $0E zoneOffsetTableEntry.w Rings_DEZ_2 ; 29 zoneOffsetTableEntry.w Rings_ARZ_1 ; 30 $0F zoneOffsetTableEntry.w Rings_ARZ_2 ; 31 zoneOffsetTableEntry.w Rings_SCZ_1 ; 32 $10 zoneOffsetTableEntry.w Rings_SCZ_2 ; 33 zoneTableEnd Rings_EHZ_1: BINCLUDE "level/rings/EHZ_1.bin" Rings_EHZ_2: BINCLUDE "level/rings/EHZ_2.bin" Rings_Lev1_1: BINCLUDE "level/rings/01_1.bin" Rings_Lev1_2: BINCLUDE "level/rings/01_2.bin" Rings_Lev2_1: BINCLUDE "level/rings/02_1.bin" Rings_Lev2_2: BINCLUDE "level/rings/02_2.bin" Rings_Lev3_1: BINCLUDE "level/rings/03_1.bin" Rings_Lev3_2: BINCLUDE "level/rings/03_2.bin" Rings_MTZ_1: BINCLUDE "level/rings/MTZ_1.bin" Rings_MTZ_2: BINCLUDE "level/rings/MTZ_2.bin" Rings_MTZ_3: BINCLUDE "level/rings/MTZ_3.bin" Rings_MTZ_4: BINCLUDE "level/rings/MTZ_4.bin" Rings_HTZ_1: BINCLUDE "level/rings/HTZ_1.bin" Rings_HTZ_2: BINCLUDE "level/rings/HTZ_2.bin" Rings_HPZ_1: BINCLUDE "level/rings/HPZ_1.bin" Rings_HPZ_2: BINCLUDE "level/rings/HPZ_2.bin" Rings_Lev9_1: BINCLUDE "level/rings/09_1.bin" Rings_Lev9_2: BINCLUDE "level/rings/09_2.bin" Rings_OOZ_1: BINCLUDE "level/rings/OOZ_1.bin" Rings_OOZ_2: BINCLUDE "level/rings/OOZ_2.bin" Rings_MCZ_1: BINCLUDE "level/rings/MCZ_1.bin" Rings_MCZ_2: BINCLUDE "level/rings/MCZ_2.bin" Rings_CNZ_1: BINCLUDE "level/rings/CNZ_1.bin" Rings_CNZ_2: BINCLUDE "level/rings/CNZ_2.bin" Rings_CPZ_1: BINCLUDE "level/rings/CPZ_1.bin" Rings_CPZ_2: BINCLUDE "level/rings/CPZ_2.bin" Rings_DEZ_1: BINCLUDE "level/rings/DEZ_1.bin" Rings_DEZ_2: BINCLUDE "level/rings/DEZ_2.bin" Rings_WFZ_1: BINCLUDE "level/rings/WFZ_1.bin" Rings_WFZ_2: BINCLUDE "level/rings/WFZ_2.bin" Rings_ARZ_1: BINCLUDE "level/rings/ARZ_1.bin" Rings_ARZ_2: BINCLUDE "level/rings/ARZ_2.bin" Rings_SCZ_1: BINCLUDE "level/rings/SCZ_1.bin" Rings_SCZ_2: BINCLUDE "level/rings/SCZ_2.bin" ; -------------------------------------------------------------------------------------- ; Filler (free space) (unnecessary; could be replaced with "even") ; -------------------------------------------------------------------------------------- align $200 ; -------------------------------------------------------------------------------------- ; Offset index of object locations ; -------------------------------------------------------------------------------------- Off_Objects: zoneOrderedOffsetTable 2,2 zoneOffsetTableEntry.w Objects_EHZ_1 ; 0 $00 zoneOffsetTableEntry.w Objects_EHZ_2 ; 1 zoneOffsetTableEntry.w Objects_Null3 ; 2 $01 zoneOffsetTableEntry.w Objects_Null3 ; 3 zoneOffsetTableEntry.w Objects_Null3 ; 4 $02 zoneOffsetTableEntry.w Objects_Null3 ; 5 zoneOffsetTableEntry.w Objects_Null3 ; 6 $03 zoneOffsetTableEntry.w Objects_Null3 ; 7 zoneOffsetTableEntry.w Objects_MTZ_1 ; 8 $04 zoneOffsetTableEntry.w Objects_MTZ_2 ; 9 zoneOffsetTableEntry.w Objects_MTZ_3 ; 10 $05 zoneOffsetTableEntry.w Objects_MTZ_3 ; 11 zoneOffsetTableEntry.w Objects_WFZ_1 ; 12 $06 zoneOffsetTableEntry.w Objects_WFZ_2 ; 13 zoneOffsetTableEntry.w Objects_HTZ_1 ; 14 $07 zoneOffsetTableEntry.w Objects_HTZ_2 ; 15 zoneOffsetTableEntry.w Objects_HPZ_1 ; 16 $08 zoneOffsetTableEntry.w Objects_HPZ_2 ; 17 zoneOffsetTableEntry.w Objects_Null3 ; 18 $09 zoneOffsetTableEntry.w Objects_Null3 ; 19 zoneOffsetTableEntry.w Objects_OOZ_1 ; 20 $0A zoneOffsetTableEntry.w Objects_OOZ_2 ; 21 zoneOffsetTableEntry.w Objects_MCZ_1 ; 22 $0B zoneOffsetTableEntry.w Objects_MCZ_2 ; 23 zoneOffsetTableEntry.w Objects_CNZ_1 ; 24 $0C zoneOffsetTableEntry.w Objects_CNZ_2 ; 25 zoneOffsetTableEntry.w Objects_CPZ_1 ; 26 $0D zoneOffsetTableEntry.w Objects_CPZ_2 ; 27 zoneOffsetTableEntry.w Objects_DEZ_1 ; 28 $0E zoneOffsetTableEntry.w Objects_DEZ_2 ; 29 zoneOffsetTableEntry.w Objects_ARZ_1 ; 30 $0F zoneOffsetTableEntry.w Objects_ARZ_2 ; 31 zoneOffsetTableEntry.w Objects_SCZ_1 ; 32 $10 zoneOffsetTableEntry.w Objects_SCZ_2 ; 33 zoneTableEnd ;Objects_Null1: ; looks unused, but it's really not. there must be a null entry first or you will get crashes. (try going left from second screen of EHZ1) BINCLUDE "level/objects/Null_1.bin" Objects_EHZ_1: BINCLUDE "level/objects/EHZ_1.bin" if gameRevision=0 Objects_EHZ_2: BINCLUDE "level/objects/EHZ_2 (REV00).bin" else ; a collision switcher was moved Objects_EHZ_2: BINCLUDE "level/objects/EHZ_2.bin" endif Objects_MTZ_1: BINCLUDE "level/objects/MTZ_1.bin" Objects_MTZ_2: BINCLUDE "level/objects/MTZ_2.bin" Objects_MTZ_3: BINCLUDE "level/objects/MTZ_3.bin" if gameRevision=0 Objects_WFZ_1: BINCLUDE "level/objects/WFZ_1 (REV00).bin" else ; lampposts' 'remember state' flags were set Objects_WFZ_1: BINCLUDE "level/objects/WFZ_1.bin" endif Objects_WFZ_2: BINCLUDE "level/objects/WFZ_2.bin" Objects_HTZ_1: BINCLUDE "level/objects/HTZ_1.bin" Objects_HTZ_2: BINCLUDE "level/objects/HTZ_2.bin" Objects_HPZ_1: BINCLUDE "level/objects/HPZ_1.bin" Objects_HPZ_2: BINCLUDE "level/objects/HPZ_2.bin" ;Objects_Null2: ; unused BINCLUDE "level/objects/Null_2.bin" Objects_OOZ_1: BINCLUDE "level/objects/OOZ_1.bin" Objects_OOZ_2: BINCLUDE "level/objects/OOZ_2.bin" Objects_MCZ_1: BINCLUDE "level/objects/MCZ_1.bin" Objects_MCZ_2: BINCLUDE "level/objects/MCZ_2.bin" if gameRevision=0 Objects_CNZ_1: BINCLUDE "level/objects/CNZ_1 (REV00).bin" Objects_CNZ_2: BINCLUDE "level/objects/CNZ_2 (REV00).bin" else ; the signposts were moved up slightly so they weren't poking out the bottom of the ground Objects_CNZ_1: BINCLUDE "level/objects/CNZ_1.bin" Objects_CNZ_2: BINCLUDE "level/objects/CNZ_2.bin" endif Objects_CPZ_1: BINCLUDE "level/objects/CPZ_1.bin" Objects_CPZ_2: BINCLUDE "level/objects/CPZ_2.bin" Objects_DEZ_1: BINCLUDE "level/objects/DEZ_1.bin" Objects_DEZ_2: BINCLUDE "level/objects/DEZ_2.bin" Objects_ARZ_1: BINCLUDE "level/objects/ARZ_1.bin" Objects_ARZ_2: BINCLUDE "level/objects/ARZ_2.bin" Objects_SCZ_1: BINCLUDE "level/objects/SCZ_1.bin" Objects_SCZ_2: BINCLUDE "level/objects/SCZ_2.bin" Objects_Null3: BINCLUDE "level/objects/Null_3.bin" ;Objects_Null4: ; unused BINCLUDE "level/objects/Null_4.bin" ;Objects_Null5: ; unused BINCLUDE "level/objects/Null_5.bin" ;Objects_Null6: ; unused BINCLUDE "level/objects/Null_6.bin" ; -------------------------------------------------------------------------------------- ; Filler (free space) (unnecessary; could be replaced with "even") ; -------------------------------------------------------------------------------------- align $1000 ; --------------------------------------------------------------------------- ; Subroutine to load the sound driver ; --------------------------------------------------------------------------- ; sub_EC000: SoundDriverLoad: move sr,-(sp) movem.l d0-a6,-(sp) move #$2700,sr lea (Z80_Bus_Request).l,a3 lea (Z80_Reset).l,a2 moveq #0,d2 move.w #$100,d1 move.w d1,(a3) ; get Z80 bus move.w d1,(a2) ; release Z80 reset (was held high by console on startup) - btst d2,(a3) bne.s - ; wait until the 68000 has the bus jsr DecompressSoundDriver(pc) btst #0,(VDP_control_port+1).l ; check video mode sne (Z80_RAM+zPalModeByte).l ; set if PAL move.w d2,(a2) ; hold Z80 reset move.w d2,(a3) ; release Z80 bus moveq #$E6,d0 - dbf d0,- ; wait for 2,314 cycles move.w d1,(a2) ; release Z80 reset movem.l (sp)+,d0-a6 move (sp)+,sr rts ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; slightly modified Saxman decompression of the sound driver ; a4 == $A00000 (start of Z80 RAM) ; a5 == current position in Z80 RAM? ; a6 == current position in compressed sound driver? ; d0 == data to decompress? (byte) ; d4 == ??? ; d5 == ??? ; d6 == ??? ; d7 == bytes left to decompress ; loc_EC04A: DecompressSoundDriver: lea Snd_Driver(pc),a6 ; WARNING: the build script needs editing if you rename this label movewZ80CompSize: move.w #Snd_Driver_End-Snd_Driver,d7 ; patched (by fixpointer.exe) after compression since the exact size can't be known beforehand moveq #0,d6 lea (Z80_RAM).l,a5 moveq #0,d5 lea (Z80_RAM).l,a4 loc_EC062: lsr.w #1,d6 btst #8,d6 bne.s + jsr sub_EC0DE(pc) move.b d0,d6 ori.w #$FF00,d6 + btst #0,d6 beq.s loc_EC086 jsr sub_EC0DE(pc) move.b d0,(a5)+ addq.w #1,d5 bra.w loc_EC062 ; --------------------------------------------------------------------------- loc_EC086: jsr sub_EC0DE(pc) moveq #0,d4 move.b d0,d4 jsr sub_EC0DE(pc) move.b d0,d3 andi.w #$F,d3 addq.w #2,d3 andi.w #$F0,d0 lsl.w #4,d0 add.w d0,d4 addi.w #$12,d4 andi.w #$FFF,d4 move.w d5,d0 andi.w #$F000,d0 add.w d0,d4 cmp.w d4,d5 bhs.s loc_EC0CC subi.w #$1000,d4 bcc.s loc_EC0CC add.w d3,d5 addq.w #1,d5 - move.b #0,(a5)+ dbf d3,- bra.w loc_EC062 ; --------------------------------------------------------------------------- loc_EC0CC: add.w d3,d5 addq.w #1,d5 - move.b (a4,d4.w),(a5)+ addq.w #1,d4 dbf d3,- bra.w loc_EC062 ; End of function DecompressSoundDriver ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| sub_EC0DE: move.b (a6)+,d0 subq.w #1,d7 bne.s + addq.w #4,sp + rts ; End of function sub_EC0DE ; =========================================================================== ; --------------------------------------------------------------------------- ; S2 sound driver (Sound driver compression (slightly modified Saxman)) ; --------------------------------------------------------------------------- ; loc_EC0E8: Snd_Driver: save include "s2.sounddriver.asm" ; CPU Z80 restore padding off !org (Snd_Driver+Size_of_Snd_driver_guess) ; don't worry; I know what I'm doing ; loc_ED04C: Snd_Driver_End: ; --------------------------------------------------------------------------- ; Filler (free space) ; --------------------------------------------------------------------------- ; the DAC data has to line up with the end of the bank. ; actually it only has to fit within one bank, but we'll line it up to the end anyway ; because the padding gives the sound driver some room to grow cnop -Size_of_DAC_samples, $8000 ; --------------------------------------------------------------------------- ; DAC samples ; --------------------------------------------------------------------------- ; loc_ED100: SndDAC_Start: SndDAC_Sample1: BINCLUDE "sound/DAC/Sample 1.bin" SndDAC_Sample1_End SndDAC_Sample2: BINCLUDE "sound/DAC/Sample 2.bin" SndDAC_Sample2_End SndDAC_Sample5: BINCLUDE "sound/DAC/Sample 5.bin" SndDAC_Sample5_End SndDAC_Sample6: BINCLUDE "sound/DAC/Sample 6.bin" SndDAC_Sample6_End SndDAC_Sample3: BINCLUDE "sound/DAC/Sample 3.bin" SndDAC_Sample3_End SndDAC_Sample4: BINCLUDE "sound/DAC/Sample 4.bin" SndDAC_Sample4_End SndDAC_Sample7: BINCLUDE "sound/DAC/Sample 7.bin" SndDAC_Sample7_End SndDAC_End if SndDAC_End - SndDAC_Start > $8000 fatal "DAC samples must fit within $8000 bytes, but you have $\{SndDAC_End-SndDAC_Start } bytes of DAC samples." endif if SndDAC_End - SndDAC_Start > Size_of_DAC_samples fatal "Size_of_DAC_samples = $\{Size_of_DAC_samples}, but you have $\{SndDAC_End-SndDAC_Start} bytes of DAC samples." endif ; --------------------------------------------------------------------------- ; Music pointers ; --------------------------------------------------------------------------- ; loc_F0000: MusicPoint1: startBank MusPtr_Continue: rom_ptr_z80 Mus_Continue Mus_Continue: BINCLUDE "sound/music/Continue.bin" finishBank ; -------------------------------------------------------------------- ; Nemesis compressed art (20 blocks) ; Buzzer's fireball ArtNem_Buzzer_Fireball: BINCLUDE "art/nemesis/Fireball 1 (Buzzer).bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (24 blocks) ; Waterfall tiles ArtNem_Waterfall: BINCLUDE "art/nemesis/Waterfall tiles.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (16 blocks) ; Another fireball ArtNem_HtzFireball: BINCLUDE "art/nemesis/Fireball 2.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (8 blocks) ; Bridge in EHZ ArtNem_EHZ_Bridge: BINCLUDE "art/nemesis/EHZ bridge.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (48 blocks) ; Diagonally moving lift in HTZ ArtNem_HtzZipline: BINCLUDE "art/nemesis/HTZ zip-line platform.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (4 blocks) ; One way barrier from HTZ ArtNem_HtzValveBarrier: BINCLUDE "art/nemesis/One way barrier from HTZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (24 blocks) ; See-saw in HTZ ArtNem_HtzSeeSaw: BINCLUDE "art/nemesis/See-saw in HTZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (24 blocks) ; Unused Fireball ;ArtNem_F0B06: BINCLUDE "art/nemesis/Fireball 3.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (20 blocks) ; Rock from HTZ ArtNem_HtzRock: BINCLUDE "art/nemesis/Rock from HTZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (4 blocks) ; Orbit badnik from HTZ ; ArtNem_HtzSol: ArtNem_Sol: BINCLUDE "art/nemesis/Sol badnik from HTZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (120 blocks) ; Large spinning wheel from MTZ ArtNem_MtzWheel: BINCLUDE "art/nemesis/Large spinning wheel from MTZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (9 blocks) ; Indent in large spinning wheel from MTZ ArtNem_MtzWheelIndent: BINCLUDE "art/nemesis/Large spinning wheel from MTZ - indent.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (8 blocks) ; Spike block from MTZ ArtNem_MtzSpikeBlock: BINCLUDE "art/nemesis/MTZ spike block.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (15 blocks) ; Steam from MTZ ArtNem_MtzSteam: BINCLUDE "art/nemesis/Steam from MTZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (8 blocks) ; Spike from MTZ ArtNem_MtzSpike: BINCLUDE "art/nemesis/Spike from MTZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (54 blocks) ; Similarly shaded blocks from MTZ ArtNem_MtzAsstBlocks: BINCLUDE "art/nemesis/Similarly shaded blocks from MTZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (9 blocks) ; Lava bubble from MTZ ArtNem_MtzLavaBubble: BINCLUDE "art/nemesis/Lava bubble from MTZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (4 blocks) ; Lava cup ArtNem_LavaCup: BINCLUDE "art/nemesis/Lava cup from MTZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (8 blocks) ; End of a bolt and rope from MTZ ArtNem_BoltEnd_Rope: BINCLUDE "art/nemesis/Bolt end and rope from MTZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (12 blocks) ; Small cog from MTZ ArtNem_MtzCog: BINCLUDE "art/nemesis/Small cog from MTZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (4 blocks) ; Flash inside spin tube from MTZ ArtNem_MtzSpinTubeFlash: BINCLUDE "art/nemesis/Spin tube flash from MTZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (32 blocks) ; Large wooden box from MCZ ; ArtNem_F187C: ArtNem_Crate: BINCLUDE "art/nemesis/Large wooden box from MCZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (26 blocks) ; Collapsing platform from MCZ ; ArtNem_F1ABA: ArtNem_MCZCollapsePlat: BINCLUDE "art/nemesis/Collapsing platform from MCZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (16 blocks) ; Switch that you pull on from MCZ ; ArtNem_F1C64: ArtNem_VineSwitch: BINCLUDE "art/nemesis/Pull switch from MCZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (10 blocks) ; Vine that lowers in MCZ ; ArtNem_F1D5C: ArtNem_VinePulley: BINCLUDE "art/nemesis/Vine that lowers from MCZ.bin" ; -------------------------------------------------------------------- ; Nemesis compressed art (20 blocks) ; Log viewed from the end for folding gates in MCZ (start of MCZ2) ; ArtNem_F1E06: ArtNem_MCZGateLog: BINCLUDE "art/nemesis/Drawbridge logs from MCZ.bin" ; ---------------------------------------------------------------------------------- ; Filler (free space) ; ---------------------------------------------------------------------------------- ; the PCM data has to line up with the end of the bank. cnop -Size_of_SEGA_sound, $8000 ; ------------------------------------------------------------------------------- ; Sega Intro Sound ; 8-bit unsigned raw audio at 16Khz ; ------------------------------------------------------------------------------- ; loc_F1E8C: Snd_Sega: BINCLUDE "sound/PCM/SEGA.bin" Snd_Sega_End: if Snd_Sega_End - Snd_Sega > $8000 fatal "Sega sound must fit within $8000 bytes, but you have a $\{Snd_Sega_End-Snd_Sega} byte Sega sound." endif if Snd_Sega_End - Snd_Sega > Size_of_SEGA_sound fatal "Size_of_SEGA_sound = $\{Size_of_SEGA_sound}, but you have a $\{Snd_Sega_End-Snd_Sega} byte Sega sound." endif ; ------------------------------------------------------------------------------ ; Music pointers ; ------------------------------------------------------------------------------ ; loc_F8000: MusicPoint2: startBank MusPtr_CNZ_2P: rom_ptr_z80 Mus_CNZ_2P MusPtr_EHZ: rom_ptr_z80 Mus_EHZ MusPtr_MTZ: rom_ptr_z80 Mus_MTZ MusPtr_CNZ: rom_ptr_z80 Mus_CNZ MusPtr_MCZ: rom_ptr_z80 Mus_MCZ MusPtr_MCZ_2P: rom_ptr_z80 Mus_MCZ_2P MusPtr_ARZ: rom_ptr_z80 Mus_ARZ MusPtr_DEZ: rom_ptr_z80 Mus_DEZ MusPtr_SpecStage: rom_ptr_z80 Mus_SpecStage MusPtr_Options: rom_ptr_z80 Mus_Options MusPtr_Ending: rom_ptr_z80 Mus_Ending MusPtr_EndBoss: rom_ptr_z80 Mus_EndBoss MusPtr_CPZ: rom_ptr_z80 Mus_CPZ MusPtr_Boss: rom_ptr_z80 Mus_Boss MusPtr_SCZ: rom_ptr_z80 Mus_SCZ MusPtr_OOZ: rom_ptr_z80 Mus_OOZ MusPtr_WFZ: rom_ptr_z80 Mus_WFZ MusPtr_EHZ_2P: rom_ptr_z80 Mus_EHZ_2P MusPtr_2PResult: rom_ptr_z80 Mus_2PResult MusPtr_SuperSonic: rom_ptr_z80 Mus_SuperSonic MusPtr_HTZ: rom_ptr_z80 Mus_HTZ MusPtr_ExtraLife: rom_ptr_z80 Mus_ExtraLife MusPtr_Title: rom_ptr_z80 Mus_Title MusPtr_EndLevel: rom_ptr_z80 Mus_EndLevel MusPtr_GameOver: rom_ptr_z80 Mus_GameOver MusPtr_Invincible: rom_ptr_z80 Mus_Invincible MusPtr_Emerald: rom_ptr_z80 Mus_Emerald MusPtr_HPZ: rom_ptr_z80 Mus_HPZ MusPtr_Drowning: rom_ptr_z80 Mus_Drowning MusPtr_Credits: rom_ptr_z80 Mus_Credits ; loc_F803C: Mus_HPZ: BINCLUDE "sound/music/HPZ.bin" Mus_Drowning: BINCLUDE "sound/music/Drowning.bin" Mus_Invincible: BINCLUDE "sound/music/Invincible.bin" Mus_CNZ_2P: BINCLUDE "sound/music/CNZ_2p.bin" Mus_EHZ: BINCLUDE "sound/music/EHZ.bin" Mus_MTZ: BINCLUDE "sound/music/MTZ.bin" Mus_CNZ: BINCLUDE "sound/music/CNZ.bin" Mus_MCZ: BINCLUDE "sound/music/MCZ.bin" Mus_MCZ_2P: BINCLUDE "sound/music/MCZ_2p.bin" Mus_ARZ: BINCLUDE "sound/music/ARZ.bin" Mus_DEZ: BINCLUDE "sound/music/DEZ.bin" Mus_SpecStage: BINCLUDE "sound/music/SpecStg.bin" Mus_Options: BINCLUDE "sound/music/Options.bin" Mus_Ending: BINCLUDE "sound/music/Ending.bin" Mus_EndBoss: BINCLUDE "sound/music/End_Boss.bin" Mus_CPZ: BINCLUDE "sound/music/CPZ.bin" Mus_Boss: BINCLUDE "sound/music/Boss.bin" Mus_SCZ: BINCLUDE "sound/music/SCZ.bin" Mus_OOZ: BINCLUDE "sound/music/OOZ.bin" Mus_WFZ: BINCLUDE "sound/music/WFZ.bin" Mus_EHZ_2P: BINCLUDE "sound/music/EHZ_2p.bin" Mus_2PResult: BINCLUDE "sound/music/2player results screen.bin" Mus_SuperSonic: BINCLUDE "sound/music/Supersonic.bin" Mus_HTZ: BINCLUDE "sound/music/HTZ.bin" Mus_Title: BINCLUDE "sound/music/Title screen.bin" Mus_EndLevel: BINCLUDE "sound/music/End of level.bin" ; The following act mostly like sound effects ; despite being listed with the music. ; This means they're uncompressed format with absolute pointers ; instead of compressed with relative pointers. ; Because they have absolute pointers, ; they have to be assembled rather than BINCLUDE'd. ; See below (right before Sound20) for other notes ; about the sound format that apply to these too. ;Mus_ExtraLife: BINCLUDE "sound/music/Extra life.bin" Mus_ExtraLife: dc.w z80_ptr(Mus_EL_Voices),$0603,$02CD dc.w z80_ptr(Mus_EL_DAC),$0000 dc.w z80_ptr(Mus_EL_FM1),$E810 dc.w z80_ptr(Mus_EL_FM2),$E810 dc.w z80_ptr(Mus_EL_FM3),$E810 dc.w z80_ptr(Mus_EL_FM4),$E810 dc.w z80_ptr(Mus_EL_FM5),$E810 dc.w z80_ptr(Mus_EL_PSG1),$D008,$0005 dc.w z80_ptr(Mus_EL_PSG2),$DC08,$0005 dc.w z80_ptr(Mus_EL_PSG3),$DC00,$0004 Mus_EL_FM4: dc.b $E1,$03,$E0,$40,$F6 dc.w z80_ptr(+) Mus_EL_FM1: dc.b $E0,$80 + dc.b $EF,$00,$E8,$06,$D9,$06,$03,$03,$06,$06 dc.b $E8,$00,$DB,$09,$D7,$D6,$06,$D9,$18,$F2 Mus_EL_FM2: dc.b $EF,$01,$E8,$06,$E2,$01,$D6,$06,$03,$03,$06,$06 dc.b $E8,$00,$D7,$09,$D4,$D2,$06,$D6,$18,$E2,$01,$F2 Mus_EL_FM5: dc.b $E1,$03,$E0,$40,$F6 dc.w z80_ptr(+) Mus_EL_FM3: dc.b $E0,$80 + dc.b $EF,$02,$BA,$0C,$80,$06,$BA,$B8,$80,$03 dc.b $B8,$06,$80,$03,$B8,$06,$BA,$18,$F2 Mus_EL_PSG1: dc.b $E8,$06,$D6,$06,$03,$03,$06,$06,$E8,$00,$D7,$09 dc.b $D4,$D2,$06,$D6,$18 Mus_EL_PSG2: Mus_EL_PSG3: dc.b $F2 Mus_EL_DAC: dc.b $88,$12,$06,$8B,$09,$09,$06,$88,$06,$8A,$88,$8A dc.b $88,$0C,$E4 Mus_EL_Voices: dc.b $3A,$01,$01,$07,$01,$8E,$8D,$8E,$53,$0E,$0E,$0E dc.b $03,$00,$00,$00,$00,$1F,$1F,$FF,$0F,$18,$16,$4E,$80 dc.b $3A,$01,$01,$07,$01,$8E,$8D,$8E,$53,$0E,$0E,$0E dc.b $03,$00,$00,$00,$00,$1F,$1F,$FF,$0F,$18,$27,$28,$80 dc.b $3A,$01,$01,$07,$01,$8E,$8D,$8E,$53,$0E,$0E,$0E dc.b $03,$00,$00,$00,$07,$1F,$1F,$FF,$0F,$18,$27,$28,$80 ;Mus_GameOver: BINCLUDE "sound/music/Game over.bin" Mus_GameOver: dc.w z80_ptr(MusGO_Voices),$0603,$02F2 dc.w z80_ptr(MusGOver_DAC),$0000 dc.w z80_ptr(MusGOver_FM1),$E80A dc.w z80_ptr(MusGOver_FM2),$F40F dc.w z80_ptr(MusGOver_FM3),$F40F dc.w z80_ptr(MusGOver_FM4),$F40D dc.w z80_ptr(MusGOver_FM5),$DC16 dc.w z80_ptr(MusGOver_PSG),$D003,$0005 dc.w z80_ptr(MusGOver_PSG),$DC06,$0005 dc.w z80_ptr(MusGOver_PSG),$DC00,$0004 MusGOver_FM1: dc.b $EF,$00 dc.b $F0,$20,$01,$04,$05 dc.b $80,$0C,$CA,$12,$80,$06,$CA,$80,$CB,$12,$C8,$1E dc.b $CA,$06,$80,$CA,$80,$CA,$80,$C6,$80,$C4,$12,$C8 dc.b $0C,$80,$12,$C9,$04,$80,$C9,$C8,$06,$80,$C7,$80 dc.b $C6,$80 dc.b $F0,$28,$01,$18,$05 dc.b $C5,$60,$F2 MusGOver_FM2: dc.b $EF,$01,$80,$01,$D9,$06,$80,$D9,$80,$D6,$80,$D6 dc.b $80,$D7,$15,$D7,$1B,$D9,$06,$80,$D9,$80,$D6,$80 dc.b $D6,$80,$DC,$15,$DC,$1B,$F2 MusGOver_FM3: dc.b $EF,$01,$D6,$0C,$D6,$D2,$D2,$D4,$15,$D4,$1B,$D6 dc.b $0C,$D6,$D2,$D2,$D7,$15,$D7,$1B,$F2 MusGOver_FM4: dc.b $EF,$02,$E2,$01,$AE,$06,$80,$AE,$80,$A9,$80,$A9 dc.b $80,$AC,$15,$AB,$0C,$AC,$03,$AB,$0C,$AE,$06,$80 dc.b $AE,$80,$A9,$80,$A9,$80,$B3,$15,$B2,$0C,$B3,$03 dc.b $B2,$0C,$AE,$04,$80,$AE,$AD,$06,$80,$AC,$80,$AB dc.b $80,$AB,$60,$E2,$01,$F2 MusGOver_FM5: dc.b $EF,$03,$80,$30,$D7,$12,$80,$03,$D7,$1B,$80,$30 dc.b $DC,$12,$80,$03,$DC,$1B MusGOver_PSG: dc.b $F2 MusGOver_DAC: dc.b $80,$18,$81 dc.b $F7,$00,$04 dc.w z80_ptr(MusGOver_DAC) dc.b $F2 MusGO_Voices: dc.b $3A,$51,$51,$08,$02,$1E,$1E,$1E,$10,$1F,$1F,$1F dc.b $0F,$00,$00,$00,$02,$0F,$0F,$0F,$1F,$18,$22,$24,$81 dc.b $3C,$33,$73,$30,$70,$94,$96,$9F,$9F,$12,$14,$00 dc.b $0F,$04,$04,$0A,$0D,$2F,$4F,$0F,$2F,$33,$1A,$80,$80 dc.b $3A,$01,$01,$07,$01,$8E,$8D,$8E,$53,$0E,$0E,$0E dc.b $03,$00,$00,$00,$07,$1F,$1F,$FF,$0F,$1C,$27,$28,$80 dc.b $1F,$66,$53,$31,$22,$1C,$1F,$98,$1F,$12,$0F,$0F dc.b $0F,$00,$00,$00,$00,$FF,$0F,$0F,$0F,$8C,$8A,$8D,$8B ;Mus_Emerald: BINCLUDE "sound/music/Got an emerald.bin" Mus_Emerald: dc.w z80_ptr(MusEmrldVoices),$0703,$01D5 dc.w z80_ptr(MusEmeraldDAC),$0000 dc.w z80_ptr(MusEmeraldFM1),$F408 dc.w z80_ptr(MusEmeraldFM2),$F408 dc.w z80_ptr(MusEmeraldFM3),$F407 dc.w z80_ptr(MusEmeraldFM4),$F416 dc.w z80_ptr(MusEmeraldFM5),$F416 dc.w z80_ptr(MusEmeraldFM6),$F416 dc.w z80_ptr(MusEmeraldPSG1),$F402,$0004 dc.w z80_ptr(MusEmeraldPSG2),$F402,$0005 dc.w z80_ptr(MusEmeraldPSG3),$F400,$0004 MusEmeraldFM3: dc.b $E1,$02 MusEmeraldFM1: dc.b $EF,$00,$C1,$06,$C4,$C9,$CD,$0C,$C9,$D0,$2A,$F2 MusEmeraldFM2: dc.b $EF,$00,$BD,$06,$C1,$C4,$C9,$0C,$C6,$CB,$2A,$F2 MusEmeraldFM4: dc.b $EF,$01,$C1,$0C,$C1,$06,$C4,$06,$80,$C4,$80,$C9 dc.b $2A,$F2 MusEmeraldFM5: dc.b $EF,$01,$C9,$0C,$C9,$06,$CD,$06,$80,$CD,$80,$D0 dc.b $2A,$F2 MusEmeraldFM6: dc.b $EF,$01,$C4,$0C,$C4,$06,$C9,$06,$80,$C9,$80,$CD dc.b $2A,$F2 MusEmeraldPSG2: dc.b $80,$2D - dc.b $C4,$06,$C2,$C1,$BF,$EC,$03 dc.b $F7,$00,$04 dc.w z80_ptr(-) dc.b $F2 MusEmeraldPSG1: dc.b $E2,$01,$80,$02,$80,$2D - dc.b $C4,$06,$C2,$C1,$BF,$EC,$03 dc.b $F7,$00,$04 dc.w z80_ptr(-) MusEmeraldPSG3: MusEmeraldDAC: dc.b $E2,$01,$F2 MusEmrldVoices: dc.b $04,$35,$54,$72,$46,$1F,$1F,$1F,$1F,$07,$07,$0A dc.b $0D,$00,$00,$0B,$0B,$1F,$1F,$0F,$0F,$23,$1D,$14,$80 dc.b $3C,$31,$50,$52,$30,$52,$52,$53,$53,$08,$08,$00 dc.b $00,$04,$04,$00,$00,$10,$10,$07,$07,$1A,$16,$80,$80 ;Mus_Credits: BINCLUDE "sound/music/Credits.bin" Mus_Credits: dc.w z80_ptr(MusCred_Voices),$0603,$01F0 dc.w z80_ptr(MusCred_DAC),$0000 dc.w z80_ptr(MusCred_FM1),$000E dc.w z80_ptr(MusCred_FM2),$180A dc.w z80_ptr(MusCred_FM3),$0014 dc.w z80_ptr(MusCred_FM4),$0016 dc.w z80_ptr(MusCred_FM5),$0C16 dc.w z80_ptr(MusCred_PSG1),$E806,$000B dc.w z80_ptr(MusCred_PSG2),$DC07,$000B dc.w z80_ptr(MusCred_PSG3),$0002,$0003 MusCred_FM1: dc.b $E9,$F4,$E6,$FE,$F8 dc.w z80_ptr(MusCreditsDB06) dc.b $E9,$0C,$E6,$02 - dc.b $80,$30 dc.b $F7,$00,$08 dc.w z80_ptr(-) dc.b $EF,$03,$F8 dc.w z80_ptr(MusCreditsD9D1) dc.b $AE,$06,$A2,$F8 dc.w z80_ptr(MusCreditsD9D1) dc.b $E6,$FD - dc.b $EF,$00,$B7,$06,$BA,$F8 dc.w z80_ptr(MusCreditsDA13) dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $80,$06,$80,$80,$30,$80,$EF,$0B,$E9,$18,$E6,$02 - dc.b $94,$0C,$8F,$92,$8F,$06,$94,$05,$94,$07,$06,$8F dc.b $0C,$92,$8F dc.b $F7,$00,$05 dc.w z80_ptr(-) dc.b $80,$30,$80,$EF,$0E,$E6,$FF,$E9,$E8,$F8 dc.w z80_ptr(MusCreditsDAE5) dc.b $80,$12,$91,$94,$06,$80,$18,$96,$12,$9A,$06,$80 dc.b $80,$12,$8F,$93,$08,$80,$16,$96,$06,$91,$92,$94 dc.b $96,$F8 dc.w z80_ptr(MusCreditsDAE5) dc.b $80,$12,$9D,$9A,$08,$80,$16,$96,$12,$9D,$08,$80 dc.b $04,$EF,$12 dc.b $F0,$18,$01,$0A,$04 dc.b $80,$30,$80,$F8 dc.w z80_ptr(MusCreditsDA5F) dc.b $E7,$24,$E7,$C5,$01,$E7,$C4,$E7,$C3,$E7,$C2,$E7 dc.b $C1,$E7,$C0,$E7,$BF,$E7,$BE,$E7,$BD,$E7,$BC,$E7 dc.b $BB,$E7,$BA,$80,$60,$EF,$01,$E9,$F4,$E6,$FA,$F4 dc.b $F8 dc.w z80_ptr(MusCreditsDA99) dc.b $B1,$03,$F8 dc.w z80_ptr(MusCreditsDA99) dc.b $80,$03,$80,$60,$E6,$04,$E1,$01,$EF,$1B,$E6,$06 dc.b $C1,$0C,$E8,$06,$BD,$06,$BA,$BD,$0C,$80,$80,$EF dc.b $1C,$E6,$FA,$E8,$00,$BC,$0C,$12,$06,$EF,$1B,$E6 dc.b $06,$E8,$06,$C2,$06,$C2,$80,$C2,$80,$C2,$E8,$00 dc.b $C3,$0C,$C4,$80,$E8,$06,$C4,$06,$06,$C6,$C4,$E8 dc.b $00,$C1,$0C,$E8,$06,$BD,$06,$BA,$BD,$0C,$80,$80 dc.b $E8,$00,$EF,$1C,$E6,$FA,$C1,$C4,$C1,$EF,$1A,$E6 dc.b $06,$E8,$06,$C2,$06,$C2,$80,$C2,$80,$C2,$E8,$00 dc.b $C3,$0C,$C4,$06,$80,$80,$24,$80,$30,$80,$EF,$1F dc.b $E9,$18,$E6,$F7,$E1,$00,$80,$06,$AC,$AE,$80,$B1 dc.b $80,$B3,$80,$B4,$80,$B3,$80,$B1,$B3,$80,$B1,$E9 dc.b $F4,$EF,$00,$80,$0C,$AC,$06,$AE,$B1,$80,$12,$AC dc.b $06,$AE,$B1,$80,$B4,$B1,$80,$B1,$E9,$0C,$EF,$1F dc.b $80,$06,$B8,$12,$B4,$06,$80,$B3,$80,$B4,$80,$B3 dc.b $80,$B1,$AE,$80,$B1,$E9,$F4,$EF,$00,$80,$06,$AF dc.b $12,$AE,$06,$80,$12,$AF,$06,$80,$AE,$80,$AF,$B1 dc.b $80,$B1,$80,$30,$80,$EF,$21,$E9,$0C,$80,$30,$80 dc.b $08,$A0,$04,$9E,$0C,$9D,$9B,$99,$08,$04,$91,$0C dc.b $92,$93,$94,$98,$99,$9B,$9D,$98,$95,$93,$91,$98 dc.b $9D,$91,$96,$98,$99,$98,$96,$99,$9D,$96,$95,$97 dc.b $99,$97,$95,$96,$97,$98,$99,$98,$99,$9B,$9D,$08 dc.b $04,$98,$0C,$91,$95,$96,$98,$99,$9D,$9E,$08,$96 dc.b $10,$97,$0C,$98,$F8 dc.w z80_ptr(MusCreditsDAFE) dc.b $9E,$E6,$04,$F8 dc.w z80_ptr(MusCreditsDAFE) dc.b $9E,$E6,$FC,$F8 dc.w z80_ptr(MusCreditsDAFE) dc.b $9E,$08,$99,$04,$EF,$23,$E9,$E8,$E6,$07,$80,$60 dc.b $F8 dc.w z80_ptr(MusCreditsDABE) dc.b $80,$60,$E6,$FB,$80,$0C,$CD,$06,$80,$D4,$CD,$06 dc.b $80,$0C,$CD,$06,$80,$D4,$CD,$06,$80,$18,$E6,$05 dc.b $80,$0C,$AE,$80,$AE,$80,$24,$E1,$02,$E6,$08,$A2 dc.b $6C,$F2 MusCreditsD9D1: dc.b $A5,$0C,$B1,$06,$80,$B1,$0C,$AC,$B3,$12,$B1,$0C dc.b $AC,$06,$AE,$B1,$A7,$0C,$B3,$06,$80,$B3,$0C,$AE dc.b $B5,$12,$B3,$06,$80,$AE,$B0,$B3,$A3,$0C,$AF,$06 dc.b $80,$AF,$0C,$AA,$B1,$12,$AF,$0C,$AA,$06,$AC,$AF dc.b $A2,$0C,$AE,$06,$A2,$A4,$0C,$B0,$06,$A4,$A5,$0C dc.b $B1,$06,$A5,$A2,$0C,$E3 MusCreditsDA13: dc.b $BE,$0C,$BC,$06,$BA,$BC,$BA,$04,$E7,$08,$BA,$04 dc.b $80,$0E,$EF,$07,$B7,$06,$B2,$B5,$B7,$EF,$00,$B7 dc.b $BA,$BE,$0C,$BC,$06,$BA,$BC,$BA,$0C,$BC,$04,$80 dc.b $08,$BA,$04,$80,$08,$BC,$04,$80,$08,$BE,$12,$BA dc.b $06,$B7,$80,$B7,$80,$24,$EF,$07,$B7,$06,$B2,$B5 dc.b $B7,$80,$0C,$80,$30,$BE,$06,$BE,$BA,$04,$80,$08 dc.b $BC,$06,$BE,$E3 MusCreditsDA5F: dc.b $C3,$01,$E7,$C4,$E7,$C5,$E7,$C6,$2D,$E9,$02,$C3 dc.b $01,$E7,$C4,$E7,$C5,$E7,$C6,$2D,$E9,$01,$C3,$01 dc.b $E7,$C4,$E7,$C5,$E7,$C6,$2D,$E9,$FC,$C3,$01,$E7 dc.b $C4,$E7,$C5,$E7,$C6,$2D,$E9,$01,$C3,$01,$E7,$C4 dc.b $E7,$C5,$E7,$C6,$2D,$E7,$30,$E7,$30,$E3 MusCreditsDA99: dc.b $A7,$0C,$B3,$06,$80,$B1,$80,$B3,$0C,$A7,$03,$80 dc.b $06,$A7,$03,$B3,$0C,$B1,$B3,$09,$AE,$03,$AC,$06 dc.b $80,$AC,$0C,$AE,$06,$80,$AE,$0C,$AF,$06,$80,$27 dc.b $E3 MusCreditsDABE: dc.b $80,$0C,$CA,$15,$80,$03,$CA,$06,$80,$CB,$0F,$80 dc.b $03,$C8,$18,$80,$06,$CA,$80,$CA,$80,$CA,$80,$C6 dc.b $80,$C4,$0F,$80,$03,$C8,$18,$80,$06 dc.b $F7,$00,$02 dc.w z80_ptr(MusCreditsDABE) dc.b $E3 MusCreditsDAE5: dc.b $80,$12,$94,$97,$06,$80,$18,$99,$12,$94,$06,$80 dc.b $80,$12,$92,$96,$06,$80,$18,$97,$12,$92,$06,$80 dc.b $E3 MusCreditsDAFE: dc.b $80,$99,$80,$99,$80,$9E,$80,$E3 MusCreditsDB06: dc.b $EF,$07,$80,$54,$C7,$04,$C8,$C9,$CA,$24,$CD,$D2 dc.b $18,$D0,$24,$CF,$CB,$18,$CB,$0C,$CA,$80,$CD,$60 dc.b $E7,$3C,$CA,$24,$CD,$D2,$18,$D4,$24,$D0,$D4,$18 dc.b $D4,$24,$D6,$60,$E7,$3C,$E3 MusCred_FM2: dc.b $80,$60,$EF,$01,$E8,$06,$F8 dc.w z80_ptr(MusCreditsDE2A) dc.b $F8 dc.w z80_ptr(MusCreditsDE2A) - dc.b $85,$0C dc.b $F7,$00,$0C dc.w z80_ptr(-) dc.b $8A,$87,$88,$89,$F8 dc.w z80_ptr(MusCreditsDE2A) - dc.b $88 dc.b $F7,$00,$0B dc.w z80_ptr(-) - dc.b $8A dc.b $F7,$00,$0A dc.w z80_ptr(-) dc.b $E8,$00,$E6,$FC,$8A,$8B,$8C,$E6,$04,$E8,$09 - dc.b $8D,$0C dc.b $F7,$00,$0C dc.w z80_ptr(-) dc.b $E8,$00,$8D,$8A,$8B,$8C,$E8,$09 - dc.b $8D,$0C dc.b $F7,$00,$0C dc.w z80_ptr(-) dc.b $8D,$06,$99,$E8,$00,$8A,$0C,$8B,$8C,$E9,$E8,$E6 dc.b $0C,$EF,$04 - dc.b $F8 dc.w z80_ptr(MusCreditsDD59) dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $E6,$F9,$EF,$08 MusCreditsDB93: dc.b $F8 dc.w z80_ptr(MusCreditsDD8D) - dc.b $9F,$04,$80,$08,$9F,$0C dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $06,$9C,$12,$9D,$0C,$9E,$F8 dc.w z80_ptr(MusCreditsDD8D) - dc.b $9D,$04,$80,$08,$9D,$0C dc.b $F7,$00,$02 dc.w z80_ptr(-) - dc.b $9C,$04,$80,$08,$9C,$0C dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $F7,$01,$02 dc.w z80_ptr(MusCreditsDB93) dc.b $80,$60,$80,$48,$EF,$0C,$E6,$13,$F8 dc.w z80_ptr(MusCreditsDD9D) dc.b $24,$80,$60,$EF,$0F,$E6,$F3 dc.b $F0,$04,$02,$03,$02 dc.b $F8 dc.w z80_ptr(MusCreditsDDB5) dc.b $C4,$18,$C3,$30,$E7,$18,$80,$0C,$F8 dc.w z80_ptr(MusCreditsDDB5) dc.b $BE,$EF,$13,$E6,$F5,$F4,$80,$60 - dc.b $F8 dc.w z80_ptr(MusCreditsDDEA) dc.b $A8,$0C,$A9,$08,$A1,$10,$F8 dc.w z80_ptr(MusCreditsDDEA) dc.b $A8,$08,$A9,$04,$80,$18 dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $80,$60,$EF,$17,$E1,$02,$E9,$F4,$E6,$0A,$F8 dc.w z80_ptr(MusCreditsDDD5) dc.b $CE,$15,$CD,$03,$CB,$06,$80,$C9,$0C,$CD,$06,$80 dc.b $C9,$0C,$CB,$06,$80,$12,$80,$60,$EF,$1B,$E1,$00 dc.b $E8,$06,$80,$3C,$B8,$06,$06,$BA,$BD,$BD,$BA,$EF dc.b $1D,$E6,$FA,$E8,$00,$F8 dc.w z80_ptr(MusCreditsDDF9) dc.b $80,$F8 dc.w z80_ptr(MusCreditsDE09) dc.b $F8 dc.w z80_ptr(MusCreditsDDF9) dc.b $EF,$1C,$BD,$EF,$1D,$F8 dc.w z80_ptr(MusCreditsDE09) dc.b $80,$30,$80,$EF,$01,$E9,$18,$E6,$F9 - dc.b $99,$0C,$A5,$06,$80,$96,$0C,$A2,$06,$80,$97,$0C dc.b $A3,$06,$80,$98,$0C,$A8,$06,$A7,$99,$06,$99,$12 dc.b $96,$0C,$A2,$06,$80,$97,$0C,$A3,$06,$80,$98,$0C dc.b $A4,$06,$80 dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $80,$60,$EF,$22,$E9,$E8,$E6,$03 dc.b $F0,$1C,$01,$06,$04 dc.b $80,$50,$AC,$04,$AE,$08,$B1,$04,$B5,$30,$80,$0C dc.b $B5,$08,$80,$04,$B6,$08,$B5,$10,$B9,$08,$04,$80 dc.b $08,$B5,$34,$80,$0C,$B5,$BA,$08,$04,$80,$08,$B5 dc.b $04,$B1,$24,$80,$0C,$B1,$08,$80,$04,$B3,$08,$B1 dc.b $04,$B4,$0C,$B3,$08,$B1,$4C,$80,$0C,$B5,$08,$80 dc.b $04,$B6,$08,$80,$04,$B5,$08,$80,$04,$B9,$08,$04 dc.b $80,$08,$B5,$1C,$80,$0C,$BA,$18,$BC,$08,$BA,$04 dc.b $BD,$18,$80,$0C,$BA,$04,$80,$08,$B8,$18,$B5,$B1 dc.b $B3,$0C,$E6,$04,$F8 dc.w z80_ptr(MusCreditsDE17) dc.b $B3,$0C,$E6,$FC,$F8 dc.w z80_ptr(MusCreditsDE17) dc.b $B3,$14,$B1,$04,$E6,$FF,$EF,$24,$F4,$80,$60 - dc.b $F8 dc.w z80_ptr(MusCreditsDE20) dc.b $AC,$12,$AB,$0C,$AC,$06,$AB,$0C,$F8 dc.w z80_ptr(MusCreditsDE20) dc.b $B3,$12,$B2,$0C,$B3,$06,$B2,$0C dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $AC,$06,$80,$A9,$80,$AA,$80,$AB,$80,$AC,$AC,$A9 dc.b $80,$AA,$80,$AC,$80,$A9,$80,$A9,$80,$AD,$80,$AD dc.b $80,$B0,$80,$B0,$80,$B3,$80,$B3,$80,$80,$0C,$A2 dc.b $12,$80,$06,$A2,$12,$AD,$AE,$06,$80,$E6,$FD,$A2 dc.b $6C,$F2 MusCreditsDD59: dc.b $80,$0C,$C4,$06,$80,$C6,$80,$C4,$80,$C9,$80,$C9 dc.b $80,$CB,$CD,$80,$0C,$80,$CB,$18,$C6,$06,$80,$C9 dc.b $C9,$80,$CB,$0C,$80,$12,$80,$1E,$C7,$06,$C9,$C7 dc.b $CB,$80,$C9,$80,$C7,$C9,$80,$C6,$E7,$C6,$30,$E7 dc.b $18,$80,$18,$E3 MusCreditsDD8D: dc.b $9F,$04,$80,$08,$9F,$0C dc.b $F7,$00,$03 dc.w z80_ptr(MusCreditsDD8D) dc.b $06,$AB,$9F,$0C,$E3 MusCreditsDD9D: dc.b $B8,$08,$BA,$BC,$B6,$30,$E7,$30,$E7,$B6,$80,$18 dc.b $B8,$08,$BA,$BC,$B6,$30,$E7,$30,$E7,$30,$E7,$E3 MusCreditsDDB5: dc.b $BF,$06,$BD,$BF,$12,$C2,$BF,$0C,$C1,$80,$06,$12 dc.b $C4,$0C,$C2,$06,$80,$C9,$C6,$3C,$80,$06,$0C,$C7 dc.b $12,$C6,$C4,$06,$C2,$C1,$18,$E3 MusCreditsDDD5: dc.b $CE,$15,$CD,$03,$CB,$06,$80,$C9,$0C,$CD,$06,$80 dc.b $C9,$0C,$CB,$06,$80,$12,$80,$60,$E3 MusCreditsDDEA: dc.b $A2,$0C,$AE,$AC,$08,$AE,$04,$AC,$08,$A9,$04,$A7 dc.b $08,$04,$E3 MusCreditsDDF9: dc.b $80,$0C,$B1,$AE,$06,$06,$AC,$0C,$80,$B0,$AE,$06 dc.b $06,$AC,$0C,$E3 MusCreditsDE09: dc.b $AE,$AC,$06,$06,$AA,$0C,$80,$AC,$0C,$06,$06,$AE dc.b $AC,$E3 MusCreditsDE17: dc.b $BA,$04,$80,$08,$B8,$18,$B5,$B1,$E3 MusCreditsDE20: dc.b $AE,$06,$80,$AE,$80,$A9,$80,$A9,$80,$E3 MusCreditsDE2A: dc.b $8A,$0C dc.b $F7,$00,$08 dc.w z80_ptr(MusCreditsDE2A) dc.b $E3 MusCred_FM3: dc.b $80,$60,$F8 dc.w z80_ptr(MusCreditsE065) dc.b $E9,$18,$EF,$02,$F8 dc.w z80_ptr(MusCreditsE040) dc.b $B8,$3C,$F8 dc.w z80_ptr(MusCreditsE040) dc.b $BD,$3C,$E9,$E8,$E6,$02,$E1,$03,$EF,$04,$E0,$80 - dc.b $F8 dc.w z80_ptr(MusCreditsDD59) dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $EF,$09,$E9,$0C,$E6,$FD,$E0,$40 dc.b $F0,$06,$01,$05,$04 dc.b $E1,$00 - dc.b $9F,$0C,$AB,$06,$80,$A9,$80,$AB,$9F,$80,$9F,$AB dc.b $80,$A9,$80,$AB,$0C dc.b $F7,$00,$03 dc.w z80_ptr(-) dc.b $9D,$0C,$A9,$06,$80,$A8,$80,$A9,$9C,$80,$9C,$A8 dc.b $80,$A6,$80,$A8,$0C dc.b $F7,$01,$02 dc.w z80_ptr(-) dc.b $80,$60,$EF,$0D,$E6,$FB,$E0,$C0,$F4,$80,$60 - dc.b $F8 dc.w z80_ptr(MusCreditsDFF2) dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $80,$60,$EF,$0F,$E0,$80,$E6,$0B,$F8 dc.w z80_ptr(MusCreditsDDB5) dc.b $C4,$18,$C3,$48,$80,$0C,$F8 dc.w z80_ptr(MusCreditsDDB5) dc.b $BE,$0C dc.b $F0,$18,$01,$03,$04 dc.b $E6,$F3,$E0,$C0,$EF,$14,$A2,$14,$A4,$04,$A5,$04 dc.b $80,$08,$A9,$04,$80,$08,$A8,$04,$80,$08,$A9,$04 dc.b $80,$08,$AC,$08,$A9,$10 - dc.b $80,$30 dc.b $F7,$00,$0A dc.w z80_ptr(-) dc.b $EF,$18,$E9,$F4,$E6,$08,$F4,$E0,$40,$80,$60,$80 dc.b $30,$C6,$06,$80,$C2,$0C,$C4,$09,$C2,$03,$BF,$0C dc.b $80,$60,$80,$3C,$80,$60,$EF,$1B,$E6,$FB,$E0,$C0 dc.b $E8,$06,$C4,$06,$06,$C6,$C9,$C9,$C6,$E8,$00,$CD dc.b $0C,$E8,$06,$C9,$06,$C6,$C9,$0C,$80,$80,$12,$EF dc.b $1C,$E8,$00,$BD,$BA,$0C,$E8,$06,$EF,$1B,$CE,$06 dc.b $CE,$80,$CE,$80,$CE,$E8,$00,$CF,$0C,$D0,$80,$E8 dc.b $06,$D0,$06,$06,$D2,$D0,$E8,$00,$CD,$0C,$E8,$06 dc.b $C9,$06,$C6,$C9,$0C,$E8,$00,$EF,$1C,$80,$1E,$C2 dc.b $0C,$C2,$BD,$06,$80,$60,$80,$60,$EF,$00,$E9,$18 dc.b $80,$60,$80,$0C,$AC,$06,$AE,$B1,$80,$12,$AC,$06 dc.b $AE,$B1,$80,$B4,$B1,$80,$B1,$80,$60,$80,$06,$AF dc.b $12,$AE,$06,$80,$12,$AF,$06,$80,$AE,$80,$AF,$B1 dc.b $80,$B1,$80,$60,$EF,$22,$E9,$DC,$E6,$FF,$E0,$80 dc.b $80,$60,$F8 dc.w z80_ptr(MusCreditsE004) dc.b $CD,$30,$CB,$18,$CD,$0C,$CB,$C9,$30,$CE,$F8 dc.w z80_ptr(MusCreditsE051) dc.b $E6,$04,$F8 dc.w z80_ptr(MusCreditsE051) dc.b $E6,$FC,$80,$C4,$80,$C4,$80,$C6,$18,$08,$C4,$04 dc.b $E9,$0C,$E6,$FF,$E0,$C0,$EF,$00,$80,$60 - dc.b $F8 dc.w z80_ptr(MusCreditsE05B) dc.b $CB,$12,$CB,$1E,$F8 dc.w z80_ptr(MusCreditsE05B) dc.b $D0,$12,$D0,$1E dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $80,$0C,$CB,$12,$80,$06,$CB,$80,$CA,$12,$CB,$CA dc.b $0C,$C5,$18,$C8,$CB,$D1,$80,$0C,$CD,$80,$CD,$12 dc.b $CC,$CD,$06,$80,$E6,$F8,$EF,$01,$E1,$03,$A2,$6C dc.b $F2 MusCreditsDFF2: dc.b $80,$60,$BC,$06,$BD,$BC,$B8,$BA,$B6,$0C,$B8,$B3 dc.b $B3,$06,$B6,$0C,$B8,$E3 MusCreditsE004: dc.b $80,$0C,$CD,$04,$80,$10,$CD,$04,$80,$0C,$CD,$0C dc.b $CE,$08,$CD,$04,$80,$18,$80,$0C,$CB,$04,$80,$10 dc.b $CB,$04,$80,$0C,$CB,$0C,$CD,$08,$CB,$04,$80,$18 - dc.b $80,$0C,$C9,$04,$80,$10,$C9,$04,$80,$0C,$C9,$0C dc.b $CB,$08,$C9,$04,$80,$18 dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $E3 MusCreditsE040: dc.b $80,$18,$B8,$0B,$80,$0D,$BA,$0C,$0B,$80,$19,$BD dc.b $0C,$0B,$80,$0D,$E3 MusCreditsE051: dc.b $80,$0C,$C4,$80,$C4,$80,$C6,$80,$C6,$E3 MusCreditsE05B: dc.b $CD,$06,$80,$CD,$80,$CA,$80,$CA,$80,$E3 MusCreditsE065: dc.b $EF,$05,$E9,$F4,$C6,$60,$CB,$CD,$E7,$CD,$C6,$60 dc.b $D0,$D0,$24,$D2,$60,$E7,$3C,$E3 MusCred_FM4: dc.b $80,$60,$E9,$FB,$E6,$FE,$F8 dc.w z80_ptr(MusCreditsE065) dc.b $E9,$1D,$E6,$02,$EF,$02,$F8 dc.w z80_ptr(MusCreditsE2AE) dc.b $B5,$3C,$F8 dc.w z80_ptr(MusCreditsE2AE) dc.b $B8,$3C,$E6,$06,$EF,$05 dc.b $F0,$02,$01,$FE,$04 - dc.b $C1,$30,$E7,$30,$C3,$E7,$30,$BF,$E7,$30,$BD,$E7 dc.b $30 dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $EF,$0A,$E9,$F4,$E6,$F7 dc.b $F0,$0C,$01,$FB,$04 - dc.b $F8 dc.w z80_ptr(MusCreditsE2BF) dc.b $80,$25,$C3,$06,$C3,$80,$0C,$C3,$06,$C3,$05,$80 dc.b $0D,$C3,$06,$C5,$30,$E7,$06,$F8 dc.w z80_ptr(MusCreditsE2BF) dc.b $80,$31,$80,$60 dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $80,$60,$80,$48,$EF,$0C,$E6,$05,$F4,$E1,$02,$E0 dc.b $80,$F8 dc.w z80_ptr(MusCreditsDD9D) dc.b $24,$80,$0C,$80,$60,$EF,$10,$E6,$F7,$E1,$00,$E0 dc.b $40,$F8 dc.w z80_ptr(MusCreditsE2D2) dc.b $B3,$B7,$06,$AE,$0C,$B1,$B3,$B7,$06,$80,$B7,$AE dc.b $0C,$B1,$F8 dc.w z80_ptr(MusCreditsE2D2) dc.b $EF,$15,$E6,$01,$F8 dc.w z80_ptr(MusCreditsE22D) - dc.b $EF,$14,$80,$4E,$E0,$40,$A1,$12,$A2,$06,$E0,$C0 dc.b $EF,$16,$80,$30,$80,$06,$BA,$08,$B9,$04,$B8,$08 dc.b $B7,$04,$B6,$08,$B5,$04 dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $80,$60,$EF,$17,$E9,$F4,$E6,$02,$E0,$C0 dc.b $F0,$01,$01,$03,$03 - dc.b $F8 dc.w z80_ptr(MusCreditsDDD5) dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $80,$60,$EF,$1E,$E0,$40,$E6,$FE,$E9,$F4,$F4,$E8 dc.b $06,$80,$0C,$C1,$06,$12,$18,$C4,$06,$12,$0C,$EF dc.b $1C,$E0,$C0,$E6,$FA,$E8,$00,$C6,$E8,$06,$E6,$06 dc.b $EF,$1E,$E0,$40,$C2,$06,$12,$18,$C4,$06,$12,$18 dc.b $C1,$06,$12,$18,$C4,$06,$12,$0C,$EF,$1A,$E0,$C0 dc.b $E9,$0C,$C6,$06,$C6,$80,$C6,$80,$C6,$E8,$00,$C7 dc.b $0C,$C8,$06,$EF,$1E,$E0,$40,$E9,$F4,$E8,$06,$80 dc.b $C4,$06,$12,$0C,$80,$60,$EF,$20,$E9,$18,$E6,$FA dc.b $E0,$C0,$E8,$00,$B4,$03,$E7,$B6,$5D,$B3,$03,$E7 dc.b $B5,$5D,$B1,$03,$E7,$B3,$5D,$B3,$03,$E7,$B5,$5D dc.b $80,$60,$EF,$22,$E0,$40,$E9,$E8,$E6,$04,$80,$30 dc.b $80,$F8 dc.w z80_ptr(MusCreditsE246) dc.b $C9,$30,$C8,$18,$C9,$0C,$C8,$C6,$30,$C9,$80,$0C dc.b $C1,$80,$C1,$80,$C2,$80,$C2,$E6,$04,$80,$C1,$80 dc.b $C1,$80,$C2,$80,$C2,$E6,$FC,$80,$C1,$80,$C1,$80 dc.b $C2,$18,$08,$C1,$04,$E9,$0C,$E6,$FF,$E0,$C0,$EF dc.b $00,$80,$60 - dc.b $F8 dc.w z80_ptr(MusCreditsE2C8) dc.b $C8,$12,$C8,$1E,$F8 dc.w z80_ptr(MusCreditsE2C8) dc.b $CB,$12,$CB,$1E dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $E1,$03,$E6,$08,$F8 dc.w z80_ptr(MusCreditsE28F) dc.b $E6,$F0,$EF,$01 dc.b $F0,$00,$01,$06,$04 dc.b $A2,$6C,$F2 MusCreditsE22D: dc.b $A2,$14,$A4,$04,$A5,$04,$80,$08,$A9,$04,$80,$08 dc.b $A8,$04,$80,$08,$A9,$04,$80,$08,$AC,$08,$A9,$10 dc.b $E3 MusCreditsE246: dc.b $80,$0C dc.b $C9,$04,$80,$10 dc.b $C9,$04,$80,$0C dc.b $C9,$0C dc.b $CB,$08 dc.b $C9,$04,$80,$18,$80,$0C dc.b $C8,$04,$80,$10 dc.b $C8,$04,$80,$0C dc.b $C8,$0C dc.b $C9,$08 dc.b $C8,$04,$80,$18,$80,$0C if 1==1 ; this part of the original credits music (CNZ PSG) sounds buggy (dissonant) dc.b $C6,$04,$80,$10 dc.b $C6,$04,$80,$0C dc.b $C6,$0C dc.b $C8,$08 dc.b $C6,$04,$80,$18,$80,$0C dc.b $C5,$04,$80,$10 dc.b $C5,$04,$80,$0C dc.b $C5,$0C dc.b $C7,$08 else ; replace the above block of notes with this to fix it. ; (I'm not sure why, but the notes $C6 and $C7 are broken here, ; so I've replaced them with pitch-shifted $C8s) dc.b $E1,-64 dc.b $C8,$04,$80,$10 ; $C6 dc.b $C8,$04,$80,$0C ; $C6 dc.b $C8,$0C ; $C6 dc.b $E1,0 dc.b $C8,$08 dc.b $E1,-64 dc.b $C8,$04,$80,$24 ; $C6 dc.b $E1,0 dc.b $C5,$04,$80,$10 dc.b $C5,$04,$80,$0C dc.b $C5,$0C dc.b $E1,-32 dc.b $C8,$08 ; $C7 dc.b $E1,0 endif dc.b $C5,$04,$80,$18 dc.b $E3 MusCreditsE28F: dc.b $EF,$25,$80,$0C,$D0,$D4,$D7,$DB,$0C,$80,$06,$DB dc.b $0C,$DC,$06,$DB,$0C,$DD,$60,$DE,$0C,$80,$DE,$80 dc.b $80,$06,$DD,$12,$DE,$0C,$E3 MusCreditsE2AE: dc.b $80,$18,$B5,$0B,$80,$0D,$B7,$0C,$0B,$80,$19,$BA dc.b $0C,$0B,$80,$0D,$E3 MusCreditsE2BF: dc.b $C3,$05,$80,$13,$C3,$12,$C3,$05,$E3 MusCreditsE2C8: dc.b $CA,$06,$80,$CA,$80,$C6,$80,$C6,$80,$E3 MusCreditsE2D2: dc.b $AF,$0C,$B3,$06,$B6,$0C,$AF,$B1,$06,$80,$B1,$0C dc.b $B5,$06,$B8,$0C,$B1,$06,$80,$B6,$0C,$BA,$06,$B1 dc.b $0C,$B5,$B6,$BA,$06,$80,$BA,$AF,$0C,$B3,$B5,$B8 dc.b $06,$B2,$0C,$B3,$B5,$B8,$06,$80,$B8,$B2,$0C,$B5 dc.b $E3 MusCred_FM5: dc.b $E9,$E8,$E6,$F8,$E1,$05,$F8 dc.w z80_ptr(MusCreditsDB06) dc.b $E9,$18,$E6,$08,$E1,$00,$EF,$02 dc.b $F0,$0C,$01,$FC,$04 dc.b $F8 dc.w z80_ptr(MusCreditsE4E8) dc.b $B1,$3C,$F8 dc.w z80_ptr(MusCreditsE4E8) dc.b $B5,$3C,$E9,$F4,$E6,$07 dc.b $F0,$30,$01,$04,$04 dc.b $EF,$06 - dc.b $C4,$30,$E7,$30,$C6,$E7,$30,$C2,$E7,$30,$C1,$E7 dc.b $30 dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $EF,$0A,$E6,$F6 dc.b $F0,$0C,$01,$05,$04 dc.b $E0,$80 - dc.b $F8 dc.w z80_ptr(MusCreditsE4F9) dc.b $80,$25,$C6,$06,$C6,$80,$0C,$C6,$06,$C6,$05,$80 dc.b $0D,$C6,$06,$C8,$30,$E7,$06,$F8 dc.w z80_ptr(MusCreditsE4F9) dc.b $80,$31,$80,$60 dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $80,$60,$80,$48,$E6,$05,$F4,$80,$01,$EF,$0C,$E1 dc.b $FE,$E0,$40,$F8 dc.w z80_ptr(MusCreditsDD9D) dc.b $23,$80,$0C,$80,$60,$EF,$11,$E9,$F4,$E6,$F4,$E1 dc.b $00,$E0,$C0 dc.b $F0,$06,$01,$06,$05 dc.b $80,$60,$80,$30,$C2,$06,$C2,$C9,$C6,$1E,$80,$60 dc.b $80,$06,$CB,$80,$CB,$C9,$80,$C9,$80,$C7,$80,$C7 dc.b $80,$C6,$03,$80,$C6,$80,$09,$80,$06,$80,$60,$80 dc.b $30,$C2,$06,$C2,$C9,$C6,$1E,$80,$60,$EF,$16,$E9 dc.b $0C,$E6,$04,$F4,$E0,$80,$80,$01,$F8 dc.w z80_ptr(MusCreditsE22D) dc.b $80,$2F,$F8 dc.w z80_ptr(MusCreditsE4CD) dc.b $80,$30,$F8 dc.w z80_ptr(MusCreditsE4CD) dc.b $80,$60,$EF,$19,$E9,$F4,$E0,$C0,$F8 dc.w z80_ptr(MusCreditsE502) dc.b $80,$27,$B1,$03,$F8 dc.w z80_ptr(MusCreditsE502) dc.b $80,$2A,$80,$60,$EF,$1E,$E9,$F4,$E8,$06 - dc.b $80,$0C,$C4,$06,$12,$18,$C8,$06,$12,$0C,$80,$C6 dc.b $06,$12,$18,$C8,$06,$12,$0C dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $80,$60,$EF,$20,$E8,$00,$E9,$18,$E6,$FA,$B8,$03 dc.b $E7,$BA,$5D,$B6,$03,$E7,$B8,$5D,$B4,$03,$E7,$B6 dc.b $5D,$B6,$03,$E7,$B8,$5D,$80,$60,$EF,$22,$E9,$F4 dc.b $E6,$05 dc.b $F0,$1C,$01,$06,$04 dc.b $80,$50,$A7,$04,$A9,$08,$AC,$04,$B1,$30,$80,$0C dc.b $B1,$08,$80,$04,$B3,$08,$B1,$10,$B5,$08,$B5,$04 dc.b $80,$08,$B0,$34,$80,$0C,$B0,$B5,$08,$04,$80,$08 dc.b $B1,$04,$AE,$24,$80,$0C,$AE,$08,$80,$04,$B0,$08 dc.b $AE,$04,$B1,$0C,$AF,$08,$AD,$4C,$80,$0C,$B1,$08 dc.b $80,$04,$B3,$08,$80,$04,$B1,$08,$80,$04,$B5,$08 dc.b $B5,$04,$80,$08,$B0,$1C,$80,$0C,$B5,$18,$B8,$08 dc.b $B5,$04,$BA,$18,$80,$0C,$B6,$04,$80,$08,$B5,$18 dc.b $B1,$AE,$B0,$0C,$E6,$04,$B6,$04,$80,$08,$B5,$18 dc.b $B1,$AE,$B0,$0C,$E6,$F8,$B6,$04,$80,$08,$B5,$18 dc.b $B1,$AE,$AA,$14,$A9,$04,$E6,$0C,$EF,$23,$E1,$03 dc.b $E6,$F7,$80,$60,$F8 dc.w z80_ptr(MusCreditsDABE) dc.b $E6,$09 dc.b $F0,$00,$01,$06,$04 dc.b $F8 dc.w z80_ptr(MusCreditsE28F) dc.b $F2 MusCreditsE4CD: dc.b $80,$1E,$EF,$14,$A4,$12,$A5,$06,$EF,$16,$80,$30 dc.b $80,$06,$BD,$08,$BC,$04,$BB,$08,$BA,$04,$B9,$08 dc.b $B8,$04,$E3 MusCreditsE4E8: dc.b $80,$18,$B1,$0B,$80,$0D,$B3,$0C,$0B,$80,$19,$B6 dc.b $0C,$0B,$80,$0D,$E3 MusCreditsE4F9: dc.b $C6,$05,$80,$13,$C6,$12,$C6,$05,$E3 MusCreditsE502: dc.b $80,$60,$AC,$06,$80,$AC,$0C,$AE,$06,$80,$AE,$0C dc.b $AF,$06,$E3 MusCred_PSG1: dc.b $80,$30 dc.b $F7,$00,$1A dc.w z80_ptr(MusCred_PSG1) - dc.b $C4,$30,$E7,$30,$C6,$E7,$30,$C2,$E7,$30,$C1,$E7 dc.b $30 dc.b $F7,$00,$02 dc.w z80_ptr(-) - dc.b $80,$30 dc.b $F7,$00,$10 dc.w z80_ptr(-) dc.b $80,$60 - dc.b $80,$30 dc.b $F7,$00,$0A dc.w z80_ptr(-) dc.b $80,$60,$E9,$F4,$E6,$FE,$F5,$01,$F8 dc.w z80_ptr(MusCreditsE635) dc.b $AE,$B3,$06,$AC,$0C,$AE,$AE,$B3,$06,$80,$B3,$AB dc.b $0C,$AE,$F8 dc.w z80_ptr(MusCreditsE635) dc.b $F5,$0B,$80,$04,$80,$60,$F8 dc.w z80_ptr(MusCreditsDA5F) dc.b $E7,$20,$E7,$C5,$01,$E7,$C4,$E7,$C3,$E7,$C2,$E7 dc.b $C1,$E7,$C0,$E7,$BF,$E7,$BE,$E7,$BD,$E7,$BC,$E7 dc.b $BB,$E7,$BA,$80,$60,$F5,$00,$E8,$06,$E9,$F4,$F8 dc.w z80_ptr(MusCreditsE62C) dc.b $C2,$80,$C2,$F8 dc.w z80_ptr(MusCreditsE62C) dc.b $C2,$04,$80,$C2,$80,$0C,$C2,$80,$60,$F5,$08,$E9 dc.b $04,$EC,$02,$E8,$06 - dc.b $F8 dc.w z80_ptr(MusCreditsE618) dc.b $F7,$00,$02 dc.w z80_ptr(-) - dc.b $80,$30 dc.b $F7,$00,$0A dc.w z80_ptr(-) dc.b $80,$60,$F5,$00,$E9,$F0,$EC,$FF,$80,$60 dc.b $F8 dc.w z80_ptr(MusCreditsE004) dc.b $E9,$18,$EC,$02,$B5,$30,$B3,$18,$B5,$0C,$B3,$B1 dc.b $30,$B6,$EC,$FE,$80,$0C,$B8,$80,$B8,$80,$BA,$80 dc.b $BA,$EC,$03,$C4,$18,$C1,$BD,$BF,$0C,$80,$EC,$FC dc.b $80,$B8,$80,$B8,$80,$BA,$18,$08,$B8,$04,$E9,$F4 dc.b $EC,$01,$F5,$05 - dc.b $80,$60 dc.b $F7,$00,$05 dc.w z80_ptr(-) dc.b $80,$0C,$C8,$12,$80,$06,$C8,$80,$C6,$12,$C8,$C6 dc.b $0C,$C1,$18,$C5,$C8,$CB,$80,$0C,$CA,$80,$CA,$12 dc.b $C9,$CA,$06,$80,$09,$E9,$30,$EC,$FC,$F6 dc.w z80_ptr(MusCreditsE770) dc.b $F2 MusCreditsE618: dc.b $80,$0C,$BD,$06,$12,$18,$C4,$06,$12,$0C,$80,$C2 dc.b $06,$12,$18,$C4,$06,$12,$0C,$E3 MusCreditsE62C: dc.b $80,$60,$80,$0C,$C2,$80,$C2,$80,$E3 MusCreditsE635: dc.b $AC,$0C,$AF,$06,$B3,$0C,$AC,$AC,$06,$80,$AC,$0C dc.b $AF,$06,$B5,$0C,$AC,$06,$80,$06,$B1,$0C,$B6,$06 dc.b $AE,$0C,$B1,$B3,$B6,$06,$80,$B6,$AA,$0C,$AF,$AF dc.b $B5,$06,$AC,$0C,$AF,$B2,$B5,$06,$80,$B5,$AE,$0C dc.b $B2,$E3 MusCred_PSG2: dc.b $80,$30 dc.b $F7,$00,$1A dc.w z80_ptr(MusCred_PSG2) - dc.b $C1,$30,$E7,$30,$C3,$E7,$30,$BF,$E7,$30,$BD,$E7 dc.b $30 dc.b $F7,$00,$02 dc.w z80_ptr(-) - dc.b $80,$30 dc.b $F7,$00,$10 dc.w z80_ptr(-) dc.b $80,$60,$E9,$0C,$EC,$FD,$F5,$04,$80 - dc.b $F8 dc.w z80_ptr(MusCreditsDFF2) dc.b $F7,$00,$02 dc.w z80_ptr(-) dc.b $80,$60 dc.b $F0,$03,$02,$01,$05 dc.b $F5,$0A,$E9,$E8,$EC,$02,$80,$30,$80,$80,$BD,$06 dc.b $BF,$C6,$C2,$1E,$80,$60,$80,$06,$C6,$80,$C6,$C4 dc.b $80,$C4,$80,$C3,$80,$C3,$80,$BF,$03,$80,$BF,$80 dc.b $09,$80,$06,$80,$30,$80,$80,$BD,$06,$BF,$C6,$C2 dc.b $1E,$80,$60,$F4 - dc.b $80,$30 dc.b $F7,$00,$0C dc.w z80_ptr(-) dc.b $F5,$00,$EC,$FE,$E8,$06,$80,$60,$80,$0C,$BF,$80 dc.b $BF,$80,$BF,$80,$BF,$80,$60,$80,$0C,$BF,$80,$BF dc.b $80,$BF,$04,$80,$BF,$80,$0C,$BF,$80,$60,$EC,$02 - dc.b $F8 dc.w z80_ptr(MusCreditsE618) dc.b $F7,$00,$02 dc.w z80_ptr(-) - dc.b $80,$30 dc.b $F7,$00,$0A dc.w z80_ptr(-) dc.b $80,$60,$F5,$00,$E9,$F4,$EC,$FF,$E9,$E8,$80,$60 dc.b $F8 dc.w z80_ptr(MusCreditsE246) dc.b $E9,$18,$EC,$02,$B1,$30,$B0,$18,$B1,$0C,$B0,$AE dc.b $30,$B1,$EC,$FE,$80,$0C,$B5,$80,$B5,$80,$B6,$80 dc.b $B6,$EC,$03,$80,$B1,$80,$B1,$80,$B1,$80,$B1,$EC dc.b $FC,$80,$B1,$80,$B1,$80,$B1,$18,$08,$B1,$04,$EC dc.b $01,$E9,$18,$F5,$05,$E1,$01,$80,$60,$80,$80,$80 dc.b $80,$80,$80,$0C,$CD,$06,$80,$D4,$CD,$80,$0C,$CD dc.b $06,$80,$D4,$CD,$80,$18,$80,$54,$E9,$24,$EC,$FD MusCreditsE770: dc.b $F5,$03,$80,$06 - dc.b $BF,$03,$C1,$C3,$EC,$01,$E9,$FF dc.b $F7,$00,$05 dc.w z80_ptr(-) - dc.b $BF,$03,$C1,$C3,$EC,$01,$E9,$01 dc.b $F7,$00,$07 dc.w z80_ptr(-) dc.b $F2 MusCred_PSG3: dc.b $F3,$E7,$80,$60,$F5,$02 - dc.b $C6,$0C,$0C,$0C,$06,$06,$0C,$0C,$06,$06,$0C dc.b $F7,$00,$08 dc.w z80_ptr(-) - dc.b $80,$30 dc.b $F7,$00,$08 dc.w z80_ptr(-) - dc.b $C6,$0C,$06,$06 dc.b $F7,$00,$1F dc.w z80_ptr(-) dc.b $0C,$F5,$03,$C6,$F5,$02 - dc.b $C6,$0C,$06,$06 dc.b $F7,$00,$07 dc.w z80_ptr(-) dc.b $06,$06,$06,$06 dc.b $F7,$01,$04 dc.w z80_ptr(-) - dc.b $80,$30 dc.b $F7,$00,$0C dc.w z80_ptr(-) dc.b $F5,$04,$EC,$02 - dc.b $E8,$03,$C6,$06,$06,$E8,$00,$0C dc.b $F7,$00,$04 dc.w z80_ptr(-) dc.b $F5,$02,$EC,$FD - dc.b $80,$0C,$C6,$06,$80,$07,$C6,$06,$80,$11,$C6,$0C dc.b $80,$06,$C6,$0C,$80,$06,$C6,$80 dc.b $F7,$00,$07 dc.w z80_ptr(-) dc.b $EC,$02 - dc.b $C6,$0C,$08,$04 dc.b $F7,$00,$18 dc.w z80_ptr(-) - dc.b $C6,$0C,$0C,$0C,$08,$04 dc.b $F7,$00,$08 dc.w z80_ptr(-) dc.b $80,$60,$F5,$04,$EC,$02 - dc.b $C6,$06,$06,$0C dc.b $F7,$00,$10 dc.w z80_ptr(-) - dc.b $80,$30 dc.b $F7,$00,$0A dc.w z80_ptr(-) dc.b $80,$60,$EC,$FF - dc.b $F5,$01,$C6,$0C,$F5,$02,$EC,$FF,$08,$F5,$01,$EC dc.b $01,$04 dc.b $F7,$00,$27 dc.w z80_ptr(-) dc.b $EC,$FF,$F5,$04 - dc.b $E8,$03,$C6,$0C,$E8,$0C,$0C dc.b $F7,$00,$1E dc.w z80_ptr(-) dc.b $E8,$03,$C6,$06,$E8,$0E,$12,$E8,$03,$0C,$E8,$0F dc.b $0C,$F2 MusCred_DAC: dc.b $82,$06,$82,$82,$82,$82,$0C,$06,$0C,$06,$0C,$0C dc.b $0C - dc.b $81,$18,$82 dc.b $F7,$00,$0E dc.w z80_ptr(-) dc.b $81,$0C - dc.b $82 dc.b $F7,$00,$07 dc.w z80_ptr(-) dc.b $EA,$EA,$F8 dc.w z80_ptr(MusCreditsEA6E) dc.b $81,$0C,$8D,$82,$81,$81,$8E,$82,$84,$04,$06,$02 dc.b $81,$0C,$82,$06,$82,$82,$82,$81,$0C,$82,$06,$82 dc.b $81,$81,$82,$82,$82,$82 - dc.b $81,$18,$82,$81,$82 dc.b $F7,$00,$07 dc.w z80_ptr(-) dc.b $81,$0C,$82,$82,$82,$82,$06,$82,$8C,$8C,$8D,$8D dc.b $8E,$8E,$F8 dc.w z80_ptr(MusCreditsEA84) dc.b $81,$18,$82,$0C,$81,$18,$82,$0C,$82,$82,$06,$82 dc.b $F8 dc.w z80_ptr(MusCreditsEA84) dc.b $81,$0C,$82,$82,$82,$8D,$06,$8D,$8E,$8E,$82,$06 dc.b $82,$8D,$0C,$82,$0C,$82,$06,$82,$80,$82,$82,$0C MusCreditsE8E5: dc.b $82,$0C,$82,$82,$06,$82,$8D,$8D - dc.b $81,$0C,$8F,$06,$90,$82,$0C,$90,$06,$91,$81,$0C dc.b $8F,$06,$91,$82,$0C,$8F,$06,$91 dc.b $F7,$00,$04 dc.w z80_ptr(-) dc.b $81,$0C,$8F,$06,$91,$82,$0C,$8F,$06,$91,$8C,$06 dc.b $03,$03,$8D,$06,$8D,$8D,$8E,$8E,$8E,$81,$06,$0C dc.b $82,$06,$80,$0C,$81,$82,$8E,$82,$06,$82,$82,$82 - dc.b $81,$0C,$82,$06,$81,$12,$81,$06,$81,$12,$8C,$06 dc.b $82,$0C,$83,$06,$81,$80 dc.b $F7,$00,$06 dc.w z80_ptr(-) dc.b $81,$0C,$82,$06,$81,$12,$81,$06,$81,$06,$82,$06 dc.b $81,$0C,$06,$82,$0C,$08,$04,$EA,$CD,$82,$30,$82 dc.b $0C,$82,$82,$82,$08,$04,$F8 dc.w z80_ptr(MusCreditsEA9F) dc.b $F8 dc.w z80_ptr(MusCreditsEA9F) dc.b $81,$08,$0C,$04,$82,$0C,$81,$08,$04,$82,$08,$04 dc.b $08,$04,$04,$04,$04,$08,$04,$EA,$C5 - dc.b $81,$09,$81,$03,$0C,$82,$81,$81,$18,$82 dc.b $F7,$00,$03 dc.w z80_ptr(-) dc.b $81,$09,$81,$03,$0C,$82,$81,$81,$18,$82,$0C,$06 dc.b $06,$81,$0C,$82,$06,$82,$82,$82,$8D,$0C,$82,$0C dc.b $0C,$0C,$06,$06 - dc.b $81,$0C,$81,$82,$80,$81,$81,$82,$83 dc.b $F7,$00,$03 dc.w z80_ptr(-) dc.b $81,$82,$82,$82,$82,$06,$06,$06,$06,$0C,$06,$06 dc.b $81,$06,$81,$82,$82,$81,$82,$81,$81,$82,$02,$82 dc.b $04,$81,$0C,$06,$82,$0C,$06,$06,$81,$18,$82,$0C dc.b $81,$81,$18,$82,$81,$06,$81,$12,$82,$0C,$81,$81 dc.b $18,$82,$81,$18,$82,$0C,$81,$81,$18,$82,$81,$06 dc.b $81,$12,$82,$0C,$0C,$06,$06,$06,$06,$0C,$06,$06 dc.b $82,$02,$04,$81,$0C,$06,$0C,$82,$02,$04,$81,$0C dc.b $06,$0C,$82,$06,$82,$82,$82,$EA,$C0,$81,$0C,$82 dc.b $81,$82,$81,$82,$81,$08,$82,$04,$0C - dc.b $81,$0C,$82 dc.b $F7,$00,$0F dc.w z80_ptr(-) dc.b $81,$08,$82,$04,$0C - dc.b $81,$0C,$82 dc.b $F7,$00,$13 dc.w z80_ptr(-) dc.b $82,$08,$0C,$04,$81,$0C,$82,$81,$82,$81,$0C,$82 dc.b $81,$06,$80,$02,$82,$82,$82,$09,$82,$03 - dc.b $81,$0C,$82 dc.b $F7,$00,$06 dc.w z80_ptr(-) dc.b $81,$0C,$82,$81,$06,$80,$02,$82,$82,$82,$09,$82 dc.b $03 dc.b $F7,$01,$03 dc.w z80_ptr(-) dc.b $81,$0C,$82,$81,$82,$81,$06,$82,$12,$82,$0C,$81 dc.b $F2 MusCreditsEA6E: dc.b $81,$0C,$8D,$82,$81,$81,$8E,$82,$84,$04,$06,$02 dc.b $81,$0C,$8D,$82,$81,$81,$8E,$82,$83,$E3 MusCreditsEA84: dc.b $81,$18,$82,$0C,$81,$18,$0C,$82,$81,$81,$18,$82 dc.b $0C,$81,$12,$81,$82,$18,$81,$82,$0C,$81,$18,$0C dc.b $82,$81,$E3 MusCreditsEA9F: dc.b $81,$08,$0C,$04,$82,$0C,$81,$08,$0C,$82,$04,$81 dc.b $0C,$82,$81,$81,$08,$0C,$04,$82,$0C,$81,$08,$0C dc.b $82,$04,$81,$0C,$82,$82,$08,$04,$E3,$81,$06,$80 dc.b $03,$81,$81,$06,$82,$81,$06,$80,$03,$81,$81,$06 dc.b $82,$03,$82,$81,$06,$80,$03,$81,$81,$06,$82,$E3 MusCred_Voices: dc.b $3A,$01,$01,$07,$01,$8E,$8D,$8E,$53,$0E,$0E,$0E dc.b $03,$00,$00,$00,$01,$1F,$1F,$FF,$0F,$17,$27,$28,$80 dc.b $08,$09,$30,$70,$00,$1F,$5F,$1F,$5F,$12,$0A,$0E dc.b $0A,$00,$04,$04,$03,$2F,$2F,$2F,$2F,$25,$0E,$30,$84 dc.b $3C,$31,$50,$52,$30,$52,$52,$53,$53,$08,$08,$00 dc.b $00,$04,$04,$00,$00,$10,$10,$0B,$0D,$19,$0B,$80,$80 dc.b $08,$0A,$30,$70,$00,$1F,$5F,$1F,$5F,$12,$0A,$0E dc.b $0A,$00,$04,$04,$03,$2F,$2F,$2F,$2F,$24,$13,$2D,$80 dc.b $3D,$01,$51,$21,$01,$12,$14,$14,$0F,$0A,$05,$05 dc.b $05,$00,$00,$00,$00,$2B,$2B,$2B,$1B,$19,$80,$80,$80 dc.b $04,$57,$70,$02,$50,$1F,$1F,$1F,$1F,$00,$00,$00 dc.b $00,$06,$00,$0A,$0A,$00,$00,$0F,$0F,$1A,$10,$80,$80 dc.b $35,$01,$13,$01,$00,$1F,$18,$1D,$19,$00,$06,$09 dc.b $0D,$00,$02,$00,$03,$00,$15,$06,$16,$1E,$83,$80,$80 dc.b $3C,$31,$50,$52,$30,$52,$52,$53,$53,$08,$08,$00 dc.b $00,$04,$04,$00,$00,$1F,$1F,$0F,$0F,$1A,$16,$88,$88 dc.b $20,$36,$30,$35,$31,$DF,$9F,$DF,$9F,$07,$09,$06 dc.b $06,$07,$06,$06,$08,$2F,$1F,$1F,$FF,$14,$0F,$37,$80 dc.b $3B,$0F,$01,$06,$02,$DF,$1F,$1F,$DF,$0C,$0A,$00 dc.b $03,$0F,$00,$00,$01,$F3,$55,$05,$5C,$22,$22,$20,$80 dc.b $3C,$31,$50,$52,$30,$52,$52,$53,$53,$08,$08,$00 dc.b $00,$04,$04,$00,$00,$1F,$1F,$0F,$0F,$1C,$14,$84,$80 dc.b $3A,$69,$50,$70,$60,$1C,$1A,$18,$18,$10,$02,$0C dc.b $09,$08,$06,$06,$03,$F9,$06,$56,$06,$28,$14,$15,$00 dc.b $3D,$00,$02,$01,$01,$4C,$50,$0F,$12,$0C,$00,$02 dc.b $05,$01,$00,$00,$00,$28,$2A,$29,$19,$1A,$06,$00,$00 dc.b $2C,$71,$31,$71,$31,$1F,$1F,$16,$16,$00,$00,$0F dc.b $0F,$00,$00,$0F,$0F,$00,$00,$FA,$FA,$15,$14,$00,$00 dc.b $18,$37,$31,$32,$31,$9E,$1C,$DC,$9C,$0D,$04,$06 dc.b $01,$08,$03,$0A,$05,$B6,$36,$B6,$28,$2C,$14,$22,$00 dc.b $3D,$01,$02,$02,$02,$10,$50,$50,$50,$07,$08,$08 dc.b $08,$01,$00,$00,$00,$24,$18,$18,$18,$1C,$82,$82,$82 dc.b $32,$71,$33,$0D,$01,$5F,$5F,$99,$94,$05,$05,$05 dc.b $07,$02,$02,$02,$02,$11,$11,$11,$72,$23,$26,$2D,$80 dc.b $3A,$32,$52,$01,$31,$1F,$1F,$1F,$18,$01,$00,$1F dc.b $00,$00,$00,$0F,$00,$5A,$03,$0F,$1A,$3B,$4F,$30,$00 dc.b $3C,$42,$32,$41,$41,$12,$12,$12,$12,$00,$00,$00 dc.b $00,$00,$00,$00,$00,$06,$06,$08,$08,$24,$24,$08,$08 dc.b $31,$34,$30,$35,$31,$DF,$9F,$DF,$9F,$0C,$0C,$07 dc.b $09,$07,$07,$07,$08,$2F,$1F,$1F,$2F,$17,$14,$32,$80 dc.b $3D,$01,$01,$01,$01,$10,$50,$50,$50,$07,$08,$08 dc.b $08,$01,$00,$00,$00,$20,$1A,$1A,$1A,$19,$84,$84,$84 dc.b $24,$70,$30,$74,$38,$12,$1F,$1F,$1F,$05,$05,$03 dc.b $03,$05,$05,$03,$03,$36,$26,$2C,$2C,$0A,$06,$08,$08 dc.b $3A,$01,$01,$01,$02,$8D,$07,$07,$52,$09,$00,$00 dc.b $03,$01,$02,$02,$00,$5F,$0F,$0F,$2F,$18,$18,$22,$80 dc.b $3A,$01,$01,$07,$01,$8E,$8D,$8E,$53,$0E,$0E,$0E dc.b $03,$00,$00,$00,$00,$1F,$1F,$FF,$0F,$18,$16,$4E,$80 dc.b $3A,$03,$03,$08,$01,$8E,$8D,$8E,$53,$0E,$0E,$0E dc.b $03,$00,$00,$00,$00,$1F,$1F,$FF,$0F,$17,$20,$28,$80 dc.b $20,$7A,$00,$31,$00,$9F,$DC,$D8,$DF,$10,$04,$0A dc.b $04,$0F,$08,$08,$08,$5F,$BF,$5F,$BF,$14,$17,$2B,$80 dc.b $3A,$61,$51,$08,$02,$5D,$5D,$5D,$50,$04,$1F,$0F dc.b $1F,$00,$00,$00,$00,$1F,$0F,$5F,$0F,$22,$22,$1E,$80 dc.b $02,$01,$02,$55,$04,$92,$8E,$8D,$54,$0D,$00,$0C dc.b $03,$00,$00,$00,$00,$FF,$0F,$2F,$5F,$16,$1D,$2A,$80 dc.b $02,$75,$73,$71,$31,$1F,$96,$58,$9F,$01,$03,$1B dc.b $08,$01,$01,$04,$05,$FF,$3F,$2F,$2F,$24,$30,$29,$80 dc.b $20,$66,$60,$65,$60,$DF,$9F,$DF,$1F,$00,$09,$06 dc.b $0C,$07,$06,$06,$08,$2F,$1F,$1F,$FF,$1C,$16,$3A,$80 dc.b $0D,$32,$06,$08,$01,$1F,$19,$19,$19,$0A,$05,$05 dc.b $05,$00,$02,$02,$02,$3F,$2F,$2F,$2F,$28,$86,$80,$8D dc.b $38,$3A,$11,$0A,$02,$D4,$50,$14,$0E,$05,$02,$08 dc.b $88,$00,$00,$00,$00,$99,$09,$09,$1A,$2D,$19,$2C,$86 dc.b $0D,$32,$02,$04,$01,$1F,$19,$19,$19,$0A,$05,$05 dc.b $05,$00,$02,$02,$02,$3F,$2F,$2F,$2F,$28,$8B,$86,$93 dc.b $3A,$20,$60,$23,$01,$1E,$1F,$1F,$1F,$0A,$0B,$0A dc.b $0A,$05,$0A,$07,$08,$A4,$96,$85,$78,$21,$28,$25,$00 dc.b $3A,$32,$32,$56,$42,$8D,$15,$4F,$52,$06,$07,$08 dc.b $04,$02,$00,$00,$00,$18,$28,$18,$28,$19,$2A,$20,$00 dc.b $3A,$51,$51,$08,$02,$1E,$1E,$1E,$10,$1F,$1F,$1F dc.b $0F,$00,$00,$00,$02,$0F,$0F,$0F,$1F,$18,$22,$24,$81 dc.b $20,$36,$30,$35,$31,$DF,$9F,$DF,$9F,$07,$09,$06 dc.b $06,$07,$06,$06,$08,$2F,$1F,$1F,$FF,$19,$13,$37,$80 dc.b $3D,$01,$02,$02,$02,$14,$8C,$0E,$0E,$08,$02,$05 dc.b $05,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$1A,$80,$80,$80 ; end of Mus_Credits ; ------------------------------------------------------------------------------------------ ; Sound effect pointers ; ------------------------------------------------------------------------------------------ ; WARNING the sound driver treats certain sounds specially ; going by the ID of the sound. ; SndID_Ring, SndID_RingLeft, SndID_Gloop, SndID_SpindashRev ; are referenced by the sound driver directly. ; If needed you can change this in s2.sounddriver.asm ; NOTE: the exact order of this list determines the priority of each sound, since it determines the sound's SndID. ; a sound can get dropped if a higher-priority sound is already playing. ; see zSFXPriority for the priority allocation itself. ; loc_FEE91: SoundPoint: SoundIndex: SndPtr_Jump: rom_ptr_z80 Sound20 ; jumping sound SndPtr_Checkpoint: rom_ptr_z80 Sound21 ; checkpoint ding-dong sound SndPtr_SpikeSwitch: rom_ptr_z80 Sound22 ; spike switch sound SndPtr_Hurt: rom_ptr_z80 Sound23 ; hurt sound SndPtr_Skidding: rom_ptr_z80 Sound24 ; skidding sound SndPtr_BlockPush: rom_ptr_z80 Sound25 ; block push sound SndPtr_HurtBySpikes: rom_ptr_z80 Sound26 ; spiky impalement sound SndPtr_Sparkle: rom_ptr_z80 Sound27 ; sparkling sound SndPtr_Beep: rom_ptr_z80 Sound28 ; short beep SndPtr_Bwoop: rom_ptr_z80 Sound29 ; bwoop (unused) SndPtr_Splash: rom_ptr_z80 Sound2A ; splash sound SndPtr_Swish: rom_ptr_z80 Sound2B ; swish SndPtr_BossHit: rom_ptr_z80 Sound2C ; boss hit SndPtr_InhalingBubble: rom_ptr_z80 Sound2D ; inhaling a bubble SndPtr_ArrowFiring: SndPtr_LavaBall: rom_ptr_z80 Sound2E ; arrow firing SndPtr_Shield: rom_ptr_z80 Sound2F ; shield sound SndPtr_LaserBeam: rom_ptr_z80 Sound30 ; laser beam SndPtr_Zap: rom_ptr_z80 Sound31 ; zap (unused) SndPtr_Drown: rom_ptr_z80 Sound32 ; drownage SndPtr_FireBurn: rom_ptr_z80 Sound33 ; fire + burn SndPtr_Bumper: rom_ptr_z80 Sound34 ; bumper bing SndPtr_Ring: SndPtr_RingRight: rom_ptr_z80 Sound35 ; ring sound SndPtr_SpikesMove: rom_ptr_z80 Sound36 SndPtr_Rumbling: rom_ptr_z80 Sound37 ; rumbling rom_ptr_z80 Sound38 ; (unused) SndPtr_Smash: rom_ptr_z80 Sound39 ; smash/breaking rom_ptr_z80 Sound3A ; nondescript ding (unused) SndPtr_DoorSlam: rom_ptr_z80 Sound3B ; door slamming shut SndPtr_SpindashRelease: rom_ptr_z80 Sound3C ; spindash unleashed SndPtr_Hammer: rom_ptr_z80 Sound3D ; slide-thunk SndPtr_Roll: rom_ptr_z80 Sound3E ; rolling sound SndPtr_ContinueJingle: rom_ptr_z80 Sound3F ; got continue SndPtr_CasinoBonus: rom_ptr_z80 Sound40 ; short bonus ding SndPtr_Explosion: rom_ptr_z80 Sound41 ; badnik bust SndPtr_WaterWarning: rom_ptr_z80 Sound42 ; warning ding-ding SndPtr_EnterGiantRing: rom_ptr_z80 Sound43 ; special stage ring flash (mostly unused) SndPtr_BossExplosion: rom_ptr_z80 Sound44 ; thunk SndPtr_TallyEnd: rom_ptr_z80 Sound45 ; cha-ching SndPtr_RingSpill: rom_ptr_z80 Sound46 ; losing rings rom_ptr_z80 Sound47 ; chain pull chink-chink (unused) SndPtr_Flamethrower: rom_ptr_z80 Sound48 ; flamethrower SndPtr_Bonus: rom_ptr_z80 Sound49 ; bonus pwoieeew (mostly unused) SndPtr_SpecStageEntry: rom_ptr_z80 Sound4A ; special stage entry SndPtr_SlowSmash: rom_ptr_z80 Sound4B ; slower smash/crumble SndPtr_Spring: rom_ptr_z80 Sound4C ; spring boing SndPtr_Blip: rom_ptr_z80 Sound4D ; selection blip SndPtr_RingLeft: rom_ptr_z80 Sound4E ; another ring sound (only plays in the left speaker?) SndPtr_Signpost: rom_ptr_z80 Sound4F ; signpost spin sound SndPtr_CNZBossZap: rom_ptr_z80 Sound50 ; mosquito zapper rom_ptr_z80 Sound51 ; (unused) rom_ptr_z80 Sound52 ; (unused) SndPtr_Signpost2P: rom_ptr_z80 Sound53 SndPtr_OOZLidPop: rom_ptr_z80 Sound54 ; OOZ lid pop sound SndPtr_SlidingSpike: rom_ptr_z80 Sound55 SndPtr_CNZElevator: rom_ptr_z80 Sound56 SndPtr_PlatformKnock: rom_ptr_z80 Sound57 SndPtr_BonusBumper: rom_ptr_z80 Sound58 ; CNZ bonusy bumper sound SndPtr_LargeBumper: rom_ptr_z80 Sound59 ; CNZ baaang bumper sound SndPtr_Gloop: rom_ptr_z80 Sound5A ; CNZ gloop / water droplet sound SndPtr_PreArrowFiring: rom_ptr_z80 Sound5B SndPtr_Fire: rom_ptr_z80 Sound5C SndPtr_ArrowStick: rom_ptr_z80 Sound5D ; chain clink SndPtr_Helicopter: SndPtr_WingFortress: rom_ptr_z80 Sound5E ; helicopter SndPtr_SuperTransform: rom_ptr_z80 Sound5F SndPtr_SpindashRev: rom_ptr_z80 Sound60 ; spindash charge SndPtr_Rumbling2: rom_ptr_z80 Sound61 ; rumbling SndPtr_CNZLaunch: rom_ptr_z80 Sound62 SndPtr_Flipper: rom_ptr_z80 Sound63 ; CNZ blooing bumper SndPtr_HTZLiftClick: rom_ptr_z80 Sound64 ; HTZ track click sound SndPtr_Leaves: rom_ptr_z80 Sound65 ; kicking up leaves sound SndPtr_MegaMackDrop: rom_ptr_z80 Sound66 ; leaf splash? SndPtr_DrawbridgeMove: rom_ptr_z80 Sound67 SndPtr_QuickDoorSlam: rom_ptr_z80 Sound68 ; door slamming quickly (unused) SndPtr_DrawbridgeDown: rom_ptr_z80 Sound69 SndPtr_LaserBurst: rom_ptr_z80 Sound6A ; robotic laser burst SndPtr_Scatter: SndPtr_LaserFloor: rom_ptr_z80 Sound6B ; scatter SndPtr_Teleport: rom_ptr_z80 Sound6C SndPtr_Error: rom_ptr_z80 Sound6D ; error sound SndPtr_MechaSonicBuzz: rom_ptr_z80 Sound6E ; silver sonic buzz saw SndPtr_LargeLaser: rom_ptr_z80 Sound6F SndPtr_OilSlide: rom_ptr_z80 Sound70 SndPtr__End: ; There are many non-relative pointers in these sound effects, ; so the sounds shouldn't simply be BINCLUDE'd. ; They could be included as separate .asm files using "include" instead of "binclude", ; but I wanted to minimize the number of included asm files. ; some comments on what the various script commands do (after the header): ; 0x00-0x7F sets the note duration (of the previous note and following notes) ; 0x81-0xDF plays a note (the valid range may be smaller for PSG or DAC) ; 0x80 plays silence ; 0xE0-0xFF does special things. I won't list them here... search for "Coordination flags" sonic 2. ; the FM voices (poorly named "ssamp" or "samples" below) ; are 25 bytes each and go directly to YM2612 registers. ; they can be hard to edit (there's an art to it) ; but search for sonic "Voice editing" for more info if you want to try. ; jumping sound Sound20: dc.w $0000,$0101 dc.w $8080,z80_ptr(+),$F400 + dc.b $F5,$00,$9E,$05,$F0,$02,$01,$F8,$65,$A3,$15,$F2 ; checkpoint ding-dong sound Sound21: dc.w z80_ptr(ssamp21),$0101 dc.w $8005,z80_ptr(+),$0001 ssamp21: dc.b $3C,$05,$0A,$01,$01,$56,$5C,$5C,$5C,$0E,$11,$11 dc.b $11,$09,$06,$0A,$0A,$4F,$3F,$3F,$3F,$17,$20,$80,$80 + dc.b $EF,$00,$BD,$06,$BA,$16,$F2 ; spike switch sound Sound22: dc.w $0000,$0101 dc.w $80C0,z80_ptr(+),$0000 + dc.b $F0,$01,$01,$F0,$08,$F3,$E7,$C0,$04,$CA,$04 - dc.b $C0,$01,$EC dc.w $01F7,$0006,z80_ptr(-) dc.b $F2 ; hurt sound Sound23: dc.w z80_ptr(ssamp23),$0101 dc.w $8005,z80_ptr(+),$F400 + dc.b $EF,$00,$B0,$07,$E7,$AD - dc.b $01,$E6 dc.w $01F7,$002F,z80_ptr(-) dc.b $F2 ssamp23: dc.b $30,$30,$30,$30,$30,$9E,$DC,$D8,$DC,$0E,$04,$0A dc.b $05,$08,$08,$08,$08,$BF,$BF,$BF,$BF,$14,$14,$3C,$80 ; skidding sound Sound24: dc.w $0000,$0102 ; sound header... no sample and 2 script entries dc.w $80A0,z80_ptr(+),$F400 ; entry 1 header dc.w $80C0,z80_ptr(++),$F400 ; entry 2 header + dc.b $F5,$00,$AF,$01,$80,$AF,$80,$03 ; script entry 1 - dc.b $AF,$01,$80 dc.w $01F7,$000B,z80_ptr(-) ; loopback dc.b $F2 ; script 1 end + dc.b $F5,$00,$80,$01,$AD,$80,$AD,$80,$03 ; script entry 2 - dc.b $AD,$01,$80 dc.w $01F7,$000B,z80_ptr(-) ; loopback dc.b $F2 ; script 2 end ; block push sound Sound25: dc.w z80_ptr(ssamp25),$0101 dc.w $8005,z80_ptr(+),$0000 + dc.b $EF,$00,$80,$01,$8B,$0A,$80,$02,$F2 ssamp25: dc.b $FA,$21,$10,$30,$32,$2F,$2F,$1F,$2F,$05,$09,$08 dc.b $02,$06,$06,$0F,$02,$1F,$4F,$2F,$2F,$0F,$0E,$1A,$80 ; spiky impalement sound Sound26: dc.w z80_ptr(ssamp26),$0101 dc.w $8005,z80_ptr(+),$F200 + dc.b $EF,$00,$F0,$01,$01,$10,$FF,$CF,$05,$D7,$25,$F2 ssamp26: dc.b $3B,$3C,$30,$39,$31,$DF,$1F,$1F,$DF,$04,$04,$05 dc.b $01,$04,$04,$04,$02,$FF,$1F,$0F,$AF,$29,$0F,$20,$80 ; sparkling sound Sound27: dc.w z80_ptr(ssamp27),$0101 dc.w $8004,z80_ptr(+),$0C1C + dc.b $EF,$00,$C1,$05,$C4,$05,$C9,$2B,$F2 ssamp27: dc.b $07,$73,$33,$33,$73,$0F,$19,$14,$1A,$0A,$0A,$0A dc.b $0A,$0A,$0A,$0A,$0A,$57,$57,$57,$57,$00,$00,$00,$00 ; short beep Sound28: dc.w $0000,$0101 dc.w $8080,z80_ptr(+),$E803 + dc.b $F5,$04,$CB,$04,$F2 ; bwoop (unused) Sound29: dc.w $0000,$0101 dc.w $80A0,z80_ptr(+),$0000 + dc.b $F0,$01,$01,$E6,$35,$8E,$06,$F2 ; splash sound Sound2A: dc.w z80_ptr(ssamp2A),$0102 dc.w $80C0,z80_ptr(+),$0000 dc.w $8005,z80_ptr(++),$0003 + dc.b $F5,$00,$F3,$E7,$C2,$05,$C6,$05,$E7 - dc.b $07,$EC,$01 dc.w $E7F7,$000F,z80_ptr(-) dc.b $F2 + dc.b $EF,$00,$A6,$14,$F2 ssamp2A: dc.b $00,$00,$02,$03,$00,$D9,$1F,$DF,$1F,$12,$14,$11 dc.b $0F,$0A,$0A,$00,$0D,$FF,$FF,$FF,$FF,$22,$27,$07,$80 ; swish Sound2B: dc.w $0000,$0101 dc.w $80C0,z80_ptr(+),$0000 + dc.b $F5,$00,$F3,$E7,$C6,$03,$80,$03,$C6,$01,$E7 - dc.b $01,$EC,$01 dc.w $E7F7,$0015,z80_ptr(-) dc.b $F2 ; boss hit Sound2C: dc.w z80_ptr(smashsamp),$0101 dc.w $8005,z80_ptr(+),$0000 + dc.b $EF,$00,$F0,$01,$01,$0C,$01 - dc.b $81,$0A,$E6 dc.w $10F7,$0004,z80_ptr(-) dc.b $F2 smashsamp: dc.b $F9,$21,$10,$30,$32,$1F,$1F,$1F,$1F,$05,$09,$18 dc.b $02,$0B,$10,$1F,$05,$1F,$4F,$2F,$2F,$0E,$04,$07,$80 ; inhaling a bubble Sound2D: dc.w z80_ptr(ssamp2D),$0101 dc.w $8005,z80_ptr(+),$0E00 + dc.b $EF,$00,$F0,$01,$01,$21,$6E,$A6,$07 dc.b $80,$06,$F0,$01,$01,$44,$1E,$AD,$08,$F2 ssamp2D: dc.b $35,$05,$08,$09,$07,$1E,$0D,$0D,$0E,$0C,$03,$15 dc.b $06,$16,$09,$0E,$10,$2F,$1F,$2F,$1F,$15,$12,$12,$80 ; arrow firing Sound2E: dc.w z80_ptr(ssamp2E),$0102 dc.w $8005,z80_ptr(+),$0000 dc.w $80C0,z80_ptr(++),$0000 + dc.b $EF,$00,$80,$01,$F0,$01,$01,$40,$48,$83,$06,$85,$02,$F2 + dc.b $F5,$00,$80,$0B,$F3,$E7,$C6,$01,$E7 - dc.b $02,$EC,$01 dc.w $E7F7,$0010,z80_ptr(-) dc.b $F2 ssamp2E: dc.b $FA,$02,$00,$03,$05,$12,$0F,$11,$13,$05,$09,$18 dc.b $02,$06,$06,$0F,$02,$1F,$4F,$2F,$2F,$2F,$0E,$1A,$80 ; shield sound Sound2F: dc.w z80_ptr(ssamp2F),$0101 dc.w $8005,z80_ptr(+),$0C00 + dc.b $EF,$00,$80,$01,$A3,$05,$E7,$A4,$26,$F2 ssamp2F: dc.b $30,$30,$30,$30,$30,$9E,$AC,$A8,$DC,$0E,$04,$0A dc.b $05,$08,$08,$08,$08,$BF,$BF,$BF,$BF,$04,$14,$2C,$80 ; laser beam Sound30: dc.w z80_ptr(ssamp30),$0101 ; sound header... a voice and 1 script entry dc.w $8005,z80_ptr(+),$FB05 ; script entry header + dc.b $EF,$00,$DF,$7F ; script start - dc.b $DF,$02,$E6 ; script continued dc.w $01F7,$001B,z80_ptr(-) ; loopback dc.b $F2 ; script end ssamp30: dc.b $83,$1F,$1F,$15,$1F,$1F,$1F,$1F,$1F,$00,$00,$00 ; voice dc.b $00,$02,$02,$02,$02,$2F,$FF,$2F,$3F,$0B,$01,$16,$82 ; (fixed length) ; zap (unused) Sound31: dc.w z80_ptr(ssamp31),$0101 dc.w $8005,z80_ptr(+),$FB02 + dc.b $EF,$00,$B3,$05,$80,$01,$B3,$09,$F2 ssamp31: dc.b $83,$12,$13,$10,$1E,$1F,$1F,$1F,$1F,$00,$00,$00 dc.b $00,$02,$02,$02,$02,$2F,$FF,$2F,$3F,$05,$34,$10,$87 ; drownage Sound32: dc.w z80_ptr(ssamp32),$0102 dc.w $8004,z80_ptr(++),$0C04 dc.w $8005,z80_ptr(+),$0E02 + dc.b $EF,$00,$F0,$01,$01,$83,$0C - dc.b $8A,$05,$05,$E6 dc.w $03F7,$000A,z80_ptr(-) dc.b $F2 + dc.b $80,$06,$EF,$00,$F0,$01,$01,$6F,$0E - dc.b $8D,$04,$05,$E6 dc.w $03F7,$000A,z80_ptr(-) dc.b $F2 ssamp32: dc.b $35,$14,$04,$1A,$09,$0E,$11,$10,$0E,$0C,$03,$15 dc.b $06,$16,$09,$0E,$10,$2F,$4F,$2F,$4F,$2F,$12,$12,$80 ; fire + burn Sound33: dc.w z80_ptr(ssamp2E),$0102 dc.w $8005,z80_ptr(+),$0000 dc.w $80C0,z80_ptr(++),$0000 + dc.b $EF,$00,$80,$01,$F0,$01,$01,$40,$48,$83,$06,$85,$02,$F2 + dc.b $F5,$00,$80,$0B,$F3,$E7,$A7,$25,$E7 - dc.b $02,$EC,$01 dc.w $E7F7,$0010,z80_ptr(-) dc.b $F2 ; bumper bing Sound34: dc.w z80_ptr(ssamp34),$0103 dc.w $8005,z80_ptr(+),$0000 dc.w $8004,z80_ptr(++),$0000 dc.w $8002,z80_ptr(+++),$0002 + dc.b $EF,$00,$F6 dc.w z80_ptr(Sound34_3) + dc.b $EF,$00,$E1,$07,$80,$01 Sound34_3: dc.b $BA,$20,$F2 + dc.b $EF,$01,$9A,$03,$F2 ssamp34: dc.b $3C,$05,$0A,$01,$01,$56,$5C,$5C,$5C,$0E,$11,$11 dc.b $11,$09,$06,$0A,$0A,$4F,$3F,$3F,$3F,$1F,$2B,$80,$80 dc.b $05,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$12,$0C,$0C dc.b $0C,$12,$08,$08,$08,$1F,$5F,$5F,$5F,$07,$80,$80,$80 ; ring sound Sound35: dc.w z80_ptr(ringsamp),$0101 dc.w $8005,z80_ptr(+),$0005 + dc.b $EF,$00,$E0,$40,$C1,$05,$C4,$05,$C9,$1B,$F2 Sound36: dc.w $0000,$0101 dc.w $80C0,z80_ptr(+),$0000 + dc.b $F0,$01,$01,$F0,$08,$F3,$E7,$C1,$07 - dc.b $D0,$01,$EC dc.w $01F7,$000C,z80_ptr(-) dc.b $F2 ; rumbling Sound37: dc.w z80_ptr(ssamp37),$0101 dc.w $8005,z80_ptr(+),$0000 + dc.b $EF,$00,$F0,$01,$01,$20,$08 - dc.b $8B dc.w $0AF7,$0008,z80_ptr(-) - dc.b $8B,$10,$E6 dc.w $03F7,$0009,z80_ptr(-) dc.b $F2 ssamp37: dc.b $FA,$21,$10,$30,$32,$1F,$1F,$1F,$1F,$05,$09,$18 dc.b $02,$06,$06,$0F,$02,$1F,$4F,$2F,$2F,$0F,$0E,$1A,$80 ; (unused) Sound38: dc.w $0000,$0101 dc.w $80C0,z80_ptr(+),$0000 + dc.b $F0,$01,$01,$F0,$08,$F3,$E7,$B4,$08 - dc.b $B0,$02,$EC dc.w $01F7,$0003,z80_ptr(-) dc.b $F2 ; smash/breaking Sound39: dc.w z80_ptr(smashsamp),$0104 dc.w $8002,z80_ptr(+),$1000 dc.w $8004,z80_ptr(+++),$0000 dc.w $8005,z80_ptr(++),$1000 dc.w $80C0,z80_ptr(s39s4),$0000 + dc.b $E0,$40,$80,$02,$F6 dc.w z80_ptr(++) + dc.b $E0,$80,$80,$01 + dc.b $EF,$00,$F0,$03,$01,$20,$04 - dc.b $81,$18,$E6 dc.w $0AF7,$0006,z80_ptr(-) dc.b $F2 s39s4: dc.b $F0,$01,$01,$0F,$05,$F3,$E7 - dc.b $B0,$18,$E7,$EC dc.w $03F7,$0005,z80_ptr(-) dc.b $F2 ; nondescript ding (unused) Sound3A: dc.w z80_ptr(ssamp3A),$0101 dc.w $8005,z80_ptr(+),$0007 + dc.b $EF,$00,$AE,$08,$F2 ssamp3A: dc.b $1C,$2E,$0F,$02,$02,$1F,$1F,$1F,$1F,$18,$14,$0F dc.b $0E,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$20,$1B,$80,$80 ; door slamming shut Sound3B: dc.w z80_ptr(ssamp3B),$0101 dc.w $8005,z80_ptr(+),$F400 + dc.b $EF,$00,$9B,$04,$80,$A0,$06,$F2 ssamp3B: dc.b $3C,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$00,$0F,$16 dc.b $0F,$00,$00,$00,$00,$0F,$FF,$AF,$FF,$00,$0A,$80,$80 ; spindash unleashed Sound3C: dc.w z80_ptr(ssamp3C),$0102 dc.w $8005,z80_ptr(+),$9000 dc.w $80C0,z80_ptr(++),$0000 + dc.b $EF,$00,$F0,$01,$01,$C5,$1A,$CD,$07,$F2 + dc.b $F5,$07,$80,$07,$F0,$01,$02,$05,$FF,$F3,$E7,$BB,$4F,$F2 ssamp3C: dc.b $FD,$09,$00,$03,$00,$1F,$1F,$1F,$1F,$10,$0C,$0C dc.b $0C,$0B,$10,$1F,$05,$1F,$4F,$2F,$2F,$09,$92,$84,$8E ; slide-thunk Sound3D: dc.w z80_ptr(ssamp3D),$0102 dc.w $8005,z80_ptr(+),$100A dc.w $8004,z80_ptr(++),$0000 + dc.b $EF,$00,$F0,$01,$01,$60,$01,$A7,$08,$F2 + dc.b $80,$08,$EF,$01,$84,$22,$F2 ssamp3D: dc.b $FA,$21,$19,$3A,$30,$1F,$1F,$1F,$1F,$05,$09,$18 dc.b $02,$0B,$10,$1F,$05,$1F,$4F,$2F,$2F,$0E,$04,$07,$80 dc.b $FA,$31,$10,$30,$32,$1F,$1F,$1F,$1F,$05,$05,$18 dc.b $10,$0B,$10,$1F,$10,$1F,$1F,$2F,$2F,$0D,$01,$00,$80 ; rolling sound Sound3E: dc.w z80_ptr(ssamp3E),$0101 dc.w $8004,z80_ptr(+),$0C05 + dc.b $EF,$00,$80,$01,$F0,$03,$01,$09,$FF,$CA,$25,$F4 - dc.b $E7,$E6,$01,$D0 dc.w $02F7,$002A,z80_ptr(-) dc.b $F2 ssamp3E: dc.b $3C,$00,$02,$44,$02,$1F,$1F,$1F,$15,$00,$00,$1F dc.b $00,$00,$00,$00,$00,$0F,$0F,$0F,$0F,$0D,$28,$00,$00 ; got continue Sound3F: dc.w z80_ptr(ssamp3F),$0103 dc.w $8002,z80_ptr(+),$F406 dc.w $8004,z80_ptr(++),$F406 dc.w $8005,z80_ptr(+++),$F406 + dc.b $EF,$00,$C9,$07,$CD,$D0,$CB,$CE,$D2,$CD,$D0,$D4,$CE,$D2,$D5 - dc.b $D0,$07,$D4,$D7,$E6 dc.w $05F7,$0008,z80_ptr(-) dc.b $F2 + dc.b $EF,$00,$E1,$01,$80,$07,$CD,$15,$CE,$D0,$D2 - dc.b $D4,$15,$E6 dc.w $05F7,$0008,z80_ptr(-) dc.b $F2 + dc.b $EF,$00,$E1,$01,$C9,$15,$CB,$CD,$CE - dc.b $D0,$15,$E6 dc.w $05F7,$0008,z80_ptr(-) dc.b $F2 ssamp3F: dc.b $14,$25,$36,$33,$11,$1F,$1F,$1F,$1F,$15,$1C,$18 dc.b $13,$0B,$0D,$08,$09,$0F,$8F,$9F,$0F,$24,$0A,$05,$80 ; short bonus ding Sound40: dc.w z80_ptr(ssamp3F),$0102 dc.w $8005,z80_ptr(++),$0008 dc.w $8004,z80_ptr(+),$0008 + dc.b $E1,$03,$80,$02 + dc.b $EF,$00,$C4,$16,$F2 ; badnik bust Sound41: dc.w z80_ptr(ssamp41),$0102 dc.w $8005,z80_ptr(+),$0000 dc.w $80C0,z80_ptr(++),$0002 + dc.b $F0,$03,$01,$72,$0B,$EF,$00,$BA,$16,$F2 + dc.b $F5,$01,$F3,$E7,$B0,$1B,$F2 ssamp41: dc.b $3C,$0F,$03,$01,$01,$1F,$1F,$1F,$1F,$19,$19,$12 dc.b $0E,$05,$00,$12,$0F,$0F,$FF,$7F,$FF,$00,$00,$80,$80 ; warning ding-ding Sound42: dc.w z80_ptr(ssamp3F),$0101 dc.w $8005,z80_ptr(+),$0C08 + dc.b $EF,$00,$BA,$08,$BA,$25,$F2 ; special stage ring flash (mostly unused) Sound43: dc.w z80_ptr(ssamp43),$0102 dc.w $8004,z80_ptr(+),$0C00 dc.w $8005,z80_ptr(++),$0013 + dc.b $EF,$01,$80,$01,$A2,$08,$EF,$00,$E7,$AD,$26,$F2 + dc.b $EF,$02,$F0,$06,$01,$03,$FF,$80,$0A - dc.b $C3 dc.w $06F7,$0005,z80_ptr(-) dc.b $C3,$17,$F2 ssamp43: dc.b $30,$30,$34,$5C,$30,$9E,$AC,$A8,$DC,$0E,$04,$0A dc.b $05,$08,$08,$08,$08,$BF,$BF,$BF,$BF,$24,$04,$1C,$80 dc.b $30,$30,$34,$5C,$30,$9E,$AC,$A8,$DC,$0E,$04,$0A dc.b $05,$08,$08,$08,$08,$BF,$BF,$BF,$BF,$24,$04,$2C,$80 dc.b $04,$37,$77,$72,$49,$1F,$1F,$1F,$1F,$07,$07,$0A dc.b $0D,$00,$00,$0B,$0B,$1F,$1F,$0F,$0F,$13,$13,$81,$88 ; thunk Sound44: dc.w z80_ptr(ssamp44),$0101 dc.w $8005,z80_ptr(+),$0000 + dc.b $EF,$00,$8A,$22,$F2 ssamp44: dc.b $FA,$21,$10,$30,$32,$1F,$1F,$1F,$1F,$05,$05,$18 dc.b $10,$0B,$10,$1F,$10,$1F,$4F,$2F,$2F,$0D,$04,$07,$80 ; cha-ching Sound45: dc.w z80_ptr(ssamp45),$0103 dc.w $8005,z80_ptr(+),$0000 dc.w $8004,z80_ptr(++),$0000 dc.w $80C0,z80_ptr(+++),$0000 + dc.b $EF,$00,$8A,$08,$80,$02,$8A,$08,$F2 + dc.b $EF,$01,$80,$12,$C6,$55,$F2 + dc.b $F5,$02,$F3,$E7,$80,$02,$C2,$05,$C4,$04,$C2,$05,$C4,$04,$F2 ssamp45: dc.b $3B,$03,$02,$02,$06,$18,$1A,$1A,$96,$17,$0A,$0E dc.b $10,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$00,$39,$28,$80 ringsamp: dc.b $04,$37,$77,$72,$49,$1F,$1F,$1F,$1F,$07,$07,$0A dc.b $0D,$00,$00,$0B,$0B,$1F,$1F,$0F,$0F,$23,$23,$80,$80 ; losing rings (scatter) Sound46: dc.w z80_ptr(ringsamp),$0102 dc.w $8004,z80_ptr(+),$0005 dc.w $8005,z80_ptr(++),$0008 + dc.b $EF,$00,$C6,$02,$05,$05,$05,$05,$05,$05,$3A,$F2 + dc.b $EF,$00,$80,$02,$C4,$02,$05,$15,$02,$05,$32,$F2 ; chain pull chink-chink (unused) Sound47: dc.w z80_ptr(ssamp47),$0101 dc.w $8005,z80_ptr(+),$0000 + dc.b $EF,$00,$BE,$05,$80,$04,$BE,$04,$80,$04,$F2 ssamp47: dc.b $28,$2F,$37,$5F,$2B,$1F,$1F,$1F,$1F,$15,$15,$15 dc.b $13,$13,$0D,$0C,$10,$2F,$3F,$2F,$2F,$00,$1F,$10,$80 ; flamethrower Sound48: dc.w $0000,$0101 dc.w $80C0,z80_ptr(+),$0000 + dc.b $F5,$00,$F3,$E7,$A7,$25,$F2 ; bonus pwoieeew (mostly unused) Sound49: dc.w z80_ptr(ssamp49),$0101 dc.w $8005,z80_ptr(+),$0E00 + dc.b $EF,$00,$F0,$01,$01,$33,$18,$B9,$1A,$F2 ssamp49: dc.b $3B,$0A,$05,$31,$02,$5F,$5F,$5F,$5F,$04,$16,$14 dc.b $0C,$00,$00,$04,$00,$1F,$D8,$6F,$FF,$03,$00,$25,$80 ; special stage entry Sound4A: dc.w z80_ptr(ssamp4A),$0101 dc.w $8005,z80_ptr(+),$0002 + dc.b $EF,$00,$F0,$01,$01,$5B,$02,$CC,$65,$F2 ssamp4A: dc.b $20,$36,$30,$35,$31,$41,$3B,$49,$4B,$09,$09,$06 dc.b $08,$01,$02,$03,$A9,$0F,$0F,$0F,$0F,$29,$23,$27,$80 ; slower smash/crumble Sound4B: dc.w z80_ptr(smashsamp),$0102 dc.w $8005,z80_ptr(+),$0000 dc.w $80C0,z80_ptr(++),$0000 + dc.b $EF,$00,$F0,$03,$01,$20,$04 - dc.b $81,$18,$E6 dc.w $0AF7,$0006,z80_ptr(-) dc.b $F2 + dc.b $F0,$01,$01,$0F,$05,$F3,$E7 - dc.b $B0,$18,$E7,$EC dc.w $03F7,$0005,z80_ptr(-) dc.b $F2 ; spring boing Sound4C: dc.w z80_ptr(ssamp4C),$0101 dc.w $8004,z80_ptr(+),$0002 + dc.b $EF,$00,$80,$01,$F0,$03,$01,$5D,$0F,$B0,$0C,$F4 - dc.b $E7,$E6,$02,$BD dc.w $02F7,$0019,z80_ptr(-) dc.b $F2 ssamp4C: dc.b $20,$36,$30,$35,$31,$DF,$9F,$DF,$9F,$07,$09,$06 dc.b $06,$07,$06,$06,$08,$2F,$1F,$1F,$FF,$16,$13,$30,$80 ; selection blip Sound4D: dc.w $0000,$0101 dc.w $80C0,z80_ptr(+),$0000 + dc.b $BB,$02,$F2 ; another ring sound (only plays in the left speaker?) Sound4E: dc.w z80_ptr(ringsamp),$0101 dc.w $8004,z80_ptr(+),$0005 + dc.b $EF,$00,$E0,$80,$C1,$04,$C4,$05,$C9,$1B,$F2 ; signpost spin sound Sound4F: dc.w z80_ptr(ssamp4F),$0102 dc.w $8004,z80_ptr(+),$2703 dc.w $8005,z80_ptr(++),$2700 + dc.b $80,$04 + dc.b $EF,$00 - dc.b $B4,$05,$E6 dc.w $02F7,$0015,z80_ptr(-) dc.b $F2 ssamp4F: dc.b $F4,$06,$0F,$04,$0E,$1F,$1F,$1F,$1F,$00,$0B,$00 dc.b $0B,$00,$05,$00,$08,$0F,$FF,$0F,$FF,$0C,$03,$8B,$80 ; mosquito zapper Sound50: dc.w z80_ptr(ssamp50),$0101 dc.w $8005,z80_ptr(+),$F400 + dc.b $EF,$00,$B3,$04,$80,$01 - dc.b $B4,$04,$80 dc.w $01F7,$0004,z80_ptr(-) dc.b $F2 ssamp50: dc.b $83,$12,$13,$10,$1E,$1F,$1F,$1F,$1F,$00,$00,$00 dc.b $00,$02,$02,$02,$02,$2F,$FF,$2F,$3F,$06,$34,$10,$87 ; (unused) Sound51: dc.w z80_ptr(ssamp51),$0102 dc.w $80C0,z80_ptr(+),$0001 dc.w $8005,z80_ptr(++),$000B + dc.b $F5,$02,$F3,$E4,$B0,$04,$85,$02,$F2 + dc.b $EF,$00,$E8,$04,$A5,$06,$F2 ssamp51: dc.b $3C,$02,$01,$00,$01,$1F,$1F,$1F,$1F,$00,$19,$0E dc.b $10,$00,$00,$0C,$0F,$0F,$FF,$EF,$FF,$05,$00,$80,$80 ; (unused) Sound52: dc.w z80_ptr(ssamp52),$0101 dc.w $8005,z80_ptr(+),$0002 + dc.b $F0,$01,$01,$2A,$07,$EF,$00 - dc.b $A5,$03 dc.w $E7F7,$0013,z80_ptr(-) - dc.b $A5,$03,$E7,$E6 dc.w $02F7,$0013,z80_ptr(-) dc.b $F2 ssamp52: dc.b $28,$21,$21,$21,$30,$1F,$1F,$1F,$1F,$00,$00,$00 dc.b $00,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$29,$20,$29,$80 Sound53: dc.w z80_ptr(ssamp53),$0101 dc.w $8005,z80_ptr(+),$F503 + dc.b $EF,$00,$F0,$01,$01,$46,$09,$A7,$14,$E7,$14,$E7,$E6,$04 dc.b $14,$E7,$E6,$04,$14,$E7,$E6,$04,$0A,$E7,$E6,$04,$0A,$F2 ssamp53: dc.b $07,$0A,$0C,$0C,$0C,$1F,$1F,$1F,$1F,$00,$00,$00 dc.b $00,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$2A,$0F,$0F,$80 ; OOZ lid pop sound Sound54: dc.w z80_ptr(ssamp54),$0102 dc.w $8005,z80_ptr(+),$0000 dc.w $80C0,z80_ptr(++),$0006 + dc.b $EF,$00,$B6,$15,$F2 + dc.b $F3,$E7,$F5,$04,$C6,$03,$E7,$C5,$E7 dc.b $C4,$E7,$C3,$E7,$C2,$E7,$C1,$E7,$C0,$F2 ssamp54: dc.b $07,$03,$02,$03,$00,$FF,$6F,$6F,$3F,$12,$14,$11 dc.b $0E,$1A,$0A,$03,$0D,$FF,$FF,$FF,$FF,$03,$07,$07,$80 Sound55: dc.w z80_ptr(ssamp55),$0101 dc.w $8005,z80_ptr(+),$0000 + dc.b $EF,$00,$AA,$07,$B6,$15,$F2 ssamp55: dc.b $42,$20,$0E,$0F,$0F,$1F,$1F,$1F,$1F,$1F,$1F,$1F dc.b $1F,$0F,$0E,$0F,$0E,$0F,$0F,$0F,$0F,$2E,$80,$20,$80 Sound56: dc.w z80_ptr(ssamp56),$0101 dc.w $8005,z80_ptr(+),$100E + dc.b $EF,$00,$F0,$01,$01,$1E,$FF,$8F,$1C,$F4 - dc.b $E7,$9A dc.w $05F7,$0009,z80_ptr(-) - dc.b $E7,$9A,$04,$E6,$02,$E7,$9A,$04,$E6 dc.w $02F7,$0008,z80_ptr(-) dc.b $F2 ssamp56: dc.b $0D,$06,$00,$00,$E5,$1F,$1F,$1F,$1F,$00,$00,$00 dc.b $00,$00,$00,$00,$00,$0F,$0F,$0F,$0F,$27,$80,$80,$80 Sound57: dc.w z80_ptr(ssamp57),$0101 dc.w $8005,z80_ptr(+),$0000 + dc.b $EF,$00,$CA,$15,$F2 ssamp57: dc.b $04,$09,$70,$00,$30,$1C,$1F,$DF,$1F,$15,$12,$0B dc.b $0F,$0C,$0D,$00,$0D,$07,$2F,$FA,$FA,$00,$29,$00,$00 ; CNZ bonusy bumper sound Sound58: dc.w z80_ptr(ssamp58),$0101 dc.w $8005,z80_ptr(+),$0007 + dc.b $EF,$00,$B3,$06,$B3,$15,$F2 ssamp58: dc.b $3C,$05,$0A,$01,$01,$56,$5C,$5C,$5C,$0E,$11,$11 dc.b $11,$09,$06,$0A,$0A,$4F,$3F,$3F,$3F,$17,$20,$80,$80 ; CNZ baaang bumper sound Sound59: dc.w z80_ptr(ssamp59),$0103 dc.w $8004,z80_ptr(+),$0000 dc.w $8002,z80_ptr(++),$0002 dc.w $8005,z80_ptr(+++),$0000 + dc.b $EF,$00,$E1,$0C,$B5,$14,$F2 + dc.b $EF,$01,$9A,$03,$F2 + dc.b $EF,$00,$B6,$14,$F2 ssamp59: dc.b $32,$30,$30,$40,$70,$1F,$1F,$1F,$1F,$12,$0A,$01 dc.b $0D,$00,$01,$01,$0C,$00,$23,$C3,$F6,$08,$07,$1C,$03 dc.b $05,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$12,$0C,$0C dc.b $0C,$12,$08,$08,$08,$1F,$5F,$5F,$5F,$07,$80,$80,$80 ; CNZ gloop / water droplet sound Sound5A: dc.w z80_ptr(ssamp5A),$0101 dc.w $8005,z80_ptr(+),$0000 + dc.b $EF,$00,$F0,$01,$01,$7F,$F1,$AA,$0A,$F2 ssamp5A: dc.b $47,$03,$02,$02,$04,$5F,$5F,$5F,$5F,$0E,$1A,$11 dc.b $0A,$09,$0A,$0A,$0A,$4F,$3F,$3F,$3F,$7F,$80,$80,$A3 Sound5B: dc.w z80_ptr(ssamp5B),$0101 dc.w $8005,z80_ptr(+),$0000 + dc.b $EF,$00,$80,$02,$A5,$01,$E7 - dc.b $01,$E7,$E6 dc.w $02F7,$0005,z80_ptr(-) dc.b $F2 ssamp5B: dc.b $38,$0F,$0F,$0F,$0F,$1F,$1F,$1F,$0E,$00,$00,$00 dc.b $00,$00,$00,$00,$00,$0F,$0F,$0F,$1F,$00,$00,$00,$80 Sound5C: dc.w z80_ptr(ssamp5C),$0102 dc.w $8004,z80_ptr(+),$000E dc.w $80C0,z80_ptr(++),$0000 + dc.b $EF,$00,$85,$40 - dc.b $E7,$04,$E6 dc.w $04F7,$000A,z80_ptr(-) dc.b $F2 + dc.b $F5,$00,$F3,$E7,$A7,$40 - dc.b $E7,$08,$E6 dc.w $01F7,$0005,z80_ptr(-) dc.b $F2 ssamp5C: dc.b $FA,$12,$01,$01,$01,$1F,$1F,$1F,$1F,$00,$00,$00 dc.b $00,$00,$00,$00,$00,$0F,$0F,$0F,$0F,$81,$8E,$14,$80 ; chain clink Sound5D: dc.w z80_ptr(ssamp5D),$0101 dc.w $8005,z80_ptr(+),$0000 + dc.b $EF,$00,$C0,$04,$F2 ssamp5D: dc.b $28,$2F,$37,$5F,$2B,$1F,$1F,$1F,$1F,$15,$15,$15 dc.b $13,$13,$0D,$0C,$10,$2F,$3F,$2F,$2F,$00,$1F,$10,$80 ; helicopter Sound5E: dc.w z80_ptr(ssamp5E),$0101 dc.w $8002,z80_ptr(+),$1405 + dc.b $EF,$00 - dc.b $95,$02,$95 dc.w $01F7,$0013,z80_ptr(-) - dc.b $95,$02,$95,$01,$E6 dc.w $01F7,$001B,z80_ptr(-) dc.b $F2 ssamp5E: dc.b $35,$30,$44,$40,$51,$1F,$1F,$1F,$1F,$10,$00,$13 dc.b $15,$1F,$00,$1F,$1A,$7F,$0F,$7F,$5F,$02,$A8,$80,$80 Sound5F: dc.w z80_ptr(ssamp5F),$0103 dc.w $8005,z80_ptr(s5Fs1),$0000 dc.w $80C0,z80_ptr(s5Fs2),$0000 dc.w $80A0,z80_ptr(s5Fs3),$0000 s5Fs1 dc.b $EF,$00,$F0,$01,$01,$C5,$1A,$CD,$07,$E6,$0A,$80 dc.b $06,$EF,$01,$F0,$01,$01,$11,$FF,$A2,$28 - dc.b $E7,$03,$E6 dc.w $03F7,$0005,z80_ptr(-) dc.b $F2 s5Fs2 dc.b $80,$07,$F0,$01,$02,$05,$FF,$F3,$E7,$BB,$1D - dc.b $E7,$07,$EC dc.w $01F7,$0010,z80_ptr(-) dc.b $F2 s5Fs3 dc.b $80,$16,$F5,$03 - dc.b $BF,$04,$C1,$C3,$EC,$01,$E9 dc.w $FFF7,$0005,z80_ptr(-) - dc.b $BF,$04,$C1,$C3,$EC,$01,$E9 dc.w $01F7,$0007,z80_ptr(-) dc.b $F2 ssamp5F: dc.b $FD,$09,$00,$03,$00,$1F,$1F,$1F,$1F,$10,$0C,$0C dc.b $0C,$0B,$10,$1F,$05,$1F,$4F,$2F,$2F,$09,$92,$84,$8E dc.b $3A,$70,$30,$04,$01,$0F,$14,$19,$16,$08,$0A,$0B dc.b $05,$03,$03,$03,$05,$1F,$6F,$8F,$5F,$1F,$22,$1F,$80 ; spindash charge Sound60: dc.w z80_ptr(ssamp60),$0101 dc.w $8005,z80_ptr(+),$FE00 + dc.b $EF,$00,$F0,$00,$01,$20,$F6,$C4,$16,$E7,$F4,$D0,$18,$E7 - dc.b $04,$E7,$E6 dc.w $03F7,$0010,z80_ptr(-) dc.b $F2 ssamp60: dc.b $34,$00,$03,$0C,$09,$9F,$8C,$8F,$95,$00,$00,$00 dc.b $00,$00,$00,$00,$00,$0F,$0F,$0F,$0F,$00,$1D,$00,$00 ; rumbling Sound61: dc.w z80_ptr(ssamp61),$0101 dc.w $8004,z80_ptr(+),$0004 + dc.b $80,$01,$EF,$00,$F0,$00,$01,$70,$06,$82,$06,$85,$08,$83 dc.b $01,$82,$05,$86,$06,$89,$03,$82,$08,$88,$04,$82,$06,$E6 dc.b $02,$85,$08,$E6,$02,$83,$01,$E6,$02,$82,$05,$E6,$02,$86 dc.b $06,$E6,$02,$89,$03,$E6,$02,$82,$08,$E6,$02,$88,$04,$E6,$02,$F2 ssamp61: dc.b $32,$30,$30,$50,$30,$1F,$0E,$19,$0E,$07,$12,$15 dc.b $09,$0A,$09,$1D,$06,$E8,$03,$0A,$17,$07,$00,$00,$00 Sound62: dc.w z80_ptr(ssamp62),$0101 dc.w $8005,z80_ptr(+),$FF00 + dc.b $EF,$00,$A6,$05,$F0,$01,$01,$E7,$40 - dc.b $C4,$02,$E7,$E6 dc.w $01F7,$0012,z80_ptr(-) dc.b $F2 ssamp62: dc.b $34,$0C,$10,$73,$0C,$AF,$AC,$FF,$D5,$06,$00,$02 dc.b $01,$02,$0A,$04,$08,$BF,$BF,$BF,$BF,$00,$08,$80,$80 ; CNZ blooing bumper Sound63: dc.w z80_ptr(ssamp63),$0101 dc.w $8005,z80_ptr(+),$0907 + dc.b $EF,$00,$F0,$01,$01,$04,$56,$92,$03,$9A,$25,$F2 ssamp63: dc.b $3D,$12,$10,$77,$30,$5F,$5F,$5F,$5F,$0F,$0A,$00 dc.b $01,$0A,$0A,$0D,$0D,$4F,$0F,$0F,$0F,$13,$80,$80,$80 ; HTZ track click sound Sound64: dc.w z80_ptr(ssamp64),$0101 dc.w $8005,z80_ptr(+),$1100 + dc.b $EF,$00,$C7,$02,$F2 ssamp64: dc.b $24,$2A,$02,$05,$01,$1A,$1F,$10,$1F,$0F,$1F,$1F dc.b $1F,$0C,$0D,$11,$11,$0C,$09,$09,$0F,$0E,$04,$80,$80 ; kicking up leaves sound Sound65: dc.w z80_ptr(ssamp65),$0101 dc.w $80C0,z80_ptr(+),$F800 + dc.b $F5,$03,$F3,$E7,$CE,$03,$F5,$06,$CE,$04,$EC dc.b $02,$CE,$02,$F5,$03,$EC,$FE,$CE,$08,$CE,$18,$F2 ssamp65: ; uhm... apparently they forgot to null out the pointer to here. ; luckily, sound 65 doesn't really use its sample ; leaf splash? Sound66: dc.w z80_ptr(ssamp66),$0102 dc.w $8005,z80_ptr(++),$EE08 dc.w $80C0,z80_ptr(+),$0000 + dc.b $F3,$E7,$F5,$09,$C6,$36,$F2 + dc.b $EF,$00,$80,$01,$92,$02,$02,$02,$30,$F2 ssamp66: dc.b $32,$33,$17,$34,$13,$0F,$0D,$1B,$17,$00,$04,$02 dc.b $0B,$08,$00,$08,$09,$6F,$5F,$4F,$6F,$05,$00,$00,$80 Sound67: dc.w z80_ptr(ssamp67),$0101 dc.w $80C0,z80_ptr(+),$0000 + dc.b $F5,$06,$F3,$E7,$90,$0A,$94,$0A,$98,$0A,$9C dc.b $0A,$A0,$0A,$A4,$08,$A8,$08,$AC,$08,$B0,$08,$F2 ssamp67: ; another not-really-used sample (like Sound65) ; door slamming quickly (unused) Sound68: dc.w z80_ptr(ssamp68),$0101 dc.w $8005,z80_ptr(+),$F400 + dc.b $EF,$00,$9B,$04,$A5,$06,$F2 ssamp68: dc.b $3C,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$00,$0F,$16 dc.b $0F,$00,$00,$00,$00,$0F,$FF,$AF,$FF,$00,$0A,$80,$80 Sound69: dc.w z80_ptr(ssamp69),$0102 dc.w $8005,z80_ptr(+),$F400 dc.w $80C0,z80_ptr(++),$0000 + dc.b $EF,$00,$9B,$03,$A8,$06,$9E,$08,$F2 + dc.b $F5,$04,$F3,$E7,$C6,$03,$C6,$06,$C6,$08,$F2 ssamp69: dc.b $3C,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$00,$0F,$16 dc.b $0F,$00,$00,$00,$00,$0F,$FF,$AF,$FF,$00,$0A,$80,$80 ; robotic laser burst Sound6A: dc.w z80_ptr(ssamp6A),$0101 dc.w $8005,z80_ptr(+),$0004 + dc.b $EF,$00,$DF,$14,$E6,$18,$06,$F2 ssamp6A: dc.b $3D,$09,$34,$34,$28,$1F,$16,$16,$16,$00,$00,$00 dc.b $04,$00,$00,$00,$00,$0F,$0F,$0F,$0F,$15,$02,$02,$00 ; scatter Sound6B: dc.w z80_ptr(ssamp6B),$0101 dc.w $8004,z80_ptr(+),$0002 + dc.b $EF,$00,$81,$04,$80,$0C,$F2 ssamp6B: dc.b $3A,$30,$30,$40,$70,$1F,$1F,$1F,$1F,$12,$0A,$01 dc.b $07,$00,$01,$01,$03,$00,$23,$C3,$46,$08,$07,$1C,$03 Sound6C: dc.w z80_ptr(ssamp6C),$0104 dc.w $8005,z80_ptr(++),$0010 dc.w $8004,z80_ptr(+),$0010 dc.w $80C0,z80_ptr(s5Fs2),$0000 dc.w $80A0,z80_ptr(s5Fs3),$0000 + dc.b $E1,$10 + dc.b $EF,$01,$F0,$01,$01,$EC,$56,$C0,$24,$F4,$EF,$00,$E6,$F0 - dc.b $BB,$02,$E7,$E6,$02,$E9 dc.w $01F7,$0020,z80_ptr(-) dc.b $F2 ssamp6C: dc.b $00,$53,$30,$03,$30,$1F,$1F,$1F,$1F,$00,$00,$00 dc.b $00,$00,$00,$00,$00,$00,$00,$00,$0F,$0F,$06,$23,$80 dc.b $3C,$72,$32,$32,$72,$14,$14,$0F,$0F,$00,$00,$00 dc.b $00,$00,$00,$00,$00,$02,$02,$08,$08,$35,$14,$00,$00 ; error sound Sound6D: dc.w z80_ptr(ssamp6D),$0101 dc.w $8005,z80_ptr(+),$0004 + dc.b $EF,$00,$B0,$06,$80,$06,$B0,$18,$F2 ssamp6D: dc.b $38,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$00,$00,$00 dc.b $00,$00,$00,$00,$00,$0F,$0F,$0F,$0F,$1F,$0C,$17,$00 ; silver sonic buzz saw Sound6E: dc.w z80_ptr(ssamp6E),$0102 dc.w $8005,z80_ptr(+),$0000 dc.w $80C0,z80_ptr(++),$0000 + dc.b $EF,$00,$C6,$24,$E7 - dc.b $C6,$04,$E7,$E6 dc.w $04F7,$0008,z80_ptr(-) dc.b $F2 + dc.b $F3,$E7,$C7,$44,$F2 ssamp6E: dc.b $33,$00,$10,$00,$31,$1F,$1D,$1E,$0E,$00,$0C,$1D dc.b $00,$00,$00,$01,$00,$0F,$0F,$0F,$0F,$08,$06,$07,$80 Sound6F: dc.w z80_ptr(ssamp6A),$0103 dc.w $8005,z80_ptr(++),$000B dc.w $8004,z80_ptr(+),$0012 dc.w $80C0,z80_ptr(+++),$0000 + dc.b $E1,$02,$80,$02 + dc.b $EF,$00,$E6,$0C,$DF,$06,$E7,$E6,$F4,$06,$E7 dc.b $E6,$F4,$12,$E7,$E6,$0C,$06,$E7,$E6,$0C,$06,$F2 + dc.b $F3,$E7,$C6,$04,$C0,$BA,$B4,$AE,$E6 dc.b $01,$AE,$E6,$01,$AE,$E6,$01,$AE,$F2 Sound70: dc.w $0000,$0101 dc.w $80C0,z80_ptr(+),$0000 + dc.b $F3,$E7,$C6,$18 - dc.b $E7,$03,$E6 dc.w $01F7,$0008,z80_ptr(-) dc.b $F2 finishBank ; end of 'ROM' if padToPowerOfTwo && (*)&(*-1) cnop -1,2<