; ; --------------------------------------------------------------------------- ; ║ This file is generated by The Interactive Disassembler (IDA) ║ ; ║ Copyright (c) 2003 by DataRescue sa/nv, ║ ; ║ Licensed to: Michael Wolski - Personal Use (1-user Standard 07/2003) ║ ; --------------------------------------------------------------------------- ; ; File Name : C:\SKDisasm\SONICNUC.BIN ; Format : Binary File ; Base Address: 0000h Range: 0000h - 200000h Loaded length: 200000h ; ; 2006-12-31 - Original buildable disassembly, labeling, and formatting by Stealth ; Please list any revisions ; Processor: 68000 ; Target Assembler: 680x0 Assembler in MRI compatible mode ; This file should be compiled with "as -M" ; --------------------------------------------------------------------------- cpu 68000 include "sonic3k.macrosetup.asm" ; include a few basic macros include "sonic3k.macros.asm" ; include some simplifying macros and functions include "sonic3k.constants.asm" ; include some constants ; --------------------------------------------------------------------------- ; Include SMPS2ASM, for expressing SMPS bytecode in a portable and human-readable form. FixMusicAndSFXDataBugs = 0 SonicDriverVer = 4 ; Tell SMPS2ASM that we are targetting Sonic & Knuckles' sound driver include "Sound/_smps2asm_inc.asm" ; --------------------------------------------------------------------------- ; Assembly options: ; 'Sonic3_Complete' is set via build scripts to 0 or 1. ; If 1, includes all required Sonic 3 data in order to assemble a smaller version of S3K (with all redundancies removed) strip_padding = 0|Sonic3_Complete ; If 1, strips all unnecessary padding Size_of_Snd_driver_guess = $E00 Size_of_Snd_driver2_guess = $690 ; Approximate size of compressed sound driver. Change when appropriate Size_of_Snd_Bank1 = $3EFC ; This particular bank has its contents aligned to the end ; --------------------------------------------------------------------------- StartOfROM: if * <> 0 fatal "StartOfROM was $\{*} but it should be 0" endif Vectors: dc.l $00000000, EntryPoint, ErrorTrap, ErrorTrap ; 0 dc.l ErrorTrap, ErrorTrap, 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 H_int_jump, ErrorTrap, V_int_jump, ErrorTrap ; 28 dc.l ErrorTrap, ErrorTrap, ErrorTrap, 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 Header: dc.b "SEGA GENESIS " Copyright: dc.b "(C)SEGA 1994.JUN" Domestic_Name: dc.b "SONIC & KNUCKLES " Overseas_Name: dc.b "SONIC & KNUCKLES " Serial_Number: dc.b "GM MK-1563 -00" Checksum: dc.w $DFB3 Input: dc.b "J " ROMStartLoc: dc.l StartOfROM ROMEndLoc: dc.l EndOfROM-1 RAMStartLoc: dc.l (RAM_start&$FFFFFF) RAMEndLoc: dc.l (RAM_start&$FFFFFF)+$FFFF if Sonic3_Complete CartRAM_Info: dc.b "RA" CartRAM_Type: dc.w %1111100000100000 CartRAMStartLoc:dc.l $00200001 CartRAMEndLoc: dc.l $002003FF else CartRAM_Info: dc.b " " CartRAM_Type: dc.w %10000000100000 CartRAMStartLoc:dc.b " " CartRAMEndLoc: dc.b " " endif Modem_Info: dc.b " " dc.b " " Unknown_Header: dc.w 0 dc.b " " dc.w 0, 0 dc.l EndOfROM-1 ; 0 ;CHECKLATER (ROM Bank Info) dc.b " " KiS2ROM_Info: dc.b "RO" KiS2ROM_Type: dc.w %10000000100000 KiS2ROMStartLoc: tribyte $300000 KiS2ROMEndLoc: tribyte $33FFFF KiS2ROMStartLoc2: tribyte $300000 KiS2ROMEndLoc2: tribyte $33FFFF Country_Code: dc.b "JUE " ; --------------------------------------------------------------------------- ErrorTrap: nop nop nop ; --------------------------------------------------------------------------- EntryPoint: lea (System_stack).w,sp tst.l (HW_Port_1_Control-1).l bne.s + tst.w (HW_Expansion_Control-1).l + bne.s Init_SkipPowerOn ; in case of a soft reset 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 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 Init_VDPRegs: move.b (a5)+,d5 move.w d5,(a4) add.w d7,d5 dbf d1,Init_VDPRegs ; set all 24 registers 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 WaitForZ80: btst d0,(a1) ; has the Z80 stopped? bne.s WaitForZ80 ; if not, branch moveq #Z80StartupCodeEnd-Z80StartupCodeBegin-1,d2 Init_SoundRAM: move.b (a5)+,(a0)+ dbf d2,Init_SoundRAM move.w d0,(a2) move.w d0,(a1) ; start the Z80 move.w d7,(a2) ; reset the Z80 Init_ClearRAM: move.l d0,-(a6) ; Clear normal RAM dbf d6,Init_ClearRAM move.l (a5)+,(a4) ; set VDP display mode and increment move.l (a5)+,(a4) ; set VDP to CRAM write moveq #bytesToLcnt($80),d3 Init_ClearCRAM: move.l d0,(a3) ; Clear CRAM dbf d3,Init_ClearCRAM move.l (a5)+,(a4) moveq #bytesToLcnt($50),d4 Init_ClearVSRAM: move.l d0,(a3) ; Clear VSRAM dbf d4,Init_ClearVSRAM moveq #PSGInitValues_End-PSGInitValues-1,d5 Init_InputPSG: move.b (a5)+,PSG_input-VDP_data_port(a3) ; reset the PSG dbf d5,Init_InputPSG move.w d0,(a2) movem.l (a6),d0-a6 ; clear all registers move #$2700,sr ; set the sr Init_SkipPowerOn: bra.s Test_LockOn ; --------------------------------------------------------------------------- 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 ; values for VDP registers VDPInitValues: 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 $9700 - 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: 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... 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: ; --------------------------------------------------------------------------- Test_LockOn: tst.w (VDP_control_port).l move.w #$4EF9,(V_int_jump).w ; machine code for jmp move.l #VInt,(V_int_addr).w move.w #$4EF9,(H_int_jump).w move.l #HInt,(H_int_addr).w - move.w (VDP_control_port).l,d1 btst #1,d1 bne.s - ; wait till a DMA is completed lea ((RAM_start&$FFFFFF)).l,a6 moveq #0,d7 move.w #bytesToLcnt($FE00),d6 - move.l d7,(a6)+ dbf d6,- if Sonic3_Complete moveq #0,d1 bra.s SonicAndKnucklesStartup else move.b #0,(SRAM_access_flag).l ; disable SRAM access lea (SegaHeadersText).l,a1 moveq #1,d4 ; test for both MEGA DRIVE and GENESIS Test_SystemString: lea (LockonHeader).l,a0 moveq #0,d3 moveq #$10-1,d2 $$compareChars: move.b (a1)+,d0 cmp.b (a0)+,d0 beq.s $$matchingChar moveq #1,d3 $$matchingChar: dbf d2,$$compareChars tst.b d3 beq.s DetermineWhichGame dbf d4,Test_SystemString moveq #-1,d1 move.l (SegaHeadersText).l,d0 ; test to see if SEGA is at the locked on ROM's $100 cmp.l (LockonHeader).l,d0 bne.w SonicAndKnucklesStartup DetermineWhichGame: lea (LockonSerialsText).l,a1 moveq #3,d1 ; 3 Sonic 2 headers, 1 Sonic 3 header $$compareSerials: lea (LockonSerialNumber).l,a0 moveq #0,d3 moveq #$E-1,d2 $$compareChars: move.b (a1)+,d0 cmp.b (a0)+,d0 beq.s $$matchingChar moveq #1,d3 $$matchingChar: dbf d2,$$compareChars tst.b d3 beq.s S2orS3LockedOn dbf d1,$$compareSerials bra.s BlueSpheresStartup ; --------------------------------------------------------------------------- S2orS3LockedOn: tst.w d1 beq.w SonicAndKnucklesStartup move.b #1,(SRAM_access_flag).l jmp ($300000).l ; May be changed at a later date to become compatible with S2K disassembly ; --------------------------------------------------------------------------- LockonSerialsText: dc.b "GM 00001051-00" ; Sonic 2 REV00/1/2 dc.b "GM 00001051-01" dc.b "GM 00001051-02" dc.b "GM MK-1079 -00" ; Sonic 3 SegaHeadersText: dc.b "SEGA MEGA DRIVE " dc.b "SEGA GENESIS " ; --------------------------------------------------------------------------- BlueSpheresStartup: bsr.s Test_Checksum move.b d4,(Blue_spheres_header_flag).w bsr.w Init_VDP bsr.w SndDrvInit bsr.w Init_Controllers move.b #0,(Blue_spheres_menu_flag).w move.b #$2C,(Game_mode).w bra.w GameLoop endif ; --------------------------------------------------------------------------- ; Checksum testing subroutine ; The instructions to loop over the entire ROM and branch to the incorrect ; checksum routine have been NOPed out, so this is quite useless ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Test_Checksum: btst #6,(HW_Expansion_Control).l beq.s + cmpi.l #Ref_Checksum_String,(Checksum_string).w beq.w Test_Checksum_Done + movea.l #ErrorTrap,a6 move.l (ROMEndLoc).w,d6 moveq #0,d7 add.w (a6)+,d7 cmp.l a6,d6 nop nop cmp.w (Checksum).w,d7 nop nop lea (System_stack).w,a6 moveq #0,d7 move.w #bytesToLcnt($1F0),d6 - move.l d7,(a6)+ dbf d6,- ; clear RAM from $FFFE00 to $FFFFEF move.b (HW_Version).l,d6 andi.b #$C0,d6 move.b d6,(Graphics_flags).w move.l #Ref_Checksum_String,(Checksum_string).w Test_Checksum_Done: rts ; End of function Test_Checksum ; --------------------------------------------------------------------------- SonicAndKnucklesStartup: bsr.s Test_Checksum move.w d1,(SK_alone_flag).w bsr.w DetectPAL bsr.w Init_VDP bsr.w SndDrvInit bsr.w Init_Controllers jsr (SRAM_Load).l move.b #0,(Game_mode).w GameLoop: move.b (Game_mode).w,d0 andi.w #$7C,d0 movea.l GameModes(pc,d0.w),a0 jsr (a0) bra.s GameLoop ; --------------------------------------------------------------------------- GameModes: dc.l Sega_Screen ; 0 dc.l Title_Screen ; 4 dc.l Level ; 8 dc.l Level ; $C dc.l JumpToSegaScreen ; $10 dc.l ContinueScreen ; $14 dc.l JumpToSegaScreen ; $18 dc.l LevelSelect_S2Options ; $1C dc.l S3Credits ; $20 dc.l LevelSelect_S2Options ; $24 dc.l LevelSelect_S2Options ; $28 dc.l BlueSpheresTitle ; $2C dc.l BlueSpheresResults ; $30 dc.l SpecialStage ; $34 dc.l Competition_Menu ; $38 dc.l Competition_PlayerSelect ; $3C dc.l Competition_LevelSelect ; $40 dc.l Competition_Results ; $44 dc.l SpecialStage_Results ; $48 dc.l SaveScreen ; $4C dc.l TimeAttack_Records ; $50 ; --------------------------------------------------------------------------- JumpToSegaScreen: move.b #0,(Game_mode).w rts ; --------------------------------------------------------------------------- ; unused/dead code ; weird routine, makes the screen go haywire pretty much ChecksumError2: move.l d1,-(sp) bsr.w Init_VDP move.l (sp)+,d1 ChecksumError2_Loop: move.l #vdpComm($0000,CRAM,WRITE),(VDP_control_port).l move.w d7,(VDP_data_port).l addq.w #1,d7 bra.s ChecksumError2_Loop ; --------------------------------------------------------------------------- ; unused/dead code ChecksumError: move.l #vdpComm($0000,CRAM,WRITE),(VDP_control_port).l moveq #bytesToWcnt($80),d7 .loop: move.w #$E,(VDP_data_port).l dbf d7,.loop ; fill entire CRAM with red ChecksumError_Loop: bra.s ChecksumError_Loop ; =============== S U B R O U T I N E ======================================= DetectPAL: lea (VDP_control_port).l,a5 move.w #$8174,(a5) ; VDP Command $8174 - Display on, VInt on, DMA on, PAL off moveq #0,d0 $$waitForVBlankStart: move.w (a5),d1 andi.w #8,d1 beq.s $$waitForVBlankStart $$waitForVBlankEnd: move.w (a5),d1 andi.w #8,d1 bne.s $$waitForVBlankEnd ; Wait for VBlank to run once $$waitForNextVBlank: addq.w #1,d0 move.w (a5),d1 andi.w #8,d1 beq.s $$waitForNextVBlank move.w d0,(V_blank_cycles).w ; Count cycles between VBlanks (likely to detect PAL systems and/or for other timing mechanisms rts ; End of function DetectPAL ; --------------------------------------------------------------------------- ; Vertical interrupt handler ; --------------------------------------------------------------------------- VInt: nop movem.l d0-a6,-(sp) tst.b (V_int_routine).w beq.w VInt_0_Main - move.w (VDP_control_port).l,d0 andi.w #8,d0 beq.s - ; wait until vertical blanking is taking place move.l #vdpComm($0000,VSRAM,WRITE),(VDP_control_port).l move.l (V_scroll_value).w,(VDP_data_port).l btst #6,(Graphics_flags).w beq.s + ; branch if it's not a PAL system move.w #$700,d0 dbf d0,* ; otherwise, waste a bit of time here + move.b (V_int_routine).w,d0 move.b #0,(V_int_routine).w move.w #1,(H_int_flag).w ; Allow H Interrupt code to run andi.w #$3E,d0 move.w VInt_Table(pc,d0.w),d0 jsr VInt_Table(pc,d0.w) VInt_Done: addq.l #1,(V_int_run_count).w movem.l (sp)+,d0-a6 rte ; --------------------------------------------------------------------------- VInt_Table: dc.w VInt_0-VInt_Table dc.w VInt_2-VInt_Table dc.w VInt_4-VInt_Table dc.w VInt_6-VInt_Table dc.w VInt_8-VInt_Table dc.w VInt_A_C-VInt_Table dc.w VInt_A_C-VInt_Table dc.w VInt_E-VInt_Table dc.w VInt_10-VInt_Table dc.w VInt_12-VInt_Table dc.w VInt_14-VInt_Table dc.w VInt_16-VInt_Table dc.w VInt_18-VInt_Table dc.w VInt_1A-VInt_Table dc.w VInt_1C-VInt_Table dc.w VInt_1E-VInt_Table ; --------------------------------------------------------------------------- VInt_0: addq.w #4,sp VInt_0_Main: addq.w #1,(Lag_frame_count).w ; branch if a level or demo is running cmpi.b #$88,(Game_mode).w beq.s VInt_0_Level cmpi.b #$8C,(Game_mode).w beq.s VInt_0_Level cmpi.b #8,(Game_mode).w beq.s VInt_0_Level cmpi.b #$C,(Game_mode).w beq.s VInt_0_Level bra.s VInt_Done ; otherwise, return from V-int ; --------------------------------------------------------------------------- VInt_0_Level: tst.b (Water_flag).w beq.w VInt_0_NoWater move.w (VDP_control_port).l,d0 btst #6,(Graphics_flags).w beq.s + ; branch if it isn't a PAL system move.w #$700,d0 dbf d0,* ; otherwise waste a bit of time here + move.w #1,(H_int_flag).w stopZ80 tst.b (Water_full_screen_flag).w bne.s VInt_0_FullyUnderwater dma68kToVDP Normal_palette,$0000,$80,CRAM bra.s VInt_0_Water_Cont ; --------------------------------------------------------------------------- VInt_0_FullyUnderwater: dma68kToVDP Water_palette,$0000,$80,CRAM VInt_0_Water_Cont: move.w (H_int_counter_command).w,(a5) startZ80 bra.w VInt_Done ; --------------------------------------------------------------------------- VInt_0_NoWater: move.w (VDP_control_port).l,d0 btst #6,(Graphics_flags).w beq.s + ; branch if it isn't a PAL system move.w #$700,d0 dbf d0,* ; otherwise, waste a bit of time here + move.w #1,(H_int_flag).w move.w (H_int_counter_command).w,(VDP_control_port).l stopZ80 ; In Competition Mode, we have to update the sprite table ; even during a lag frame so that the top half of the screen ; shows the correct sprites. tst.w (Competition_mode).w beq.s VInt_0_Done ; Update V-Scroll. move.l #vdpComm($0000,VSRAM,WRITE),(VDP_control_port).l move.l (V_scroll_value).w,(VDP_data_port).l ; Unlike in Sonic 2, the sprite tables are page-flipped in two-player mode. ; This fixes a race-condition where incomplete sprite tables can be uploaded ; to the VDP on lag frames, causing corrupted sprites to appear. ; Upload the front buffer. tst.w (Current_sprite_table_page).w beq.s + dma68kToVDP Sprite_table,$F800,$280,VRAM bra.s VInt_0_Done + dma68kToVDP Sprite_table_alternate,$F800,$280,VRAM VInt_0_Done: startZ80 bra.w VInt_Done ; --------------------------------------------------------------------------- VInt_2: bsr.w Do_ControllerPal tst.w (Demo_timer).w beq.w + subq.w #1,(Demo_timer).w + rts ; --------------------------------------------------------------------------- VInt_14: move.b (V_int_run_count+3).w,d0 andi.w #$F,d0 bne.s + ; run the following code once every 16 frames stopZ80 bsr.w Poll_Controllers startZ80 + tst.w (Demo_timer).w beq.w + subq.w #1,(Demo_timer).w + jmp (Set_Kos_Bookmark).l ; --------------------------------------------------------------------------- VInt_4: bsr.w TitleAnim_FlipBuffer bsr.w Do_ControllerPal move.w (Ctrl_1).w,(Ctrl_1_title).w bsr.w Process_Nem_Queue tst.w (Demo_timer).w beq.w + subq.w #1,(Demo_timer).w + rts ; --------------------------------------------------------------------------- VInt_6: bsr.w Do_ControllerPal rts ; --------------------------------------------------------------------------- VInt_10: cmpi.b #$34,(Game_mode).w beq.w VInt_1C ; If in a special stage, branch VInt_8: stopZ80 bsr.w Poll_Controllers tst.b (Hyper_Sonic_flash_timer).w beq.s VInt_8_NoFlash ; flash screen white when Hyper Sonic's double jump move is used subq.b #1,(Hyper_Sonic_flash_timer).w lea (VDP_data_port).l,a6 move.l #vdpComm($0000,CRAM,WRITE),(VDP_control_port).l move.w #$EEE,d0 move.w #$20-1,d1 - move.w d0,(a6) dbf d1,- ; fill entire first and second palette lines with white move.w #0,(a6) ; keep backdrop black move.w #$1F-1,d1 - move.w d0,(a6) dbf d1,- ; fill remaining colours with white bra.s VInt_8_Cont ; --------------------------------------------------------------------------- VInt_8_NoFlash: tst.b (Water_full_screen_flag).w bne.s + dma68kToVDP Normal_palette,$0000,$80,CRAM bra.s ++ + dma68kToVDP Water_palette,$0000,$80,CRAM + move.w (H_int_counter_command).w,(a5) VInt_8_Cont: dma68kToVDP H_scroll_buffer,$F000,$380,VRAM tst.w (Competition_mode).w beq.s ++ ; Unlike in Sonic 2, the sprite tables are page-flipped in two-player mode. ; This fixes a race-condition where incomplete sprite tables can be uploaded ; to the VDP on lag frames, causing corrupted sprites to appear. ; Perform page-flipping. tst.w (Sprite_table_page_flip_pending).w beq.s + clr.w (Sprite_table_page_flip_pending).w eori.w #$FFFF,(Current_sprite_table_page).w ; a not.w would've accomplished the same thing ... + ; Upload the front buffer. tst.w (Current_sprite_table_page).w bne.s + dma68kToVDP Sprite_table_alternate,$F800,$280,VRAM bra.s ++ + dma68kToVDP Sprite_table,$F800,$280,VRAM + bsr.w Process_DMA_Queue move.l (V_scroll_value_P2).w,(V_scroll_value_P2_copy).w jsr (SpecialVInt_Function).l jsr (VInt_DrawLevel).l startZ80 move #$2300,sr tst.b (Water_flag).w beq.s + cmpi.b #92,(H_int_counter).w ; is H-int occuring on or below line 92? bhs.s + ; if it is, branch move.b #1,(Do_Updates_in_H_int).w jmp (Set_Kos_Bookmark).l + bsr.s Do_Updates jmp (Set_Kos_Bookmark).l ; =============== S U B R O U T I N E ======================================= Do_Updates: jsr (UpdateHUD).l move.w #0,(Lag_frame_count).w bsr.w Process_Nem_Queue_2 tst.w (Demo_timer).w beq.w + subq.w #1,(Demo_timer).w + rts ; End of function Do_Updates ; --------------------------------------------------------------------------- VInt_A_C: stopZ80 bsr.w Poll_Controllers tst.b (Water_full_screen_flag).w bne.s + dma68kToVDP Normal_palette,$0000,$80,CRAM bra.s ++ + dma68kToVDP Water_palette,$0000,$80,CRAM + move.w (H_int_counter_command).w,(a5) dma68kToVDP H_scroll_buffer,$F000,$380,VRAM tst.w (Competition_mode).w beq.s ++ ; Unlike in Sonic 2, the sprite tables are page-flipped in two-player mode. ; This fixes a race-condition where incomplete sprite tables can be uploaded ; to the VDP on lag frames, causing corrupted sprites to appear. ; Perform page-flipping. tst.w (Sprite_table_page_flip_pending).w beq.s + clr.w (Sprite_table_page_flip_pending).w eori.w #$FFFF,(Current_sprite_table_page).w ; a not.w would've accomplished the same thing... + ; Upload the front buffer. tst.w (Current_sprite_table_page).w bne.s + dma68kToVDP Sprite_table_alternate,$F800,$280,VRAM bra.s ++ + dma68kToVDP Sprite_table,$F800,$280,VRAM + bsr.w Process_DMA_Queue move.l (V_scroll_value_P2).w,(V_scroll_value_P2_copy).w startZ80 bsr.w Process_Nem_Queue jmp (Set_Kos_Bookmark).l ; --------------------------------------------------------------------------- VInt_E: bsr.w Do_ControllerPal move.b #$E,(V_int_routine).w rts ; --------------------------------------------------------------------------- VInt_12: bsr.w Do_ControllerPal move.w (H_int_counter_command).w,(a5) bra.w Process_Nem_Queue ; --------------------------------------------------------------------------- VInt_18: stopZ80 bsr.w Poll_Controllers dma68kToVDP Normal_palette,$0000,$80,CRAM dma68kToVDP Sprite_table,$F800,$280,VRAM dma68kToVDP H_scroll_buffer,$F000,$380,VRAM bclr #0,(_unkFA88).w beq.s + dma68kToVDP $FF2000,$C000,$2000,VRAM + bsr.w Process_DMA_Queue startZ80 rts ; --------------------------------------------------------------------------- VInt_16: stopZ80 bsr.w Poll_Controllers dma68kToVDP Normal_palette,$0000,$80,CRAM dma68kToVDP Sprite_table,$F800,$280,VRAM dma68kToVDP H_scroll_buffer,$F000,$380,VRAM bsr.w Process_DMA_Queue startZ80 bsr.w Process_Nem_Queue tst.w (Demo_timer).w beq.w + subq.w #1,(Demo_timer).w + jmp (Set_Kos_Bookmark).l ; --------------------------------------------------------------------------- VInt_1A: bsr.w Do_ControllerPal move.w (Ctrl_1).w,(Ctrl_1_title).w bsr.w Process_Nem_Queue tst.w (Demo_timer).w beq.w + subq.w #1,(Demo_timer).w + jmp (Set_Kos_Bookmark).l ; --------------------------------------------------------------------------- VInt_1C: bsr.w Rotate_SSPal bsr.w Do_ControllerPal bsr.w Update_SSMap tst.w (Demo_timer).w beq.w + subq.w #1,(Demo_timer).w + jmp (Set_Kos_Bookmark).l ; --------------------------------------------------------------------------- VInt_1E: bsr.s Do_ControllerPal movea.l (_unkEF44_1).w,a0 jsr (a0) bsr.w Process_Nem_Queue_2 jmp (Set_Kos_Bookmark).l ; =============== S U B R O U T I N E ======================================= Do_ControllerPal: stopZ80 bsr.w Poll_Controllers tst.b (Water_full_screen_flag).w bne.s + dma68kToVDP Normal_palette,$0000,$80,CRAM bra.s ++ + dma68kToVDP Water_palette,$0000,$80,CRAM + dma68kToVDP Sprite_table,$F800,$280,VRAM dma68kToVDP H_scroll_buffer,$F000,$380,VRAM bsr.w Process_DMA_Queue startZ80 rts ; End of function Do_ControllerPal ; --------------------------------------------------------------------------- ; Unused leftover from Sonic 3 JmpTo_HInt: jmp (H_int_jump).w ; --------------------------------------------------------------------------- ; Horizontal interrupt handler for Competition Mode ; --------------------------------------------------------------------------- HInt: tst.w (H_int_flag).w beq.w HInt_Done move.w #0,(H_int_flag).w move.l a5,-(sp) move.l d0,-(sp) - move.w (VDP_control_port).l,d0 andi.w #4,d0 ; is horizontal blanking occuring? beq.s - ; if not, wait until it is move.w (VDP_reg_1_command).w,d0 andi.b #$BF,d0 move.w d0,(VDP_control_port).l ; blank the display ; Update V-Scroll. move.l #vdpComm($0000,VSRAM,WRITE),(VDP_control_port).l move.l (V_scroll_value_P2_copy).w,(VDP_data_port).l stopZ80 ; Unlike in Sonic 2, the sprite tables are page-flipped in two-player mode. ; This fixes a race-condition where incomplete sprite tables can be uploaded ; to the VDP on lag frames, causing corrupted sprites to appear. ; Upload the front buffer. tst.w (Current_sprite_table_page).w beq.s + dma68kToVDP Sprite_table_P2,$F800,$280,VRAM bra.s ++ + dma68kToVDP Sprite_table_P2_alternate,$F800,$280,VRAM + startZ80 - move.w (VDP_control_port).l,d0 andi.w #4,d0 ; is a horizontal blank occuring? beq.s - ; if not, wait move.w (VDP_reg_1_command).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l ; enable display move.l (sp)+,d0 movea.l (sp)+,a5 HInt_Done: rte ; --------------------------------------------------------------------------- ; Used for water levels apart from Hydrocity, for uneven water surfaces ; --------------------------------------------------------------------------- HInt3: tst.w (H_int_flag).w beq.s HInt3_Done move.w #0,(H_int_flag).w movem.l d0-d1/a0-a2,-(sp) lea (VDP_data_port).l,a1 move.w #$8AFF,VDP_control_port-VDP_data_port(a1) ; Reset HInt timing stopZ80 movea.l (Water_palette_data_addr).w,a2 moveq #$C,d0 dbf d0,* ; waste a few cycles here move.w (a2)+,d1 move.b (H_int_counter).w,d0 subi.b #200,d0 ; is H-int occuring below line 200? bcs.s $$transferColors ; if it is, branch sub.b d0,d1 bcs.s $$skipTransfer $$transferColors: move.w (a2)+,d0 lea (Water_palette).w,a0 adda.w d0,a0 addi.w #$C000,d0 swap d0 move.l d0,VDP_control_port-VDP_data_port(a1) ; write to CRAM at appropriate address move.l (a0)+,(a1) ; transfer two colors move.w (a0)+,(a1) ; transfer the third color nop nop moveq #$24,d0 dbf d0,* ; waste some cycles dbf d1,$$transferColors ; repeat for number of colors $$skipTransfer: startZ80 movem.l (sp)+,d0-d1/a0-a2 tst.b (Do_Updates_in_H_int).w bne.s HInt3_Do_Updates HInt3_Done: rte ; --------------------------------------------------------------------------- HInt3_Do_Updates: clr.b (Do_Updates_in_H_int).w movem.l d0-a6,-(sp) jsr (Do_Updates).l movem.l (sp)+,d0-a6 rte ; --------------------------------------------------------------------------- ; Identical to HInt3 except it transfers colors from the above water palette ; Seems to be unused ; --------------------------------------------------------------------------- HInt5: tst.w (H_int_flag).w ; Seems to be a compliment to HInt 3, but doesn't seem to be used beq.s HInt5_Done move.w #0,(H_int_flag).w movem.l d0-d1/a0-a2,-(sp) lea (VDP_data_port).l,a1 move.w #$8AFF,VDP_control_port-VDP_data_port(a1) stopZ80 movea.l (Water_palette_data_addr).w,a2 moveq #$C,d0 dbf d0,* move.w (a2)+,d1 move.b (H_int_counter).w,d0 subi.b #200,d0 bcs.s $$transferColors sub.b d0,d1 bcs.s $$skipTransfer $$transferColors: move.w (a2)+,d0 lea (Normal_palette).w,a0 adda.w d0,a0 addi.w #$C000,d0 swap d0 move.l d0,VDP_control_port-VDP_data_port(a1) move.l (a0)+,(a1) move.w (a0)+,(a1) nop nop moveq #$24,d0 dbf d0,* ; waste some cycles dbf d1,$$transferColors $$skipTransfer: startZ80 movem.l (sp)+,d0-d1/a0-a2 tst.b (Do_Updates_in_H_int).w bne.s HInt5_Do_Updates HInt5_Done: rte ; --------------------------------------------------------------------------- HInt5_Do_Updates: clr.b (Do_Updates_in_H_int).w movem.l d0-a6,-(sp) jsr (Do_Updates).l movem.l (sp)+,d0-a6 rte ; --------------------------------------------------------------------------- ; Identical to HInt3, except for faster systems ; --------------------------------------------------------------------------- HInt4: tst.w (H_int_flag).w beq.s Hint4_Done move.w #0,(H_int_flag).w movem.l d0-d1/a0-a2,-(sp) lea (VDP_data_port).l,a1 move.w #$8AFF,VDP_control_port-VDP_data_port(a1) stopZ80 movea.l (Water_palette_data_addr).w,a2 moveq #$1B,d0 dbf d0,* move.w (a2)+,d1 move.b (H_int_counter).w,d0 subi.b #200,d0 bcs.s $$transferColors sub.b d0,d1 bcs.s $$skipTransfer $$transferColors: move.w (a2)+,d0 lea (Water_palette).w,a0 adda.w d0,a0 addi.w #$C000,d0 swap d0 move.l d0,VDP_control_port-VDP_data_port(a1) move.l (a0)+,(a1) move.w (a0)+,(a1) nop moveq #$33,d0 dbf d0,* ; waste some cycles dbf d1,$$transferColors $$skipTransfer: startZ80 movem.l (sp)+,d0-d1/a0-a2 tst.b (Do_Updates_in_H_int).w bne.s HInt4_Do_Updates Hint4_Done: rte ; --------------------------------------------------------------------------- HInt4_Do_Updates: clr.b (Do_Updates_in_H_int).w movem.l d0-a6,-(sp) jsr (Do_Updates).l movem.l (sp)+,d0-a6 rte ; --------------------------------------------------------------------------- ; Identical to HInt5, except for faster systems ; --------------------------------------------------------------------------- HInt_6: tst.w (H_int_flag).w beq.s HInt6_Done move.w #0,(H_int_flag).w movem.l d0-d1/a0-a2,-(sp) lea (VDP_data_port).l,a1 move.w #$8AFF,VDP_control_port-VDP_data_port(a1) stopZ80 movea.l (Water_palette_data_addr).w,a2 moveq #$1B,d0 dbf d0,* move.w (a2)+,d1 move.b (H_int_counter).w,d0 subi.b #200,d0 bcs.s $$transferColors sub.b d0,d1 bcs.s $$skipTransfer $$transferColors: move.w (a2)+,d0 lea (Normal_palette).w,a0 adda.w d0,a0 addi.w #$C000,d0 swap d0 move.l d0,VDP_control_port-VDP_data_port(a1) move.l (a0)+,(a1) move.w (a0)+,(a1) nop moveq #$33,d0 dbf d0,* ; waste some cycles dbf d1,$$transferColors $$skipTransfer: startZ80 movem.l (sp)+,d0-d1/a0-a2 tst.b (Do_Updates_in_H_int).w bne.s HInt6_Do_Updates HInt6_Done: rte ; --------------------------------------------------------------------------- HInt6_Do_Updates: clr.b (Do_Updates_in_H_int).w movem.l d0-a6,-(sp) jsr (Do_Updates).l movem.l (sp)+,d0-a6 rte ; --------------------------------------------------------------------------- ; Copies the entire water palette to CRAM, used only in Hydrocity ; --------------------------------------------------------------------------- HInt2: move #$2700,sr tst.w (H_int_flag).w beq.s HInt2_Done move.w #0,(H_int_flag).w movem.l a0-a1,-(sp) lea (VDP_data_port).l,a1 move.w #$8ADF,VDP_control_port-VDP_data_port(a1) lea (Water_palette).w,a0 move.l #vdpComm($0000,CRAM,WRITE),VDP_control_port-VDP_data_port(a1) rept 32 move.l (a0)+,(a1) endm movem.l (sp)+,a0-a1 tst.b (Do_Updates_in_H_int).w bne.s HInt2_Do_Updates HInt2_Done: rte ; --------------------------------------------------------------------------- HInt2_Do_Updates: 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 ======================================= Init_Controllers: stopZ80 moveq #$40,d0 move.b d0,(HW_Port_1_Control).l move.b d0,(HW_Port_2_Control).l move.b d0,(HW_Expansion_Control).l startZ80 rts ; End of function Init_Controllers ; =============== S U B R O U T I N E ======================================= Poll_Controllers: lea (Ctrl_1).w,a0 lea (HW_Port_1_Data).l,a1 bsr.s Poll_Controller ; poll first controller addq.w #2,a1 ; poll second controller ; End of function Poll_Controllers ; =============== S U B R O U T I N E ======================================= Poll_Controller: move.b #0,(a1) ; Poll controller data port nop nop move.b (a1),d0 ; Get controller port data (start/A) lsl.b #2,d0 andi.b #$C0,d0 move.b #$40,(a1) ; Poll controller data port again nop nop move.b (a1),d1 ; Get controller port data (B/C/Dpad) andi.b #$3F,d1 or.b d1,d0 ; Fuse together into one controller bit array not.b d0 move.b (a0),d1 ; Get press button data eor.b d0,d1 ; Toggle off buttons that are being held move.b d0,(a0)+ ; Put raw controller input (for held buttons) in F604/F606 and.b d0,d1 move.b d1,(a0)+ ; Put pressed controller input in F605/F607 rts ; End of function Poll_Controller ; =============== S U B R O U T I N E ======================================= Init_VDP: lea (VDP_control_port).l,a0 lea (VDP_data_port).l,a1 lea (VDP_register_values).l,a2 moveq #19-1,d7 $$setRegisters: move.w (a2)+,(a0) dbf d7,$$setRegisters move.w (VDP_register_values+2).l,d0 ; get command for register #1 move.w d0,(VDP_reg_1_command).w ; and store it in RAM (for easy display blanking/enabling) move.w #$8ADF,(H_int_counter_command).w 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($80),d7 $$clearCRAM: move.w d0,(a1) dbf d7,$$clearCRAM clr.l (V_scroll_value).w clr.l (_unkF61A).w move.l d1,-(sp) dmaFillVRAM 0,$0000,$10000 ; clear entire VRAM move.l (sp)+,d1 rts ; End of function Init_VDP ; --------------------------------------------------------------------------- VDP_register_values: dc.w $8004 ; H-int disabled dc.w $8134 ; V-int enabled, display blanked, DMA enabled, 224 line display dc.w $8230 ; Scroll A PNT base $C000 dc.w $8320 ; Window PNT base $8000 dc.w $8407 ; Scroll B PNT base $E000 dc.w $857C ; Sprite attribute table base $F800 dc.w $8600 dc.w $8700 ; Backdrop color is color 0 of the first palette line dc.w $8800 dc.w $8900 dc.w $8A00 dc.w $8B00 ; Full-screen horizontal and vertical scrolling dc.w $8C81 ; 40 cell wide display, no interlace dc.w $8D3C ; Horizontal scroll table base $F000 dc.w $8E00 dc.w $8F02 ; Auto-increment is 2 dc.w $9001 ; Scroll planes are 64x32 cells dc.w $9100 dc.w $9200 ; Window disabled ; =============== S U B R O U T I N E ======================================= Clear_DisplayData: stopZ80 dmaFillVRAM 0,$0000,$40 tst.w (Competition_mode).w beq.s Clear_DisplayData_No2P dmaFillVRAM 0,$8000,$4000 bra.s Clear_DisplayData_Cont ; --------------------------------------------------------------------------- Clear_DisplayData_No2P: dmaFillVRAM 0,$C000,$1000 ; clear plane A PNT dmaFillVRAM 0,$E000,$1000 ; clear plane B PNT Clear_DisplayData_Cont: clr.l (V_scroll_value).w clr.l (_unkF61A).w ; Bug: this should be $280 clearRAM Sprite_table,$280+4 ; Bug: this should be $400 clearRAM H_scroll_buffer,$400+4 startZ80 rts ; End of function Clear_DisplayData ; =============== S U B R O U T I N E ======================================= SndDrvInit: nop move.w #$100,(Z80_bus_request).l move.w #$100,(Z80_reset).l ; release Z80 reset ; Load SMPS sound driver lea (Z80_SoundDriver).l,a0 lea (Z80_RAM).l,a1 bsr.w Kos_Decomp ; Load sound driver data (PSG envelopes, music/sound pointers, FM voice bank) lea (Z80_SoundDriverData).l,a0 lea (Z80_RAM+$1300).l,a1 bsr.w Kos_Decomp ; Load default variables lea (Z80_DefaultVariables).l,a0 lea (Z80_RAM+zDataStart).l,a1 move.w #Z80_DefaultVariables_end-Z80_DefaultVariables-1,d0 - move.b (a0)+,(a1)+ dbf d0,- ; Detect PAL region consoles btst #6,(Graphics_flags).w beq.s + move.b #1,(Z80_RAM+zPalFlag).l + move.w #0,(Z80_reset).l ; reset Z80 nop nop nop nop move.w #$100,(Z80_reset).l ; release reset startZ80 rts ; End of function SndDrvInit ; --------------------------------------------------------------------------- ; Default Z80 variables. These are actually set to more meaningful values ; in other SMPS Z80 drivers. ; --------------------------------------------------------------------------- Z80_DefaultVariables: dc.b 0 ; Unused 1 dc.b 0 ; Unused 2 dc.b 0 ; zPalFlag dc.b 0 ; Unused 3 dc.b 0 ; zPalDblUpdCounter dc.b 0 ; zSoundQueue0 dc.b 0 ; zSoundQueue1 dc.b 0 ; zSoundQueue2 dc.b 0 ; zTempoSpeedup dc.b 0 ; zNextSound dc.b 0 ; zMusicNumber dc.b 0 ; zSFXNumber0 dc.b 0 ; zSFXNumber1 dc.b 0 ; zFadeOutTimeout dc.b 0 ; zFadeDelay dc.b 0 ; zFadeDelayTimeout Z80_DefaultVariables_end: ; --------------------------------------------------------------------------- ; Always replaces an index previous passed to this function ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Play_Music: stopZ80 move.b d0,(Z80_RAM+zMusicNumber).l startZ80 rts ; End of function Play_Music ; --------------------------------------------------------------------------- ; plays a sound if the source object is on-screen ; unused/dead code, left over from Sonic 2 Play_SFX_Local: tst.b render_flags(a0) bpl.s Play_SFX_Done ; --------------------------------------------------------------------------- ; Can handle up to two different indexes in one frame ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Play_SFX: stopZ80 cmp.b (Z80_RAM+zSFXNumber0).l,d0 beq.s ++ tst.b (Z80_RAM+zSFXNumber0).l bne.s + move.b d0,(Z80_RAM+zSFXNumber0).l startZ80 rts + move.b d0,(Z80_RAM+zSFXNumber1).l + startZ80 Play_SFX_Done: rts ; End of function Play_SFX ; =============== S U B R O U T I N E ======================================= Change_Music_Tempo: stopZ80 move.b d0,(Z80_RAM+zTempoSpeedup).l startZ80 rts ; End of function Change_Music_Tempo ; =============== S U B R O U T I N E ======================================= Pause_Game: nop tst.w (Ending_running_flag).w beq.s Pause_Main rts ; --------------------------------------------------------------------------- Pause_Main: tst.b (Life_count).w beq.w Pause_Unpause tst.w (Game_paused).w bne.s + move.b (Ctrl_1_pressed).w,d0 andi.b #$80,d0 ; is Start pressed? beq.w Pause_NoPause ; if not, branch + move.w #1,(Game_paused).w stopZ80 move.b #1,(Z80_RAM+zPauseFlag).l ; Pause the music startZ80 Pause_Loop: move.b #$10,(V_int_routine).w bsr.w Wait_VSync tst.b (Slow_motion_flag).w beq.s Pause_NoSlowMo btst #button_A,(Ctrl_1_pressed).w beq.s Pause_ChkFrameAdvance ; branch if A isn't pressed move.b #4,(Game_mode).w nop bra.s Pause_ResumeMusic ; --------------------------------------------------------------------------- Pause_ChkFrameAdvance: btst #button_B,(Ctrl_1_held).w bne.s Pause_FrameAdvance ; branch if B is held btst #button_C,(Ctrl_1_pressed).w bne.s Pause_FrameAdvance ; branch if C is pressed Pause_NoSlowMo: cmpi.b #$E,(Current_zone).w blo.s Pause_ChkStart ; if the zone is below ALZ cmpi.b #$12,(Current_zone).w bhi.s Pause_ChkStart ; if the zone is above EMZ tst.b (Competition_type).w bpl.s Pause_ChkStart btst #button_B,(Ctrl_1_pressed).w beq.s Pause_ChkStart move.b #$C0,(Game_mode).w ; If in time attack mode, go back to 2P menu if B is pressed bra.s Pause_ResumeMusic ; --------------------------------------------------------------------------- Pause_ChkStart: move.b (Ctrl_1_pressed).w,d0 andi.b #button_start_mask,d0 beq.s Pause_Loop Pause_ResumeMusic: stopZ80 move.b #$80,(Z80_RAM+zPauseFlag).l ; Unpause music startZ80 Pause_Unpause: move.w #0,(Game_paused).w Pause_NoPause: rts ; --------------------------------------------------------------------------- Pause_FrameAdvance: move.w #1,(Game_paused).w stopZ80 move.b #$80,(Z80_RAM+zPauseFlag).l ; Unpause music startZ80 rts ; advance by a single frame ; End of function Pause_Game ; --------------------------------------------------------------------------- ; Copies a plane map to a plane PNT ; Inputs: ; a1 = map address ; d0 = VDP command to write to the PNT ; d1 = number of cells in a row - 1 ; d2 = number of cell rows - 1 ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Plane_Map_To_VRAM: lea (VDP_data_port).l,a6 move.l #$80<<16,d4 ; row increment value - move.l d0,VDP_control_port-VDP_data_port(a6) move.w d1,d3 - move.w (a1)+,(a6) dbf d3,- ; copy one row add.l d4,d0 ; move onto next row dbf d2,-- ; and copy it rts ; End of function Plane_Map_To_VRAM ; --------------------------------------------------------------------------- ; Copies a plane map to a plane PNT, used for a 128-cell wide plane ; Inputs: ; a1 = map address ; d0 = VDP command to write to the PNT ; d1 = number of cells in a row - 1 ; d2 = number of cell rows - 1 ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Plane_Map_To_VRAM_2: lea (VDP_data_port).l,a6 move.l #$100<<16,d4 ; row increment value - move.l d0,VDP_control_port-VDP_data_port(a6) move.w d1,d3 - move.w (a1)+,(a6) dbf d3,- ; copy one row add.l d4,d0 ; move onto next row dbf d2,-- ; and copy it rts ; End of function Plane_Map_To_VRAM_2 ; --------------------------------------------------------------------------- ; Adds art to the DMA queue ; Inputs: ; d1 = source address ; d2 = destination VRAM address ; d3 = number of words to transfer ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Add_To_DMA_Queue: if Sonic3_Complete ; Detect if transfer crosses 128KB boundary lsr.l #1,d1 move.w d3,d0 neg.w d0 sub.w d1,d0 bcc.s .transfer ; Do first transfer movem.l d1-d3,-(sp) add.w d0,d3 ; d3 = words remaining in 128KB "bank" bsr.s .transfer movem.l (sp)+,d1-d3 ; Get second transfer's source, destination, and length moveq #0,d0 sub.w d1,d0 sub.w d0,d3 add.l d0,d1 add.w d0,d2 add.w d0,d2 ; Do second transfer .transfer: endif movea.l (DMA_queue_slot).w,a1 cmpa.w #DMA_queue_slot,a1 ; is the queue full? beq.s Add_To_DMA_Queue_Done ; if it is, return move.w #$9300,d0 move.b d3,d0 move.w d0,(a1)+ ; command to specify transfer length in words & $00FF move.w #$9400,d0 lsr.w #8,d3 move.b d3,d0 move.w d0,(a1)+ ; command to specify transfer length in words & $FF00 move.w #$9500,d0 if ~~Sonic3_Complete lsr.l #1,d1 endif move.b d1,d0 move.w d0,(a1)+ ; command to specify transfer source & $0001FE move.w #$9600,d0 lsr.l #8,d1 move.b d1,d0 move.w d0,(a1)+ ; command to specify transfer source & $01FE00 move.w #$9700,d0 lsr.l #8,d1 andi.b #$7F,d1 ; this instruction safely allows source to be in RAM; S2's lacks this move.b d1,d0 move.w d0,(a1)+ ; command to specify transfer source & $FE0000 andi.l #$FFFF,d2 lsl.l #2,d2 lsr.w #2,d2 swap d2 ori.l #vdpComm($0000,VRAM,DMA),d2 move.l d2,(a1)+ ; command to specify transfer destination and begin DMA move.l a1,(DMA_queue_slot).w ; set new free slot address cmpa.w #DMA_queue_slot,a1 ; has the end of the queue been reached? beq.s Add_To_DMA_Queue_Done ; if it has, branch move.w #0,(a1) ; place stop token at the end of the queue Add_To_DMA_Queue_Done: rts ; End of function Add_To_DMA_Queue ; =============== S U B R O U T I N E ======================================= Process_DMA_Queue: lea (VDP_control_port).l,a5 lea (DMA_queue).w,a1 $$loop: move.w (a1)+,d0 ; has a stop token been encountered? beq.s $$stop ; if it has, branch move.w d0,(a5) move.w (a1)+,(a5) move.w (a1)+,(a5) move.w (a1)+,(a5) move.w (a1)+,(a5) move.w (a1)+,(a5) move.w (a1)+,(a5) cmpa.w #DMA_queue_slot,a1 ; has the end of the queue been reached? bne.s $$loop ; if not, loop $$stop: move.w #0,(DMA_queue).w move.l #DMA_queue,(DMA_queue_slot).w rts ; End of function Process_DMA_Queue ; --------------------------------------------------------------------------- ; Nemesis decompression subroutine, decompresses art directly to VRAM ; Inputs: ; a0 = art address ; a VDP command to write to the destination VRAM address must be issued ; before calling this routine ; See http://www.segaretro.org/Nemesis_compression for format description ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Nem_Decomp: movem.l d0-a1/a3-a5,-(sp) lea (Nem_PCD_WriteRowToVDP).l,a3 lea (VDP_data_port).l,a4 ; write all rows to the VDP data port bra.s Nem_Decomp_Main ; --------------------------------------------------------------------------- ; Nemesis decompression subroutine, decompresses art to RAM ; Inputs: ; a0 = art address ; a4 = destination RAM address ; --------------------------------------------------------------------------- Nem_Decomp_To_RAM: movem.l d0-a1/a3-a5,-(sp) lea (Nem_PCD_WriteRowToRAM).l,a3 ; --------------------------------------------------------------------------- ; Main Nemesis decompression subroutine ; --------------------------------------------------------------------------- Nem_Decomp_Main: lea (Nem_code_table).w,a1 move.w (a0)+,d2 ; get number of patterns lsl.w #1,d2 bcc.s + ; branch if the sign bit isn't set adda.w #Nem_PCD_WriteRowToVDP_XOR-Nem_PCD_WriteRowToVDP,a3 ; otherwise the file uses XOR mode + lsl.w #2,d2 ; get number of 8-pixel rows in the uncompressed data movea.w d2,a5 ; and store it in a5 because there aren't any spare data registers moveq #8,d3 ; 8 pixels in a pattern row moveq #0,d2 moveq #0,d4 bsr.w Nem_Build_Code_Table move.b (a0)+,d5 ; get first byte of compressed data asl.w #8,d5 ; shift up by a byte move.b (a0)+,d5 ; get second byte of compressed data move.w #$10,d6 ; set initial shift value bsr.s Nem_Process_Compressed_Data movem.l (sp)+,d0-a1/a3-a5 rts ; --------------------------------------------------------------------------- ; Part of the Nemesis decompressor, processes the actual compressed data ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= ; PCD is used throughout this subroutine as an initialism for Process_Compressed_Data Nem_Process_Compressed_Data: move.w d6,d7 subq.w #8,d7 ; get shift value move.w d5,d1 lsr.w d7,d1 ; shift so that high bit of the code is in bit position 7 cmpi.b #%11111100,d1 ; are the high 6 bits set? bhs.s Nem_PCD_InlineData ; if they are, it signifies inline data andi.w #$FF,d1 add.w d1,d1 move.b (a1,d1.w),d0 ; get the length of the code in bits ext.w d0 sub.w d0,d6 ; subtract from shift value so that the next code is read next time around cmpi.w #9,d6 ; does a new byte need to be read? bhs.s + ; if not, branch addq.w #8,d6 asl.w #8,d5 move.b (a0)+,d5 ; read next byte + move.b 1(a1,d1.w),d1 move.w d1,d0 andi.w #$F,d1 ; get palette index for pixel andi.w #$F0,d0 Nem_PCD_GetRepeatCount: lsr.w #4,d0 ; get repeat count Nem_PCD_WritePixel: lsl.l #4,d4 ; shift up by a nybble or.b d1,d4 ; write pixel subq.w #1,d3 ; has an entire 8-pixel row been written? bne.s Nem_PCD_WritePixel_Loop ; if not, loop jmp (a3) ; otherwise, write the row to its destination ; --------------------------------------------------------------------------- Nem_PCD_NewRow: moveq #0,d4 ; reset row moveq #8,d3 ; reset nybble counter Nem_PCD_WritePixel_Loop: dbf d0,Nem_PCD_WritePixel bra.s Nem_Process_Compressed_Data ; --------------------------------------------------------------------------- Nem_PCD_InlineData: subq.w #6,d6 ; 6 bits needed to signal inline data cmpi.w #9,d6 bhs.s + addq.w #8,d6 asl.w #8,d5 move.b (a0)+,d5 + subq.w #7,d6 ; and 7 bits needed for the inline data itself move.w d5,d1 lsr.w d6,d1 ; shift so that low bit of the code is in bit position 0 move.w d1,d0 andi.w #$F,d1 ; get palette index for pixel andi.w #$70,d0 ; high nybble is repeat count for pixel cmpi.w #9,d6 bhs.s Nem_PCD_GetRepeatCount addq.w #8,d6 asl.w #8,d5 move.b (a0)+,d5 bra.s Nem_PCD_GetRepeatCount ; --------------------------------------------------------------------------- Nem_PCD_WriteRowToVDP: move.l d4,(a4) ; write 8-pixel row subq.w #1,a5 move.w a5,d4 ; have all the 8-pixel rows been written? bne.s Nem_PCD_NewRow ; if not, branch rts ; otherwise the decompression is finished ; --------------------------------------------------------------------------- Nem_PCD_WriteRowToVDP_XOR: eor.l d4,d2 ; XOR the previous row by the current row move.l d2,(a4) ; and write the result subq.w #1,a5 move.w a5,d4 bne.s Nem_PCD_NewRow rts ; --------------------------------------------------------------------------- Nem_PCD_WriteRowToRAM: move.l d4,(a4)+ subq.w #1,a5 move.w a5,d4 bne.s Nem_PCD_NewRow rts ; --------------------------------------------------------------------------- Nem_PCD_WriteRowToRAM_XOR: eor.l d4,d2 move.l d2,(a4)+ subq.w #1,a5 move.w a5,d4 bne.s Nem_PCD_NewRow rts ; --------------------------------------------------------------------------- ; Part of the Nemesis decompressor, builds the code table (in RAM) ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= ; BCT is used throughout this subroutine as an initialism for Build_Code_Table Nem_Build_Code_Table: move.b (a0)+,d0 ; read first byte Nem_BCT_ChkEnd: cmpi.b #$FF,d0 ; has the end of the code table description been reached? bne.s Nem_BCT_NewPalIndex ; if not, branch rts ; otherwise, this subroutine's work is done ; --------------------------------------------------------------------------- Nem_BCT_NewPalIndex: move.w d0,d7 Nem_BCT_Loop: move.b (a0)+,d0 ; read next byte cmpi.b #$80,d0 ; sign bit being set signifies a new palette index bhs.s Nem_BCT_ChkEnd ; a bmi could have been used instead of a compare and bcc move.b d0,d1 andi.w #$F,d7 ; get palette index andi.w #$70,d1 ; get repeat count for palette index or.w d1,d7 ; combine the two andi.w #$F,d0 ; get the length of the code in bits move.b d0,d1 lsl.w #8,d1 or.w d1,d7 ; combine with palette index and repeat count to form code table entry moveq #8,d1 sub.w d0,d1 ; is the code 8 bits long? bne.s Nem_BCT_ShortCode ; if not, a bit of extra processing is needed move.b (a0)+,d0 ; get code add.w d0,d0 ; each code gets a word-sized entry in the table move.w d7,(a1,d0.w) ; store the entry for the code bra.s Nem_BCT_Loop ; repeat ; --------------------------------------------------------------------------- ; the Nemesis decompressor uses prefix-free codes (no valid code is a prefix of a longer code) ; e.g. if 10 is a valid 2-bit code, 110 is a valid 3-bit code but 100 isn't ; also, when the actual compressed data is processed the high bit of each code is in bit position 7 ; so the code needs to be bit-shifted appropriately over here before being used as a code table index ; additionally, the code needs multiple entries in the table because no masking is done during compressed data processing ; so if 11000 is a valid code then all indices of the form 11000XXX need to have the same entry Nem_BCT_ShortCode: move.b (a0)+,d0 ; get code lsl.w d1,d0 ; shift so that high bit is in bit position 7 add.w d0,d0 ; get index into code table moveq #1,d5 lsl.w d1,d5 subq.w #1,d5 ; d5 = 2^d1 - 1 Nem_BCT_ShortCode_Loop: move.w d7,(a1,d0.w) ; store entry addq.w #2,d0 ; increment index dbf d5,Nem_BCT_ShortCode_Loop ; repeat for required number of entries bra.s Nem_BCT_Loop ; End of function Nem_Build_Code_Table ; --------------------------------------------------------------------------- ; Adds pattern load requests to the Nemesis decompression queue ; Input: d0 = ID of the PLC to load ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Load_PLC: movem.l a1-a2,-(sp) lea (Offs_PLC).l,a1 add.w d0,d0 move.w (a1,d0.w),d0 lea (a1,d0.w),a1 lea (Nem_decomp_queue).w,a2 $$findFreeSlot: tst.l (a2) ; is the current slot in the queue free? beq.s $$getPieceCount ; if it is, branch addq.w #6,a2 ; otherwise check the next slot bra.s $$findFreeSlot ; --------------------------------------------------------------------------- $$getPieceCount: move.w (a1)+,d0 bmi.s $$done $$queuePieces: move.l (a1)+,(a2)+ ; store compressed data location move.w (a1)+,(a2)+ ; store destination in VRAM dbf d0,$$queuePieces $$done: movem.l (sp)+,a1-a2 rts ; End of function Load_PLC ; --------------------------------------------------------------------------- ; Loads a raw PLC from ROM ; Input: a1 = address of the PLC ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Load_PLC_Raw: lea (Nem_decomp_queue).w,a2 $$findFreeSlot: tst.l (a2) beq.s $$getPieceCount addq.w #6,a2 bra.s $$findFreeSlot ; --------------------------------------------------------------------------- $$getPieceCount: move.w (a1)+,d0 bmi.s $$done $$queuePieces: move.l (a1)+,(a2)+ move.w (a1)+,(a2)+ dbf d0,$$queuePieces $$done: rts ; End of function Load_PLC_Raw ; --------------------------------------------------------------------------- ; Adds pattern load requests to the Nemesis decompression queue ; Differs from Load_PLC in that it clears the queue before loading ; Input: d0 = ID of the PLC to load ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Load_PLC_2: movem.l a1-a2,-(sp) ; This differs from Load_PLC in that it overrides any PLCs already in the queue lea (Offs_PLC).l,a1 add.w d0,d0 move.w (a1,d0.w),d0 lea (a1,d0.w),a1 bsr.s Clear_Nem_Queue lea (Nem_decomp_queue).w,a2 move.w (a1)+,d0 bmi.s $$done $$queuePieces: move.l (a1)+,(a2)+ move.w (a1)+,(a2)+ dbf d0,$$queuePieces $$done: movem.l (sp)+,a1-a2 rts ; End of function Load_PLC_2 ; --------------------------------------------------------------------------- ; Clears the Nemesis decompression queue and its associated variables ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Clear_Nem_Queue: lea (Nem_decomp_queue).w,a2 moveq #bytesToLcnt($80),d0 ; clear till the end of Nem_decomp_vars $$loop: clr.l (a2)+ dbf d0,$$loop rts ; End of function Clear_Nem_Queue ; --------------------------------------------------------------------------- ; Initializes Nemesis decompression queue processing ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Process_Nem_Queue_Init: tst.l (Nem_decomp_queue).w beq.s ++ ; return if the queue is empty tst.w (Nem_patterns_left).w bne.s ++ ; return if processing of a previous piece is still going on movea.l (Nem_decomp_queue).w,a0 lea (Nem_PCD_WriteRowToVDP).l,a3 nop lea (Nem_code_table).w,a1 move.w (a0)+,d2 bpl.s + adda.w #Nem_PCD_WriteRowToVDP_XOR-Nem_PCD_WriteRowToVDP,a3 + andi.w #$7FFF,d2 bsr.w Nem_Build_Code_Table move.b (a0)+,d5 asl.w #8,d5 move.b (a0)+,d5 moveq #$10,d6 moveq #0,d0 move.l a0,(Nem_decomp_queue).w move.l a3,(Nem_decomp_vars).w move.l d0,(Nem_repeat_count).w move.l d0,(Nem_palette_index).w move.l d0,(Nem_previous_row).w move.l d5,(Nem_data_word).w move.l d6,(Nem_shift_value).w move.w d2,(Nem_patterns_left).w + rts ; End of function Process_Nem_Queue_Init ; --------------------------------------------------------------------------- ; Processes the first piece on the Nemesis decompression queue ; Decompresses 6 patterns per frame ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Process_Nem_Queue: tst.w (Nem_patterns_left).w beq.w Process_Nem_Queue_Done move.w #6,(Nem_frame_patterns_left).w ; decompress 6 patterns per frame moveq #0,d0 move.w (Nem_decomp_destination).w,d0 addi.w #6*$20,(Nem_decomp_destination).w ; increment by 6 patterns' worth of data bra.s Process_Nem_Queue_Main ; End of function Process_Nem_Queue ; --------------------------------------------------------------------------- ; Processes the first piece on the Nemesis decompression queue ; Decompresses 3 patterns per frame ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Process_Nem_Queue_2: tst.w (Nem_patterns_left).w beq.s Process_Nem_Queue_Done move.w #3,(Nem_frame_patterns_left).w ; decompress 3 patterns per frame moveq #0,d0 move.w (Nem_decomp_destination).w,d0 addi.w #3*$20,(Nem_decomp_destination).w ; increment by 3 patterns' worth of data ; End of function Process_Nem_Queue_2 ; --------------------------------------------------------------------------- ; Main Nemesis decompression queue processor ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Process_Nem_Queue_Main: lea (VDP_control_port).l,a4 lsl.l #2,d0 lsr.w #2,d0 ori.w #$4000,d0 swap d0 ; d0 = VDP command word to write to VRAM destination move.l d0,(a4) subq.w #VDP_control_port-VDP_data_port,a4 ; a4 = VDP_data_port movea.l (Nem_decomp_queue).w,a0 movea.l (Nem_decomp_vars).w,a3 move.l (Nem_repeat_count).w,d0 move.l (Nem_palette_index).w,d1 move.l (Nem_previous_row).w,d2 move.l (Nem_data_word).w,d5 move.l (Nem_shift_value).w,d6 lea (Nem_code_table).w,a1 Process_Nem_Queue_Loop: movea.w #8,a5 ; decompress all 8 rows in a pattern bsr.w Nem_PCD_NewRow subq.w #1,(Nem_patterns_left).w ; have all the patterns been decompressed? beq.s Process_Nem_Queue_ShiftUp ; if yes, shift all other queue entries up subq.w #1,(Nem_frame_patterns_left).w ; has the current frame's worth of patterns been decompressed? bne.s Process_Nem_Queue_Loop ; if not, loop move.l a0,(Nem_decomp_queue).w move.l a3,(Nem_decomp_vars).w move.l d0,(Nem_repeat_count).w move.l d1,(Nem_palette_index).w move.l d2,(Nem_previous_row).w move.l d5,(Nem_data_word).w move.l d6,(Nem_shift_value).w Process_Nem_Queue_Done: rts ; --------------------------------------------------------------------------- ; Bug: filling in all $10 slots is dangerous because this routine ; doesn't copy the VRAM location for the last entry in the queue, ; nor does it mark the last slot in the queue as clear Process_Nem_Queue_ShiftUp: lea (Nem_decomp_queue).w,a0 moveq #$16-1,d0 .loop: move.l 6(a0),(a0)+ dbf d0,.loop rts ; End of function Process_Nem_Queue_Main ; --------------------------------------------------------------------------- lea (Offs_PLC).l,a1 add.w d0,d0 move.w (a1,d0.w),d0 lea (a1,d0.w),a1 ; --------------------------------------------------------------------------- ; Loads a raw PLC from the ROM and decompresses it immediately ; Input: a1 = the address of the PLC ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Load_PLC_Immediate: move.w (a1)+,d1 $$decompPieces: movea.l (a1)+,a0 ; get source address moveq #0,d0 move.w (a1)+,d0 ; get destination VRAM address lsl.l #2,d0 lsr.w #2,d0 ori.w #$4000,d0 swap d0 ; d0 = VDP command to write to destination move.l d0,(VDP_control_port).l bsr.w Nem_Decomp dbf d1,$$decompPieces rts ; End of function Load_PLC_Immediate ; --------------------------------------------------------------------------- ; Enigma decompression subroutine ; Inputs: ; a0 = compressed data location ; a1 = destination (in RAM) ; d0 = starting art tile ; See http://www.segaretro.org/Enigma_compression for format description ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Eni_Decomp: 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 number of bits in inline copy value move.b (a0)+,d4 lsl.b #3,d4 ; store PCCVH flags bitfield movea.w (a0)+,a2 adda.w a3,a2 ; store incremental copy word movea.w (a0)+,a4 adda.w a3,a4 ; store literal copy word move.b (a0)+,d5 asl.w #8,d5 move.b (a0)+,d5 ; get first word in format list moveq #$10,d6 ; initial shift value Eni_Decomp_Loop: moveq #7,d0 ; assume a format list entry is 7 bits move.w d6,d7 sub.w d0,d7 move.w d5,d1 lsr.w d7,d1 andi.w #$7F,d1 ; get format list entry move.w d1,d2 ; and copy it cmpi.w #$40,d1 ; is the high bit of the entry set? bhs.s + moveq #6,d0 ; if it isn't, the entry is actually 6 bits lsr.w #1,d2 + bsr.w Eni_Decomp_FetchByte andi.w #$F,d2 ; get repeat count lsr.w #4,d1 add.w d1,d1 jmp Eni_Decomp_Index(pc,d1.w) ; --------------------------------------------------------------------------- Eni_Decomp_00: move.w a2,(a1)+ ; copy incremental copy word addq.w #1,a2 ; increment it dbf d2,Eni_Decomp_00 ; repeat bra.s Eni_Decomp_Loop ; --------------------------------------------------------------------------- Eni_Decomp_01: move.w a4,(a1)+ ; copy literal copy word dbf d2,Eni_Decomp_01 ; repeat bra.s Eni_Decomp_Loop ; --------------------------------------------------------------------------- Eni_Decomp_100: bsr.w Eni_Decomp_FetchInlineValue $$loop: move.w d1,(a1)+ ; copy inline value dbf d2,$$loop ; repeat bra.s Eni_Decomp_Loop ; --------------------------------------------------------------------------- Eni_Decomp_101: bsr.w Eni_Decomp_FetchInlineValue $$loop: move.w d1,(a1)+ ; copy inline value addq.w #1,d1 ; increment dbf d2,$$loop ; repeat bra.s Eni_Decomp_Loop ; --------------------------------------------------------------------------- Eni_Decomp_110: bsr.w Eni_Decomp_FetchInlineValue $$loop: move.w d1,(a1)+ ; copy inline value subq.w #1,d1 ; decrement dbf d2,$$loop ; repeat bra.s Eni_Decomp_Loop ; --------------------------------------------------------------------------- Eni_Decomp_111: cmpi.w #$F,d2 beq.s Eni_Decomp_Done $$loop: bsr.w Eni_Decomp_FetchInlineValue ; fetch new inline value move.w d1,(a1)+ ; copy it dbf d2,$$loop ; and repeat bra.s Eni_Decomp_Loop ; --------------------------------------------------------------------------- Eni_Decomp_Index: bra.s Eni_Decomp_00 ; --------------------------------------------------------------------------- bra.s Eni_Decomp_00 ; --------------------------------------------------------------------------- bra.s Eni_Decomp_01 ; --------------------------------------------------------------------------- bra.s Eni_Decomp_01 ; --------------------------------------------------------------------------- bra.s Eni_Decomp_100 ; --------------------------------------------------------------------------- bra.s Eni_Decomp_101 ; --------------------------------------------------------------------------- bra.s Eni_Decomp_110 ; --------------------------------------------------------------------------- bra.s Eni_Decomp_111 ; --------------------------------------------------------------------------- Eni_Decomp_Done: subq.w #1,a0 ; go back by one byte cmpi.w #$10,d6 bne.s + subq.w #1,a0 ; and another one if needed + move.w a0,d0 lsr.w #1,d0 bcc.s + addq.w #1,a0 ; make sure it's an even address + movem.l (sp)+,d0-d7/a1-a5 rts ; End of function Eni_Decomp ; --------------------------------------------------------------------------- ; Part of the Enigma decompressor ; Fetches an inline copy value and stores it in d1 ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Eni_Decomp_FetchInlineValue: move.w a3,d3 ; copy starting art tile move.b d4,d1 ; copy PCCVH bitfield add.b d1,d1 ; is the priority bit set? bcc.s + ; if not, branch subq.w #1,d6 btst d6,d5 ; is the priority bit set in the inline render flags? beq.s + ; if not, branch ori.w #$8000,d3 ; otherwise set priority bit in art tile + add.b d1,d1 ; is the high palette line bit set? bcc.s + ; if not, branch subq.w #1,d6 btst d6,d5 beq.s + addi.w #$4000,d3 + add.b d1,d1 ; is the low palette line bit set? bcc.s + ; if not, branch subq.w #1,d6 btst d6,d5 beq.s + addi.w #$2000,d3 + add.b d1,d1 ; is the vertical flip flag set? bcc.s + ; if not, branch subq.w #1,d6 btst d6,d5 beq.s + ori.w #$1000,d3 + add.b d1,d1 ; is the horizontal flip flag set? bcc.s + ; if not, branch subq.w #1,d6 btst d6,d5 beq.s + ori.w #$800,d3 + move.w d5,d1 move.w d6,d7 sub.w a5,d7 ; subtract length in bits of inline copy value bcc.s $$enoughBits ; branch if a new word doesn't need to be read move.w d7,d6 addi.w #$10,d6 neg.w d7 ; calculate bit deficit lsl.w d7,d1 ; and make space for that many bits move.b (a0),d5 ; get next byte rol.b d7,d5 ; and rotate the required bits into the lowest positions add.w d7,d7 and.w Eni_Decomp_Masks-2(pc,d7.w),d5 add.w d5,d1 ; combine upper bits with lower bits $$maskValue: move.w a5,d0 ; get length in bits of inline copy value add.w d0,d0 and.w Eni_Decomp_Masks-2(pc,d0.w),d1 ; mask value appropriately add.w d3,d1 ; add starting art tile move.b (a0)+,d5 lsl.w #8,d5 move.b (a0)+,d5 ; get next word rts ; --------------------------------------------------------------------------- $$enoughBits: beq.s $$justEnough ; if the word has been exactly exhausted, branch lsr.w d7,d1 ; get inline copy value move.w a5,d0 add.w d0,d0 and.w Eni_Decomp_Masks-2(pc,d0.w),d1 ; and mask it appropriately add.w d3,d1 ; add starting art tile move.w a5,d0 bra.s Eni_Decomp_FetchByte ; --------------------------------------------------------------------------- $$justEnough: moveq #$10,d6 ; reset shift value bra.s $$maskValue ; End of function Eni_Decomp_FetchInlineValue ; --------------------------------------------------------------------------- Eni_Decomp_Masks: dc.w 1 dc.w 3 dc.w 7 dc.w $F dc.w $1F dc.w $3F dc.w $7F dc.w $FF dc.w $1FF dc.w $3FF dc.w $7FF dc.w $FFF dc.w $1FFF dc.w $3FFF dc.w $7FFF dc.w $FFFF ; --------------------------------------------------------------------------- ; Part of the Enigma decompressor, fetches the next byte if needed ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Eni_Decomp_FetchByte: sub.w d0,d6 ; subtract length of current entry from shift value so that next entry is read next time around cmpi.w #9,d6 ; does a new byte need to be read? bhs.s + ; if not, branch addq.w #8,d6 asl.w #8,d5 move.b (a0)+,d5 + rts ; End of function Eni_Decomp_FetchByte ; --------------------------------------------------------------------------- ; Kosinski decompression subroutine ; Inputs: ; a0 = compressed data location ; a1 = destination ; See http://www.segaretro.org/Kosinski_compression for format description ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Kos_Decomp: subq.l #2,sp ; make space for two bytes on the stack move.b (a0)+,1(sp) move.b (a0)+,(sp) move.w (sp),d5 ; copy first description field moveq #$F,d4 ; 16 bits in a byte Kos_Decomp_Loop: lsr.w #1,d5 ; bit which is shifted out goes into C flag move sr,d6 dbf d4,Kos_Decomp_ChkBit move.b (a0)+,1(sp) move.b (a0)+,(sp) move.w (sp),d5 ; get next description field if needed moveq #$F,d4 ; reset bit counter Kos_Decomp_ChkBit: move d6,ccr ; was the bit set? bcc.s Kos_Decomp_Match ; if not, branch (C flag clear means bit was clear) move.b (a0)+,(a1)+ ; otherwise, copy byte as-is bra.s Kos_Decomp_Loop ; --------------------------------------------------------------------------- Kos_Decomp_Match: moveq #0,d3 lsr.w #1,d5 ; get next bit move sr,d6 dbf d4,Kos_Decomp_ChkBit2 move.b (a0)+,1(sp) move.b (a0)+,(sp) move.w (sp),d5 moveq #$F,d4 Kos_Decomp_ChkBit2: move d6,ccr ; was the bit set? bcs.s Kos_Decomp_FullMatch ; if it was, branch lsr.w #1,d5 ; bit which is shifted out goes into X flag dbf d4,+ move.b (a0)+,1(sp) move.b (a0)+,(sp) move.w (sp),d5 moveq #$F,d4 + roxl.w #1,d3 ; get high repeat count bit (shift X flag in) 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 ; get low repeat count bit addq.w #1,d3 ; increment repeat count moveq #-1,d2 move.b (a0)+,d2 ; calculate offset bra.s Kos_Decomp_MatchLoop ; --------------------------------------------------------------------------- Kos_Decomp_FullMatch: move.b (a0)+,d0 ; get first byte move.b (a0)+,d1 ; get second byte moveq #-1,d2 move.b d1,d2 lsl.w #5,d2 move.b d0,d2 ; calculate offset andi.w #7,d1 ; does a third byte need to be read? beq.s Kos_Decomp_FullMatch2 ; if it does, branch move.b d1,d3 ; copy repeat count addq.w #1,d3 ; and increment it Kos_Decomp_MatchLoop: move.b (a1,d2.w),d0 move.b d0,(a1)+ ; copy appropriate byte dbf d3,Kos_Decomp_MatchLoop ; and repeat the copying bra.s Kos_Decomp_Loop ; --------------------------------------------------------------------------- Kos_Decomp_FullMatch2: move.b (a0)+,d1 beq.s Kos_Decomp_Done ; 0 indicates end of compressed data cmpi.b #1,d1 beq.w Kos_Decomp_Loop ; 1 indicates a new description needs to be read move.b d1,d3 ; otherwise, copy repeat count bra.s Kos_Decomp_MatchLoop ; --------------------------------------------------------------------------- Kos_Decomp_Done: addq.l #2,sp ; restore stack pointer to original state rts ; End of function Kos_Decomp ; --------------------------------------------------------------------------- ; Adds a Kosinski Moduled archive to the module queue ; Inputs: ; a1 = address of the archive ; d2 = destination in VRAM ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Queue_Kos_Module: lea (Kos_module_queue).w,a2 tst.l (a2) ; is the first slot free? beq.s Process_Kos_Module_Queue_Init ; if it is, branch addq.w #6,a2 ; otherwise, check next slot $$findFreeSlot: tst.l (a2) beq.s $$freeSlotFound addq.w #6,a2 bra.s $$findFreeSlot ; --------------------------------------------------------------------------- $$freeSlotFound: move.l a1,(a2)+ ; store source address move.w d2,(a2)+ ; store destination VRAM address rts ; End of function Queue_Kos_Module ; --------------------------------------------------------------------------- ; Initializes processing of the first module on the queue ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Process_Kos_Module_Queue_Init: move.w (a1)+,d3 ; get uncompressed size cmpi.w #$A000,d3 bne.s + move.w #$8000,d3 ; $A000 means $8000 for some reason + lsr.w #1,d3 move.w d3,d0 rol.w #5,d0 andi.w #$1F,d0 ; get number of complete modules move.b d0,(Kos_modules_left).w andi.l #$7FF,d3 ; get size of last module in words bne.s + ; branch if it's non-zero subq.b #1,(Kos_modules_left).w ; otherwise decrement the number of modules move.l #$800,d3 ; and take the size of the last module to be $800 words + move.w d3,(Kos_last_module_size).w move.w d2,(Kos_module_destination).w move.l a1,(Kos_module_queue).w addq.b #1,(Kos_modules_left).w ; store total number of modules rts ; End of function Process_Kos_Module_Queue_Init ; --------------------------------------------------------------------------- ; Processes the first module on the queue ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Process_Kos_Module_Queue: tst.b (Kos_modules_left).w bne.s $$modulesLeft $$done: rts ; --------------------------------------------------------------------------- $$modulesLeft: bmi.s $$decompressionStarted cmpi.w #4,(Kos_decomp_queue_count).w bhs.s $$done ; branch if the Kosinski decompression queue is full movea.l (Kos_module_queue).w,a1 lea (Kos_decomp_buffer).w,a2 bsr.w Queue_Kos ; add current module to decompression queue ori.b #$80,(Kos_modules_left).w ; and set bit to signify decompression in progress rts ; --------------------------------------------------------------------------- $$decompressionStarted: tst.w (Kos_decomp_queue_count).w bne.s $$done ; branch if the decompression isn't complete ; otherwise, DMA the decompressed data to VRAM andi.b #$7F,(Kos_modules_left).w move.l #$800,d3 subq.b #1,(Kos_modules_left).w bne.s + ; branch if it isn't the last module move.w (Kos_last_module_size).w,d3 + move.w (Kos_module_destination).w,d2 move.w d2,d0 add.w d3,d0 add.w d3,d0 move.w d0,(Kos_module_destination).w ; set new destination move.l (Kos_module_queue).w,d0 move.l (Kos_decomp_queue).w,d1 sub.l d1,d0 andi.l #$F,d0 add.l d0,d1 ; round to the nearest $10 boundary move.l d1,(Kos_module_queue).w ; and set new source move.l #Kos_decomp_buffer,d1 andi.l #$FFFFFF,d1 jsr (Add_To_DMA_Queue).l tst.b (Kos_modules_left).w bne.s + ; return if this wasn't the last module lea (Kos_module_queue).w,a0 lea (Kos_module_queue+6).w,a1 move.l (a1)+,(a0)+ ; otherwise, shift all entries up move.w (a1)+,(a0)+ move.l (a1)+,(a0)+ move.w (a1)+,(a0)+ move.l (a1)+,(a0)+ move.w (a1)+,(a0)+ move.l #0,(a0)+ ; and mark the last slot as free move.w #0,(a0)+ move.l (Kos_module_queue).w,d0 beq.s + ; return if the queue is now empty movea.l d0,a1 move.w (Kos_module_destination).w,d2 jmp (Process_Kos_Module_Queue_Init).l + rts ; End of function Process_Kos_Module_Queue ; --------------------------------------------------------------------------- ; Adds Kosinski-compressed data to the decompression queue ; Inputs: ; a1 = compressed data address ; a2 = decompression destination in RAM ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Queue_Kos: move.w (Kos_decomp_queue_count).w,d0 lsl.w #3,d0 lea (Kos_decomp_queue).w,a3 move.l a1,(a3,d0.w) ; store source move.l a2,4(a3,d0.w) ; store destination addq.w #1,(Kos_decomp_queue_count).w rts ; End of function Queue_Kos ; --------------------------------------------------------------------------- ; Checks if V-int occured in the middle of Kosinski queue processing ; and stores the location from which processing is to resume if it did ; --------------------------------------------------------------------------- Set_Kos_Bookmark: tst.w (Kos_decomp_queue_count).w bpl.s .return ; branch if decompression wasn't in progress move.l $42(sp),d0 ; check address V-int is supposed to rte to cmpi.l #Process_Kos_Queue_Main,d0 blo.s .return cmpi.l #Process_Kos_Queue_Done,d0 bhs.s .return move.l $42(sp),(Kos_decomp_bookmark).w move.l #Backup_Kos_Registers,$42(sp) ; force V-int to rte here instead if needed .return: rts ; --------------------------------------------------------------------------- ; Processes the first entry in the Kosinski decompression queue ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Process_Kos_Queue: tst.w (Kos_decomp_queue_count).w beq.w Process_Kos_Queue_Done bmi.w Restore_Kos_Bookmark ; branch if decompression was interrupted by V-int Process_Kos_Queue_Main: ori.w #$8000,(Kos_decomp_queue_count).w ; set sign bit to signify decompression in progress movea.l (Kos_decomp_queue).w,a0 movea.l (Kos_decomp_destination).w,a1 ; what follows is identical to the normal Kosinski decompressor except for using Kos_description_field instead of the stack lea (Kos_description_field).w,a2 move.b (a0)+,1(a2) move.b (a0)+,(a2) move.w (a2),d5 moveq #$F,d4 Process_Kos_Queue_Loop: lsr.w #1,d5 move sr,d6 dbf d4,Process_Kos_Queue_ChkBit move.b (a0)+,1(a2) move.b (a0)+,(a2) move.w (a2),d5 moveq #$F,d4 Process_Kos_Queue_ChkBit: move d6,ccr bcc.s Process_Kos_Queue_RLE move.b (a0)+,(a1)+ bra.s Process_Kos_Queue_Loop ; --------------------------------------------------------------------------- Process_Kos_Queue_RLE: moveq #0,d3 lsr.w #1,d5 move sr,d6 dbf d4,Process_Kos_Queue_ChkBit2 move.b (a0)+,1(a2) move.b (a0)+,(a2) move.w (a2),d5 moveq #$F,d4 Process_Kos_Queue_ChkBit2: move d6,ccr bcs.s Process_Kos_Queue_SeparateRLE lsr.w #1,d5 dbf d4,+ move.b (a0)+,1(a2) move.b (a0)+,(a2) move.w (a2),d5 moveq #$F,d4 + roxl.w #1,d3 lsr.w #1,d5 dbf d4,+ move.b (a0)+,1(a2) move.b (a0)+,(a2) move.w (a2),d5 moveq #$F,d4 + roxl.w #1,d3 addq.w #1,d3 moveq #-1,d2 move.b (a0)+,d2 bra.s Process_Kos_Queue_RLELoop ; --------------------------------------------------------------------------- Process_Kos_Queue_SeparateRLE: 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 Process_Kos_Queue_SeparateRLE2 move.b d1,d3 addq.w #1,d3 Process_Kos_Queue_RLELoop: move.b (a1,d2.w),d0 move.b d0,(a1)+ dbf d3,Process_Kos_Queue_RLELoop bra.s Process_Kos_Queue_Loop ; --------------------------------------------------------------------------- Process_Kos_Queue_SeparateRLE2: move.b (a0)+,d1 beq.s Process_Kos_Queue_EndReached cmpi.b #1,d1 beq.w Process_Kos_Queue_Loop move.b d1,d3 bra.s Process_Kos_Queue_RLELoop ; --------------------------------------------------------------------------- Process_Kos_Queue_EndReached: move.l a0,(Kos_decomp_queue).w move.l a1,(Kos_decomp_destination).w andi.w #$7FFF,(Kos_decomp_queue_count).w ; clear decompression in progress bit subq.w #1,(Kos_decomp_queue_count).w beq.s Process_Kos_Queue_Done ; branch if there aren't any entries remaining in the queue lea (Kos_decomp_queue).w,a0 lea (Kos_decomp_queue+8).w,a1 ; otherwise, shift all entries up move.l (a1)+,(a0)+ move.l (a1)+,(a0)+ move.l (a1)+,(a0)+ move.l (a1)+,(a0)+ move.l (a1)+,(a0)+ move.l (a1)+,(a0)+ Process_Kos_Queue_Done: rts ; --------------------------------------------------------------------------- Restore_Kos_Bookmark: movem.l (Kos_decomp_stored_registers).w,d0-d6/a0-a2 move.l (Kos_decomp_bookmark).w,-(sp) move.w (Kos_decomp_stored_SR).w,-(sp) rte ; --------------------------------------------------------------------------- Backup_Kos_Registers: move sr,(Kos_decomp_stored_SR).w movem.l d0-d6/a0-a2,(Kos_decomp_stored_registers).w rts ; --------------------------------------------------------------------------- ; Called at the end of each frame to perform vertical synchronization ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Wait_VSync: move #$2300,sr .loop: tst.b (V_int_routine).w bne.s .loop ; wait until V-int's run rts ; End of function Wait_VSync ; --------------------------------------------------------------------------- ; Generates a pseudo-random number in d0 ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Random_Number: move.l (RNG_seed).w,d1 tst.w d1 bne.s + move.l #$2A6D365B,d1 ; reset seed if needed + move.l d1,d0 asl.l #2,d1 add.l d0,d1 asl.l #3,d1 add.l d0,d1 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 Random_Number ; --------------------------------------------------------------------------- ; Calculates the sine and cosine of the angle in d0 (360 degrees = 256) ; Returns the sine in d0 and the cosine in d1 (both multiplied by $100) ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= GetSineCosine: andi.w #$FF,d0 add.w d0,d0 addi.w #$40*2,d0 ; $40 = 90 degrees, sin(x+90) = cos(x) move.w SineTable(pc,d0.w),d1 subi.w #$40*2,d0 move.w SineTable(pc,d0.w),d0 rts ; End of function GetSineCosine ; --------------------------------------------------------------------------- SineTable: binclude "Levels/Misc/sine.bin" even ; --------------------------------------------------------------------------- ; Calculates the arctangent of y/x and returns it in d0 (360 degrees = 256) ; Inputs: d1 = input x, d2 = input y ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= GetArcTan: 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 GetArcTan_Zero ; special case when both x and y are zero move.w d2,d4 tst.w d3 bpl.s + neg.w d3 + tst.w d4 bpl.s + neg.w d4 + cmp.w d3,d4 bhs.s + ; if |y| >= |x| lsl.l #8,d4 divu.w d3,d4 moveq #0,d0 move.b ArcTanTable(pc,d4.w),d0 bra.s ++ + lsl.l #8,d3 divu.w d4,d3 moveq #$40,d0 sub.b ArcTanTable(pc,d3.w),d0 ; arctan(y/x) = 90 - arctan(x/y) + tst.w d1 bpl.s + neg.w d0 addi.w #$80,d0 ; place angle in appropriate quadrant + tst.w d2 bpl.s + neg.w d0 addi.w #$100,d0 ; place angle in appropriate quadrant + movem.l (sp)+,d3-d4 rts ; --------------------------------------------------------------------------- GetArcTan_Zero: move.w #$40,d0 ; angle = 90 degrees movem.l (sp)+,d3-d4 rts ; End of function GetArcTan ; --------------------------------------------------------------------------- ArcTanTable: binclude "Levels/Misc/arctan.bin" even ; --------------------------------------------------------------------------- AnPal_Load: bsr.w SuperHyper_PalCycle moveq #0,d2 moveq #0,d0 move.w (Current_zone_and_act).w,d0 ror.b #1,d0 lsr.w #6,d0 move.w OffsAnPal(pc,d0.w),d0 jmp OffsAnPal(pc,d0.w) ; --------------------------------------------------------------------------- rts ; --------------------------------------------------------------------------- OffsAnPal: dc.w AnPal_AIZ1-OffsAnPal dc.w AnPal_AIZ2-OffsAnPal dc.w AnPal_HCZ1-OffsAnPal dc.w AnPal_HCZ2-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_CNZ-OffsAnPal dc.w AnPal_CNZ-OffsAnPal dc.w AnPal_FBZ-OffsAnPal dc.w AnPal_FBZ-OffsAnPal dc.w AnPal_ICZ-OffsAnPal dc.w AnPal_ICZ-OffsAnPal dc.w AnPal_LBZ1-OffsAnPal dc.w AnPal_LBZ2-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_SOZ1-OffsAnPal dc.w AnPal_SOZ2-OffsAnPal dc.w AnPal_LRZ1-OffsAnPal dc.w AnPal_LRZ2-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_DEZ1-OffsAnPal dc.w AnPal_DEZ2-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_BPZ-OffsAnPal dc.w AnPal_BPZ-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_CGZ-OffsAnPal dc.w AnPal_CGZ-OffsAnPal dc.w AnPal_EMZ-OffsAnPal dc.w AnPal_EMZ-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_Pachinko-OffsAnPal dc.w AnPal_Pachinko-OffsAnPal dc.w AnPal_Slots-OffsAnPal dc.w AnPal_Slots-OffsAnPal dc.w AnPal_LRZ3-OffsAnPal dc.w AnPal_HPZ-OffsAnPal dc.w AnPal_None-OffsAnPal dc.w AnPal_HPZ-OffsAnPal ; --------------------------------------------------------------------------- AnPal_None: rts ; --------------------------------------------------------------------------- AnPal_AIZ1: move.b (AIZ1_palette_cycle_flag).w,d0 bne.s loc_221E subq.w #1,(Palette_cycle_counter1).w bpl.s locret_221C move.w #7,(Palette_cycle_counter1).w move.w (Palette_cycle_counter0).w,d0 addq.w #8,(Palette_cycle_counter0).w andi.w #$18,d0 lea (AnPal_PalAIZ1_1).l,a0 move.l (a0,d0.w),(Normal_palette_line_3+$16).w move.l 4(a0,d0.w),(Normal_palette_line_3+$1A).w tst.b (Palette_cycle_counters+$00).w bne.s locret_221C move.w (Palette_cycle_counters+$02).w,d0 addq.w #6,(Palette_cycle_counters+$02).w cmpi.w #$30,(Palette_cycle_counters+$02).w blo.s loc_220A move.w #0,(Palette_cycle_counters+$02).w loc_220A: lea (AnPal_PalAIZ1_2).l,a0 move.l (a0,d0.w),(Normal_palette_line_4+$18).w move.w 4(a0,d0.w),(Normal_palette_line_4+$1C).w locret_221C: rts ; --------------------------------------------------------------------------- loc_221E: subq.w #1,(Palette_cycle_counter1).w bpl.s locret_227A move.w #9,(Palette_cycle_counter1).w move.w (Palette_cycle_counter0).w,d0 addq.w #8,(Palette_cycle_counter0).w cmpi.w #$50,(Palette_cycle_counter0).w blo.s loc_2240 move.w #0,(Palette_cycle_counter0).w loc_2240: lea (AnPal_PalAIZ1_3).l,a0 move.l (a0,d0.w),(Normal_palette_line_4+$04).w move.l 4(a0,d0.w),(Normal_palette_line_4+$08).w move.w (Palette_cycle_counters+$02).w,d0 addq.w #6,(Palette_cycle_counters+$02).w cmpi.w #$3C,(Palette_cycle_counters+$02).w blo.s loc_2268 move.w #0,(Palette_cycle_counters+$02).w loc_2268: lea (AnPal_PalAIZ1_4).l,a0 move.l (a0,d0.w),(Normal_palette_line_4+$1A).w move.w 4(a0,d0.w),(Normal_palette_line_4+$1E).w locret_227A: rts ; --------------------------------------------------------------------------- AnPal_AIZ2: subq.w #1,(Palette_cycle_counter1).w bpl.s loc_22F6 move.w #5,(Palette_cycle_counter1).w move.w (Palette_cycle_counter0).w,d0 addq.w #8,(Palette_cycle_counter0).w andi.w #$18,d0 lea (AnPal_PalAIZ2_1).l,a0 move.l (a0,d0.w),(Normal_palette_line_4+$18).w move.l 4(a0,d0.w),(Normal_palette_line_4+$1C).w move.w (Palette_cycle_counters+$02).w,d0 addq.w #6,(Palette_cycle_counters+$02).w cmpi.w #$30,(Palette_cycle_counters+$02).w blo.s loc_22BC move.w #0,(Palette_cycle_counters+$02).w loc_22BC: lea (AnPal_PalAIZ2_2).l,a0 cmpi.w #$3800,(Camera_X_pos).w blo.s loc_22D0 lea (AnPal_PalAIZ2_3).l,a0 loc_22D0: move.w (a0,d0.w),(Normal_palette_line_3+$08).w move.w 2(a0,d0.w),(Normal_palette_line_3+$10).w move.w 4(a0,d0.w),(Normal_palette_line_4+$16).w move.w #$A0E,(Normal_palette_line_3+$1C).w cmpi.w #$1C0,(Camera_X_pos).w bhs.s loc_22F6 move.w 4(a0,d0.w),(Normal_palette_line_3+$1C).w loc_22F6: subq.w #1,(Palette_cycle_counters+$08).w bpl.s locret_2332 move.w #1,(Palette_cycle_counters+$08).w move.w (Palette_cycle_counters+$04).w,d0 addq.w #2,(Palette_cycle_counters+$04).w cmpi.w #$34,(Palette_cycle_counters+$04).w blo.s loc_2318 move.w #0,(Palette_cycle_counters+$04).w loc_2318: lea (AnPal_PalAIZ2_4).l,a0 cmpi.w #$3800,(Camera_X_pos).w blo.s loc_232C lea (AnPal_PalAIZ2_5).l,a0 loc_232C: move.w (a0,d0.w),(Normal_palette_line_4+$02).w locret_2332: rts ; =============== S U B R O U T I N E ======================================= AnPal_HCZ1: subq.w #1,(Palette_cycle_counter1).w bpl.s locret_2380 move.w #7,(Palette_cycle_counter1).w tst.b (Palette_cycle_counters+$00).w beq.s loc_234C move.w #0,(Palette_cycle_counter1).w loc_234C: lea (AnPal_PalHCZ1).l,a0 move.w (Palette_cycle_counter0).w,d0 addq.w #8,(Palette_cycle_counter0).w cmpi.w #$20,(Palette_cycle_counter0).w blo.s loc_2368 move.w #0,(Palette_cycle_counter0).w loc_2368: move.l (a0,d0.w),(Normal_palette_line_3+$06).w move.l 4(a0,d0.w),(Normal_palette_line_3+$0A).w move.l (a0,d0.w),(Water_palette_line_3+$06).w move.l 4(a0,d0.w),(Water_palette_line_3+$0A).w locret_2380: rts ; End of function AnPal_HCZ1 ; --------------------------------------------------------------------------- AnPal_HCZ2: rts ; --------------------------------------------------------------------------- AnPal_CNZ: subq.w #1,(Palette_cycle_counter1).w bpl.s loc_23CA move.w #3,(Palette_cycle_counter1).w lea (AnPal_PalCNZ_1).l,a0 move.w (Palette_cycle_counter0).w,d0 addq.w #6,(Palette_cycle_counter0).w cmpi.w #$60,(Palette_cycle_counter0).w blo.s loc_23AC move.w #0,(Palette_cycle_counter0).w loc_23AC: move.l (a0,d0.w),(Normal_palette_line_4+$12).w move.w 4(a0,d0.w),(Normal_palette_line_4+$16).w lea (AnPal_PalCNZ_2).l,a0 move.l (a0,d0.w),(Water_palette_line_4+$12).w move.w 4(a0,d0.w),(Water_palette_line_4+$16).w loc_23CA: lea (AnPal_PalCNZ_3).l,a0 move.w (Palette_cycle_counters+$02).w,d0 addq.w #6,(Palette_cycle_counters+$02).w cmpi.w #$B4,(Palette_cycle_counters+$02).w blo.s loc_23E6 move.w #0,(Palette_cycle_counters+$02).w loc_23E6: move.l (a0,d0.w),(Normal_palette_line_3+$12).w move.w 4(a0,d0.w),(Normal_palette_line_3+$16).w lea (AnPal_PalCNZ_4).l,a0 move.l (a0,d0.w),(Water_palette_line_3+$12).w move.w 4(a0,d0.w),(Water_palette_line_3+$16).w subq.w #1,(Palette_cycle_counters+$08).w bpl.s locret_243E move.w #2,(Palette_cycle_counters+$08).w lea (AnPal_PalCNZ_5).l,a0 move.w (Palette_cycle_counters+$04).w,d0 addq.w #4,(Palette_cycle_counters+$04).w cmpi.w #$40,(Palette_cycle_counters+$04).w blo.s loc_242C move.w #0,(Palette_cycle_counters+$04).w loc_242C: move.l (a0,d0.w),(Normal_palette_line_3+$E).w lea (AnPal_PalCNZ_5).l,a0 move.l (a0,d0.w),(Water_palette_line_3+$E).w locret_243E: rts ; --------------------------------------------------------------------------- AnPal_FBZ: tst.b (Level_frame_counter+1).w bne.s locret_244C bchg #0,(_unkF7C1).w locret_244C: rts ; --------------------------------------------------------------------------- AnPal_ICZ: subq.w #1,(Palette_cycle_counter1).w bpl.s loc_247C move.w #5,(Palette_cycle_counter1).w lea (AnPal_PalICZ_1).l,a0 move.w (Palette_cycle_counter0).w,d0 addq.w #4,(Palette_cycle_counter0).w cmpi.w #$40,(Palette_cycle_counter0).w blo.s loc_2476 move.w #0,(Palette_cycle_counter0).w loc_2476: move.l (a0,d0.w),(Normal_palette_line_3+$1C).w loc_247C: subq.w #1,(Palette_cycle_counters+$08).w bpl.s loc_24B0 move.w #9,(Palette_cycle_counters+$08).w lea (AnPal_PalICZ_2).l,a0 move.w (Palette_cycle_counters+$02).w,d0 addq.w #4,(Palette_cycle_counters+$02).w cmpi.w #$48,(Palette_cycle_counters+$02).w blo.s loc_24A4 move.w #0,(Palette_cycle_counters+$02).w loc_24A4: tst.w (Events_bg+$16).w beq.s loc_24B0 move.l (a0,d0.w),(Normal_palette_line_4+$1C).w loc_24B0: subq.w #1,(Palette_cycle_counters+$0A).w bpl.s locret_2506 move.w #7,(Palette_cycle_counters+$0A).w lea (AnPal_PalICZ_3).l,a0 move.w (Palette_cycle_counters+$04).w,d0 addq.w #4,(Palette_cycle_counters+$04).w cmpi.w #$18,(Palette_cycle_counters+$04).w blo.s loc_24D8 move.w #0,(Palette_cycle_counters+$04).w loc_24D8: tst.w (Events_bg+$16).w beq.s loc_24E4 move.l (a0,d0.w),(Normal_palette_line_4+$18).w loc_24E4: lea (AnPal_PalICZ_4).l,a0 move.w (Palette_cycle_counters+$06).w,d0 addq.w #4,(Palette_cycle_counters+$06).w cmpi.w #$40,(Palette_cycle_counters+$06).w blo.s loc_2500 move.w #0,(Palette_cycle_counters+$06).w loc_2500: move.l (a0,d0.w),(Normal_palette_line_3+$18).w locret_2506: rts ; --------------------------------------------------------------------------- AnPal_LBZ1: lea (AnPal_PalLBZ1).l,a0 bra.s loc_2516 ; --------------------------------------------------------------------------- AnPal_LBZ2: lea (AnPal_PalLBZ2).l,a0 loc_2516: subq.w #1,(Palette_cycle_counter1).w bpl.s locret_2544 move.w #3,(Palette_cycle_counter1).w move.w (Palette_cycle_counter0).w,d0 addq.w #6,(Palette_cycle_counter0).w cmpi.w #$12,(Palette_cycle_counter0).w blo.s loc_2538 move.w #0,(Palette_cycle_counter0).w loc_2538: move.l (a0,d0.w),(Normal_palette_line_3+$10).w move.w 4(a0,d0.w),(Normal_palette_line_3+$14).w locret_2544: rts ; --------------------------------------------------------------------------- AnPal_SOZ1: subq.w #1,(Palette_cycle_counters+$0A).w bpl.s locret_257A move.w #5,(Palette_cycle_counters+$0A).w lea (AnPal_PalSOZ1).l,a0 move.w (Palette_cycle_counters+$04).w,d0 addq.w #8,(Palette_cycle_counters+$04).w cmpi.w #$20,(Palette_cycle_counters+$04).w blo.s loc_256E move.w #0,(Palette_cycle_counters+$04).w loc_256E: move.l (a0,d0.w),(Normal_palette_line_3+$18).w move.l 4(a0,d0.w),(Normal_palette_line_3+$1C).w locret_257A: rts ; --------------------------------------------------------------------------- ; unused move.w #900-1,(Palette_cycle_counter1).w move.b #0,(_unkF7C3).w move.w (Palette_cycle_counters+$06).w,d0 neg.b d0 move.b d0,(Palette_cycle_counters+$00).w move.w #0,(Palette_cycle_counters+$08).w AnPal_SOZ2: subq.w #1,(Palette_cycle_counter1).w bpl.s loc_25C4 move.w #900-1,(Palette_cycle_counter1).w cmpi.b #5,(_unkF7C3).w bhs.s loc_25C4 addq.b #1,(_unkF7C3).w btst #0,(_unkF7C3).w bne.s loc_25C4 move.b #2,(Palette_cycle_counters+$00).w move.w #0,(Palette_cycle_counters+$08).w loc_25C4: tst.b (Palette_cycle_counters+$00).w beq.s loc_262C subq.w #1,(Palette_cycle_counters+$08).w bpl.s loc_262C move.w #3,(Palette_cycle_counters+$08).w tst.b (Palette_cycle_counters+$00).w bmi.s loc_25EC subq.b #1,(Palette_cycle_counters+$00).w addi.w #$34,(Palette_cycle_counters+$02).w addq.w #1,(Palette_cycle_counters+$06).w bra.s loc_25FA ; --------------------------------------------------------------------------- loc_25EC: addq.b #1,(Palette_cycle_counters+$00).w subi.w #$34,(Palette_cycle_counters+$02).w subq.w #1,(Palette_cycle_counters+$06).w loc_25FA: move.w (Palette_cycle_counters+$02).w,d0 lea (AnPal_PalSOZ2_Light).l,a0 lea (a0,d0.w),a0 lea (Normal_palette_line_3+$2).w,a1 moveq #$B-1,d0 loc_260E: move.w (a0)+,(a1)+ dbf d0,loc_260E lea (Normal_palette_line_4+$2).w,a1 moveq #$F-1,d0 loc_261A: move.w (a0)+,(a1)+ dbf d0,loc_261A move.w (Palette_cycle_counters+$04).w,d0 subq.w #1,(Palette_cycle_counters+$0A).w bpl.s loc_264E bra.s loc_2632 ; --------------------------------------------------------------------------- loc_262C: subq.w #1,(Palette_cycle_counters+$0A).w bpl.s locret_266A loc_2632: move.w #5,(Palette_cycle_counters+$0A).w move.w (Palette_cycle_counters+$04).w,d0 addq.w #8,(Palette_cycle_counters+$04).w cmpi.w #$20,(Palette_cycle_counters+$04).w blo.s loc_264E move.w #0,(Palette_cycle_counters+$04).w loc_264E: lea (AnPal_PalSOZ1).l,a0 move.w (Palette_cycle_counters+$06).w,d1 lsl.w #5,d1 lea (a0,d1.w),a0 move.l (a0,d0.w),(Normal_palette_line_3+$18).w move.l 4(a0,d0.w),(Normal_palette_line_3+$1C).w locret_266A: rts ; --------------------------------------------------------------------------- AnPal_LRZ1: subq.w #1,(Palette_cycle_counter1).w bpl.s loc_26C2 move.w #$F,(Palette_cycle_counter1).w move.w (Palette_cycle_counter0).w,d0 addq.w #8,(Palette_cycle_counter0).w cmpi.w #$80,(Palette_cycle_counter0).w blo.s loc_268E move.w #0,(Palette_cycle_counter0).w loc_268E: lea (AnPal_PalLRZ12_1).l,a0 move.l (a0,d0.w),(Normal_palette_line_3+$02).w move.l 4(a0,d0.w),(Normal_palette_line_3+$06).w move.w (Palette_cycle_counters+$02).w,d0 addq.w #4,(Palette_cycle_counters+$02).w cmpi.w #$1C,(Palette_cycle_counters+$02).w blo.s loc_26B6 move.w #0,(Palette_cycle_counters+$02).w loc_26B6: lea (AnPal_PalLRZ12_2).l,a0 move.l (a0,d0.w),(Normal_palette_line_4+$02).w loc_26C2: subq.w #1,(Palette_cycle_counters+$08).w bpl.s locret_26F0 move.w #7,(Palette_cycle_counters+$08).w move.w (Palette_cycle_counters+$04).w,d0 addq.w #2,(Palette_cycle_counters+$04).w cmpi.w #$22,(Palette_cycle_counters+$04).w blo.s loc_26E4 move.w #0,(Palette_cycle_counters+$04).w loc_26E4: lea (AnPal_PalLRZ1_3).l,a0 move.w (a0,d0.w),(Normal_palette_line_3+$16).w locret_26F0: rts ; --------------------------------------------------------------------------- AnPal_LRZ2: subq.w #1,(Palette_cycle_counter1).w bpl.s loc_2748 move.w #$F,(Palette_cycle_counter1).w move.w (Palette_cycle_counter0).w,d0 addq.w #8,(Palette_cycle_counter0).w cmpi.w #$80,(Palette_cycle_counter0).w blo.s loc_2714 move.w #0,(Palette_cycle_counter0).w loc_2714: lea (AnPal_PalLRZ12_1).l,a0 move.l (a0,d0.w),(Normal_palette_line_3+$2).w move.l 4(a0,d0.w),(Normal_palette_line_3+$6).w move.w (Palette_cycle_counters+$02).w,d0 addq.w #4,(Palette_cycle_counters+$02).w cmpi.w #$1C,(Palette_cycle_counters+$02).w blo.s loc_273C move.w #0,(Palette_cycle_counters+$02).w loc_273C: lea (AnPal_PalLRZ12_2).l,a0 move.l (a0,d0.w),(Normal_palette_line_4+$2).w loc_2748: subq.w #1,(Palette_cycle_counters+$08).w bpl.s locret_277C move.w #$F,(Palette_cycle_counters+$08).w move.w (Palette_cycle_counters+$04).w,d0 addq.w #8,(Palette_cycle_counters+$04).w cmpi.w #$100,(Palette_cycle_counters+$04).w blo.s loc_276A move.w #0,(Palette_cycle_counters+$04).w loc_276A: lea (AnPal_PalLRZ2_3).l,a0 move.l (a0,d0.w),(Normal_palette_line_4+$16).w move.l (a0,d0.w),(Normal_palette_line_4+$1A).w locret_277C: rts ; --------------------------------------------------------------------------- AnPal_DEZ1: subq.w #1,(Palette_cycle_counters+$0A).w bpl.s AnPal_DEZ2 move.w #$F,(Palette_cycle_counters+$0A).w move.w (Palette_cycle_counters+$04).w,d0 addq.w #8,(Palette_cycle_counters+$04).w cmpi.w #$30,(Palette_cycle_counters+$04).w blo.s loc_27A0 move.w #0,(Palette_cycle_counters+$04).w loc_27A0: lea (AnPal_PalDEZ1).l,a0 move.l (a0,d0.w),(Normal_palette_line_4+$18).w move.l 4(a0,d0.w),(Normal_palette_line_4+$1C).w AnPal_DEZ2: subq.w #1,(Palette_cycle_counter1).w bpl.s loc_27E0 move.w #4,(Palette_cycle_counter1).w move.w (Palette_cycle_counter0).w,d0 addq.w #4,(Palette_cycle_counter0).w cmpi.w #$30,(Palette_cycle_counter0).w blo.s loc_27D4 move.w #0,(Palette_cycle_counter0).w loc_27D4: lea (AnPal_PalDEZ12_1).l,a0 move.l (a0,d0.w),(Normal_palette_line_3+$1A).w loc_27E0: subq.w #1,(Palette_cycle_counters+$08).w bpl.s locret_2818 move.w #$13,(Palette_cycle_counters+$08).w move.w (Palette_cycle_counters+$02).w,d0 addi.w #$A,(Palette_cycle_counters+$02).w cmpi.w #$28,(Palette_cycle_counters+$02).w blo.s loc_2804 move.w #0,(Palette_cycle_counters+$02).w loc_2804: lea (AnPal_PalDEZ12_2).l,a0 lea (a0,d0.w),a0 lea (Normal_palette_line_3+$10).w,a1 move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.w (a0)+,(a1)+ locret_2818: rts ; --------------------------------------------------------------------------- AnPal_BPZ: subq.w #1,(Palette_cycle_counter1).w bpl.s loc_284E move.w #7,(Palette_cycle_counter1).w lea (AnPal_PalBPZ_1).l,a0 move.w (Palette_cycle_counter0).w,d0 addq.w #6,(Palette_cycle_counter0).w cmpi.w #$12,(Palette_cycle_counter0).w blo.s loc_2842 move.w #0,(Palette_cycle_counter0).w loc_2842: move.l (a0,d0.w),(Normal_palette_line_3+$1A).w move.w 4(a0,d0.w),(Normal_palette_line_3+$1E).w loc_284E: subq.w #1,(Palette_cycle_counters+$08).w bpl.s locret_2882 move.w #$11,(Palette_cycle_counters+$08).w lea (AnPal_PalBPZ_2).l,a0 move.w (Palette_cycle_counters+$02).w,d0 addq.w #6,(Palette_cycle_counters+$02).w cmpi.w #$7E,(Palette_cycle_counters+$02).w blo.s loc_2876 move.w #0,(Palette_cycle_counters+$02).w loc_2876: move.l (a0,d0.w),(Normal_palette_line_4+$04).w move.w 4(a0,d0.w),(Normal_palette_line_4+$08).w locret_2882: rts ; --------------------------------------------------------------------------- AnPal_CGZ: subq.w #1,(Palette_cycle_counter1).w bpl.s locret_28B8 move.w #9,(Palette_cycle_counter1).w lea (AnPal_PalCGZ).l,a0 move.w (Palette_cycle_counter0).w,d0 addq.w #8,(Palette_cycle_counter0).w cmpi.w #$50,(Palette_cycle_counter0).w blo.s loc_28AC move.w #0,(Palette_cycle_counter0).w loc_28AC: move.l (a0,d0.w),(Normal_palette_line_3+$04).w move.l 4(a0,d0.w),(Normal_palette_line_3+$08).w locret_28B8: rts ; --------------------------------------------------------------------------- AnPal_EMZ: subq.w #1,(Palette_cycle_counter1).w bpl.s loc_28E8 move.w #7,(Palette_cycle_counter1).w lea (AnPal_PalEMZ_1).l,a0 move.w (Palette_cycle_counter0).w,d0 addq.w #2,(Palette_cycle_counter0).w cmpi.w #$3C,(Palette_cycle_counter0).w blo.s loc_28E2 move.w #0,(Palette_cycle_counter0).w loc_28E2: move.w 4(a0,d0.w),(Normal_palette_line_3+$1C).w loc_28E8: subq.w #1,(Palette_cycle_counters+$08).w bpl.s locret_2916 move.w #$1F,(Palette_cycle_counters+$08).w lea (AnPal_PalEMZ_2).l,a0 move.w (Palette_cycle_counters+$02).w,d0 addq.w #4,(Palette_cycle_counters+$02).w cmpi.w #$34,(Palette_cycle_counters+$02).w blo.s loc_2910 move.w #0,(Palette_cycle_counters+$02).w loc_2910: move.l (a0,d0.w),(Normal_palette_line_4+$12).w locret_2916: rts ; --------------------------------------------------------------------------- AnPal_Pachinko: subq.w #1,(Palette_cycle_counter1).w bpl.s loc_2952 move.w #0,(Palette_cycle_counter1).w move.w (Palette_cycle_counter0).w,d0 addi.w #$E,(Palette_cycle_counter0).w cmpi.w #$FC,(Palette_cycle_counter0).w blo.s loc_293C move.w #0,(Palette_cycle_counter0).w loc_293C: lea (Chunk_table+$7800).l,a0 lea (Normal_palette_line_4+$10).w,a1 lea (a0,d0.w),a0 move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.w (a0)+,(a1)+ loc_2952: subq.w #1,(Palette_cycle_counters+$08).w bpl.s locret_29A6 move.w #3,(Palette_cycle_counters+$08).w move.w (Palette_cycle_counters+$02).w,d0 addi.w #$A,(Palette_cycle_counters+$02).w cmpi.w #$3E8,(Palette_cycle_counters+$02).w blo.s loc_2976 move.w #0,(Palette_cycle_counters+$02).w loc_2976: lea (Chunk_table+$78FC).l,a0 lea (Normal_palette_line_3+$2).w,a1 lea (a0,d0.w),a0 move.l $50(a0),(a1)+ move.l $54(a0),(a1)+ move.w $58(a0),(a1)+ move.l $28(a0),(a1)+ move.l $2C(a0),(a1)+ move.w $30(a0),(a1)+ move.l (a0),(a1)+ move.l 4(a0),(a1)+ move.w 8(a0),(a1)+ locret_29A6: rts ; --------------------------------------------------------------------------- AnPal_Slots: tst.b (Palette_cycle_counters+$00).w bmi.s locret_29F0 bne.s loc_29F2 subq.w #1,(Palette_cycle_counter1).w bpl.s locret_29F0 move.w #3,(Palette_cycle_counter1).w move.w (Palette_cycle_counter0).w,d0 addq.w #8,(Palette_cycle_counter0).w cmpi.w #$40,(Palette_cycle_counter0).w blo.s loc_29D2 move.w #0,(Palette_cycle_counter0).w loc_29D2: lea (AnPal_PalSlots_1).l,a0 move.l (a0,d0.w),(Normal_palette_line_3+$14).w move.l 4(a0,d0.w),(Normal_palette_line_3+$18).w move.w #$E02,(Normal_palette_line_3+$1C).w move.w #$E02,(Normal_palette_line_4+$1C).w locret_29F0: rts ; --------------------------------------------------------------------------- loc_29F2: subq.w #1,(Palette_cycle_counters+$08).w bpl.s locret_2A4E move.w #0,(Palette_cycle_counters+$08).w move.w (Palette_cycle_counters+$02).w,d0 addq.w #8,(Palette_cycle_counters+$02).w cmpi.w #$78,(Palette_cycle_counters+$02).w blo.s loc_2A14 move.w #0,(Palette_cycle_counters+$02).w loc_2A14: lea (AnPal_PalSlots_2).l,a0 move.l (a0,d0.w),(Normal_palette_line_3+$14).w move.l 4(a0,d0.w),(Normal_palette_line_3+$18).w move.w (Palette_cycle_counters+$04).w,d0 addq.w #2,(Palette_cycle_counters+$04).w cmpi.w #$C,(Palette_cycle_counters+$04).w blo.s loc_2A3C move.w #0,(Palette_cycle_counters+$04).w loc_2A3C: lea (AnPal_PalSlots_3).l,a0 move.w (a0,d0.w),(Normal_palette_line_3+$1C).w move.w (a0,d0.w),(Normal_palette_line_4+$1C).w locret_2A4E: rts ; --------------------------------------------------------------------------- AnPal_LRZ3: tst.b (Palette_cycle_counters+$00).w bmi.s locret_2ABE subq.w #1,(Palette_cycle_counter1).w bpl.s loc_2A8A move.w #$F,(Palette_cycle_counter1).w move.w (Palette_cycle_counter0).w,d0 addq.w #8,(Palette_cycle_counter0).w cmpi.w #$80,(Palette_cycle_counter0).w blo.s loc_2A78 move.w #0,(Palette_cycle_counter0).w loc_2A78: lea (AnPal_PalLRZ12_1).l,a0 move.l (a0,d0.w),(Normal_palette_line_3+$2).w move.l 4(a0,d0.w),(Normal_palette_line_3+$6).w loc_2A8A: tst.b (Palette_cycle_counters+$00).w beq.s locret_2ABE subq.w #1,(Palette_cycle_counters+$08).w bpl.s locret_2ABE move.w #7,(Palette_cycle_counters+$08).w move.w (Palette_cycle_counters+$04).w,d0 addq.w #4,(Palette_cycle_counters+$04).w cmpi.w #$3C,(Palette_cycle_counters+$04).w blo.s loc_2AB2 move.w #0,(Palette_cycle_counters+$04).w loc_2AB2: lea (AnPal_PalLRZ3).l,a0 move.l (a0,d0.w),(Normal_palette_line_4+$18).w locret_2ABE: rts ; --------------------------------------------------------------------------- AnPal_HPZ: tst.b (Palette_cycle_counters+$00).w bne.s locret_2AF4 subq.w #1,(Palette_cycle_counter1).w bpl.s locret_2AF4 move.w #7,(Palette_cycle_counter1).w move.w (Palette_cycle_counter0).w,d0 addq.w #4,(Palette_cycle_counter0).w cmpi.w #$28,(Palette_cycle_counter0).w blo.s loc_2AE8 move.w #0,(Palette_cycle_counter0).w loc_2AE8: lea (AnPal_PalHPZ).l,a0 move.l (a0,d0.w),(Normal_palette_line_4+$2).w locret_2AF4: rts ; --------------------------------------------------------------------------- AnPal_PalAIZ1_1: dc.w $EE8, $EE2, $EA4, $E64 dc.w $EE2, $EA4, $E64, $EE8 dc.w $EA4, $E64, $EE8, $EE2 dc.w $E64, $EE8, $EE2, $EA4 AnPal_PalAIZ1_3: dc.w $EEC, $EEE, $EE8, $E40 dc.w $EEC, $EE8, $EE8, $EEE dc.w $EEA, $E86, $EE8, $EE8 dc.w $EE8, $E40, $EE8, $E86 dc.w $EE6, $EEE, $EE8, $E40 dc.w $EEA, $EE8, $EE8, $EEE dc.w $EE8, $E86, $EE8, $EE8 dc.w $EE8, $E40, $EE8, $E86 dc.w $EE6, $EEE, $EE8, $E40 dc.w $EE8, $EE8, $EE8, $EEE dc.w $EEA, $E86, $EE8, $EE8 dc.w $EEC, $E40, $EE8, $E86 dc.w $EEC, $EEE, $EE8, $E40 dc.w $EEC, $EE8, $EE8, $EEE dc.w $EEC, $E86, $EE8, $EE8 dc.w $EEC, $E40, $EE8, $E86 AnPal_PalAIZ1_4: dc.w $CEC, $CEE, $EEE dc.w $CEE, $EEE, $EEE dc.w $EEE, $EEE, $EEE dc.w $EEE, $EEE, $EEE dc.w $EEE, $EEE, $EEE dc.w $EEE, $EEE, $EEE dc.w $EEE, $EEE, $EEE dc.w $EE8, $EEE, $EEE dc.w $EE8, $EE8, $EEE dc.w $EE8, $EE8, $EE8 dc.w $EE8, $EE8, $EE8 dc.w $EE8, $EE8, $EE8 dc.w $EE8, $EE8, $EE8 dc.w $EE8, $EE8, $AEC dc.w $EE8, $AEC, $CEC dc.w $AEC, $CEC, $CEC AnPal_PalAIZ1_2: dc.w $EA4, $E60, $EE2 dc.w $EA4, $EE8, $EA4 dc.w $E60, $EE8, $EEE dc.w $E60, $EE2, $EE2 dc.w $EE8, $EA4, $EA4 dc.w $EE2, $E60, $E60 dc.w $EE2, $E60, $EEE dc.w $EE2, $E60, $EE8 AnPal_PalAIZ2_1: dc.w $EE8, $EE2, $EC4, $EA4 dc.w $EE2, $EC4, $EA4, $EE8 dc.w $EC4, $EA4, $EE8, $EE2 dc.w $EA4, $EE8, $EE2, $EC4 AnPal_PalAIZ2_2: dc.w $24, $44, $8E dc.w $26, $46, $AE dc.w $24, $48, $8E dc.w $26, $4A, $AE dc.w $24, $4C, $8E dc.w $26, $4A, $AE dc.w $24, $48, $8E dc.w $24, $46, $8E AnPal_PalAIZ2_3: dc.w $24, $44, $C dc.w $26, $46, $E dc.w $24, $48, $C dc.w $26, $4A, $E dc.w $24, $4C, $C dc.w $26, $4A, $E dc.w $24, $48, $C dc.w $24, $46, $C AnPal_PalAIZ2_4: dc.w $6E dc.w $6E dc.w $6E dc.w $6E dc.w $28E dc.w $4AE dc.w $6AE dc.w $8CE dc.w $8EE dc.w $AEE dc.w $AEE dc.w $AEE dc.w $AEE dc.w $AEE dc.w $8EE dc.w $8EE dc.w $8EE dc.w $8EE dc.w $8CE dc.w $8CE dc.w $8CE dc.w $6AE dc.w $6AE dc.w $4AE dc.w $4AE dc.w $28E AnPal_PalAIZ2_5: dc.w $C dc.w $C dc.w $C dc.w $C dc.w $2C dc.w $E dc.w $2E dc.w $4E dc.w $6E dc.w $8E dc.w $8E dc.w $8E dc.w $8E dc.w $8E dc.w $6E dc.w $4E dc.w $4E dc.w $4E dc.w $2E dc.w $2E dc.w $2E dc.w $E dc.w $E dc.w $2C dc.w $2C dc.w $2C AnPal_PalHCZ1: dc.w $EC8, $EC0, $EA0, $E80 dc.w $EC0, $EA0, $E80, $EC8 dc.w $EA0, $E80, $EC8, $EC0 dc.w $E80, $EC8, $EC0, $EA0 AnPal_PalCNZ_1: dc.w 0, $66, $EE dc.w $22, $44, $CC dc.w $44, $22, $AA dc.w $66, 0, $88 dc.w $88, 0, $66 dc.w $AA, $22, $44 dc.w $CC, $44, $22 dc.w $EE, $66, 0 dc.w $EE, $88, 0 dc.w $CC, $AA, $22 dc.w $AA, $CC, $44 dc.w $88, $EE, $66 dc.w $66, $EE, $88 dc.w $44, $CC, $AA dc.w $22, $AA, $CC dc.w 0, $88, $EE AnPal_PalCNZ_3: dc.w $E20, $8A, $C0E dc.w $C42, $6C, $E0E dc.w $A64, $4C, $E0C dc.w $884, $2E, $E0A dc.w $6A6, $E, $E08 dc.w $4C6, $20E, $E06 dc.w $2E8, $40E, $E04 dc.w $E8, $60E, $E02 dc.w $C8, $80E, $E00 dc.w $AA, $A0E, $E00 dc.w $8A, $C0E, $E20 dc.w $6C, $E0E, $C42 dc.w $4C, $E0C, $A64 dc.w $2E, $E0A, $884 dc.w $E, $E08, $6A6 dc.w $20E, $E06, $4C6 dc.w $40E, $E04, $2E8 dc.w $60E, $E02, $E8 dc.w $80E, $E00, $C8 dc.w $A0E, $E00, $AA dc.w $C0E, $E20, $8A dc.w $E0E, $C42, $6C dc.w $E0C, $A64, $4C dc.w $E0A, $884, $2E dc.w $E08, $6A6, $E dc.w $E06, $4C6, $20E dc.w $E04, $2E8, $40E dc.w $E02, $E8, $60E dc.w $E00, $C8, $80E dc.w $E00, $AA, $A0E AnPal_PalCNZ_5: dc.w $2E0, $ECE dc.w $4E2, $EAC dc.w $6E4, $E8A dc.w $8E6, $E68 dc.w $AE8, $E46 dc.w $CEA, $E24 dc.w $EEC, $E02 dc.w $EEE, $E00 dc.w $EEC, $E02 dc.w $CEA, $E24 dc.w $AE8, $E46 dc.w $8E6, $E68 dc.w $6E4, $E8A dc.w $4E2, $EAC dc.w $2E0, $ECE dc.w $E0, $EEE AnPal_PalCNZ_2: dc.w $800, $800, $886 dc.w $800, $800, $864 dc.w $800, $800, $842 dc.w $800, $800, $820 dc.w $820, $800, $800 dc.w $842, $800, $800 dc.w $864, $800, $800 dc.w $886, $800, $800 dc.w $886, $820, $800 dc.w $864, $842, $800 dc.w $842, $864, $800 dc.w $820, $886, $800 dc.w $800, $886, $820 dc.w $800, $864, $842 dc.w $800, $842, $864 dc.w $800, $820, $886 AnPal_PalCNZ_4: dc.w $E20, $E8A, $E0A dc.w $E42, $E6A, $E0A dc.w $E64, $E4A, $E0A dc.w $E84, $E2A, $E0A dc.w $EA6, $E0A, $E08 dc.w $EC6, $E0A, $E06 dc.w $EE8, $E0A, $E04 dc.w $EE8, $E0A, $E02 dc.w $EC8, $E0A, $E00 dc.w $EAA, $E0A, $E00 dc.w $E8A, $E0A, $E20 dc.w $E6A, $E0A, $C42 dc.w $E4A, $E0A, $E64 dc.w $E2A, $E0A, $E84 dc.w $E0A, $E08, $EA6 dc.w $E0A, $E06, $EC6 dc.w $E0A, $E04, $EE8 dc.w $E0A, $E02, $EE8 dc.w $E0A, $E00, $EC8 dc.w $E0A, $E00, $EAA dc.w $E0A, $E20, $E8A dc.w $E0A, $E42, $E6A dc.w $E0A, $E64, $E4A dc.w $E0A, $E84, $E2A dc.w $E08, $EA6, $E0A dc.w $E06, $EC6, $E0A dc.w $E04, $EE8, $E0A dc.w $E02, $EE8, $E0A dc.w $E00, $EC8, $E0A dc.w $E00, $EAA, $E0A dc.w $840, $ECA dc.w $862, $EAA dc.w $884, $E88 dc.w $8A6, $E66 dc.w $AE8, $E44 dc.w $CEA, $E22 dc.w $EEC, $E00 dc.w $EEC, $E00 dc.w $EEC, $E00 dc.w $CEA, $E22 dc.w $AE8, $E44 dc.w $8A6, $E66 dc.w $884, $E88 dc.w $862, $EAA dc.w $840, $ECA dc.w $822, $ECA AnPal_PalICZ_1: dc.w $E62, $E20 dc.w $E44, $E20 dc.w $E44, $E00 dc.w $E42, $E00 dc.w $E62, $C00 dc.w $E82, $A00 dc.w $EA2, $C00 dc.w $EC0, $E00 dc.w $EE0, $E20 dc.w $EE4, $E00 dc.w $EE4, $C00 dc.w $EE4, $A00 dc.w $EE0, $800 dc.w $EC2, $A00 dc.w $EA2, $C00 dc.w $E82, $E20 AnPal_PalICZ_2: dc.w $E06, $E08 dc.w $E04, $E06 dc.w $C04, $E04 dc.w $C02, $C04 dc.w $A02, $C02 dc.w $A00, $A02 dc.w $800, $A00 dc.w $600, $800 dc.w $600, $800 dc.w $600, $800 dc.w $600, $800 dc.w $800, $A00 dc.w $A00, $A02 dc.w $A02, $C02 dc.w $C02, $C04 dc.w $C04, $E04 dc.w $E04, $E06 dc.w $E06, $E08 AnPal_PalICZ_3: dc.w $840, $EEA dc.w $860, $EE0 dc.w $A80, $EC0 dc.w $EC0, $A80 dc.w $A80, $EC0 dc.w $860, $EE0 AnPal_PalICZ_4: dc.w $E8, $CEC dc.w $C8, $AEA dc.w $C8, $AEA dc.w $A6, $6E8 dc.w $A6, $6E8 dc.w $84, $E8 dc.w $84, $E8 dc.w $82, $C8 dc.w $64, $A6 dc.w $64, $A6 dc.w $82, $C8 dc.w $84, $E8 dc.w $A6, $6E8 dc.w $C8, $AEA dc.w $E8, $CEC dc.w $E8, $CEC AnPal_PalLBZ1: dc.w $8E0, $C0, $80 dc.w $C0, $80, $8E0 dc.w $80, $8E0, $C0 AnPal_PalLBZ2: dc.w $EEA, $EA4, $C62 dc.w $EA4, $C62, $EEA dc.w $C62, $EEA, $EA4 AnPal_PalSOZ1: dc.w $2CE, $6CE, $AE, $6C dc.w $6C, $2CE, $6CE, $AE dc.w $AE, $6C, $2CE, $6CE dc.w $6CE, $AE, $6C, $2CE dc.w $28A, $6AC, $8A, $48 dc.w $48, $28A, $6AC, $8A dc.w $8A, $48, $28A, $6AC dc.w $6AC, $8A, $48, $28A dc.w $468, $668, $248, $26 dc.w $26, $468, $668, $248 dc.w $248, $26, $468, $668 dc.w $668, $248, $26, $468 dc.w $424, $846, $224, $222 dc.w $222, $424, $846, $224 dc.w $224, $222, $424, $846 dc.w $846, $224, $222, $424 dc.w $602, $824, $402, $200 dc.w $200, $602, $824, $402 dc.w $402, $200, $602, $824 dc.w $824, $402, $200, $602 AnPal_PalSOZ2_Light: dc.w $EEE, $8EE, $4EE, $CE, $24C, 6, 0, $CEA, $886, $424, $E0 AnPal_PalSOZ2_Light_2: dc.w $EEE, $AEE, $6EE, $4AC, $68, $46, $22, $8AA, $468, $224, 2, $28E, $4EE, $8C, $C dc.w $8CE, $6CC, $4AC, $8A, $248, 4, 0, $8A8, $664, $422, $80 dc.w $CEE, $ACC, $6CC, $48A, $266, $46, $22, $ACC, $468, $224, 2, $28E, $6EE, $28C, $22C dc.w $2CE, $28A, $268, $246, $224, $202, 0, $464, $222, $200, $40 dc.w $ACE, $8AA, $688, $468, $244, $24, $22, $CCC, $468, $224, 2, $26C, $6EE, $28C, $24C dc.w $88A, $668, $646, $424, $224, $202, 0, $444, $222, $200, $40 dc.w $8CE, $888, $666, $446, $222, $22, $22, $EEE, $468, $224, 2, $26A, $6EE, $48C, $26C dc.w $C46, $824, $804, $402, $202, $200, 0, $422, $402, $200, $40 dc.w $6AE, $664, $422, $402, $200, 0, 0, $EEE, $466, $224, 0, $46, $6EE, $48C, $26A AnPal_PalLRZ12_1: dc.w $EE, $AE, $6E, $E dc.w $AE, $6E, $E, $EE dc.w $6E, $E, $EE, $2CE dc.w $2E, $8EE, $4EE, $6E dc.w $AEE, $6EE, $8E, $4E dc.w $4EE, $6E, $2E, $8EE dc.w $6E, $E, $EE, $2CE dc.w $E, $EE, $2CE, $6E dc.w $EE, $AE, $6E, $E dc.w $8E, $4E, $C, $CE dc.w $2E, $A, $AC, $6E dc.w 8, $8E, $4C, $C dc.w $AC, $6E, $2E, $A dc.w $8E, $4E, $C, $CE dc.w $6E, $E, $EE, $AE dc.w $E, $EE, $AE, $6E AnPal_PalLRZ12_2: dc.w $224, $224 dc.w $224, $424 dc.w $224, $426 dc.w $426, $224 dc.w $424, $224 dc.w $224, $224 dc.w $224, $224 dc.w $224, $422 dc.w $422, $422 AnPal_PalLRZ1_3: dc.w $624 dc.w $624 dc.w $624 dc.w $624 dc.w $624 dc.w $624 dc.w $626 dc.w $626 dc.w $826 dc.w $826 dc.w $826 dc.w $826 dc.w $826 dc.w $826 dc.w $826 dc.w $626 dc.w $626 AnPal_PalLRZ2_3: dc.w $824, $C44, $E2A, $EAE dc.w $824, $C44, $E2A, $EAE dc.w $824, $C44, $E2A, $EAE dc.w $824, $C44, $E48, $EAC dc.w $822, $C44, $E66, $EAA dc.w $822, $C44, $E66, $EAA dc.w $822, $C44, $E66, $EAA dc.w $842, $C64, $EA4, $EC6 dc.w $642, $A82, $CC2, $EE0 dc.w $642, $A82, $CC2, $EE0 dc.w $642, $A82, $CC2, $EE0 dc.w $642, $882, $AC2, $CE0 dc.w $642, $682, $8C2, $8E0 dc.w $642, $682, $8C2, $8E0 dc.w $642, $682, $8C2, $8E0 dc.w $642, $486, $4C8, $4E8 dc.w $442, $288, $2CA, $2EC dc.w $442, $288, $2CC, $2EE dc.w $442, $288, $2CA, $2EC dc.w $642, $486, $4C8, $4E8 dc.w $642, $682, $8C2, $8E0 dc.w $642, $882, $AC2, $CE0 dc.w $642, $A82, $CC2, $EE0 dc.w $842, $C64, $EA4, $EC6 dc.w $822, $C44, $E66, $EAA dc.w $824, $C44, $E48, $EAC dc.w $824, $C44, $E2A, $EAE dc.w $826, $C46, $E4A, $E8E dc.w $624, $A48, $C6C, $E6E dc.w $624, $A48, $C6C, $E6E dc.w $624, $A48, $C6C, $E6E dc.w $826, $C46, $E4A, $E8E AnPal_PalDEZ12_1: dc.w $E0, 0 dc.w 0, $E0E dc.w $E00, 0 dc.w 0, $EE dc.w $E, 0 dc.w 0, $EE0 dc.w $EE0, 0 dc.w 0, $E dc.w $EE, 0 dc.w 0, $E00 dc.w $E0E, 0 dc.w 0, $E0 AnPal_PalDEZ12_2: dc.w $8E, $6C, $4A, $28, $6AE dc.w $28C, $26A, $4A, $226, $4AC dc.w $48A, $468, $248, $424, $4AA dc.w $28C, $26A, $4A, $226, $4AC AnPal_PalDEZ1: dc.w $8AC, $68A, $468, $246 dc.w $246, $8AC, $68A, $468 dc.w $468, $246, $8AC, $68A dc.w $68A, $468, $246, $8AC dc.w $468, $246, $8AC, $68A dc.w $246, $8AC, $68A, $468 AnPal_PalBPZ_1: dc.w $EE, $AE, $6C dc.w $AE, $6E, $EE dc.w $6E, $EE, $AE AnPal_PalBPZ_2: dc.w $EE0, $E0E, $EE dc.w $EA0, $A0E, $EA dc.w $E60, $60E, $E6 dc.w $E20, $20E, $E2 dc.w $E02, $2E, $2E0 dc.w $E06, $6E, $6E0 dc.w $E0A, $AE, $AE0 dc.w $E0E, $EE, $EE0 dc.w $A0E, $EA, $EA0 dc.w $60E, $E6, $E60 dc.w $20E, $E2, $E20 dc.w $2E, $2E0, $E02 dc.w $6E, $6E0, $E06 dc.w $AE, $AE0, $E0A dc.w $EE, $EE0, $E0E dc.w $EA, $EA0, $A0E dc.w $E6, $E60, $60E dc.w $E2, $E20, $20E dc.w $2E0, $E02, $2E dc.w $6E0, $E06, $6E dc.w $AE0, $E0A, $AE AnPal_PalCGZ: dc.w $E, 8, 4, $EEE dc.w $C, 6, 2, $CCE dc.w $A, 4, 0, $AAE dc.w 8, 2, 0, $88E dc.w 6, 0, 0, $66E dc.w 4, 0, 0, $44E dc.w 6, 0, 0, $66E dc.w 8, 2, 0, $88E dc.w $A, 4, 2, $AAE dc.w $C, 6, 4, $CCE AnPal_PalEMZ_1: dc.w 6 dc.w 8 dc.w $A dc.w $C dc.w $E dc.w $E dc.w $E dc.w $E dc.w $C dc.w $A dc.w 8 dc.w 6 dc.w 6 dc.w 6 dc.w 6 dc.w 8 dc.w $A dc.w $C dc.w $E dc.w $E dc.w $E dc.w $C dc.w $A dc.w 8 dc.w 6 dc.w 8 dc.w $A dc.w $A dc.w $A dc.w 8 AnPal_PalEMZ_2: dc.w 0, $E dc.w 2, $C dc.w 4, $A dc.w 6, 8 dc.w 8, 6 dc.w $A, 4 dc.w $C, 2 dc.w $E, 0 dc.w $C, 2 dc.w $A, 4 dc.w 8, 6 dc.w 6, 8 dc.w 4, $A dc.w 2, $C AnPal_PalSlots_1: dc.w $46, $488, $2EE, $8A dc.w $68, $26A, $EEE, $AC dc.w $8A, $46, $488, $2EE dc.w $AC, $68, $26A, $EEE dc.w $2EE, $8A, $46, $488 dc.w $EEE, $AC, $68, $26A dc.w $48A, $2EE, $8A, $46 dc.w $268, $EEE, $AC, $68 AnPal_PalSlots_2: dc.w $268, $EEE, $AC, $68 dc.w $EEE, $EEE, $EEE, $EEE dc.w $48A, $2EE, $8A, $46 dc.w $EE, $EE, $EE, $EE dc.w $EEE, $AC, $68, $26A dc.w $EEE, $EEE, $EEE, $EEE dc.w $2EE, $8A, $46, $488 dc.w $E0E, $E0E, $E0E, $E0E dc.w $AC, $68, $26A, $EEE dc.w $EEE, $EEE, $EEE, $EEE dc.w $8A, $46, $488, $2EE dc.w $EE0, $EE0, $EE0, $EE0 dc.w $68, $26A, $EEE, $AC dc.w $EEE, $EEE, $EEE, $EEE dc.w $46, $488, $2EE, $8A dc.w $E0, $E0, $E0, $E0 AnPal_PalSlots_3: dc.w $E02 dc.w $E24 dc.w $E46 dc.w $E68 dc.w $E8A dc.w $EAC AnPal_PalLRZ3: dc.w $424, $AE dc.w $424, $AE dc.w $424, $AE dc.w $426, $8E dc.w $428, $6E dc.w $42A, $4E dc.w $42C, $2E dc.w $42E, $E dc.w $42E, $E dc.w $42E, $E dc.w $42C, $2E dc.w $42A, $4E dc.w $428, $6E dc.w $426, $8E dc.w $424, $AE AnPal_PalHPZ: dc.w $E, $A dc.w $E, $A dc.w $E, $A dc.w $E, $A dc.w $C, 8 dc.w $A, 6 dc.w 8, 4 dc.w 8, 4 dc.w $A, 6 dc.w $C, 8 ; =============== S U B R O U T I N E ======================================= SuperHyper_PalCycle: move.b (Super_palette_status).w,d0 ; 0 = off | 1 = fading | -1 = fading done beq.w locret_37EC ; return, if player isn't super bmi.w SuperHyper_PalCycle_Normal ; branch, if fade-in is done subq.b #1,d0 bne.w SuperHyper_PalCycle_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.w locret_37EC move.b #1,(Palette_timer).w ; Tails and Knuckles only ; Only Sonic has a fade-in; Tails and Knuckles just *pop* into their normal Super/Hyper palette cycle cmpi.w #2,(Player_mode).w blo.s SuperHyper_PalCycle_FadeIn move.b #-1,(Super_palette_status).w ; -1 = fading done move.w #0,(Palette_frame).w ; Used by Knuckles and Tails' Super Flickies move.b #0,(Palette_frame_Tails).w ; Used by Tails move.b #0,(Player_1+object_control).w ; restore Player's movement rts ; --------------------------------------------------------------------------- SuperHyper_PalCycle_FadeIn: ; increment palette frame and update Sonic's palette lea (PalCycle_SuperSonic).l,a0 move.w (Palette_frame).w,d0 addq.w #6,(Palette_frame).w ; 1 palette entry = 1 word, Sonic uses 3 shades of blue cmpi.w #$24,(Palette_frame).w ; has palette cycle reached the 6th frame? blo.s SuperHyper_PalCycle_SonicApply ; if not, branch move.b #-1,(Super_palette_status).w ; mark fade-in as done move.b #0,(Player_1+object_control).w ; restore Sonic's movement SuperHyper_PalCycle_SonicApply: lea (Normal_palette+$04).w,a1 move.l (a0,d0.w),(a1)+ ; Write first two palette entries move.w 4(a0,d0.w),(a1) ; Write last palette entry tst.b (Water_flag).w beq.s locret_37EC lea (PalCycle_SuperSonicUnderwaterAIZICZ).l,a0 ; Load underwater fade-in palette tst.b (Current_zone).w ; Is Sonic in Angel Island Zone? beq.s SuperHyper_PalCycle_ApplyUnderwater ; If so, branch cmpi.b #5,(Current_zone).w ; Is Sonic in IceCap Zone? beq.s SuperHyper_PalCycle_ApplyUnderwater ; If so, branch lea (PalCycle_SuperSonicUnderwaterHCZCNZLBZ).l,a0 ; Load alternate underwater fade-in palette SuperHyper_PalCycle_ApplyUnderwater: lea (Water_palette+$04).w,a1 move.l (a0,d0.w),(a1)+ ; Write first two palette entries move.w 4(a0,d0.w),(a1) ; Write last palette entry locret_37EC: rts ; --------------------------------------------------------------------------- SuperHyper_PalCycle_Revert: ; runs the fade in transition backwards cmpi.w #2,(Player_mode).w ; If Tails or Knuckles, branch, making this code Sonic-specific bhs.s SuperHyper_PalCycle_RevertNotSonic ; run frame timer subq.b #1,(Palette_timer).w bpl.s locret_37EC move.b #3,(Palette_timer).w ; decrement palette frame and update Sonic's palette lea (PalCycle_SuperSonic).l,a0 move.w (Palette_frame).w,d0 subq.w #6,(Palette_frame).w ; previous frame bhs.s loc_381E ; branch, if it isn't the first frame ; Bug: this only clears the high byte of Palette_frame, causing subsequent ; fade-ins to pull color values from PalCycle_SuperTails move.b #0,(Palette_frame).w move.b #0,(Super_palette_status).w ; 0 = off loc_381E: bra.s SuperHyper_PalCycle_SonicApply ; --------------------------------------------------------------------------- SuperHyper_PalCycle_RevertNotSonic: moveq #0,d0 move.w d0,(Palette_frame).w move.b d0,(Super_palette_status).w ; 0 = off move.b d0,(Palette_frame_Tails).w cmpi.w #3,(Player_mode).w ; If Knuckles, branch, making this code Tails-specific bhs.s SuperHyper_PalCycle_RevertKnuckles lea (PalCycle_SuperTails).l,a0 ; Used here because the first set of colours is Tails' normal palette bsr.w SuperHyper_PalCycle_ApplyTails lea (PalCycle_SuperSonic).l,a0 ; Why does Tails manipulate Sonic's palette? For his Super-form's Super Flickies bra.w SuperHyper_PalCycle_Apply ; --------------------------------------------------------------------------- SuperHyper_PalCycle_RevertKnuckles: lea (PalCycle_SuperHyperKnucklesRevert).l,a0 bra.w SuperHyper_PalCycle_Apply ; --------------------------------------------------------------------------- SuperHyper_PalCycle_Normal: cmpi.w #2,(Player_mode).w ; If Tails... beq.w SuperHyper_PalCycle_NormalTails cmpi.w #3,(Player_mode).w ; ...or Knuckles, branch, making this code Sonic-specific beq.w SuperHyper_PalCycle_NormalKnuckles tst.b (Super_Sonic_Knux_flag).w ; If Hyper Sonic, branch bmi.s SuperHyper_PalCycle_HyperSonic SuperHyper_PalCycle_SuperSonic: ; Tails' code falls back here so the Super Flickies' palette can update ; run frame timer subq.b #1,(Palette_timer).w bpl.w locret_37EC move.b #6,(Palette_timer).w ; increment palette frame and update Sonic's palette lea (PalCycle_SuperSonic).l,a0 move.w (Palette_frame).w,d0 addq.w #6,(Palette_frame).w ; next frame cmpi.w #$36,(Palette_frame).w ; is it the last frame? blo.s loc_3898 ; if not, branch move.w #$24,(Palette_frame).w ; reset frame counter (Super Sonic's normal palette cycle starts at $24. Everything before that is for the palette fade) loc_3898: bra.w SuperHyper_PalCycle_SonicApply ; --------------------------------------------------------------------------- SuperHyper_PalCycle_HyperSonic: ; run frame timer subq.b #1,(Palette_timer).w bpl.w locret_37EC move.b #4,(Palette_timer).w ; increment palette frame and update Sonic's palette lea (PalCycle_HyperSonic).l,a0 move.w (Palette_frame).w,d0 addq.w #6,(Palette_frame).w ; next frame cmpi.w #$48,(Palette_frame).w ; is it the last frame? blo.s SuperHyper_PalCycle_HyperSonicApply ; if not, branch move.w #0,(Palette_frame).w ; reset frame counter SuperHyper_PalCycle_HyperSonicApply: ; Redundant. SuperHyper_PalCycle_Apply does the exact same thing ; and other areas of code do branch to it instead of duplicating the code as seen here lea (Normal_palette+$4).w,a1 move.l (a0,d0.w),(a1)+ ; Write first two palette entries move.w 4(a0,d0.w),(a1) ; Write last palette entry tst.b (Water_flag).w beq.w locret_37EC lea (Water_palette+$4).w,a1 move.l (a0,d0.w),(a1)+ ; Write first two palette entries move.w 4(a0,d0.w),(a1) ; Write last palette entry rts ; --------------------------------------------------------------------------- SuperHyper_PalCycle_NormalTails: ; run frame timer subq.b #1,(Palette_timer_Tails).w bpl.w SuperHyper_PalCycle_SuperSonic move.b #$B,(Palette_timer_Tails).w ; increment palette frame and update Tails' palette lea (PalCycle_SuperTails).l,a0 moveq #0,d0 move.b (Palette_frame_Tails).w,d0 addq.b #6,(Palette_frame_Tails).w ; next frame cmpi.b #$24,(Palette_frame_Tails).w ; is it the last frame? blo.s SuperHyper_PalCycle_ApplyTails ; if not, branch move.b #0,(Palette_frame_Tails).w ; reset frame counter ; go straight to SuperHyper_PalCycle_ApplyTails... ; End of function SuperHyper_PalCycle ; =============== S U B R O U T I N E ======================================= SuperHyper_PalCycle_ApplyTails: ; Tails gets his own because of the unique location of his palette entries lea (Normal_palette+$10).w,a1 move.l (a0,d0.w),(a1)+ ; Write first two palette entries move.w 4(a0,d0.w),2(a1) ; Write last palette entry tst.b (Water_flag).w beq.w SuperHyper_PalCycle_SuperSonic lea (Water_palette+$10).w,a1 move.l (a0,d0.w),(a1)+ ; Write first two palette entries move.w 4(a0,d0.w),2(a1) ; Write last palette entry bra.w SuperHyper_PalCycle_SuperSonic ; End of function SuperHyper_PalCycle_ApplyTails ; --------------------------------------------------------------------------- SuperHyper_PalCycle_NormalKnuckles: ; run frame timer subq.b #1,(Palette_timer).w bpl.w locret_37EC move.b #2,(Palette_timer).w ; increment palette frame and update Knuckles' palette lea (PalCycle_SuperHyperKnuckles).l,a0 move.w (Palette_frame).w,d0 addq.w #6,(Palette_frame).w ; next frame cmpi.w #$3C,(Palette_frame).w ; is it the last frame? blo.s SuperHyper_PalCycle_Apply ; if not, branch move.w #0,(Palette_frame).w ; reset frame counter move.b #$E,(Palette_timer).w SuperHyper_PalCycle_Apply: lea (Normal_palette+$4).w,a1 move.l (a0,d0.w),(a1)+ ; Write first two palette entries move.w 4(a0,d0.w),(a1) ; Write last palette entry tst.b (Water_flag).w beq.w locret_37EC lea (Water_palette+$4).w,a1 move.l (a0,d0.w),(a1)+ ; Write first two palette entries move.w 4(a0,d0.w),(a1) ; Write last palette entry rts ; --------------------------------------------------------------------------- PalCycle_SuperSonic: dc.w $E66,$C42,$822 dc.w $E88,$C66,$844 dc.w $EAA,$C88,$A66 dc.w $ECC,$EAA,$C88 dc.w $EEE,$ECC,$EAA dc.w $EEE,$EEE,$EEE dc.w $CEE,$CEE,$AEE dc.w $AEE,$8EE,$6CC dc.w $8EE,$0EE,$0AA dc.w $AEE,$8EE,$6CC PalCycle_SuperSonicUnderwaterAIZICZ: dc.w $A82,$860,$640 dc.w $E88,$C66,$844 dc.w $EAA,$C88,$A66 dc.w $ECC,$EAA,$C88 dc.w $EEE,$ECC,$EAA dc.w $EEE,$EEE,$EEE dc.w $CEE,$CEC,$AEC dc.w $AEC,$8EC,$6CA dc.w $8EC,$4EA,$4A8 dc.w $CEE,$CEC,$AEC PalCycle_SuperSonicUnderwaterHCZCNZLBZ: dc.w $C66,$A44,$624 dc.w $E88,$C66,$844 dc.w $EAA,$C88,$A66 dc.w $ECC,$EAA,$C88 dc.w $EEE,$ECC,$EAA dc.w $EEE,$EEE,$EEE dc.w $CEE,$CEC,$AEC dc.w $AEC,$8EC,$6CA dc.w $8EC,$4EA,$4A8 dc.w $CEE,$CEC,$AEC PalCycle_HyperSonic: dc.w $EEC,$ECA,$EA8 dc.w $EEE,$EEE,$EEE dc.w $CEC,$AEA,$2E0 dc.w $EEE,$EEE,$EEE dc.w $AEC,$4EC,$0CC dc.w $EEE,$EEE,$EEE dc.w $CEE,$8EE,$4CE dc.w $EEE,$EEE,$EEE dc.w $EEE,$CCE,$AAE dc.w $EEE,$EEE,$EEE dc.w $EEE,$ECE,$CAC dc.w $EEE,$EEE,$EEE PalCycle_SuperTails: dc.w $0AE,$08E,$46A dc.w $4CE,$2AE,$46A dc.w $8CE,$4CE,$46C dc.w $AEE,$8CE,$48E dc.w $8CE,$4CE,$46C dc.w $4CE,$2AE,$46A PalCycle_SuperHyperKnuckles: dc.w $A6E,$64E,$428 dc.w $C8E,$86E,$64A dc.w $EAE,$A8E,$86C dc.w $ECE,$CAE,$A8E dc.w $EEE,$ECE,$CAE dc.w $ECE,$CAE,$A8E dc.w $EAE,$A8E,$86C dc.w $C8E,$86E,$64A dc.w $A6E,$64E,$428 dc.w $84E,$40C,$206 PalCycle_SuperHyperKnucklesRevert: dc.w $64E,$20C,$206 ; =============== S U B R O U T I N E ======================================= Pal_FadeFromBlack: move.w #$40-1,(Palette_fade_info).w jsr Pal_FillBlack(pc) move.w #$15,d4 loc_3AFE: move.b #$12,(V_int_routine).w bsr.w Wait_VSync bsr.s Pal_FromBlack bsr.w Process_Nem_Queue_Init dbf d4,loc_3AFE rts ; End of function Pal_FadeFromBlack ; =============== S U B R O U T I N E ======================================= Pal_FromBlack: moveq #0,d0 lea (Normal_palette).w,a0 lea (Target_palette).w,a1 move.b (Palette_fade_info).w,d0 adda.w d0,a0 adda.w d0,a1 move.b (Palette_fade_count).w,d0 loc_3B2A: bsr.s Pal_AddColor dbf d0,loc_3B2A tst.b (Water_flag).w beq.s locret_3B52 moveq #0,d0 lea (Water_palette).w,a0 lea (Target_water_palette).w,a1 move.b (Palette_fade_info).w,d0 adda.w d0,a0 adda.w d0,a1 move.b (Palette_fade_count).w,d0 loc_3B4C: bsr.s Pal_AddColor dbf d0,loc_3B4C locret_3B52: rts ; End of function Pal_FromBlack ; =============== S U B R O U T I N E ======================================= Pal_AddColor: move.w (a1)+,d2 move.w (a0),d3 cmp.w d2,d3 beq.s loc_3B7C move.w d3,d1 addi.w #$200,d1 cmp.w d2,d1 bhi.s loc_3B6A move.w d1,(a0)+ rts ; --------------------------------------------------------------------------- loc_3B6A: move.w d3,d1 addi.w #$20,d1 cmp.w d2,d1 bhi.s loc_3B78 move.w d1,(a0)+ rts ; --------------------------------------------------------------------------- loc_3B78: addq.w #2,(a0)+ rts ; --------------------------------------------------------------------------- loc_3B7C: addq.w #2,a0 rts ; End of function Pal_AddColor ; =============== S U B R O U T I N E ======================================= Pal_FillBlack: cmpi.w #$D01,(Current_zone_and_act).w beq.w Pal_FillWhite cmpi.w #$1701,(Current_zone_and_act).w beq.w Pal_FillWhite ; If one of either Sky Sanctuary Knuckles level or the Super Emerald special stage arena, branch moveq #0,d0 lea (Normal_palette).w,a0 move.b (Palette_fade_info).w,d0 adda.w d0,a0 moveq #0,d1 move.b (Palette_fade_count).w,d0 loc_3BA6: move.w d1,(a0)+ tst.b (Water_flag).w beq.s loc_3BB2 move.w d1,(Water_palette-Normal_palette)-2(a0) loc_3BB2: dbf d0,loc_3BA6 rts ; End of function Pal_FillBlack ; =============== S U B R O U T I N E ======================================= Animate_Palette: tst.w (Palette_fade_timer).w bmi.s locret_3BE2 beq.s loc_3BDC subq.w #1,(Palette_fade_timer).w cmpi.w #$D01,(Current_zone_and_act).w beq.w Pal_FromWhite cmpi.w #$1701,(Current_zone_and_act).w beq.w Pal_FromWhite bra.w Pal_FromBlack ; --------------------------------------------------------------------------- loc_3BDC: jmp (AnPal_Load).l ; --------------------------------------------------------------------------- locret_3BE2: rts ; End of function Animate_Palette ; =============== S U B R O U T I N E ======================================= Pal_FadeToBlack: move.w #$40-1,(Palette_fade_info).w move.w #$15,d4 loc_3BEE: move.b #$12,(V_int_routine).w bsr.w Wait_VSync bsr.s Pal_ToBlack bsr.w Process_Nem_Queue_Init dbf d4,loc_3BEE rts ; End of function Pal_FadeToBlack ; =============== S U B R O U T I N E ======================================= Pal_ToBlack: moveq #0,d0 lea (Normal_palette).w,a0 move.b (Palette_fade_info).w,d0 adda.w d0,a0 move.b (Palette_fade_count).w,d0 loc_3C14: bsr.s Pal_DecColor dbf d0,loc_3C14 moveq #0,d0 lea (Water_palette).w,a0 move.b (Palette_fade_info).w,d0 adda.w d0,a0 move.b (Palette_fade_count).w,d0 loc_3C2A: bsr.s Pal_DecColor dbf d0,loc_3C2A rts ; End of function Pal_ToBlack ; =============== S U B R O U T I N E ======================================= Pal_DecColor: move.w (a0),d2 beq.s loc_3C5E move.w d2,d1 andi.w #$E,d1 beq.s loc_3C42 subq.w #2,(a0)+ rts ; --------------------------------------------------------------------------- loc_3C42: move.w d2,d1 andi.w #$E0,d1 beq.s loc_3C50 subi.w #$20,(a0)+ rts ; --------------------------------------------------------------------------- loc_3C50: move.w d2,d1 andi.w #$E00,d1 beq.s loc_3C5E subi.w #$200,(a0)+ rts ; --------------------------------------------------------------------------- loc_3C5E: addq.w #2,a0 rts ; End of function Pal_DecColor ; =============== S U B R O U T I N E ======================================= Pal_FillWhite: moveq #0,d0 lea (Normal_palette).w,a0 move.b (Palette_fade_info).w,d0 adda.w d0,a0 move.w #$EEE,d1 move.b (Palette_fade_count).w,d0 loc_3C76: move.w d1,(a0)+ dbf d0,loc_3C76 clr.w (Pal_fade_delay2).w rts ; End of function Pal_FillWhite ; =============== S U B R O U T I N E ======================================= Pal_FadeFromWhite: move.w #$40-1,(Palette_fade_info).w bsr.s Pal_FillWhite move.w #$15,d4 loc_3C8E: move.b #$12,(V_int_routine).w bsr.w Wait_VSync bsr.s Pal_FromWhite bsr.w Process_Nem_Queue_Init dbf d4,loc_3C8E rts ; End of function Pal_FadeFromWhite ; =============== S U B R O U T I N E ======================================= Pal_FromWhite: subq.w #1,(Pal_fade_delay2).w bpl.s locret_3CEE move.w #2,(Pal_fade_delay2).w moveq #0,d0 lea (Normal_palette).w,a0 lea (Target_palette).w,a1 move.b (Palette_fade_info).w,d0 adda.w d0,a0 adda.w d0,a1 move.b (Palette_fade_count).w,d0 loc_3CC6: bsr.s Pal_DecColor2 dbf d0,loc_3CC6 tst.b (Water_flag).w beq.s locret_3CEE moveq #0,d0 lea (Water_palette).w,a0 lea (Target_water_palette).w,a1 move.b (Palette_fade_info).w,d0 adda.w d0,a0 adda.w d0,a1 move.b (Palette_fade_count).w,d0 loc_3CE8: bsr.s Pal_DecColor2 dbf d0,loc_3CE8 locret_3CEE: rts ; End of function Pal_FromWhite ; =============== S U B R O U T I N E ======================================= Pal_DecColor2: move.b (a1)+,d2 andi.b #$E,d2 move.b (a0),d3 andi.b #$E,d3 cmp.b d2,d3 bls.s loc_3D02 subq.b #2,d3 loc_3D02: move.b d3,(a0)+ move.b (a1)+,d1 move.b d1,d2 andi.b #$E0,d1 move.b (a0),d3 move.b d3,d5 andi.b #$E0,d3 cmp.b d1,d3 bls.s loc_3D1C subi.b #$20,d3 loc_3D1C: andi.b #$E,d2 andi.b #$E,d5 cmp.b d2,d5 bls.s loc_3D2A subq.b #2,d5 loc_3D2A: or.b d5,d3 move.b d3,(a0)+ rts ; End of function Pal_DecColor2 ; =============== S U B R O U T I N E ======================================= Pal_FadeToWhite: move.w #$40-1,(Palette_fade_info).w move.w #$15,d4 loc_3D3A: move.b #$12,(V_int_routine).w bsr.w Wait_VSync bsr.s Pal_ToWhite bsr.w Process_Nem_Queue_Init dbf d4,loc_3D3A rts ; End of function Pal_FadeToWhite ; =============== S U B R O U T I N E ======================================= Pal_ToWhite: moveq #0,d0 lea (Normal_palette).w,a0 move.b (Palette_fade_info).w,d0 adda.w d0,a0 move.b (Palette_fade_count).w,d0 loc_3D60: bsr.s Pal_AddColor2 dbf d0,loc_3D60 moveq #0,d0 lea (Water_palette).w,a0 move.b (Palette_fade_info).w,d0 adda.w d0,a0 move.b (Palette_fade_count).w,d0 loc_3D76: bsr.s Pal_AddColor2 dbf d0,loc_3D76 rts ; End of function Pal_ToWhite ; =============== S U B R O U T I N E ======================================= Pal_AddColor2: move.w (a0),d2 cmpi.w #$EEE,d2 beq.s loc_3DBA move.w d2,d1 andi.w #$E,d1 cmpi.w #$E,d1 beq.s loc_3D96 addq.w #2,(a0)+ rts ; --------------------------------------------------------------------------- loc_3D96: move.w d2,d1 andi.w #$E0,d1 cmpi.w #$E0,d1 beq.s loc_3DA8 addi.w #$20,(a0)+ rts ; --------------------------------------------------------------------------- loc_3DA8: move.w d2,d1 andi.w #$E00,d1 cmpi.w #$E00,d1 beq.s loc_3DBA addi.w #$200,(a0)+ rts ; --------------------------------------------------------------------------- loc_3DBA: addq.w #2,a0 rts ; End of function Pal_AddColor2 ; =============== S U B R O U T I N E ======================================= LoadPalette: lea (PalPoint).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 .loop: move.l (a2)+,(a3)+ dbf d7,.loop rts ; End of function LoadPalette ; =============== S U B R O U T I N E ======================================= LoadPalette_Immediate: lea (PalPoint).l,a1 lsl.w #3,d0 adda.w d0,a1 movea.l (a1)+,a2 movea.w (a1)+,a3 move.w (a1)+,d7 .loop: move.l (a2)+,(a3)+ dbf d7,.loop rts ; End of function LoadPalette_Immediate ; =============== S U B R O U T I N E ======================================= LoadPalette2: lea (PalPoint).l,a1 lsl.w #3,d0 adda.w d0,a1 movea.l (a1)+,a2 movea.w (a1)+,a3 suba.w #Normal_palette-Water_palette,a3 move.w (a1)+,d7 .loop: move.l (a2)+,(a3)+ dbf d7,.loop rts ; End of function LoadPalette2 ; =============== S U B R O U T I N E ======================================= LoadPalette2_Immediate: lea (PalPoint).l,a1 lsl.w #3,d0 adda.w d0,a1 movea.l (a1)+,a2 movea.w (a1)+,a3 suba.w #Normal_palette-Target_water_palette,a3 move.w (a1)+,d7 .loop: move.l (a2)+,(a3)+ dbf d7,.loop rts ; End of function LoadPalette2_Immediate ; --------------------------------------------------------------------------- Sega_Screen: move.b #4,(Game_mode).w rts ; --------------------------------------------------------------------------- Title_Screen: moveq #signextendB(mus_FadeOut),d0 bsr.w Play_Music ; Fade music if any is playing clr.w (Kos_decomp_queue_count).w clearRAM Kos_decomp_stored_registers,$6C ; Clear FFFF10-FFFF7B bsr.w Clear_Nem_Queue clr.w (Current_zone_and_act).w ; Clear zone/act index bsr.w Pal_FadeToBlack ; Fade out move #$2700,sr lea (VDP_control_port).l,a6 move.w #$8004,(a6) ; Command $8004 - Disable HInt, HV Counter move.w #$8230,(a6) ; Command $8230 - Nametable A at $C000 move.w #$8407,(a6) ; Command $8407 - Nametable B at $E000 move.w #$9001,(a6) ; Command $9001 - 64x32 cell nametable area move.w #$9200,(a6) ; Command $9200 - Window V position at default move.w #$8B03,(a6) ; Command $8B03 - Vscroll full, HScroll line-based move.w #$8700,(a6) ; Command $8700 - BG color is Pal 0 Color 0 clr.b (Water_full_screen_flag).w clr.b (Water_flag).w ; Both water flags cleared move.w #$8C81,(a6) ; Command $8C81 - 40cell screen size, no interlacing, no s/h bsr.w Clear_DisplayData clearRAM Sprite_table_input,$400 ; Clear object display array clearRAM Object_RAM,(Kos_decomp_buffer-Object_RAM) ; Clear SST array clearRAM Tails_CPU_interact,$100 ; Clear active play variables clearRAM Camera_RAM,$100 ; Clear play positional values jsr (Init_SpriteTable).l ; Initialize the sprite table clearRAM Normal_palette,$100 ; Clear main palette moveq #0,d0 move.b d0,(Last_star_post_hit).w move.b d0,(Special_bonus_entry_flag).w move.w d0,(Debug_placement_mode).w move.w d0,(Demo_mode_flag).w move.w d0,(Palette_cycle_counter1).w move.w d0,(Competition_mode).w move.b d0,(Level_started_flag).w move.b d0,(Debug_mode_flag).w move.w d0,(Competition_mode).w move.w d0,(Level_select_cheat_counter).w move.w d0,(Debug_mode_cheat_counter).w move.b d0,(Blue_spheres_stage_flag).w move.w #(6*60)-1,(Demo_timer).w ; Wait on title screen for six seconds clr.w (DMA_queue).w move.l #DMA_queue,(DMA_queue_slot).w ; Clear DMA queue nop nop nop nop nop nop tst.w (SK_alone_flag).w bne.w SK_Alone_Title_Screen lea (ArtKos_S3TitleSonic1).l,a0 ;S3DATA lea (RAM_start).l,a1 bsr.w Kos_Decomp move.w a1,d3 lsr.w #1,d3 move.l #RAM_start&$FFFFFF,d1 move.w #tiles_to_bytes($000),d2 jsr (Add_To_DMA_Queue).l ; DMA Sega logo+Sonic art data 1 to $0 in VRAM lea (RAM_start+$8000).w,a1 lea (MapEni_S3TitleSonic1).l,a0 ;S3DATA move.w #0,d0 bsr.w Eni_Decomp ; Decompress Enigma mappings tst.b (Graphics_flags).w bmi.s loc_3F7E moveq #0,d0 move.l d0,(RAM_start+$83AC).w ; Hide trademark symbol if the console is Japanese loc_3F7E: lea (RAM_start+$8000).w,a1 move.l #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE),d0 moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l ; Copy screen mappings to VRAM lea (Pal_TitleSonic1).l,a0 lea (Target_palette).w,a1 moveq #bytesToLcnt($20),d0 loc_3F9E: move.l (a0)+,(a1)+ ; Fill 2 palette lines with title screen data dbf d0,loc_3F9E move.w #4*60,(Demo_timer).w move.w (VDP_reg_1_command).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l ; Turn the display on bsr.w Pal_FadeFromBlack ; Fade in to logo moveq #signextendB(mus_SEGA),d0 bsr.w Play_Music move.w #3*60,(Demo_timer).w ; Set to wait for 3 seconds Wait_SegaS3K: move.b #$14,(V_int_routine).w bsr.w Wait_VSync ; Wait for SEGA sound move.b (Ctrl_1_pressed).w,d0 andi.b #button_start_mask,d0 bne.w loc_3FE4 ; If start was pressed, skip ahead tst.w (Demo_timer).w bne.s Wait_SegaS3K loc_3FE4: moveq #signextendB(mus_StopSEGA),d0 bsr.w Play_Music ; Stop SEGA sound lea (Pal_Title).l,a1 loc_3FF0: move.b #2,(V_int_routine).w bsr.w Wait_VSync lea (Normal_palette).w,a2 move.l (a1)+,(a2)+ move.l (a1)+,(a2)+ move.l (a1)+,(a2)+ move.w (a1)+,(a2)+ tst.w -$E(a1) ; Wait for BG color to turn to black bne.s loc_3FF0 clr.w (_unkF660).w clr.w (_unkF662).w move.b #-1,(Title_anim_buffer).w move.b #0,(Title_anim_delay).w move.w #1,(Title_anim_frame).w ; Set initial variables for Sonic animation page flipping moveq #1,d0 bsr.w TitleSonic_LoadFrame move.w #15*60,(Demo_timer).w ; Set to wait 15 seconds (900 frames in NTSC) btst #6,(Graphics_flags).w beq.s loc_4040 move.w #15*50,(Demo_timer).w ; Set to wait 15 seconds (750 frames in PAL) loc_4040: lea (ArtKos_S3TitleSonic8).l,a1 lea (RAM_start).l,a2 jsr (Queue_Kos).l ; Queue frame 8 of data into a2 since frame 1 is already in VRAM moveq #signextendB(mus_TitleScreen),d0 bsr.w Play_Music ; Start playing the title screen music Wait_TitleS3K: move.b #4,(V_int_routine).w jsr (Process_Kos_Queue).l bsr.w Wait_VSync bsr.w Iterate_TitleSonicFrame jsr (Process_Sprites).l jsr (Render_Sprites).l bsr.w Process_Nem_Queue_Init move.b (Ctrl_1_pressed).w,d0 andi.b #button_start_mask,d0 bne.w loc_4090 ; If start was pressed, skip straight to title cmpi.w #$C,(Title_anim_frame).w blo.s Wait_TitleS3K ; If last frame was reached, don't repeat loc_4090: move.w #$C,(Title_anim_frame).w lea (Normal_palette).w,a1 moveq #$40-1,d1 loc_409C: move.w #$EEE,(a1)+ dbf d1,loc_409C ; Flash palette white move.b #3,(Title_anim_delay).w move.b #4,(V_int_routine).w bsr.w Wait_VSync lea (ArtKos_S3TitleSonicD).l,a0 ;S3DATA lea (RAM_start).l,a1 bsr.w Kos_Decomp move.w a1,d3 lsr.w #1,d3 move.l #RAM_start,d1 move.w #tiles_to_bytes($000),d2 andi.l #$FFFFFF,d1 jsr (Add_To_DMA_Queue).l ; Load Sonic art frame 14 lea (Level_layout_header).w,a1 lea (MapEni_S3TitleSonicD).l,a0 move.w #make_art_tile($000,0,1),d0 bsr.w Eni_Decomp lea (Level_layout_header).w,a1 move.l #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE),d0 moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l ; Load Sonic mapping frame 14 to $C000 VRAM lea (Level_layout_header).w,a1 lea (MapEni_S3TitleBg).l,a0 move.w #make_art_tile($000,2,0),d0 bsr.w Eni_Decomp lea (Level_layout_header).w,a1 move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0 moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l ; Load S3K Title BG to $E000 VRAM move.b #4,(V_int_routine).w bsr.w Wait_VSync lea (Pal_TitleSonicD).l,a0 ; Title palette lea (Target_palette).w,a1 moveq #bytesToLcnt($80),d0 loc_4140: move.l (a0)+,(a1)+ dbf d0,loc_4140 move.l #vdpComm(tiles_to_bytes($500),VRAM,WRITE),(VDP_control_port).l ; to VRAM $A000 lea (ArtNem_Title_S3Banner).l,a0 bsr.w Nem_Decomp move.l #vdpComm(tiles_to_bytes($680),VRAM,WRITE),(VDP_control_port).l ; to VRAM $D000 lea (ArtNem_TitleScreenText).l,a0 bsr.w Nem_Decomp move.l #vdpComm(tiles_to_bytes($400),VRAM,WRITE),(VDP_control_port).l ; to VRAM $8000 lea (ArtNem_Title_SonicSprites).l,a0 bsr.w Nem_Decomp move.l #vdpComm(tiles_to_bytes($4C0),VRAM,WRITE),(VDP_control_port).l ; to VRAM $9800 lea (ArtNem_Title_ANDKnuckles).l,a0 bsr.w Nem_Decomp move.l #Obj_TitleBanner,(Player_1).w move.l #Obj_TitleSelection,(Player_2).w move.l #Obj_TitleCopyright,(Dynamic_object_RAM).w move.l #Obj_TitleSonicFinger,(Dynamic_object_RAM+object_size).w move.l #Obj_TitleSonicWink,(Dynamic_object_RAM+(object_size*2)).w move.l #Obj_TitleTailsPlane,(Dynamic_object_RAM+(object_size*3)).w move.l #Obj_TitleANDKnuckles,(Dynamic_object_RAM+(object_size*4)).w ; Load all applicable title objects move.b #0,(Title_anim_delay).w loc_41D4: move.b #4,(V_int_routine).w bsr.w Wait_VSync jsr (Process_Sprites).l jsr (Render_Sprites).l bsr.w Process_Nem_Queue_Init tst.l (Reserved_object_3).w beq.s loc_41D4 ; Don't do anything at all until banner has finished moving tst.w (Demo_timer).w beq.w loc_4278 ; If the timer has run out, go do the level demos move.b (Ctrl_1_pressed).w,d0 or.b (Ctrl_2_pressed).w,d0 andi.b #button_start_mask,d0 beq.w loc_41D4 ; Repeat until start has been pressed on either controller move.b #$C,(Game_mode).w move.b #3,(Life_count).w move.b #3,(Life_count_P2).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_P2).w move.l d0,(Timer_P2).w move.l d0,(Score_P2).w move.b d0,(Continue_count).w move.l #5000,(Next_extra_life_score).w move.l #5000,(Next_extra_life_score_P2).w moveq #signextendB(mus_FadeOut),d0 bsr.w Play_SFX ; Fade out the title screen music moveq #0,d0 move.b (Title_screen_option).w,d0 ; Selection is stored here bne.w loc_4264 move.b #$4C,(Game_mode).w ; Game Mode 4C is the save select rts ; --------------------------------------------------------------------------- loc_4264: subq.b #1,d0 bne.s loc_4270 move.b #$38,(Game_mode).w ; Game Mode 38 is Competition mode rts ; --------------------------------------------------------------------------- loc_4270: move.b #$28,(Game_mode).w ; Game Mode 28 is the level select rts ; --------------------------------------------------------------------------- loc_4278: moveq #signextendB(mus_FadeOut),d0 bsr.w Play_SFX ; Fade out music move.w (Next_demo_number).w,d0 ; Get index of current demo to run move.w d0,(Demo_number).w andi.w #7,d0 add.w d0,d0 lea DemoLevels(pc),a0 move.w (a0,d0.w),d0 move.w d0,(Current_zone_and_act).w ; Load level index to the appropriate variables move.w d0,(Apparent_zone_and_act).w move.w d0,(Saved_zone_and_act).w move.w (Next_demo_number).w,d1 addq.w #1,d1 tst.w (SK_alone_flag).w bne.s loc_42C0 ; If playing only Sonic & Knuckles, branch cmpi.w #3,d1 bne.s loc_42B6 moveq #4,d1 bra.s loc_42C8 ; --------------------------------------------------------------------------- loc_42B6: cmpi.w #7,d1 blo.s loc_42C8 moveq #0,d1 bra.s loc_42C8 ; --------------------------------------------------------------------------- ; unused/dead code, since it's not possible to reach the S3K title screen in S&K mode ; Even if were, this sets the next demo to a S3 level, which would crash S&K when played loc_42C0: cmpi.w #3,d1 blo.s loc_42C8 moveq #0,d1 loc_42C8: move.w d1,(Next_demo_number).w tst.w d0 bpl.s loc_4300 ; Branch if we are indeed playing a level move.b #$34,(Game_mode).w ; Do the special stage demo move.b #1,(Current_special_stage).w move.b #1,(SK_special_stage_flag).w move.b #7,(Current_zone).w clr.w (Emerald_counts).w clr.l (Collected_emeralds_array).w clr.w (Collected_emeralds_array+4).w clr.b (Collected_emeralds_array+6).w move.b #2,(Collected_emeralds_array+1).w bra.s loc_4306 ; --------------------------------------------------------------------------- loc_4300: move.b #8,(Game_mode).w ; We're about to perform a level demo loc_4306: move.w #1,(Demo_mode_flag).w move.b #3,(Life_count).w move.b #3,(Life_count_P2).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_P2).w move.l d0,(Timer_P2).w move.l d0,(Score_P2).w move.l #5000,(Next_extra_life_score).w move.l #5000,(Next_extra_life_score_P2).w rts ; --------------------------------------------------------------------------- DemoLevels: dc.w 0 ; Angel Island dc.w $100 ; Hydrocity dc.w $200 ; Marble Garden dc.w $700 ; Mushroom Hill dc.w $400 ; Flying Battery dc.w $800 ; Sandopolis dc.w $FFFF ; --------------------------------------------------------------------------- TitleAnim_FlipBuffer: tst.b (Title_anim_delay).w bne.s loc_43AC move.b #4-1,(Title_anim_delay).w cmpi.w #$C,(Title_anim_frame).w bhs.s loc_43B2 move.b #4-1,(Title_anim_delay).w lea (Target_palette).w,a0 lea (Normal_palette).w,a1 moveq #bytesToLcnt($40),d0 loc_4376: move.l (a0)+,(a1)+ dbf d0,loc_4376 eori.b #-1,(Title_anim_buffer).w tst.b (Title_anim_buffer).w beq.s loc_439A move.w #$8406,(VDP_control_port).l ; Nametable B Address $C000 move.w #$8230,(VDP_control_port).l ; Nametable A Address $C000 rts ; --------------------------------------------------------------------------- loc_439A: move.w #$8407,(VDP_control_port).l ; Nametable B Address $E000 move.w #$8238,(VDP_control_port).l ; Nametable A Address $E000 rts ; --------------------------------------------------------------------------- loc_43AC: subq.b #1,(Title_anim_delay).w rts ; --------------------------------------------------------------------------- loc_43B2: lea (Target_palette).w,a0 lea (Normal_palette).w,a1 moveq #bytesToLcnt($80),d0 loc_43BC: move.l (a0)+,(a1)+ dbf d0,loc_43BC move.w #$8407,(VDP_control_port).l ; Nametable B Address $E000 move.w #$8230,(VDP_control_port).l ; Nametable A Address $C000 rts ; =============== S U B R O U T I N E ======================================= Iterate_TitleSonicFrame: cmpi.b #1,(Title_anim_delay).w bne.s locret_43F0 move.w (Title_anim_frame).w,d0 move.b SonicFrameIndex(pc,d0.w),d0 ext.w d0 bmi.s loc_43F2 bsr.w TitleSonic_LoadFrame addq.w #1,(Title_anim_frame).w locret_43F0: rts ; --------------------------------------------------------------------------- loc_43F2: move.w #$C,(Title_anim_frame).w move.b #3,(Title_anim_delay).w rts ; --------------------------------------------------------------------------- SonicFrameIndex: dc.b 1, 2, 3, 4, 5, 6, 7, 8, 9, $A, $B, $FF even ; =============== S U B R O U T I N E ======================================= TitleSonic_LoadFrame: move.w d0,d7 add.w d0,d0 add.w d0,d0 move.w d0,d1 add.w d0,d0 add.w d1,d0 lea (TitleSonic_Frames).l,a2 lea (a2,d0.w),a2 move.w #$2C60,d3 move.l (a2)+,d0 ; Art data cmpi.w #7,d7 beq.s loc_4446 bcs.s loc_4466 andi.l #$FFFFFF,d0 movea.l d0,a0 lea (RAM_start).l,a1 bsr.w Kos_Decomp move.w a1,d3 lsr.w #1,d3 loc_4446: move.l #RAM_start,d1 move.w #0,d2 tst.b (Title_anim_buffer).w ; FFFFBC toggles on and off so that each animation frame could alternate locations for a sort of makeshift double-buffering beq.s loc_445A move.w #tiles_to_bytes($300),d2 loc_445A: andi.l #$FFFFFF,d1 jsr (Add_To_DMA_Queue).l loc_4466: movea.l (a2)+,a0 ; Palette data address lea (Target_palette).w,a1 moveq #bytesToLcnt($40),d0 loc_446E: move.l (a0)+,(a1)+ dbf d0,loc_446E tst.b (Title_anim_buffer).w bne.s loc_44B8 lea (RAM_start+$8000).w,a1 ; Buffer 1 movea.l (a2)+,a0 ; Enigma Mappings move.w #make_art_tile($000,0,0),d0 bsr.w Eni_Decomp cmpi.w #7,d7 bhs.s loc_449A tst.b (Graphics_flags).w bmi.s loc_449A moveq #0,d0 move.l d0,(RAM_start+$83AC).w loc_449A: move #$2700,sr lea (RAM_start+$8000).w,a1 move.l #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE),d0 ; to $C000 in VRAM, Nametable A moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l move #$2300,sr rts ; --------------------------------------------------------------------------- loc_44B8: lea (RAM_start+$8000).w,a1 ; Buffer 2 movea.l (a2)+,a0 ; Enigma Mappings move.w #make_art_tile($300,0,0),d0 cmpi.w #7,d7 bhs.s loc_44CC move.w #make_art_tile($000,0,0),d0 loc_44CC: bsr.w Eni_Decomp cmpi.w #7,d7 bhs.s loc_44E2 tst.b (Graphics_flags).w bmi.s loc_44E2 moveq #0,d0 move.l d0,(RAM_start+$83AC).w loc_44E2: move #$2700,sr lea (RAM_start+$8000).w,a1 move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0 ; to $E000 in VRAM Nametable B moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l move #$2300,sr rts ; End of function TitleSonic_LoadFrame ; --------------------------------------------------------------------------- TitleSonic_Frames: dc.l ArtKos_S3TitleSonic1 ;S3DATA dc.l Pal_TitleSonic1 dc.l MapEni_S3TitleSonic1 ;S3DATA dc.l ArtKos_S3TitleSonic1 ;S3DATA dc.l Pal_TitleSonic2 dc.l MapEni_S3TitleSonic2 ;S3DATA dc.l ArtKos_S3TitleSonic1 ;S3DATA dc.l Pal_TitleSonic3 dc.l MapEni_S3TitleSonic3 ;S3DATA dc.l ArtKos_S3TitleSonic1 ;S3DATA dc.l Pal_TitleSonic4 dc.l MapEni_S3TitleSonic4 ;S3DATA dc.l ArtKos_S3TitleSonic1 ;S3DATA dc.l Pal_TitleSonic5 dc.l MapEni_S3TitleSonic5 ;S3DATA dc.l ArtKos_S3TitleSonic1 ;S3DATA dc.l Pal_TitleSonic6 dc.l MapEni_S3TitleSonic6 ;S3DATA dc.l ArtKos_S3TitleSonic1 ;S3DATA dc.l Pal_TitleSonic7 dc.l MapEni_S3TitleSonic7 ;S3DATA dc.l ArtKos_S3TitleSonic8 ;S3DATA dc.l Pal_TitleSonic8 dc.l MapEni_S3TitleSonic8 ;S3DATA dc.l ArtKos_S3TitleSonic9 ;S3DATA dc.l Pal_TitleSonic9 dc.l MapEni_S3TitleSonic9 ;S3DATA dc.l ArtKos_S3TitleSonicA ;S3DATA dc.l Pal_TitleSonicA dc.l MapEni_S3TitleSonicA ;S3DATA dc.l ArtKos_S3TitleSonicB ;S3DATA dc.l Pal_TitleSonicB dc.l MapEni_S3TitleSonicB ;S3DATA dc.l ArtKos_S3TitleSonicC ;S3DATA dc.l Pal_TitleSonicC dc.l MapEni_S3TitleSonicC ;S3DATA dc.l ArtKos_S3TitleSonicD ;S3DATA dc.l Pal_TitleSonicD dc.l MapEni_S3TitleSonicD ;S3DATA Pal_Title: binclude "General/Title/Palettes/S3.bin" even Pal_TitleSonic1: binclude "General/Title/Palettes/S3 Sonic 1.bin" even Pal_TitleSonic2: binclude "General/Title/Palettes/S3 Sonic 2.bin" even Pal_TitleSonic3: binclude "General/Title/Palettes/S3 Sonic 3.bin" even Pal_TitleSonic4: binclude "General/Title/Palettes/S3 Sonic 4.bin" even Pal_TitleSonic5: binclude "General/Title/Palettes/S3 Sonic 5.bin" even Pal_TitleSonic6: binclude "General/Title/Palettes/S3 Sonic 6.bin" even Pal_TitleSonic7: binclude "General/Title/Palettes/S3 Sonic 7.bin" even Pal_TitleSonic8: binclude "General/Title/Palettes/S3 Sonic 8.bin" even Pal_TitleSonic9: binclude "General/Title/Palettes/S3 Sonic 9.bin" even Pal_TitleSonicA: binclude "General/Title/Palettes/S3 Sonic A.bin" even Pal_TitleSonicB: binclude "General/Title/Palettes/S3 Sonic B.bin" even Pal_TitleSonicC: binclude "General/Title/Palettes/S3 Sonic C.bin" even Pal_TitleSonicD: binclude "General/Title/Palettes/S3 Sonic D.bin" even ; --------------------------------------------------------------------------- Obj_TitleBanner: move.l #Map_S3TitleBanner,mappings(a0) move.w #make_art_tile($500,3,1),art_tile(a0) ; Origin at $A000 move.w #$80,priority(a0) move.b #$80,width_pixels(a0) move.b #$40,height_pixels(a0) move.w #$120,x_pos(a0) move.w #$F0,y_pos(a0) move.w #$400,y_vel(a0) move.l #$FFA00000,$30(a0) move.l #Obj_TitleBanner_Main,(a0) Obj_TitleBanner_Main: move.b $34(a0),d2 move.w y_vel(a0),d0 ext.l d0 lsl.l #8,d0 add.l d0,$30(a0) move.w $30(a0),d0 move.b #0,$34(a0) move.w #$40,d1 cmpi.w #0,d0 blt.s loc_48B4 bne.s loc_48AA cmpi.w #-$5B,y_vel(a0) bne.s loc_48AA move.l #Obj_TitleBanner_Display,(a0) move.l #Obj_TitleTM,(Reserved_object_3).w bra.s loc_48C2 ; --------------------------------------------------------------------------- loc_48AA: move.b #-1,$34(a0) move.w #-$40,d1 loc_48B4: add.w d1,y_vel(a0) cmp.b $34(a0),d2 beq.s loc_48C2 asr y_vel(a0) loc_48C2: move.w $30(a0),d0 neg.w d0 addi.w #$D4,d0 move.w d0,y_pos(a0) cmpi.w #$10,(V_scroll_value).w ; Raise title screen Y position to make room for the &KNUCKLES beq.s Obj_TitleBanner_Display addq.w #1,(V_scroll_value).w Obj_TitleBanner_Display: subq.b #1,anim_frame_timer(a0) bpl.s loc_48F2 move.b #9,anim_frame_timer(a0) addq.b #4,anim_frame(a0) andi.b #$1C,anim_frame(a0) loc_48F2: moveq #0,d0 move.b anim_frame(a0),d0 move.l Pal_TitleWaterRot(pc,d0.w),(Target_palette_line_3+$1A).w jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Pal_TitleWaterRot: binclude "General/Title/Palettes/S3 Water Anim.bin" even ; --------------------------------------------------------------------------- Obj_TitleTM: move.l #Map_S3TitleBanner,mappings(a0) ;S3DATA move.w #make_art_tile($500,3,1),art_tile(a0) ; Start at $A000 move.w #$188,x_pos(a0) move.w #$EC,y_pos(a0) move.w #$80,priority(a0) move.b #$C,width_pixels(a0) move.b #4,height_pixels(a0) move.b #1,mapping_frame(a0) move.l #Obj_TitleTM_Display,(a0) Obj_TitleTM_Display: tst.b (Graphics_flags).w bpl.s locret_4968 jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_4968: rts ; --------------------------------------------------------------------------- Obj_TitleANDKnuckles: move.l #Map_TitleANDKnuckles,mappings(a0) move.w #make_art_tile($4C0,3,1),art_tile(a0) ; Start at $9800 move.w #$120,x_pos(a0) move.w #$108,y_pos(a0) move.w #$80,priority(a0) move.b #$54,width_pixels(a0) move.b #$C,height_pixels(a0) move.l #Obj_TitleANDKnuckles_Display,(a0) Obj_TitleANDKnuckles_Display: move.w (Player_1+y_pos).w,d0 addi.w #$5C,d0 move.w d0,y_pos(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Map_TitleANDKnuckles: include "General/Title/Map - S3 ANDKnuckles.asm" ; --------------------------------------------------------------------------- ; Dead code OldDebugCode: lea (OldDebugCodeDat).l,a1 move.w (Debug_mode_cheat_counter).w,d0 adda.w d0,a1 move.b (Ctrl_1_pressed_title).w,d0 andi.b #$7F,d0 beq.s locret_4A10 move.b (Ctrl_1_held_title).w,d0 cmp.b (a1),d0 bne.s loc_4A0A addq.w #1,(Debug_mode_cheat_counter).w tst.b 1(a1) bne.s locret_4A10 move.w #(1<<8)|1,(Debug_cheat_flag).w moveq #signextendB(sfx_RingLoss),d0 bsr.w Play_SFX loc_4A0A: move.w #0,(Debug_mode_cheat_counter).w locret_4A10: rts ; --------------------------------------------------------------------------- OldDebugCodeDat: dc.b button_C_mask dc.b button_C_mask|button_B_mask dc.b button_C_mask|button_B_mask|button_A_mask dc.b button_B_mask dc.b button_B_mask|button_A_mask dc.b button_B_mask|button_A_mask|button_C_mask dc.b button_A_mask dc.b button_A_mask|button_C_mask dc.b button_A_mask|button_C_mask|button_B_mask dc.b button_A_mask|button_C_mask|button_B_mask|button_up_mask dc.b button_A_mask|button_C_mask|button_B_mask|button_down_mask dc.b 0 even ; --------------------------------------------------------------------------- Obj_TitleCopyright: move.l #Map_TitleScreenText,mappings(a0) move.w #make_art_tile($680,3,1),art_tile(a0) ; Start at $D000 VRAM move.w #$158,x_pos(a0) move.w #$14C,y_pos(a0) move.w #$80,priority(a0) move.b #$C,width_pixels(a0) move.b #4,height_pixels(a0) move.b #3,mapping_frame(a0) move.l #Obj_TitleCopyright_Display,(a0) Obj_TitleCopyright_Display: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Obj_TitleSelection: move.w #$F0,x_pos(a0) move.w #$140,y_pos(a0) move.l #Map_TitleScreenText,mappings(a0) move.w #make_art_tile($680,2,1),art_tile(a0) ; Start at $D000 VRAM andi.b #1,(Title_screen_option).w move.b (Title_screen_option).w,mapping_frame(a0) move.l #Obj_TitleSelection_Main,(a0) Obj_TitleSelection_Main: moveq #0,d2 move.b (Title_screen_option).w,d2 move.b (Ctrl_1_pressed).w,d0 or.b (Ctrl_2_pressed).w,d0 btst #0,d0 beq.s loc_4AAE subq.b #1,d2 bcc.s loc_4AAE move.b #2,d2 tst.b (Level_select_flag).w ; If level select is on, maximum choices are 3 bne.s loc_4AAE move.b #1,d2 loc_4AAE: btst #1,d0 beq.s loc_4AC8 addq.b #1,d2 tst.b (Level_select_flag).w ; See above bne.s loc_4AC0 andi.b #1,d2 loc_4AC0: cmpi.b #3,d2 blo.s loc_4AC8 moveq #0,d2 loc_4AC8: move.b d2,mapping_frame(a0) move.b d2,(Title_screen_option).w andi.b #3,d0 beq.s loc_4ADE moveq #signextendB(sfx_Switch),d0 jsr (Play_SFX).l ; Only play sound if selection was changed loc_4ADE: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Obj_TitleSonicFinger: move.l #Map_TitleSonicAnim,mappings(a0) move.w #make_art_tile($400,1,1),art_tile(a0) ; Start at $8000 VRAM move.w #$148,x_pos(a0) move.w #$DC,y_pos(a0) move.w #$180,priority(a0) move.b #$18,width_pixels(a0) move.b #$1C,height_pixels(a0) move.l #Obj_TitleSonicFinger_Display,(a0) Obj_TitleSonicFinger_Display: move.w #$DC,d0 sub.w (V_scroll_value).w,d0 move.w d0,y_pos(a0) lea (Ani_TitleSonicFinger).l,a1 jsr (Animate_Sprite).l jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Ani_TitleSonicFinger: include "General/Title/Anim - S3 Sonic Finger.asm" ; --------------------------------------------------------------------------- Obj_TitleSonicWink: move.l #Map_TitleSonicAnim,mappings(a0) move.w #make_art_tile($400,1,1),art_tile(a0) ; Start at $8000 VRAM move.w #$F8,x_pos(a0) move.w #$C8,y_pos(a0) move.w #$180,priority(a0) move.b #$10,width_pixels(a0) move.b #$18,height_pixels(a0) move.l #Obj_TitleSonicWink_Display,(a0) Obj_TitleSonicWink_Display: move.w #$C8,d0 sub.w (V_scroll_value).w,d0 move.w d0,y_pos(a0) lea (Ani_TitleSonicWink).l,a1 jsr (Animate_SpriteIrregularDelay).l jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Ani_TitleSonicWink: include "General/Title/Anim - S3 Sonic Wink.asm" ; --------------------------------------------------------------------------- Obj_TitleTailsPlane: move.l #Map_TitleTailsPlane,mappings(a0) move.w #make_art_tile($400,3,0),art_tile(a0) ; Start at $8000 VRAM move.w #0,x_pos(a0) move.w #$C0,y_pos(a0) move.w #$380,priority(a0) move.b #$18,width_pixels(a0) move.b #8,height_pixels(a0) move.l #Obj_TitleTailsPlane_Main,(a0) Obj_TitleTailsPlane_Main: tst.b $30(a0) bne.s loc_4C0A addq.w #1,x_pos(a0) cmpi.w #$240,x_pos(a0) bne.s loc_4C08 move.b #1,$30(a0) bset #0,status(a0) move.w #$D0,y_pos(a0) loc_4C08: bra.s loc_4C28 ; --------------------------------------------------------------------------- loc_4C0A: subq.w #1,x_pos(a0) cmpi.w #0,x_pos(a0) bne.s loc_4C28 move.b #0,$30(a0) bclr #0,status(a0) move.w #$C0,y_pos(a0) loc_4C28: lea (Ani_TitleTailsPlane).l,a1 jsr (Animate_Sprite).l tst.b render_flags(a0) bpl.s loc_4C3E bsr.w S3_Level_Select_Code loc_4C3E: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Ani_TitleTailsPlane: include "General/Title/Anim - S3 Tails Plane.asm" ; =============== S U B R O U T I N E ======================================= S3_Level_Select_Code: rts ; --------------------------------------------------------------------------- lea (LSelect3CodeDat).l,a1 move.w (Level_select_cheat_counter).w,d0 adda.w d0,a1 move.b (Ctrl_1_pressed_title).w,d0 andi.b #$7F,d0 beq.s locret_4C90 move.b (Ctrl_1_held_title).w,d0 cmp.b (a1),d0 bne.s loc_4C8A addq.w #1,(Level_select_cheat_counter).w tst.b 1(a1) bne.s locret_4C90 move.w #(1<<8)|1,(Level_select_flag).w move.w #(1<<8)|1,(Debug_cheat_flag).w moveq #signextendB(sfx_RingRight),d0 bsr.w Play_SFX loc_4C8A: move.w #0,(Level_select_cheat_counter).w locret_4C90: rts ; End of function S3_Level_Select_Code ; --------------------------------------------------------------------------- LSelect3CodeDat: dc.b button_up_mask dc.b button_up_mask dc.b button_down_mask dc.b button_down_mask dc.b button_up_mask dc.b button_up_mask dc.b button_up_mask dc.b button_up_mask dc.b 0 even Map_TitleScreenText: include "General/Title/Map - S3 Screen Text.asm" ArtNem_TitleScreenText: binclude "General/Title/Nemesis Art/S3 Screen Text.bin" even Map_TitleSonicAnim: include "General/Title/Map - S3 Sonic Anim.asm" Map_TitleTailsPlane: include "General/Title/Map - S3 Tails Plane.asm" ; --------------------------------------------------------------------------- SK_Alone_Title_Screen: lea (ArtKos_SKTitleScreenBG).l,a0 lea (RAM_start).l,a1 bsr.w Kos_Decomp lea (ArtKos_BigSEGA).l,a0 bsr.w Kos_Decomp lea (ArtKos_SKTitle_SonicFall).l,a0 ; Get title BG, Sega logo, and Sonic falling frame going bsr.w Kos_Decomp move.w a1,d3 lsr.w #1,d3 move.l #$FF0000,d1 move.w #tiles_to_bytes($000),d2 move.w #$E20,d3 jsr (Add_To_DMA_Queue).l ; DMA the BG first to $0 in VRAM move.l #$FF1C40,d1 move.w #tiles_to_bytes($49C),d2 move.w #$1640,d3 jsr (Add_To_DMA_Queue).l ; Then DMA the logo and Sonic falling frame to $9380 in VRAM lea (RAM_start+$4E00).l,a1 lea (ArtKos_SKTitle_DeathEgg).l,a0 bsr.w Kos_Decomp move.l #$FF4E00,d1 move.w #tiles_to_bytes($680),d2 move.w #$720,d3 jsr (Add_To_DMA_Queue).l ; DMA the Death Egg title screen art to $D000 in VRAM lea (RAM_start+$5D00).l,a1 lea (ArtKos_SKTitle_Mountain).l,a0 bsr.w Kos_Decomp move.l #$FF5D00,d1 move.w #tiles_to_bytes($7A0),d2 move.w #$150,d3 jsr (Add_To_DMA_Queue).l ; DMA the little section of mountain that is drawn above the Death Egg lea (RAM_start+$7400).l,a1 lea (MapEni_SKTitle_Sega).l,a0 ; Get the SEGA logo mappings move.w #make_art_tile($49C,0,1),d0 bsr.w Eni_Decomp tst.b (Graphics_flags).w bmi.s loc_5122 move.w #make_art_tile($49C,1,1),d0 move.w d0,(RAM_start+$775C).l move.w d0,(RAM_start+$775E).l move.w d0,(RAM_start+$7760).l move.w d0,(RAM_start+$77AC).l move.w d0,(RAM_start+$77AE).l move.w d0,(RAM_start+$77B0).l ; Remove the TM from the Sega logo if on a Japan console loc_5122: lea (RAM_start+$7400).l,a1 move.l #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE),d0 moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l ; Copy Sega logo mappings to VRAM location $C000 lea (RAM_start+$7CC0).l,a1 lea (MapEni_SKTitle_Background).l,a0 move.w #make_art_tile($000,0,0),d0 bsr.w Eni_Decomp lea (RAM_start+$7CC0).l,a1 move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0 bsr.w RAM_Map_Data_To_VDP ; Copy SK Title Background mappings to VRAM location $E000 lea (RAM_start+$8580).w,a1 lea (MapEni_SKTitle_Frame1).l,a0 move.w #make_art_tile($0E2,0,1),d0 bsr.w Eni_Decomp lea (RAM_start+$8E40).w,a1 lea (MapEni_SKTitle_Frame2).l,a0 move.w #make_art_tile($0E2,0,1),d0 bsr.w Eni_Decomp lea (RAM_start+$9700).w,a1 lea (MapEni_SKTitle_Frame3).l,a0 move.w #make_art_tile($0E2,0,1),d0 bsr.w Eni_Decomp lea (RAM_start+$9FC0).w,a1 lea (MapEni_SKTitle_Frame4).l,a0 move.w #make_art_tile($0E2,0,1),d0 bsr.w Eni_Decomp lea (ArtKos_SKTitle_SonKnuxHand).l,a1 lea (RAM_start+$4800).l,a2 jsr (Queue_Kos).l ; Queue the Sonic/Knuckles hand animation art lea (Target_palette).w,a1 moveq #4-1,d1 loc_51BC: move.w #0,(a1)+ moveq #$F-1,d0 loc_51C2: move.w #$EEE,(a1)+ ; Set up the palette to full white dbf d0,loc_51C2 dbf d1,loc_51BC lea (Pal_SKTitle_SegaBG).l,a0 lea (Target_palette_line_2).w,a1 moveq #bytesToLcnt($20),d0 loc_51DA: move.l (a0)+,(a1)+ ; Load Sega palette into the first F colors of pal line 1 dbf d0,loc_51DA move.w #3*60,(Demo_timer).w ; Set vsync timer to 3 seconds (180 frames NTSC) btst #6,(Graphics_flags).w beq.s loc_51F4 move.w #3*50,(Demo_timer).w ; Set vsync timer to 3 seconds (150 frames PAL) loc_51F4: move.w (VDP_reg_1_command).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l ; Turn the display on bsr.w Pal_FadeFromBlack ; Fade to Sega screen moveq #signextendB(mus_SEGA),d0 ; SEGA sound bsr.w Play_Music loc_520C: move.b #$14,(V_int_routine).w jsr (Process_Kos_Queue).l bsr.w Wait_VSync jsr (Process_Kos_Module_Queue).l tst.b (Kos_modules_left).w bne.s loc_520C ; Don't allow the game to continue until the Knuckles art has been decompressed move.b (Ctrl_1_pressed).w,d0 andi.b #button_start_mask,d0 bne.w loc_523A ; If start is pressed afterwards, skip to next part of title tst.w (Demo_timer).w bne.s loc_520C ; Otherwise, wait for vsync timer to run out loc_523A: moveq #signextendB(mus_StopSEGA),d0 bsr.w Play_Music ; Stop the SEGA sound if necessary lea (Pal_SKTitle_Sonic).l,a0 lea (Target_palette).w,a1 moveq #bytesToLcnt($80),d0 loc_524C: move.l (a0)+,(a1)+ dbf d0,loc_524C ; Load the Sonic palette and Sega palette lea (ArtKosM_SonicKnuxStand).l,a1 move.w #tiles_to_bytes($0E2),d2 jsr (Queue_Kos_Module).l ; Cue the art Sonic and Knuckles standing move.w #$40-1,(Palette_fade_info).w move.w #$16,(Palette_fade_timer).w ; Number of frames to fade from white move.l #Obj_SKTitle_SonicFall,(Player_1).w move.l #Obj_SKTitle_DeathEgg,(Player_2).w move.l #Obj_SKTitle_Mountain,(Reserved_object_3).w moveq #signextendB(mus_TitleScreen),d0 bsr.w Play_Music ; Play the title screen music move.b #3,(Life_count).w move.w #18*60,(Demo_timer).w ; 18 second delay (1080 frames NTSC) btst #6,(Graphics_flags).w beq.s loc_52A6 move.w #18*50,(Demo_timer).w ; 18 second delay (900 frames PAL) loc_52A6: move.b #$1A,(V_int_routine).w jsr (Process_Kos_Queue).l bsr.w Wait_VSync tst.w (Palette_fade_timer).w beq.s loc_52C4 subq.w #1,(Palette_fade_timer).w bsr.w Pal_FromWhite ; Fade from white for set number of frames loc_52C4: jsr (Process_Sprites).l jsr (Render_Sprites).l bsr.w SKTitle_DeformBG jsr (Process_Kos_Module_Queue).l move.b (Ctrl_1_pressed).w,d0 andi.b #button_start_mask,d0 bne.w loc_52F0 ; If start is pressed, branch tst.l (Dynamic_object_RAM).w ; test if banner object has been created beq.s loc_52A6 ; If not, continue with the above bra.w loc_537C ; --------------------------------------------------------------------------- loc_52F0: tst.w (Palette_fade_timer).w bne.s loc_52A6 ; If palette fade hasn't completed, go back lea (Dynamic_object_RAM+object_size).w,a0 bsr.w Obj_SKTitle_HandAnim ; Initialize Hand animation object move.l #Obj_SKTitle_DeathEggShake,(Player_2).w ; Change Death Egg object to second phase move.w #$140,(Player_2+objoff_2E).l move.w #$70,(Player_2+objoff_32).l ; Set its proper position move.w #3,(Events_routine_fg).w ; Put title routine counter to max moveq #0,d0 move.w d0,(Screen_shake_flag).w ; Turn off shaking move.w #$100,d0 move.w d0,(V_scroll_value_BG).w move.w d0,(V_scroll_value_BG).w move.w d0,(Camera_Y_pos).w move.w d0,(Camera_Y_pos_P2).w ; Set all Y scrolls to $100 lea (Pal_SKTitle_Knux).l,a0 lea (Normal_palette_line_2).w,a2 moveq #8-1,d0 loc_5342: move.l (a0),$80(a2) move.l (a0)+,(a2)+ ; Change to Knuckles palette dbf d0,loc_5342 bsr.w SKTitle_DeformBG ; Deform the BG to apply the changes move.b #$1A,(V_int_routine).w bsr.w Wait_VSync ; Refresh the screen move #$2700,sr lea (Chunk_table+$7CC0).l,a1 move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0 moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l ; Load the background lea (Player_1).w,a0 bsr.w Obj_SKTitle_SonicFallFinish ; Finish the sonic fall object loc_537C: move.b #$1A,(V_int_routine).w jsr (Process_Kos_Queue).l bsr.w Wait_VSync tst.w (Palette_fade_timer).w beq.s loc_539A subq.w #1,(Palette_fade_timer).w bsr.w Pal_FromWhite loc_539A: jsr (Process_Sprites).l jsr (Render_Sprites).l bsr.w SKTitle_DeformBG jsr (Process_Kos_Module_Queue).l bsr.w S3_Level_Select_Code ; This routine is dummied out tst.l (Dynamic_object_RAM+(object_size*2)).w beq.s loc_537C ; If menu object isn't loaded, branch tst.w (Demo_timer).w beq.w loc_546C ; If timer has run out, branch forward move.b (Ctrl_1_pressed).w,d0 andi.b #button_start_mask,d0 beq.w loc_537C ; If start is not pressed, branch back move.b #$C,(Game_mode).w ; Play a level move.b #3,(Life_count).w move.b #3,(Life_count_P2).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_P2).w move.l d0,(Timer_P2).w move.l d0,(Score_P2).w move.b d0,(Continue_count).w move.l #5000,(Next_extra_life_score).w move.l #5000,(Next_extra_life_score_P2).w moveq #signextendB(mus_FadeOut),d0 bsr.w Play_SFX moveq #0,d0 move.b (Title_screen_option).w,d0 cmpi.b #2,d0 bhs.w loc_5464 add.w d0,d0 addq.w #1,d0 move.w d0,(Player_option).w move.w #$700,d0 move.w d0,(Current_zone_and_act).w move.w d0,(Apparent_zone_and_act).w move.w d0,(Saved_zone_and_act).w clr.w (Current_special_stage).w clr.w (Emerald_counts).w clr.l (Collected_emeralds_array).w clr.w (Collected_emeralds_array+4).w clr.b (Collected_emeralds_array+6).w clr.l (Collected_special_ring_array).w clr.l (Save_pointer).w tst.b (Level_select_flag).w beq.s locret_546A btst #button_A,(Ctrl_1).w beq.s locret_546A loc_5464: move.b #$28,(Game_mode).w locret_546A: rts ; --------------------------------------------------------------------------- loc_546C: moveq #signextendB(mus_FadeOut),d0 ; Start demo by fading out music bsr.w Play_SFX move.w (Next_demo_number).w,d0 ; Get demo number cmpi.w #3,d0 bhs.s loc_547E moveq #3,d0 loc_547E: move.w d0,(Next_demo_number).w move.w d0,(Demo_number).w andi.w #7,d0 add.w d0,d0 lea DemoLevels(pc),a0 move.w (a0,d0.w),d0 ; Get the right demo level move.w d0,(Current_zone_and_act).w move.w d0,(Apparent_zone_and_act).w move.w d0,(Saved_zone_and_act).w ; Move it to various level ID locations move.w (Next_demo_number).w,d1 addq.w #1,d1 cmpi.w #7,d1 blo.s loc_54AE moveq #3,d1 loc_54AE: move.w d1,(Next_demo_number).w tst.w d0 bpl.s loc_54E0 move.b #$34,(Game_mode).w ; Special stage move.b #1,(Current_special_stage).w move.b #1,(SK_special_stage_flag).w move.b #7,(Current_zone).w clr.w (Emerald_counts).w clr.l (Collected_emeralds_array).w clr.w (Collected_emeralds_array+4).w clr.b (Collected_emeralds_array+6).w bra.s loc_54F0 ; --------------------------------------------------------------------------- loc_54E0: cmpi.w #$700,d0 bne.s loc_54EA jsr Prep_MHZDemo(pc) ; If doing Mushroom Hill demo, do this routine loc_54EA: move.b #8,(Game_mode).w loc_54F0: move.w #1,(Demo_mode_flag).w move.b #3,(Life_count).w move.b #3,(Life_count_P2).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_P2).w move.l d0,(Timer_P2).w move.l d0,(Score_P2).w move.l #5000,(Next_extra_life_score).w move.l #5000,(Next_extra_life_score_P2).w rts ; =============== S U B R O U T I N E ======================================= Prep_MHZDemo: move.w #$6F4,(Saved_X_pos).w move.w #$9EC,(Saved_Y_pos).w move.b #1,(Last_star_post_hit).w move.b #1,(Saved_last_star_post_hit).w move.w d0,(Saved_zone_and_act).w move.w d0,(Saved_apparent_zone_and_act).w move.w #$680,(Saved_art_tile).w move.w #$C0D,(Saved_solid_bits).w clr.w (Saved_ring_count).w clr.b (Saved_extra_life_flags).w clr.l (Saved_timer).w clr.b (Saved_dynamic_resize_routine).w move.w #$AA0,(Saved_camera_max_Y_pos).w move.w #$680,(Saved_camera_X_pos).w move.w #$98C,(Saved_camera_Y_pos).w move.w #$1000,(Saved_mean_water_level).w clr.b (Saved_water_full_screen_flag).w rts ; End of function Prep_MHZDemo ; --------------------------------------------------------------------------- Pal_SKTitle_Sonic: binclude "General/Title/Palettes/SK Sonic.bin" even Pal_SKTitle_SegaBG: binclude "General/Title/Palettes/SK Sega and BG.bin" even Pal_SKTitle_Knux: binclude "General/Title/Palettes/SK Knuckles.bin" even ; --------------------------------------------------------------------------- Obj_SKTitle_SonicFall: move.l #Map_SKTitle_SonicFall,mappings(a0) move.w #make_art_tile($4EF,0,0),art_tile(a0) move.w #$E8,x_pos(a0) move.w #$16,y_pos(a0) ; Set position of falling Sonic sprite move.w #$80,priority(a0) move.b #$68,width_pixels(a0) move.b #$70,height_pixels(a0) ; Set effective size of sprite move.l #Obj_SKTitle_SonicFallMain,(a0) Obj_SKTitle_SonicFallMain: cmpi.w #$F0,y_pos(a0) beq.s loc_5666 addq.w #1,y_pos(a0) ; Slowly move Sonic downwards loc_5666: cmpi.w #3,(Events_routine_fg).w bne.s loc_56AA ; Wait until the proper phase of the title sequence ori.w #high_priority,art_tile(a0) ; Modify the priority of the sprite cmpi.w #$E0,(Camera_Y_pos).w bhs.s loc_56B0 ; If the foreground Y is past $E0, branch addq.w #8,(Camera_Y_pos).w ; Otherwise scroll foreground by 8 pixels cmpi.w #$C8,(Camera_Y_pos).w bne.s loc_5698 lea (ArtKosM_SonicLand).l,a1 ; Once foreground has hit C8 Y move.w #tiles_to_bytes($462),d2 jsr (Queue_Kos_Module).l ; Queue the landing frames into VRAM loc_5698: lea (RAM_start+$8580).w,a1 ; First frame data (Knuckles only) move.l #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE),d0 move.w (Camera_Y_pos).w,d1 bsr.w Copy_Map_Line_To_VRAM ; Since the nametable is only 32 tiles high, we can't copy the first foreground mapping frame for Sonic and Knuckles wholesale. ; We set up each line of mappings data every time the screen scrolls down further loc_56AA: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_56B0: bne.s loc_56D4 move #$2700,sr ; Only do this when screen scrolling has his E0 Y lea (RAM_start+$8E40).w,a1 ; Second frame data (Sonic lands) move.l #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE),d0 moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l ; Copy the frame data move #$2300,sr move.b #6,anim_frame_timer(a0) ; Set up an internal timer loc_56D4: cmpi.w #$100,(Camera_Y_pos).w beq.s loc_56E2 ; When screen has hit $100 Y, branch addq.w #8,(Camera_Y_pos).w rts ; --------------------------------------------------------------------------- loc_56E2: move.l #Obj_SKTitle_SonicFallLand,(a0) Obj_SKTitle_SonicFallLand: subq.b #1,anim_frame_timer(a0) bpl.s locret_5716 move #$2700,sr lea (Block_table+$700).w,a1 ; Get third mapping frame (Sonic starting to stand) move.l #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE),d0 moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l move #$2300,sr move.b #4,anim_frame_timer(a0) move.l #Obj_SKTitle_SonicFallLand_2,(a0) locret_5716: rts ; --------------------------------------------------------------------------- Obj_SKTitle_SonicFallLand_2: subq.b #1,anim_frame_timer(a0) bpl.s Obj_SKTitle_SonicFallEnd ; =============== S U B R O U T I N E ======================================= Obj_SKTitle_SonicFallFinish: move #$2700,sr lea (Block_table+$FC0).w,a1 ; Get last mapping frame (Sonic and Knuckles standing properly) move.l #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE),d0 moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l move #$2300,sr lea (ArtKosM_SKTitle_Banner).l,a1 move.w #tiles_to_bytes($4EE),d2 jsr (Queue_Kos_Module).l lea (ArtKosM_SKTitle_Menu).l,a1 move.w #tiles_to_bytes($462),d2 jsr (Queue_Kos_Module).l ; Set up the banner and menu graphics to replace the landing graphics move.l #Obj_SKTitle_Banner,(Dynamic_object_RAM).w move.b #30,(Dynamic_object_RAM+anim_frame_timer).w ; $24 of object set to 30 move.l #Obj_SKTitle_SonicFallEnd,(a0) ; Disable object Obj_SKTitle_SonicFallEnd: rts ; End of function Obj_SKTitle_SonicFallFinish ; --------------------------------------------------------------------------- Obj_SKTitle_DeathEgg: move.l #Map_SKTitle_DeathEgg,mappings(a0) move.w #make_art_tile($680,2,0),art_tile(a0) move.w #$140,x_pos(a0) move.w #$B0,y_pos(a0) move.w #$180,priority(a0) move.b #$40,width_pixels(a0) move.b #$40,height_pixels(a0) move.l #Obj_SKTitle_DeathEggMain,(a0) Obj_SKTitle_DeathEggMain: cmpi.w #$F0,y_pos(a0) beq.s loc_57D8 ; If Death Egg has reached volcano, branch addi.l #$8000,y_pos(a0) ; Move Death Egg sprite downward cmpi.w #$100,(Camera_Y_pos_P2).w beq.s loc_57D2 addq.w #1,(Camera_Y_pos_P2).w ; Scroll screen downwards lea (Chunk_table+$7CC0).l,a1 move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0 move.w (Camera_Y_pos_P2).w,d1 bsr.w Copy_Map_Line_To_VRAM ; Update second nametable with background mappings as the screen scrolls down loc_57D2: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_57D8: move.l x_pos(a0),$2E(a0) move.l y_pos(a0),$32(a0) ; Backup position values move.w #$8000,(Camera_Y_pos_P2+2).w move.w #$22,(Events_bg+$00).w move.w #1,(Events_routine_fg).w move.w #$1E,(Screen_shake_flag).w move.l #Obj_SKTitle_DeathEggShake,(a0) Obj_SKTitle_DeathEggShake: bsr.w SKTitle_ScreenShake cmpi.w #$100,(Camera_Y_pos_P2).w beq.s loc_5832 subi.l #$8000,$32(a0) ; Move Death Egg backwards to keep up with scroll addi.l #$8000,(Camera_Y_pos_P2).w lea (Chunk_table+$7CC0).l,a1 move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0 move.w (Camera_Y_pos_P2).w,d1 bsr.w Copy_Map_Line_To_VRAM ; Continue drawing mapping lines loc_5832: move.w $2E(a0),d0 move.w $32(a0),d1 tst.w (Screen_shake_flag).w beq.s loc_5848 sub.w (Camera_X_pos_P2_copy).w,d0 sub.w (Camera_Y_pos_P2_copy).w,d1 ; Shake Death Egg along with screen loc_5848: move.w d0,x_pos(a0) move.w d1,y_pos(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Obj_SKTitle_Mountain: move.l #Map_SKTitle_Mountain,mappings(a0) ; The top of the mountain is a sprite so it can cover the Death Egg move.w #make_art_tile($7A0,3,0),art_tile(a0) move.w #$100,priority(a0) move.b #$30,width_pixels(a0) move.b #8,height_pixels(a0) move.l #Obj_SKTitle_MountainMain,(a0) Obj_SKTitle_MountainMain: move.w #$140,d0 move.w #$1A8,d1 sub.w (Camera_X_pos_P2).w,d0 sub.w (Camera_Y_pos_P2).w,d1 tst.w (Screen_shake_flag).w beq.s loc_589A sub.w (Camera_X_pos_P2_copy).w,d0 sub.w (Camera_Y_pos_P2_copy).w,d1 loc_589A: move.w d0,x_pos(a0) move.w d1,y_pos(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Obj_SKTitle_Banner: subq.b #1,anim_frame_timer(a0) beq.s loc_58B0 ; Wait for the timer to finish rts ; --------------------------------------------------------------------------- loc_58B0: move.l #Map_SKTitle_Banner,mappings(a0) move.w #make_art_tile($4EE,0,1),art_tile(a0) move.w #0,priority(a0) move.b #$7C,width_pixels(a0) move.b #$28,height_pixels(a0) ; Set up sprite size and priority move.w #$120,x_pos(a0) move.w #$180,y_pos(a0) ; Position sprite below the screen move.w #$400,y_vel(a0) ; Set up Y velocity move.l #-$600000,$30(a0) ; Set up Y position offset move.l #Obj_SKTitle_BannerMain,(a0) Obj_SKTitle_BannerMain: move.b $34(a0),d2 move.w y_vel(a0),d0 ext.l d0 lsl.l #8,d0 add.l d0,$30(a0) ; Add velocity to Y offset move.w $30(a0),d0 move.b #0,$34(a0) ; Set direction toggle flag move.w #$40,d1 cmpi.w #0,d0 blt.s loc_5950 ; If offset is negative, branch bne.s loc_5946 ; If offset is positive and nonzero, branch cmpi.w #-$5B,y_vel(a0) bne.s loc_5946 ; Branch if the velocity isn't small enough move.l #Obj_SKTitle_BannerDisplay,(a0) move.l #Obj_SKTitle_Icon,(Dynamic_object_RAM+(object_size*2)).w move.l #Obj_SKTitle_Icon2,(Dynamic_object_RAM+(object_size*3)).w move.l #Obj_SKTitle_TM,(Dynamic_object_RAM+(object_size*4)).w move.l #Obj_SKTitle_Copyright,(Dynamic_object_RAM+(object_size*5)).w ; Set up menu items and the like bra.s loc_595E ; --------------------------------------------------------------------------- loc_5946: move.b #-1,$34(a0) ; This is all to perform the bobbing motion into place move.w #-$40,d1 loc_5950: add.w d1,y_vel(a0) cmp.b $34(a0),d2 beq.s loc_595E asr y_vel(a0) loc_595E: move.w $30(a0),d0 neg.w d0 addi.w #$118,d0 move.w d0,y_pos(a0) Obj_SKTitle_BannerDisplay: jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= Obj_SKTitle_HandAnim: move.l #Chunk_table+$4800,d1 move.w #tiles_to_bytes($0E3),d2 move.w #$30,d3 jsr (Add_To_DMA_Queue).l move.l #Chunk_table+$4E40,d1 move.w #tiles_to_bytes($0E6),d2 move.w #$290,d3 jsr (Add_To_DMA_Queue).l ; Load the correct initial art move.b #3*60,$30(a0) move.l #Obj_SKTitle_HandAnimMain,(a0) Obj_SKTitle_HandAnimMain: lea (SKTitle_AnimSmile).l,a1 lea $30(a0),a2 bsr.w SKTitle_AnimateHands bmi.s loc_59D0 lea (RAM_start+$4800).l,a1 lea (a1,d0.w),a1 move.l a1,d1 move.w #tiles_to_bytes($0E3),d2 move.w #$30,d3 jsr (Add_To_DMA_Queue).l loc_59D0: lea (SKTitle_AnimFinger).l,a1 lea $32(a0),a2 bsr.w SKTitle_AnimateHands bmi.s loc_59FA lea (RAM_start+$4920).l,a1 lea (a1,d0.w),a1 move.l a1,d1 move.w #tiles_to_bytes($0E6),d2 move.w #$290,d3 jsr (Add_To_DMA_Queue).l loc_59FA: lea (SKTitle_AnimKnuckle1).l,a1 lea $34(a0),a2 bsr.w SKTitle_AnimateHands bmi.s loc_5A24 lea (RAM_start+$5880).l,a1 lea (a1,d0.w),a1 move.l a1,d1 move.w #tiles_to_bytes($10F),d2 move.w #$2F0,d3 jsr (Add_To_DMA_Queue).l loc_5A24: lea (SKTitle_AnimKnuckle2).l,a1 lea $36(a0),a2 bsr.w SKTitle_AnimateHands bmi.s locret_5A4E lea (RAM_start+$6A20).l,a1 lea (a1,d0.w),a1 move.l a1,d1 move.w #tiles_to_bytes($13E),d2 move.w #$140,d3 jsr (Add_To_DMA_Queue).l locret_5A4E: rts ; End of function Obj_SKTitle_HandAnim ; =============== S U B R O U T I N E ======================================= SKTitle_AnimateHands: subq.b #1,(a2) bcc.s loc_5A6C move.b (a1),(a2) moveq #0,d1 move.b 1(a2),d1 move.b 1(a1,d1.w),d0 bmi.s loc_5A70 loc_5A62: addq.b #1,1(a2) ext.w d0 lsl.w #5,d0 rts ; --------------------------------------------------------------------------- loc_5A6C: moveq #-1,d0 rts ; --------------------------------------------------------------------------- loc_5A70: addq.b #1,d0 bne.s loc_5A80 move.b #0,1(a2) move.b 1(a1),d0 bra.s loc_5A62 ; --------------------------------------------------------------------------- loc_5A80: addq.b #1,d0 bne.s loc_5A6C move.b 2(a1,d1.w),d0 sub.b d0,1(a2) sub.b d0,d1 move.b 1(a1,d1.w),d0 bra.s loc_5A62 ; End of function sub_5A50 ; --------------------------------------------------------------------------- SKTitle_AnimSmile: dc.b 5, 0, 3, 6, $FE, 1 SKTitle_AnimFinger: dc.b 3, $29, $29, $29, $29, $29, $29, $29, $29, $29, $29, $29, $29, $29, $29, $29, $29, $29, $29, $29 dc.b $29, $29, $29, $29, $29, $29, $29, $29, $29, $29, $29, $29, $29, 0, 0, $29, $52, $29, 0, $29 dc.b $52, $29, 0, $29, $52, $29, $FF SKTitle_AnimKnuckle1: dc.b 3, 0, 0, 0, 0, 0, 0, 0, 0, $2F, $5E, $2F, 0, $2F, $5E, $2F, $FF SKTitle_AnimKnuckle2: dc.b 3, 0, 0, $14, $28, $14, 0, 0, $FF even ; --------------------------------------------------------------------------- Obj_SKTitle_Icon: move.w #$108,x_pos(a0) move.w #$150,y_pos(a0) move.w x_pos(a0),$44(a0) move.w y_pos(a0),$46(a0) move.l #Map_SKTitle_Icon,mappings(a0) move.w #make_art_tile($462,0,1),art_tile(a0) bset #6,render_flags(a0) ; Turn on multi-sprite mode lea sub2_x_pos(a0),a2 move.w #2,mainspr_childsprites(a0) move.w x_pos(a0),(a2)+ move.w y_pos(a0),(a2)+ ; First sprite is the Sonic/Knuckles icon move.w #0,(a2)+ andi.b #1,(Title_screen_option).w move.b (Title_screen_option).w,d0 ror.b #1,d0 move.b d0,angle(a0) move.b #8,$27(a0) move.l #Obj_SKTitle_IconDisplay,(a0) Obj_SKTitle_IconDisplay: moveq #0,d2 move.b (Title_screen_option).w,d2 ; Get current selection move.b angle(a0),d0 andi.b #$7F,d0 bne.s loc_5B9E ; If selection is currently, being rotated, branch move.b (Ctrl_1_pressed).w,d0 btst #0,d0 beq.s loc_5B6E subq.b #8,angle(a0) ; if down was pressed, rotate backwards move.b #-8,$27(a0) subq.b #1,d2 bcc.s loc_5B6E move.b #1,d2 loc_5B6E: btst #1,d0 beq.s loc_5B8C addq.b #8,angle(a0) ; if up was pressed, rotate forward move.b #8,$27(a0) addq.b #1,d2 andi.b #1,d2 cmpi.b #3,d2 blo.s loc_5B8C moveq #0,d2 loc_5B8C: move.b d2,(Title_screen_option).w ; Move selection andi.b #3,d0 beq.s loc_5B9E moveq #signextendB(sfx_Switch),d0 jsr (Play_SFX).l ; Only play sound if selection was made loc_5B9E: move.b angle(a0),d0 andi.b #$7F,d0 beq.s loc_5BB0 move.b $27(a0),d0 ; Perform rotation if necessary add.b d0,angle(a0) loc_5BB0: move.b angle(a0),d0 ; Get rotation angle addi.b #$98,d0 jsr (GetSineCosine).l muls.w #5,d1 muls.w #5,d0 asr.l #8,d1 asr.l #8,d0 ; Convert to X/Y coordinates move.w d1,d3 move.w d0,d2 add.w $44(a0),d1 add.w $46(a0),d0 neg.w d3 neg.w d2 add.w $44(a0),d3 add.w $46(a0),d2 moveq #0,d4 moveq #2,d5 move.b angle(a0),d6 subi.b #$A0,d6 bpl.s loc_5BF6 exg d1,d3 ; Exchange attributes of Sonic/Knuckles text sprites depending on the rotation angle exg d0,d2 exg d4,d5 loc_5BF6: addq.b #1,d5 lea sub2_x_pos(a0),a2 move.w d1,(a2)+ ; sub2_x_pos move.w d0,(a2)+ ; sub2_y_pos move.w d4,(a2)+ ; sub2_mapframe move.w d3,(a2)+ ; sub3_x_pos move.w d2,(a2)+ ; sub3_y_pos move.b d5,1(a2) ; sub3_mapframe jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Obj_SKTitle_Icon2: move.w #$D0,x_pos(a0) move.w #$14C,y_pos(a0) move.l #Map_SKTitle_Icon,mappings(a0) move.w #make_art_tile($462,0,1),art_tile(a0) move.b (Title_screen_option).w,d0 move.b d0,anim(a0) move.b d0,prev_anim(a0) move.b #1,anim_frame(a0) move.l #Obj_SKTitle_Icon2Display,(a0) Obj_SKTitle_Icon2Display: move.b (Title_screen_option).w,anim(a0) lea (Ani_SKTitle_Icon).l,a1 jsr (Animate_Sprite).l jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Ani_SKTitle_Icon: include "General/Title/Anim - SK Icon.asm" ; --------------------------------------------------------------------------- Obj_SKTitle_TM: move.l #Map_SKTitle_TM,mappings(a0) move.w #make_art_tile($462,0,1),art_tile(a0) move.w #$1A2,x_pos(a0) move.w #$11D,y_pos(a0) move.w #$80,priority(a0) move.b #8,width_pixels(a0) move.b #4,height_pixels(a0) move.l #Obj_SKTitle_TMDisplay,(a0) Obj_SKTitle_TMDisplay: tst.b (Graphics_flags).w bpl.s locret_5CAE jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_5CAE: rts ; --------------------------------------------------------------------------- Obj_SKTitle_Copyright: move.l #Map_SKTitle_Copyright,mappings(a0) move.w #make_art_tile($462,0,1),art_tile(a0) move.w #$17F,x_pos(a0) move.w #$152,y_pos(a0) move.w #$80,priority(a0) move.b #$2C,width_pixels(a0) move.b #4,height_pixels(a0) move.l #Obj_SKTitle_CopyrightDisplay,(a0) Obj_SKTitle_CopyrightDisplay: jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= Copy_Map_Line_To_VRAM: subi.w #$10,d1 bcs.s locret_5D22 move.w d1,d3 andi.w #7,d3 bne.s locret_5D22 andi.w #$F8,d1 move.w d1,d2 add.w d1,d1 move.w d1,d3 lsl.w #2,d1 add.w d3,d1 lea (a1,d1.w),a1 lsl.w #4,d2 swap d0 add.w d2,d0 swap d0 moveq #$28-1,d3 lea (VDP_data_port).l,a6 move #$2700,sr bsr.s sub_5D42 move #$2300,sr locret_5D22: rts ; End of function Copy_Map_Line_To_VRAM ; =============== S U B R O U T I N E ======================================= RAM_Map_Data_To_VDP: lea (VDP_data_port).l,a6 moveq #$28-1,d1 moveq #$20-1,d2 .loop: movea.l a1,a2 move.w d1,d3 bsr.s sub_5D42 movea.l a2,a1 addi.l #$80<<16,d0 dbf d2,.loop rts ; End of function RAM_Map_Data_To_VDP ; =============== S U B R O U T I N E ======================================= sub_5D42: move.l d0,VDP_control_port-VDP_data_port(a6) .loop: move.w (a1)+,(a6) dbf d3,.loop rts ; End of function sub_5D42 ; =============== S U B R O U T I N E ======================================= ClearVRAMArea: lea (VDP_data_port).l,a6 move.l d0,VDP_control_port-VDP_data_port(a6) moveq #0,d0 .loop: move.l d0,(a6) dbf d3,.loop rts ; End of function ClearVRAMArea ; =============== S U B R O U T I N E ======================================= SKTitle_ScreenShake: tst.w (Screen_shake_flag).w beq.s locret_5D92 ; If timer has run out, don't do anything subq.w #1,(Screen_shake_flag).w bne.s loc_5D72 addq.w #1,(Events_routine_fg).w ; Increment title routine counter when this is done loc_5D72: move.w (V_int_run_count+2).w,d0 andi.w #$3F,d0 ; Get frame counter then AND it for offset lea (SKTitle_ShakeOffsets).l,a1 lea (a1,d0.w),a1 moveq #0,d0 move.b (a1)+,d0 move.w d0,(Camera_Y_pos_P2_copy).w move.b (a1)+,d0 move.w d0,(Camera_X_pos_P2_copy).w locret_5D92: rts ; End of function SKTitle_ScreenShake ; =============== S U B R O U T I N E ======================================= SKTitle_DeformBG: move.w (Camera_Y_pos).w,(V_scroll_value).w move.w (Camera_Y_pos_P2).w,(V_scroll_value_BG).w ; Move BG position values to their proper spots moveq #0,d2 tst.w (Screen_shake_flag).w beq.s loc_5DB8 move.w (Camera_Y_pos_P2_copy).w,d0 add.w d0,(V_scroll_value).w add.w d0,(V_scroll_value_BG).w ; Shake the screen by the proper offsets if screen shaking is on move.w (Camera_X_pos_P2_copy).w,d2 ; Move shake X amount to d2 loc_5DB8: lea (H_scroll_buffer).w,a1 move.w (Events_routine_fg).w,d0 bne.s loc_5DE0 loc_5DC2: move.w #$E0-1,d1 ; If routine counter is zero move.w (Camera_X_pos).w,d0 add.w d2,d0 neg.w d0 swap d0 move.w (Camera_X_pos_P2).w,d0 add.w d2,d0 neg.w d0 loc_5DD8: move.l d0,(a1)+ ; Do normal deformation, nothing special dbf d1,loc_5DD8 rts ; --------------------------------------------------------------------------- loc_5DE0: subq.w #1,d0 bne.s loc_5E0E add.w (Camera_X_pos_P2).w,d2 ; If routine counter is 1 neg.w d2 move.w #$70-1,d3 loc_5DEE: jsr (Random_Number).l andi.w #7,d0 move.w d0,(a1)+ ; Shake the scanlines of the foreground (SEGA logo) by random amounts to simulate static move.w d2,(a1)+ swap d0 andi.w #7,d0 neg.w d0 move.w d0,(a1)+ move.w d2,(a1)+ dbf d3,loc_5DEE rts ; --------------------------------------------------------------------------- loc_5E0E: subq.w #1,d0 bne.s loc_5DC2 subq.w #1,(Events_bg+$00).w ; If routine counter is 2 bne.s loc_5E52 addq.w #1,(Events_routine_fg).w ; If above timer has expired move #$2700,sr move.l #vdpComm(VRAM_Plane_A_Name_Table+$500,VRAM,WRITE),d0 move.w #$100-1,d3 bsr.w ClearVRAMArea ; Clear the Sega logo mappings from foreground move #$2300,sr lea (Pal_SKTitle_Knux).l,a0 lea (Normal_palette_line_2).w,a2 moveq #bytesToLcnt($20),d0 loc_5E3E: move.l (a0)+,(a2)+ ; Load the knuckles palette into the final line dbf d0,loc_5E3E move.l #Obj_SKTitle_HandAnim,(Dynamic_object_RAM+object_size).w ; Start hand animations moveq #0,d2 bra.w loc_5DC2 ; Then do normal deformation ; --------------------------------------------------------------------------- loc_5E52: move.w (Camera_X_pos_P2).w,d2 neg.w d2 move.w #$70-1,d3 loc_5E5C: jsr (Random_Number).l addq.w #8,(a1) ; On every other line, alternate between moving the line randomly to the left and randomly to the right andi.w #7,d0 ; The result is a staticy phaseout effect of the SEGA logo add.w d0,(a1) cmpi.w #$FC,(a1) blt.s loc_5E74 move.w #$FC,(a1) loc_5E74: addq.w #2,a1 move.w d2,(a1)+ subq.w #8,(a1) swap d0 andi.w #7,d0 sub.w d0,(a1) cmpi.w #-$104,(a1) bgt.s loc_5E8C move.w #-$104,(a1) loc_5E8C: addq.w #2,a1 move.w d2,(a1)+ dbf d3,loc_5E5C rts ; End of function SKTitle_DeformBG ; --------------------------------------------------------------------------- SKTitle_ShakeOffsets: dc.b 1, 2, 1, 3, 1, 2, 2, 1, 2, 3, 1, 2, 1, 2, 0, 0 dc.b 2, 0, 3, 2, 2, 3, 2, 2, 1, 3, 0, 0, 1, 0, 1, 3 dc.b 1, 2, 1, 3, 1, 2, 2, 1, 2, 3, 1, 2, 1, 2, 0, 0 dc.b 2, 0, 3, 2, 2, 3, 2, 2, 1, 3, 0, 0, 1, 0, 1, 3, 1, 2 even Map_SKTitle_Icon: include "General/Title/Map - SK Icon.asm" Map_SKTitle_TM: include "General/Title/Map - SK TM.asm" Map_SKTitle_Copyright: include "General/Title/Map - SK Copyright.asm" ; --------------------------------------------------------------------------- LevelMusic_Playlist: dc.b mus_AIZ1, mus_AIZ2 ; ANGEL ISLAND ZONE dc.b mus_HCZ1, mus_HCZ2 ; HYDROCITY ZONE dc.b mus_MGZ1, mus_MGZ2 ; MARBLE GARDEN ZONE dc.b mus_CNZ1, mus_CNZ2 ; CARNIVAL NIGHT ZONE dc.b mus_FBZ1, mus_FBZ2 ; FLYING BATTERY ZONE dc.b mus_ICZ1, mus_ICZ2 ; ICECAP ZONE dc.b mus_LBZ1, mus_LBZ2 ; LAUNCH BASE ZONE dc.b mus_MHZ1, mus_MHZ2 ; MUSHROOM HILL ZONE dc.b mus_SOZ1, mus_SOZ2 ; SANDOPOLIS ZONE dc.b mus_LRZ1, mus_LRZ2 ; LAVA REEF ZONE dc.b mus_SSZ, mus_SSZ ; SKY SANCTUARY ZONE dc.b mus_DEZ1, mus_DEZ2 ; DEATH EGG ZONE dc.b mus_DDZ, mus_DDZ ; DOOMSDAY ZONE dc.b mus_SpecialStage, mus_SSZ ; AIZ INTRO & ENDING dc.b mus_ALZ, mus_ALZ ; AZURE LAKE ZONE dc.b mus_BPZ, mus_BPZ ; BALLOON PARK ZONE dc.b mus_DPZ, mus_DPZ ; DESERT PALACE ZONE dc.b mus_CGZ, mus_CGZ ; CHROME GADGET ZONE dc.b mus_EMZ, mus_EMZ ; ENDLESS MINE ZONE dc.b mus_Gumball, mus_Gumball ; GUMBALL dc.b mus_Pachinko, mus_Pachinko ; PACHINKO dc.b mus_Slots, mus_Slots ; SLOTS dc.b mus_EndBoss, mus_LRZ2 ; LAVA REEF ZONE BOSS & HIDDEN PALACE ZONE dc.b mus_DEZ2, mus_LRZ2 ; FINAL BOSS & SPECIAL STAGE HUB even ; --------------------------------------------------------------------------- Level: bset #7,(Game_mode).w ; Set bit 7 of F600 is indicate that we're loading the level tst.w (Demo_mode_flag).w bmi.s loc_5FC4 moveq #signextendB(mus_FadeOut),d0 ; If a demo bsr.w Play_SFX loc_5FC4: clr.w (Ending_running_flag).w clr.w (Kos_decomp_queue_count).w clearRAM Kos_decomp_stored_registers,$6C ; Clear the KosM bytes bsr.w Clear_Nem_Queue ; Clear PLCs cmpi.w #$D01,(Current_zone_and_act).w beq.s loc_5FFC tst.b (Respawn_table_keep).w beq.s loc_5FF6 cmpi.w #$1701,(Current_zone_and_act).w beq.s loc_5FFC loc_5FF6: bsr.w Pal_FadeToBlack ; If any normal level bra.s loc_6000 ; --------------------------------------------------------------------------- loc_5FFC: bsr.w Pal_FadeToWhite ; If level being loaded is the special stage arena or an ending loc_6000: tst.w (Demo_mode_flag).w bmi.w loc_60DE ; Skip ahead if negative (?) move #$2700,sr bsr.w Clear_DisplayData ; Clear the screen move #$2300,sr moveq #0,d0 move.w d0,(Level_frame_counter).w tst.b (Last_star_post_hit).w beq.s loc_6040 ; If no lampost was set, branch tst.b (Special_bonus_entry_flag).w bne.s loc_6034 ; Otherwise, ensure that the proper level ID is set to account for levels that use multiple ones in an act move.w (Saved_zone_and_act).w,(Current_zone_and_act).w move.w (Saved_apparent_zone_and_act).w,(Apparent_zone_and_act).w bra.s loc_6040 ; --------------------------------------------------------------------------- loc_6034: move.w (Saved2_zone_and_act).w,(Current_zone_and_act).w move.w (Saved2_apparent_zone_and_act).w,(Apparent_zone_and_act).w loc_6040: move.w (Current_zone_and_act).w,d0 ; Useless code. Player_mode has not been set yet, and level $D00 has the same PLCs as level 0 bne.s loc_6058 cmpi.w #2,(Player_mode).w ; If level is Angel Island 1 bhs.s loc_6054 tst.b (Last_star_post_hit).w ; If character is Sonic beq.s loc_6058 ; And no lamppost is set loc_6054: move.w #$D00,d0 ; Set the level ID to skip the intro loc_6058: cmpi.w #$401,(Current_zone_and_act).w ; If level is Flying Battery 2... bne.s loc_6068 cmpi.b #6,(Last_star_post_hit).w ; ...and lamppost is 6 or above (the one before the rising floor at the end)... beq.s loc_6088 ; ...don't bother loading level PLCs loc_6068: ror.b #1,d0 lsr.w #4,d0 andi.w #$1F8,d0 move.w d0,d1 add.w d0,d0 add.w d0,d1 lea (LevelLoadBlock).l,a2 moveq #0,d0 move.b (a2,d1.w),d0 ; Get the first PLC number for the level beq.s loc_6088 bsr.w Load_PLC loc_6088: bsr.w LevelLoad_ActiveCharacter tst.b (Last_star_post_hit).w bne.w loc_60B4 cmpi.w #0,(Current_zone_and_act).w bne.s loc_60B4 cmpi.w #2,(Player_mode).w bhs.s loc_60B4 moveq #1,d0 ; If in AIZ intro jsr (Load_PLC_2).l moveq #$A,d0 bsr.w Load_PLC ; Load the AIZ Intro graphics bra.s loc_60DE ; --------------------------------------------------------------------------- loc_60B4: moveq #6,d0 tst.w (Competition_mode).w bne.s loc_60DA moveq #5,d0 cmpi.w #3,(Player_mode).w beq.s loc_60DA moveq #1,d0 cmpi.w #2,(Player_mode).w bne.s loc_60DA moveq #7,d0 tst.b (Graphics_flags).w bmi.s loc_60DA moveq #$52,d0 loc_60DA: bsr.w Load_PLC loc_60DE: clearRAM Sprite_table_input,$400 clearRAM Object_RAM,(Kos_decomp_buffer-Object_RAM) clearRAM Lag_frame_count,$58 clearRAM Tails_CPU_interact,$100 clearRAM Oscillating_table,(AIZ_vine_angle-Oscillating_table) clearRAM _unkFA80,$80 jsr (Init_SpriteTable).l lea (VDP_control_port).l,a6 move.w #$8B03,(a6) move.w #$8230,(a6) move.w #$8407,(a6) move.w #$857C,(a6) move.w #$9001,(a6) move.w #$8004,(a6) move.w #$9200,(a6) move.w #$8720,(a6) move.w #$8C81,(a6) tst.b (Debug_cheat_flag).w beq.s loc_6182 btst #button_A,(Ctrl_1).w beq.s loc_6182 move.b #1,(Debug_mode_flag).w loc_6182: move.w #$8AFF,(H_int_counter_command).w tst.w (Competition_mode).w beq.s loc_61BE move.w #$4EF9,(H_int_jump).w move.l #HInt,(H_int_addr).w move.w #$8014,(a6) move.w #$8220,(a6) move.w #$8405,(a6) move.w #$8A6B,(H_int_counter_command).w move.w #$9003,(a6) cmpi.b #$F,(Current_zone).w bne.s loc_61BE move.w #$9011,(a6) loc_61BE: move.w (H_int_counter_command).w,(a6) clr.w (DMA_queue).w move.l #DMA_queue,(DMA_queue_slot).w moveq #3,d0 cmpi.w #3,(Player_mode).w bne.s loc_61DA moveq #5,d0 loc_61DA: bsr.w LoadPalette_Immediate bsr.w CheckLevelForWater clearRAM Water_palette_line_2,$60 tst.b (Water_flag).w beq.s loc_61FC move.w #$8014,(a6) loc_61FC: tst.w (Demo_mode_flag).w bmi.w loc_6310 moveq #0,d0 move.w (Current_zone_and_act).w,d0 ror.b #1,d0 lsr.w #7,d0 lea (LevelMusic_Playlist).l,a1 move.b (a1,d0.w),d0 cmpi.w #1,(Current_zone_and_act).w bne.s loc_622A cmpi.b #3,(Last_star_post_hit).w bne.s loc_622A moveq #signextendB(mus_AIZ1),d0 loc_622A: cmpi.w #$700,(Current_zone_and_act).w bne.s loc_6248 cmpi.w #3,(Player_mode).w bne.s loc_6248 tst.w (SK_alone_flag).w beq.s loc_6248 tst.b (Last_star_post_hit).w bne.s loc_6248 moveq #signextendB(mus_Knuckles),d0 loc_6248: move.w d0,(Current_music).w bsr.w Play_Music tst.w (Current_zone_and_act).w bne.s loc_6268 cmpi.w #2,(Player_mode).w bhs.s loc_62B6 tst.b (Last_star_post_hit).w beq.w loc_62FE bra.s loc_62B6 ; --------------------------------------------------------------------------- loc_6268: cmpi.w #$700,(Current_zone_and_act).w bne.s loc_62B6 cmpi.w #3,(Player_mode).w bne.s loc_62B6 tst.w (SK_alone_flag).w beq.s loc_62B6 tst.b (Last_star_post_hit).w bne.s loc_62B6 move #$2700,sr move.l #vdpComm(tiles_to_bytes($580),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_Squirrel).l,a0 jsr (Nem_Decomp).l move.l #vdpComm(tiles_to_bytes($592),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_Chicken).l,a0 jsr (Nem_Decomp).l bra.s loc_62FE ; --------------------------------------------------------------------------- loc_62B6: cmpi.w #$1701,(Current_zone_and_act).w beq.s loc_62FE tst.b (Act3_flag).w bne.s loc_62FE move.l #Obj_TitleCard,(Dynamic_object_RAM+(object_size*5)).w loc_62CC: move.b #$C,(V_int_routine).w jsr (Process_Kos_Queue).l bsr.w Wait_VSync jsr (Process_Sprites).l jsr (Render_Sprites).l bsr.w Process_Nem_Queue_Init jsr (Process_Kos_Module_Queue).l tst.w (Dynamic_object_RAM+(object_size*5)+objoff_48).w bne.s loc_62CC tst.l (Nem_decomp_queue).w bne.s loc_62CC loc_62FE: clr.b (Act3_flag).w move #$2700,sr jsr (HUD_DrawInitial).l move #$2300,sr loc_6310: moveq #3,d0 bsr.w LoadPalette jsr (Get_LevelSizeStart).l jsr (DeformBgLayer).l bsr.w LoadLevelLoadBlock jsr (LoadLevelLoadBlock2).l move #$2700,sr jsr (j_LevelSetup).l move #$2300,sr jsr (Animate_Init).l bsr.w LoadSolids bsr.w Handle_Onscreen_Water_Height move.w (Ctrl_2).w,(_unkFF7C).w 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,(Ctrl_1_locked).w move.b #1,(Ctrl_2_locked).w move.b #0,(Level_started_flag).w tst.b (Water_flag).w beq.s loc_63A4 cmpi.b #1,(Current_zone).w beq.s loc_638E cmpi.b #1,(Current_zone).w bne.s loc_63A4 loc_638E: move.l #Obj_HCZWaveSplash,(Wave_Splash).w move.l #Obj_HCZWaterSplash,(Dynamic_object_RAM+(object_size*2)).w move.b #1,(Dynamic_object_RAM+(object_size*2)+subtype).w loc_63A4: cmpi.b #7,(Current_zone).w bne.s loc_63B4 move.l #Obj_MHZ_Pollen_Spawner,(Dynamic_object_RAM+object_size).w loc_63B4: moveq #0,d0 tst.b (Last_star_post_hit).w bne.s loc_6404 move.w d0,(Ring_count).w move.l d0,(Timer).w move.b d0,(Extra_life_flags).w move.w d0,(Ring_count_P2).w move.l d0,(Timer_P2).w move.b d0,(Saved_status_secondary).w cmpi.w #$1600,(Current_zone_and_act).w beq.s loc_6400 cmpi.w #$1700,(Current_zone_and_act).w beq.s loc_6400 cmpi.w #$1701,(Current_zone_and_act).w beq.s loc_6404 cmpi.b #$16,(Current_zone).w bhs.s loc_63FC cmpi.b #$13,(Current_zone).w bhs.s loc_6404 loc_63FC: move.b d0,(Saved2_status_secondary).w loc_6400: move.b d0,(Respawn_table_keep).w loc_6404: move.b d0,(Time_over_flag).w move.w d0,(Debug_placement_mode).w move.w d0,(Restart_level_flag).w move.b d0,(Teleport_active_timer).w move.b d0,(Teleport_active_flag).w move.w d0,(Total_ring_count).w move.w d0,(Total_ring_count_P2).w move.w d0,(Monitors_broken).w move.w d0,(Monitors_broken_P2).w move.w d0,(Loser_time_left).w move.b d0,(LRZ_rocks_routine).w move.b d0,(Super_Sonic_Knux_flag).w bsr.w OscillateNumInit move.b #1,(Update_HUD_score).w move.b #1,(Update_HUD_ring_count).w move.b #1,(Update_HUD_timer).w move.b #1,(Level_started_flag).w cmpi.w #$D01,(Current_zone_and_act).w beq.s loc_6460 cmpi.w #$1701,(Current_zone_and_act).w bne.s loc_6468 loc_6460: clr.b (Update_HUD_timer).w clr.b (Level_started_flag).w loc_6468: bsr.w SpawnLevelMainSprites jsr (Load_Sprites).l jsr (Load_Rings).l jsr (Draw_LRZ_Special_Rock_Sprites).l jsr (Process_Sprites).l jsr (Render_Sprites).l jsr (Animate_Tiles).l move.w #1800,(Demo_timer).w bsr.w LoadWaterPalette clearRAM Water_palette_line_2,$60 move.b #0,(Ctrl_1_locked).w move.b #0,(Ctrl_2_locked).w jsr GetDemoPtr(pc) tst.w (Competition_mode).w bne.w loc_663A tst.w (Current_zone_and_act).w bne.s loc_64CE tst.b (Last_star_post_hit).w beq.s loc_64DC loc_64CE: cmpi.b #$E,(Current_zone).w bhs.s loc_64DC jsr (PLCLoad_AnimalsAndExplosion).l loc_64DC: move.w #$2030-1,(Palette_fade_info).w jsr (Pal_FillBlack).l move.w #$16,(Palette_fade_timer).w move.w #$16,(Dynamic_object_RAM+(object_size*5)+objoff_2E).w move.w #$7F<<8,(Ctrl_1).w move.w #$7F<<8,(Ctrl_2).w andi.b #$7F,(Last_star_post_hit).w bclr #7,(Game_mode).w LevelLoop: bsr.w Pause_Game move.b #8,(V_int_routine).w jsr (Process_Kos_Queue).l bsr.w Wait_VSync addq.w #1,(Level_frame_counter).w bsr.w Demo_PlayRecord jsr (Animate_Palette).l jsr (SpecialEvents).l jsr (Load_Sprites).l jsr (Process_Sprites).l tst.w (Restart_level_flag).w bne.w Level jsr (DeformBgLayer).l jsr (ScreenEvents).l bsr.w Handle_Onscreen_Water_Height jsr (Load_Rings).l cmpi.b #9,(Current_zone).w bne.s Level_NotLRZ jsr (Draw_LRZ_Special_Rock_Sprites).l Level_NotLRZ: jsr (Animate_Tiles).l bsr.w Process_Nem_Queue_Init jsr (Process_Kos_Module_Queue).l bsr.w OscillateNumDo bsr.w ChangeRingFrame jsr (Render_Sprites).l cmpi.b #$15,(Current_zone).w bne.s Level_NotSlots jsr (Slots_RenderLayout).l jsr (Slots_CycleOptions).l Level_NotSlots: cmpi.b #8,(Game_mode).w beq.s DemoMode cmpi.b #$C,(Game_mode).w beq.w LevelLoop rts ; --------------------------------------------------------------------------- DemoMode: tst.w (Restart_level_flag).w bne.s loc_65D0 tst.w (Demo_timer).w beq.s loc_65D0 cmpi.b #8,(Game_mode).w beq.w LevelLoop move.b #0,(Game_mode).w rts ; --------------------------------------------------------------------------- loc_65D0: cmpi.b #8,(Game_mode).w bne.s loc_65E0 move.b #0,(Game_mode).w rts ; --------------------------------------------------------------------------- loc_65E0: move.w #60,(Demo_timer).w move.w #$40-1,(Palette_fade_info).w clr.w (Pal_fade_delay).w loc_65F0: move.b #8,(V_int_routine).w bsr.w Wait_VSync bsr.w Demo_PlayRecord jsr (Process_Sprites).l jsr (DeformBgLayer).l jsr (ScreenEvents).l jsr (Render_Sprites).l jsr (Load_Sprites).l jsr (Process_Kos_Module_Queue).l subq.w #1,(Pal_fade_delay).w bpl.s loc_6632 move.w #2,(Pal_fade_delay).w bsr.w Pal_ToBlack loc_6632: tst.w (Demo_timer).w bne.s loc_65F0 rts ; --------------------------------------------------------------------------- loc_663A: move.w #0,(_unkFF7E).w tst.b (Debug_cheat_flag).w beq.s loc_665A move.b (_unkFF7C).w,d0 cmpi.b #$A0,d0 bne.s loc_665A move.w (Sound_test_sound).w,d0 lsl.w #8,d0 move.w d0,(_unkFF7E).w loc_665A: move.w #$40-1,(Palette_fade_info).w jsr (Pal_FillBlack).l move.w #$16,(Palette_fade_timer).w move.w #0,(_unkFF7C).w bclr #7,(Game_mode).w loc_6678: bsr.w Pause_Game move.b #8,(V_int_routine).w jsr (Process_Kos_Queue).l bsr.w Wait_VSync addq.w #1,(Level_frame_counter).w move.w #4,-(sp) bra.s loc_66DA ; --------------------------------------------------------------------------- loc_6696: move.w (_unkFF7E).w,d0 add.w d0,(_unkFF7C).w bcc.s loc_66EA bsr.w Pause_Game move.w #$100,(Z80_bus_request).l ; stop the Z80 bsr.w Poll_Controllers startZ80 move.w #0,(DMA_queue).w move.l #DMA_queue,(DMA_queue_slot).w lea (Sprite_table_input).w,a5 loc_66CA: move.w #0,(a5) lea $80(a5),a5 cmpa.l #Player_1,a5 blo.s loc_66CA loc_66DA: bsr.w Demo_PlayRecord jsr (Process_Sprites).l jsr (DeformBgLayer).l loc_66EA: subq.w #1,(sp) bne.s loc_6696 addq.w #2,sp tst.w (Restart_level_flag).w bne.w Level jsr (ScreenEvents).l jsr (Animate_Tiles).l jsr (Render_Sprites).l jsr (Animate_Palette).l bsr.w Process_Nem_Queue_Init jsr (Process_Kos_Module_Queue).l cmpi.b #8,(Game_mode).w beq.s loc_672E cmpi.b #$C,(Game_mode).w beq.w loc_6678 rts ; --------------------------------------------------------------------------- loc_672E: tst.w (Restart_level_flag).w bne.s loc_674C tst.w (Demo_timer).w beq.s loc_674C cmpi.b #8,(Game_mode).w beq.w loc_6678 move.b #0,(Game_mode).w rts ; --------------------------------------------------------------------------- loc_674C: cmpi.b #8,(Game_mode).w bne.s loc_675C move.b #0,(Game_mode).w rts ; --------------------------------------------------------------------------- loc_675C: move.w #60,(Demo_timer).w move.w #$40-1,(Palette_fade_info).w clr.w (Pal_fade_delay).w loc_676C: move.b #8,(V_int_routine).w bsr.w Wait_VSync bsr.w Demo_PlayRecord jsr (Process_Sprites).l jsr (DeformBgLayer).l jsr (ScreenEvents).l jsr (Render_Sprites).l jsr (Load_Sprites).l jsr (Process_Kos_Module_Queue).l subq.w #1,(Pal_fade_delay).w bpl.s loc_67AE move.w #2,(Pal_fade_delay).w bsr.w Pal_ToBlack loc_67AE: tst.w (Demo_timer).w bne.s loc_676C rts ; =============== S U B R O U T I N E ======================================= LevelLoad_ActiveCharacter: cmpi.b #$88,(Game_mode).w beq.s loc_67CC tst.w (Competition_mode).w bne.s loc_67CC move.w (Player_option).w,(Player_mode).w ; Move selected character to active character rts ; --------------------------------------------------------------------------- loc_67CC: move.w #3,(Player_mode).w ; If loading a demo OR 2P mode enabled (?) cmpi.b #7,(Current_zone).w beq.s locret_67EC move.w #0,(Player_mode).w tst.w (SK_alone_flag).w beq.s locret_67EC move.w #1,(Player_mode).w locret_67EC: rts ; End of function LevelLoad_ActiveCharacter ; =============== S U B R O U T I N E ======================================= SpawnLevelMainSprites: move.l #Obj_ResetCollisionResponseList,(Reserved_object_3).w bsr.w SpawnLevelMainSprites_SpawnPlayers bsr.w SpawnLevelMainSprites_SpawnPowerup tst.b (Last_star_post_hit).w bne.w locret_69B6 tst.b (Special_bonus_entry_flag).w bne.w locret_69B6 lea (Player_1).w,a1 lea (Player_2).w,a2 cmpi.w #0,(Current_zone_and_act).w bne.s loc_6834 cmpi.w #2,(Player_mode).w bhs.s locret_6832 move.l #Obj_AIZPlaneIntro,(Dynamic_object_RAM+(object_size*2)).w clr.b (Level_started_flag).w locret_6832: rts ; --------------------------------------------------------------------------- loc_6834: cmpi.w #$100,(Current_zone_and_act).w bne.s loc_6886 move.b #$1B,anim(a1) cmpi.w #3,(Player_mode).w bne.s loc_685C move.w #($21<<8)|$21,anim(a1) ; and prev_anim move.b #1,anim_frame(a1) ; Bug: this tries to clear Knuckles' anim_frame_timer, but Knuckles is in a1 move.b #0,anim_frame_timer(a0) loc_685C: bset #Status_InAir,status(a1) cmpi.w #2,(Player_mode).w bne.s loc_6870 move.b #1,jumping(a1) loc_6870: tst.l (a2) beq.s loc_6886 move.b #$1B,anim(a2) bset #Status_InAir,status(a2) move.b #1,jumping(a2) loc_6886: cmpi.w #$900,(Current_zone_and_act).w bne.s loc_6896 cmpi.w #3,(Player_mode).w bne.s loc_68A6 loc_6896: cmpi.w #$1600,(Current_zone_and_act).w beq.s loc_68A6 cmpi.w #$200,(Current_zone_and_act).w bne.s loc_68C2 loc_68A6: move.b #$1B,anim(a1) bset #Status_InAir,status(a1) tst.l (a2) beq.s loc_68C2 move.b #$1B,anim(a2) bset #Status_InAir,status(a2) loc_68C2: cmpi.w #$700,(Current_zone_and_act).w bne.s loc_68D0 tst.w (SK_alone_flag).w beq.s loc_68D8 loc_68D0: cmpi.w #$300,(Current_zone_and_act).w bne.s loc_690A loc_68D8: cmpi.w #1,(Player_mode).w bne.s loc_68FC move.l #Obj_Tails,(Player_2).w move.w (Player_1+x_pos).w,(Player_2+x_pos).w move.w (Player_1+y_pos).w,(Player_2+y_pos).w move.w #0,(Tails_CPU_routine).w bra.s loc_690A ; --------------------------------------------------------------------------- loc_68FC: cmpi.w #2,(Player_mode).w bne.s loc_690A move.w #$20,(Tails_CPU_routine).w loc_690A: cmpi.w #$500,(Current_zone_and_act).w bne.s loc_692E cmpi.w #2,(Player_mode).w blo.s loc_6926 bne.s loc_692E move.l #Obj_LevelIntroICZ1Tails,(Dynamic_object_RAM+(object_size*2)).w bra.s loc_692E ; --------------------------------------------------------------------------- loc_6926: move.l #Obj_LevelIntroICZ1,(Dynamic_object_RAM+(object_size*2)).w loc_692E: cmpi.w #$600,(Current_zone_and_act).w bne.s loc_693E move.l #Obj_LevelIntro_PlayerLaunchFromGround,(Dynamic_object_RAM+(object_size*2)).w loc_693E: cmpi.w #$700,(Current_zone_and_act).w bne.s loc_695A cmpi.w #3,(Player_mode).w bne.s loc_695A move.b #$1B,anim(a1) bset #Status_InAir,status(a1) loc_695A: cmpi.w #$800,(Current_zone_and_act).w bne.s loc_6986 move.l #Obj_LevelIntro_PlayerFallIntoGround,(Dynamic_object_RAM+(object_size*2)).w move.b #2,anim(a1) bset #Status_InAir,status(a1) tst.l (a2) beq.s loc_6986 move.b #2,anim(a2) bset #Status_InAir,status(a2) loc_6986: cmpi.w #$300,(Current_zone_and_act).w beq.s loc_69A6 cmpi.w #$B00,(Current_zone_and_act).w beq.s loc_69AE cmpi.w #$1601,(Current_zone_and_act).w beq.s loc_69AE cmpi.w #$900,(Current_zone_and_act).w bne.s locret_69B6 loc_69A6: cmpi.w #3,(Player_mode).w bne.s locret_69B6 loc_69AE: move.l #Obj_LevelIntro_PlayerRun,(Dynamic_object_RAM+(object_size*2)).w locret_69B6: rts ; End of function SpawnLevelMainSprites ; =============== S U B R O U T I N E ======================================= SpawnLevelMainSprites_SpawnPowerup: cmpi.w #$D01,(Current_zone_and_act).w beq.s locret_6A00 cmpi.b #$13,(Current_zone).w beq.s loc_69E0 cmpi.b #$14,(Current_zone).w beq.s loc_69E0 cmpi.b #$16,(Current_zone).w bhs.s loc_69E0 cmpi.b #$E,(Current_zone).w bhs.s locret_6A00 loc_69E0: lea (Player_1).w,a1 move.b (Saved_status_secondary).w,d0 clr.b (Saved_status_secondary).w andi.b #(1<= 0? moveq #$20,d0 ; set to $20 loc_7E94: btst #button_down,d1 beq.s loc_7EA4 addq.w #1,d0 ; yes, add 1 cmpi.w #$21,d0 blo.s loc_7EA4 ; smaller than $21? moveq #0,d0 ; if not, set to 0 loc_7EA4: move.w d0,(Level_select_option).w rts ; --------------------------------------------------------------------------- LevSelControls_CheckLR: cmpi.w #$20,(Level_select_option).w ; are we in the sound test? bne.s LevSelControls_SwitchSide ; no move.w (Sound_test_sound).w,d0 move.b (Ctrl_1_pressed).w,d1 btst #button_left,d1 beq.s loc_7EC6 subq.b #1,d0 bcc.s loc_7EC6 moveq #0,d0 loc_7EC6: btst #button_right,d1 beq.s loc_7ED6 addq.b #1,d0 cmpi.w #$100,d0 blo.s loc_7ED6 moveq #0,d0 loc_7ED6: btst #button_A,d1 beq.s loc_7EE4 addi.b #$10,d0 andi.b #$FF,d0 loc_7EE4: move.w d0,(Sound_test_sound).w btst #button_C,d1 beq.s loc_7EF8 move.w (Sound_test_sound).w,d0 jsr (Play_Music).l loc_7EF8: btst #button_B,d1 beq.s locret_7F06 moveq #signextendB(mus_MutePSG),d0 jsr (Play_Music).l locret_7F06: rts ; --------------------------------------------------------------------------- LevSelControls_SwitchSide: move.b (Ctrl_1_pressed).w,d1 andi.b #button_left_mask|button_right_mask,d1 beq.s loc_7F1E move.w (Level_select_option).w,d0 move.b LevelSelect_SwitchTable(pc,d0.w),d0 move.w d0,(Level_select_option).w loc_7F1E: bra.s LevelSelect_PickCharacterNumber ; --------------------------------------------------------------------------- rts ; --------------------------------------------------------------------------- LevelSelect_SwitchTable: dc.b $12 ; 0 dc.b $13 ; 1 dc.b $14 ; 2 dc.b $15 ; 3 dc.b $16 ; 4 dc.b $17 ; 5 dc.b $18 ; 6 dc.b $19 ; 7 dc.b $1A ; 8 dc.b $1B ; 9 dc.b $1C ; 10 dc.b $1D ; 11 dc.b $1E ; 12 dc.b $1F ; 13 dc.b $20 ; 14 dc.b $20 ; 15 dc.b $20 ; 16 dc.b $20 ; 17 dc.b 0 ; 18 dc.b 1 ; 19 dc.b 2 ; 20 dc.b 3 ; 21 dc.b 4 ; 22 dc.b 5 ; 23 dc.b 6 ; 24 dc.b 7 ; 25 dc.b 8 ; 26 dc.b 9 ; 27 dc.b $A ; 28 dc.b $B ; 29 dc.b $C ; 30 dc.b $D ; 31 dc.b $E ; 32 dc.b $F ; 33 dc.b $10 ; 34 dc.b $11 ; 35 ; --------------------------------------------------------------------------- LevelSelect_PickCharacterNumber: btst #button_C,(Ctrl_1_pressed).w beq.s locret_7F60 addq.w #1,(Player_option).w cmpi.w #4,(Player_option).w blo.s locret_7F60 move.w #0,(Player_option).w locret_7F60: rts ; End of function LevSelControls ; =============== S U B R O U T I N E ======================================= LevelSelect_MarkFields: lea (RAM_start).l,a4 lea (LevSel_MarkTable).l,a5 lea (VDP_data_port).l,a6 moveq #0,d0 move.w (Level_select_option).w,d0 lsl.w #2,d0 lea (a5,d0.w),a3 moveq #0,d0 move.b (a3),d0 mulu.w #$28*2,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,VDP_control_port-VDP_data_port(a6) moveq #$F-1,d2 loc_7FB2: move.w (a1)+,d0 add.w d3,d0 move.w d0,(a6) dbf d2,loc_7FB2 addq.w #2,a3 moveq #0,d0 move.b (a3),d0 beq.s loc_7FF6 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,VDP_control_port-VDP_data_port(a6) move.w (a1)+,d0 add.w d3,d0 move.w d0,(a6) loc_7FF6: cmpi.w #$20,(Level_select_option).w bne.s LevelSelect_DrawCharacterNumber bra.w LevelSelect_DrawSoundNumber ; --------------------------------------------------------------------------- LevelSelect_DrawCharacterNumber: move.l #vdpComm(VRAM_Plane_A_Name_Table+$19C,VRAM,WRITE),(VDP_control_port).l move.w (Player_option).w,d0 bra.s LevelSelect_DrawContinued ; End of function LevelSelect_MarkFields ; =============== S U B R O U T I N E ======================================= LevelSelect_DrawSoundNumber: move.l #vdpComm(VRAM_Plane_A_Name_Table+$B46,VRAM,WRITE),(VDP_control_port).l move.w (Sound_test_sound).w,d0 LevelSelect_DrawContinued: move.b d0,d2 lsr.b #4,d0 bsr.s sub_8028 move.b d2,d0 sub_8028: andi.w #$F,d0 cmpi.b #$A,d0 blo.s loc_8036 addi.b #4,d0 loc_8036: addi.b #$10,d0 add.w d3,d0 move.w d0,(a6) rts ; End of function LevelSelect_DrawSoundNumber ; LevelSelect_DrawIcon and LevSel_IconTable used to be here ; --------------------------------------------------------------------------- LevSel_MarkTable: ; 4 bytes per level select entry ; line primary, 2*column ($E fields), line secondary, 2*column secondary (1 field) dc.b 1, 6, 1, $24 dc.b 1, 6, 2, $24 dc.b 4, 6, 4, $24 dc.b 4, 6, 5, $24 dc.b 7, 6, 7, $24 dc.b 7, 6, 8, $24 dc.b $A, 6, $A, $24 dc.b $A, 6, $B, $24 dc.b $D, 6, $D, $24 dc.b $D, 6, $E, $24 dc.b $10, 6, $10, $24 dc.b $10, 6, $11, $24 dc.b $13, 6, $13, $24 dc.b $13, 6, $14, $24 dc.b $16, 6, $16, $24 dc.b $16, 6, $17, $24 dc.b $19, 6, $19, $24 dc.b $19, 6, $1A, $24 ; --- second column --- dc.b 1, $2C, 1, $4A dc.b 1, $2C, 2, $4A dc.b 4, $2C, 4, $4A dc.b 4, $2C, 5, $4A dc.b 7, $2C, 7, $4A dc.b 7, $2C, 8, $4A dc.b $A, $2C, $A, $4A dc.b $A, $2C, $B, $4A dc.b $D, $2C, $D, $4A dc.b $D, $2C, $E, $4A dc.b $10, $2C, $10, $4A dc.b $10, $2C, $11, $4A dc.b $13, $2C, $13, $4A dc.b $13, $2C, $14, $4A dc.b $16, $2C, $16, $4A LevSel_MappingOffsets: dc.w planeLocH28(3,1) dc.w planeLocH28(3,4) dc.w planeLocH28(3,7) dc.w planeLocH28(3,$A) dc.w planeLocH28(3,$D) dc.w planeLocH28(3,$10) dc.w planeLocH28(3,$13) dc.w planeLocH28(3,$16) dc.w planeLocH28(3,$19) dc.w planeLocH28($16,1) dc.w planeLocH28($16,4) dc.w planeLocH28($16,7) dc.w planeLocH28($16,$A) dc.w planeLocH28($16,$D) dc.w planeLocH28($16,$10) dc.w planeLocH28($16,$13) dc.w planeLocH28($16,$16) LevelSelectText: levselstr "ANGEL ISLAND" levselstr "HYDROCITY" levselstr "MARBLE GARDEN" levselstr "CARNIVAL NIGHT" levselstr "ICECAP" levselstr "LAUNCH BASE" levselstr "MUSHROOM HILL" levselstr "FLYING BATTERY" levselstr "SANDOPOLIS" levselstr "LAVA REEF" levselstr "LAVA REEF" levselstr "SKY SANCTUARY" levselstr "DEATHEGG" levselstr "THE DOOMSDAY" levselstr "BONUS" levselstr "SPECIAL STAGE" levselstr "SOUND TEST *" even AniPLC_SONICMILES: zoneanimstart ; Sonic/Miles animated background zoneanimdecl -1, ArtUnc_SONICMILES, $001, 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 ; --------------------------------------------------------------------------- SpecialStage: moveq #signextendB(mus_Stop),d0 bsr.w Play_Music clr.w (Kos_decomp_queue_count).w clearRAM Kos_decomp_stored_registers,$6C bsr.w Clear_Nem_Queue bsr.w Pal_FadeToWhite move #$2700,sr lea (VDP_control_port).l,a6 move.w #$8004,(a6) move.w #$8230,(a6) move.w #$8407,(a6) move.w #$9001,(a6) move.w #$9200,(a6) move.w #$8B00,(a6) move.w #$8720,(a6) clr.b (Water_full_screen_flag).w move.w #$8C81,(a6) bsr.w Clear_DisplayData clearRAM Sprite_table_input,$400 clearRAM Object_RAM,(Kos_decomp_buffer-Object_RAM) clearRAM Oscillating_table,(AIZ_vine_angle-Oscillating_table) clearRAM Stat_table,$100 moveq #0,d0 move.l d0,(LRZ_rocks_addr_front).w move.l d0,(LRZ_rocks_addr_back).w jsr (Init_SpriteTable).l clr.w (DMA_queue).w move.l #DMA_queue,(DMA_queue_slot).w lea (Pal_SStage_Main).l,a1 lea (Target_palette).w,a2 move.w #bytesToWcnt($80),d0 loc_8284: move.w (a1)+,(a2)+ dbf d0,loc_8284 cmpi.w #3,(Player_mode).w bne.s loc_82A6 lea (Pal_SStage_Knux).l,a1 lea (Target_palette+$10).w,a2 move.w #bytesToWcnt($10),d0 loc_82A0: move.w (a1)+,(a2)+ dbf d0,loc_82A0 loc_82A6: move.l #vdpComm(tiles_to_bytes($000),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_SStageLayout).l,a0 bsr.w Nem_Decomp bsr.w sub_85B0 lea (RAM_start+$5500).l,a1 lea (MapEni_SStageLayout).l,a0 move.w #make_art_tile($000,0,0),d0 bsr.w Eni_Decomp lea (RAM_start+$5500).l,a1 move.l #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE),d0 moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l move.l #vdpComm(tiles_to_bytes($680),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_SStageSphere).l,a0 bsr.w Nem_Decomp move.l #vdpComm(tiles_to_bytes($5A7),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_SStageRing).l,a0 bsr.w Nem_Decomp move.l #vdpComm(tiles_to_bytes($59B),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_SStageBG).l,a0 bsr.w Nem_Decomp move.l #vdpComm(tiles_to_bytes($55F),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_GetBlueSpheres).l,a0 bsr.w Nem_Decomp move.l #vdpComm(tiles_to_bytes($6F8),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_GBSArrow).l,a0 bsr.w Nem_Decomp move.l #vdpComm(tiles_to_bytes($781),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_SStageDigits).l,a0 bsr.w Nem_Decomp lea (ArtNem_SStageDigits).l,a0 lea (H_scroll_buffer+$20).w,a4 bsr.w Nem_Decomp_To_RAM move.l #vdpComm(tiles_to_bytes($589),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_SStageIcons).l,a0 bsr.w Nem_Decomp move.l #vdpComm(tiles_to_bytes($7A0),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_SStageShadow).l,a0 bsr.w Nem_Decomp lea (MapUnc_SSNum000).l,a1 move.l #vdpComm(VRAM_Plane_A_Name_Table+$084,VRAM,WRITE),d0 moveq #8-1,d1 moveq #3-1,d2 jsr (Plane_Map_To_VRAM).l lea (MapUnc_SSNum000).l,a1 move.l #vdpComm(VRAM_Plane_A_Name_Table+$0BC,VRAM,WRITE),d0 moveq #8-1,d1 moveq #3-1,d2 jsr (Plane_Map_To_VRAM).l lea (RAM_start).l,a1 lea (MapEni_SStageBG).l,a0 move.w #make_art_tile($59B,2,0),d0 bsr.w Eni_Decomp lea (RAM_start).l,a1 move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0 moveq #$40-1,d1 moveq #$20-1,d2 jsr (Plane_Map_To_VRAM).l lea (SStageKos_PerspectiveMaps).l,a0 lea (RAM_start).l,a1 bsr.w Kos_Decomp bsr.w sub_9EA0 bsr.w Load_SSSprite_Mappings clr.b (Level_started_flag).w move.b #$FF,(Special_stage_sphere_HUD_flag).w move.b #$80,(Special_stage_extra_life_flags).w move.w #$1000,(Special_stage_rate).w move.w #30*60,(Special_stage_rate_timer).w tst.b (Blue_spheres_stage_flag).w beq.s loc_842C move.w #45*60,(Special_stage_rate_timer).w loc_842C: move.w #0,(Camera_X_pos_copy).w move.w #0,(Camera_Y_pos_copy).w move.w #-1,(Screen_Y_wrap_value).w move.l #Obj_SStage_8FAA,(Player_1).w tst.w (Player_mode).w bne.s loc_8454 move.l #Obj_SStage_9212,(Player_2).w loc_8454: move.l #Obj_SStage_8DF8,(Reserved_object_3).w move.l #Obj_SStage_8E40,(Dynamic_object_RAM).w jsr (Process_Sprites).l bsr.w Animate_SSRings bsr.w Touch_SSSprites jsr (Render_Sprites).l jsr Draw_SSSprites(pc) bsr.w sub_9D5E move.b #1,(Special_stage_fade_timer).w move.b #$1C,(V_int_routine).w bsr.w Wait_VSync move.b #0,(Special_stage_fade_timer).w move.w #$8C89,(VDP_control_port).l move.w #30*60,(Demo_timer).w jsr (GetDemoPtr).l moveq #signextendB(mus_SpecialStage),d0 bsr.w Play_Music move.w (VDP_reg_1_command).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l bsr.w Pal_FadeFromWhite loc_84C2: bsr.w Pause_Game move.b #$1C,(V_int_routine).w jsr (Process_Kos_Queue).l bsr.w Wait_VSync addq.w #1,(Level_frame_counter).w jsr (Demo_PlayRecord).l jsr (Process_Sprites).l bsr.w Animate_SSRings bsr.w Touch_SSSprites jsr (Render_Sprites).l jsr Draw_SSSprites(pc) bsr.w Draw_SSShadows bsr.w sub_9D5E bsr.w sub_9B62 bsr.w Process_Nem_Queue_Init jsr (Process_Kos_Module_Queue).l tst.w (Demo_mode_flag).w beq.s loc_851A tst.w (Demo_timer).w beq.s loc_8522 loc_851A: cmpi.b #$34,(Game_mode).w beq.s loc_84C2 loc_8522: tst.w (Demo_mode_flag).w beq.s loc_852E move.b #0,(Game_mode).w loc_852E: move.w #60,(Demo_timer).w move.w #$40-1,(Palette_fade_info).w clr.w (Pal_fade_delay).w loc_853E: move.b #$1C,(V_int_routine).w bsr.w Wait_VSync jsr (Demo_PlayRecord).l jsr (Process_Sprites).l bsr.w Animate_SSRings bsr.w Touch_SSSprites jsr (Render_Sprites).l jsr Draw_SSSprites(pc) bsr.w sub_9D5E bsr.w sub_9B62 bsr.w Process_Nem_Queue_Init jsr (Process_Kos_Module_Queue).l subq.w #1,(Pal_fade_delay).w bpl.s loc_8588 move.w #2,(Pal_fade_delay).w bsr.w Pal_ToWhite loc_8588: tst.w (Demo_timer).w bne.s loc_853E rts ; --------------------------------------------------------------------------- SSLayoutOffs_RAM: dc.l RAM_start+$0000 dc.l RAM_start+$0408 dc.l RAM_start+$0810 dc.l RAM_start+$0C18 dc.l RAM_start+$1020 dc.l RAM_start+$1428 dc.l RAM_start+$1830 dc.l RAM_start+$1C38 ; =============== S U B R O U T I N E ======================================= sub_85B0: tst.b (Blue_spheres_stage_flag).w bne.w loc_86C8 lea (SSCompressedLayoutPtrs).l,a0 movea.l (a0),a0 lea (RAM_start).l,a1 bsr.w Kos_Decomp lea (SStageLayoutPtrs).l,a2 move.b (Chaos_emerald_count).w,d3 tst.w (SK_alone_flag).w beq.s loc_85E4 lea (SSLayoutOffs_RAM).l,a2 moveq #0,d2 bra.s loc_85F4 ; --------------------------------------------------------------------------- loc_85E4: move.b (SK_special_stage_flag).w,d2 beq.s loc_85F4 lea (SSLayoutOffs_RAM).l,a2 move.b (Super_emerald_count).w,d3 loc_85F4: tst.b (Debug_cheat_flag).w beq.s loc_8606 move.w (Sound_test_sound).w,d0 btst #button_A,(Ctrl_1).w bne.s loc_8630 loc_8606: moveq #0,d0 move.b (Current_special_stage).w,d0 cmpi.b #7,d3 bhs.s loc_8630 moveq #5,d1 lea (Collected_emeralds_array).w,a1 add.b d2,d2 loc_861A: cmp.b (a1,d0.w),d2 beq.s loc_8630 addq.w #1,d0 cmpi.w #7,d0 blo.s loc_861A moveq #0,d0 dbf d1,loc_861A moveq #7,d0 loc_8630: andi.w #7,d0 move.b d0,(Current_special_stage).w move.w d0,d1 lsl.w #2,d0 movea.l (a2,d0.w),a2 if Sonic3_Complete=0 tst.w (SK_alone_flag).w bne.s loc_8652 tst.b (SK_special_stage_flag).w bne.s loc_8652 adda.l #LockOnROM_Start,a2 loc_8652: endif lea (SStage_layout_buffer).w,a3 moveq #0,d2 move.w #bytesToLcnt($100),d0 loc_865C: move.l d2,(a3)+ dbf d0,loc_865C move.w #bytesToLcnt($400),d0 loc_8666: move.l (a2)+,(a3)+ dbf d0,loc_8666 move.w #bytesToLcnt($100),d0 loc_8670: move.l d2,(a3)+ dbf d0,loc_8670 move.w (a2)+,(Special_stage_angle).w move.w (a2)+,(Special_stage_X_pos).w move.w (a2)+,(Special_stage_Y_pos).w move.w (a2)+,(Special_stage_rings_left).w lsl.w #4,d1 lea (SS_Pal_Map_Ptrs).l,a1 lea (Target_palette).w,a2 movea.l 4(a1,d1.w),a1 tst.w (SK_alone_flag).w bne.s loc_86A2 tst.b (SK_special_stage_flag).w beq.s loc_86A6 loc_86A2: lea $130(a1),a1 loc_86A6: move.l a1,(Special_stage_palette_addr).w move.l (a1)+,$70(a2) move.l (a1)+,$74(a2) move.l (a1)+,$78(a2) move.l (a1)+,$7C(a2) move.l $10(a1),$50(a2) move.w $14(a1),$54(a2) rts ; --------------------------------------------------------------------------- loc_86C8: lea (SSCompressedLayoutPtrs).l,a0 movea.l 4(a0),a0 lea (RAM_start).l,a1 bsr.w Kos_Decomp lea (SStage_layout_buffer).w,a3 moveq #0,d2 move.w #bytesToLcnt($600),d0 loc_86E6: move.l d2,(a3)+ dbf d0,loc_86E6 move.b #0,(Current_special_stage).w move.w #$4000,(Special_stage_angle).w move.w #$1000,(Special_stage_X_pos).w move.w #$300,(Special_stage_Y_pos).w clr.w (Special_stage_rings_left).w clr.w (Blue_spheres_difficulty).w lea (Blue_spheres_current_stage).w,a4 lea word_87BA(pc),a1 moveq #4-1,d7 loc_8716: lea (RAM_start).l,a2 move.b (a4)+,d0 andi.w #$7F,d0 moveq #0,d1 move.b (a2,d0.w),d1 add.w d1,(Special_stage_rings_left).w lea $80(a2),a2 moveq #0,d1 move.b (a2,d0.w),d1 add.w d1,(Blue_spheres_difficulty).w lea $80(a2),a2 lsl.w #8,d0 lea (a2,d0.w),a2 move.w (a1)+,d3 move.w (a1)+,d4 move.w (a1)+,d5 move.w (a1)+,d0 lea (SStage_layout_buffer+$100).w,a3 lea (a3,d0.w),a3 moveq #$F,d0 loc_8756: move.w d4,d2 moveq #$10-1,d1 loc_875A: move.b (a2,d2.w),(a3)+ add.w d3,d2 dbf d1,loc_875A lea $10(a3),a3 add.w d5,d4 dbf d0,loc_8756 dbf d7,loc_8716 moveq #0,d1 move.b (Blue_spheres_current_stage+2).w,d1 move.w d1,d2 andi.w #7,d1 lsl.w #4,d1 lea (SS_Pal_Map_Ptrs).l,a1 lea (Target_palette).w,a2 movea.l 4(a1,d1.w),a1 andi.w #8,d2 beq.s loc_8798 lea $130(a1),a1 loc_8798: move.l a1,(Special_stage_palette_addr).w move.l (a1)+,$70(a2) move.l (a1)+,$74(a2) move.l (a1)+,$78(a2) move.l (a1)+,$7C(a2) move.l $10(a1),$50(a2) move.w $14(a1),$54(a2) rts ; End of function sub_85B0 ; --------------------------------------------------------------------------- word_87BA: dc.w 1 dc.w 0 dc.w $10 dc.w 0 dc.w $FFFF dc.w $F dc.w $10 dc.w $10 dc.w 1 dc.w $F0 dc.w $FFF0 dc.w $200 dc.w $FFFF dc.w $FF dc.w $FFF0 dc.w $210 ; =============== S U B R O U T I N E ======================================= Rotate_SSPal: tst.b (Special_stage_fade_timer).w bne.s locret_8818 move.w (Special_stage_anim_frame).w,d0 cmpi.w #$10,d0 blo.s loc_87F8 tst.b (Special_stage_turning).w bpl.s locret_8818 move.b (Special_stage_palette_frame).w,d0 andi.w #$F,d0 loc_87F8: andi.w #$E,d0 neg.w d0 addi.w #$10,d0 movea.l (Special_stage_palette_addr).w,a1 lea (a1,d0.w),a1 lea (Normal_palette_line_4+$10).w,a2 move.w #bytesToWcnt($10),d0 loc_8812: move.w (a1)+,(a2)+ dbf d0,loc_8812 locret_8818: rts ; End of function Rotate_SSPal ; =============== S U B R O U T I N E ======================================= Update_SSMap: lea (VDP_data_port).l,a6 lea (SS_Pal_Map_Ptrs).l,a1 move.w (Special_stage_anim_frame).w,d0 cmp.b (Special_stage_prev_anim_frame).w,d0 beq.s loc_8876 move.b d0,(Special_stage_prev_anim_frame).w lsl.w #3,d0 movea.l (a1,d0.w),a3 lea $10E(a3),a1 move.l #vdpComm(VRAM_Plane_A_Name_Table+$19E,VRAM,WRITE),(VDP_control_port).l ; VRAM write $C19E moveq #$A-1,d1 loc_884A: move.w (a1)+,(a6) dbf d1,loc_884A lea $140(a3),a3 move.l #vdpComm(VRAM_Plane_A_Name_Table+$200,VRAM,WRITE),d0 ; VRAM write $C200 moveq #$28-1,d1 moveq #$18-1,d2 move.l #$80<<16,d4 loc_8864: move.l d0,VDP_control_port-VDP_data_port(a6) move.w d1,d3 loc_886A: move.w (a3)+,(a6) dbf d3,loc_886A add.l d4,d0 dbf d2,loc_8864 loc_8876: tst.b (Special_stage_sphere_HUD_flag).w beq.s loc_8890 move.b #0,(Special_stage_sphere_HUD_flag).w move.l #vdpComm(VRAM_Plane_A_Name_Table+$086,VRAM,WRITE),d0 ; VRAM write $C086 move.w (Special_stage_spheres_left).w,d1 bsr.w Draw_SSNum loc_8890: tst.b (Special_stage_extra_life_flags).w bpl.s locret_88B4 bclr #7,(Special_stage_extra_life_flags).w move.l #vdpComm(VRAM_Plane_A_Name_Table+$0BE,VRAM,WRITE),d0 ; VRAM write $C0BE move.w (Special_stage_ring_count).w,d1 tst.b (Blue_spheres_stage_flag).w beq.s loc_88B0 move.w (Special_stage_rings_left).w,d1 loc_88B0: bsr.w Draw_SSNum locret_88B4: rts ; End of function Update_SSMap ; --------------------------------------------------------------------------- SS_Pal_Map_Ptrs: dc.l RAM_start+$5500 dc.l Pal_SStage_3_1 dc.l RAM_start+$5DC0 dc.l Pal_SStage_3_1 dc.l RAM_start+$5500 dc.l Pal_SStage_3_2 dc.l RAM_start+$5DC0 dc.l Pal_SStage_3_2 dc.l RAM_start+$5500 dc.l Pal_SStage_3_3 dc.l RAM_start+$5DC0 dc.l Pal_SStage_3_3 dc.l RAM_start+$5500 dc.l Pal_SStage_3_4 dc.l RAM_start+$5DC0 dc.l Pal_SStage_3_4 dc.l RAM_start+$5500 dc.l Pal_SStage_3_5 dc.l RAM_start+$5DC0 dc.l Pal_SStage_3_5 dc.l RAM_start+$5500 dc.l Pal_SStage_3_6 dc.l RAM_start+$5DC0 dc.l Pal_SStage_3_6 dc.l RAM_start+$5500 dc.l Pal_SStage_3_7 dc.l RAM_start+$5DC0 dc.l Pal_SStage_3_7 dc.l RAM_start+$5500 dc.l Pal_SStage_3_8 dc.l RAM_start+$5DC0 dc.l Pal_SStage_3_8 dc.l RAM_start+$9B00 dc.l Pal_SStage_3_1 dc.l RAM_start+$9240 dc.l Pal_SStage_3_1 dc.l RAM_start+$8980 dc.l Pal_SStage_3_1 dc.l RAM_start+$80C0 dc.l Pal_SStage_3_1 dc.l RAM_start+$7800 dc.l Pal_SStage_3_1 dc.l RAM_start+$6F40 dc.l Pal_SStage_3_1 dc.l RAM_start+$6680 dc.l Pal_SStage_3_1 Pal_SStage_Main: binclude "General/Special Stage/Palettes/Main.bin" even Pal_SStage_Knux: binclude "General/Special Stage/Palettes/Knux Patch.bin" even Pal_SStage_3_1: binclude "General/Special Stage/Palettes/3-1.bin" even Pal_SStage_3_2: binclude "General/Special Stage/Palettes/3-2.bin" even Pal_SStage_3_3: binclude "General/Special Stage/Palettes/3-3.bin" even Pal_SStage_3_4: binclude "General/Special Stage/Palettes/3-4.bin" even Pal_SStage_3_5: binclude "General/Special Stage/Palettes/3-5.bin" even Pal_SStage_3_6: binclude "General/Special Stage/Palettes/3-6.bin" even Pal_SStage_3_7: binclude "General/Special Stage/Palettes/3-7.bin" even Pal_SStage_3_8: binclude "General/Special Stage/Palettes/3-8.bin" even Pal_SStage_K_1: binclude "General/Special Stage/Palettes/K-1.bin" even Pal_SStage_K_2: binclude "General/Special Stage/Palettes/K-2.bin" even Pal_SStage_K_3: binclude "General/Special Stage/Palettes/K-3.bin" even Pal_SStage_K_4: binclude "General/Special Stage/Palettes/K-4.bin" even Pal_SStage_K_5: binclude "General/Special Stage/Palettes/K-5.bin" even Pal_SStage_K_6: binclude "General/Special Stage/Palettes/K-6.bin" even Pal_SStage_K_7: binclude "General/Special Stage/Palettes/K-7.bin" even Pal_SStage_K_8: binclude "General/Special Stage/Palettes/K-8.bin" even ; =============== S U B R O U T I N E ======================================= Draw_SSNum: lea (SSNum_Precision).l,a2 moveq #3-1,d6 lea MapUnc_SSNum(pc),a1 loc_8C6A: moveq #0,d2 move.w (a2)+,d3 loc_8C6E: sub.w d3,d1 bcs.s loc_8C76 addq.w #1,d2 bra.s loc_8C6E ; --------------------------------------------------------------------------- loc_8C76: add.w d3,d1 move.l d0,VDP_control_port-VDP_data_port(a6) add.w d2,d2 add.w d2,d2 lea (a1,d2.w),a3 move.l (a3),(a6) addi.l #$80<<16,d0 move.l d0,VDP_control_port-VDP_data_port(a6) move.l $28(a3),(a6) addi.l #$80<<16,d0 move.l d0,VDP_control_port-VDP_data_port(a6) move.l $50(a3),(a6) subi.l #$FC<<16,d0 dbf d6,loc_8C6A rts ; End of function Draw_SSNum ; --------------------------------------------------------------------------- SSNum_Precision: dc.w 100 dc.w 10 dc.w 1 MapUnc_SSNum: binclude "General/Special Stage/Uncompressed Map/HUD Numbers.bin" even MapUnc_SSNum000: binclude "General/Special Stage/Uncompressed Map/HUD.bin" even ; =============== S U B R O U T I N E ======================================= ; Create_New_Sprite2: AllocateObjectAfterCurrent_SpecialStage: movea.l a0,a1 move.w #Object_RAM_end-object_size,d0 sub.w a0,d0 lsr.w #6,d0 move.b .lookup(pc,d0.w),d0 bmi.s .return .loop: lea next_object(a1),a1 tst.l (a1) dbeq d0,.loop .return: rts .lookup: .a set Object_RAM-object_size*2 ; Oddly, this does too many object slots. .b set Object_RAM_end-object_size .c set .b ; begin from bottom of array and decrease backwards ; There's a mistake here: this division should be rounded up, ; otherwise the first object slot might not get an entry. ; In this case, the aforementioned surplus entries counteract this problem. rept (.b-.a)/$40 ; repeat for all slots, minus exception .c set .c-$40 ; address for previous $40 (also skip last part) dc.b (.b-.c-1)/object_size-1 ; write possible slots according to object_size division + hack + dbf hack endm even ; End of function AllocateObjectAfterCurrent_SpecialStage ; --------------------------------------------------------------------------- Obj_SStage_8DF8: move.b #$80,width_pixels(a0) move.b #$80,height_pixels(a0) move.w #0,priority(a0) move.l #Map_SSIcons,mappings(a0) move.w #make_art_tile($589,2,1),art_tile(a0) move.w #$120,x_pos(a0) move.w #$94,y_pos(a0) move.l #loc_8E2A,(a0) loc_8E2A: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Map_SSIcons: include "General/Special Stage/Map - Icons.asm" ; --------------------------------------------------------------------------- Obj_SStage_8E40: jsr (AllocateObjectAfterCurrent_SpecialStage).l bne.w loc_8E5C move.l #loc_8E5C,(a1) bset #0,status(a1) move.b #1,mapping_frame(a1) loc_8E5C: move.b #$80,width_pixels(a0) move.b #$80,height_pixels(a0) move.w #0,priority(a0) move.l #Map_GetBlueSpheres,mappings(a0) move.w #make_art_tile($55F,1,1),art_tile(a0) move.w #$120,x_pos(a0) move.w #$E8,y_pos(a0) move.w #3*60,$32(a0) move.l #loc_8E94,(a0) loc_8E94: tst.w $32(a0) beq.s loc_8EA4 subq.w #1,$32(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_8EA4: cmpi.w #$C0,$30(a0) blo.s loc_8ECA move.l #loc_8EEC,(a0) addq.b #2,mapping_frame(a0) tst.w (Special_stage_velocity).w bne.s loc_8ED0 move.b #1,(Special_stage_advancing).w move.b #1,(Special_stage_started).w bra.s loc_8ED0 ; --------------------------------------------------------------------------- loc_8ECA: addi.w #$10,$30(a0) loc_8ED0: move.w $30(a0),d0 btst #0,status(a0) bne.s loc_8EDE neg.w d0 loc_8EDE: addi.w #$120,d0 move.w d0,x_pos(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_8EEC: tst.w (Special_stage_rings_left).w beq.s loc_8EF4 rts ; --------------------------------------------------------------------------- loc_8EF4: subi.w #$10,$30(a0) bne.s loc_8F08 move.l #loc_8F24,(a0) move.w #180,$32(a0) loc_8F08: move.w $30(a0),d0 btst #0,status(a0) bne.s loc_8F16 neg.w d0 loc_8F16: addi.w #$120,d0 move.w d0,x_pos(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_8F24: tst.w $32(a0) beq.s loc_8F34 subq.w #1,$32(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_8F34: cmpi.w #$C0,$30(a0) bhs.s loc_8F42 addi.w #$10,$30(a0) loc_8F42: move.w $30(a0),d0 btst #0,status(a0) bne.s loc_8F50 neg.w d0 loc_8F50: addi.w #$120,d0 move.w d0,x_pos(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Map_GetBlueSpheres: include "General/Special Stage/Map - Get Blue Spheres.asm" ; --------------------------------------------------------------------------- Obj_SStage_8FAA: move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #$10,height_pixels(a0) move.w #$200,priority(a0) move.l #Map_SStageSonic,mappings(a0) move.w #make_art_tile($7D4,0,1),art_tile(a0) cmpi.w #2,(Player_mode).w bne.s loc_8FFA move.l #Map_SStageTails,mappings(a0) move.w #make_art_tile($7EB,1,1),art_tile(a0) jsr (AllocateObjectAfterCurrent_SpecialStage).l bne.w loc_8FFA move.l #Obj_SStage_9444,(a1) move.w a0,$3E(a1) loc_8FFA: cmpi.w #3,(Player_mode).w bne.s loc_9010 move.l #Map_SStageKnuckles,mappings(a0) move.w #make_art_tile($7D4,0,1),art_tile(a0) loc_9010: move.w #$A0,$30(a0) move.w #$70,$32(a0) move.w #0,$34(a0) move.w #$F800,$36(a0) move.w #0,$38(a0) bsr.w sub_950C move.b #$FF,$3A(a0) move.l #loc_903E,(a0) loc_903E: tst.w (Special_stage_rate_timer).w beq.s loc_907E subq.w #1,(Special_stage_rate_timer).w bne.s loc_907E move.w #30*60,(Special_stage_rate_timer).w tst.b (Blue_spheres_stage_flag).w beq.s loc_905C move.w #45*60,(Special_stage_rate_timer).w loc_905C: cmpi.w #$2000,(Special_stage_rate).w beq.s loc_907E addi.w #$400,(Special_stage_rate).w move.b (Special_stage_rate).w,d0 subi.b #$20,d0 neg.b d0 add.b d0,d0 addq.b #8,d0 jsr (Change_Music_Tempo).l loc_907E: bsr.w sub_9580 moveq #$C,d0 move.w (Special_stage_velocity).w,d1 beq.s loc_90A8 asr.w #5,d1 add.w d1,anim_frame_timer(a0) moveq #0,d0 move.b anim_frame_timer(a0),d0 bpl.s loc_909E addi.b #$C,d0 bra.s loc_90A8 ; --------------------------------------------------------------------------- loc_909E: cmpi.b #$C,d0 blo.s loc_90A8 subi.b #$C,d0 loc_90A8: move.b d0,anim_frame_timer(a0) lea (byte_91E8).l,a1 tst.b (Special_stage_jumping).w bpl.s loc_90CC lea (byte_91F6).l,a1 move.w (Special_stage_velocity).w,d1 bne.s loc_90CC move.b (Level_frame_counter+1).w,d0 andi.w #3,d0 loc_90CC: move.b (a1,d0.w),mapping_frame(a0) tst.b (Special_stage_clear_routine).w bne.s loc_90EE move.w (Ctrl_1).w,d0 andi.w #button_A_mask|button_B_mask|button_C_mask,d0 beq.s loc_90EE tst.b (Special_stage_jumping).w bmi.s loc_90EE move.b #1,(Special_stage_jumping).w loc_90EE: move.b (Special_stage_angle).w,d0 andi.b #$3F,d0 bne.w loc_9152 cmpi.b #1,(Special_stage_jumping).w bne.s loc_911E move.l #-$100000,$40(a0) move.b #$80,(Special_stage_jumping).w move.b #0,(Special_stage_turning).w moveq #signextendB(sfx_Jump),d0 jsr (Play_SFX).l loc_911E: tst.b (Special_stage_jumping).w bpl.s loc_9152 move.l $3C(a0),d0 add.l $40(a0),d0 bmi.s loc_9138 moveq #0,d0 move.l d0,$40(a0) move.b d0,(Special_stage_jumping).w loc_9138: move.w (Special_stage_rate).w,d1 ext.l d1 lsl.l #4,d1 add.l d1,$40(a0) move.l d0,$3C(a0) swap d0 addi.w #-$800,d0 move.w d0,$36(a0) loc_9152: bsr.w sub_950C bsr.w sub_953E jsr (Draw_Sprite).l lea (PLC_SStageSonic).l,a2 move.l #ArtUnc_SStageSonic,d6 move.w #tiles_to_bytes($7D4),d4 cmpi.w #2,(Player_mode).w bne.s loc_918A lea (PLC_SStageTails).l,a2 move.l #ArtUnc_SStageTails,d6 move.w #tiles_to_bytes($7EB),d4 bra.s SStage_PLCLoad_91A2 ; --------------------------------------------------------------------------- loc_918A: cmpi.w #3,(Player_mode).w bne.s SStage_PLCLoad_91A2 lea (PLC_SStageKnuckles).l,a2 move.l #ArtUnc_SStageKnuckles,d6 move.w #tiles_to_bytes($7D4),d4 SStage_PLCLoad_91A2: moveq #0,d0 move.b mapping_frame(a0),d0 cmp.b $3A(a0),d0 beq.s locret_91E6 move.b d0,$3A(a0) add.w d0,d0 adda.w (a2,d0.w),a2 move.w (a2)+,d5 subq.w #1,d5 bmi.s locret_91E6 loc_91BE: 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 add.l d6,d1 move.w d4,d2 add.w d3,d4 add.w d3,d4 jsr (Add_To_DMA_Queue).l dbf d5,loc_91BE locret_91E6: rts ; --------------------------------------------------------------------------- byte_91E8: dc.b 2, 6, 7, 8, 7, 6, 2, 3, 4, 5, 4, 3, 1, 0 byte_91F6: dc.b 9, $B, $A, $B, 9, $B, $A, $B, 9, $B, $A, $B, $B, 0 byte_9204: dc.b 9, $A, $B, 9, $A, $B, 9, $A, $B, 9, $A, $B, $B, 0 even ; --------------------------------------------------------------------------- Obj_SStage_9212: move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #$10,height_pixels(a0) move.w #$180,priority(a0) move.l #Map_SStageTails,mappings(a0) move.w #make_art_tile($7EB,1,1),art_tile(a0) move.w #$A0,$30(a0) move.w #$70,$32(a0) move.w #0,$34(a0) move.w #-$800,$36(a0) move.w #-$20,$38(a0) move.b #$FF,$3A(a0) bsr.w sub_93E2 jsr (AllocateObjectAfterCurrent_SpecialStage).l bne.w loc_9274 move.l #Obj_SStage_9444,(a1) move.w a0,$3E(a1) loc_9274: move.l #loc_927A,(a0) loc_927A: moveq #$C,d0 move.w (Special_stage_velocity).w,d1 beq.s loc_92A0 asr.w #5,d1 add.w d1,anim_frame_timer(a0) moveq #0,d0 move.b anim_frame_timer(a0),d0 bpl.s loc_9296 addi.b #$C,d0 bra.s loc_92A0 ; --------------------------------------------------------------------------- loc_9296: cmpi.b #$C,d0 blo.s loc_92A0 subi.b #$C,d0 loc_92A0: move.b d0,anim_frame_timer(a0) lea (byte_91E8).l,a1 tst.b (Special_stage_jumping_P2).w beq.s loc_92C4 lea (byte_9204).l,a1 move.w (Special_stage_velocity).w,d1 bne.s loc_92C4 move.b (Level_frame_counter+1).w,d0 andi.w #3,d0 loc_92C4: move.b (a1,d0.w),mapping_frame(a0) bsr.w sub_9402 cmpi.b #5,$44(a0) bne.s loc_9304 tst.b (Special_stage_clear_routine).w bne.s loc_9304 tst.b (Special_stage_jumping_P2).w bmi.s loc_9304 move.b (Special_stage_angle).w,d0 andi.b #$3F,d0 bne.w loc_9304 move.l #$FFE80000,$40(a0) move.b #$81,(Special_stage_jumping_P2).w moveq #signextendB(sfx_Spring),d0 jsr (Play_SFX).l loc_9304: bsr.w sub_937C andi.w #button_A_mask|button_B_mask|button_C_mask,d0 beq.s loc_932A tst.b (Special_stage_jumping_P2).w bne.s loc_932A move.l #$FFF00000,$40(a0) move.b #$80,(Special_stage_jumping_P2).w moveq #signextendB(sfx_Jump),d0 jsr (Play_SFX).l loc_932A: tst.b (Special_stage_jumping_P2).w bpl.s loc_935E move.l $3C(a0),d0 add.l $40(a0),d0 bmi.s loc_9344 moveq #0,d0 move.l d0,$40(a0) move.b d0,(Special_stage_jumping_P2).w loc_9344: move.w (Special_stage_rate).w,d1 ext.l d1 lsl.l #4,d1 add.l d1,$40(a0) move.l d0,$3C(a0) swap d0 addi.w #-$800,d0 move.w d0,$36(a0) loc_935E: bsr.w sub_953E jsr (Draw_Sprite).l lea (PLC_SStageTails).l,a2 move.l #ArtUnc_SStageTails,d6 move.w #tiles_to_bytes($7EB),d4 bra.w SStage_PLCLoad_91A2 ; =============== S U B R O U T I N E ======================================= sub_937C: move.w (Pos_table_index).w,d0 lea (Pos_table).w,a1 lea (a1,d0.w),a1 move.w (Ctrl_1).w,(a1) move.b (Special_stage_jumping).w,2(a1) addq.b #4,(Pos_table_index+1).w move.b (Ctrl_2_held).w,d0 andi.b #$7F,d0 beq.s loc_93A6 move.w #600,(Tails_CPU_idle_timer).w loc_93A6: tst.w (Tails_CPU_idle_timer).w beq.s loc_93B6 subq.w #1,(Tails_CPU_idle_timer).w move.w (Ctrl_2).w,d0 rts ; --------------------------------------------------------------------------- loc_93B6: lea (Pos_table).w,a1 move.w #4,d1 lsl.b #2,d1 move.w (Pos_table_index).w,d0 sub.b d1,d0 move.b 2(a1,d0.w),d2 subq.b #4,d0 move.b 2(a1,d0.w),d1 moveq #0,d0 cmpi.b #-$7F,d2 beq.s locret_93E0 tst.b d1 bpl.s locret_93E0 move.w #$70,d0 locret_93E0: rts ; End of function sub_937C ; =============== S U B R O U T I N E ======================================= sub_93E2: lea (Pos_table).w,a2 move.w #bytesToLcnt($100),d0 loc_93EA: move.l #0,(a2)+ dbf d0,loc_93EA move.w #0,(Pos_table_index).w move.w #0,(Tails_CPU_idle_timer).w rts ; End of function sub_93E2 ; =============== S U B R O U T I N E ======================================= sub_9402: lea (SStage_layout_buffer+$100).w,a1 move.w (Special_stage_X_pos).w,d0 addi.w #$80,d0 lsr.w #8,d0 andi.w #$1F,d0 move.w (Special_stage_Y_pos).w,d1 addi.w #$80,d1 lsr.w #8,d1 andi.w #$1F,d1 lsl.w #5,d1 or.b d0,d1 lea (a1,d1.w),a1 lea $44(a0),a2 move.b 1(a2),(a2) move.b 2(a2),1(a2) move.b 3(a2),2(a2) move.b (a1),3(a2) rts ; End of function sub_9402 ; --------------------------------------------------------------------------- Obj_SStage_9444: move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #$10,height_pixels(a0) move.w #$100,priority(a0) move.l #Map_SStageTailstails,mappings(a0) move.w #make_art_tile($7B0,1,1),art_tile(a0) move.w #$A0,$30(a0) move.w #$70,$32(a0) move.b #-1,$3A(a0) move.b #1,mapping_frame(a0) move.l #loc_9488,(a0) loc_9488: movea.w $3E(a0),a1 move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) move.w #$2AAA,d0 move.w (Special_stage_velocity).w,d1 bmi.s loc_94A4 add.w d1,d0 loc_94A4: add.w d0,anim_frame_timer(a0) bcc.s loc_94BC move.b mapping_frame(a0),d0 addq.b #1,d0 cmpi.b #$F,d0 blo.s loc_94B8 moveq #1,d0 loc_94B8: move.b d0,mapping_frame(a0) loc_94BC: jsr (Draw_Sprite).l lea (PLC_SStageTailstails).l,a2 move.l #ArtUnc_SStageTailstails,d6 move.w #tiles_to_bytes($7B0),d4 bra.w SStage_PLCLoad_91A2 ; =============== S U B R O U T I N E ======================================= Draw_SSShadows: lea (word_94FC).l,a3 move.w (a3)+,(a6)+ move.b (a3)+,(a6)+ addq.w #1,a3 addq.w #1,a6 move.w (a3)+,(a6)+ move.w (a3)+,(a6)+ tst.w (Player_mode).w bne.s locret_94FA move.w (a3)+,(a6)+ move.b (a3)+,(a6)+ addq.w #1,a3 addq.w #1,a6 move.w (a3)+,(a6)+ move.w (a3)+,(a6)+ locret_94FA: rts ; End of function Draw_SSShadows ; --------------------------------------------------------------------------- word_94FC: dc.w $116, $F0A, make_art_tile($7A0,3,1), $110 dc.w $127, $F0B, make_art_tile($7A0,3,1), $110 ; =============== S U B R O U T I N E ======================================= sub_950C: move.w (SStage_scalar_index_2).w,d0 lea (SStage_scalar_result_2).w,a1 bsr.w GetScalars2 move.w (SStage_scalar_index_1).w,d0 lea (SStage_scalar_result_1).w,a1 bsr.w GetScalars2 move.w (SStage_scalar_index_0).w,d0 lea (SStage_scalar_result_0).w,a1 bsr.w GetScalars2 move.w #$E0,d0 lea (SStage_scalar_result_3).w,a1 bsr.w GetScalars2 rts ; End of function sub_950C ; =============== S U B R O U T I N E ======================================= sub_953E: move.w $34(a0),d1 move.w $36(a0),d2 move.w $38(a0),d0 bsr.w sub_A1DC bsr.w sub_A1B2 bsr.w sub_A188 addi.w #$100,d0 addi.w #$980,d2 bsr.w sub_A206 ext.l d1 lsl.l #8,d1 divs.w d0,d1 ext.l d2 lsl.l #8,d2 divs.w d0,d2 add.w $30(a0),d1 move.w d1,x_pos(a0) add.w $32(a0),d2 move.w d2,y_pos(a0) rts ; End of function sub_953E ; =============== S U B R O U T I N E ======================================= sub_9580: tst.b (Special_stage_fade_timer).w beq.s loc_95AE cmpi.b #$61,(Special_stage_fade_timer).w bhs.s loc_959A moveq #8,d1 add.b d1,(Special_stage_angle).w addq.b #1,(Special_stage_fade_timer).w rts ; --------------------------------------------------------------------------- loc_959A: move.w (Special_stage_X_pos).w,d0 or.w (Special_stage_Y_pos).w,d0 andi.w #$E0,d0 beq.s loc_95AE move.b #0,(Special_stage_fade_timer).w loc_95AE: move.w (Special_stage_X_pos).w,d3 btst #6,(Special_stage_angle).w bne.s loc_95BE move.w (Special_stage_Y_pos).w,d3 loc_95BE: moveq #0,d2 move.b (Special_stage_turning).w,d1 beq.s loc_95F4 andi.w #$E0,d3 bne.s loc_95F4 tst.b (Special_stage_jumping).w bmi.s loc_9600 add.b d1,(Special_stage_angle).w move.b (Special_stage_angle).w,d0 andi.b #$3F,d0 bne.w locret_972C move.b #0,(Special_stage_turning).w tst.w (Special_stage_velocity).w beq.s loc_95F4 move.b #1,(Special_stage_turn_lock).w loc_95F4: andi.w #$E0,d3 beq.s loc_9600 move.b #0,(Special_stage_turn_lock).w loc_9600: move.b (Ctrl_1).w,d1 move.w (Special_stage_velocity).w,d2 tst.b (Special_stage_clear_routine).w bne.w loc_96FA tst.b (Special_stage_bumper_lock).w bne.s loc_9658 btst #0,d1 beq.s loc_9628 move.b #1,(Special_stage_advancing).w move.b #1,(Special_stage_started).w loc_9628: tst.b (Special_stage_advancing).w bne.s loc_964A tst.b (Special_stage_started).w beq.s loc_9658 tst.w d2 bpl.s loc_964A move.w (Special_stage_rate).w,d3 neg.w d3 subi.w #$200,d2 cmp.w d3,d2 bgt.s loc_9658 move.w d3,d2 bra.s loc_9658 ; --------------------------------------------------------------------------- loc_964A: move.w (Special_stage_rate).w,d3 addi.w #$200,d2 cmp.w d3,d2 blt.s loc_9658 move.w d3,d2 loc_9658: tst.b (Special_stage_turn_lock).w bne.s loc_9676 btst #2,d1 beq.s loc_966A move.b #4,(Special_stage_turning).w loc_966A: btst #3,d1 beq.s loc_9676 move.b #-4,(Special_stage_turning).w loc_9676: move.w d2,(Special_stage_velocity).w tst.b (Special_stage_bumper_lock).w beq.s loc_96FA move.w (Special_stage_X_pos).w,d0 btst #6,(Special_stage_angle).w bne.s loc_9690 move.w (Special_stage_Y_pos).w,d0 loc_9690: andi.w #$E0,d0 bne.s loc_96D4 move.w (Special_stage_X_pos).w,d0 addi.w #$80,d0 lsr.w #8,d0 andi.w #$1F,d0 move.w (Special_stage_Y_pos).w,d1 addi.w #$80,d1 lsr.w #8,d1 andi.w #$1F,d1 lsl.w #5,d1 or.b d0,d1 cmp.w (Special_stage_interact).w,d1 beq.s loc_96D4 move.b #0,(Special_stage_bumper_lock).w move.w (Special_stage_rate).w,d2 tst.w (Special_stage_velocity).w bmi.s loc_96CE neg.w d2 loc_96CE: move.w d2,(Special_stage_velocity).w rts ; --------------------------------------------------------------------------- loc_96D4: move.w (Special_stage_velocity).w,d2 bne.s loc_96F8 move.b #0,(Special_stage_bumper_lock).w move.b #1,(Special_stage_advancing).w move.w (Special_stage_rate).w,d2 tst.w (Special_stage_velocity).w bmi.s loc_96F2 neg.w d2 loc_96F2: move.w d2,(Special_stage_velocity).w bra.s loc_96FA ; --------------------------------------------------------------------------- loc_96F8: neg.w d2 loc_96FA: cmpi.b #$81,(Special_stage_jumping).w bne.s loc_9704 add.w d2,d2 loc_9704: move.b (Special_stage_angle).w,d0 jsr (GetSineCosine).l muls.w d2,d0 muls.w d2,d1 swap d0 sub.w d0,(Special_stage_X_pos).w swap d1 sub.w d1,(Special_stage_Y_pos).w tst.b (Special_stage_jumping).w bmi.s locret_972C tst.b (Special_stage_clear_routine).w bne.s locret_972C bsr.s sub_972E locret_972C: rts ; End of function sub_9580 ; =============== S U B R O U T I N E ======================================= sub_972E: lea (SStage_layout_buffer+$100).w,a1 move.w (Special_stage_X_pos).w,d0 addi.w #$80,d0 lsr.w #8,d0 andi.w #$1F,d0 move.w (Special_stage_Y_pos).w,d1 addi.w #$80,d1 lsr.w #8,d1 andi.w #$1F,d1 lsl.w #5,d1 or.b d0,d1 lea (a1,d1.w),a1 move.b (a1),d2 beq.w locret_98AE cmpi.b #1,d2 bne.s loc_97AA move.w (Special_stage_X_pos).w,d0 or.w (Special_stage_Y_pos).w,d0 andi.w #$E0,d0 bne.s locret_97A8 tst.b (Special_stage_fade_timer).w bne.s locret_97A8 move.b #1,(Special_stage_fade_timer).w move.b #$48,(Game_mode).w tst.b (Blue_spheres_stage_flag).w beq.s loc_978E move.b #$2C,(Game_mode).w loc_978E: tst.b (Special_bonus_entry_flag).w beq.s loc_97A0 move.w (Saved2_zone_and_act).w,(Current_zone_and_act).w ori.b #$80,(Last_star_post_hit).w loc_97A0: moveq #signextendB(sfx_Goal),d0 jsr (Play_SFX).l locret_97A8: rts ; --------------------------------------------------------------------------- loc_97AA: cmpi.b #2,d2 bne.s loc_97C8 bsr.w Find_SStageCollisionResponseSlot bne.s loc_97BE move.b #2,(a2) move.l a1,4(a2) loc_97BE: moveq #signextendB(sfx_BlueSphere),d0 jsr (Play_SFX).l rts ; --------------------------------------------------------------------------- loc_97C8: cmpi.b #3,d2 bne.s loc_97EE tst.b (Special_stage_bumper_lock).w bne.s loc_97EE move.w d1,(Special_stage_interact).w move.b #1,(Special_stage_bumper_lock).w move.b #0,(Special_stage_advancing).w moveq #signextendB(sfx_Bumper),d0 jsr (Play_SFX).l rts ; --------------------------------------------------------------------------- loc_97EE: cmpi.b #5,d2 bne.s loc_9822 tst.b (Special_stage_clear_routine).w bne.s loc_9822 tst.b (Special_stage_jumping).w bmi.s loc_9822 move.b (Special_stage_angle).w,d0 andi.b #$3F,d0 bne.w loc_9822 move.l #$FFE80000,$40(a0) move.b #$81,(Special_stage_jumping).w moveq #signextendB(sfx_Spring),d0 jsr (Play_SFX).l loc_9822: cmpi.b #4,d2 bne.w locret_98AE bsr.w Find_SStageCollisionResponseSlot bne.s loc_9838 move.b #1,(a2) move.l a1,4(a2) loc_9838: tst.w (Special_stage_rings_left).w beq.s loc_984C subq.w #1,(Special_stage_rings_left).w bne.s loc_984C moveq #signextendB(sfx_Perfect),d0 jsr (Play_Music).l loc_984C: addi.w #1,(Special_stage_ring_count).w bset #7,(Special_stage_extra_life_flags).w moveq #signextendB(sfx_RingRight),d0 tst.b (Blue_spheres_stage_flag).w bne.s loc_98A6 cmpi.w #50,(Special_stage_ring_count).w blo.s loc_987E bset #0,(Special_stage_extra_life_flags).w bne.s loc_987E addq.b #1,(Continue_count).w move.w #signextendB(sfx_Continue),d0 jmp (Play_Music).l ; --------------------------------------------------------------------------- loc_987E: moveq #signextendB(sfx_RingRight),d0 cmpi.w #100,(Special_stage_ring_count).w blo.s loc_98A6 bset #1,(Special_stage_extra_life_flags).w beq.s loc_98A0 cmpi.w #200,(Special_stage_ring_count).w blo.s loc_98A6 bset #2,(Special_stage_extra_life_flags).w bne.s loc_98A6 loc_98A0: addq.b #1,(Life_count).w moveq #signextendB(sfx_RingLoss),d0 loc_98A6: jsr (Play_SFX).l rts ; --------------------------------------------------------------------------- locret_98AE: rts ; End of function sub_972E ; --------------------------------------------------------------------------- word_98B0: dc.w $18 dc.w 6 dc.w 1 dc.w $1F dc.w $FFFF dc.w $1F dc.w 0 dc.w 0 dc.w 8 dc.w 6 dc.w $FFFF dc.w $1F dc.w $FFFF dc.w $1F dc.w 0 dc.w 0 dc.w 8 dc.w $1A dc.w $FFFF dc.w $1F dc.w 1 dc.w $1F dc.w 0 dc.w 0 dc.w $18 dc.w $1A dc.w 1 dc.w $1F dc.w 1 dc.w $1F dc.w 0 dc.w 0 ; =============== S U B R O U T I N E ======================================= Draw_SSSprites: move.b (Special_stage_angle).w,d0 andi.w #$C0,d0 lsr.w #2,d0 lea word_98B0(pc,d0.w),a5 moveq #0,d1 move.b (Special_stage_X_pos).w,d1 move.w (Special_stage_X_pos).w,d0 addi.w #$100,d0 move.w (Special_stage_Y_pos).w,d2 andi.w #$100,d2 add.w d2,d0 btst #6,(Special_stage_angle).w bne.s loc_9930 move.b (Special_stage_Y_pos).w,d1 move.w (Special_stage_Y_pos).w,d0 move.w (Special_stage_X_pos).w,d2 andi.w #$100,d2 add.w d2,d0 loc_9930: tst.b (Special_stage_angle).w bmi.s loc_9946 neg.w d0 addi.w #$1F,d0 move.w d0,d2 andi.w #$E0,d2 beq.s loc_9946 addq.b #1,d1 loc_9946: andi.w #$1E0,d0 lsr.w #5,d0 move.w d0,(Special_stage_anim_frame).w move.b d0,(Special_stage_palette_frame).w move.b (Special_stage_angle).w,d0 andi.w #$38,d0 beq.s loc_9968 lsr.w #3,d0 addi.w #$F,d0 move.w d0,(Special_stage_anim_frame).w loc_9968: lea (Draw_SSSprite_Normal).l,a0 tst.w (Special_stage_clear_timer).w beq.s loc_997A lea (Draw_SSSprite_FlyAway).l,a0 loc_997A: btst #6,(Special_stage_angle).w bne.w loc_9A3C move.w 2(a5),d5 add.w d1,d5 and.w $A(a5),d5 move.w (Special_stage_anim_frame).w,d0 add.w d0,d0 add.w d0,d0 lea (RAM_start).l,a1 movea.l (a1,d0.w),a1 lea (SStage_layout_buffer+$100).w,a2 lea (SStage_extra_sprites).w,a4 lea (Sprite_table).w,a6 moveq #$50-1,d7 moveq #0,d6 move.b (Sprites_drawn).w,d6 sub.b d6,d7 lsl.w #3,d6 adda.w d6,a6 moveq #$10-1,d2 loc_99BC: move.w (a5),d4 moveq #0,d0 move.b (Special_stage_X_pos).w,d0 add.w d0,d4 and.w 6(a5),d4 moveq #$F-1,d3 loc_99CC: move.w d5,d0 lsl.w #5,d0 or.b d4,d0 move.b (a2,d0.w),d0 beq.s loc_9A20 move.w (a1),d1 andi.w #$7C,d1 beq.s loc_9A20 lsr.w #2,d1 subq.w #6,d1 cmpi.w #$10,d1 bhs.s loc_9A20 add.w d1,d1 andi.w #$FF,d0 lsl.w #3,d0 movea.l (a4,d0.w),a3 move.w 4(a4,d0.w),d6 cmpi.w #$54,(a1) blo.s loc_9A04 andi.w #$7FFF,d6 loc_9A04: move.w 6(a4,d0.w),d0 add.w d0,d0 bcc.s loc_9A0E moveq #0,d1 loc_9A0E: add.w d0,d1 adda.w (a3,d1.w),a3 move.w (a3)+,d1 subq.w #1,d1 bmi.s loc_9A20 jsr (a0) tst.w d7 bmi.s locret_9A3A loc_9A20: addq.w #6,a1 add.w 4(a5),d4 and.w 6(a5),d4 dbf d3,loc_99CC add.w 8(a5),d5 and.w $A(a5),d5 dbf d2,loc_99BC locret_9A3A: rts ; --------------------------------------------------------------------------- loc_9A3C: move.w 2(a5),d5 add.w d1,d5 and.w $A(a5),d5 move.w (Special_stage_anim_frame).w,d0 add.w d0,d0 add.w d0,d0 lea (RAM_start).l,a1 movea.l (a1,d0.w),a1 lea (SStage_layout_buffer+$100).w,a2 lea (SStage_extra_sprites).w,a4 lea (Sprite_table).w,a6 moveq #$50-1,d7 moveq #0,d6 move.b (Sprites_drawn).w,d6 sub.b d6,d7 lsl.w #3,d6 adda.w d6,a6 moveq #$10-1,d2 loc_9A74: move.w (a5),d4 moveq #0,d0 move.b (Special_stage_Y_pos).w,d0 add.w d0,d4 and.w 6(a5),d4 moveq #$F-1,d3 loc_9A84: move.w d4,d0 lsl.w #5,d0 or.b d5,d0 move.b (a2,d0.w),d0 beq.s loc_9AD8 move.w (a1),d1 andi.w #$7C,d1 beq.s loc_9AD8 lsr.w #2,d1 subq.w #6,d1 cmpi.w #$10,d1 bhs.s loc_9AD8 add.w d1,d1 andi.w #$FF,d0 lsl.w #3,d0 movea.l (a4,d0.w),a3 move.w 4(a4,d0.w),d6 cmpi.w #$54,(a1) blo.s loc_9ABC andi.w #$7FFF,d6 loc_9ABC: move.w 6(a4,d0.w),d0 add.w d0,d0 bcc.s loc_9AC6 moveq #0,d1 loc_9AC6: add.w d0,d1 adda.w (a3,d1.w),a3 move.w (a3)+,d1 subq.w #1,d1 bmi.s loc_9AD8 jsr (a0) tst.w d7 bmi.s locret_9AF2 loc_9AD8: addq.w #6,a1 add.w 4(a5),d4 and.w 6(a5),d4 dbf d3,loc_9A84 add.w 8(a5),d5 and.w $A(a5),d5 dbf d2,loc_9A74 locret_9AF2: rts ; End of function Draw_SSSprites ; --------------------------------------------------------------------------- Draw_SSSprite_Normal: move.b (a3)+,d0 ext.w d0 add.w 4(a1),d0 move.w d0,(a6)+ move.b (a3)+,(a6)+ addq.w #1,a6 move.w (a3)+,d0 add.w d6,d0 move.w d0,(a6)+ move.w (a3)+,d0 add.w 2(a1),d0 move.w d0,(a6)+ subq.w #1,d7 dbmi d1,Draw_SSSprite_Normal rts ; --------------------------------------------------------------------------- Draw_SSSprite_FlyAway: move.b (a3)+,d0 ext.w d0 add.w 4(a1),d0 sub.w (Special_stage_clear_timer).w,d0 move.w d0,(a6)+ move.b (a3)+,(a6)+ addq.w #1,a6 move.w (a3)+,d0 add.w d6,d0 move.w d0,(a6)+ move.w (a3)+,d0 add.w 2(a1),d0 move.w d1,-(sp) subi.w #$120,d0 move.w (Special_stage_clear_timer).w,d1 addi.w #$100,d1 muls.w d1,d0 asr.l #8,d0 addi.w #$120,d0 cmpi.w #$1D0,d0 blo.s loc_9B56 move.w #1,d0 loc_9B56: move.w (sp)+,d1 move.w d0,(a6)+ subq.w #1,d7 dbmi d1,Draw_SSSprite_FlyAway rts ; =============== S U B R O U T I N E ======================================= sub_9B62: move.b (Special_stage_clear_routine).w,d1 beq.w locret_9D1C subq.b #1,d1 bne.w loc_9C5C cmpi.w #$100,(Special_stage_clear_timer).w bhs.s loc_9BA6 addq.w #2,(Special_stage_clear_timer).w cmpi.w #2,(Special_stage_clear_timer).w bne.s loc_9B8C moveq #signextendB(sfx_AllSpheres),d0 jsr (Play_Music).l loc_9B8C: cmpi.w #$40,(Special_stage_clear_timer).w blo.s locret_9BA4 addq.w #1,(Special_stage_clear_timer).w cmpi.w #$80,(Special_stage_clear_timer).w blo.s locret_9BA4 addq.w #1,(Special_stage_clear_timer).w locret_9BA4: rts ; --------------------------------------------------------------------------- loc_9BA6: addq.b #1,(Special_stage_clear_routine).w lea (SStage_layout_buffer+$100).w,a1 move.w #bytesToLcnt($400),d0 loc_9BB2: move.l #0,(a1)+ dbf d0,loc_9BB2 move.b (Special_stage_angle).w,d0 jsr (GetSineCosine).l move.w (Special_stage_X_pos).w,d2 move.w (Special_stage_Y_pos).w,d3 asl.w #3,d0 asl.w #3,d1 sub.w d0,d2 sub.w d1,d3 lea (SStage_layout_buffer+$100).w,a1 move.w d2,d0 addi.w #$80,d0 lsr.w #8,d0 andi.w #$1F,d0 move.w d3,d1 addi.w #$80,d1 lsr.w #8,d1 andi.w #$1F,d1 lsl.w #5,d1 or.b d0,d1 move.b #$B,(a1,d1.w) tst.b (SK_special_stage_flag).w beq.s loc_9C08 move.b #$D,(a1,d1.w) loc_9C08: move.w d1,(Special_stage_interact).w move.w #$800,(Special_stage_velocity).w move.b #120,(Special_stage_emerald_timer).w moveq #0,d0 move.b (Current_special_stage).w,d0 tst.b (Blue_spheres_stage_flag).w beq.s loc_9C28 move.b (Blue_spheres_current_stage+2).w,d0 loc_9C28: andi.w #7,d0 lea (Pal_SStage_Emeralds).l,a1 lsl.w #3,d0 lea (a1,d0.w),a1 lea (Normal_palette_line_4+$4).w,a2 move.l (a1)+,(a2)+ move.l (a1)+,(a2)+ lea (ArtKosM_SStageChaosEmerald).l,a1 tst.b (SK_special_stage_flag).w beq.s loc_9C52 lea (ArtKosM_SStageSuperEmerald).l,a1 loc_9C52: move.w #tiles_to_bytes($5A7),d2 jmp (Queue_Kos_Module).l ; --------------------------------------------------------------------------- loc_9C5C: subq.b #1,d1 bne.s loc_9C80 tst.b (Kos_modules_left).w bne.s locret_9C7E move.w #0,(Special_stage_clear_timer).w subq.b #1,(Special_stage_emerald_timer).w bne.s locret_9C7E addq.b #1,(Special_stage_clear_routine).w moveq #signextendB(mus_Emerald),d0 jsr (Play_Music).l locret_9C7E: rts ; --------------------------------------------------------------------------- loc_9C80: subq.b #1,d1 bne.w locret_9D1C move.w (Special_stage_X_pos).w,d0 addi.w #$80,d0 lsr.w #8,d0 andi.w #$1F,d0 move.w (Special_stage_Y_pos).w,d1 addi.w #$80,d1 lsr.w #8,d1 andi.w #$1F,d1 lsl.w #5,d1 or.b d0,d1 cmp.w (Special_stage_interact).w,d1 bne.s locret_9D1C move.w (Special_stage_X_pos).w,d0 or.w (Special_stage_Y_pos).w,d0 andi.w #$E0,d0 bne.s locret_9D1C tst.b (Blue_spheres_stage_flag).w bne.s loc_9CE6 lea (Chaos_emerald_count).w,a2 move.b (SK_special_stage_flag).w,d2 beq.s loc_9CCE lea (Super_emerald_count).w,a2 loc_9CCE: cmpi.b #7,(a2) bhs.s loc_9CE6 addq.b #1,(a2) lea (Collected_emeralds_array).w,a1 moveq #0,d0 move.b (Current_special_stage).w,d0 bset #0,(a1,d0.w) loc_9CE6: addq.b #1,(Special_stage_clear_routine).w move.b #1,(Special_stage_fade_timer).w move.b #$48,(Game_mode).w tst.b (Blue_spheres_stage_flag).w beq.s loc_9D02 move.b #$30,(Game_mode).w loc_9D02: tst.b (Special_bonus_entry_flag).w beq.s loc_9D14 move.w (Saved2_zone_and_act).w,(Current_zone_and_act).w ori.b #$80,(Last_star_post_hit).w loc_9D14: moveq #signextendB(sfx_Goal),d0 jsr (Play_SFX).l locret_9D1C: rts ; End of function sub_9B62 ; --------------------------------------------------------------------------- Pal_SStage_Emeralds: binclude "General/Special Stage/Palettes/Emeralds.bin" even ; =============== S U B R O U T I N E ======================================= sub_9D5E: move.w (Special_stage_X_pos).w,d0 sub.w (Special_stage_prev_X_pos).w,d0 btst #6,(Special_stage_angle).w bne.s loc_9D76 move.w (Special_stage_Y_pos).w,d0 sub.w (Special_stage_prev_Y_pos).w,d0 loc_9D76: tst.b (Special_stage_angle).w bmi.s loc_9D7E neg.w d0 loc_9D7E: asr.w #2,d0 add.w d0,(V_scroll_value_BG).w moveq #0,d1 move.b (Special_stage_angle).w,d1 asl.w #2,d1 move.w d1,(H_scroll_buffer+2).w move.w (Special_stage_X_pos).w,(Special_stage_prev_X_pos).w move.w (Special_stage_Y_pos).w,(Special_stage_prev_Y_pos).w rts ; End of function sub_9D5E ; =============== S U B R O U T I N E ======================================= Animate_SSRings: lea (SStage_extra_sprites+$07).w,a1 subq.b #1,(Rings_frame_timer).w bpl.s loc_9DC2 move.b #7,(Rings_frame_timer).w addi.b #$10,(Rings_frame).w cmpi.b #$30,(Rings_frame).w blo.s loc_9DC2 move.b #0,(Rings_frame).w loc_9DC2: move.b (Rings_frame).w,anim(a1) rts ; End of function Animate_SSRings ; =============== S U B R O U T I N E ======================================= Find_SStageCollisionResponseSlot: lea (SStage_collision_response_list).w,a2 move.w #$20-1,d0 loc_9DD2: tst.b (a2) beq.s locret_9DDC addq.w #8,a2 dbf d0,loc_9DD2 locret_9DDC: rts ; End of function Find_SStageCollisionResponseSlot ; =============== S U B R O U T I N E ======================================= Touch_SSSprites: lea (SStage_collision_response_list).w,a0 move.w #$20-1,d7 loc_9DE6: moveq #0,d0 move.b (a0),d0 beq.s loc_9DF4 lsl.w #2,d0 movea.l off_9DFC-4(pc,d0.w),a1 jsr (a1) loc_9DF4: addq.w #8,a0 dbf d7,loc_9DE6 rts ; End of function Touch_SSSprites ; --------------------------------------------------------------------------- off_9DFC: dc.l Touch_SSSprites_Ring dc.l Touch_SSSprites_BlueSphere ; --------------------------------------------------------------------------- Touch_SSSprites_Ring: subq.b #1,2(a0) bpl.s locret_9E2C move.b #5,2(a0) moveq #0,d0 move.b 3(a0),d0 addq.b #1,3(a0) movea.l 4(a0),a1 move.b byte_9E2E(pc,d0.w),d0 move.b d0,(a1) bne.s locret_9E2C clr.l (a0) clr.l 4(a0) locret_9E2C: rts ; --------------------------------------------------------------------------- byte_9E2E: dc.b 6, 7, 8, 9, 0 even ; --------------------------------------------------------------------------- Touch_SSSprites_BlueSphere: subq.b #1,2(a0) bpl.s locret_9E86 move.b #9,2(a0) movea.l 4(a0),a1 cmpi.b #2,(a1) bne.s loc_9E62 bsr.w sub_9E88 move.b #$A,(a1) bsr.s sub_9EBC beq.s locret_9E60 move.b #4,(a1) clr.l (a0) clr.l 4(a0) locret_9E60: rts ; --------------------------------------------------------------------------- loc_9E62: move.b #0,2(a0) move.w (Special_stage_X_pos).w,d0 or.w (Special_stage_Y_pos).w,d0 andi.w #$E0,d0 beq.s locret_9E86 cmpi.b #$A,(a1) bne.s loc_9E80 move.b #1,(a1) loc_9E80: clr.l (a0) clr.l 4(a0) locret_9E86: rts ; =============== S U B R O U T I N E ======================================= sub_9E88: move.w d0,-(sp) move.b #-1,(Special_stage_sphere_HUD_flag).w subq.w #1,(Special_stage_spheres_left).w bne.s loc_9E9C move.b #1,(Special_stage_clear_routine).w loc_9E9C: move.w (sp)+,d0 rts ; End of function sub_9E88 ; =============== S U B R O U T I N E ======================================= sub_9EA0: lea (SStage_layout_buffer+$100).w,a3 moveq #0,d1 move.w #$400-1,d0 loc_9EAA: cmpi.b #2,(a3)+ bne.s loc_9EB2 addq.w #1,d1 loc_9EB2: dbf d0,loc_9EAA move.w d1,(Special_stage_spheres_left).w rts ; End of function sub_9EA0 ; =============== S U B R O U T I N E ======================================= sub_9EBC: lea (SStage_layout_buffer+$100).w,a2 move.l a1,d5 sub.l a2,d5 bsr.s sub_9F44 moveq #0,d6 move.l a5,d1 lea (SStage_unkA500).w,a4 sub.l a4,d1 beq.s locret_9F42 loc_9ED2: move.w (a4)+,d5 lea (word_A0CA).l,a3 move.w #8-1,d0 loc_9EDE: move.w (a3)+,d2 add.w d5,d2 andi.w #$3FF,d2 cmpi.b #2,(a2,d2.w) bne.s loc_9EFC bsr.w sub_9E88 move.b #4,(a2,d2.w) move.w d2,(a5)+ addq.w #2,d1 loc_9EFC: dbf d0,loc_9EDE subq.w #2,d1 bne.s loc_9ED2 move.l a5,d1 lea (SStage_unkA500).w,a4 sub.l a4,d1 beq.s locret_9F42 loc_9F0E: move.w (a4)+,d5 lea (word_A0CA).l,a3 move.w #8-1,d0 loc_9F1A: move.w (a3)+,d2 add.w d5,d2 andi.w #$3FF,d2 cmpi.b #1,(a2,d2.w) bne.s loc_9F30 move.b #4,(a2,d2.w) loc_9F30: dbf d0,loc_9F1A subq.w #2,d1 bne.s loc_9F0E moveq #signextendB(sfx_RingLoss),d0 jsr (Play_SFX).l moveq #1,d1 locret_9F42: rts ; End of function sub_9EBC ; =============== S U B R O U T I N E ======================================= sub_9F44: lea (SStage_unkA500).w,a5 lea (word_A0CA).l,a3 moveq #0,d2 move.w #8-1,d0 loc_9F54: move.w (a3)+,d1 add.w d5,d1 andi.w #$3FF,d1 cmpi.b #$A,(a2,d1.w) bne.s loc_9F6A move.b #1,(a2,d1.w) loc_9F6A: cmpi.b #2,(a2,d1.w) bne.s loc_9F74 addq.w #1,d2 loc_9F74: dbf d0,loc_9F54 tst.w d2 beq.w locret_A076 moveq #0,d2 move.w d5,d1 moveq #$10-1,d3 loc_9F84: addq.w #1,d2 addi.w #-1,d1 tst.b (a2,d1.w) beq.s loc_9F94 dbf d3,loc_9F84 loc_9F94: move.w d5,d1 moveq #$10-1,d3 loc_9F98: addq.w #1,d2 addi.w #1,d1 tst.b (a2,d1.w) beq.s loc_9FA8 dbf d3,loc_9F98 loc_9FA8: cmpi.w #4,d2 blo.w locret_A076 moveq #0,d2 move.w d5,d1 moveq #$10-1,d3 loc_9FB6: addq.w #1,d2 addi.w #$FFE0,d1 tst.b (a2,d1.w) beq.s loc_9FC6 dbf d3,loc_9FB6 loc_9FC6: move.w d5,d1 moveq #$10-1,d3 loc_9FCA: addq.w #1,d2 addi.w #$20,d1 tst.b (a2,d1.w) beq.s loc_9FDA dbf d3,loc_9FCA loc_9FDA: cmpi.w #4,d2 blo.w locret_A076 lea (SStage_unkA600).w,a4 lea (word_A0DA).l,a3 moveq #0,d6 moveq #0,d3 moveq #6,d4 add.w d3,d4 move.w d5,d0 loc_9FF6: move.w (a3,d4.w),d1 add.w d0,d1 andi.w #$3FF,d1 move.b (a2,d1.w),d2 cmpi.b #$8A,d2 beq.s loc_A078 cmpi.b #1,d2 bne.s loc_A054 cmpi.w #2,d6 blo.s loc_A034 move.w d1,d2 sub.w -6(a4),d2 cmpi.w #-1,d2 beq.s loc_A054 cmpi.w #1,d2 beq.s loc_A054 cmpi.w #$20,d2 beq.s loc_A054 cmpi.w #-$20,d2 beq.s loc_A054 loc_A034: ori.b #$80,(a2,d0.w) move.b d3,(a4)+ move.b d4,(a4)+ move.w d0,(a4)+ addq.w #1,d6 move.w d4,d3 subq.w #2,d3 andi.w #6,d3 move.w #4,d4 add.w d3,d4 move.w d1,d0 bra.s loc_9FF6 ; --------------------------------------------------------------------------- loc_A054: subq.w #2,d4 cmp.w d3,d4 bge.s loc_9FF6 loc_A05A: moveq #0,d3 moveq #0,d4 move.w -(a4),d0 move.b -(a4),d4 move.b -(a4),d3 subq.w #1,d6 bcs.s locret_A076 andi.b #$7F,(a2,d0.w) subq.w #2,d4 cmp.w d3,d4 bge.s loc_9FF6 bra.s loc_A05A ; --------------------------------------------------------------------------- locret_A076: rts ; --------------------------------------------------------------------------- loc_A078: movem.l d0/d3-d4/d6/a4,-(sp) sub.w d5,d0 move.w d0,d4 neg.w d4 lea (SStage_unkA600+6).w,a4 move.w (a4),d2 sub.w d5,d2 move.w d5,d3 loc_A08C: move.w (a4)+,d0 addq.w #2,a4 sub.w d3,d0 cmp.w d2,d0 bne.s loc_A09A add.w d0,d3 bra.s loc_A08C ; --------------------------------------------------------------------------- loc_A09A: cmp.w d4,d0 beq.s loc_A0A4 cmp.w d4,d2 beq.s loc_A0A4 add.w d2,d0 loc_A0A4: add.w d5,d0 cmpi.b #2,(a2,d0.w) beq.s loc_A0B8 cmpi.b #4,(a2,d0.w) beq.s loc_A0C4 bra.s loc_A0C4 ; --------------------------------------------------------------------------- loc_A0B8: bsr.w sub_9E88 move.b #4,(a2,d0.w) move.w d0,(a5)+ loc_A0C4: movem.l (sp)+,d0/d3-d4/d6/a4 bra.s loc_A054 ; End of function sub_9F44 ; --------------------------------------------------------------------------- word_A0CA: dc.w -$21 dc.w -$20 dc.w -$1F dc.w -1 dc.w 1 dc.w $1F dc.w $20 dc.w $21 word_A0DA: dc.w -1 dc.w -$20 dc.w 1 dc.w $20 dc.w -1 dc.w -$20 ; =============== S U B R O U T I N E ======================================= Load_SSSprite_Mappings: lea (SStage_extra_sprites).w,a1 lea (MapPtr_A10A).l,a0 moveq #$E-1,d1 loc_A0F2: move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ dbf d1,loc_A0F2 lea (SStage_collision_response_list).w,a1 move.w #$40-1,d1 loc_A102: clr.l (a1)+ dbf d1,loc_A102 rts ; End of function Load_SSSprite_Mappings ; --------------------------------------------------------------------------- MapPtr_A10A: dc.l Map_SStageSphere dc.w make_art_tile($680,0,1), $0000 dc.l Map_SStageSphere dc.w make_art_tile($680,0,1), $0000 dc.l Map_SStageSphere dc.w make_art_tile($680,2,1), $0000 dc.l Map_SStageSphere dc.w make_art_tile($680,1,1), $0000 dc.l Map_SStageRing dc.w make_art_tile($5A7,2,1), $0000 dc.l Map_SStageSphere dc.w make_art_tile($680,3,1), $0000 dc.l Map_SStageRing dc.w make_art_tile($5A7,2,1), $8030 dc.l Map_SStageRing dc.w make_art_tile($5A7,2,1), $8031 dc.l Map_SStageRing dc.w make_art_tile($5A7,2,1), $8032 dc.l Map_SStageRing dc.w make_art_tile($5A7,2,1), $8033 dc.l Map_SStageSphere dc.w make_art_tile($680,2,1), $0000 dc.l Map_SStageChaosEmerald dc.w make_art_tile($5A7,3,1), $0000 dc.l Map_SStageSphere dc.w make_art_tile($680,2,1), $0000 dc.l Map_SStageSuperEmerald dc.w make_art_tile($5A7,3,1), $0000 ; --------------------------------------------------------------------------- ext.l d1 lsl.l #8,d1 divs.w d0,d1 ext.l d2 lsl.l #8,d2 divs.w d0,d2 rts ; =============== S U B R O U T I N E ======================================= sub_A188: swap d0 move.w d1,d3 move.w d2,d4 move.w (SStage_scalar_result_2).w,d0 muls.w d0,d3 muls.w d0,d4 move.w (SStage_scalar_result_2+2).w,d0 muls.w d0,d1 muls.w d0,d2 sub.l d4,d1 add.l d1,d1 add.l d1,d1 swap d1 add.l d3,d2 add.l d2,d2 add.l d2,d2 swap d2 swap d0 rts ; End of function sub_A188 ; =============== S U B R O U T I N E ======================================= sub_A1B2: swap d2 move.w d0,d3 move.w d1,d4 move.w (SStage_scalar_result_1).w,d2 muls.w d2,d3 muls.w d2,d4 move.w (SStage_scalar_result_1+2).w,d2 muls.w d2,d0 muls.w d2,d1 sub.l d4,d0 add.l d0,d0 add.l d0,d0 swap d0 add.l d3,d1 add.l d1,d1 add.l d1,d1 swap d1 swap d2 rts ; End of function sub_A1B2 ; =============== S U B R O U T I N E ======================================= sub_A1DC: swap d1 move.w d0,d3 move.w d2,d4 move.w (SStage_scalar_result_0).w,d1 muls.w d1,d3 muls.w d1,d4 move.w (SStage_scalar_result_0+2).w,d1 muls.w d1,d0 muls.w d1,d2 sub.l d4,d0 add.l d0,d0 add.l d0,d0 swap d0 add.l d3,d2 add.l d2,d2 add.l d2,d2 swap d2 swap d1 rts ; End of function sub_A1DC ; =============== S U B R O U T I N E ======================================= sub_A206: swap d1 move.w d0,d3 move.w d2,d4 move.w (SStage_scalar_result_3).w,d1 muls.w d1,d3 muls.w d1,d4 move.w (SStage_scalar_result_3+2).w,d1 muls.w d1,d0 muls.w d1,d2 sub.l d4,d0 add.l d0,d0 add.l d0,d0 swap d0 add.l d3,d2 add.l d2,d2 add.l d2,d2 swap d2 swap d1 rts ; End of function sub_A206 ; =============== S U B R O U T I N E ======================================= sub_A230: add.w d0,d0 addi.w #$80,d0 andi.w #$1FE,d0 move.w ScalarTable2(pc,d0.w),d1 subi.w #$80,d0 andi.w #$1FE,d0 move.w ScalarTable2(pc,d0.w),d0 rts ; End of function sub_A230 ; =============== S U B R O U T I N E ======================================= GetScalars2: add.w d0,d0 andi.w #$1FE,d0 move.w ScalarTable2(pc,d0.w),(a1)+ addi.w #$80,d0 andi.w #$1FE,d0 move.w ScalarTable2(pc,d0.w),(a1)+ rts ; End of function GetScalars2 ; --------------------------------------------------------------------------- ScalarTable2: binclude "General/Special Stage/Scalars.bin" even Map_SStageSphere: include "General/Special Stage/Map - Sphere.asm" Map_SStageRing: include "General/Special Stage/Map - Ring.asm" Map_SStageChaosEmerald: include "General/Special Stage/Map - Chaos Emerald.asm" Map_SStageSuperEmerald: include "General/Special Stage/Map - Super Emerald.asm" ; --------------------------------------------------------------------------- locret_A85C: rts ; --------------------------------------------------------------------------- Competition_Menu: bsr.w Pal_FadeToBlack move #$2700,sr move.w (VDP_reg_1_command).w,d0 andi.b #$BF,d0 move.w d0,(VDP_control_port).l jsr (Clear_DisplayData).l lea (VDP_control_port).l,a6 move.w #$8004,(a6) move.w #$8230,(a6) move.w #$8407,(a6) move.w #$8730,(a6) move.w #$8B00,(a6) move.w #$8C81,(a6) move.w #$9011,(a6) jsr sub_C02A(pc) clearRAM Sprite_table_input,$400 clearRAM Object_RAM,(Kos_decomp_buffer-Object_RAM) clr.w (DMA_queue).w move.l #DMA_queue,(DMA_queue_slot).w clr.w (Level_frame_counter).w cmpi.b #3,(Competition_menu_selection).w blo.s loc_A8DC clr.b (Competition_menu_selection).w loc_A8DC: lea (MapEni_S3MenuBG).l,a0 lea (RAM_start).l,a1 move.w #make_art_tile($001,3,0),d0 jsr (Eni_Decomp).l lea (RAM_start).l,a1 move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0 moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l lea (ArtKos_S3MenuBG).l,a0 ; Decompress source lea (RAM_start).l,a1 ; Decompress destination/Transfer source movea.w #tiles_to_bytes(ArtTile_ArtKos_S3MenuBG),a2 ; Transfer destination jsr KosArt_To_VDP(pc) move.l #locret_A85C,(_unkEF44_1).w move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l lea (ArtKos_CompetitionLevel).l,a0 ; Decompress source lea (RAM_start).l,a1 ; Decompress destination/Transfer source, used by the next KosArt_To_VDP also movea.w #tiles_to_bytes(ArtTile_ArtKos_Competition_LevSel),a2 ; Transfer destination jsr KosArt_To_VDP(pc) lea (ArtKos_CompetitionMode).l,a0 ; Decompress source movea.w #tiles_to_bytes(ArtTile_ArtKos_Competition_ModeSel),a2 ; Transfer destination jsr KosArt_To_VDP(pc) move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l lea (Pal_Competition1).l,a0 lea (Target_palette).w,a1 moveq #bytesToLcnt($60),d0 loc_A96A: move.l (a0)+,(a1)+ dbf d0,loc_A96A lea (Pal_CompetitionMenuBG).l,a0 moveq #bytesToLcnt($20),d0 loc_A978: move.l (a0)+,(a1)+ dbf d0,loc_A978 lea (Object_RAM).w,a0 lea ObjDat_AB48(pc),a1 move.w (a1)+,d0 loc_A988: move.l (a1)+,(a0) move.w #make_art_tile(ArtTile_ArtKos_Competition_ModeSel,0,0),art_tile(a0) move.l #Map_CompetitionObject,mappings(a0) move.w (a1)+,x_pos(a0) move.w (a1)+,y_pos(a0) move.b (a1)+,mapping_frame(a0) move.b (a1)+,$2E(a0) lea next_object(a0),a0 dbf d0,loc_A988 jsr (Init_SpriteTable).l jsr (Process_Sprites).l jsr (Render_Sprites).l moveq #signextendB(mus_CompetitionMenu),d0 jsr (Play_Music).l move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l move.w (VDP_reg_1_command).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l bsr.w Pal_FadeFromBlack loc_A9E8: move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l addq.w #1,(Level_frame_counter).w jsr (Process_Sprites).l jsr (Render_Sprites).l move.b (Ctrl_1_pressed).w,d0 or.b (Ctrl_2_pressed).w,d0 move.b d0,d1 andi.b #button_A_mask|button_B_mask|button_C_mask|button_start_mask,d1 beq.w loc_AAA6 btst #button_B,d1 bne.s loc_AA2E moveq #0,d2 move.b (Competition_menu_selection).w,d2 add.w d2,d2 jmp loc_AA28(pc,d2.w) ; --------------------------------------------------------------------------- loc_AA28: bra.s loc_AA36 ; --------------------------------------------------------------------------- bra.s loc_AA54 ; --------------------------------------------------------------------------- bra.s loc_AA74 ; --------------------------------------------------------------------------- loc_AA2E: move.b #4,(Game_mode).w rts ; --------------------------------------------------------------------------- loc_AA36: clr.b (Competition_type).w move.b (Competition_menu_items).w,(Competition_items).w move.b (Ctrl_2_pressed).w,d0 andi.b #button_A_mask|button_C_mask|button_start_mask,d0 sne (Not_ghost_flag).w move.b #$3C,(Game_mode).w bra.s loc_AA8E ; --------------------------------------------------------------------------- loc_AA54: move.b #3,(Competition_type).w move.b (Competition_menu_items).w,(Competition_items).w move.b (Ctrl_2_pressed).w,d0 andi.b #button_A_mask|button_C_mask|button_start_mask,d0 sne (Not_ghost_flag).w move.b #$40,(Game_mode).w bra.s loc_AA8E ; --------------------------------------------------------------------------- loc_AA74: move.b (Ctrl_1_pressed).w,d2 andi.w #button_A_mask|button_C_mask|button_start_mask,d2 beq.s loc_AAA6 move.w #-1,(Competition_settings).w clr.b (Not_ghost_flag).w move.b #$C0,(Game_mode).w loc_AA8E: lea ($FF7800).l,a1 moveq #0,d0 moveq #bytesToLcnt($28),d1 loc_AA98: move.l d0,(a1)+ dbf d1,loc_AA98 moveq #signextendB(sfx_Starpost),d0 jmp (Play_SFX).l ; --------------------------------------------------------------------------- loc_AAA6: moveq #0,d2 move.b (Competition_menu_selection).w,d1 lsr.w #1,d0 bcc.s loc_AABA moveq #signextendB(sfx_Switch),d2 subq.b #1,d1 bcc.s loc_AACA moveq #3,d1 bra.s loc_AACA ; --------------------------------------------------------------------------- loc_AABA: lsr.w #1,d0 bcc.s loc_AACA moveq #signextendB(sfx_Switch),d2 addq.b #1,d1 cmpi.b #3,d1 bls.s loc_AACA moveq #0,d1 loc_AACA: move.b d1,(Competition_menu_selection).w move.w d2,d0 beq.s loc_AAD8 jsr (Play_SFX).l loc_AAD8: bra.w loc_A9E8 ; --------------------------------------------------------------------------- Obj_Competition_AADC: move.b $2E(a0),d0 bmi.s loc_AAFA andi.w #$9FFF,art_tile(a0) move.w #$2000,d1 cmp.b (Competition_menu_selection).w,d0 bne.s loc_AAF6 move.w #$4000,d1 loc_AAF6: or.w d1,art_tile(a0) loc_AAFA: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Obj_Competition_AB00: cmpi.b #1,(Competition_menu_selection).w bhi.s locret_AB46 move.b (Ctrl_1_pressed).w,d0 or.b (Ctrl_2_pressed).w,d0 andi.w #button_left_mask|button_right_mask,d0 beq.s loc_AB26 tst.b (Competition_menu_items).w seq (Competition_menu_items).w moveq #signextendB(sfx_Switch),d0 jsr (Play_SFX).l loc_AB26: move.w #$15C,d0 tst.b (Competition_menu_items).w beq.s loc_AB34 addi.w #$20,d0 loc_AB34: move.w d0,x_pos(a0) btst #3,(Level_frame_counter+1).w beq.s locret_AB46 jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_AB46: rts ; --------------------------------------------------------------------------- ObjDat_AB48: dc.w 7-1 dc.l Obj_Competition_AADC dc.w $114, $A0 dc.b 0, 0 dc.l Obj_Competition_AADC dc.w $10C, $C0 dc.b 1, 1 dc.l Obj_Competition_AADC dc.w $108, $E0 dc.b 2, 2 dc.l Obj_Competition_AADC dc.w $13C, $120 dc.b 3, 3 dc.l Obj_Competition_AADC dc.w $164, $B0 dc.b 4, $FF dc.l Obj_Competition_AADC dc.w $184, $B0 dc.b 5, $FF dc.l Obj_Competition_AB00 dc.w 0, $A8 dc.b 6, $FF ; --------------------------------------------------------------------------- Competition_LevelSelect: bsr.w Pal_FadeToBlack move #$2700,sr move.w (VDP_reg_1_command).w,d0 andi.b #$BF,d0 move.w d0,(VDP_control_port).l jsr (Clear_DisplayData).l lea (VDP_control_port).l,a6 move.w #$8004,(a6) move.w #$8230,(a6) move.w #$8407,(a6) move.w #$8700,(a6) move.w #$8B00,(a6) move.w #$8C89,(a6) move.w #$9011,(a6) jsr sub_C02A(pc) clearRAM Sprite_table_input,$400 clearRAM Object_RAM,(Kos_decomp_buffer-Object_RAM) clr.w (DMA_queue).w move.l #DMA_queue,(DMA_queue_slot).w clr.w (Level_frame_counter).w clr.w (Competition_mode).w clr.b (Level_started_flag).w move.w #-1,(Events_bg+$10).w clr.w (Events_bg+$12).w clr.w (Events_bg+$14).w lea (MapEni_S3MenuBG).l,a0 lea (RAM_start).l,a1 move.w #make_art_tile($001,0,0),d0 jsr (Eni_Decomp).l lea (RAM_start).l,a1 move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0 moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l lea (MapEni_CompetitionLevBorder).l,a0 lea (RAM_start).l,a1 move.w #make_art_tile(ArtTile_ArtKos_Competition_LevSel,0,1),d0 jsr (Eni_Decomp).l lea (MapEni_CompetitionLevImage).l,a0 lea (RAM_start+$1000).l,a1 move.w #make_art_tile(ArtTile_ArtKos_Competition_LevSel,3,1),d0 jsr (Eni_Decomp).l lea (MapEni_CompetitionLevName).l,a0 lea (RAM_start+$2000).l,a1 move.w #make_art_tile(ArtTile_ArtKos_Competition_LevSel,1,1),d0 jsr (Eni_Decomp).l lea VRAMDatList_CompetitionLevelSelect(pc),a0 jsr Copy_Listed_Data_To_VRAM(pc) jsr sub_AFB2(pc) mulu.w #$48,d0 move.w d0,(V_scroll_value).w jsr sub_B006(pc) jsr sub_B036(pc) lea (ArtKos_S3MenuBG).l,a0 ; Decompress source lea (RAM_start).l,a1 ; Decompress destination/Transfer source movea.w #tiles_to_bytes(ArtTile_ArtKos_S3MenuBG),a2 ; Transfer destination jsr KosArt_To_VDP(pc) move.l #locret_A85C,(_unkEF44_1).w move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l lea (ArtKos_CompetitionLevel).l,a0 ; Decompress source lea (RAM_start).l,a1 ; Decompress destination/Transfer source, used by the next KosArt_To_VDP also movea.w #tiles_to_bytes(ArtTile_ArtKos_Competition_LevSel),a2 ; Transfer destination jsr KosArt_To_VDP(pc) lea (ArtKos_CompetitionPlayer).l,a0 ; Decompress source movea.w #tiles_to_bytes(ArtTile_ArtKos_Competition_CharSel),a2 ; Transfer destination jsr KosArt_To_VDP(pc) move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l lea (Pal_CompetitionMenuBG).l,a0 lea (Target_palette).w,a1 moveq #bytesToLcnt($20),d0 loc_AD04: move.l (a0)+,(a1)+ dbf d0,loc_AD04 lea (Pal_Competition2).l,a0 moveq #bytesToLcnt($60),d0 loc_AD12: move.l (a0)+,(a1)+ dbf d0,loc_AD12 lea (Object_RAM).w,a0 lea ObjDat_CompetitionMatchRace(pc),a1 tst.b (Game_mode).w bpl.s loc_AD2A lea ObjDat_CompetitionTimeAttack(pc),a1 loc_AD2A: move.w (a1)+,d0 loc_AD2C: move.l (a1)+,(a0) move.l #Map_CompetitionSelect,mappings(a0) move.w (a1),x_pos(a0) move.w (a1)+,$12(a0) move.w (a1),y_pos(a0) move.w (a1)+,$16(a0) move.w (a1)+,d1 addi.w #make_art_tile(ArtTile_ArtKos_Competition_LevSel,0,1),d1 move.w d1,art_tile(a0) move.b (a1)+,mapping_frame(a0) move.b (a1)+,$2E(a0) lea next_object(a0),a0 dbf d0,loc_AD2C moveq #0,d0 move.b (P1_character).w,d0 mulu.w #$55,d0 addi.b #$40,d0 move.b d0,(Reserved_object_3+objoff_2E).w tst.b (Game_mode).w bmi.s loc_AD8A moveq #0,d0 move.b (P2_character).w,d0 mulu.w #$55,d0 addi.b #$40,d0 move.b d0,(Dynamic_object_RAM+(object_size*4)+objoff_2E).w loc_AD8A: jsr (Init_SpriteTable).l jsr (Process_Sprites).l jsr (Render_Sprites).l jsr sub_C0AE(pc) jsr (Process_Sprites).l jsr (Render_Sprites).l lea (Dynamic_object_RAM+(object_size*9)).w,a0 move.l #loc_AF58,(a0) move.l #Map_CompetitionSelect,mappings(a0) addi.w #make_art_tile(ArtTile_ArtKos_Competition_LevSel,2,1),art_tile(a0) move.w #$B0,x_pos(a0) moveq #signextendB(mus_CompetitionMenu),d0 jsr (Play_Music).l move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l move.w (VDP_reg_1_command).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l jsr (Pal_FadeFromBlack).l loc_ADF2: move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l addq.w #1,(Level_frame_counter).w jsr (Process_Sprites).l jsr sub_C0AE(pc) jsr (Render_Sprites).l move.b (Events_bg+$12).w,d0 beq.s loc_AE1E move.b d0,(Game_mode).w rts ; --------------------------------------------------------------------------- loc_AE1E: move.w (Events_bg+$10).w,d0 tst.b (Not_ghost_flag).w bne.s loc_AE2A lsr.w #8,d0 loc_AE2A: tst.w d0 beq.s loc_AE4A move.w (H_scroll_buffer).w,d0 beq.s loc_ADF2 cmpi.w #-$58,d0 bne.s loc_AE42 move.l #loc_AFC8,(_unkEF44_1).w loc_AE42: addq.w #8,d0 move.w d0,(H_scroll_buffer).w bra.s loc_ADF2 ; --------------------------------------------------------------------------- loc_AE4A: cmpi.w #-$58,(H_scroll_buffer).w beq.s loc_AE58 subq.w #8,(H_scroll_buffer).w bra.s loc_ADF2 ; --------------------------------------------------------------------------- loc_AE58: moveq #8,d0 move.w (Events_bg+$14).w,d1 beq.s loc_AE6E bpl.s loc_AE64 neg.w d0 loc_AE64: add.w d0,(V_scroll_value).w sub.w d0,(Events_bg+$14).w bra.s loc_ADF2 ; --------------------------------------------------------------------------- loc_AE6E: move.b (Ctrl_1_pressed).w,d1 moveq #0,d2 tst.b (Not_ghost_flag).w beq.s loc_AE7E move.b (Ctrl_2_pressed).w,d2 loc_AE7E: btst #button_B,d2 beq.s loc_AE8C sf (Dynamic_object_RAM+(object_size*4)+objoff_2F).w st (Events_bg+$11).w loc_AE8C: btst #button_B,d1 beq.s loc_AE9A sf (Reserved_object_3+objoff_2F).w st (Events_bg+$10).w loc_AE9A: or.b d2,d1 move.b d1,d2 andi.w #3,d2 beq.s loc_AEF2 lea (Competition_menu_zone).w,a0 lsr.w #1,d2 bcs.s loc_AED2 cmpi.b #4,(a0) beq.s loc_AEF2 moveq #signextendB(sfx_Switch),d0 jsr (Play_SFX).l addq.b #1,(a0) cmpi.b #4,(a0) beq.s loc_AEF2 cmpi.b #1,(a0) beq.s loc_AEF2 move.w #$48,(Events_bg+$14).w bra.w loc_ADF2 ; --------------------------------------------------------------------------- loc_AED2: tst.b (a0) beq.s loc_AEF2 moveq #signextendB(sfx_Switch),d0 jsr (Play_SFX).l subq.b #1,(a0) beq.s loc_AEF2 cmpi.b #3,(a0) beq.s loc_AEF2 move.w #-$48,(Events_bg+$14).w bra.w loc_ADF2 ; --------------------------------------------------------------------------- loc_AEF2: andi.w #$E0,d1 beq.w loc_ADF2 moveq #signextendB(sfx_Starpost),d0 jsr (Play_SFX).l moveq #0,d0 move.b (Competition_menu_zone).w,d0 move.b Comp_ZoneList(pc,d0.w),(Current_zone).w clr.b (Current_act).w jsr sub_C104(pc) move.b #$C,(Game_mode).w rts ; --------------------------------------------------------------------------- Comp_ZoneList: dc.b $E dc.b $F dc.b $11 dc.b $10 dc.b $12 dc.b $FF ; --------------------------------------------------------------------------- Obj_Competition_ZoneSelect: cmpi.w #-$58,(H_scroll_buffer).w bne.s locret_AF56 tst.w (Events_bg+$14).w bne.s locret_AF56 moveq #0,d0 move.b (Competition_menu_zone).w,d0 mulu.w #$48,d0 addi.w #$AC,d0 sub.w (V_scroll_value).w,d0 move.w d0,y_pos(a0) btst #3,(Level_frame_counter+1).w beq.s locret_AF56 jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_AF56: rts ; --------------------------------------------------------------------------- loc_AF58: cmpi.w #-$58,(H_scroll_buffer).w bne.s loc_AF9E tst.w (Events_bg+$14).w bne.s loc_AF9E moveq #0,d0 move.b (Competition_menu_zone).w,d0 mulu.w #$48,d0 addi.w #$A8,d0 sub.w (V_scroll_value).w,d0 move.w d0,y_pos(a0) move.b (Competition_menu_zone).w,d0 addq.b #6,d0 move.b d0,mapping_frame(a0) jsr (Draw_Sprite).l moveq #0,d0 move.b (Competition_menu_zone).w,d0 lsl.w #5,d0 lea (Pal_Competition4).l,a1 adda.w d0,a1 bra.s loc_AFA4 ; --------------------------------------------------------------------------- loc_AF9E: lea (Pal_Competition3).l,a1 loc_AFA4: lea (Normal_palette_line_3).w,a2 moveq #bytesToLcnt($20),d0 loc_AFAA: move.l (a1)+,(a2)+ dbf d0,loc_AFAA rts ; =============== S U B R O U T I N E ======================================= sub_AFB2: moveq #0,d0 move.b (Competition_menu_zone).w,d0 subq.w #1,d0 bcc.s loc_AFBE moveq #0,d0 loc_AFBE: cmpi.w #2,d0 bls.s locret_AFC6 moveq #2,d0 locret_AFC6: rts ; End of function sub_AFB2 ; --------------------------------------------------------------------------- loc_AFC8: move.l #locret_A85C,(_unkEF44_1).w move.l #vdpComm(VRAM_Plane_A_Name_Table+$204,VRAM,WRITE),d0 lea (VDP_data_port).l,a6 move.l #$80008000,d1 move.w #$8F80,VDP_control_port-VDP_data_port(a6) moveq #9-1,d2 loc_AFEA: moveq #$13-1,d3 move.l d0,VDP_control_port-VDP_data_port(a6) loc_AFF0: move.l d1,(a6) dbf d3,loc_AFF0 addi.l #2<<16,d0 dbf d2,loc_AFEA move.w #$8F02,VDP_control_port-VDP_data_port(a6) ; =============== S U B R O U T I N E ======================================= sub_B006: bsr.s sub_AFB2 mulu.w #$48,d0 addi.w #$20,d0 lsl.w #4,d0 addi.w #VRAM_Plane_A_Name_Table+$004,d0 move.w d0,d7 tst.b (Game_mode).w bmi.s loc_B02E jsr sub_C04C(pc) move.w d7,d0 addi.w #$600,d0 jmp sub_C04C(pc) ; --------------------------------------------------------------------------- rts ; --------------------------------------------------------------------------- loc_B02E: addi.w #$300,d0 jmp sub_C04C(pc) ; End of function sub_B006 ; =============== S U B R O U T I N E ======================================= sub_B036: move.w #VRAM_Plane_A_Name_Table+$2D2,d7 move.l (Competition_saved_data).w,d6 bsr.s sub_B066 addi.w #$480,d7 move.l (Competition_saved_data+$10).w,d6 bsr.s sub_B066 addi.w #$480,d7 move.l (Competition_saved_data+$30).w,d6 bsr.s sub_B066 addi.w #$480,d7 move.l (Competition_saved_data+$20).w,d6 bsr.s sub_B066 addi.w #$480,d7 move.l (Competition_saved_data+$40).w,d6 ; End of function sub_B036 ; =============== S U B R O U T I N E ======================================= sub_B066: moveq #0,d5 lsl.l #8,d6 moveq #2,d3 loc_B06C: rol.l #8,d6 moveq #0,d0 move.b d6,d0 jsr (LevResults_GetDecimalScore).l move.b d1,d5 lsl.l #8,d5 dbf d3,loc_B06C lea (Plane_buffer).w,a1 lea (MapUnc_CompetitionNumbers).l,a2 moveq #0,d0 bsr.s sub_B0C2 st d0 bsr.s sub_B0C2 moveq #$A,d1 bsr.s sub_B0D4 bsr.s sub_B0C2 bsr.s sub_B0C2 moveq #$B,d1 bsr.s sub_B0D4 bsr.s sub_B0C2 bsr.s sub_B0C2 lea (Plane_buffer).w,a1 sub_B0A6: move.w d7,d0 swap d0 clr.w d0 swap d0 lsl.l #2,d0 lsr.w #2,d0 ori.w #$4000,d0 swap d0 moveq #8-1,d1 moveq #2-1,d2 jmp (Plane_Map_To_VRAM).l ; End of function sub_B066 ; =============== S U B R O U T I N E ======================================= sub_B0C2: rol.l #4,d5 move.w d5,d1 andi.w #$F,d1 bne.s sub_B0D4 tst.w d0 bne.s sub_B0D4 moveq #$C,d1 st d0 ; End of function sub_B0C2 ; =============== S U B R O U T I N E ======================================= sub_B0D4: add.w d1,d1 add.w d1,d1 move.w (a2,d1.w),(a1)+ move.w 2(a2,d1.w),$E(a1) rts ; End of function sub_B0D4 ; =============== S U B R O U T I N E ======================================= sub_B0E4: lea (byte_37E52).l,a1 moveq #0,d0 move.b d6,d0 move.b (a1,d0.w),d6 rts ; End of function sub_B0E4 ; --------------------------------------------------------------------------- VRAMDatList_CompetitionLevelSelect: dc.w $19-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_A_Name_Table+$0098, $1B-1, 9-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_A_Name_Table+$0518, $1B-1, 9-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_A_Name_Table+$0998, $1B-1, 9-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_A_Name_Table+$0E18, $1B-1, 9-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_A_Name_Table+$1298, $1B-1, 9-1 dc.l RAM_start+$1180 dc.w VRAM_Plane_A_Name_Table+$011A, 8-1, 6-1 dc.l RAM_start+$1120 dc.w VRAM_Plane_A_Name_Table+$059A, 8-1, 6-1 dc.l RAM_start+$1000 dc.w VRAM_Plane_A_Name_Table+$0A1A, 8-1, 6-1 dc.l RAM_start+$1060 dc.w VRAM_Plane_A_Name_Table+$0E9A, 8-1, 6-1 dc.l RAM_start+$10C0 dc.w VRAM_Plane_A_Name_Table+$131A, 8-1, 6-1 dc.l RAM_start+$2000 dc.w VRAM_Plane_A_Name_Table+$01AC, $F-1, 5-1 dc.l RAM_start+$2258 dc.w VRAM_Plane_A_Name_Table+$062C, $F-1, 5-1 dc.l RAM_start+$2096 dc.w VRAM_Plane_A_Name_Table+$0AAC, $F-1, 5-1 dc.l RAM_start+$21C2 dc.w VRAM_Plane_A_Name_Table+$0F2C, $F-1, 5-1 dc.l RAM_start+$212C dc.w VRAM_Plane_A_Name_Table+$13AC, $F-1, 5-1 dc.l MapUnc_CompetitionTimeBorder dc.w VRAM_Plane_A_Name_Table+$00CE, $C-1, 9-1 dc.l MapUnc_CompetitionTimeBorder dc.w VRAM_Plane_A_Name_Table+$054E, $C-1, 9-1 dc.l MapUnc_CompetitionTimeBorder dc.w VRAM_Plane_A_Name_Table+$09CE, $C-1, 9-1 dc.l MapUnc_CompetitionTimeBorder dc.w VRAM_Plane_A_Name_Table+$0E4E, $C-1, 9-1 dc.l MapUnc_CompetitionTimeBorder dc.w VRAM_Plane_A_Name_Table+$12CE, $C-1, 9-1 dc.l MapUnc_CompetitionBESTTIME dc.w VRAM_Plane_A_Name_Table+$01D0, 9-1, 2-1 dc.l MapUnc_CompetitionBESTTIME dc.w VRAM_Plane_A_Name_Table+$0650, 9-1, 2-1 dc.l MapUnc_CompetitionBESTTIME dc.w VRAM_Plane_A_Name_Table+$0AD0, 9-1, 2-1 dc.l MapUnc_CompetitionBESTTIME dc.w VRAM_Plane_A_Name_Table+$0F50, 9-1, 2-1 dc.l MapUnc_CompetitionBESTTIME dc.w VRAM_Plane_A_Name_Table+$13D0, 9-1, 2-1 ObjDat_CompetitionMatchRace: dc.w $C-1 dc.l Obj_Competition_ZoneSelect dc.w $F4, 0, palette_line_0 dc.b 2, 0 dc.l Obj_Competition_StaticSprite dc.w $B0, $A9, palette_line_1 dc.b 3, 0 dc.l Obj_Competition_1PSelect dc.w $B5, $C1, palette_line_0 dc.b 0, 0 dc.l Obj_CompetitionPlayerSprite dc.w $B5, $D5, palette_line_0 dc.b 0, 0 dc.l Obj_CompetitionPlayerSprite dc.w $B5, $D5, palette_line_0 dc.b 2, 1 dc.l Obj_CompetitionPlayerSprite dc.w $B5, $D5, palette_line_0 dc.b 1, 2 dc.l Obj_Competition_StaticSprite dc.w $B2, $109, palette_line_1 dc.b 4, 0 dc.l Obj_Competition_2PSelect dc.w $B5, $121, palette_line_0 dc.b 0, 0 dc.l Obj_CompetitionPlayerSprite2P dc.w $B5, $135, palette_line_0 dc.b 0, 0 dc.l Obj_CompetitionPlayerSprite2P dc.w $B5, $135, palette_line_0 dc.b 2, 1 dc.l Obj_CompetitionPlayerSprite2P dc.w $B5, $135, palette_line_0 dc.b 1, 2 dc.l Obj_Competition_PRESSSTART dc.w $B1, $126, palette_line_1 dc.b 5, 0 ObjDat_CompetitionTimeAttack: dc.w 6-1 dc.l Obj_Competition_ZoneSelect dc.w $F4, $30, palette_line_0 dc.b 2, 0 dc.l Obj_Competition_StaticSprite dc.w $B0, 0, palette_line_1 dc.b 3, 0 dc.l Obj_Competition_1PSelect dc.w $B5, $F1, palette_line_0 dc.b 0, 0 dc.l Obj_CompetitionPlayerSprite dc.w $B5, $101, palette_line_0 dc.b 0, 0 dc.l Obj_CompetitionPlayerSprite dc.w $B5, $101, palette_line_0 dc.b 2, 1 dc.l Obj_CompetitionPlayerSprite dc.w $B5, $101, palette_line_0 dc.b 1, 2 ; --------------------------------------------------------------------------- Competition_PlayerSelect: jsr (Pal_FadeToBlack).l move #$2700,sr move.w (VDP_reg_1_command).w,d0 andi.b #$BF,d0 move.w d0,(VDP_control_port).l jsr (Clear_DisplayData).l lea (VDP_control_port).l,a6 move.w #$8004,(a6) move.w #$8230,(a6) move.w #$8407,(a6) move.w #$8700,(a6) move.w #$8B00,(a6) move.w #$8C89,(a6) move.w #$9011,(a6) jsr sub_C02A(pc) move.w #VRAM_Plane_A_Name_Table+$220,d0 jsr sub_C04C(pc) move.w #VRAM_Plane_A_Name_Table+$820,d0 jsr sub_C04C(pc) clearRAM Sprite_table_input,$400 clearRAM Object_RAM,(Kos_decomp_buffer-Object_RAM) clr.w (DMA_queue).w move.l #DMA_queue,(DMA_queue_slot).w clr.w (Level_frame_counter).w move.w #-1,(Events_bg+$10).w clr.w (Events_bg+$12).w lea (MapEni_S3MenuBG).l,a0 lea (RAM_start).l,a1 move.w #make_art_tile(ArtTile_ArtKos_S3MenuBG,0,0),d0 jsr (Eni_Decomp).l lea (RAM_start).l,a1 move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0 moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l lea (ArtKos_S3MenuBG).l,a0 ; Decompress source lea (RAM_start).l,a1 ; Decompress destination/Transfer source movea.w #tiles_to_bytes(ArtTile_ArtKos_S3MenuBG),a2 ; Transfer destination jsr KosArt_To_VDP(pc) move.l #locret_A85C,(_unkEF44_1).w move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l lea (ArtKos_CompetitionLevel).l,a0 ; Decompress source lea (RAM_start).l,a1 ; Decompress destination/Transfer source, used by the next KosArt_To_VDP also movea.w #tiles_to_bytes(ArtTile_ArtKos_Competition_LevSel),a2 ; Transfer destination jsr KosArt_To_VDP(pc) lea (ArtKos_CompetitionPlayer).l,a0 ; Decompress source movea.w #tiles_to_bytes(ArtTile_ArtKos_Competition_CharSel),a2 ; Transfer destination jsr KosArt_To_VDP(pc) move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l lea (Pal_CompetitionMenuBG).l,a0 lea (Target_palette).w,a1 moveq #bytesToLcnt($20),d0 loc_B3E8: move.l (a0)+,(a1)+ dbf d0,loc_B3E8 lea (Pal_Competition2).l,a0 moveq #bytesToLcnt($60),d0 loc_B3F6: move.l (a0)+,(a1)+ dbf d0,loc_B3F6 lea (Player_2).w,a0 lea ObjDat_B6C8(pc),a1 move.w (a1)+,d0 loc_B406: move.l (a1)+,(a0) move.l #Map_CompetitionSelect,mappings(a0) move.w (a1),x_pos(a0) move.w (a1)+,$12(a0) move.w (a1),y_pos(a0) move.w (a1)+,$16(a0) move.w (a1)+,d1 addi.w #make_art_tile(ArtTile_ArtKos_Competition_LevSel,0,1),d1 move.w d1,art_tile(a0) move.b (a1)+,mapping_frame(a0) move.b (a1)+,$2E(a0) lea next_object(a0),a0 dbf d0,loc_B406 moveq #0,d0 move.b (P1_character).w,d0 mulu.w #$55,d0 addi.b #$40,d0 move.b d0,(Reserved_object_3+objoff_2E).w moveq #0,d0 move.b (P2_character).w,d0 mulu.w #$55,d0 addi.b #$40,d0 move.b d0,(Dynamic_object_RAM+(object_size*4)+objoff_2E).w jsr (Init_SpriteTable).l jsr (Process_Sprites).l jsr (Render_Sprites).l jsr sub_C0AE(pc) jsr (Process_Sprites).l jsr (Render_Sprites).l moveq #signextendB(mus_CompetitionMenu),d0 jsr (Play_Music).l move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l move.w (VDP_reg_1_command).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l jsr (Pal_FadeFromBlack).l loc_B4A8: move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l addq.w #1,(Level_frame_counter).w jsr (Process_Sprites).l jsr sub_C0AE(pc) jsr (Render_Sprites).l move.b (Events_bg+$12).w,d0 beq.s loc_B4D4 move.b d0,(Game_mode).w rts ; --------------------------------------------------------------------------- loc_B4D4: move.w (Events_bg+$10).w,d0 tst.b (Not_ghost_flag).w bne.s loc_B4E0 lsr.w #8,d0 loc_B4E0: tst.w d0 bne.s loc_B4A8 move.w #$E00,(Current_zone_and_act).w jsr sub_C104(pc) move.b #$C,(Game_mode).w rts ; --------------------------------------------------------------------------- Obj_Competition_StaticSprite: move.w $12(a0),d0 add.w (H_scroll_buffer).w,d0 move.w d0,x_pos(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Obj_Competition_2PSelect: lea (Ctrl_2_pressed).w,a1 lea (Events_bg+$11).w,a2 lea (P2_character).w,a3 tst.b (Not_ghost_flag).w bne.s loc_B538 tst.w (Events_bg+$14).w bne.s loc_B526 tst.b (a1) smi (Not_ghost_flag).w loc_B526: moveq #0,d0 bra.w loc_B638 ; --------------------------------------------------------------------------- Obj_Competition_1PSelect: lea (Ctrl_1_pressed).w,a1 lea (Events_bg+$10).w,a2 lea (P1_character).w,a3 loc_B538: tst.w (H_scroll_buffer).w bne.w loc_B626 tst.b $2F(a0) beq.s loc_B558 btst #4,(a1) beq.w loc_B626 sf $2F(a0) st (a2) bra.w loc_B626 ; --------------------------------------------------------------------------- loc_B558: tst.b $30(a0) bne.s loc_B5D0 move.b (a1),d0 andi.w #$C,d0 beq.w loc_B602 move.l d0,-(sp) moveq #signextendB(sfx_GravityTunnel),d0 jsr (Play_SFX).l move.l (sp)+,d0 clr.b $34(a0) move.b $2E(a0),$35(a0) btst #2,d0 bne.s loc_B5AC move.b #1,$30(a0) move.b (a3),d0 addq.b #1,d0 cmpi.b #2,d0 bls.s loc_B596 moveq #0,d0 loc_B596: move.b d0,(a3) mulu.w #$55,d0 bne.s loc_B5A2 move.w #$100,d0 loc_B5A2: addi.w #$40,d0 move.w d0,$32(a0) bra.s loc_B5D0 ; --------------------------------------------------------------------------- loc_B5AC: move.b #-1,$30(a0) move.b (a3),d0 subq.b #1,d0 bcc.s loc_B5BA moveq #2,d0 loc_B5BA: move.b d0,(a3) mulu.w #$55,d0 cmpi.w #$80,d0 blo.s loc_B5C8 ext.w d0 loc_B5C8: addi.w #$40,d0 move.w d0,$32(a0) loc_B5D0: move.w $34(a0),d0 move.w $32(a0),d1 tst.b $30(a0) bmi.s loc_B5EC addq.w #5,d0 cmp.w d0,d1 bgt.s loc_B5F8 move.w d1,d0 clr.b $30(a0) bra.s loc_B5F8 ; --------------------------------------------------------------------------- loc_B5EC: subq.w #5,d0 cmp.w d0,d1 blt.s loc_B5F8 move.w d1,d0 clr.b $30(a0) loc_B5F8: move.w d0,$34(a0) move.b d0,$2E(a0) bra.s loc_B626 ; --------------------------------------------------------------------------- loc_B602: btst #4,(a1) beq.s loc_B610 move.b #$38,(Events_bg+$12).w bra.s loc_B626 ; --------------------------------------------------------------------------- loc_B610: move.b (a1),d0 andi.w #$E0,d0 beq.s loc_B626 st $2F(a0) sf (a2) moveq #signextendB(sfx_Starpost),d0 jsr (Play_SFX).l loc_B626: moveq #1,d0 tst.b $2F(a0) bne.s loc_B638 move.w (Level_frame_counter).w,d0 lsr.w #3,d0 andi.w #1,d0 loc_B638: move.b d0,mapping_frame(a0) move.w $12(a0),d0 add.w (H_scroll_buffer).w,d0 move.w d0,x_pos(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Obj_CompetitionPlayerSprite2P: tst.b (Not_ghost_flag).w bne.s Obj_CompetitionPlayerSprite rts ; --------------------------------------------------------------------------- Obj_CompetitionPlayerSprite: move.l #Map_CompetitionPlayerSprite,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_Competition_CharSel,1,0),art_tile(a0) moveq #0,d0 moveq #-$55,d1 moveq #0,d2 move.b $2E(a0),d2 loc_B66E: addi.w #object_size,d0 addi.w #$55,d1 dbf d2,loc_B66E neg.w d0 move.b $2E(a0,d0.w),d0 add.b d1,d0 jsr (GetSineCosine).l asr.w #4,d1 add.w $12(a0),d1 add.w (H_scroll_buffer).w,d1 move.w d1,x_pos(a0) asr.w #5,d0 add.w $16(a0),d0 move.w d0,y_pos(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Obj_Competition_PRESSSTART: tst.b (Not_ghost_flag).w bne.s locret_B6C6 btst #5,(Level_frame_counter+1).w beq.s locret_B6C6 move.w $12(a0),d0 add.w (H_scroll_buffer).w,d0 move.w d0,x_pos(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_B6C6: rts ; --------------------------------------------------------------------------- ObjDat_B6C8: dc.w $B-1 dc.l Obj_Competition_StaticSprite dc.w $120, $A9, palette_line_1 dc.b 3, 0 dc.l Obj_Competition_1PSelect dc.w $125, $C1, palette_line_0 dc.b 0, 0 dc.l Obj_CompetitionPlayerSprite dc.w $125, $D5, palette_line_0 dc.b 0, 0 dc.l Obj_CompetitionPlayerSprite dc.w $125, $D5, palette_line_0 dc.b 2, 1 dc.l Obj_CompetitionPlayerSprite dc.w $125, $D5, palette_line_0 dc.b 1, 2 dc.l Obj_Competition_StaticSprite dc.w $122, $109, palette_line_1 dc.b 4, 0 dc.l Obj_Competition_2PSelect dc.w $125, $121, palette_line_0 dc.b 0, 0 dc.l Obj_CompetitionPlayerSprite2P dc.w $125, $135, palette_line_0 dc.b 0, 0 dc.l Obj_CompetitionPlayerSprite2P dc.w $125, $135, palette_line_0 dc.b 2, 1 dc.l Obj_CompetitionPlayerSprite2P dc.w $125, $135, palette_line_0 dc.b 1, 2 dc.l Obj_Competition_PRESSSTART dc.w $121, $126, palette_line_1 dc.b 5, 0 ; --------------------------------------------------------------------------- Competition_Results: jsr (Pal_FadeToBlack).l move #$2700,sr move.w (VDP_reg_1_command).w,d0 andi.b #$BF,d0 move.w d0,(VDP_control_port).l jsr (Clear_DisplayData).l lea (VDP_control_port).l,a6 move.w #$8004,(a6) move.w #$8230,(a6) move.w #$8407,(a6) move.w #$8700,(a6) move.w #$8B00,(a6) move.w #$8C89,(a6) move.w #$9011,(a6) jsr sub_C02A(pc) move.w #VRAM_Plane_A_Name_Table+$1AA,d0 jsr sub_C04C(pc) move.w #VRAM_Plane_A_Name_Table+$82A,d0 jsr sub_C04C(pc) clearRAM Sprite_table_input,$400 clearRAM Object_RAM,(Kos_decomp_buffer-Object_RAM) clr.w (DMA_queue).w move.l #DMA_queue,(DMA_queue_slot).w clr.w (Level_frame_counter).w clr.w (Competition_mode).w clr.b (Level_started_flag).w move.w #$1E,(Events_bg+$16).w lea (MapEni_S3MenuBG).l,a0 lea (RAM_start).l,a1 move.w #make_art_tile(ArtTile_ArtKos_S3MenuBG,0,0),d0 jsr (Eni_Decomp).l lea (MapEni_CompetitionResultsLED).l,a0 lea (RAM_start+$1000).l,a1 move.w #make_art_tile(ArtTile_ArtKos_Competition_Results,1,1),d0 jsr (Eni_Decomp).l lea VRAMDatList_BBAC(pc),a0 jsr Copy_Listed_Data_To_VRAM(pc) jsr sub_BA04(pc) lea (ArtKos_S3MenuBG).l,a0 ; Decompress source lea (RAM_start).l,a1 ; Decompress destination/Transfer source movea.w #tiles_to_bytes(ArtTile_ArtKos_S3MenuBG),a2 ; Transfer destination jsr KosArt_To_VDP(pc) move.l #locret_A85C,(_unkEF44_1).w move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l lea (ArtKos_CompetitionLevel).l,a0 ; Decompress source lea (RAM_start).l,a1 ; Decompress destination/Transfer source, used by the next two KosArt_To_VDP also movea.w #tiles_to_bytes(ArtTile_ArtKos_Competition_LevSel),a2 ; Transfer destination jsr KosArt_To_VDP(pc) lea (ArtKos_CompetitionResults).l,a0 ; Decompress source movea.w #tiles_to_bytes(ArtTile_ArtKos_Competition_Results),a2 ; Transfer destination jsr KosArt_To_VDP(pc) lea (ArtKos_CompetitionPlayer).l,a0 ; Decompress source movea.w #tiles_to_bytes(ArtTile_ArtKos_Competition_CharSel),a2 ; Transfer destination jsr KosArt_To_VDP(pc) move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l lea (Pal_CompetitionMenuBG).l,a0 lea (Target_palette).w,a1 moveq #bytesToLcnt($20),d0 loc_B888: move.l (a0)+,(a1)+ dbf d0,loc_B888 lea (Pal_Competition2).l,a0 moveq #bytesToLcnt($40),d0 loc_B896: move.l (a0)+,(a1)+ dbf d0,loc_B896 lea (Pal_CompetitionResults).l,a0 moveq #bytesToLcnt($20),d0 loc_B8A4: move.l (a0)+,(a1)+ dbf d0,loc_B8A4 lea (Object_RAM).w,a0 lea ObjDat_BB4A(pc),a1 move.w (a1)+,d0 loc_B8B4: move.l (a1)+,(a0) move.l #Map_CompetitionSelect,mappings(a0) move.w (a1),x_pos(a0) move.w (a1)+,$12(a0) move.w (a1),y_pos(a0) move.w (a1)+,$16(a0) move.w (a1)+,d1 addi.w #make_art_tile(ArtTile_ArtKos_Competition_LevSel,0,1),d1 move.w d1,art_tile(a0) move.b (a1)+,mapping_frame(a0) move.b (a1)+,$2E(a0) lea next_object(a0),a0 dbf d0,loc_B8B4 jsr (Init_SpriteTable).l jsr (Process_Sprites).l jsr (Render_Sprites).l moveq #signextendB(mus_Continue),d0 jsr (Play_Music).l move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l move.w (VDP_reg_1_command).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l jsr (Pal_FadeFromBlack).l loc_B922: move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l addq.w #1,(Level_frame_counter).w move.w (_unkEEA0).w,d7 beq.s loc_B952 btst #3,(Level_frame_counter+1).w bne.s loc_B94A lea (Plane_buffer+$20).w,a1 jsr sub_B0A6(pc) bra.s loc_B952 ; --------------------------------------------------------------------------- loc_B94A: move.l (_unkEE98).w,d6 jsr sub_B066(pc) loc_B952: tst.w (Events_bg+$16).w beq.s loc_B95E subq.w #1,(Events_bg+$16).w bra.s loc_B996 ; --------------------------------------------------------------------------- loc_B95E: move.b (Ctrl_1_pressed).w,d0 tst.b (Not_ghost_flag).w beq.s loc_B96C or.b (Ctrl_2_pressed).w,d0 loc_B96C: move.w (H_scroll_buffer).w,d1 beq.s loc_B97A cmpi.w #$FF78,d1 beq.s loc_B988 bra.s loc_B980 ; --------------------------------------------------------------------------- loc_B97A: andi.w #button_start_mask|button_A_mask|button_C_mask,d0 beq.s loc_B996 loc_B980: subq.w #8,d1 move.w d1,(H_scroll_buffer).w bra.s loc_B996 ; --------------------------------------------------------------------------- loc_B988: andi.w #button_start_mask|button_A_mask|button_C_mask,d0 beq.s loc_B996 move.b #$38,(Game_mode).w rts ; --------------------------------------------------------------------------- loc_B996: jsr (Process_Sprites).l jsr (Render_Sprites).l bra.w loc_B922 ; --------------------------------------------------------------------------- Obj_Competition_B9A6: move.l #Map_CompetitionPlayerSprite,mappings(a0) move.w #make_art_tile(ArtTile_ArtKos_Competition_CharSel,1,1),art_tile(a0) move.b (P1_character).w,d0 tst.b $2E(a0) beq.s loc_B9C2 move.b (P2_character).w,d0 loc_B9C2: move.b d0,mapping_frame(a0) jmp Obj_Competition_StaticSprite(pc) ; --------------------------------------------------------------------------- Obj_Competition_B9CA: move.w #make_art_tile(ArtTile_ArtKos_Competition_Results,1,1),art_tile(a0) move.b (_unkEEA2).w,d0 move.b (_unkEEA2+1).w,d1 tst.b $2E(a0) beq.s loc_B9E0 exg d0,d1 loc_B9E0: moveq #$D,d2 cmp.b d0,d1 beq.s loc_B9EC bcs.s loc_B9EA addq.w #1,d2 loc_B9EA: subq.b #2,d2 loc_B9EC: move.b d2,mapping_frame(a0) cmpi.b #$B,d2 bne.w Obj_Competition_StaticSprite btst #3,(Level_frame_counter+1).w bne.w Obj_Competition_StaticSprite rts ; =============== S U B R O U T I N E ======================================= sub_BA04: lea ($FF7800).l,a0 move.w #$C15A,d7 jsr sub_BAEE(pc) move.w #$C7DA,d7 jsr sub_BAEE(pc) lea ($FF7800).l,a0 jsr sub_BB04(pc) move.w #$C65A,d7 move.l d6,(_unkEE98).w move.w d7,(_unkEEA0).w jsr sub_B066(pc) jsr sub_BB04(pc) move.w #$CCDA,d7 cmp.l (_unkEE98).w,d6 bhi.s loc_BA52 bne.s loc_BA4A clr.w (_unkEEA0).w bra.s loc_BA52 ; --------------------------------------------------------------------------- loc_BA4A: move.l d6,(_unkEE98).w move.w d7,(_unkEEA0).w loc_BA52: jsr sub_B066(pc) clr.w (_unkEEA2).w lea ($FF7800).l,a0 move.l #vdpComm(VRAM_Plane_A_Name_Table+$148,VRAM,WRITE),d5 moveq #5-1,d7 loc_BA68: lea (MapUnc_ResultsWin).l,a1 lea (MapUnc_ResultsLose).l,a2 addq.b #1,(_unkEEA2).w move.l (a0)+,d0 cmp.l x_pos(a0),d0 beq.s loc_BA8E bcs.s loc_BA9A exg a1,a2 subq.b #1,(_unkEEA2).w addq.b #1,(_unkEEA2+1).w bra.s loc_BA9A ; --------------------------------------------------------------------------- loc_BA8E: lea (MapUnc_ResultsTie).l,a1 movea.l a1,a2 subq.b #1,(_unkEEA2).w loc_BA9A: move.l d5,d0 moveq #2-1,d1 moveq #2-1,d2 jsr (Plane_Map_To_VRAM).l movea.l a2,a1 move.l d5,d0 addi.l #$680<<16,d0 moveq #2-1,d1 moveq #2-1,d2 jsr (Plane_Map_To_VRAM).l addi.l #$100<<16,d5 dbf d7,loc_BA68 move.w (_unkEEA0).w,d7 beq.s locret_BAEC move.l (_unkEE98).w,d6 jsr sub_B066(pc) lea (Plane_buffer).w,a0 lea $20(a0),a1 moveq #$10-1,d0 loc_BADC: move.w (a0)+,d1 andi.w #$9FFF,d1 ori.w #$6000,d1 move.w d1,(a1)+ dbf d0,loc_BADC locret_BAEC: rts ; End of function sub_BA04 ; =============== S U B R O U T I N E ======================================= sub_BAEE: moveq #5-1,d0 loc_BAF0: move.w d0,-(sp) move.l (a0)+,d6 jsr sub_B066(pc) addi.w #$100,d7 move.w (sp)+,d0 dbf d0,loc_BAF0 rts ; End of function sub_BAEE ; =============== S U B R O U T I N E ======================================= sub_BB04: clr.l (_unkEF40_1).w moveq #5-1,d7 loc_BB0A: move.l (a0)+,d6 lea (_unkEF44_2).w,a1 add.b d6,-(a1) cmpi.b #100,(a1) blo.s loc_BB20 subi.b #100,(a1) addq.b #1,-1(a1) loc_BB20: lsr.l #8,d6 add.b d6,-(a1) cmpi.b #60,(a1) blo.s loc_BB32 subi.b #60,(a1) addq.b #1,-1(a1) loc_BB32: lsr.l #8,d6 add.b d6,-(a1) cmpi.b #100,(a1) blo.s loc_BB40 move.b #99,(a1) loc_BB40: dbf d7,loc_BB0A move.l (_unkEF40_1).w,d6 rts ; End of function sub_BB04 ; --------------------------------------------------------------------------- ObjDat_BB4A: dc.w 8-1 dc.l Obj_Competition_StaticSprite dc.w $148, $A1, palette_line_1 dc.b 3, 0 dc.l Obj_Competition_StaticSprite dc.w $14D, $B9, palette_line_0 dc.b 0, 0 dc.l Obj_Competition_B9A6 dc.w $14D, $D3, palette_line_0 dc.b 0, 0 dc.l Obj_Competition_B9CA dc.w $CC, $BC, palette_line_0 dc.b 0, 0 dc.l Obj_Competition_StaticSprite dc.w $14A, $109, palette_line_1 dc.b 4, 0 dc.l Obj_Competition_StaticSprite dc.w $14D, $121, palette_line_0 dc.b 0, 0 dc.l Obj_Competition_B9A6 dc.w $14D, $13B, palette_line_0 dc.b 0, 1 dc.l Obj_Competition_B9CA dc.w $CC, $124, palette_line_0 dc.b 0, 1 VRAMDatList_BBAC: dc.w 9-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_B_Name_Table+$000, $28-1, $1C-1 dc.l RAM_start+$1000 dc.w VRAM_Plane_A_Name_Table+$204, $F-1, 6-1 dc.l RAM_start+$1000 dc.w VRAM_Plane_A_Name_Table+$884, $F-1, 6-1 dc.l MapUnc_CompetitionResultsLetters dc.w VRAM_Plane_A_Name_Table+$142, 2-1, $A-1 dc.l MapUnc_CompetitionResultsLetters dc.w VRAM_Plane_A_Name_Table+$7C2, 2-1, $A-1 dc.l MapUnc_CompetitionResultsDividers dc.w VRAM_Plane_A_Name_Table+$152, 4-1, $A-1 dc.l MapUnc_CompetitionResultsDividers dc.w VRAM_Plane_A_Name_Table+$7D2, 4-1, $A-1 dc.l MapUnc_CompetitionResultsTOTAL dc.w VRAM_Plane_A_Name_Table+$650, 5-1, 2-1 dc.l MapUnc_CompetitionResultsTOTAL dc.w VRAM_Plane_A_Name_Table+$CD0, 5-1, 2-1 ; --------------------------------------------------------------------------- TimeAttack_Records: jsr (Pal_FadeToBlack).l move #$2700,sr move.w (VDP_reg_1_command).w,d0 andi.b #$BF,d0 move.w d0,(VDP_control_port).l jsr (Clear_DisplayData).l lea (VDP_control_port).l,a6 move.w #$8004,(a6) move.w #$8230,(a6) move.w #$8407,(a6) move.w #$8700,(a6) move.w #$8B00,(a6) move.w #$8C89,(a6) move.w #$9011,(a6) jsr sub_C02A(pc) move.w #VRAM_Plane_A_Name_Table+$1AA,d0 jsr sub_C04C(pc) clearRAM Sprite_table_input,$400 clearRAM Object_RAM,(Kos_decomp_buffer-Object_RAM) clr.w (DMA_queue).w move.l #DMA_queue,(DMA_queue_slot).w clr.w (Level_frame_counter).w clr.w (Competition_mode).w clr.b (Level_started_flag).w move.w #$1E,(Events_bg+$16).w move.w #$FF78,(H_scroll_buffer).w lea (MapEni_S3MenuBG).l,a0 lea (RAM_start).l,a1 move.w #make_art_tile(ArtTile_ArtKos_S3MenuBG,0,0),d0 jsr (Eni_Decomp).l lea VRAMDatList_BF96(pc),a0 jsr Copy_Listed_Data_To_VRAM(pc) moveq #0,d0 move.b (Current_zone).w,d0 subi.w #$E,d0 lsl.w #2,d0 lea CompTimeAttack_LevelNameMaps(pc),a1 movea.l (a1,d0.w),a1 move.l #vdpComm(VRAM_Plane_A_Name_Table+$826,VRAM,WRITE),d0 moveq #$D-1,d1 moveq #2-1,d2 jsr (Plane_Map_To_VRAM).l jsr sub_BEB2(pc) move.l #vdpComm(tiles_to_bytes($58D),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_ContinueDigits).l,a0 jsr (Nem_Decomp).l move.l #vdpComm(tiles_to_bytes($5A1),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_S38x16Font).l,a0 jsr (Nem_Decomp).l lea (ArtKos_S3MenuBG).l,a0 ; Decompress source lea (RAM_start).l,a1 ; Decompress destination/Transfer source movea.w #tiles_to_bytes(ArtTile_ArtKos_S3MenuBG),a2 ; Transfer destination jsr KosArt_To_VDP(pc) move.l #locret_A85C,(_unkEF44_1).w move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l lea (ArtKos_CompetitionLevel).l,a0 ; Decompress source lea (RAM_start).l,a1 ; Decompress destination/Transfer source, used by the next two KosArt_To_VDP also movea.w #tiles_to_bytes(ArtTile_ArtKos_Competition_LevSel),a2 ; Transfer destination jsr KosArt_To_VDP(pc) lea (ArtKos_CompetitionResults).l,a0 ; Decompress source movea.w #tiles_to_bytes(ArtTile_ArtKos_Competition_Results),a2 ; Transfer destination jsr KosArt_To_VDP(pc) lea (ArtKos_CompetitionPlayer).l,a0 ; Decompress source movea.w #tiles_to_bytes(ArtTile_ArtKos_Competition_CharSel),a2 ; Transfer destination jsr KosArt_To_VDP(pc) move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l lea (ArtKos_SSResultsGeneral).l,a0 lea (RAM_start+$20).l,a1 jsr (Kos_Decomp).l lea (ArtKos_SSResultsTKIcons).l,a0 jsr (Kos_Decomp).l move #$2700,sr move.l #vdpComm(tiles_to_bytes($572),VRAM,WRITE),(VDP_control_port).l lea (RAM_start+$F60).l,a0 lea (VDP_data_port).l,a6 move.w #bytesToLcnt(tiles_to_bytes($1B)),d0 loc_BDAA: move.l (a0)+,(a6) dbf d0,loc_BDAA lea (Pal_CompetitionMenuBG).l,a0 lea (Target_palette).w,a1 moveq #bytesToLcnt($20),d0 loc_BDBC: move.l (a0)+,(a1)+ dbf d0,loc_BDBC lea (Pal_Competition2).l,a0 moveq #bytesToLcnt($40),d0 loc_BDCA: move.l (a0)+,(a1)+ dbf d0,loc_BDCA lea (Pal_CompetitionTimeAttack).l,a0 moveq #bytesToLcnt($20),d0 loc_BDD8: move.l (a0)+,(a1)+ dbf d0,loc_BDD8 lea (Object_RAM).w,a0 lea ObjDat_BF58(pc),a1 move.w (a1)+,d0 loc_BDE8: move.l (a1)+,(a0) move.l #Map_CompetitionSelect,mappings(a0) move.w (a1),x_pos(a0) move.w (a1)+,$12(a0) move.w (a1),y_pos(a0) move.w (a1)+,$16(a0) move.w (a1)+,d1 addi.w #make_art_tile($29F,0,1),d1 move.w d1,art_tile(a0) move.b (a1)+,mapping_frame(a0) move.b (a1)+,$2E(a0) lea next_object(a0),a0 dbf d0,loc_BDE8 jsr (Init_SpriteTable).l jsr (Process_Sprites).l jsr (Render_Sprites).l moveq #signextendB(mus_Continue),d0 jsr (Play_Music).l move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l move.w (VDP_reg_1_command).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l jsr (Pal_FadeFromBlack).l loc_BE56: move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l addq.w #1,(Level_frame_counter).w move.w (_unkEEA0).w,d7 beq.s loc_BE86 btst #3,(Level_frame_counter+1).w bne.s loc_BE7E lea (Plane_buffer+$20).w,a1 jsr sub_B0A6(pc) bra.s loc_BE86 ; --------------------------------------------------------------------------- loc_BE7E: move.l (_unkEE98).w,d6 jsr sub_B066(pc) loc_BE86: tst.w (Events_bg+$16).w beq.s loc_BE92 subq.w #1,(Events_bg+$16).w bra.s loc_BEA4 ; --------------------------------------------------------------------------- loc_BE92: move.b (Ctrl_1_pressed).w,d0 andi.w #button_start_mask|button_A_mask|button_C_mask,d0 beq.s loc_BEA4 move.b #$C0,(Game_mode).w rts ; --------------------------------------------------------------------------- loc_BEA4: jsr (Process_Sprites).l jsr (Render_Sprites).l bra.s loc_BE56 ; =============== S U B R O U T I N E ======================================= sub_BEB2: lea ($FF7828).l,a0 move.w #VRAM_Plane_A_Name_Table+$15A,d7 moveq #6-1,d0 jsr loc_BAF0(pc) moveq #0,d0 move.b (Current_zone).w,d0 subi.w #$E,d0 lsl.w #4,d0 lea (Competition_saved_data).w,a0 adda.w d0,a0 move.w #VRAM_Plane_A_Name_Table+$95A,d7 move.l (a0)+,d6 jsr sub_B066(pc) addi.w #$180,d7 move.l (a0)+,d6 jsr sub_B066(pc) addi.w #$180,d7 move.l (a0)+,d6 jsr sub_B066(pc) clr.w (_unkEEA0).w rts ; End of function sub_BEB2 ; --------------------------------------------------------------------------- Obj_Competition_BEF8: move.l #Map_Results,mappings(a0) move.w #make_art_tile($7D5,0,1)|$1800,art_tile(a0) moveq #0,d0 move.b (Current_zone).w,d0 subi.w #$E,d0 lsl.w #4,d0 lea (Competition_saved_data).w,a1 lea $C(a1,d0.w),a1 moveq #0,d0 move.b $2E(a0),d0 move.b (a1,d0.w),d0 cmpi.w #2,d0 bne.s loc_BF30 addi.w #palette_line_1,art_tile(a0) loc_BF30: addi.w #$29,d0 move.b d0,mapping_frame(a0) move.l #loc_BF3E,(a0) loc_BF3E: move.b (Competition_time_attack_new_top_record).w,d0 cmp.b $2E(a0),d0 bne.s loc_BF50 btst #3,(Level_frame_counter+1).w beq.s locret_BF56 loc_BF50: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_BF56: rts ; --------------------------------------------------------------------------- ObjDat_BF58: dc.w 5-1 dc.l Obj_Competition_StaticSprite dc.w $14D, $B9, palette_line_0 dc.b 0, 0 dc.l Obj_Competition_B9A6 dc.w $14D, $CB, palette_line_0 dc.b 0, 0 dc.l Obj_Competition_BEF8 dc.w $130, $120, palette_line_0 dc.b 0, 0 dc.l Obj_Competition_BEF8 dc.w $130, $138, palette_line_0 dc.b 0, 1 dc.l Obj_Competition_BEF8 dc.w $130, $150, palette_line_0 dc.b 0, 2 VRAMDatList_BF96: dc.w 9-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_B_Name_Table+$000, $28-1, $1C-1 dc.l MapUnc_CompetitionLAPNum dc.w VRAM_Plane_A_Name_Table+$144, 5-1, $A-1 dc.l MapUnc_CompetitionResultsDividers dc.w VRAM_Plane_A_Name_Table+$152, 4-1, $A-1 dc.l MapUnc_CompetitionResultsTOTAL dc.w VRAM_Plane_A_Name_Table+$650, 5-1, 2-1 dc.l MapUnc_CompetitionResultsDividers dc.w VRAM_Plane_A_Name_Table+$952, 4-1, 2-1 dc.l MapUnc_CompetitionResultsDividers dc.w VRAM_Plane_A_Name_Table+$AD2, 4-1, 2-1 dc.l MapUnc_CompetitionResultsDividers dc.w VRAM_Plane_A_Name_Table+$C52, 4-1, 2-1 dc.l MapUnc_CompetitionRECORDS dc.w VRAM_Plane_A_Name_Table+$92C, 7-1, 2-1 dc.l MapUnc_Competition1st2nd3rd dc.w VRAM_Plane_A_Name_Table+$944, 3-1, 8-1 CompTimeAttack_LevelNameMaps: dc.l MapUnc_CompetitionAZURELAKE dc.l MapUnc_CompetitionBALLOONPARK dc.l MapUnc_CompetitionDESERTPALACE dc.l MapUnc_CompetitionCHROMEGADGET dc.l MapUnc_CompetitionENDLESSMINE ; =============== S U B R O U T I N E ======================================= KosArt_To_VDP: movea.l a1,a3 ; a1 will be changed by Kos_Decomp, so we're backing it up to a3 jsr (Kos_Decomp).l move.l a3,d1 ; move the backed-up a1 to d1 andi.l #$FFFFFF,d1 ; d1 will be used in the DMA transfer as the Source Address move.l a1,d3 ; move end address of decompressed art to d3 sub.l a3,d3 ; subtract 'start address of decompressed art' from 'end address of decompressed art', giving you the size of the decompressed art lsr.l #1,d3 ; divide size of decompressed art by two, d3 will be used in the DMA transfer as the Transfer Length (size/2) move.w a2,d2 ; move VRAM address to d2, d2 will be used in the DMA transfer as the Destination Address movea.l a1,a3 ; backup a1, this allows the same address to be used by multiple calls to KosArt_To_VDP without constant redefining jsr (Add_To_DMA_Queue).l ; transfer *Transfer Length* of data from *Source Address* to *Destination Address* movea.l a3,a1 ; restore a1 rts ; End of function KosArt_To_VDP ; =============== S U B R O U T I N E ======================================= sub_C02A: move.l #$80008000,d0 move.w #$800-1,d1 move.l #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE),(VDP_control_port).l lea (VDP_data_port).l,a6 .loop: move.l d0,(a6) dbf d1,.loop rts ; End of function sub_C02A ; =============== S U B R O U T I N E ======================================= sub_C04C: moveq #8-1,d2 lea (VDP_data_port).l,a6 moveq #0,d1 .loop: move.w d0,d3 bsr.s sub_C068 addi.w #$80,d0 andi.w #$DFFF,d0 dbf d2,.loop rts ; End of function sub_C04C ; =============== S U B R O U T I N E ======================================= sub_C068: swap d3 clr.w d3 swap d3 lsl.l #2,d3 lsr.w #2,d3 ori.w #$4000,d3 swap d3 move.l d3,VDP_control_port-VDP_data_port(a6) move.l d1,(a6) move.l d1,(a6) move.l d1,(a6) move.l d1,(a6) move.w d1,(a6) rts ; End of function sub_C068 ; =============== S U B R O U T I N E ======================================= Copy_Listed_Data_To_VRAM: move.w (a0)+,d7 .loop: movea.l (a0)+,a1 move.w (a0)+,d0 swap d0 clr.w d0 swap d0 lsl.l #2,d0 lsr.w #2,d0 ori.w #$4000,d0 swap d0 move.w (a0)+,d1 move.w (a0)+,d2 jsr (Plane_Map_To_VRAM).l dbf d7,.loop rts ; End of function Copy_Listed_Data_To_VRAM ; =============== S U B R O U T I N E ======================================= sub_C0AE: lea (Dynamic_object_RAM).w,a0 bsr.s sub_C0B8 lea (Dynamic_object_RAM+(object_size*5)).w,a0 ; End of function sub_C0AE ; =============== S U B R O U T I N E ======================================= sub_C0B8: lea next_object(a0),a1 lea next_object(a1),a2 bsr.s sub_C0EA bsr.s sub_C0EA move.w #$80,priority(a0) move.w #$100,priority(a1) move.w #$180,priority(a2) bset #7,art_tile(a0) bclr #7,art_tile(a1) bclr #7,art_tile(a2) rts ; End of function sub_C0B8 ; =============== S U B R O U T I N E ======================================= sub_C0EA: move.w y_pos(a0),d0 cmp.w y_pos(a1),d0 bgt.s loc_C0F6 exg a0,a1 loc_C0F6: move.w y_pos(a1),d0 cmp.w y_pos(a2),d0 bgt.s locret_C102 exg a1,a2 locret_C102: rts ; End of function sub_C0EA ; =============== S U B R O U T I N E ======================================= sub_C104: move.w #1,(Competition_mode).w bra.s loc_C110 ; --------------------------------------------------------------------------- Set_Lives_and_Continues: clr.w (Competition_mode).w loc_C110: move.b #3,(Life_count).w move.b #3,(Life_count_P2).w moveq #0,d0 move.b d0,(Last_star_post_hit).w move.b d0,(Special_bonus_entry_flag).w move.w d0,(Ring_count).w move.l d0,(Timer).w move.l d0,(Score).w move.w d0,(Ring_count_P2).w move.l d0,(Timer_P2).w move.l d0,(Score_P2).w move.b d0,(Continue_count).w move.l #5000,(Next_extra_life_score).w move.l #5000,(Next_extra_life_score_P2).w rts ; End of function sub_C104 ; =============== S U B R O U T I N E ======================================= SRAM_Load: tst.w (SK_alone_flag).w bne.w locret_C260 ; Don't bother if we're playing only Sonic and Knuckles clr.w (SRAM_mask_interrupts_flag).w ; No interrupt shenanigans needed lea ($200011).l,a0 lea ($2000BD).l,a1 lea (Competition_saved_data).w,a2 moveq #$29,d0 move.w #$4C44,d1 ; RAM integrity value jsr Get_From_SRAM(pc) beq.s loc_C190 ; If the data read was successful, branch lea SaveData_GeneralDefault(pc),a0 lea (Competition_saved_data).w,a1 moveq #$29-1,d0 loc_C186: move.w (a0)+,(a1)+ ; Reset the general save data to the default dbf d0,loc_C186 jsr Write_SaveGeneral2(pc) ; Write default data back to SRAM loc_C190: lea ($200281).l,a0 lea ($20032D).l,a1 lea (Saved_data).w,a2 moveq #$29,d0 move.w #$4244,d1 ; RAM integrity value for save game data jsr Get_From_SRAM(pc) bne.s loc_C1C0 ; If the data read was not successful, branch lea (Saved_data).w,a0 moveq #8-1,d0 loc_C1B2: tst.b (a0) bpl.w loc_C256 ; If any of the save files are active, then we're done here lea $A(a0),a0 dbf d0,loc_C1B2 ; if not then we load them up with default data loc_C1C0: lea SaveData_GameDefault(pc),a0 lea (Saved_data).w,a1 moveq #bytesToWcnt(($A*8)+2),d0 loc_C1CA: move.w (a0)+,(a1)+ dbf d0,loc_C1CA ; Write default game data lea ($200169).l,a0 lea ($2001F5).l,a1 lea ($FF0000).l,a2 ; Attempt to see if there's any existing S3 save data moveq #$19,d0 move.w #$4244,d1 jsr Get_From_SRAM(pc) bne.s loc_C252 ; If write was not successful, branch lea (Saved_data).w,a0 ; If there's valid data from Sonic 3, we'll now go through the process of migrating it to SK lea ($FF0000).l,a1 lea SaveData_S3LevRef(pc),a2 moveq #6-1,d0 loc_C1FE: tst.b (a1) bmi.s loc_C248 ; If not an active save slot, branch clr.b (a0) move.b 1(a1),4(a0) ; Special stage ring memory migration move.b 7(a1),5(a0) move.b 2(a1),d1 lsl.b #4,d1 move.b d1,2(a0) ; Character ID is stored differently moveq #0,d1 move.b 3(a1),d1 move.b (a2,d1.w),3(a0) ; Current level IDs are changed slightly between S3 and SK and need to be converted move.b 4(a1),d1 or.b d1,2(a0) ; The last completed special stage was previously its own byte move.b 6(a1),d1 moveq #0,d2 moveq #7-1,d3 loc_C236: lsl.b #1,d1 bcc.s loc_C23E ori.w #1,d2 loc_C23E: lsl.w #2,d2 dbf d3,loc_C236 move.w d2,6(a0) ; The chaos/super emerald data is interleaved in SK and needs to be converted loc_C248: lea $A(a0),a0 addq.w #8,a1 dbf d0,loc_C1FE loc_C252: jsr Write_SaveGame(pc) loc_C256: clr.w (Dataselect_nosave_player).w move.b #1,(Dataselect_entry).w locret_C260: rts ; End of function SRAM_Load ; --------------------------------------------------------------------------- SaveData_GeneralDefault: dc.w $8000, 0, $8000, 0, $8000, 0, 1, $200 dc.w $8000, 0, $8000, 0, $8000, 0, 1, $200 dc.w $8000, 0, $8000, 0, $8000, 0, 1, $200 dc.w $8000, 0, $8000, 0, $8000, 0, 1, $200 dc.w $8000, 0, $8000, 0, $8000, 0, 1, $200 dc.w $4C44 SaveData_GameDefault: dc.w $8000, 0, 0, 0, $300 dc.w $8000, 0, 0, 0, $300 dc.w $8000, 0, 0, 0, $300 dc.w $8000, 0, 0, 0, $300 dc.w $8000, 0, 0, 0, $300 dc.w $8000, 0, 0, 0, $300 dc.w $8000, 0, 0, 0, $300 dc.w $8000, 0, 0, 0, $300 dc.w $4244 SaveData_S3LevRef: dc.b 0 dc.b 1 dc.b 2 dc.b 3 dc.b 0 dc.b 4 dc.b 5 dc.b 6 even ; =============== S U B R O U T I N E ======================================= Get_From_SRAM: movea.l a2,a3 move.w d0,d2 bsr.s Read_SRAM beq.s .end movea.l a1,a0 movea.l a3,a2 move.w d2,d0 bsr.s Read_SRAM .end: rts ; End of function Get_From_SRAM ; =============== S U B R O U T I N E ======================================= Read_SRAM: tst.w (SRAM_mask_interrupts_flag).w beq.s loc_C32A move #$2700,sr ; Disable interrupts if EF56 is set loc_C32A: move.b #1,(SRAM_access_flag).l ; Access SRAM movea.l a2,a6 move.w d0,d6 loc_C336: movep.w 0(a0),d3 move.w d3,(a2)+ ; Read data from SRAM addq.w #4,a0 dbf d0,loc_C336 move.b #0,(SRAM_access_flag).l ; No longer access SRAM tst.w (SRAM_mask_interrupts_flag).w beq.s loc_C354 move #$2300,sr ; Restore interrupts if EF56 is set loc_C354: subq.w #1,d6 bsr.s Create_SRAMChecksum ; Get the checksum of the given data cmp.w (a6),d7 ; Compare the result bne.s locret_C360 cmp.w -2(a6),d1 ; Also compare the data before with the data given in d1 locret_C360: rts ; End of function Read_SRAM ; =============== S U B R O U T I N E ======================================= Create_SRAMChecksum: moveq #0,d7 .loop: move.w (a6)+,d5 eor.w d5,d7 lsr.w #1,d7 bcc.s .skip eori.w #$8810,d7 .skip: dbf d6,.loop rts ; End of function Create_SRAMChecksum ; =============== S U B R O U T I N E ======================================= Write_SRAM: movea.l a2,a6 move.w d0,d6 subq.w #1,d6 bsr.s Create_SRAMChecksum move.w d7,(a6) tst.w (SRAM_mask_interrupts_flag).w beq.s loc_C38A move #$2700,sr ; If EF56 is set, disable interrupts while saving is occuring loc_C38A: move.b #1,(SRAM_access_flag).l ; Send I/O signal to SRAM, mapping it to $200001 movea.l a2,a3 move.w d0,d1 loc_C396: move.w (a2)+,d2 movep.w d2,0(a0) ; Copy data to SRAM addq.w #4,a0 dbf d0,loc_C396 loc_C3A2: move.w (a3)+,d2 movep.w d2,0(a1) ; Copy data to backup SRAM addq.w #4,a1 dbf d1,loc_C3A2 move.b #0,(SRAM_access_flag).l ; Stop SRAM access tst.w (SRAM_mask_interrupts_flag).w beq.s locret_C3C0 move #$2300,sr ; Restore interrupts if EF56 was set locret_C3C0: rts ; End of function Write_SRAM ; =============== S U B R O U T I N E ======================================= Write_SaveGeneral: st (SRAM_mask_interrupts_flag).w ; End of function Write_SaveGeneral ; =============== S U B R O U T I N E ======================================= Write_SaveGeneral2: move.l a0,-(sp) move.w d7,-(sp) lea ($200011).l,a0 ; Save general SRAM lea ($2000BD).l,a1 ; Save general Backup SRAM lea (Competition_saved_data).w,a2 ; Save general RAM moveq #$2A-1,d0 bsr.s Write_SRAM move.w (sp)+,d7 movea.l (sp)+,a0 rts ; End of function Write_SaveGeneral2 ; =============== S U B R O U T I N E ======================================= Write_SaveGame: move.l a0,-(sp) move.w d7,-(sp) lea ($200281).l,a0 ; Save game SRAM lea ($20032D).l,a1 ; Save game backup SRAM lea (Saved_data).w,a2 ; Save game RAM moveq #$2A-1,d0 jsr Write_SRAM(pc) move.w (sp)+,d7 movea.l (sp)+,a0 rts ; End of function Write_SaveGame ; --------------------------------------------------------------------------- SaveGame_NextLevel: dc.b 1, 1 dc.b 2, 2 dc.b 3, 3 dc.b 4, 4 dc.b 8, 8 dc.b 5, 5 dc.b 6, 6 dc.b 7, 7 dc.b 9, 9 dc.b $A, $A dc.b $C, $C dc.b $D, $D dc.b $E, $E dc.b 0, 0 dc.b 0, 0 dc.b 0, 0 dc.b 0, 0 dc.b 0, 0 dc.b 0, 0 dc.b 0, 0 dc.b 0, 0 dc.b 0, 0 dc.b $A, $B dc.b $D, 0 even ; =============== S U B R O U T I N E ======================================= SaveGame: tst.w (SK_alone_flag).w bne.w loc_C4CC ; If this is SK, saving is disabled move.l (Save_pointer).w,d0 beq.w loc_C4CC ; If not playing on a save file, get out movea.l d0,a1 move.w (Current_zone_and_act).w,d0 ror.b #1,d0 lsr.w #7,d0 move.b SaveGame_NextLevel(pc,d0.w),d0 move.b (a1),d1 andi.w #3,d1 beq.s loc_C464 cmp.b 3(a1),d0 ; If game is complete, make it uncomplete if last level is less than the current level blo.s loc_C4B4 ; Think of, say, getting all the super emeralds then going to Doomsday on a completed save file andi.b #$FC,(a1) loc_C464: move.b d0,3(a1) ; Move next level into current level cmpi.w #3,(Player_mode).w bne.s loc_C478 cmpi.b #$C,d0 blo.s loc_C4B0 bra.s loc_C498 ; If playing as Knuckles and level code is Death Egg or higher, make it a completed save file ; --------------------------------------------------------------------------- loc_C478: cmpi.w #2,(Player_mode).w bne.s loc_C488 cmpi.b #$D,d0 blo.s loc_C4B0 bra.s loc_C498 ; If playing as Tails and level code is Doomsday or higher, make it a completed save file ; --------------------------------------------------------------------------- loc_C488: cmpi.b #$D,d0 bhi.s loc_C498 ; If next level above Doomsday's code, make it a completed save file bne.s loc_C4B0 cmpi.b #7,(Chaos_emerald_count).w ; If next level IS Doomsday but the emeralds aren't collected, make it a completed save file bhs.s loc_C4B0 loc_C498: moveq #1,d0 cmpi.b #7,(Chaos_emerald_count).w blo.s loc_C4AE ; code 1 is completed without all emeralds addq.b #1,d0 cmpi.b #7,(Super_emerald_count).w blo.s loc_C4AE ; code 2 is completed with all chaos emeralds addq.b #1,d0 ; code 3 is completed with all super emeralds loc_C4AE: move.b d0,(a1) loc_C4B0: clr.w 4(a1) ; Clear the special stage ring collection memory loc_C4B4: move.b (Life_count).w,d0 ; Get number of lives cmpi.b #99,d0 bls.s loc_C4C0 moveq #99,d0 loc_C4C0: move.b d0,8(a1) ; Put number of lives into memory move.b d0,(Life_count).w jsr Write_SaveGame(pc) loc_C4CC: clr.l (Collected_special_ring_array).w ; Clear special stage ring collection RAM rts ; End of function SaveGame ; =============== S U B R O U T I N E ======================================= SaveGame_SpecialStage: tst.w (SK_alone_flag).w bne.s locret_C530 ; If playing Sonic and Knuckles, don't bother move.l (Save_pointer).w,d0 beq.s locret_C530 movea.l d0,a1 ; Get address of save slot tst.b (SK_special_stage_flag).w bne.s loc_C4F8 andi.b #$F0,2(a1) move.b (Current_special_stage).w,d0 andi.b #$F,d0 or.b d0,2(a1) ; Write last played special stage only if Sonic 3 special stages are in effect loc_C4F8: lea (Collected_emeralds_array).w,a2 moveq #0,d0 moveq #7-1,d1 loc_C500: move.b (a2)+,d2 andi.b #3,d2 or.b d2,d0 lsl.w #2,d0 dbf d1,loc_C500 move.w d0,6(a1) ; Compress emerald collection RAM and put it into Save Game move.w (Collected_special_ring_array+2).w,4(a1) ; Special stage entry ring memory is copied as well move.b (Continue_count).w,d0 cmpi.b #99,d0 bls.s loc_C524 moveq #99,d0 loc_C524: move.b d0,9(a1) ; Save number of continues move.b d0,(Continue_count).w jmp Write_SaveGame(pc) ; --------------------------------------------------------------------------- locret_C530: rts ; End of function SaveGame_SpecialStage ; =============== S U B R O U T I N E ======================================= SaveGame_LivesContinues: tst.w (SK_alone_flag).w bne.s locret_C56C ; If playing Sonic and Knuckles, don't bother move.l (Save_pointer).w,d0 beq.s locret_C56C movea.l d0,a1 move.b (Life_count).w,d0 cmpi.b #99,d0 bls.s loc_C54C moveq #99,d0 loc_C54C: move.b d0,8(a1) ; Save number of lives move.b d0,(Life_count).w move.b (Continue_count).w,d0 cmpi.b #99,d0 bls.s loc_C560 moveq #99,d0 loc_C560: move.b d0,9(a1) ; Save number of continues move.b d0,(Continue_count).w jmp Write_SaveGame(pc) ; --------------------------------------------------------------------------- locret_C56C: rts ; End of function SaveGame_LivesContinues ; --------------------------------------------------------------------------- locret_C56E: rts ; --------------------------------------------------------------------------- SaveScreen: jsr (Pal_FadeToBlack).l move #$2700,sr move.w (VDP_reg_1_command).w,d0 andi.b #$BF,d0 move.w d0,(VDP_control_port).l jsr (Clear_DisplayData).l dmaFillVRAM 0,$D000,$1000 lea (VDP_control_port).l,a6 move.w #$8004,(a6) move.w #$8238,(a6) move.w #$8338,(a6) move.w #$8406,(a6) move.w #$8700,(a6) move.w #$8B00,(a6) move.w #$8C81,(a6) move.w #$9003,(a6) move.w #$9280,(a6) clearRAM Sprite_table_input,$400 clearRAM Object_RAM,(Kos_decomp_buffer-Object_RAM) clr.w (DMA_queue).w move.l #DMA_queue,(DMA_queue_slot).w clr.w (Level_frame_counter).w clr.w (Events_bg+$10).w clr.w (Events_bg+$12).w lea (MapEni_S3MenuBG).l,a0 lea (RAM_start).l,a1 move.w #make_art_tile(ArtTile_ArtKos_S3MenuBG,0,0),d0 jsr (Eni_Decomp).l lea (RAM_start).l,a1 move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0 moveq #$28-1,d1 moveq #$1C-1,d2 jsr (Plane_Map_To_VRAM).l lea (MapEni_SaveScreen_Layout).l,a0 lea (RAM_start).l,a1 move.w #make_art_tile(ArtTile_ArtKos_Save_Misc,0,1),d0 jsr (Eni_Decomp).l lea word_CD58(pc),a0 jsr sub_C866(pc) move.l #vdpComm(tiles_to_bytes($562),VRAM,WRITE),(VDP_control_port).l lea (ArtNem_S22POptions).l,a0 jsr (Nem_Decomp).l lea byte_DB1C(pc),a1 move.w #VRAM_Plane_A_Name_Table+$C06,d0 jsr sub_D9F4(pc) move.w #VRAM_Plane_A_Name_Table+$C0C,d0 jsr sub_D9F4(pc) move.w #VRAM_Plane_A_Name_Table+$CEC,d0 jsr sub_D9F4(pc) lea (ArtKos_S3MenuBG).l,a0 ; Decompress source lea (RAM_start).l,a1 ; Decompress destination/Transfer source movea.w #tiles_to_bytes(ArtTile_ArtKos_S3MenuBG),a2 ; Transfer destination jsr (KosArt_To_VDP).l move.l #locret_C56E,(_unkEF44_1).w move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l lea (ArtKos_SaveScreenMisc).l,a0 ; Decompress source lea (RAM_start).l,a1 ; Decompress destination/Transfer source movea.w #tiles_to_bytes(ArtTile_ArtKos_Save_Misc),a2 ; Transfer destination jsr KosArt_To_VDP(pc) move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l lea (ArtKos_SaveScreen).l,a0 ; Decompress source lea (RAM_start).l,a1 ; Decompress destination/Transfer source movea.w #tiles_to_bytes(ArtTile_ArtKos_Save_Extra),a2 ; Transfer destination jsr KosArt_To_VDP(pc) move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l lea (Pal_SaveMenuBG).l,a0 lea (Target_palette).w,a1 moveq #bytesToLcnt($20),d0 loc_C710: move.l (a0)+,(a1)+ dbf d0,loc_C710 lea Pal_Save_Chars(pc),a0 moveq #bytesToLcnt($40),d0 loc_C71C: move.l (a0)+,(a1)+ dbf d0,loc_C71C lea (Object_RAM).w,a0 lea ObjDat_SaveScreen(pc),a1 moveq #$C-1,d0 loc_C72C: move.l (a1)+,(a0) move.w #make_art_tile(ArtTile_ArtKos_Save_Misc,0,1),art_tile(a0) move.l #Map_SaveScreen,mappings(a0) move.w (a1),x_pos(a0) move.w (a1)+,objoff_12(a0) ; copy of object's x_pos move.w (a1)+,y_pos(a0) move.b (a1)+,mapping_frame(a0) move.b (a1)+,objoff_2E(a0) ; used for save slot id move.b #$40,render_flags(a0) ; sets multi-sprite flag lea next_object(a0),a0 dbf d0,loc_C72C jsr (Init_SpriteTable).l jsr (Process_Sprites).l jsr (Render_Sprites).l lea (Normal_palette_line_4).w,a0 lea (Target_palette_line_4).w,a1 moveq #8-1,d0 loc_C77A: move.l (a0),(a1)+ clr.l (a0)+ dbf d0,loc_C77A lea (ArtKos_SaveScreenS3Zone).l,a0 lea (RAM_start).l,a1 jsr (Kos_Decomp).l lea (RAM_start+$2BC0).l,a0 lea (RAM_start+$2300).l,a1 move.w #$230-1,d0 loc_C7A4: move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ dbf d0,loc_C7A4 lea (ArtKos_SaveScreenSKZone).l,a0 jsr (Kos_Decomp).l lea (ArtKos_SaveScreenPortrait).l,a0 jsr (Kos_Decomp).l lea -$8C0(a1),a0 move.w #$150-1,d0 loc_C7CC: move.l (a0)+,(a1)+ dbf d0,loc_C7CC moveq #signextendB(mus_DataSelect),d0 jsr (Play_Music).l move.l #loc_C890,(_unkEF44_1).w move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l move.w (VDP_reg_1_command).w,d0 ori.b #$40,d0 move.w d0,(VDP_control_port).l jsr (Pal_FadeFromBlack).l SaveScreen_MainLoop: move.b #$1E,(V_int_routine).w jsr (Wait_VSync).l addq.w #1,(Level_frame_counter).w jsr (Process_Sprites).l move.w (Camera_X_pos_copy).w,d0 neg.w d0 move.w d0,(H_scroll_buffer+2).w jsr (Render_Sprites).l lea (Normal_palette_line_3+$2).w,a0 moveq #$E,d0 move.w (Emerald_flicker_flag).w,d1 addq.w #1,d1 cmpi.w #3,d1 blo.s loc_C83C moveq #0,d1 loc_C83C: move.w d1,(Emerald_flicker_flag).w beq.s loc_C84E lea Pal_Save_Emeralds(pc),a1 loc_C846: move.w (a1)+,(a0)+ dbf d0,loc_C846 bra.s loc_C856 ; --------------------------------------------------------------------------- loc_C84E: move.w #$EEE,(a0)+ dbf d0,loc_C84E loc_C856: cmpi.b #$4C,(Game_mode).w ; are we still in the savescreen mode? beq.s SaveScreen_MainLoop ; if so, loop moveq #signextendB(sfx_EnterSS),d0 jmp (Play_SFX).l ; =============== S U B R O U T I N E ======================================= sub_C866: move.w (a0)+,d7 .loop: movea.l (a0)+,a1 move.w (a0)+,d0 bsr.s sub_C87E move.w (a0)+,d1 move.w (a0)+,d2 jsr (Plane_Map_To_VRAM_2).l dbf d7,.loop rts ; End of function sub_C866 ; =============== S U B R O U T I N E ======================================= sub_C87E: swap d0 clr.w d0 swap d0 lsl.l #2,d0 lsr.w #2,d0 ori.w #$4000,d0 swap d0 rts ; End of function sub_C87E ; --------------------------------------------------------------------------- ; selects whether to display the static screen, or new screen ; and is called during vblank next_SaveSlot = $A loc_C890: move.w (Level_frame_counter).w,d0 andi.w #$C,d0 lea (MapPtrs_SaveScreenStatic).l,a2 movea.l (a2,d0.w),a2 if Sonic3_Complete=0 adda.l #LockOnROM_Start,a2 endif move.w #VRAM_Plane_A_Name_Table+$21A,d7 lea (Saved_data).w,a0 moveq #8-1,d6 loc_C8B2: lea (MapUnc_SaveScreenNEW).l,a1 tst.b (a0) ; is a game in progress? bmi.s loc_C8BE movea.l a2,a1 loc_C8BE: move.w d7,d0 bsr.s sub_C87E moveq #$A-1,d1 moveq #7-1,d2 jsr (Plane_Map_To_VRAM_2).l addi.w #$1A,d7 lea next_SaveSlot(a0),a0 dbf d6,loc_C8B2 lea (Dynamic_object_RAM+object_size).w,a3 ; load the first save slot object move.w #VRAM_Plane_A_Name_Table+$A20,d7 lea (Saved_data).w,a0 moveq #8-1,d3 loc_C8E6: move.w d7,d0 subq.w #2,d0 jsr sub_C87E(pc) move.l d0,VDP_control_port-VDP_data_port(a6) move.w #make_art_tile($2B1,0,1),(a6) lea byte_DB2B(pc),a1 tst.b (a0) bmi.s loc_C946 lea byte_DB36(pc),a1 move.b objoff_3A(a3),d0 cmp.b objoff_37(a3),d0 bne.s loc_C912 tst.b objoff_3B(a3) bne.s loc_C946 loc_C912: lea byte_DB31(pc),a1 move.w d7,d0 subq.w #2,d0 jsr sub_D9F4(pc) move.w objoff_36(a3),d0 add.w d0,d0 moveq #0,d1 move.b byte_C95E(pc,d0.w),d1 bpl.s loc_C932 move.w #high_priority,d1 bra.s loc_C936 ; --------------------------------------------------------------------------- loc_C932: addi.w #make_art_tile($562,1,1),d1 loc_C936: move.w d1,(a6) moveq #0,d1 move.b byte_C95E+1(pc,d0.w),d1 addi.w #make_art_tile($562,1,1),d1 move.w d1,(a6) bra.s loc_C94C ; --------------------------------------------------------------------------- loc_C946: move.w d7,d0 jsr sub_D9F4(pc) loc_C94C: addi.w #$1A,d7 lea next_SaveSlot(a0),a0 lea next_object(a3),a3 dbf d3,loc_C8E6 bra.s loc_C97A ; --------------------------------------------------------------------------- ; shows level number 1-14 ; NOTE: $FF acts as zero byte_C95E: dc.b $FF, 1 ; 01 dc.b $FF, 2 ; 02 dc.b $FF, 3 ; 03 dc.b $FF, 4 ; 04 dc.b $FF, 5 ; 05 dc.b $FF, 6 ; 06 dc.b $FF, 7 ; 07 dc.b $FF, 8 ; 08 dc.b $FF, 9 ; 09 dc.b 1, 0 ; 10 dc.b 1, 1 ; 11 dc.b 1, 2 ; 12 dc.b 1, 3 ; 13 dc.b 1, 4 ; 14 ; --------------------------------------------------------------------------- loc_C97A: lea word_DA8A(pc),a2 lea (Dynamic_object_RAM+object_size).w,a3 move.w #VRAM_Plane_A_Name_Table+$1220,d7 lea (Saved_data).w,a0 moveq #8-1,d6 loc_C98C: move.w objoff_34(a3),d0 bne.s loc_C994 moveq #1,d0 loc_C994: tst.b (a0) bpl.s loc_C99A moveq #0,d0 loc_C99A: lsl.w #5,d0 movea.l a2,a1 adda.w d0,a1 move.w d7,d0 bsr.w sub_C87E moveq #3-1,d1 moveq #5-1,d2 jsr (Plane_Map_To_VRAM_2).l tst.b (a0) bpl.s loc_C9CC lea word_DB08(pc),a1 move.w d7,d0 addq.w #6,d0 bsr.w sub_C87E moveq #2-1,d1 moveq #5-1,d2 jsr (Plane_Map_To_VRAM_2).l bra.s loc_CA02 ; --------------------------------------------------------------------------- loc_C9CC: move.b objoff_3E(a3),d0 jsr sub_CA14(pc) move.w d7,d0 addq.w #6,d0 bsr.w sub_C87E moveq #2-1,d1 moveq #2-1,d2 jsr (Plane_Map_To_VRAM_2).l move.b objoff_3F(a3),d0 jsr sub_CA14(pc) move.w d7,d0 addi.w #$306,d0 bsr.w sub_C87E moveq #2-1,d1 moveq #2-1,d2 jsr (Plane_Map_To_VRAM_2).l loc_CA02: addi.w #$1A,d7 lea next_SaveSlot(a0),a0 lea next_object(a3),a3 dbf d6,loc_C98C rts ; =============== S U B R O U T I N E ======================================= sub_CA14: moveq #0,d1 loc_CA16: addq.w #1,d1 subi.b #$A,d0 bcc.s loc_CA16 subq.w #1,d1 addi.b #$A,d0 lea (_unkEEEA).w,a1 lsl.w #2,d1 bne.s loc_CA2E moveq #$28,d1 loc_CA2E: move.w word_CA4C(pc,d1.w),(a1) move.w word_CA4C+2(pc,d1.w),4(a1) andi.w #$FF,d0 lsl.w #2,d0 move.w word_CA4C(pc,d0.w),2(a1) move.w word_CA4C+2(pc,d0.w),6(a1) rts ; End of function sub_CA14 ; --------------------------------------------------------------------------- word_CA4C: dc.w make_art_tile($49A,1,1), make_art_tile($49B,1,1) ; 0 dc.w make_art_tile($49C,1,1), make_art_tile($49D,1,1) ; 1 dc.w make_art_tile($49E,1,1), make_art_tile($49F,1,1) ; 2 dc.w make_art_tile($4A0,1,1), make_art_tile($4A1,1,1) ; 3 dc.w make_art_tile($4A2,1,1), make_art_tile($4A3,1,1) ; 4 dc.w make_art_tile($4A4,1,1), make_art_tile($4A5,1,1) ; 5 dc.w make_art_tile($4A6,1,1), make_art_tile($4A7,1,1) ; 6 dc.w make_art_tile($4A8,1,1), make_art_tile($4A9,1,1) ; 7 dc.w make_art_tile($4AA,1,1), make_art_tile($4AB,1,1) ; 8 dc.w make_art_tile($4AC,1,1), make_art_tile($4AD,1,1) ; 9 dc.w make_art_tile($000,0,1), make_art_tile($000,0,1) ; blank Pal_Save_Chars: binclude "General/Save Menu/Palettes/Chars.bin" even Pal_Save_Emeralds: binclude "General/Save Menu/Palettes/Emeralds.bin" even Pal_Save_FinishCard1: binclude "General/Save Menu/Palettes/Finish Card 1.bin" even Pal_Save_FinishCard2: binclude "General/Save Menu/Palettes/Finish Card 2.bin" even Pal_Save_FinishCard3: binclude "General/Save Menu/Palettes/Finish Card 3.bin" even Pal_Save_ZoneCard1: binclude "General/Save Menu/Palettes/Zone Card 1.bin" even Pal_Save_ZoneCard2: binclude "General/Save Menu/Palettes/Zone Card 2.bin" even Pal_Save_ZoneCard3: binclude "General/Save Menu/Palettes/Zone Card 3.bin" even Pal_Save_ZoneCard4: binclude "General/Save Menu/Palettes/Zone Card 4.bin" even Pal_Save_ZoneCard5: binclude "General/Save Menu/Palettes/Zone Card 5.bin" even Pal_Save_ZoneCard6: binclude "General/Save Menu/Palettes/Zone Card 6.bin" even Pal_Save_ZoneCard7: binclude "General/Save Menu/Palettes/Zone Card 7.bin" even Pal_Save_ZoneCard8: binclude "General/Save Menu/Palettes/Zone Card 8.bin" even Pal_Save_ZoneCard9: binclude "General/Save Menu/Palettes/Zone Card 9.bin" even Pal_Save_ZoneCardA: binclude "General/Save Menu/Palettes/Zone Card A.bin" even Pal_Save_ZoneCardB: binclude "General/Save Menu/Palettes/Zone Card B.bin" even Pal_Save_ZoneCardC: binclude "General/Save Menu/Palettes/Zone Card C.bin" even Pal_Save_ZoneCardD: binclude "General/Save Menu/Palettes/Zone Card D.bin" even Pal_Save_ZoneCardE: binclude "General/Save Menu/Palettes/Zone Card E.bin" even Pal_Save_ZoneCardF: binclude "General/Save Menu/Palettes/Zone Card F.bin" even Pal_Save_ZoneCard10: binclude "General/Save Menu/Palettes/Zone Card 10.bin" even Pal_Save_ZoneCard11: binclude "General/Save Menu/Palettes/Zone Card 11.bin" even Pal_Save_ZoneCard12: binclude "General/Save Menu/Palettes/Zone Card 12.bin" even word_CD58: dc.w $12-1 dc.l RAM_start+$0222 dc.w VRAM_Plane_A_Name_Table+$102, $B-1, $C-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_A_Name_Table+$118, $D-1, $15-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_A_Name_Table+$132, $D-1, $15-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_A_Name_Table+$14C, $D-1, $15-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_A_Name_Table+$166, $D-1, $15-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_A_Name_Table+$180, $D-1, $15-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_A_Name_Table+$19A, $D-1, $15-1 dc.l RAM_start+$0104 dc.w VRAM_Plane_A_Name_Table+$E18, $D-1, $B-1 dc.l RAM_start+$0104 dc.w VRAM_Plane_A_Name_Table+$E32, $D-1, $B-1 dc.l RAM_start+$0104 dc.w VRAM_Plane_A_Name_Table+$E4C, $D-1, $B-1 dc.l RAM_start+$0104 dc.w VRAM_Plane_A_Name_Table+$E66, $D-1, $B-1 dc.l RAM_start+$0104 dc.w VRAM_Plane_A_Name_Table+$E80, $D-1, $B-1 dc.l RAM_start+$0104 dc.w VRAM_Plane_A_Name_Table+$E9A, $D-1, $B-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_A_Name_Table+$1B4, $D-1, $15-1 dc.l RAM_start+$0000 dc.w VRAM_Plane_A_Name_Table+$1CE, $D-1, $15-1 dc.l RAM_start+$0222 dc.w VRAM_Plane_A_Name_Table+$1E8, $B-1, $C-1 dc.l RAM_start+$0104 dc.w VRAM_Plane_A_Name_Table+$EB4, $D-1, $B-1 dc.l RAM_start+$0104 dc.w VRAM_Plane_A_Name_Table+$ECE, $D-1, $B-1 Map_SaveScreen: include "General/Save Menu/Map - Save Screen General.asm" ObjDat_SaveScreen: dc.l Draw_Sprite ; "Data Select" Text dc.w $120 ; x_pos, objoff_12 (x_pos copy) dc.w $14C ; y_pos dc.b 3 ; mapping_frame dc.b 0 ; unused dc.l Obj_SaveScreen_Selector ; Highlights the current selected slot dc.w $120 ; x_pos, objoff_12 (x_pos copy) dc.w $E2 ; y_pos dc.b 1 ; mapping_frame dc.b 0 ; unused dc.l Obj_SaveScreen_Delete_Save ; Delete Icon that erases a saved game dc.w $448 ; x_pos, objoff_12 (x_pos copy) dc.w $D8 ; y_pos dc.b $D ; mapping_frame dc.b 0 ; unused dc.l Obj_SaveScreen_NoSave_Slot ; Slot that starts a non-saving game dc.w $B0 ; x_pos, objoff_12 (x_pos copy) dc.w $C8 ; y_pos dc.b 0 ; unused dc.b 0 ; unused dc.l Obj_SaveScreen_Save_Slot ; Save Slot dc.w $110 ; x_pos, objoff_12 (x_pos copy) dc.w $108 ; y_pos dc.b 0 ; mapping_frame dc.b 0 ; Save Slot ID Number dc.l Obj_SaveScreen_Save_Slot ; Save Slot dc.w $178 ; x_pos, objoff_12 (x_pos copy) dc.w $108 ; y_pos dc.b 0 ; unused dc.b 1 ; Save Slot ID Number dc.l Obj_SaveScreen_Save_Slot ; Save Slot dc.w $1E0 ; x_pos, objoff_12 (x_pos copy) dc.w $108 ; y_pos dc.b 0 ; unused dc.b 2 ; Save Slot ID Number dc.l Obj_SaveScreen_Save_Slot ; Save Slot dc.w $248 ; x_pos, objoff_12 (x_pos copy) dc.w $108 ; y_pos dc.b 0 ; unused dc.b 3 ; Save Slot ID Number dc.l Obj_SaveScreen_Save_Slot ; Save Slot dc.w $2B0 ; x_pos, objoff_12 (x_pos copy) dc.w $108 ; y_pos dc.b 0 ; unused dc.b 4 ; Save Slot ID Number dc.l Obj_SaveScreen_Save_Slot ; Save Slot dc.w $318 ; x_pos, objoff_12 (x_pos copy) dc.w $108 ; y_pos dc.b 0 ; unused dc.b 5 ; Save Slot ID Number dc.l Obj_SaveScreen_Save_Slot ; Save Slot dc.w $380 ; x_pos, objoff_12 (x_pos copy) dc.w $108 ; y_pos dc.b 0 ; unused dc.b 6 ; Save Slot ID Number dc.l Obj_SaveScreen_Save_Slot ; Save Slot dc.w $3E8 ; x_pos, objoff_12 (x_pos copy) dc.w $108 ; y_pos dc.b 0 ; unused dc.b 7 ; Save Slot ID Number ; --------------------------------------------------------------------------- Obj_SaveScreen_Selector: move.w #$A8,d0 moveq #0,d1 moveq #0,d2 move.b (Dataselect_entry).w,d2 subq.w #1,d2 bcs.s loc_D1E6 loc_D1C6: moveq #$D-1,d4 loc_D1C8: addq.w #8,d0 cmpi.w #$120,d0 bls.s loc_D1DE subq.w #8,d0 addq.w #8,d1 cmpi.w #$2C0,d1 bls.s loc_D1DE subq.w #8,d1 addq.w #8,d0 loc_D1DE: dbf d4,loc_D1C8 dbf d2,loc_D1C6 loc_D1E6: move.w d0,$12(a0) move.w d1,(Camera_X_pos_copy).w neg.w d1 move.w d1,(H_scroll_buffer+2).w move.l #loc_D1FA,(a0) loc_D1FA: tst.w (Events_bg+$12).w bne.s loc_D212 btst #button_B,(Ctrl_1_pressed).w beq.s loc_D212 move.b #4,(Game_mode).w bra.w loc_D2CE ; --------------------------------------------------------------------------- loc_D212: tst.w (Events_bg+$10).w bne.w loc_D2CE tst.w $30(a0) bne.s loc_D28A moveq #0,d0 btst #button_left,(Ctrl_1_pressed).w beq.s loc_D254 tst.w (Events_bg+$12).w beq.s loc_D238 cmpi.b #1,(Dataselect_entry).w beq.s loc_D254 loc_D238: tst.b (Dataselect_entry).w beq.s loc_D254 subq.b #1,(Dataselect_entry).w moveq #signextendB(sfx_SlotMachine),d0 tst.w (Events_bg+$12).w beq.s loc_D24C moveq #signextendB(sfx_SmallBumpers),d0 loc_D24C: jsr (Play_SFX).l moveq #-8,d0 loc_D254: btst #button_right,(Ctrl_1_pressed).w beq.s loc_D27A cmpi.b #9,(Dataselect_entry).w beq.s loc_D27A addq.b #1,(Dataselect_entry).w moveq #signextendB(sfx_SlotMachine),d0 tst.w (Events_bg+$12).w beq.s loc_D272 moveq #signextendB(sfx_SmallBumpers),d0 loc_D272: jsr (Play_SFX).l moveq #8,d0 loc_D27A: move.w d0,$2E(a0) beq.s loc_D288 move.w #$D,$30(a0) bra.s loc_D28A ; --------------------------------------------------------------------------- loc_D288: bra.s loc_D2CE ; --------------------------------------------------------------------------- loc_D28A: move.w $12(a0),d0 move.w (Camera_X_pos_copy).w,d1 move.w $2E(a0),d2 bmi.s loc_D2B0 add.w d2,d0 cmpi.w #$120,d0 bls.s loc_D2C2 sub.w d2,d0 add.w d2,d1 cmpi.w #$2C0,d1 bls.s loc_D2C2 sub.w d2,d1 add.w d2,d0 bra.s loc_D2C2 ; --------------------------------------------------------------------------- loc_D2B0: add.w d2,d0 cmpi.w #$120,d0 bhs.s loc_D2C2 sub.w d2,d0 add.w d2,d1 bpl.s loc_D2C2 sub.w d2,d1 add.w d2,d0 loc_D2C2: move.w d0,$12(a0) move.w d1,(Camera_X_pos_copy).w subq.w #1,$30(a0) loc_D2CE: moveq #8,d2 move.b (Dataselect_entry).w,d1 beq.s loc_D2E0 neg.w d2 cmpi.b #9,d1 beq.s loc_D2E0 moveq #0,d2 loc_D2E0: add.w $12(a0),d2 move.w d2,x_pos(a0) moveq #2,d0 cmpi.w #$F0,d2 blo.s loc_D2F8 cmpi.w #$148,d2 bhi.s loc_D2F8 moveq #1,d0 loc_D2F8: move.b d0,mapping_frame(a0) btst #2,(Level_frame_counter+1).w beq.s locret_D30A jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_D30A: rts ; --------------------------------------------------------------------------- Obj_SaveScreen_NoSave_Slot: move.b #$F,sub2_mapframe(a0) move.w (Dataselect_nosave_player).w,d0 addq.w #4,d0 move.b d0,mapping_frame(a0) tst.b (Dataselect_entry).w bne.s loc_D396 move.w (Player_2+object_control).w,d0 or.w (Events_bg+$12).w,d0 bne.s loc_D396 move.b (Ctrl_1_pressed).w,d0 andi.w #button_A_mask|button_C_mask|button_start_mask,d0 beq.s loc_D376 move.b #$C,(Game_mode).w move.w (Dataselect_nosave_player).w,(Player_option).w clr.w (Current_zone_and_act).w clr.w (Apparent_zone_and_act).w clr.w (Current_special_stage).w clr.w (Emerald_counts).w clr.l (Collected_emeralds_array).w clr.w (Collected_emeralds_array+4).w clr.b (Collected_emeralds_array+6).w clr.l (Collected_special_ring_array).w clr.b (Emeralds_converted_flag).w clr.l (Save_pointer).w jsr (Set_Lives_and_Continues).l jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_D376: move.w (Dataselect_nosave_player).w,d0 jsr sub_D6D0(pc) move.w d0,(Dataselect_nosave_player).w addq.w #4,d0 move.b d0,mapping_frame(a0) move.w #1,mainspr_childsprites(a0) btst #4,(Level_frame_counter+1).w bne.s loc_D39A loc_D396: clr.w mainspr_childsprites(a0) loc_D39A: bra.w Set_ChildSprites ; --------------------------------------------------------------------------- Obj_SaveScreen_Save_Slot: jsr (AllocateObjectAfterCurrent).l bne.s loc_D3B0 move.l #Obj_SaveScreen_Emeralds,(a1) move.w a0,parent2(a1) loc_D3B0: moveq #0,d0 move.b $2E(a0),d0 mulu.w #$A,d0 addi.l #Saved_data,d0 move.l d0,$30(a0) movea.l d0,a1 move.b 2(a1),d0 lsr.b #4,d0 move.b d0,$35(a0) move.b 3(a1),d0 move.b d0,$37(a0) move.b d0,$3A(a0) move.b (a1),d0 andi.b #3,d0 move.b d0,$3B(a0) move.w 6(a1),d0 lea (Collected_emeralds_array).w,a2 jsr sub_DA1E(pc) move.b d1,$3C(a0) move.b d2,$3D(a0) tst.b 9(a1) bne.s loc_D41A cmpi.b #3,8(a1) bhs.s loc_D41A move.b #3,8(a1) move.l a1,-(sp) st (SRAM_mask_interrupts_flag).w jsr Write_SaveGame(pc) movea.l (sp)+,a1 loc_D41A: move.b 8(a1),$3E(a0) move.b 9(a1),$3F(a0) move.l #loc_D42C,(a0) loc_D42C: clr.w mainspr_childsprites(a0) movea.l $30(a0),a1 move.b (Dataselect_entry).w,d0 subq.b #1,d0 cmp.b $2E(a0),d0 beq.s Load_Level_Icons move.b 3(a1),$37(a0) clr.w $38(a0) loc_D44A: move.w $34(a0),d0 addq.w #4,d0 move.b d0,mapping_frame(a0) bra.w Set_ChildSprites ; --------------------------------------------------------------------------- Load_Level_Icons: tst.b (a1) bmi.w loc_D5FE move.w $36(a0),d1 jsr Load_Icon_Art(pc) move.b #$17,sub3_mapframe(a0) move.w $36(a0),d1 cmp.b $3A(a0),d1 bne.s loc_D4A4 move.b $3B(a0),d0 beq.s loc_D4A4 addq.b #1,sub3_mapframe(a0) cmpi.b #1,d0 beq.s loc_D496 addq.b #1,sub3_mapframe(a0) cmpi.b #2,d0 beq.s loc_D496 addq.b #2,sub3_mapframe(a0) bra.s loc_D4A4 ; --------------------------------------------------------------------------- loc_D496: cmpi.w #1,$34(a0) bls.s loc_D4A4 move.b #$23,sub3_mapframe(a0) loc_D4A4: tst.w $38(a0) bne.s loc_D4B6 tst.b $3B(a0) beq.w loc_D534 st $38(a0) loc_D4B6: tst.w (Player_2+object_control).w bne.s loc_D44A tst.w (Events_bg+$12).w beq.s loc_D4D0 clr.b sub2_mapframe(a0) move.w #2,mainspr_childsprites(a0) bra.w loc_D44A ; --------------------------------------------------------------------------- loc_D4D0: moveq #$B,d6 cmpi.w #3,$34(a0) beq.s loc_D4EE moveq #$C,d6 cmpi.w #2,$34(a0) beq.s loc_D4EE cmpi.b #2,$3B(a0) blo.s loc_D4EE moveq #$D,d6 loc_D4EE: moveq #0,d2 move.w $36(a0),d1 move.b (Ctrl_1_pressed).w,d0 btst #1,d0 beq.s loc_D508 moveq #signextendB(sfx_Switch),d2 subq.w #1,d1 bpl.s loc_D518 move.w d6,d1 bra.s loc_D518 ; --------------------------------------------------------------------------- loc_D508: btst #0,d0 beq.s loc_D518 moveq #signextendB(sfx_Switch),d2 addq.w #1,d1 cmp.w d6,d1 bls.s loc_D518 moveq #0,d1 loc_D518: move.w d1,$36(a0) move.l d2,d0 jsr (Play_SFX).l move.b #$1A,sub2_mapframe(a0) btst #4,(Level_frame_counter+1).w beq.s loc_D53C bra.s loc_D540 ; --------------------------------------------------------------------------- loc_D534: tst.w (Player_2+object_control).w bne.w loc_D44A loc_D53C: clr.b sub2_mapframe(a0) loc_D540: move.w #2,mainspr_childsprites(a0) tst.w (Events_bg+$12).w bne.w loc_D44A move.b (Ctrl_1_pressed).w,d0 andi.w #button_A_mask|button_C_mask|button_start_mask,d0 beq.w loc_D44A move.w 4(a1),(Collected_special_ring_array+2).w move.b 3(a1),d0 tst.b $3B(a0) beq.s loc_D57A move.w $36(a0),d0 cmp.b $3A(a0),d0 bhs.w loc_D44A clr.l (Collected_special_ring_array).w loc_D57A: jsr sub_DA4E(pc) move.w d0,(Current_zone_and_act).w move.w d0,(Apparent_zone_and_act).w moveq #0,d0 move.b 2(a1),d0 lsr.b #4,d0 move.w d0,(Player_option).w move.b 2(a1),d0 andi.b #$F,d0 move.b d0,(Current_special_stage).w move.w 6(a1),d0 lea (Collected_emeralds_array).w,a2 jsr sub_DA1E(pc) move.b d1,(Chaos_emerald_count).w move.b d2,(Super_emerald_count).w move.l a1,(Save_pointer).w jsr (Set_Lives_and_Continues).l move.b 8(a1),d0 beq.s loc_D5CE cmpi.b #3,d0 bhs.s loc_D5DE tst.b 9(a1) bne.s loc_D5DE loc_D5CE: move.b #3,8(a1) subq.b #1,9(a1) bcc.s loc_D5DE clr.b 9(a1) loc_D5DE: move.b 8(a1),(Life_count).w move.b 9(a1),(Continue_count).w st (SRAM_mask_interrupts_flag).w jsr Write_SaveGame(pc) move.b #$C,(Game_mode).w jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_D5FE: move.b #$F,sub2_mapframe(a0) clr.b sub3_mapframe(a0) move.w (Player_2+object_control).w,d0 or.w (Events_bg+$12).w,d0 bne.w loc_D44A move.b (Ctrl_1_pressed).w,d0 andi.w #button_A_mask|button_C_mask|button_start_mask,d0 beq.s loc_D67A move.b #$C,(Game_mode).w clr.l (a1) clr.l 4(a1) move.w #$300,8(a1) move.w $34(a0),d0 move.w d0,(Player_option).w lsl.b #4,d0 move.b d0,2(a1) clr.w (Current_zone_and_act).w clr.w (Apparent_zone_and_act).w clr.w (Current_special_stage).w clr.w (Emerald_counts).w clr.l (Collected_emeralds_array).w clr.w (Collected_emeralds_array+4).w clr.b (Collected_emeralds_array+6).w clr.l (Collected_special_ring_array).w clr.b (Emeralds_converted_flag).w move.l a1,(Save_pointer).w jsr (Set_Lives_and_Continues).l st (SRAM_mask_interrupts_flag).w jsr Write_SaveGame(pc) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_D67A: move.w $34(a0),d0 jsr sub_D6D0(pc) move.w d0,$34(a0) addq.w #4,d0 move.b d0,mapping_frame(a0) move.w #1,mainspr_childsprites(a0) btst #4,(Level_frame_counter+1).w bne.s Set_ChildSprites clr.w mainspr_childsprites(a0) Set_ChildSprites: move.w $12(a0),d0 sub.w (Camera_X_pos_copy).w,d0 move.w d0,x_pos(a0) 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) cmpi.b #$1A,sub2_mapframe(a0) bne.s loc_D6CA subq.w #8,sub2_y_pos(a0) loc_D6CA: jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_D6D0: moveq #0,d2 tst.w (Player_2+objoff_30).w bne.s loc_D6FA move.b (Ctrl_1_pressed).w,d1 lsr.w #1,d1 bcc.s loc_D6EE moveq #signextendB(sfx_Switch),d2 addq.w #1,d0 cmpi.w #3,d0 bls.s loc_D6FA moveq #0,d0 bra.s loc_D6FA ; --------------------------------------------------------------------------- loc_D6EE: lsr.w #1,d1 bcc.s loc_D6FA moveq #signextendB(sfx_Switch),d2 subq.w #1,d0 bpl.s loc_D6FA moveq #3,d0 loc_D6FA: tst.w d2 beq.s locret_D70A move.l d0,-(sp) move.l d2,d0 jsr (Play_SFX).l move.l (sp)+,d0 locret_D70A: rts ; End of function sub_D6D0 ; --------------------------------------------------------------------------- Obj_SaveScreen_Emeralds: move.b #$40,render_flags(a0) move.w #make_art_tile(ArtTile_ArtKos_Save_Misc,0,1),art_tile(a0) move.l #Map_SaveScreen,mappings(a0) move.b #$40,width_pixels(a0) move.w #7,mainspr_childsprites(a0) movea.w parent2(a0),a1 movea.l $30(a1),a2 move.w 6(a2),d4 move.w x_pos(a1),d0 move.w y_pos(a1),d1 move.w d0,x_pos(a0) move.w d1,y_pos(a0) lea sub2_x_pos(a0),a1 moveq #$10,d2 moveq #7-1,d3 loc_D750: clr.b 5(a1) moveq #0,d6 rol.w #2,d4 move.w d4,d5 andi.w #3,d5 beq.s loc_D774 cmpi.w #3,d5 bne.s loc_D768 moveq #$C,d6 loc_D768: add.b d2,d6 move.w d0,(a1) move.w d1,sub2_y_pos-sub2_x_pos(a1) move.b d6,sub2_mapframe-sub2_x_pos(a1) loc_D774: addq.w #1,d2 addq.w #6,a1 dbf d3,loc_D750 jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Obj_SaveScreen_Delete_Save: moveq #0,d0 move.b routine(a0),d0 jmp SaveScreen_Delete_Save_Index(pc,d0.w) ; --------------------------------------------------------------------------- SaveScreen_Delete_Save_Index: bra.w loc_D7A4 ; --------------------------------------------------------------------------- bra.w loc_D7C0 ; --------------------------------------------------------------------------- bra.w loc_D7EA ; --------------------------------------------------------------------------- bra.w loc_D884 ; --------------------------------------------------------------------------- bra.w loc_D8A4 ; --------------------------------------------------------------------------- bra.w loc_D8C4 ; --------------------------------------------------------------------------- loc_D7A4: move.b #$40,render_flags(a0) move.b #$30,width_pixels(a0) move.w #1,mainspr_childsprites(a0) move.b #8,sub2_mapframe(a0) addq.b #4,routine(a0) loc_D7C0: cmpi.b #9,(Dataselect_entry).w bne.w loc_D8A0 move.b (Ctrl_1_pressed).w,d0 andi.w #button_A_mask|button_C_mask|button_start_mask,d0 beq.w loc_D8A0 moveq #signextendB(sfx_Starpost),d0 jsr (Play_SFX).l st (Events_bg+$12).w addq.b #4,routine(a0) bra.w loc_D8A0 ; --------------------------------------------------------------------------- loc_D7EA: jsr sub_D912(pc) jsr sub_D94A(pc) tst.w (Player_2+object_control).w bne.s loc_D83C move.b (Ctrl_1_pressed).w,d0 btst #button_B,d0 bne.s loc_D854 andi.w #button_A_mask|button_C_mask|button_start_mask,d0 beq.s loc_D83C cmpi.b #9,(Dataselect_entry).w beq.s loc_D854 moveq #0,d0 move.b (Dataselect_entry).w,d0 subq.w #1,d0 mulu.w #$A,d0 addi.l #Saved_data,d0 move.l d0,$2E(a0) movea.l d0,a1 tst.b (a1) bmi.s loc_D854 moveq #signextendB(sfx_Starpost),d0 jsr (Play_SFX).l st (Events_bg+$10).w addq.b #8,routine(a0) loc_D83C: move.w (Player_2+x_pos).w,d0 move.w d0,x_pos(a0) move.w d0,sub2_x_pos(a0) move.w y_pos(a0),sub2_y_pos(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_D854: clr.b $24(a0) clr.b $23(a0) clr.b $25(a0) clr.b $28(a0) move.b #$D,mapping_frame(a0) move.b #8,sub2_mapframe(a0) move.w (Player_2+x_pos).w,d0 add.w (Camera_X_pos_copy).w,d0 move.w d0,$12(a0) addq.b #4,routine(a0) bra.w Set_ChildSprites ; --------------------------------------------------------------------------- loc_D884: clr.w (Events_bg+$12).w move.w $12(a0),d0 cmpi.w #$448,d0 blo.s loc_D89A move.b #4,routine(a0) bra.s loc_D8A0 ; --------------------------------------------------------------------------- loc_D89A: addq.w #8,d0 move.w d0,$12(a0) loc_D8A0: bra.w Set_ChildSprites ; --------------------------------------------------------------------------- loc_D8A4: jsr sub_D912(pc) jsr sub_D94A(pc) cmpi.b #$B,sub2_mapframe(a0) bne.s loc_D8BE move.b #$C,sub2_mapframe(a0) addq.b #4,routine(a0) loc_D8BE: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_D8C4: jsr sub_D912(pc) btst #button_right,(Ctrl_1_pressed).w bne.s loc_D8FE btst #button_left,(Ctrl_1_pressed).w beq.s loc_D90C moveq #signextendB(sfx_Perfect),d0 jsr (Play_SFX).l movea.l $2E(a0),a1 move.w #$8000,(a1) clr.l 2(a1) clr.w 6(a1) move.w #$300,8(a1) st (SRAM_mask_interrupts_flag).w jsr Write_SaveGame(pc) loc_D8FE: move.b #8,routine(a0) clr.w (Events_bg+$10).w bra.w loc_D854 ; --------------------------------------------------------------------------- loc_D90C: jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_D912: subq.b #1,anim_frame_timer(a0) bpl.s locret_D938 move.b #5,anim_frame_timer(a0) loc_D91E: moveq #0,d0 move.b anim_frame(a0),d0 addq.b #1,anim_frame(a0) move.b byte_D93A(pc,d0.w),d0 bpl.s loc_D934 clr.b anim_frame(a0) bra.s loc_D91E ; --------------------------------------------------------------------------- loc_D934: move.b d0,mapping_frame(a0) locret_D938: rts ; End of function sub_D912 ; --------------------------------------------------------------------------- byte_D93A: dc.b $D, $E, $D, $E, $D, $E, $D, $E, $D, $E, $D, $D, $D, $D, $FF even ; =============== S U B R O U T I N E ======================================= sub_D94A: subq.b #1,$25(a0) bpl.s locret_D968 move.b #3,$25(a0) addq.b #1,$28(a0) move.b $28(a0),d0 andi.b #3,d0 addq.b #8,d0 move.b d0,sub2_mapframe(a0) locret_D968: rts ; End of function sub_D94A ; =============== S U B R O U T I N E ======================================= Load_Icon_Art: cmp.b $3A(a0),d1 bne.s loc_D9A2 tst.b $3B(a0) beq.s loc_D9A2 cmpi.w #1,$34(a0) bls.s loc_D9C8 cmpi.b #3,$3B(a0) beq.s loc_D9C8 moveq #$E,d1 cmpi.w #3,$34(a0) beq.s loc_D992 addq.w #2,d1 loc_D992: cmpi.b #1,$3B(a0) beq.s loc_D99C addq.w #1,d1 loc_D99C: move.w #tiles_to_bytes($51C),d2 bra.s loc_D9A6 ; --------------------------------------------------------------------------- loc_D9A2: move.w #tiles_to_bytes($5BA),d2 loc_D9A6: move.l a1,-(sp) move.w d1,-(sp) mulu.w #$8C0,d1 addi.l #RAM_start,d1 move.w #$460,d3 jsr (Add_To_DMA_Queue).l move.w (sp)+,d0 movea.l (sp)+,a1 lea Pal_Save_ZoneCard1(pc),a2 bra.s loc_D9E2 ; --------------------------------------------------------------------------- loc_D9C8: lea Pal_Save_FinishCard1(pc),a2 moveq #0,d0 cmpi.b #1,$3B(a0) beq.s loc_D9E2 addq.w #1,d0 cmpi.b #2,$3B(a0) beq.s loc_D9E2 addq.w #1,d0 loc_D9E2: lsl.w #5,d0 adda.w d0,a2 lea (Normal_palette_line_4).w,a3 moveq #bytesToLcnt($20),d0 loc_D9EC: move.l (a2)+,(a3)+ dbf d0,loc_D9EC rts ; End of function Load_Icon_Art ; =============== S U B R O U T I N E ======================================= sub_D9F4: lea (VDP_data_port).l,a6 jsr sub_C87E(pc) move.l d0,VDP_control_port-VDP_data_port(a6) move.w #make_art_tile($552,1,1),d5 moveq #0,d6 loc_DA08: move.b (a1)+,d6 bne.s loc_DA12 move.w #$8000,(a6) bra.s loc_DA08 ; --------------------------------------------------------------------------- loc_DA12: bmi.s locret_DA1C move.w d5,d4 add.w d6,d4 move.w d4,(a6) bra.s loc_DA08 ; --------------------------------------------------------------------------- locret_DA1C: rts ; End of function sub_D9F4 ; =============== S U B R O U T I N E ======================================= sub_DA1E: clr.b (Emeralds_converted_flag).w moveq #0,d1 moveq #0,d2 moveq #7-1,d3 loc_DA28: rol.w #2,d0 move.w d0,d4 andi.w #3,d4 move.b d4,(a2)+ beq.s loc_DA3E addq.w #1,d1 cmpi.w #3,d4 bne.s loc_DA3E addq.w #1,d2 loc_DA3E: cmpi.w #2,d4 blo.s loc_DA48 st (Emeralds_converted_flag).w loc_DA48: dbf d3,loc_DA28 rts ; End of function sub_DA1E ; =============== S U B R O U T I N E ======================================= sub_DA4E: cmpi.w #3,$34(a0) bne.s loc_DA62 cmpi.b #$B,d0 bne.s loc_DA62 move.w #$A01,d0 bra.s locret_DA6C ; --------------------------------------------------------------------------- loc_DA62: andi.w #$F,d0 add.w d0,d0 move.w LevelList_DA6E(pc,d0.w),d0 locret_DA6C: rts ; End of function sub_DA4E ; --------------------------------------------------------------------------- LevelList_DA6E: dc.w 0 dc.w $100 dc.w $200 dc.w $300 dc.w $500 dc.w $600 dc.w $700 dc.w $400 dc.w $800 dc.w $900 dc.w $1601 dc.w $A00 dc.w $B00 dc.w $C00 word_DA8A: dc.w make_art_tile($000,0,1), make_art_tile($000,0,1), make_art_tile($000,0,1) dc.w make_art_tile($000,0,1), make_art_tile($000,0,1), make_art_tile($000,0,1) dc.w make_art_tile($000,0,1), make_art_tile($000,0,1), make_art_tile($000,0,1) dc.w make_art_tile($000,0,1), make_art_tile($000,0,1), make_art_tile($000,0,1) dc.w make_art_tile($000,0,1), make_art_tile($000,0,1), make_art_tile($000,0,1) dc.w 0 dc.w make_art_tile($4C2,1,1), make_art_tile($4C4,1,1), make_art_tile($4AE,1,1) dc.w make_art_tile($4C3,1,1), make_art_tile($4C5,1,1), make_art_tile($4AF,1,1) dc.w make_art_tile($4B0,1,1), make_art_tile($4B3,1,1), make_art_tile($000,1,1) dc.w make_art_tile($4B1,1,1), make_art_tile($4B4,1,1), make_art_tile($4AE,1,1) dc.w make_art_tile($4B2,1,1), make_art_tile($4B5,1,1), make_art_tile($4AF,1,1) dc.w 0 dc.w make_art_tile($4C6,1,1), make_art_tile($4C8,1,1), make_art_tile($4AE,1,1) dc.w make_art_tile($4C7,1,1), make_art_tile($4C9,1,1), make_art_tile($4AF,1,1) dc.w make_art_tile($4B6,1,1), make_art_tile($4B9,1,1), make_art_tile($000,1,1) dc.w make_art_tile($4B7,1,1), make_art_tile($4BA,1,1), make_art_tile($4AE,1,1) dc.w make_art_tile($4B8,1,1), make_art_tile($4BB,1,1), make_art_tile($4AF,1,1) dc.w 0 dc.w make_art_tile($4CA,1,1), make_art_tile($4CC,1,1), make_art_tile($4AE,1,1) dc.w make_art_tile($4CB,1,1), make_art_tile($4CD,1,1), make_art_tile($4AF,1,1) dc.w make_art_tile($4BC,1,1), make_art_tile($4BF,1,1), make_art_tile($000,1,1) dc.w make_art_tile($4BD,1,1), make_art_tile($4C0,1,1), make_art_tile($4AE,1,1) dc.w make_art_tile($4BE,1,1), make_art_tile($4C1,1,1), make_art_tile($4AF,1,1) word_DB08: dc.w make_art_tile($000,0,1), make_art_tile($000,0,1) dc.w make_art_tile($000,0,1), make_art_tile($000,0,1) dc.w make_art_tile($000,0,1), make_art_tile($000,0,1) dc.w make_art_tile($000,0,1), make_art_tile($000,0,1) dc.w make_art_tile($000,0,1), make_art_tile($000,0,1) byte_DB1C: dc.b $2B, $2C, $FF, $30, $1E, $33, $22, $FF, $21, $22, $29, $22, $31, $22, $FF byte_DB2B: dc.b 0, 0, 0, 0, 0, $FF byte_DB31: dc.b $37, $2C, $2B, $22, $FF byte_DB36: dc.b $20, $29, $22, $1E, $2F, $FF even ; =============== S U B R O U T I N E ======================================= Render_HUD_P1: tst.w (Debug_mode_flag).w bne.s Render_HUD rts ; End of function Render_HUD_P1 ; =============== S U B R O U T I N E ======================================= Render_HUD: cmpi.b #$16,(Current_zone).w bhs.s loc_DB68 cmpi.b #$13,(Current_zone).w blo.s loc_DB68 moveq #8,d4 btst #3,(Level_frame_counter+1).w bne.s loc_DB84 tst.w (Ring_count).w bne.s loc_DB84 addq.w #2,d4 bra.s loc_DB84 ; --------------------------------------------------------------------------- loc_DB68: moveq #0,d4 btst #3,(Level_frame_counter+1).w bne.s loc_DB84 tst.w (Ring_count).w bne.s loc_DB7A addq.w #2,d4 loc_DB7A: cmpi.b #9,(Timer_minute).w bne.s loc_DB84 addq.w #4,d4 loc_DB84: move.b (Level_started_flag).w,d0 ext.w d0 bpl.s loc_DB92 addq.w #8,d0 move.b d0,(Level_started_flag).w loc_DB92: addi.w #$8F,d0 move.w #$108,d1 move.w #make_art_tile($6CA,0,1),d5 lea Map_HUD(pc),a1 adda.w (a1,d4.w),a1 move.w (a1)+,d4 subq.w #1,d4 bmi.s locret_DBB2 jmp (sub_1AF6C).l ; --------------------------------------------------------------------------- locret_DBB2: rts ; End of function Render_HUD ; =============== S U B R O U T I N E ======================================= Render_HUD_P2: rts ; End of function Render_HUD_P2 ; --------------------------------------------------------------------------- Map_HUD: include "General/Sprites/HUD Icon/Map - HUD.asm" ; =============== S U B R O U T I N E ======================================= HUD_AddToScore: move.b #1,(Update_HUD_score).w lea (Score).w,a3 add.l d0,(a3) ; Add to score move.l #999999,d1 ; 9999990 maximum points cmp.l (a3),d1 bhi.s .jump move.l d1,(a3) .jump: move.l (a3),d0 cmp.l (Next_extra_life_score).w,d0 ; If score is greater than next 50000 point increment blo.s .end addi.l #5000,(Next_extra_life_score).w addq.b #1,(Life_count).w ; Give an additional extra life addq.b #1,(Update_HUD_life_count).w move.w #mus_ExtraLife,d0 ; Play the 1up song jmp (Play_Music).l .end: rts ; End of function HUD_AddToScore ; =============== S U B R O U T I N E ======================================= UpdateHUD: nop lea (VDP_data_port).l,a6 tst.w (Competition_mode).w bne.w loc_DE7E tst.w (Debug_placement_mode).w bne.w loc_DDF4 tst.b (Update_HUD_score).w beq.s loc_DD36 clr.b (Update_HUD_score).w move.l #vdpComm(tiles_to_bytes($6E4),VRAM,WRITE),d0 move.l (Score).w,d1 bsr.w DrawSixDigitNumber loc_DD36: tst.b (Update_HUD_ring_count).w beq.s loc_DD56 bpl.s loc_DD42 bsr.w HUD_DrawZeroRings loc_DD42: clr.b (Update_HUD_ring_count).w move.l #vdpComm(tiles_to_bytes($6FA),VRAM,WRITE),d0 moveq #0,d1 move.w (Ring_count).w,d1 bsr.w DrawThreeDigitNumber loc_DD56: tst.b (Update_HUD_timer).w bpl.s loc_DD64 move.b #1,(Update_HUD_timer).w bra.s loc_DD9E ; --------------------------------------------------------------------------- loc_DD64: beq.s loc_DDBE tst.w (Game_paused).w bne.s loc_DDBE lea (Timer).w,a1 cmpi.l #(9<<16)|(59<<8)|59,(a1)+ beq.w UpdateHUD_TimeOver addq.b #1,-(a1) cmpi.b #60,(a1) blo.s loc_DDBE move.b #0,(a1) addq.b #1,-(a1) cmpi.b #60,(a1) blo.s loc_DD9E move.b #0,(a1) addq.b #1,-(a1) cmpi.b #9,(a1) blo.s loc_DD9E move.b #9,(a1) loc_DD9E: move.l #vdpComm(tiles_to_bytes($6F2),VRAM,WRITE),d0 moveq #0,d1 move.b (Timer_minute).w,d1 bsr.w DrawSingleDigitNumber move.l #vdpComm(tiles_to_bytes($6F6),VRAM,WRITE),d0 moveq #0,d1 move.b (Timer_second).w,d1 bsr.w DrawTwoDigitNumber loc_DDBE: tst.b (Update_HUD_life_count).w beq.s locret_DDCC clr.b (Update_HUD_life_count).w bsr.w HUD_Lives locret_DDCC: rts ; --------------------------------------------------------------------------- UpdateHUD_TimeOver: clr.b (Update_HUD_timer).w lea (Player_1).w,a0 cmpi.b #6,routine(a0) bhs.s loc_DDEC cmpi.b #$15,(Current_zone).w beq.s loc_DDEC movea.l a0,a2 bsr.w Kill_Character loc_DDEC: move.b #1,(Time_over_flag).w rts ; --------------------------------------------------------------------------- loc_DDF4: bsr.w HUD_Debug tst.b (Update_HUD_ring_count).w beq.s loc_DE18 bpl.s loc_DE04 bsr.w HUD_DrawZeroRings loc_DE04: clr.b (Update_HUD_ring_count).w move.l #vdpComm(tiles_to_bytes($6FA),VRAM,WRITE),d0 moveq #0,d1 move.w (Ring_count).w,d1 bsr.w DrawThreeDigitNumber loc_DE18: move.l #vdpComm(tiles_to_bytes($6F2),VRAM,WRITE),d0 moveq #0,d1 move.w (Lag_frame_count).w,d1 bsr.w DrawSingleDigitNumber move.l #vdpComm(tiles_to_bytes($6F6),VRAM,WRITE),d0 moveq #0,d1 move.b (Sprites_drawn).w,d1 bsr.w DrawTwoDigitNumber tst.b (Update_HUD_life_count).w beq.s loc_DE46 clr.b (Update_HUD_life_count).w bsr.w HUD_Lives loc_DE46: tst.w (Game_paused).w bne.s locret_DE7C lea (Timer).w,a1 cmpi.l #(9<<16)|(59<<8)|59,(a1)+ nop addq.b #1,-(a1) cmpi.b #60,(a1) blo.s locret_DE7C move.b #0,(a1) addq.b #1,-(a1) cmpi.b #60,(a1) blo.s locret_DE7C move.b #0,(a1) addq.b #1,-(a1) cmpi.b #9,(a1) blo.s locret_DE7C move.b #9,(a1) locret_DE7C: rts ; --------------------------------------------------------------------------- loc_DE7E: tst.w (Debug_mode_flag).w bne.w HUD_Debug rts ; End of function UpdateHUD ; =============== S U B R O U T I N E ======================================= HUD_DrawZeroRings: move.l #vdpComm(tiles_to_bytes($6FA),VRAM,WRITE),(VDP_control_port).l lea HUD_Zero_Rings(pc),a2 move.w #3-1,d2 bra.s loc_DEBE ; End of function HUD_DrawZeroRings ; =============== S U B R O U T I N E ======================================= HUD_DrawInitial: lea (VDP_data_port).l,a6 bsr.w HUD_Lives tst.w (Competition_mode).w bne.s locret_DEEA move.l #vdpComm(tiles_to_bytes($6E2),VRAM,WRITE),(VDP_control_port).l lea HUD_Initial_Parts(pc),a2 move.w #$F-1,d2 loc_DEBE: lea ArtUnc_HUDDigits(pc),a1 loc_DEC2: move.w #$10-1,d1 move.b (a2)+,d0 bmi.s loc_DEDE ext.w d0 lsl.w #5,d0 lea (a1,d0.w),a3 loc_DED2: move.l (a3)+,(a6) dbf d1,loc_DED2 loc_DED8: dbf d2,loc_DEC2 rts ; --------------------------------------------------------------------------- loc_DEDE: move.l #0,(a6) dbf d1,loc_DEDE bra.s loc_DED8 ; --------------------------------------------------------------------------- locret_DEEA: rts ; End of function HUD_DrawInitial ; --------------------------------------------------------------------------- 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 HUD_Initial_Parts: dc.b "E 0" dc.b "0:00" HUD_Zero_Rings: dc.b " 0" ; (zero rings) charset even ; =============== S U B R O U T I N E ======================================= HUD_Debug: move.l #vdpComm(tiles_to_bytes($6E2),VRAM,WRITE),(VDP_control_port).l move.w (Camera_X_pos).w,d1 swap d1 move.w (Player_1+x_pos).w,d1 bsr.s sub_DF1C move.w (Camera_Y_pos).w,d1 swap d1 move.w (Player_1+y_pos).w,d1 ; End of function HUD_Debug ; =============== S U B R O U T I N E ======================================= sub_DF1C: moveq #8-1,d6 lea (ArtUnc_DebugDigits).l,a1 loc_DF24: rol.w #4,d1 move.w d1,d2 andi.w #$F,d2 cmpi.w #$A,d2 blo.s loc_DF36 addi.w #7,d2 loc_DF36: lsl.w #5,d2 lea (a1,d2.w),a3 rept 8 move.l (a3)+,(a6) endm swap d1 dbf d6,loc_DF24 rts ; End of function sub_DF1C ; --------------------------------------------------------------------------- lea (Level_layout_header).w,a1 move.w (Player_1+x_pos).w,d3 move.w (Player_1+y_pos).w,d2 move.w d2,d0 lsr.w #5,d0 and.w (Layout_row_index_mask).w,d0 move.w 8(a1,d0.w),d0 move.w d3,d1 lsr.w #3,d1 move.w d1,d4 lsr.w #4,d1 add.w d1,d0 moveq #-1,d1 clr.w d1 movea.w d0,a1 move.b (a1),d1 rts ; =============== S U B R O U T I N E ======================================= DrawThreeDigitNumber: lea (dword_E04C).l,a2 moveq #3-1,d6 bra.s loc_DF92 ; End of function DrawThreeDigitNumber ; =============== S U B R O U T I N E ======================================= DrawSixDigitNumber: lea (dword_E040).l,a2 moveq #6-1,d6 loc_DF92: moveq #0,d4 lea ArtUnc_HUDDigits(pc),a1 loc_DF98: moveq #0,d2 move.l (a2)+,d3 loc_DF9C: sub.l d3,d1 bcs.s loc_DFA4 addq.w #1,d2 bra.s loc_DF9C ; --------------------------------------------------------------------------- loc_DFA4: add.l d3,d1 tst.w d2 beq.s loc_DFAE move.w #1,d4 loc_DFAE: tst.w d4 beq.s loc_DFDC lsl.w #6,d2 move.l d0,VDP_control_port-VDP_data_port(a6) lea (a1,d2.w),a3 rept 16 move.l (a3)+,(a6) endm loc_DFDC: addi.l #$40<<16,d0 dbf d6,loc_DF98 rts ; End of function DrawSixDigitNumber ; --------------------------------------------------------------------------- move.l #vdpComm(tiles_to_bytes($6FC),VRAM,WRITE),(VDP_control_port).l lea (VDP_data_port).l,a6 lea (dword_E050).l,a2 moveq #2-1,d6 moveq #0,d4 lea ArtUnc_HUDDigits(pc),a1 loc_E006: moveq #0,d2 move.l (a2)+,d3 loc_E00A: sub.l d3,d1 bcs.s loc_E012 addq.w #1,d2 bra.s loc_E00A ; --------------------------------------------------------------------------- loc_E012: add.l d3,d1 lsl.w #6,d2 lea (a1,d2.w),a3 rept 16 move.l (a3)+,(a6) endm dbf d6,loc_E006 rts ; --------------------------------------------------------------------------- dword_E040: dc.l 100000 dc.l 10000 dword_E048: dc.l 1000 dword_E04C: dc.l 100 dword_E050: dc.l 10 dword_E054: dc.l 1 ; =============== S U B R O U T I N E ======================================= DrawSingleDigitNumber: lea (dword_E054).l,a2 moveq #1-1,d6 bra.s loc_E06A ; End of function DrawSingleDigitNumber ; =============== S U B R O U T I N E ======================================= DrawTwoDigitNumber: lea (dword_E050).l,a2 moveq #2-1,d6 loc_E06A: moveq #0,d4 lea ArtUnc_HUDDigits(pc),a1 loc_E070: moveq #0,d2 move.l (a2)+,d3 loc_E074: sub.l d3,d1 bcs.s loc_E07C addq.w #1,d2 bra.s loc_E074 ; --------------------------------------------------------------------------- loc_E07C: add.l d3,d1 tst.w d2 beq.s loc_E086 move.w #1,d4 loc_E086: lsl.w #6,d2 move.l d0,VDP_control_port-VDP_data_port(a6) lea (a1,d2.w),a3 rept 16 move.l (a3)+,(a6) endm addi.l #$40<<16,d0 dbf d6,loc_E070 rts ; End of function DrawTwoDigitNumber ; --------------------------------------------------------------------------- lea (dword_E048).l,a2 moveq #4-1,d6 moveq #0,d4 lea ArtUnc_HUDDigits(pc),a1 loc_E0CA: moveq #0,d2 move.l (a2)+,d3 loc_E0CE: sub.l d3,d1 bcs.s loc_E0D6 addq.w #1,d2 bra.s loc_E0CE ; --------------------------------------------------------------------------- loc_E0D6: add.l d3,d1 tst.w d2 beq.s loc_E0E0 move.w #1,d4 loc_E0E0: tst.w d4 beq.s loc_E110 lsl.w #6,d2 lea (a1,d2.w),a3 rept 16 move.l (a3)+,(a6) endm loc_E10A: dbf d6,loc_E0CA rts ; --------------------------------------------------------------------------- loc_E110: moveq #$10-1,d5 loc_E112: move.l #0,(a6) dbf d5,loc_E112 bra.s loc_E10A ; =============== S U B R O U T I N E ======================================= HUD_Lives: move.l #vdpComm(tiles_to_bytes($7DD),VRAM,WRITE),d0 moveq #0,d1 move.b (Life_count).w,d1 lea (dword_E050).l,a2 moveq #2-1,d6 moveq #0,d4 lea ArtUnc_LivesDigits(pc),a1 loc_E138: move.l d0,VDP_control_port-VDP_data_port(a6) moveq #0,d2 move.l (a2)+,d3 loc_E140: sub.l d3,d1 bcs.s loc_E148 addq.w #1,d2 bra.s loc_E140 ; --------------------------------------------------------------------------- loc_E148: add.l d3,d1 tst.w d2 beq.s loc_E152 move.w #1,d4 loc_E152: tst.w d4 beq.s loc_E178 loc_E156: lsl.w #5,d2 lea (a1,d2.w),a3 rept 8 move.l (a3)+,(a6) endm loc_E16C: addi.l #$40<<16,d0 dbf d6,loc_E138 rts ; --------------------------------------------------------------------------- loc_E178: tst.w d6 beq.s loc_E156 moveq #8-1,d5 loc_E17E: move.l #0,(a6) dbf d5,loc_E17E bra.s loc_E16C ; End of function HUD_Lives ; --------------------------------------------------------------------------- ArtUnc_HUDDigits: binclude "General/Sprites/HUD Icon/HUD Digits.bin" even ArtUnc_LivesDigits: binclude "General/Sprites/HUD Icon/Lives Digits.bin" even ArtUnc_DebugDigits: binclude "General/Sprites/HUD Icon/Debug Digits.bin" even ; =============== S U B R O U T I N E ======================================= Load_Rings: moveq #0,d0 move.b (Rings_manager_routine).w,d0 move.w Load_Rings_Index(pc,d0.w),d0 jmp Load_Rings_Index(pc,d0.w) ; End of function Load_Rings ; --------------------------------------------------------------------------- Load_Rings_Index: dc.w loc_E8BE-Load_Rings_Index dc.w loc_E942-Load_Rings_Index dc.w loc_E9CA-Load_Rings_Index ; --------------------------------------------------------------------------- loc_E8BE: addq.b #2,(Rings_manager_routine).w bsr.w sub_EB1A cmpi.b #$14,(Current_zone).w beq.s loc_E904 movea.l (Ring_start_addr_ROM).w,a1 lea (Ring_status_table).w,a2 move.w (Camera_X_pos).w,d4 subq.w #8,d4 bhi.s loc_E8E6 moveq #1,d4 bra.s loc_E8E6 ; --------------------------------------------------------------------------- loc_E8E2: addq.w #4,a1 addq.w #2,a2 loc_E8E6: cmp.w (a1),d4 bhi.s loc_E8E2 move.l a1,(Ring_start_addr_ROM).w move.w a2,(Ring_start_addr_RAM).w addi.w #$150,d4 bra.s loc_E8FA ; --------------------------------------------------------------------------- loc_E8F8: addq.w #4,a1 loc_E8FA: cmp.w (a1),d4 bhi.s loc_E8F8 move.l a1,(Ring_end_addr_ROM).w rts ; --------------------------------------------------------------------------- loc_E904: addq.b #2,(Rings_manager_routine).w movea.l (Ring_start_addr_ROM).w,a1 lea (Ring_status_table_2).w,a2 move.w (Camera_Y_pos).w,d4 subq.w #8,d4 bhi.s loc_E920 moveq #1,d4 bra.s loc_E920 ; --------------------------------------------------------------------------- loc_E91C: addq.w #4,a1 addq.w #2,a2 loc_E920: cmp.w 2(a1),d4 bhi.s loc_E91C move.l a1,(Ring_start_addr_ROM).w move.w a2,(Ring_start_addr_RAM).w addi.w #$F0,d4 bra.s loc_E936 ; --------------------------------------------------------------------------- loc_E934: addq.w #4,a1 loc_E936: cmp.w 2(a1),d4 bhi.s loc_E934 move.l a1,(Ring_end_addr_ROM).w rts ; --------------------------------------------------------------------------- loc_E942: bsr.s sub_E994 movea.l (Ring_start_addr_ROM).w,a1 movea.w (Ring_start_addr_RAM).w,a2 move.w (Camera_X_pos).w,d4 subq.w #8,d4 bhi.s loc_E95C moveq #1,d4 bra.s loc_E95C ; --------------------------------------------------------------------------- loc_E958: addq.w #4,a1 addq.w #2,a2 loc_E95C: cmp.w (a1),d4 bhi.s loc_E958 bra.s loc_E966 ; --------------------------------------------------------------------------- loc_E962: subq.w #4,a1 subq.w #2,a2 loc_E966: cmp.w -4(a1),d4 bls.s loc_E962 move.l a1,(Ring_start_addr_ROM).w move.w a2,(Ring_start_addr_RAM).w movea.l (Ring_end_addr_ROM).w,a2 addi.w #$150,d4 bra.s loc_E980 ; --------------------------------------------------------------------------- loc_E97E: addq.w #4,a2 loc_E980: cmp.w (a2),d4 bhi.s loc_E97E bra.s loc_E988 ; --------------------------------------------------------------------------- loc_E986: subq.w #4,a2 loc_E988: cmp.w -4(a2),d4 bls.s loc_E986 move.l a2,(Ring_end_addr_ROM).w rts ; =============== S U B R O U T I N E ======================================= sub_E994: lea (Ring_consumption_table).w,a2 move.w (a2)+,d1 subq.w #1,d1 bcs.s locret_E9C8 loc_E99E: move.w (a2)+,d0 beq.s loc_E99E movea.w d0,a1 subq.b #1,(a1) bne.s loc_E9C4 move.b #6,(a1) addq.b #1,1(a1) cmpi.b #8,1(a1) bne.s loc_E9C4 move.w #-1,(a1) clr.w -2(a2) subq.w #1,(Ring_consumption_table).w loc_E9C4: dbf d1,loc_E99E locret_E9C8: rts ; End of function sub_E994 ; --------------------------------------------------------------------------- loc_E9CA: bsr.s sub_E994 movea.l (Ring_start_addr_ROM).w,a1 movea.w (Ring_start_addr_RAM).w,a2 move.w (Camera_Y_pos).w,d4 subq.w #8,d4 bhi.s loc_E9E4 moveq #1,d4 bra.s loc_E9E4 ; --------------------------------------------------------------------------- loc_E9E0: addq.w #4,a1 addq.w #2,a2 loc_E9E4: cmp.w 2(a1),d4 bhi.s loc_E9E0 bra.s loc_E9F0 ; --------------------------------------------------------------------------- loc_E9EC: subq.w #4,a1 subq.w #2,a2 loc_E9F0: cmp.w -2(a1),d4 bls.s loc_E9EC move.l a1,(Ring_start_addr_ROM).w move.w a2,(Ring_start_addr_RAM).w movea.l (Ring_end_addr_ROM).w,a2 addi.w #$F0,d4 bra.s loc_EA0A ; --------------------------------------------------------------------------- loc_EA08: addq.w #4,a2 loc_EA0A: cmp.w 2(a2),d4 bhi.s loc_EA08 bra.s loc_EA14 ; --------------------------------------------------------------------------- loc_EA12: subq.w #4,a2 loc_EA14: cmp.w -2(a2),d4 bls.s loc_EA12 move.l a2,(Ring_end_addr_ROM).w rts ; =============== S U B R O U T I N E ======================================= Test_Ring_Collisions: cmpi.b #90,invulnerability_timer(a0) bhs.w locret_EAE4 movea.l (Ring_start_addr_ROM).w,a1 movea.l (Ring_end_addr_ROM).w,a2 cmpa.l a1,a2 beq.w locret_EAE4 movea.w (Ring_start_addr_RAM).w,a4 btst #Status_LtngShield,status_secondary(a0) ; does Sonic have a Lightning Shield? beq.s Test_Ring_Collisions_NoAttraction move.w x_pos(a0),d2 move.w y_pos(a0),d3 subi.w #$40,d2 subi.w #$40,d3 move.w #6,d1 move.w #$C,d6 move.w #$80,d4 move.w #$80,d5 bra.s Test_Ring_Collisions_NextRing ; --------------------------------------------------------------------------- Test_Ring_Collisions_NoAttraction: 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 move.w #6,d1 move.w #$C,d6 move.w #$10,d4 add.w d5,d5 Test_Ring_Collisions_NextRing: tst.w (a4) bne.w loc_EADA move.w (a1),d0 sub.w d1,d0 sub.w d2,d0 bcc.s loc_EAA0 add.w d6,d0 bcs.s loc_EAA6 bra.w loc_EADA ; --------------------------------------------------------------------------- loc_EAA0: cmp.w d4,d0 bhi.w loc_EADA loc_EAA6: move.w 2(a1),d0 sub.w d1,d0 sub.w d3,d0 bcc.s loc_EAB8 add.w d6,d0 bcs.s loc_EABE bra.w loc_EADA ; --------------------------------------------------------------------------- loc_EAB8: cmp.w d5,d0 bhi.w loc_EADA loc_EABE: btst #Status_LtngShield,status_secondary(a0) ; does Sonic have a Lightning Shield? bne.s Test_Ring_Collisions_AttractRing loc_EAC6: move.w #$604,(a4) bsr.s sub_EAE6 lea (Ring_consumption_list).w,a3 loc_EAD0: tst.w (a3)+ bne.s loc_EAD0 move.w a4,-(a3) addq.w #1,(Ring_consumption_table).w loc_EADA: addq.w #4,a1 addq.w #2,a4 cmpa.l a1,a2 bne.w Test_Ring_Collisions_NextRing locret_EAE4: rts ; End of function Test_Ring_Collisions ; =============== S U B R O U T I N E ======================================= sub_EAE6: subq.w #1,(Perfect_rings_left).w jmp (GiveRing).l ; End of function sub_EAE6 ; --------------------------------------------------------------------------- Test_Ring_Collisions_AttractRing: movea.l a1,a3 jsr (AllocateObject).l bne.w loc_EB16 move.l #Obj_Attracted_Ring,(a1) move.w (a3),x_pos(a1) move.w 2(a3),y_pos(a1) move.w a4,$30(a1) move.w #-1,(a4) rts ; --------------------------------------------------------------------------- loc_EB16: movea.l a3,a1 bra.s loc_EAC6 ; =============== S U B R O U T I N E ======================================= sub_EB1A: moveq #0,d0 tst.b (Respawn_table_keep).w bne.s loc_EB30 lea (Ring_status_table).w,a1 move.w #bytesToLcnt($400),d1 loc_EB2A: move.l d0,(a1)+ dbf d1,loc_EB2A loc_EB30: lea (Ring_consumption_table).w,a1 moveq #bytesToLcnt($80),d1 loc_EB36: move.l d0,(a1)+ dbf d1,loc_EB36 cmpi.b #$14,(Current_zone).w bne.s loc_EB52 lea (Ring_status_table_2).w,a1 move.w #bytesToLcnt($400),d1 loc_EB4C: move.l d0,(a1)+ dbf d1,loc_EB4C loc_EB52: move.w (Current_zone_and_act).w,d0 ror.b #1,d0 lsr.w #5,d0 lea (RingLocPtrs).l,a1 movea.l (a1,d0.w),a1 move.l a1,(Ring_start_addr_ROM).w addq.w #4,a1 moveq #0,d5 move.w #$1FF-1,d0 loc_EB70: tst.l (a1)+ bmi.s loc_EB7A addq.w #1,d5 dbf d0,loc_EB70 loc_EB7A: move.w d5,(Perfect_rings_left).w move.w #0,(_unkFF06).w rts ; End of function sub_EB1A ; =============== S U B R O U T I N E ======================================= Render_Rings: movea.l (Ring_start_addr_ROM).w,a0 move.l (Ring_end_addr_ROM).w,d2 sub.l a0,d2 beq.s locret_EBEC movea.w (Ring_start_addr_RAM).w,a4 lea CMap_Ring(pc),a1 move.w 4(a3),d4 move.w #$F0,d5 move.w (Screen_Y_wrap_value).w,d3 loc_EBA6: tst.w (a4)+ bmi.s loc_EBE6 move.w 2(a0),d1 sub.w d4,d1 addq.w #8,d1 and.w d3,d1 cmp.w d5,d1 bhs.s loc_EBE6 addi.w #$78,d1 move.w (a0),d0 sub.w (a3),d0 addi.w #$80,d0 move.b -1(a4),d6 bne.s loc_EBCE move.b (Rings_frame).w,d6 loc_EBCE: lsl.w #3,d6 lea (a1,d6.w),a2 add.w (a2)+,d1 move.w d1,(a6)+ move.w (a2)+,d6 move.b d6,(a6) addq.w #2,a6 move.w (a2)+,(a6)+ add.w (a2)+,d0 move.w d0,(a6)+ subq.w #1,d7 loc_EBE6: addq.w #4,a0 subq.w #4,d2 bne.s loc_EBA6 locret_EBEC: rts ; End of function Render_Rings ; --------------------------------------------------------------------------- ; Custom mappings format. Compare to Map_Ring. ; Differences include... ; No offset table (each sprite assumed to be 8 bytes) ; No 'sprite pieces per frame' value (hardcoded to 1) ; Sign-extended Y-pos value ; Sign-extended sprite size value CMap_Ring: ;frame1: dc.w -8 dc.w $0005 dc.w $0000+make_art_tile(ArtTile_Ring,1,0) dc.w -8 ;frame2: dc.w -8 dc.w $0005 dc.w $0004+make_art_tile(ArtTile_Ring,1,0) dc.w -8 ;frame3: dc.w -8 dc.w $0001 dc.w $0008+make_art_tile(ArtTile_Ring,1,0) dc.w -4 ;frame4: dc.w -8 dc.w $0005 dc.w $0804+make_art_tile(ArtTile_Ring,1,0) dc.w -8 ;frame5: dc.w -8 dc.w $0005 dc.w $000A+make_art_tile(ArtTile_Ring,1,0) dc.w -8 ;frame6: dc.w -8 dc.w $0005 dc.w $180A+make_art_tile(ArtTile_Ring,1,0) dc.w -8 ;frame7: dc.w -8 dc.w $0005 dc.w $080A+make_art_tile(ArtTile_Ring,1,0) dc.w -8 ;frame8: dc.w -8 dc.w $0005 dc.w $100A+make_art_tile(ArtTile_Ring,1,0) dc.w -8 ; =============== S U B R O U T I N E ======================================= Player_AnglePos: move.l (Primary_collision_addr).w,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s loc_EC42 move.l (Secondary_collision_addr).w,(Collision_addr).w loc_EC42: move.b top_solid_bit(a0),d5 btst #Status_OnObj,status(a0) beq.s loc_EC5A moveq #0,d0 move.b d0,(Primary_Angle).w move.b d0,(Secondary_Angle).w rts ; --------------------------------------------------------------------------- loc_EC5A: 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_EC7C move.b angle(a0),d0 bpl.s loc_EC76 subq.b #1,d0 loc_EC76: addi.b #$20,d0 bra.s loc_EC88 ; --------------------------------------------------------------------------- loc_EC7C: move.b angle(a0),d0 bpl.s loc_EC84 addq.b #1,d0 loc_EC84: addi.b #$1F,d0 loc_EC88: andi.b #$C0,d0 cmpi.b #$40,d0 beq.w Player_WalkVertL cmpi.b #$80,d0 beq.w Player_WalkCeiling cmpi.b #$C0,d0 beq.w Player_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 Player_Angle tst.w d1 beq.s locret_ED12 bpl.s loc_ED14 cmpi.w #-$E,d1 blt.s locret_ED12 add.w d1,y_pos(a0) locret_ED12: rts ; --------------------------------------------------------------------------- loc_ED14: tst.b stick_to_convex(a0) bne.s loc_ED32 move.b x_vel(a0),d0 bpl.s loc_ED22 neg.b d0 loc_ED22: addq.b #4,d0 cmpi.b #$E,d0 blo.s loc_ED2E move.b #$E,d0 loc_ED2E: cmp.b d0,d1 bgt.s loc_ED38 loc_ED32: add.w d1,y_pos(a0) rts ; --------------------------------------------------------------------------- loc_ED38: bset #Status_InAir,status(a0) bclr #Status_Push,status(a0) move.b #1,prev_anim(a0) rts ; End of function Player_AnglePos ; =============== S U B R O U T I N E ======================================= Player_Angle: move.w d0,d3 move.b (Secondary_Angle).w,d2 cmp.w d0,d1 ble.s loc_ED5E move.b (Primary_Angle).w,d2 move.w d1,d3 move.w d0,d1 loc_ED5E: btst #0,d2 bne.s loc_ED7A move.b d2,d0 sub.b angle(a0),d0 bpl.s loc_ED6E neg.b d0 loc_ED6E: cmpi.b #$20,d0 bhs.s loc_ED7A move.b d2,angle(a0) rts ; --------------------------------------------------------------------------- loc_ED7A: move.b angle(a0),d2 addi.b #$20,d2 andi.b #$C0,d2 move.b d2,angle(a0) rts ; End of function Player_Angle ; --------------------------------------------------------------------------- Player_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 Player_Angle tst.w d1 beq.s locret_EE00 bpl.s loc_EE22 cmpi.w #-$E,d1 blt.s loc_EE0E tst.b $41(a0) bne.s loc_EE02 add.w d1,x_pos(a0) locret_EE00: rts ; --------------------------------------------------------------------------- loc_EE02: subq.b #1,$41(a0) move.b #$C0,angle(a0) rts ; --------------------------------------------------------------------------- loc_EE0E: tst.w (Current_zone_and_act).w bne.s locret_EE00 move.b #$C0,angle(a0) move.b #3,$41(a0) rts ; --------------------------------------------------------------------------- loc_EE22: tst.b stick_to_convex(a0) bne.s loc_EE40 move.b y_vel(a0),d0 bpl.s loc_EE30 neg.b d0 loc_EE30: addq.b #4,d0 cmpi.b #$E,d0 blo.s loc_EE3C move.b #$E,d0 loc_EE3C: cmp.b d0,d1 bgt.s loc_EE46 loc_EE40: add.w d1,x_pos(a0) rts ; --------------------------------------------------------------------------- loc_EE46: bset #Status_InAir,status(a0) bclr #Status_Push,status(a0) move.b #1,prev_anim(a0) rts ; --------------------------------------------------------------------------- Player_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 Player_Angle tst.w d1 beq.s locret_EECE bpl.s loc_EED0 cmpi.w #-$E,d1 blt.s locret_EECE sub.w d1,y_pos(a0) locret_EECE: rts ; --------------------------------------------------------------------------- loc_EED0: tst.b stick_to_convex(a0) bne.s loc_EEEE move.b x_vel(a0),d0 bpl.s loc_EEDE neg.b d0 loc_EEDE: addq.b #4,d0 cmpi.b #$E,d0 blo.s loc_EEEA move.b #$E,d0 loc_EEEA: cmp.b d0,d1 bgt.s loc_EEF4 loc_EEEE: sub.w d1,y_pos(a0) rts ; --------------------------------------------------------------------------- loc_EEF4: bset #Status_InAir,status(a0) bclr #Status_Push,status(a0) move.b #1,prev_anim(a0) rts ; --------------------------------------------------------------------------- Player_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 Player_Angle tst.w d1 beq.s locret_EF7C bpl.s loc_EF7E cmpi.w #-$E,d1 blt.s locret_EF7C sub.w d1,x_pos(a0) locret_EF7C: rts ; --------------------------------------------------------------------------- loc_EF7E: tst.b stick_to_convex(a0) bne.s loc_EF9C move.b y_vel(a0),d0 bpl.s loc_EF8C neg.b d0 loc_EF8C: addq.b #4,d0 cmpi.b #$E,d0 blo.s loc_EF98 move.b #$E,d0 loc_EF98: cmp.b d0,d1 bgt.s loc_EFA2 loc_EF9C: sub.w d1,x_pos(a0) rts ; --------------------------------------------------------------------------- loc_EFA2: bset #Status_InAir,status(a0) bclr #Status_Push,status(a0) move.b #1,prev_anim(a0) rts ; --------------------------------------------------------------------------- ;GetFloorPosition_BG Find_Tile_BG: lea (Level_layout_header).w,a1 move.w d2,d0 lsr.w #5,d0 and.w (Layout_row_index_mask).w,d0 move.w $A(a1,d0.w),d0 move.w d3,d1 lsr.w #3,d1 move.w d1,d4 lsr.w #4,d1 add.w d1,d0 moveq #-1,d1 clr.w d1 movea.w d0,a1 move.b (a1),d1 add.w d1,d1 move.w ChunkAddrArray(pc,d1.w),d1 move.w d2,d0 andi.w #$70,d0 add.w d0,d1 andi.w #$E,d4 add.w d4,d1 movea.l d1,a1 rts ; --------------------------------------------------------------------------- ;GetFloorPosition_FG Find_Tile_FG: lea (Level_layout_header).w,a1 move.w d2,d0 lsr.w #5,d0 and.w (Layout_row_index_mask).w,d0 move.w 8(a1,d0.w),d0 move.w d3,d1 lsr.w #3,d1 move.w d1,d4 lsr.w #4,d1 add.w d1,d0 moveq #-1,d1 clr.w d1 movea.w d0,a1 move.b (a1),d1 add.w d1,d1 move.w ChunkAddrArray(pc,d1.w),d1 move.w d2,d0 andi.w #$70,d0 add.w d0,d1 andi.w #$E,d4 add.w d4,d1 movea.l d1,a1 rts ; --------------------------------------------------------------------------- ChunkAddrArray: dc.w 0, $80, $100, $180, $200, $280, $300, $380, $400, $480, $500, $580, $600, $680, $700, $780 dc.w $800, $880, $900, $980, $A00, $A80, $B00, $B80, $C00, $C80, $D00, $D80, $E00, $E80, $F00, $F80 dc.w $1000,$1080,$1100,$1180,$1200,$1280,$1300,$1380,$1400,$1480,$1500,$1580,$1600,$1680,$1700,$1780 dc.w $1800,$1880,$1900,$1980,$1A00,$1A80,$1B00,$1B80,$1C00,$1C80,$1D00,$1D80,$1E00,$1E80,$1F00,$1F80 dc.w $2000,$2080,$2100,$2180,$2200,$2280,$2300,$2380,$2400,$2480,$2500,$2580,$2600,$2680,$2700,$2780 dc.w $2800,$2880,$2900,$2980,$2A00,$2A80,$2B00,$2B80,$2C00,$2C80,$2D00,$2D80,$2E00,$2E80,$2F00,$2F80 dc.w $3000,$3080,$3100,$3180,$3200,$3280,$3300,$3380,$3400,$3480,$3500,$3580,$3600,$3680,$3700,$3780 dc.w $3800,$3880,$3900,$3980,$3A00,$3A80,$3B00,$3B80,$3C00,$3C80,$3D00,$3D80,$3E00,$3E80,$3F00,$3F80 dc.w $4000,$4080,$4100,$4180,$4200,$4280,$4300,$4380,$4400,$4480,$4500,$4580,$4600,$4680,$4700,$4780 dc.w $4800,$4880,$4900,$4980,$4A00,$4A80,$4B00,$4B80,$4C00,$4C80,$4D00,$4D80,$4E00,$4E80,$4F00,$4F80 dc.w $5000,$5080,$5100,$5180,$5200,$5280,$5300,$5380,$5400,$5480,$5500,$5580,$5600,$5680,$5700,$5780 dc.w $5800,$5880,$5900,$5980,$5A00,$5A80,$5B00,$5B80,$5C00,$5C80,$5D00,$5D80,$5E00,$5E80,$5F00,$5F80 dc.w $6000,$6080,$6100,$6180,$6200,$6280,$6300,$6380,$6400,$6480,$6500,$6580,$6600,$6680,$6700,$6780 dc.w $6800,$6880,$6900,$6980,$6A00,$6A80,$6B00,$6B80,$6C00,$6C80,$6D00,$6D80,$6E00,$6E80,$6F00,$6F80 dc.w $7000,$7080,$7100,$7180,$7200,$7280,$7300,$7380,$7400,$7480,$7500,$7580,$7600,$7680,$7700,$7780 dc.w $7800,$7880,$7900,$7980,$7A00,$7A80,$7B00,$7B80,$7C00,$7C80,$7D00,$7D80,$7E00,$7E80,$7F00,$7F80 ; =============== S U B R O U T I N E ======================================= FindFloor: lea (Find_Tile_FG).l,a5 tst.b (Background_collision_flag).w beq.s sub_F264 bsr.s sub_F264 move.b (a4),Primary_Angle_save-Primary_Angle(a4) move.w d1,-(sp) sub.w (Camera_X_diff).w,d3 sub.w (Camera_Y_diff).w,d2 lea (Find_Tile_BG).l,a5 bsr.s sub_F264 add.w (Camera_X_diff).w,d3 add.w (Camera_Y_diff).w,d2 move.w (sp)+,d0 cmp.w d0,d1 ble.s locret_F262 move.b Primary_Angle_save-Primary_Angle(a4),(a4) move.w d0,d1 locret_F262: rts ; End of function FindFloor ; =============== S U B R O U T I N E ======================================= sub_F264: jsr (a5) move.w (a1),d0 move.w d0,d4 andi.w #$3FF,d0 beq.s loc_F274 btst d5,d4 bne.s loc_F282 loc_F274: add.w a3,d2 bsr.w sub_F30C sub.w a3,d2 addi.w #$10,d1 rts ; --------------------------------------------------------------------------- loc_F282: movea.l (Collision_addr).w,a2 add.w d0,d0 move.b (a2,d0.w),d0 andi.w #$FF,d0 beq.s loc_F274 lea (AngleArray).l,a2 move.b (a2,d0.w),(a4) lsl.w #4,d0 move.w d3,d1 btst #$A,d4 beq.s loc_F2AA not.w d1 neg.b (a4) loc_F2AA: btst #$B,d4 beq.s loc_F2BA addi.b #$40,(a4) neg.b (a4) subi.b #$40,(a4) loc_F2BA: andi.w #$F,d1 add.w d0,d1 lea (HeightMaps).l,a2 move.b (a2,d1.w),d0 ext.w d0 eor.w d6,d4 btst #$B,d4 beq.s loc_F2D6 neg.w d0 loc_F2D6: tst.w d0 beq.s loc_F274 bmi.s loc_F2F2 cmpi.b #$10,d0 beq.s loc_F2FE move.w d2,d1 andi.w #$F,d1 add.w d1,d0 move.w #$F,d1 sub.w d0,d1 rts ; --------------------------------------------------------------------------- loc_F2F2: move.w d2,d1 andi.w #$F,d1 add.w d1,d0 bpl.w loc_F274 loc_F2FE: sub.w a3,d2 bsr.w sub_F30C add.w a3,d2 subi.w #$10,d1 rts ; End of function sub_F264 ; =============== S U B R O U T I N E ======================================= sub_F30C: jsr (a5) move.w (a1),d0 move.w d0,d4 andi.w #$3FF,d0 beq.s loc_F31C btst d5,d4 bne.s loc_F32A loc_F31C: move.w #$F,d1 move.w d2,d0 andi.w #$F,d0 sub.w d0,d1 rts ; --------------------------------------------------------------------------- loc_F32A: movea.l (Collision_addr).w,a2 add.w d0,d0 move.b (a2,d0.w),d0 andi.w #$FF,d0 beq.s loc_F31C lea (AngleArray).l,a2 move.b (a2,d0.w),(a4) lsl.w #4,d0 move.w d3,d1 btst #$A,d4 beq.s loc_F352 not.w d1 neg.b (a4) loc_F352: btst #$B,d4 beq.s loc_F362 addi.b #$40,(a4) neg.b (a4) subi.b #$40,(a4) loc_F362: andi.w #$F,d1 add.w d0,d1 lea (HeightMaps).l,a2 move.b (a2,d1.w),d0 ext.w d0 eor.w d6,d4 btst #$B,d4 beq.s loc_F37E neg.w d0 loc_F37E: tst.w d0 beq.s loc_F31C bmi.s loc_F394 move.w d2,d1 andi.w #$F,d1 add.w d1,d0 move.w #$F,d1 sub.w d0,d1 rts ; --------------------------------------------------------------------------- loc_F394: move.w d2,d1 andi.w #$F,d1 add.w d1,d0 bpl.w loc_F31C not.w d1 rts ; End of function sub_F30C ; --------------------------------------------------------------------------- ;loc_F3A4 Ring_FindFloor: lea (Find_Tile_FG).l,a5 tst.b (Background_collision_flag).w beq.s sub_F3DE bsr.s sub_F3DE move.b (a4),Primary_Angle_save-Primary_Angle(a4) move.w d1,-(sp) sub.w (Camera_X_diff).w,d3 sub.w (Camera_Y_diff).w,d2 lea (Find_Tile_BG).l,a5 bsr.s sub_F3DE add.w (Camera_X_diff).w,d3 add.w (Camera_Y_diff).w,d2 move.w (sp)+,d0 cmp.w d0,d1 ble.s locret_F3DC move.b Primary_Angle_save-Primary_Angle(a4),(a4) move.w d0,d1 locret_F3DC: rts ; =============== S U B R O U T I N E ======================================= sub_F3DE: jsr (a5) move.w (a1),d0 move.w d0,d4 andi.w #$3FF,d0 beq.s loc_F3EE btst d5,d4 bne.s loc_F3F4 loc_F3EE: move.w #$10,d1 rts ; --------------------------------------------------------------------------- loc_F3F4: movea.l (Collision_addr).w,a2 add.w d0,d0 move.b (a2,d0.w),d0 andi.w #$FF,d0 beq.s loc_F3EE lea (AngleArray).l,a2 move.b (a2,d0.w),(a4) lsl.w #4,d0 move.w d3,d1 btst #$A,d4 beq.s loc_F41C not.w d1 neg.b (a4) loc_F41C: btst #$B,d4 beq.s loc_F42C addi.b #$40,(a4) neg.b (a4) subi.b #$40,(a4) loc_F42C: andi.w #$F,d1 add.w d0,d1 lea (HeightMaps).l,a2 move.b (a2,d1.w),d0 ext.w d0 eor.w d6,d4 btst #$B,d4 beq.s loc_F448 neg.w d0 loc_F448: tst.w d0 beq.s loc_F3EE bmi.s loc_F464 cmpi.b #$10,d0 beq.s loc_F470 move.w d2,d1 andi.w #$F,d1 add.w d1,d0 move.w #$F,d1 sub.w d0,d1 rts ; --------------------------------------------------------------------------- loc_F464: move.w d2,d1 andi.w #$F,d1 add.w d1,d0 bpl.w loc_F3EE loc_F470: sub.w a3,d2 bsr.w sub_F30C add.w a3,d2 subi.w #$10,d1 rts ; End of function sub_F3DE ; =============== S U B R O U T I N E ======================================= FindWall: lea (Find_Tile_FG).l,a5 tst.b (Background_collision_flag).w beq.s sub_F4DC bsr.s sub_F4DC move.b (a4),Primary_Angle_save-Primary_Angle(a4) move.w d1,-(sp) move.w a3,d0 bpl.s loc_F4A4 eori.w #$F,d3 sub.w (Camera_X_diff).w,d3 eori.w #$F,d3 bra.s loc_F4A8 ; --------------------------------------------------------------------------- loc_F4A4: sub.w (Camera_X_diff).w,d3 loc_F4A8: sub.w (Camera_Y_diff).w,d2 lea (Find_Tile_BG).l,a5 bsr.s sub_F4DC move.w a3,d0 bpl.s loc_F4C6 eori.w #$F,d3 add.w (Camera_X_diff).w,d3 eori.w #$F,d3 bra.s loc_F4CA ; --------------------------------------------------------------------------- loc_F4C6: add.w (Camera_X_diff).w,d3 loc_F4CA: add.w (Camera_Y_diff).w,d2 move.w (sp)+,d0 cmp.w d0,d1 ble.s locret_F4DA move.b Primary_Angle_save-Primary_Angle(a4),(a4) move.w d0,d1 locret_F4DA: rts ; End of function FindWall ; =============== S U B R O U T I N E ======================================= sub_F4DC: jsr (a5) move.w (a1),d0 move.w d0,d4 andi.w #$3FF,d0 beq.s loc_F4EC btst d5,d4 bne.s loc_F4FA loc_F4EC: add.w a3,d3 bsr.w sub_F584 sub.w a3,d3 addi.w #$10,d1 rts ; --------------------------------------------------------------------------- loc_F4FA: movea.l (Collision_addr).w,a2 add.w d0,d0 move.b (a2,d0.w),d0 andi.w #$FF,d0 beq.s loc_F4EC lea (AngleArray).l,a2 move.b (a2,d0.w),(a4) lsl.w #4,d0 move.w d2,d1 btst #$B,d4 beq.s loc_F52A not.w d1 addi.b #$40,(a4) neg.b (a4) subi.b #$40,(a4) loc_F52A: btst #$A,d4 beq.s loc_F532 neg.b (a4) loc_F532: andi.w #$F,d1 add.w d0,d1 lea (HeightMapsRot).l,a2 move.b (a2,d1.w),d0 ext.w d0 eor.w d6,d4 btst #$A,d4 beq.s loc_F54E neg.w d0 loc_F54E: tst.w d0 beq.s loc_F4EC bmi.s loc_F56A cmpi.b #$10,d0 beq.s loc_F576 move.w d3,d1 andi.w #$F,d1 add.w d1,d0 move.w #$F,d1 sub.w d0,d1 rts ; --------------------------------------------------------------------------- loc_F56A: move.w d3,d1 andi.w #$F,d1 add.w d1,d0 bpl.w loc_F4EC loc_F576: sub.w a3,d3 bsr.w sub_F584 add.w a3,d3 subi.w #$10,d1 rts ; End of function sub_F4DC ; =============== S U B R O U T I N E ======================================= sub_F584: jsr (a5) move.w (a1),d0 move.w d0,d4 andi.w #$3FF,d0 beq.s loc_F594 btst d5,d4 bne.s loc_F5A2 loc_F594: move.w #$F,d1 move.w d3,d0 andi.w #$F,d0 sub.w d0,d1 rts ; --------------------------------------------------------------------------- loc_F5A2: movea.l (Collision_addr).w,a2 add.w d0,d0 move.b (a2,d0.w),d0 andi.w #$FF,d0 beq.s loc_F594 lea (AngleArray).l,a2 move.b (a2,d0.w),(a4) lsl.w #4,d0 move.w d2,d1 btst #$B,d4 beq.s loc_F5D2 not.w d1 addi.b #$40,(a4) neg.b (a4) subi.b #$40,(a4) loc_F5D2: btst #$A,d4 beq.s loc_F5DA neg.b (a4) loc_F5DA: andi.w #$F,d1 add.w d0,d1 lea (HeightMapsRot).l,a2 move.b (a2,d1.w),d0 ext.w d0 eor.w d6,d4 btst #$A,d4 beq.s loc_F5F6 neg.w d0 loc_F5F6: tst.w d0 beq.s loc_F594 bmi.s loc_F60C move.w d3,d1 andi.w #$F,d1 add.w d1,d0 move.w #$F,d1 sub.w d0,d1 rts ; --------------------------------------------------------------------------- loc_F60C: move.w d3,d1 andi.w #$F,d1 add.w d1,d0 bpl.w loc_F594 not.w d1 rts ; End of function sub_F584 ; =============== S U B R O U T I N E ======================================= sub_F61C: tst.w (Competition_mode).w bne.w sub_F6B4 move.l (Primary_collision_addr).w,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s loc_F638 move.l (Secondary_collision_addr).w,(Collision_addr).w loc_F638: move.b lrb_solid_bit(a0),d5 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 tst.b (Reverse_gravity_flag).w beq.s loc_F65A neg.w d1 loc_F65A: 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_F680 move.b d1,d0 bpl.s loc_F67A subq.b #1,d0 loc_F67A: addi.b #$20,d0 bra.s loc_F68A ; --------------------------------------------------------------------------- loc_F680: move.b d1,d0 bpl.s loc_F686 addq.b #1,d0 loc_F686: addi.b #$1F,d0 loc_F68A: andi.b #$C0,d0 beq.w CheckFloorDist_Part2 cmpi.b #$80,d0 beq.w CheckCeilingDist_Part2 tst.w (Competition_mode).w bne.s loc_F6A8 andi.b #$38,d1 bne.s loc_F6A8 addq.w #8,d2 loc_F6A8: cmpi.b #$40,d0 beq.w loc_FDA8 bra.w loc_FA88 ; End of function sub_F61C ; =============== S U B R O U T I N E ======================================= sub_F6B4: move.l (Primary_collision_addr).w,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s loc_F6C8 move.l (Secondary_collision_addr).w,(Collision_addr).w loc_F6C8: move.b lrb_solid_bit(a0),d5 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_F708 move.b d1,d0 bpl.s loc_F702 subq.b #1,d0 loc_F702: addi.b #$20,d0 bra.s loc_F712 ; --------------------------------------------------------------------------- loc_F708: move.b d1,d0 bpl.s loc_F70E addq.b #1,d0 loc_F70E: addi.b #$1F,d0 loc_F712: andi.b #$C0,d0 beq.w sub_F828 cmpi.b #$80,d0 beq.w CheckCeilingDist_WithRadius cmpi.b #$40,d0 beq.w loc_FDC8 bra.w loc_FAA4 ; End of function sub_F6B4 ; --------------------------------------------------------------------------- ; 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 ======================================= CalcRoomOverHead: move.l (Primary_collision_addr).w,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s loc_F742 move.l (Secondary_collision_addr).w,(Collision_addr).w loc_F742: 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 ======================================= Sonic_CheckFloor: move.l (Primary_collision_addr).w,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s loc_F782 move.l (Secondary_collision_addr).w,(Collision_addr).w loc_F782: 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_F7E2: move.b (Secondary_Angle).w,d3 cmp.w d0,d1 ble.s loc_F7F0 move.b (Primary_Angle).w,d3 exg d0,d1 loc_F7F0: btst #0,d3 beq.s locret_F7F8 move.b d2,d3 locret_F7F8: rts ; End of function Sonic_CheckFloor ; --------------------------------------------------------------------------- CheckFloorDist: ; unused/dead code move.w y_pos(a0),d2 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 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_F81A: move.b (Primary_Angle).w,d3 btst #0,d3 beq.s locret_F826 move.b d2,d3 locret_F826: rts ; =============== S U B R O U T I N E ======================================= sub_F828: move.b x_radius(a0),d0 ext.w d0 add.w d0,d2 lea (Primary_Angle).w,a4 movea.w #$10,a3 move.w #0,d6 bsr.w FindFloor move.b #0,d2 bra.s loc_F81A ; End of function sub_F828 ; =============== S U B R O U T I N E ======================================= sub_F846: move.w x_pos(a0),d3 move.w y_pos(a0),d2 subq.w #4,d2 move.l (Primary_collision_addr).w,(Collision_addr).w cmpi.b #$D,lrb_solid_bit(a0) beq.s loc_F864 move.l (Secondary_collision_addr).w,(Collision_addr).w loc_F864: lea (Primary_Angle).w,a4 move.b #0,(a4) movea.w #$10,a3 move.w #0,d6 move.b lrb_solid_bit(a0),d5 movem.l a4-a6,-(sp) bsr.w FindFloor movem.l (sp)+,a4-a6 move.b (Primary_Angle).w,d3 btst #0,d3 beq.s locret_F892 move.b #0,d3 locret_F892: rts ; End of function sub_F846 ; =============== S U B R O U T I N E ======================================= ChkFloorEdge: move.w x_pos(a0),d3 ChkFloorEdge_Part2: move.w y_pos(a0),d2 moveq #0,d0 move.b y_radius(a0),d0 ext.w d0 add.w d0,d2 ChkFloorEdge_Part3: move.l (Primary_collision_addr).w,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s loc_F8BA move.l (Secondary_collision_addr).w,(Collision_addr).w loc_F8BA: lea (Primary_Angle).w,a4 move.b #0,(a4) movea.w #$10,a3 move.w #0,d6 move.b top_solid_bit(a0),d5 movem.l a4-a6,-(sp) bsr.w FindFloor movem.l (sp)+,a4-a6 move.b (Primary_Angle).w,d3 btst #0,d3 beq.s locret_F8E8 move.b #0,d3 locret_F8E8: rts ; End of function ChkFloorEdge_Part3 ; =============== S U B R O U T I N E ======================================= SonicOnObjHitFloor: 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_addr).w,(Collision_addr).w cmpi.b #$C,top_solid_bit(a1) beq.s loc_F910 move.l (Secondary_collision_addr).w,(Collision_addr).w loc_F910: 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 locret_F936 move.b #0,d3 locret_F936: rts ; End of function SonicOnObjHitFloor ; --------------------------------------------------------------------------- ; 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 ======================================= ObjCheckFloorDist: move.w x_pos(a0),d3 ObjCheckFloorDist2: move.w y_pos(a0),d2 ; Get object position move.b y_radius(a0),d0 ; Get object height 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 locret_F96C move.b #0,d3 locret_F96C: rts ; End of function ObjCheckFloorDist ; --------------------------------------------------------------------------- ; --------------------------------------------------------------------------- ; Unused collision check used in S2 to let the HTZ boss fire attack hit the ground ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= 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 ; =============== S U B R O U T I N E ======================================= 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 ; --------------------------------------------------------------------------- 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_F7E2 ; =============== S U B R O U T I N E ======================================= sub_FA1A: 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 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 FindWall 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 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_F7E2 ; End of function sub_FA1A ; =============== S U B R O U T I N E ======================================= CheckRightWallDist: move.w y_pos(a0),d2 move.w x_pos(a0),d3 tst.w (Competition_mode).w bne.s loc_FAA4 loc_FA88: 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_F81A ; --------------------------------------------------------------------------- loc_FAA4: 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 FindWall move.b #-$40,d2 bra.w loc_F81A ; End of function CheckRightWallDist ; =============== S U B R O U T I N E ======================================= 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 locret_FAF0 move.b #-$40,d3 locret_FAF0: rts ; End of function ObjCheckRightWallDist ; =============== S U B R O U T I N E ======================================= 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 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_F7E2 ; End of function Sonic_CheckCeiling ; =============== S U B R O U T I N E ======================================= sub_FB5A: 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 subq.w #2,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 subq.w #2,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_F7E2 ; End of function sub_FB5A ; --------------------------------------------------------------------------- CheckCeilingDist: ; unused/dead code move.w y_pos(a0),d2 move.w x_pos(a0),d3 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_F81A ; --------------------------------------------------------------------------- ;sub_FBEE CheckCeilingDist_WithRadius: move.b x_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 bsr.w FindFloor move.b #$80,d2 bra.w loc_F81A ; =============== S U B R O U T I N E ======================================= 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 locret_FC48 move.b #$80,d3 locret_FC48: rts ; End of function ObjCheckCeilingDist ; --------------------------------------------------------------------------- ChkFloorEdge_ReverseGravity: move.w y_pos(a0),d2 moveq #0,d0 move.b y_radius(a0),d0 ext.w d0 sub.w d0,d2 eori.w #$F,d2 ChkFloorEdge_ReverseGravity_Part2: move.l (Primary_collision_addr).w,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s loc_FC70 move.l (Secondary_collision_addr).w,(Collision_addr).w loc_FC70: lea (Primary_Angle).w,a4 move.b #0,(a4) movea.w #-$10,a3 move.w #$800,d6 move.b top_solid_bit(a0),d5 movem.l a4-a6,-(sp) bsr.w FindFloor movem.l (sp)+,a4-a6 move.b (Primary_Angle).w,d3 btst #0,d3 beq.s locret_FC9E move.b #0,d3 locret_FC9E: rts ; End of function ChkFloorEdge_ReverseGravity_Part2 ; =============== S U B R O U T I N E ======================================= ;sub_FCA0 RingCheckFloorDist_ReverseGravity: move.w x_pos(a0),d3 move.w y_pos(a0),d2 move.b y_radius(a0),d0 ext.w d0 sub.w d0,d2 eori.w #$F,d2 lea (Primary_Angle).w,a4 move.b #0,(a4) movea.w #-$10,a3 move.w #$800,d6 moveq #$C,d5 bra.w Ring_FindFloor ; End of function RingCheckFloorDist_ReverseGravity ; --------------------------------------------------------------------------- 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_F7E2 ; =============== S U B R O U T I N E ======================================= sub_FD32: 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 move.b x_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 y_radius(a0),d0 ext.w d0 add.w d0,d2 move.b x_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_F7E2 ; End of function sub_FD32 ; =============== S U B R O U T I N E ======================================= CheckLeftWallDist: move.w y_pos(a0),d2 move.w x_pos(a0),d3 tst.w (Competition_mode).w bne.s loc_FDC8 loc_FDA8: 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_F81A ; --------------------------------------------------------------------------- loc_FDC8: move.b x_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.b #$40,d2 bra.w loc_F81A ; End of function CheckLeftWallDist ; =============== S U B R O U T I N E ======================================= sub_FDEC: move.l (Primary_collision_addr).w,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s loc_FE00 move.l (Secondary_collision_addr).w,(Collision_addr).w loc_FE00: move.w x_pos(a0),d3 move.w y_pos(a0),d2 move.b y_radius(a0),d0 ext.w d0 sub.w d0,d3 eori.w #$F,d3 lea (Primary_Angle).w,a4 move.b #0,(a4) movea.w #-$10,a3 move.w #$400,d6 move.b lrb_solid_bit(a0),d5 bsr.w FindWall move.b (Primary_Angle).w,d3 btst #0,d3 beq.s locret_FE3A move.b #$40,d3 locret_FE3A: rts ; End of function sub_FDEC ; =============== S U B R O U T I N E ======================================= ObjCheckLeftWallDist: add.w x_pos(a0),d3 eori.w #$F,d3 ; this was not here in S1/S2/S3, resulting in a bug ObjCheckLeftWallDist_Part2: move.w y_pos(a0),d2 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 locret_FE6C move.b #$40,d3 locret_FE6C: rts ; End of function ObjCheckLeftWallDist ; =============== S U B R O U T I N E ======================================= TouchResponse_CompetitionMode: nop move.w x_pos(a0),d2 ; Get player's x_pos move.w y_pos(a0),d3 ; Get player's y_pos subi.w #4,d2 ; Subtract Obj_Sonic2P's x_radius-1 from x_pos moveq #0,d5 move.b y_radius(a0),d5 subq.b #3,d5 sub.w d5,d3 move.w #8,d4 ; Player's width add.w d5,d5 bra.s Touch_Process ; --------------------------------------------------------------------------- TouchResponse: nop jsr (Test_Ring_Collisions).l bsr.w ShieldTouchResponse tst.b character_id(a0) ; Is the player Sonic? bne.s Touch_NoInstaShield ; If not, branch move.b status_secondary(a0),d0 andi.b #$73,d0 ; Does the player have any shields or is invincible? bne.s Touch_NoInstaShield ; If so, branch ; By this point, we're focussing purely on the Insta-Shield cmpi.b #1,double_jump_flag(a0) ; Is the Insta-Shield currently in its 'attacking' mode? bne.s Touch_NoInstaShield ; If not, branch move.b status_secondary(a0),d0 ; Get status_secondary... move.w d0,-(sp) ; ...and save it bset #Status_Invincible,status_secondary(a0) ; Make the player invincible move.w x_pos(a0),d2 ; Get player's x_pos move.w y_pos(a0),d3 ; Get player's y_pos subi.w #$18,d2 ; Subtract width of Insta-Shield subi.w #$18,d3 ; Subtract height of Insta-Shield move.w #$30,d4 ; Player's width move.w #$30,d5 ; Player's height bsr.s Touch_Process move.w (sp)+,d0 ; Get the backed-up status_secondary btst #Status_Invincible,d0 ; Was the player already invincible (wait, what? An earlier check ensures that this can't happen) bne.s .alreadyinvincible ; If so, branch bclr #Status_Invincible,status_secondary(a0) ; Make the player vulnerable again .alreadyinvincible: moveq #0,d0 rts ; --------------------------------------------------------------------------- Touch_NoInstaShield: move.w x_pos(a0),d2 ; Get player's x_pos move.w y_pos(a0),d3 ; Get player's y_pos subi.w #8,d2 ; Subtract Obj_Sonic's x_radius-1 from x_pos (becomes player's left collision boundary) moveq #0,d5 move.b y_radius(a0),d5 subq.b #3,d5 ; Now player's collision height sub.w d5,d3 ; Note the lack of a check for if the player is ducking ; Height is no longer reduced by ducking move.w #$10,d4 ; Player's collision width add.w d5,d5 Touch_Process: lea (Collision_response_list).w,a4 move.w (a4)+,d6 ; Get number of objects queued beq.s locret_FF1C ; If there are none, return Touch_Loop: movea.w (a4)+,a1 ; Get address of first object's RAM move.b collision_flags(a1),d0 ; Get its collision_flags bne.s Touch_Width ; If it actually has collision, branch Touch_NextObj: subq.w #2,d6 ; Count the object as done bne.s Touch_Loop ; If there are still objects left, loop moveq #0,d0 locret_FF1C: rts ; --------------------------------------------------------------------------- Touch_Width: andi.w #$3F,d0 ; Get only collision size add.w d0,d0 ; Turn into index lea Touch_Sizes(pc,d0.w),a2 moveq #0,d1 move.b (a2)+,d1 ; Get width value from Touch_Sizes move.w x_pos(a1),d0 ; Get object's x_pos sub.w d1,d0 ; Subtract object's width sub.w d2,d0 ; Subtract player's left collision boundary bcc.s .checkrightside ; If player's left side is to the left of the object, branch add.w d1,d1 ; Double object's width value add.w d1,d0 ; Add object's width*2 (now at right of object) bcs.s Touch_Height ; If carry, branch (player is within the object's boundaries) bra.s Touch_NextObj ; If not, loop and check next object ; --------------------------------------------------------------------------- .checkrightside: cmp.w d4,d0 ; Is player's right side to the left of the object? bhi.s Touch_NextObj ; If so, loop and check next object Touch_Height: moveq #0,d1 move.b (a2)+,d1 ; Get height value from Touch_Sizes move.w y_pos(a1),d0 ; Get object's y_pos sub.w d1,d0 ; Subtract object's height sub.w d3,d0 ; Subtract player's bottom collision boundary bcc.s .checktop ; If bottom of player is under the object, branch add.w d1,d1 ; Double object's height value add.w d1,d0 ; Add object's height*2 (now at top of object) bcs.w Touch_ChkValue ; If carry, branch (player is within the object's boundaries) bra.s Touch_NextObj ; If not, loop and check next object ; --------------------------------------------------------------------------- .checktop: cmp.w d5,d0 ; Is top of player under the object? bhi.s Touch_NextObj ; If so, loop and check next object bra.w Touch_ChkValue ; --------------------------------------------------------------------------- ; collision sizes (width,height) Touch_Sizes: dc.b 4, 4 dc.b $14, $14 dc.b $C, $14 dc.b $14, $C dc.b 4, $10 dc.b $C, $12 dc.b $10, $10 dc.b 6, 6 dc.b $18, $C dc.b $C, $10 dc.b $10, 8 dc.b 8, 8 dc.b $14, $10 dc.b $14, 8 dc.b $E, $E dc.b $18, $18 dc.b $28, $10 dc.b $10, $18 dc.b 8, $10 dc.b $20, $70 dc.b $40, $20 dc.b $80, $20 dc.b $20, $20 dc.b 8, 8 dc.b 4, 4 dc.b $20, 8 dc.b $C, $C dc.b 8, 4 dc.b $18, 4 dc.b $28, 4 dc.b 4, 8 dc.b 4, $18 dc.b 4, $28 dc.b $18, $18 dc.b $18, $18 dc.b $C, $18 dc.b $48, 8 dc.b $18, $28 dc.b $10, 4 dc.b $20, 2 dc.b $10, $1C dc.b $C, $24 dc.b $10, 2 dc.b 4, $40 dc.b $18, $40 dc.b $20, $10 dc.b $1C, $14 dc.b $10, 2 dc.b $10, 1 dc.b 2, 8 dc.b $10, $40 dc.b $C, 4 dc.b 8, $C dc.b $28, $20 dc.b $40, 2 dc.b $60, 2 dc.b $28, $28 ; --------------------------------------------------------------------------- Touch_ChkValue: move.b collision_flags(a1),d1 ; Get its collision_flags andi.b #$C0,d1 ; Get only collision type bits beq.w Touch_Enemy ; If 00, enemy, branch cmpi.b #$C0,d1 beq.w Touch_Special ; If 11, "special thing for starpole", branch tst.b d1 bmi.w Touch_ChkHurt ; If 10, "harmful", branch ; If 01... move.b collision_flags(a1),d0 ; Get collision_flags andi.b #$3F,d0 ; Get only collision size cmpi.b #6,d0 ; Is touch response $46 ? beq.s Touch_Monitor ; If yes, branch move.b (Player_1+invulnerability_timer).w,d0 ; Get the main character's invulnerability_timer tst.w (Competition_mode).w ; Is the competition mode? beq.s .notcompetition ; If not, branch move.b invulnerability_timer(a0),d0 ; Get invulnerability_timer from whoever branched to TouchResponse .notcompetition: cmpi.b #90,d0 ; Is there more than 90 frames on the timer remaining? bhs.w .return ; If so, branch move.b #4,routine(a1) ; Set target object's routine to 4 (must be reserved for collision response) .return: rts ; --------------------------------------------------------------------------- Touch_Monitor: move.w y_vel(a0),d0 ; Get player's y_vel tst.b (Reverse_gravity_flag).w ; Are we in reverse gravity mode? beq.s .normalgravity ; If not, branch neg.w d0 ; Negate player's y_vel .normalgravity: btst #1,render_flags(a1) ; Is the monitor upside down? beq.s .monitornotupsidedown ; If not, branch tst.w d0 beq.s .checkdestroy ; If player isn't moving up or down at all, branch bmi.s .checkdestroy ; If player is moving up, branch bra.s .checkfall ; If player is moving down, branch ; --------------------------------------------------------------------------- .monitornotupsidedown: tst.w d0 bpl.s .checkdestroy ; If player is moving down, branch .checkfall: ; This check is responsible for S&K's monitors not falling if hit from below (but only in regular gravity. See below) btst #1,status(a1) ; Is the monitor upside down (different way of checking)? beq.s .checkdestroy ; If not, branch btst #1,render_flags(a1) ; Is the monitor upside down? bne.s .monitorupsidedown ; If so, branch move.w y_pos(a0),d0 ; Get player's y_pos subi.w #$10,d0 ; Subtract height of monitor from it cmp.w y_pos(a1),d0 blo.s .return ; If new value is lower than monitor's y_pos, return bra.s .monitorfall ; --------------------------------------------------------------------------- .monitorupsidedown: move.w y_pos(a0),d0 ; Get player's y_pos addi.w #$10,d0 ; Add height of monitor from it cmp.w y_pos(a1),d0 bhs.s .return ; If new value is higher than monitor's y_pos, return .monitorfall: ; Fun fact: In S3, like the games before it, hitting a monitor from below would make it fall ; In S&K, that was removed, and they are destroyed as normal. ; However, according to this code, if a monitor is upside down, and player is in reverse gravity, ; hitting the monitor from below will still make it fall. ; Playing with Debug Mode confirms this. neg.w y_vel(a0) ; Reverse Sonic's y-motion move.w #-$180,y_vel(a1) tst.b routine_secondary(a1) bne.s .return move.b #4,routine_secondary(a1) ; Set the monitor's routine_secondary counter rts ; --------------------------------------------------------------------------- .checkdestroy: cmpa.w #Player_1,a0 ; Is this the main character? beq.s .validcharacter ; If so, branch tst.w (Competition_mode).w ; Are we in competition mode? beq.s .return ; If not, return .validcharacter: cmpi.b #2,anim(a0) ; Is player in his rolling animation? beq.s .okaytodestroy ; If so, branch cmpi.b #2,character_id(a0) ; Is player Knuckles? bne.s .return ; If not, return cmpi.b #1,double_jump_flag(a0) ; Is Knuckles gliding? beq.s .okaytodestroy ; If so, branch cmpi.b #3,double_jump_flag(a0) ; Is Knuckles sliding across the ground after gliding? bne.s .return ; If not, branch .okaytodestroy: neg.w y_vel(a0) move.b #4,routine(a1) move.w a0,parent(a1) .return: rts ; --------------------------------------------------------------------------- Touch_Enemy: btst #Status_Invincible,status_secondary(a0) ; Is player invincible? bne.s .checkhurtenemy ; If so, branch cmpi.b #9,anim(a0) ; Is player in their spin dash animation? beq.s .checkhurtenemy ; If so, branch cmpi.b #2,anim(a0) ; Is player in their rolling animation? beq.s .checkhurtenemy ; If so, branch cmpi.b #2,character_id(a0) ; Is player Knuckles? bne.s .notknuckles ; If not, branch cmpi.b #1,double_jump_flag(a0) ; Is Knuckles gliding? beq.s .checkhurtenemy ; If so, branch cmpi.b #3,double_jump_flag(a0) ; Is Knuckles sliding across the ground after gliding? beq.s .checkhurtenemy ; If so, branch bra.w Touch_ChkHurt ; --------------------------------------------------------------------------- .notknuckles: cmpi.b #1,character_id(a0) ; Is player Tails? bne.w Touch_ChkHurt ; If not, branch tst.b double_jump_flag(a0) ; Is Tails flying ("gravity-affected")? beq.w Touch_ChkHurt ; If not, branch btst #Status_Underwater,status(a0) ; Is Tails underwater? bne.w Touch_ChkHurt ; If not, branch 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 (GetArcTan).l subi.b #$20,d0 cmpi.b #$40,d0 bhs.w Touch_ChkHurt .checkhurtenemy: ; Boss related? Could be special enemies in general tst.b boss_hitcount2(a1) ; Is this a boss? (?) beq.s Touch_EnemyNormal ; If not, branch neg.w x_vel(a0) ; Bounce player directly off boss neg.w y_vel(a0) neg.w ground_vel(a0) move.b collision_flags(a1),$25(a1) ; ??? move.w a0,d0 ; Save value of RAM address of which player hit the boss: move.b d0,$1C(a1) ; ($FFFFB000) for main character, ($FFFFB04A) for sidekick move.b #0,collision_flags(a1) subq.b #1,boss_hitcount2(a1) ; Subtract from boss hit counter bne.s .bossnotdefeated ; If boss is not defeated yet, branch bset #7,status(a1) .bossnotdefeated: cmpi.b #2,character_id(a0) ; Is player Knuckles? bne.s .return ; If not, return cmpi.b #1,double_jump_flag(a0) ; Is Knuckles gliding? bne.s .return ; If not, return move.b #2,double_jump_flag(a0) ; Make him stop gliding move.b #$21,anim(a0) ; Put Knuckles in his falling animation ; Decide which direction to make Knuckles face bclr #0,status(a0) tst.w x_vel(a0) bmi.s .directiondecided bset #0,status(a0) .directiondecided: move.b default_y_radius(a0),y_radius(a0) move.b default_x_radius(a0),x_radius(a0) .return: rts ; --------------------------------------------------------------------------- Touch_EnemyNormal: btst #2,status(a1) ; Should the object remember that it's been destroyed (Remember Sprite State flag)? beq.s .dontremember ; If not, branch move.b ros_bit(a1),d0 movea.w ros_addr(a1),a2 bclr d0,(a2) ; Mark object as destroyed .dontremember: bset #7,status(a1) moveq #0,d0 move.w (Chain_bonus_counter).w,d0 ; Get copy of chain bonus counter addq.w #2,(Chain_bonus_counter).w ; Add 2 to chain bonus counter cmpi.w #6,d0 ; Has the counter already surpassed 5? blo.s .notreachedlimit ; If not, branch moveq #6,d0 ; Cap counter at 6 .notreachedlimit: move.w d0,objoff_3E(a1) move.w Enemy_Points(pc,d0.w),d0 ; Get appropriate number of points cmpi.w #16*2,(Chain_bonus_counter).w ; Have 16 enemies been destroyed? blo.s .notreachedlimit2 ; If not, branch move.w #1000,d0 ; Fix bonus to 10000 points move.w #$A,objoff_3E(a1) .notreachedlimit2: movea.w a0,a3 bsr.w HUD_AddToScore move.l #Obj_Explosion,(a1) ; Create enemy destruction explosion move.b #0,routine(a1) tst.w y_vel(a0) ; Is player moving up? bmi.s .bounceplayerdown ; If so, branch move.w y_pos(a0),d0 cmp.w y_pos(a1),d0 ; Was player above, or at the same height as, the enemy when it was destroyed? bhs.s .bounceplayerup ; If so, branch neg.w y_vel(a0) ; Totally negate velocity (???) rts ; --------------------------------------------------------------------------- .bounceplayerdown: addi.w #$100,y_vel(a0) ; Bounce down rts ; --------------------------------------------------------------------------- .bounceplayerup: subi.w #$100,y_vel(a0) ; Bounce up rts ; --------------------------------------------------------------------------- Enemy_Points: dc.w 10, 20, 50, 100 ; --------------------------------------------------------------------------- ; --------------------------------------------------------------------------- ; Subroutine for checking if Sonic/Tails/Knuckles should be hurt and hurting them if so ; note: character must be at a0 ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Touch_ChkHurt: move.b status_secondary(a0),d0 andi.b #$73,d0 ; Does player have any shields or is invincible? beq.s Touch_ChkHurt_NoPowerUp ; If not, branch and.b shield_reaction(a1),d0 ; Does one of the player's shields grant immunity to this object?? bne.s Touch_ChkHurt_Return ; If so, branch btst #Status_Shield,status_secondary(a0) ; Does the player have a shield (strange time to ask) bne.s Touch_ChkHurt_HaveShield ; If so, branch Touch_ChkHurt2: btst #Status_Invincible,status_secondary(a0) ; Is player invincible? beq.s Touch_Hurt ; If not, branch Touch_ChkHurt_Return: moveq #-1,d0 rts ; --------------------------------------------------------------------------- Touch_ChkHurt_NoPowerUp: ; Note that this check could apply to the Insta-Shield, ; but the check that branches to this requires the player not be invincible. ; The Insta-Shield grants temporary invincibility. See the problem? cmpi.b #1,double_jump_flag(a0) ; Is player Insta-Shield-attacking (Sonic), flying (Tails) or gliding (Knuckles)? bne.s Touch_ChkHurt2 ; If not, branch Touch_ChkHurt_HaveShield: move.b shield_reaction(a1),d0 andi.b #1<<3,d0 ; Should the object be bounced away by a shield? beq.s Touch_ChkHurt2 ; If not, branch Touch_ChkHurt_Bounce_Projectile: 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 (GetArcTan).l jsr (GetSineCosine).l muls.w #-$800,d1 asr.l #8,d1 move.w d1,x_vel(a1) muls.w #-$800,d0 asr.l #8,d0 move.w d0,y_vel(a1) clr.b collision_flags(a1) bra.s Touch_ChkHurt_Return ; --------------------------------------------------------------------------- Touch_Hurt: nop tst.b invulnerability_timer(a0) ; Is the player invulnerable? bne.s Touch_ChkHurt_Return ; If so, branch movea.l a1,a2 ; continue straight to HurtCharacter ; --------------------------------------------------------------------------- ; Hurting Sonic/Tails/Knuckles subroutine ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= HurtCharacter: move.w (Ring_count).w,d0 cmpa.w #Player_1,a0 beq.s loc_102A8 tst.w (Competition_mode).w beq.s loc_102E0 move.w (Ring_count_P2).w,d0 loc_102A8: btst #0,status_secondary(a0) bne.s loc_102DA tst.b status_tertiary(a0) bmi.s loc_102E0 tst.w d0 beq.w loc_10350 jsr (AllocateObject).l bne.s loc_102DA move.l #Obj_Bouncing_Ring,(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w a0,$3E(a1) loc_102DA: andi.b #$8E,status_secondary(a0) loc_102E0: move.b #4,routine(a0) jsr (Player_TouchFloor).l bset #Status_InAir,status(a0) move.w #-$400,y_vel(a0) move.w #-$200,x_vel(a0) btst #Status_Underwater,status(a0) beq.s loc_10312 move.w #-$200,y_vel(a0) move.w #-$100,x_vel(a0) loc_10312: move.w x_pos(a0),d0 cmp.w x_pos(a2),d0 blo.s loc_10320 neg.w x_vel(a0) loc_10320: move.w #0,ground_vel(a0) move.b #$1A,anim(a0) move.b #120,invulnerability_timer(a0) moveq #signextendB(sfx_Death),d0 cmpi.l #Obj_Spikes,(a2) blo.s loc_10346 cmpi.l #sub_24280,(a2) bhs.s loc_10346 moveq #signextendB(sfx_SpikeHit),d0 loc_10346: jsr (Play_SFX).l moveq #-1,d0 rts ; --------------------------------------------------------------------------- loc_10350: moveq #signextendB(sfx_Death),d0 cmpi.l #Obj_Spikes,(a2) blo.s loc_10364 cmpi.l #sub_24280,(a2) bhs.s loc_10364 moveq #signextendB(sfx_SpikeHit),d0 loc_10364: bra.s loc_1036E ; --------------------------------------------------------------------------- Kill_Character: tst.w (Debug_placement_mode).w bne.s loc_103B6 moveq #signextendB(sfx_Death),d0 loc_1036E: clr.b status_secondary(a0) clr.b status_tertiary(a0) move.b #6,routine(a0) move.w d0,-(sp) jsr (Player_TouchFloor).l move.w (sp)+,d0 bset #Status_InAir,status(a0) move.w #-$700,y_vel(a0) move.w #0,x_vel(a0) move.w #0,ground_vel(a0) move.b #$18,anim(a0) move.w art_tile(a0),(Debug_saved_art_tile).w bset #7,art_tile(a0) jsr (Play_SFX).l loc_103B6: moveq #-1,d0 rts ; --------------------------------------------------------------------------- Touch_Special: move.b collision_flags(a1),d1 ; Get collision_flags andi.b #$3F,d1 ; Get only collision size (but that doesn't seems to be its use here) cmpi.b #7,d1 beq.s loc_103FA cmpi.b #6,d1 beq.s loc_103FA cmpi.b #$A,d1 beq.s loc_103FA cmpi.b #$C,d1 beq.s loc_103FA cmpi.b #$15,d1 beq.s loc_103FA cmpi.b #$16,d1 beq.s loc_103FA cmpi.b #$17,d1 beq.s loc_103FA cmpi.b #$18,d1 beq.s loc_103FA cmpi.b #$21,d1 beq.s loc_103FA rts ; --------------------------------------------------------------------------- loc_103FA: move.w a0,d1 ; Get RAM address of what object hit this subi.w #Object_RAM,d1 beq.s .ismaincharacter ; If the main character hit it, branch addq.b #1,collision_property(a1) ; Otherwise, it seems everything else does double .ismaincharacter: addq.b #1,collision_property(a1) ; So hitting a boss with your Tails sidekick does double damage? rts ; =============== S U B R O U T I N E ======================================= Add_SpriteToCollisionResponseList: lea (Collision_response_list).w,a1 cmpi.w #$7E,(a1) ; Is list full? bhs.s .return ; If so, return addq.w #2,(a1) ; Count this new entry adda.w (a1),a1 ; Offset into right area of list move.w a0,(a1) ; Store RAM address in list .return: rts ; End of function Add_SpriteToCollisionResponseList ; =============== S U B R O U T I N E ======================================= ShieldTouchResponse: move.b status_secondary(a0),d0 andi.b #$71,d0 ; Does the player have any shields? beq.s locret_1045C move.w x_pos(a0),d2 ; Get player's x_pos move.w y_pos(a0),d3 ; Get player's y_pos subi.w #$18,d2 ; Subtract width of shield subi.w #$18,d3 ; Subtract height of shield move.w #$30,d4 ; Player's width move.w #$30,d5 ; Player's height lea (Collision_response_list).w,a4 move.w (a4)+,d6 ; Get number of objects queued beq.s locret_1045C ; If there are none, return ShieldTouch_Loop: movea.w (a4)+,a1 ; Get address of first object's RAM move.b collision_flags(a1),d0 ; Get its collision_flags andi.b #$C0,d0 ; Get only collision type bits cmpi.b #$80,d0 ; Is only the high bit set ("harmful")? beq.s ShieldTouch_Width ; If so, branch ShieldTouch_NextObj: subq.w #2,d6 ; Count the object as done bne.s ShieldTouch_Loop ; If there are still objects left, loop locret_1045C: rts ; --------------------------------------------------------------------------- ShieldTouch_Width: move.b collision_flags(a1),d0 ; Get collision_flags andi.w #$3F,d0 ; Get only collision size beq.s ShieldTouch_NextObj ; If it doesn't have a size, branch add.w d0,d0 ; Turn into index lea (Touch_Sizes).l,a2 lea (a2,d0.w),a2 ; Go to correct entry moveq #0,d1 move.b (a2)+,d1 ; Get width value from Touch_Sizes move.w x_pos(a1),d0 ; Get object's x_pos sub.w d1,d0 ; Subtract object's width sub.w d2,d0 ; Subtract player's left collision boundary bhs.s .checkrightside ; If player's left side is to the left of the object, branch add.w d1,d1 ; Double object's width value add.w d1,d0 ; Add object's width*2 (now at right of object) blo.s ShieldTouch_Height ; If carry, branch (player is within the object's boundaries) bra.s ShieldTouch_NextObj ; If not, loop and check next object ; --------------------------------------------------------------------------- .checkrightside: cmp.w d4,d0 ; Is player's right side to the left of the object? bhi.s ShieldTouch_NextObj ; If so, loop and check next object ShieldTouch_Height: moveq #0,d1 move.b (a2)+,d1 ; Get height value from Touch_Sizes move.w y_pos(a1),d0 ; Get object's y_pos sub.w d1,d0 ; Subtract object's height sub.w d3,d0 ; Subtract player's bottom collision boundary bcc.s .checktop ; If bottom of player is under the object, branch add.w d1,d1 ; Double object's height value add.w d1,d0 ; Add object's height*2 (now at top of object) bcs.w .checkdeflect ; If carry, branch (player is within the object's boundaries) bra.s ShieldTouch_NextObj ; If not, loop and check next object ; --------------------------------------------------------------------------- .checktop: cmp.w d5,d0 ; Is top of player under the object? bhi.s ShieldTouch_NextObj ; If so, loop and check next object .checkdeflect: move.b shield_reaction(a1),d0 andi.b #8,d0 ; Should the object be bounced away by a shield? beq.s ShieldTouch_NextObj ; If not, branch 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 (GetArcTan).l jsr (GetSineCosine).l muls.w #-$800,d1 asr.l #8,d1 move.w d1,x_vel(a1) muls.w #-$800,d0 asr.l #8,d0 move.w d0,y_vel(a1) clr.b collision_flags(a1) rts ; End of function ShieldTouchResponse ; =============== S U B R O U T I N E ======================================= ; It seems this is used by Hyper Sonic & Hyper Knuckles for their screen-nukes ; (Hyper Dash, and Hyper Knuckles gliding into a wall) HyperAttackTouchResponse: movem.l a2-a4,-(sp) lea (Collision_response_list).w,a4 move.w (a4)+,d6 ; Get number of objects queued beq.s HyperTouch_Exit ; If there are none, branch HyperTouch_Loop: movea.w (a4)+,a1 ; Get address of first object's RAM move.b collision_flags(a1),d0 ; Get its collision_flags beq.s HyperTouch_NextObj ; If it doesn't have collision, branch bsr.s HyperTouch_ChkValue ; Else, process object HyperTouch_NextObj: subq.w #2,d6 ; Count the object as done bne.s HyperTouch_Loop ; If there are still objects left, loop moveq #0,d0 HyperTouch_Exit: movem.l (sp)+,a2-a4 rts ; End of function HyperAttackTouchResponse ; =============== S U B R O U T I N E ======================================= HyperTouch_ChkValue: tst.b render_flags(a1) ; Is object on-screen? bpl.s .return ; If not, return (screen-nuke only affects what's on-screen) andi.b #$C0,d0 ; Get collision_flags type data beq.s HyperTouch_Enemy ; If 00, enemy, branch cmpi.b #$C0,d0 beq.w HyperTouch_Special ; If 11, "special thing for starpole", branch tst.b d0 bmi.s HyperTouch_Harmful ; If 10, "harmful", branch .return: rts ; --------------------------------------------------------------------------- HyperTouch_Enemy: tst.b collision_property(a1) ; Is this a special enemy? beq.s HyperTouch_DestroyEnemy ; If not, branch rts ; --------------------------------------------------------------------------- ; Similar to other enemy destruction subroutines, but this one doesn't make the player bounce HyperTouch_DestroyEnemy: btst #2,status(a1) ; Should the object remember that it's been destroyed (Remember Sprite State flag)? beq.s .dontremember ; If not, branch move.b ros_bit(a1),d0 movea.w ros_addr(a1),a2 bclr d0,(a2) ; Mark object as destroyed .dontremember: bset #7,status(a1) moveq #0,d0 move.w (Chain_bonus_counter).w,d0 ; Get copy of chain bonus counter addq.w #2,(Chain_bonus_counter).w ; Add 2 to chain bonus counter cmpi.w #6,d0 ; Has the counter already surpassed 5? blo.s .notreachedlimit ; If not, branch moveq #6,d0 ; Cap counter at 6 .notreachedlimit: move.w d0,objoff_3E(a1) move.w HyperEnemy_Score(pc,d0.w),d0 ; Get appropriate number of points cmpi.w #16*2,(Chain_bonus_counter).w ; Have 16 enemies been destroyed? blo.s .notreachedlimit2 ; If not, branch move.w #1000,d0 ; Fix bonus to 10000 points move.w #$A,objoff_3E(a1) .notreachedlimit2: movea.w a0,a3 bsr.w HUD_AddToScore move.l #Obj_Explosion,(a1) ; Create enemy destruction explosion move.b #0,routine(a1) rts ; --------------------------------------------------------------------------- HyperEnemy_Score: dc.w 10, 20, 50, 100 ; --------------------------------------------------------------------------- HyperTouch_Harmful: move.b shield_reaction(a1),d0 andi.b #8,d0 ; Should the object be bounced away by a shield? bne.w Touch_ChkHurt_Bounce_Projectile ; If so, branch rts ; --------------------------------------------------------------------------- HyperTouch_Special: ori.b #3,collision_property(a1) cmpi.w #3,(Player_mode).w ; Are we in Knuckles Alone mode? bne.s .sonicortails ; If not, branch move.w x_pos(a1),(Player_2+x_pos).w ; ??? move.w y_pos(a1),(Player_2+y_pos).w ; ??? .sonicortails: move.b #2,(Player_2+anim).w ; Put sidekick in his rolling animation bset #Status_InAir,(Player_2+status).w rts ; End of function HyperTouch_ChkValue ; --------------------------------------------------------------------------- Obj_Sonic2P: cmpa.w #Player_1,a0 bne.s loc_105F2 lea (Max_speed).w,a4 lea (Distance_from_top).w,a5 lea (Dust).w,a6 move.b (Player_2+character_id).w,d0 cmp.b character_id(a0),d0 bne.s loc_105E6 bchg #3,render_flags(a0) loc_105E6: tst.w (Debug_placement_mode).w beq.s loc_1060E jmp (DebugMode).l ; --------------------------------------------------------------------------- loc_105F2: lea (Max_speed_P2).w,a4 lea (Distance_from_top_P2).w,a5 lea (Dust_P2).w,a6 move.b (Player_1+character_id).w,d0 cmp.b character_id(a0),d0 bne.s loc_1060E bchg #4,render_flags(a0) loc_1060E: moveq #0,d0 move.b routine(a0),d0 move.w Sonic2P_Index(pc,d0.w),d1 jmp Sonic2P_Index(pc,d1.w) ; --------------------------------------------------------------------------- Sonic2P_Index: dc.w loc_10628-Sonic2P_Index dc.w loc_10740-Sonic2P_Index dc.w loc_122BE-Sonic2P_Index dc.w loc_12390-Sonic2P_Index dc.w loc_1257C-Sonic2P_Index dc.w loc_12590-Sonic2P_Index ; --------------------------------------------------------------------------- loc_10628: addq.b #2,routine(a0) move.b #$B,y_radius(a0) move.b #5,x_radius(a0) move.b #$B,default_y_radius(a0) move.b #5,default_x_radius(a0) move.w #$100,priority(a0) move.b #$C,width_pixels(a0) move.b #$C,height_pixels(a0) move.b #4,render_flags(a0) lea (Character_Speeds).l,a1 moveq #0,d0 move.b character_id(a0),d0 lsl.w #3,d0 lea (a1,d0.w),a1 move.w (a1)+,Max_speed-Max_speed(a4) move.w (a1)+,Acceleration-Max_speed(a4) move.w (a1)+,Deceleration-Max_speed(a4) tst.b (Last_star_post_hit).w bne.w loc_10724 move.b #$C,top_solid_bit(a0) move.b #$D,lrb_solid_bit(a0) cmpa.w #Player_1,a0 bne.s loc_106DC move.w #make_art_tile(ArtTile_Player_1,0,0),art_tile(a0) move.l #Map_Sonic2P,mappings(a0) tst.b character_id(a0) beq.s loc_106B4 move.l #Map_Knuckles2P,mappings(a0) addi.w #palette_line_1,art_tile(a0) loc_106B4: cmpi.b #$12,(Current_zone).w bne.s loc_106C2 ori.w #high_priority,art_tile(a0) loc_106C2: 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 loc_10724 ; --------------------------------------------------------------------------- loc_106DC: move.w #make_art_tile(ArtTile_Player_2,0,0),art_tile(a0) move.l #Map_Sonic2P,mappings(a0) tst.b character_id(a0) beq.s loc_106FE move.l #Map_Knuckles2P,mappings(a0) addi.w #palette_line_1,art_tile(a0) loc_106FE: cmpi.b #$12,(Current_zone).w bne.s loc_1070C ori.w #high_priority,art_tile(a0) loc_1070C: move.w x_pos(a0),(Saved2_X_pos).w move.w y_pos(a0),(Saved2_Y_pos).w move.w art_tile(a0),(Saved2_art_tile).w move.w top_solid_bit(a0),(Saved2_solid_bits).w loc_10724: move.b #0,flips_remaining(a0) move.b #4,flip_speed(a0) move.b #0,(Super_Sonic_Knux_flag).w move.b #30,air_left(a0) bsr.w Reset_Player_Position_Array loc_10740: tst.w (Debug_mode_flag).w beq.s loc_10760 cmpa.w #Player_1,a0 bne.s loc_10760 btst #button_B,(Ctrl_1_pressed).w beq.s loc_10760 move.w #1,(Debug_placement_mode).w clr.b (Ctrl_1_locked).w rts ; --------------------------------------------------------------------------- loc_10760: cmpa.w #Player_1,a0 bne.s loc_10774 tst.b (Ctrl_1_locked).w bne.s loc_10780 move.w (Ctrl_1).w,(Ctrl_1_logical).w bra.s loc_10780 ; --------------------------------------------------------------------------- loc_10774: tst.b (Ctrl_2_locked).w bne.s loc_10780 move.w (Ctrl_2).w,(Ctrl_1_logical).w loc_10780: bsr.w Sonic_Display btst #0,object_control(a0) bne.s loc_1079E moveq #0,d0 move.b status(a0),d0 andi.w #6,d0 move.w off_107EE(pc,d0.w),d1 jsr off_107EE(pc,d1.w) loc_1079E: cmpi.w #-$100,(Camera_min_Y_pos).w bne.s loc_107AE move.w (Screen_Y_wrap_value).w,d0 and.w d0,y_pos(a0) loc_107AE: move.w (Screen_X_wrap_value).w,d0 and.w d0,x_pos(a0) addi.w #$400,x_pos(a0) bsr.w Sonic_RecordPos move.b (Primary_Angle).w,next_tilt(a0) move.b (Secondary_Angle).w,tilt(a0) btst #1,object_control(a0) bne.s loc_107DC bsr.w Animate_SonicKnuckles_2P bsr.w SonicKnuckles2P_Load_PLC loc_107DC: move.b object_control(a0),d0 andi.b #$A0,d0 bne.s locret_107EC jsr (TouchResponse_CompetitionMode).l locret_107EC: rts ; --------------------------------------------------------------------------- off_107EE: dc.w loc_107F6-off_107EE dc.w loc_10868-off_107EE dc.w loc_10896-off_107EE dc.w loc_108B8-off_107EE ; --------------------------------------------------------------------------- loc_107F6: move.b (Ctrl_1_pressed_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 bne.s loc_10844 cmpi.b #$A,anim(a0) beq.s locret_10866 cmpi.b #$B,anim(a0) beq.s locret_10866 cmpi.b #5,anim(a0) bne.s loc_10844 cmpi.b #$1E,anim_frame(a0) blo.s loc_10844 bsr.w Player_SlopeResist move.b (Ctrl_1_logical).w,d0 andi.b #$7F,d0 beq.s loc_1085E move.b #$A,anim(a0) cmpi.b #$AC,anim_frame(a0) blo.s loc_1085E move.b #$B,anim(a0) bra.s loc_1085E ; --------------------------------------------------------------------------- loc_10844: bsr.w sub_1094C bsr.w Sonic_Jump bsr.w Player_SlopeResist bsr.w Sonic_Move bsr.w sub_108E6 jsr (MoveSprite2).l loc_1085E: bsr.w Player_AnglePos bsr.w Player_SlopeRepel locret_10866: rts ; --------------------------------------------------------------------------- loc_10868: bsr.w Sonic_JumpHeight bsr.w Sonic_ChgJumpDir jsr (MoveSprite).l btst #Status_Underwater,status(a0) beq.s loc_10884 subi.w #$28,y_vel(a0) loc_10884: bsr.w Player_JumpAngle movem.l a4-a6,-(sp) bsr.w SonicKnux_DoLevelCollision movem.l (sp)+,a4-a6 rts ; --------------------------------------------------------------------------- loc_10896: tst.b spin_dash_flag(a0) bne.s loc_108A0 bsr.w Sonic_Jump loc_108A0: bsr.w Player_RollRepel bsr.w Sonic_RollSpeed jsr (MoveSprite2).l bsr.w Player_AnglePos bsr.w Player_SlopeRepel rts ; --------------------------------------------------------------------------- loc_108B8: bsr.w Sonic_JumpHeight bsr.w Sonic_ChgJumpDir jsr (MoveSprite).l btst #Status_Underwater,status(a0) beq.s loc_108D4 subi.w #$28,y_vel(a0) loc_108D4: bsr.w Player_JumpAngle movem.l a4-a6,-(sp) bsr.w SonicKnux_DoLevelCollision movem.l (sp)+,a4-a6 rts ; =============== S U B R O U T I N E ======================================= sub_108E6: tst.b status_secondary(a0) bmi.s locret_1090C move.w ground_vel(a0),d0 bpl.s loc_108F4 neg.w d0 loc_108F4: cmpi.w #$80,d0 blo.s locret_1090C move.b (Ctrl_1_logical).w,d0 andi.b #button_left_mask|button_right_mask,d0 bne.s locret_1090C btst #button_down,(Ctrl_1_held_logical).w bne.s loc_1090E locret_1090C: rts ; --------------------------------------------------------------------------- loc_1090E: btst #2,status(a0) beq.s loc_10918 rts ; --------------------------------------------------------------------------- loc_10918: bset #Status_Roll,status(a0) move.b #7,y_radius(a0) move.b #3,x_radius(a0) move.b #2,anim(a0) addq.w #4,y_pos(a0) move.w #sfx_Roll,d0 jsr (Play_SFX).l tst.w ground_vel(a0) bne.s locret_1094A move.w #$200,ground_vel(a0) locret_1094A: rts ; End of function sub_108E6 ; =============== S U B R O U T I N E ======================================= sub_1094C: tst.b spin_dash_flag(a0) bne.s loc_10998 cmpi.b #8,anim(a0) bne.s locret_10996 move.b (Ctrl_1_pressed_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 beq.w locret_10996 move.b #9,anim(a0) move.w #signextendB(sfx_Spindash),d0 jsr (Play_SFX).l addq.l #4,sp move.b #1,spin_dash_flag(a0) move.w #0,spin_dash_counter(a0) cmpi.b #12,air_left(a0) blo.s loc_10992 move.b #2,anim(a6) loc_10992: bsr.w Player_AnglePos locret_10996: rts ; --------------------------------------------------------------------------- loc_10998: move.b (Ctrl_1_logical).w,d0 btst #button_down,d0 bne.w loc_10A38 move.b #7,y_radius(a0) move.b #3,x_radius(a0) move.b #2,anim(a0) addq.w #4,y_pos(a0) move.b #0,spin_dash_flag(a0) moveq #0,d0 move.b spin_dash_counter(a0),d0 add.w d0,d0 move.w word_10A14(pc,d0.w),ground_vel(a0) move.w ground_vel(a0),d0 subi.w #$800,d0 add.w d0,d0 andi.w #$1F00,d0 neg.w d0 addi.w #$2000,d0 lea (H_scroll_frame_offset).w,a1 cmpa.w #Player_1,a0 beq.s loc_109F0 lea (H_scroll_frame_offset_P2).w,a1 loc_109F0: move.w d0,(a1) btst #Status_Facing,status(a0) beq.s loc_109FE neg.w ground_vel(a0) loc_109FE: bset #Status_Roll,status(a0) move.b #0,anim(a6) moveq #signextendB(sfx_Dash),d0 jsr (Play_SFX).l bra.s loc_10A80 ; --------------------------------------------------------------------------- word_10A14: dc.w $800 dc.w $880 dc.w $900 dc.w $980 dc.w $A00 dc.w $A80 dc.w $B00 dc.w $B80 dc.w $C00 word_10A26: dc.w $B00 dc.w $B80 dc.w $C00 dc.w $C80 dc.w $D00 dc.w $D80 dc.w $E00 dc.w $E80 dc.w $F00 ; --------------------------------------------------------------------------- loc_10A38: tst.w spin_dash_counter(a0) beq.s loc_10A50 move.w spin_dash_counter(a0),d0 lsr.w #5,d0 sub.w d0,spin_dash_counter(a0) bcc.s loc_10A50 move.w #0,spin_dash_counter(a0) loc_10A50: move.b (Ctrl_1_pressed_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 beq.w loc_10A80 move.w #9<<8,anim(a0) ; and prev_anim move.w #signextendB(sfx_Spindash),d0 jsr (Play_SFX).l addi.w #$200,spin_dash_counter(a0) cmpi.w #$800,spin_dash_counter(a0) blo.s loc_10A80 move.w #$800,spin_dash_counter(a0) loc_10A80: addq.l #4,sp cmpi.w #$60,(a5) beq.s loc_10A8E bcc.s loc_10A8C addq.w #4,(a5) loc_10A8C: subq.w #2,(a5) loc_10A8E: bsr.w Player_AnglePos rts ; End of function sub_1094C ; --------------------------------------------------------------------------- Obj_Sonic: ; Load some addresses into registers ; This is done to allow some subroutines to be ; shared with Tails/Knuckles. lea (Max_speed).w,a4 lea (Distance_from_top).w,a5 lea (Dust).w,a6 tst.w (Debug_placement_mode).w beq.s Sonic_Normal ; Debug only code cmpi.b #1,(Debug_placement_type).w ; Is Sonic in debug object placement mode? beq.s JmpTo_DebugMode ; If so, skip to debug mode routine ; By this point, we're assuming you're in frame cycling mode btst #button_B,(Ctrl_1_pressed).w beq.s loc_10ABC move.w #0,(Debug_placement_mode).w ; Leave debug mode loc_10ABC: addq.b #1,mapping_frame(a0) ; Next frame cmpi.b #$FB,mapping_frame(a0) ; Have we reached the end of Sonic's frames? blo.s loc_10ACE move.b #0,mapping_frame(a0) ; If so, reset to Sonic's first frame loc_10ACE: bsr.w Sonic_Load_PLC jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- JmpTo_DebugMode: jmp (DebugMode).l ; --------------------------------------------------------------------------- Sonic_Normal: moveq #0,d0 move.b routine(a0),d0 move.w Sonic_Index(pc,d0.w),d1 jmp Sonic_Index(pc,d1.w) ; --------------------------------------------------------------------------- Sonic_Index: dc.w Sonic_Init-Sonic_Index ; 0 dc.w Sonic_Control-Sonic_Index ; 2 dc.w loc_122BE-Sonic_Index ; 4 dc.w loc_12390-Sonic_Index ; 6 dc.w loc_1257C-Sonic_Index ; 8 dc.w loc_12590-Sonic_Index ; $A dc.w loc_125AC-Sonic_Index ; $C ; --------------------------------------------------------------------------- Sonic_Init: ; Routine 0 addq.b #2,routine(a0) ; => Sonic_Control move.b #$13,y_radius(a0) ; this sets Sonic's collision height (2*pixels) move.b #9,x_radius(a0) move.b #$13,default_y_radius(a0) move.b #9,default_x_radius(a0) move.l #Map_Sonic,mappings(a0) move.w #$100,priority(a0) move.b #$18,width_pixels(a0) move.b #$18,height_pixels(a0) move.b #4,render_flags(a0) move.b #0,character_id(a0) move.w #$600,Max_speed-Max_speed(a4) move.w #$C,Acceleration-Max_speed(a4) move.w #$80,Deceleration-Max_speed(a4) tst.b (Last_star_post_hit).w bne.s Sonic_Init_Continued ; only happens when not starting at a checkpoint: move.w #make_art_tile(ArtTile_Player_1,0,0),art_tile(a0) move.b #$C,top_solid_bit(a0) move.b #$D,lrb_solid_bit(a0) cmpi.b #2,(Special_bonus_entry_flag).w beq.s Sonic_Init_Continued ; only happens when not starting at a Special Stage ring: 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 Sonic_Init_Continued: move.b #0,flips_remaining(a0) move.b #4,flip_speed(a0) move.b #0,(Super_Sonic_Knux_flag).w move.b #30,air_left(a0) subi.w #$20,x_pos(a0) addi.w #4,y_pos(a0) bsr.w Reset_Player_Position_Array addi.w #$20,x_pos(a0) subi.w #4,y_pos(a0) rts ; --------------------------------------------------------------------------- ; Normal state for Sonic ; --------------------------------------------------------------------------- Sonic_Control: ; Routine 2 tst.w (Debug_mode_flag).w ; is debug cheat enabled? beq.s loc_10BF0 ; if not, branch bclr #button_A,(Ctrl_1_pressed).w ; is button A pressed? beq.s loc_10BCE ; if not, branch eori.b #1,(Reverse_gravity_flag).w ; toggle reverse gravity loc_10BCE: btst #button_B,(Ctrl_1_pressed).w ; is button B pressed? beq.s loc_10BF0 ; if not, branch move.w #1,(Debug_placement_mode).w ; change Sonic into a ring/item clr.b (Ctrl_1_locked).w ; unlock control btst #button_C,(Ctrl_1_held).w ; was button C held before pressing B? beq.s locret_10BEE ; if not, branch move.w #2,(Debug_placement_mode).w ; enter animation cycle mode locret_10BEE: rts ; --------------------------------------------------------------------------- loc_10BF0: tst.b (Ctrl_1_locked).w ; are controls locked? bne.s loc_10BFC ; if yes, branch move.w (Ctrl_1).w,(Ctrl_1_logical).w ; copy new held buttons, to enable joypad control loc_10BFC: btst #0,object_control(a0) ; is Sonic interacting with another object that holds him in place or controls his movement somehow? beq.s loc_10C0C ; if yes, branch to skip Sonic's control move.b #0,double_jump_flag(a0) ; enable double jump bra.s loc_10C26 ; --------------------------------------------------------------------------- loc_10C0C: movem.l a4-a6,-(sp) moveq #0,d0 move.b status(a0),d0 andi.w #6,d0 move.w Sonic_Modes(pc,d0.w),d1 jsr Sonic_Modes(pc,d1.w) ; run Sonic's movement control code movem.l (sp)+,a4-a6 loc_10C26: cmpi.w #-$100,(Camera_min_Y_pos).w ; is vertical wrapping enabled? bne.s loc_10C36 ; if not, branch move.w (Screen_Y_wrap_value).w,d0 and.w d0,y_pos(a0) ; perform wrapping of Sonic's y position loc_10C36: bsr.s Sonic_Display bsr.w SonicKnux_SuperHyper 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 loc_10C62 tst.b anim(a0) bne.s loc_10C62 move.b prev_anim(a0),anim(a0) loc_10C62: btst #1,object_control(a0) bne.s loc_10C7E bsr.w Animate_Sonic tst.b (Reverse_gravity_flag).w beq.s loc_10C7A eori.b #2,render_flags(a0) loc_10C7A: bsr.w Sonic_Load_PLC loc_10C7E: move.b object_control(a0),d0 andi.b #$A0,d0 bne.s locret_10C8E jsr (TouchResponse).l locret_10C8E: rts ; --------------------------------------------------------------------------- ; secondary states under state Sonic_Control Sonic_Modes: dc.w Sonic_MdNormal-Sonic_Modes dc.w Sonic_MdAir-Sonic_Modes dc.w Sonic_MdRoll-Sonic_Modes dc.w Sonic_MdJump-Sonic_Modes ; =============== S U B R O U T I N E ======================================= Sonic_Display: move.b invulnerability_timer(a0),d0 beq.s loc_10CA6 subq.b #1,invulnerability_timer(a0) lsr.b #3,d0 bcc.s Sonic_ChkInvin loc_10CA6: jsr (Draw_Sprite).l Sonic_ChkInvin: ; Checks if invincibility has expired and disables it if it has. btst #Status_Invincible,status_secondary(a0) beq.s Sonic_ChkShoes tst.b invincibility_timer(a0) beq.s Sonic_ChkShoes ; If there wasn't any time left, that means we're in Super/Hyper mode move.b (Level_frame_counter+1).w,d0 andi.b #7,d0 bne.s Sonic_ChkShoes subq.b #1,invincibility_timer(a0) ; reduce invincibility_timer only on every 8th frame bne.s Sonic_ChkShoes ; if time is still left, branch tst.b (Boss_flag).w ; Don't change music if in a boss fight bne.s Sonic_RmvInvin cmpi.b #12,air_left(a0) ; Don't change music if drowning blo.s Sonic_RmvInvin move.w (Current_music).w,d0 jsr (Play_Music).l ; stop playing invincibility theme and resume normal level music Sonic_RmvInvin: bclr #Status_Invincible,status_secondary(a0) Sonic_ChkShoes: ; Checks if Speed Shoes have expired and disables them if they have. btst #Status_SpeedShoes,status_secondary(a0) ; does Sonic have speed shoes? beq.s Sonic_ExitChk ; if so, branch tst.b speed_shoes_timer(a0) beq.s Sonic_ExitChk move.b (Level_frame_counter+1).w,d0 andi.b #7,d0 bne.s Sonic_ExitChk subq.b #1,speed_shoes_timer(a0) ; reduce speed_shoes_timer only on every 8th frame bne.s Sonic_ExitChk tst.w (Competition_mode).w ; is this Competition mode? bne.s Sonic_ChkShoesCompetition ; if so, branch move.w #$600,Max_speed-Max_speed(a4) ; set Max_speed move.w #$C,Acceleration-Max_speed(a4) ; set Acceleration move.w #$80,Deceleration-Max_speed(a4) ; set Deceleration tst.b (Super_Sonic_Knux_flag).w beq.s loc_10D32 ; if Super/Hyper, set different values move.w #$A00,Max_speed-Max_speed(a4) ; set Max_speed move.w #$30,Acceleration-Max_speed(a4) ; set Acceleration move.w #$100,Deceleration-Max_speed(a4) ; set Deceleration loc_10D32: bclr #Status_SpeedShoes,status_secondary(a0) moveq #0,d0 ; Slow down tempo jmp (Change_Music_Tempo).l ; --------------------------------------------------------------------------- Sonic_ExitChk: rts ; --------------------------------------------------------------------------- Sonic_ChkShoesCompetition: lea (Character_Speeds).l,a1 moveq #0,d0 move.b character_id(a0),d0 lsl.w #3,d0 lea (a1,d0.w),a1 move.w (a1)+,Max_speed-Max_speed(a4) move.w (a1)+,Acceleration-Max_speed(a4) move.w (a1)+,Deceleration-Max_speed(a4) bclr #Status_SpeedShoes,status_secondary(a0) rts ; End of function 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 ======================================= Sonic_RecordPos: tst.w (Competition_mode).w ; are we in Competition mode? bne.s Sonic_RecordPosCompetition ; if so, branch cmpa.w #Player_1,a0 ; is Sonic the sidekick? bne.s locret_10D9E ; if so, branch move.w (Pos_table_index).w,d0 lea (Pos_table).w,a1 lea (a1,d0.w),a1 move.w x_pos(a0),(a1)+ ; write location to pos_table move.w y_pos(a0),(a1)+ addq.b #4,(Pos_table_index+1).w ; increment index as the post-increments did a1 lea (Stat_table).w,a1 lea (a1,d0.w),a1 move.w (Ctrl_1_logical).w,(a1)+ move.b status(a0),(a1)+ move.b art_tile(a0),(a1)+ locret_10D9E: rts ; --------------------------------------------------------------------------- Sonic_RecordPosCompetition: cmpa.w #Player_1,a0 ; is object player 1? bne.s Sonic_RecordPosCompetitionP2 ; if not, branch move.w (Pos_table_index).w,d0 lea (Pos_table).w,a1 lea (a1,d0.w),a1 move.w x_pos(a0),(a1)+ ; write location to pos_table move.w y_pos(a0),(a1)+ addq.b #4,(Pos_table_index+1).w ; increment index as the post-increments did a1 rts ; --------------------------------------------------------------------------- Sonic_RecordPosCompetitionP2: move.w (Pos_table_index_P2).w,d0 lea (Stat_table).w,a1 lea (a1,d0.w),a1 move.w x_pos(a0),(a1)+ ; write location to pos_table move.w y_pos(a0),(a1)+ addq.b #4,(Pos_table_index_P2+1).w ; increment index as the post-increments did a1 rts ; End of function Sonic_RecordPos ; =============== S U B R O U T I N E ======================================= Reset_Player_Position_Array: cmpa.w #Player_1,a0 ; is object player 1? bne.s Reset_Player_Position_ArrayP2 ; if not, branch lea (Pos_table).w,a1 lea (Stat_table).w,a2 move.w #bytesToLcnt($100),d0 .loop: move.w x_pos(a0),(a1)+ ; write location to pos_table move.w y_pos(a0),(a1)+ move.l #0,(a2)+ dbf d0,.loop move.w #0,(Pos_table_index).w Reset_Player_Position_ArrayP2: tst.w (Competition_mode).w ; are we in Competition mode? beq.s .return ; if not, branch lea (Stat_table).w,a1 move.w #bytesToLcnt($100),d0 .loop: move.w x_pos(a0),(a1)+ move.w y_pos(a0),(a1)+ dbf d0,.loop move.w #0,(Pos_table_index_P2).w .return: rts ; End of function Reset_Player_Position_Array ; --------------------------------------------------------------------------- ; Subroutine for Sonic when he's underwater ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Sonic_Water: tst.b (Water_flag).w ; does level have water? bne.s Sonic_InWater ; if yes, branch locret_10E2C: rts ; --------------------------------------------------------------------------- Sonic_InWater: move.w (Water_level).w,d0 cmp.w y_pos(a0),d0 ; is Sonic above the water? bge.s Sonic_OutWater ; if yes, branch bset #Status_Underwater,status(a0) ; set underwater flag bne.s locret_10E2C ; if already underwater, branch addq.b #1,(Water_entered_counter).w movea.l a0,a1 bsr.w Player_ResetAirTimer move.l #Obj_AirCountdown,(Breathing_bubbles).w ; load Sonic's breathing bubbles move.b #$81,(Breathing_bubbles+subtype).w move.l a0,(Breathing_bubbles+objoff_40).w move.w #$300,Max_speed-Max_speed(a4) move.w #6,Acceleration-Max_speed(a4) move.w #$40,Deceleration-Max_speed(a4) tst.b (Super_Sonic_Knux_flag).w beq.s loc_10E82 ; if Super/Hyper, set different values move.w #$500,Max_speed-Max_speed(a4) move.w #$18,Acceleration-Max_speed(a4) move.w #$80,Deceleration-Max_speed(a4) loc_10E82: tst.b object_control(a0) bne.s locret_10E2C asr x_vel(a0) asr y_vel(a0) ; memory operands can only be shifted one bit at a time asr y_vel(a0) beq.s locret_10E2C move.w #1<<8,anim(a6) ; splash animation, write 1 to anim and clear prev_anim move.w #sfx_Splash,d0 jmp (Play_SFX).l ; --------------------------------------------------------------------------- Sonic_OutWater: bclr #Status_Underwater,status(a0) ; unset underwater flag beq.w locret_10E2C ; if already above water, branch addq.b #1,(Water_entered_counter).w movea.l a0,a1 bsr.w Player_ResetAirTimer move.w #$600,Max_speed-Max_speed(a4) move.w #$C,Acceleration-Max_speed(a4) move.w #$80,Deceleration-Max_speed(a4) tst.b (Super_Sonic_Knux_flag).w beq.s loc_10EE0 ; if Super/Hyper, set different values move.w #$A00,Max_speed-Max_speed(a4) move.w #$30,Acceleration-Max_speed(a4) move.w #$100,Deceleration-Max_speed(a4) loc_10EE0: cmpi.b #4,routine(a0) ; is Sonic falling back from getting hurt? beq.s loc_10EFC ; if yes, branch tst.b object_control(a0) bne.s loc_10EFC move.w y_vel(a0),d0 cmpi.w #-$400,d0 blt.s loc_10EFC asl y_vel(a0) loc_10EFC: cmpi.b #$1C,anim(a0) ; is Sonic in his 'blank' animation? beq.w locret_10E2C ; if so, branch tst.w y_vel(a0) beq.w locret_10E2C move.w #1<<8,anim(a6) ; splash animation, write 1 to anim and clear prev_anim cmpi.w #-$1000,y_vel(a0) bgt.s loc_10F22 move.w #-$1000,y_vel(a0) ; limit upward y velocity exiting the water loc_10F22: move.w #sfx_Splash,d0 jmp (Play_SFX).l ; End of function Sonic_Water ; --------------------------------------------------------------------------- ; --------------------------------------------------------------------------- ; Start of subroutine Obj01_MdNormal ; Called if Sonic is neither airborne nor rolling this frame ; --------------------------------------------------------------------------- Sonic_MdNormal: bsr.w SonicKnux_Spindash bsr.w Sonic_Jump bsr.w Player_SlopeResist bsr.w Sonic_Move bsr.w SonicKnux_Roll bsr.w Player_LevelBound jsr (MoveSprite_TestGravity2).l bsr.w Call_Player_AnglePos bsr.w Player_SlopeRepel tst.b (Background_collision_flag).w beq.s locret_10F82 bsr.w sub_F846 tst.w d1 bmi.w Kill_Character movem.l a4-a6,-(sp) bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_10F72 sub.w d1,x_pos(a0) loc_10F72: bsr.w CheckRightWallDist tst.w d1 bpl.s loc_10F7E add.w d1,x_pos(a0) loc_10F7E: movem.l (sp)+,a4-a6 locret_10F82: rts ; =============== S U B R O U T I N E ======================================= Call_Player_AnglePos: tst.b (Reverse_gravity_flag).w beq.w Player_AnglePos move.b angle(a0),d0 addi.b #$40,d0 neg.b d0 subi.b #$40,d0 move.b d0,angle(a0) bsr.w Player_AnglePos move.b angle(a0),d0 addi.b #$40,d0 neg.b d0 subi.b #$40,d0 move.b d0,angle(a0) rts ; End of function Call_Player_AnglePos ; --------------------------------------------------------------------------- ; Start of subroutine Sonic_MdAir ; Called if Sonic is airborne, but not in a ball (thus, probably not jumping) Sonic_MdAir: bsr.w Sonic_JumpHeight bsr.w Sonic_ChgJumpDir bsr.w Player_LevelBound jsr (MoveSprite_TestGravity).l btst #Status_Underwater,status(a0) ; is Sonic underwater? beq.s loc_10FD6 ; if not, branch subi.w #$28,y_vel(a0) ; reduce gravity by $28 ($38-$28=$10) loc_10FD6: bsr.w Player_JumpAngle bsr.w SonicKnux_DoLevelCollision rts ; --------------------------------------------------------------------------- ; Start of subroutine Sonic_MdRoll ; Called if Sonic is in a ball, but not airborne (thus, probably rolling) Sonic_MdRoll: tst.b spin_dash_flag(a0) bne.s loc_10FEA bsr.w Sonic_Jump loc_10FEA: bsr.w Player_RollRepel bsr.w Sonic_RollSpeed bsr.w Player_LevelBound jsr (MoveSprite_TestGravity2).l bsr.w Call_Player_AnglePos bsr.w Player_SlopeRepel tst.b (Background_collision_flag).w beq.s locret_11034 bsr.w sub_F846 tst.w d1 bmi.w Kill_Character movem.l a4-a6,-(sp) bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_11024 sub.w d1,x_pos(a0) loc_11024: bsr.w CheckRightWallDist tst.w d1 bpl.s loc_11030 add.w d1,x_pos(a0) loc_11030: movem.l (sp)+,a4-a6 locret_11034: rts ; --------------------------------------------------------------------------- ; Start of subroutine Sonic_MdJump ; Called if Sonic is in a ball and airborne (he could be jumping but not necessarily) ; Notes: This is identical to Sonic_MdAir, at least at this outer level. ; Why they gave it a separate copy of the code, I don't know. Sonic_MdJump: bsr.w Sonic_JumpHeight bsr.w Sonic_ChgJumpDir bsr.w Player_LevelBound jsr (MoveSprite_TestGravity).l btst #Status_Underwater,status(a0) ; is Sonic underwater? beq.s loc_11056 ; if not, branch subi.w #$28,y_vel(a0) ; reduce gravity by $28 ($38-$28=$10) loc_11056: bsr.w Player_JumpAngle bsr.w SonicKnux_DoLevelCollision rts ; --------------------------------------------------------------------------- ; Subroutine to make Sonic walk/run ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Sonic_Move: move.w Max_speed-Max_speed(a4),d6 ; set Max_speed move.w Acceleration-Max_speed(a4),d5 ; set Acceleration move.w Deceleration-Max_speed(a4),d4 ; set Deceleration tst.b status_secondary(a0) ; is bit 7 set? (Infinite inertia) bmi.w loc_11332 ; if so, branch tst.w move_lock(a0) bne.w loc_112EA btst #button_left,(Ctrl_1_held_logical).w ; is left being pressed? beq.s Sonic_NotLeft ; if not, branch bsr.w sub_113F6 Sonic_NotLeft: btst #button_right,(Ctrl_1_held_logical).w ; is right being pressed? beq.s Sonic_NotRight ; if not, branch bsr.w sub_11482 Sonic_NotRight: move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 ; is Sonic on a slope? bne.w loc_112EA ; if yes, branch tst.w ground_vel(a0) ; is Sonic moving? bne.w loc_112EA ; if yes, branch bclr #Status_Push,status(a0) move.b #5,anim(a0) ; use standing animation btst #Status_OnObj,status(a0) beq.w Sonic_Balance movea.w interact(a0),a1 ; load interacting object's RAM space tst.b status(a1) ; is status bit 7 set? (unused?) bmi.w loc_11276 ; if so, branch ; Calculations to determine where on the object Sonic is, and make him balance accordingly moveq #0,d1 ; Clear d1 move.b width_pixels(a1),d1 ; Load interacting object's width into d1 move.w d1,d2 ; Move to d2 for seperate calculations add.w d2,d2 ; Double object width, converting it to X pos' units of measurement subq.w #2,d2 ; Subtract 2: This is the margin for 'on edge' add.w x_pos(a0),d1 ; Add Sonic's X position to object width sub.w x_pos(a1),d1 ; Subtract object's X position from width+Sonic's X pos, giving you Sonic's distance from left edge of object tst.b (Super_Sonic_Knux_flag).w ; is Sonic Super/Hyper? bne.w SuperSonic_Balance ; if so, branch cmpi.w #2,d1 ; is Sonic within two units of object's left edge? blt.s Sonic_BalanceOnObjLeft ; if so, branch cmp.w d2,d1 bge.s Sonic_BalanceOnObjRight ; if Sonic is within two units of object's right edge, branch (Realistically, it checks this, and BEYOND the right edge of the object) bra.w loc_11276 ; if Sonic is more than 2 units from both edges, branch ; --------------------------------------------------------------------------- SuperSonic_Balance: cmpi.w #2,d1 ; is Sonic within two units of object's left edge? blt.w loc_11268 ; if so, branch cmp.w d2,d1 bge.w loc_11258 ; if Sonic is within two units of object's right edge, branch (Realistically, it checks this, and BEYOND the right edge of the object) bra.w loc_11276 ; if Sonic is more than 2 units from both edges, branch ; --------------------------------------------------------------------------- ; balancing checks for when you're on the right edge of an object Sonic_BalanceOnObjRight: btst #Status_Facing,status(a0) ; is Sonic facing right? bne.s loc_11128 ; if so, branch move.b #6,anim(a0) ; Balance animation 1 addq.w #6,d2 ; extend balance range cmp.w d2,d1 ; is Sonic within (two units before and) four units past the right edge? blt.w loc_112EA ; if so, branch move.b #$C,anim(a0) ; if REALLY close to the edge, use different animation (Balance animation 2) bra.w loc_112EA loc_11128: ; Somewhat dummied out/redundant code from Sonic 2 ; Originally, Sonic displayed different animations for each direction faced ; But now, Sonic uses only the one set of animations no matter what, making the check pointless, and the code redundant bclr #Status_Facing,status(a0) move.b #6,anim(a0) ; Balance animation 1 addq.w #6,d2 ; extend balance range cmp.w d2,d1 ; is Sonic within (two units before and) four units past the right edge? blt.w loc_112EA ; if so, branch move.b #$C,anim(a0) ; if REALLY close to the edge, use different animation (Balance animation 2) bra.w loc_112EA ; --------------------------------------------------------------------------- Sonic_BalanceOnObjLeft: btst #Status_Facing,status(a0) ; is Sonic facing right? beq.s loc_11166 move.b #6,anim(a0) ; Balance animation 1 cmpi.w #-4,d1 ; is Sonic within (two units before and) four units past the left edge? bge.w loc_112EA ; if so branch (instruction signed to match) move.b #$C,anim(a0) ; if REALLY close to the edge, use different animation (Balance animation 2) bra.w loc_112EA loc_11166: ; Somewhat dummied out/redundant code from Sonic 2 ; Originally, Sonic displayed different animations for each direction faced ; But now, Sonic uses only the one set of animations no matter what, making the check pointless, and the code redundant bset #Status_Facing,status(a0) ; is Sonic facing right? move.b #6,anim(a0) ; Balance animation 1 cmpi.w #-4,d1 ; is Sonic within (two units before and) four units past the left edge? bge.w loc_112EA ; if so branch (instruction signed to match) move.b #$C,anim(a0) ; if REALLY close to the edge, use different animation (Balance animation 2) bra.w loc_112EA ; --------------------------------------------------------------------------- ; balancing checks for when you're on the edge of part of the level Sonic_Balance: move.w x_pos(a0),d3 bsr.w ChooseChkFloorEdge cmpi.w #$C,d1 blt.w loc_11276 tst.b (Super_Sonic_Knux_flag).w ; is Sonic Super/Hyper? bne.w loc_11250 ; if so, branch cmpi.b #3,next_tilt(a0) bne.s loc_111F6 btst #Status_Facing,status(a0) bne.s loc_111CE move.b #6,anim(a0) move.w x_pos(a0),d3 subq.w #6,d3 bsr.w ChooseChkFloorEdge cmpi.w #$C,d1 blt.w loc_112EA move.b #$C,anim(a0) bra.w loc_112EA ; on right edge but facing left: loc_111CE: ; Somewhat dummied out/redundant code from Sonic 2 ; Originally, Sonic displayed different animations for each direction faced ; But now, Sonic uses only the one set of animations no matter what, making the check pointless, and the code redundant bclr #Status_Facing,status(a0) move.b #6,anim(a0) move.w x_pos(a0),d3 subq.w #6,d3 bsr.w ChooseChkFloorEdge cmpi.w #$C,d1 blt.w loc_112EA move.b #$C,anim(a0) bra.w loc_112EA ; --------------------------------------------------------------------------- loc_111F6: cmpi.b #3,tilt(a0) bne.s loc_11276 btst #Status_Facing,status(a0) beq.s loc_11228 move.b #6,anim(a0) move.w x_pos(a0),d3 addq.w #6,d3 bsr.w ChooseChkFloorEdge cmpi.w #$C,d1 blt.w loc_112EA move.b #$C,anim(a0) bra.w loc_112EA ; --------------------------------------------------------------------------- loc_11228: bset #Status_Facing,status(a0) move.b #6,anim(a0) move.w x_pos(a0),d3 addq.w #6,d3 bsr.w ChooseChkFloorEdge cmpi.w #$C,d1 blt.w loc_112EA move.b #$C,anim(a0) bra.w loc_112EA ; --------------------------------------------------------------------------- loc_11250: cmpi.b #3,next_tilt(a0) bne.s loc_11260 loc_11258: bclr #Status_Facing,status(a0) bra.s loc_1126E ; --------------------------------------------------------------------------- loc_11260: cmpi.b #3,tilt(a0) bne.s loc_11276 loc_11268: bset #Status_Facing,status(a0) loc_1126E: move.b #6,anim(a0) bra.s loc_112EA ; --------------------------------------------------------------------------- loc_11276: btst #button_down,(Ctrl_1_logical).w beq.s loc_112B0 move.b #8,anim(a0) addq.b #1,scroll_delay_counter(a0) cmpi.b #120,scroll_delay_counter(a0) blo.s loc_112F0 move.b #120,scroll_delay_counter(a0) tst.b (Reverse_gravity_flag).w bne.s loc_112A6 cmpi.w #8,(a5) beq.s loc_112FC subq.w #2,(a5) bra.s loc_112FC ; --------------------------------------------------------------------------- loc_112A6: cmpi.w #$D8,(a5) beq.s loc_112FC addq.w #2,(a5) bra.s loc_112FC ; --------------------------------------------------------------------------- loc_112B0: btst #button_up,(Ctrl_1_held_logical).w beq.s loc_112EA move.b #7,anim(a0) addq.b #1,scroll_delay_counter(a0) cmpi.b #120,scroll_delay_counter(a0) blo.s loc_112F0 move.b #120,scroll_delay_counter(a0) tst.b (Reverse_gravity_flag).w bne.s loc_112E0 cmpi.w #$C8,(a5) beq.s loc_112FC addq.w #2,(a5) bra.s loc_112FC ; --------------------------------------------------------------------------- loc_112E0: cmpi.w #$18,(a5) beq.s loc_112FC subq.w #2,(a5) bra.s loc_112FC ; --------------------------------------------------------------------------- loc_112EA: move.b #0,scroll_delay_counter(a0) loc_112F0: cmpi.w #$60,(a5) beq.s loc_112FC bcc.s loc_112FA addq.w #4,(a5) loc_112FA: subq.w #2,(a5) loc_112FC: tst.b (Super_Sonic_Knux_flag).w beq.s loc_11306 move.w #$C,d5 loc_11306: move.b (Ctrl_1_held_logical).w,d0 andi.b #button_left_mask|button_right_mask,d0 bne.s loc_11332 move.w ground_vel(a0),d0 beq.s loc_11332 bmi.s loc_11326 sub.w d5,d0 bcc.s loc_11320 move.w #0,d0 loc_11320: move.w d0,ground_vel(a0) bra.s loc_11332 ; --------------------------------------------------------------------------- loc_11326: add.w d5,d0 bcc.s loc_1132E move.w #0,d0 loc_1132E: move.w d0,ground_vel(a0) loc_11332: move.b angle(a0),d0 jsr (GetSineCosine).l muls.w ground_vel(a0),d1 asr.l #8,d1 move.w d1,x_vel(a0) muls.w ground_vel(a0),d0 asr.l #8,d0 move.w d0,y_vel(a0) loc_11350: btst #6,object_control(a0) bne.w locret_113F4 move.b angle(a0),d0 andi.b #$3F,d0 beq.s loc_11370 move.b angle(a0),d0 addi.b #$40,d0 bmi.w locret_113F4 loc_11370: move.b #$40,d1 tst.w ground_vel(a0) beq.s locret_113F4 bmi.s loc_1137E neg.w d1 loc_1137E: move.b angle(a0),d0 add.b d1,d0 move.w d0,-(sp) bsr.w sub_F61C move.w (sp)+,d0 tst.w d1 bpl.s locret_113F4 asl.w #8,d1 cmpi.b #8,(Current_zone).w bne.s loc_113A0 tst.b d0 bpl.s loc_113A0 subq.b #1,d0 loc_113A0: addi.b #$20,d0 andi.b #$C0,d0 beq.s loc_113F0 cmpi.b #$40,d0 beq.s loc_113D6 cmpi.b #$80,d0 beq.s loc_113D0 add.w d1,x_vel(a0) move.w #0,ground_vel(a0) btst #Status_Facing,status(a0) bne.s locret_113CE bset #Status_Push,status(a0) locret_113CE: rts ; --------------------------------------------------------------------------- loc_113D0: sub.w d1,y_vel(a0) rts ; --------------------------------------------------------------------------- loc_113D6: sub.w d1,x_vel(a0) move.w #0,ground_vel(a0) btst #Status_Facing,status(a0) beq.s locret_113CE bset #Status_Push,status(a0) rts ; --------------------------------------------------------------------------- loc_113F0: add.w d1,y_vel(a0) locret_113F4: rts ; End of function Sonic_Move ; =============== S U B R O U T I N E ======================================= sub_113F6: move.w ground_vel(a0),d0 beq.s loc_113FE bpl.s loc_11430 loc_113FE: bset #Status_Facing,status(a0) bne.s loc_11412 bclr #Status_Push,status(a0) move.b #1,prev_anim(a0) loc_11412: sub.w d5,d0 move.w d6,d1 neg.w d1 cmp.w d1,d0 bgt.s loc_11424 add.w d5,d0 cmp.w d1,d0 ble.s loc_11424 move.w d1,d0 loc_11424: move.w d0,ground_vel(a0) move.b #0,anim(a0) rts ; --------------------------------------------------------------------------- loc_11430: sub.w d4,d0 bcc.s loc_11438 move.w #-$80,d0 loc_11438: move.w d0,ground_vel(a0) move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 bne.s locret_11480 cmpi.w #$400,d0 blt.s locret_11480 tst.b flip_type(a0) bmi.s locret_11480 move.w #sfx_Skid,d0 jsr (Play_SFX).l move.b #$D,anim(a0) bclr #Status_Facing,status(a0) cmpi.b #12,air_left(a0) blo.s locret_11480 move.b #6,routine(a6) move.b #$15,mapping_frame(a6) locret_11480: rts ; End of function sub_113F6 ; =============== S U B R O U T I N E ======================================= sub_11482: move.w ground_vel(a0),d0 bmi.s loc_114B6 bclr #Status_Facing,status(a0) beq.s loc_1149C bclr #Status_Push,status(a0) move.b #1,prev_anim(a0) loc_1149C: add.w d5,d0 cmp.w d6,d0 blt.s loc_114AA sub.w d5,d0 cmp.w d6,d0 bge.s loc_114AA move.w d6,d0 loc_114AA: move.w d0,ground_vel(a0) move.b #0,anim(a0) rts ; --------------------------------------------------------------------------- loc_114B6: add.w d4,d0 bcc.s loc_114BE move.w #$80,d0 loc_114BE: move.w d0,ground_vel(a0) move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 bne.s locret_11506 cmpi.w #-$400,d0 bgt.s locret_11506 tst.b flip_type(a0) bmi.s locret_11506 move.w #sfx_Skid,d0 jsr (Play_SFX).l move.b #$D,anim(a0) bset #Status_Facing,status(a0) cmpi.b #12,air_left(a0) blo.s locret_11506 move.b #6,routine(a6) move.b #$15,mapping_frame(a6) locret_11506: rts ; End of function sub_11482 ; =============== S U B R O U T I N E ======================================= Sonic_RollSpeed: move.w Max_speed-Max_speed(a4),d6 asl.w #1,d6 move.w Acceleration-Max_speed(a4),d5 asr.w #1,d5 tst.b (Super_Sonic_Knux_flag).w beq.s loc_1151C move.w #6,d5 loc_1151C: move.w #$20,d4 tst.b spin_dash_flag(a0) bmi.w loc_115C6 tst.b status_secondary(a0) bmi.w loc_115C6 tst.w move_lock(a0) bne.s loc_1154E btst #button_left,(Ctrl_1_logical).w beq.s loc_11542 bsr.w sub_11608 loc_11542: btst #button_right,(Ctrl_1_logical).w beq.s loc_1154E bsr.w sub_1162C loc_1154E: move.w ground_vel(a0),d0 beq.s loc_11570 bmi.s loc_11564 sub.w d5,d0 bcc.s loc_1155E move.w #0,d0 loc_1155E: move.w d0,ground_vel(a0) bra.s loc_11570 ; --------------------------------------------------------------------------- loc_11564: add.w d5,d0 bcc.s loc_1156C move.w #0,d0 loc_1156C: move.w d0,ground_vel(a0) loc_11570: move.w ground_vel(a0),d0 bpl.s loc_11578 neg.w d0 loc_11578: cmpi.w #$80,d0 bhs.s loc_115C6 tst.b spin_dash_flag(a0) bne.s loc_115B4 bclr #2,status(a0) move.b y_radius(a0),d0 move.b default_y_radius(a0),y_radius(a0) move.b default_x_radius(a0),x_radius(a0) move.b #5,anim(a0) sub.b default_y_radius(a0),d0 ext.w d0 tst.b (Reverse_gravity_flag).w beq.s loc_115AE neg.w d0 loc_115AE: add.w d0,y_pos(a0) bra.s loc_115C6 ; --------------------------------------------------------------------------- loc_115B4: move.w #$400,ground_vel(a0) btst #Status_Facing,status(a0) beq.s loc_115C6 neg.w ground_vel(a0) loc_115C6: cmpi.w #$60,(a5) beq.s loc_115D2 bcc.s loc_115D0 addq.w #4,(a5) loc_115D0: subq.w #2,(a5) loc_115D2: move.b angle(a0),d0 jsr (GetSineCosine).l muls.w ground_vel(a0),d0 asr.l #8,d0 move.w d0,y_vel(a0) muls.w ground_vel(a0),d1 asr.l #8,d1 cmpi.w #$1000,d1 ble.s loc_115F6 move.w #$1000,d1 loc_115F6: cmpi.w #-$1000,d1 bge.s loc_11600 move.w #-$1000,d1 loc_11600: move.w d1,x_vel(a0) bra.w loc_11350 ; End of function Sonic_RollSpeed ; =============== S U B R O U T I N E ======================================= sub_11608: move.w ground_vel(a0),d0 beq.s loc_11610 bpl.s loc_1161E loc_11610: bset #Status_Facing,status(a0) move.b #2,anim(a0) rts ; --------------------------------------------------------------------------- loc_1161E: sub.w d4,d0 bcc.s loc_11626 move.w #-$80,d0 loc_11626: move.w d0,ground_vel(a0) rts ; End of function sub_11608 ; =============== S U B R O U T I N E ======================================= sub_1162C: move.w ground_vel(a0),d0 bmi.s loc_11640 bclr #Status_Facing,status(a0) move.b #2,anim(a0) rts ; --------------------------------------------------------------------------- loc_11640: add.w d4,d0 bcc.s loc_11648 move.w #$80,d0 loc_11648: move.w d0,ground_vel(a0) rts ; End of function sub_1162C ; --------------------------------------------------------------------------- ; Subroutine for moving Sonic left or right when he's in the air ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Sonic_ChgJumpDir: move.w Max_speed-Max_speed(a4),d6 move.w Acceleration-Max_speed(a4),d5 asl.w #1,d5 btst #Status_RollJump,status(a0) ; did Sonic jump from rolling? bne.s Sonic_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 loc_11682 ; if not holding left, branch bset #Status_Facing,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 loc_11682 ; 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 loc_11682 ; if speed was already greater than the maximum, branch move.w d1,d0 loc_11682: btst #button_right,(Ctrl_1_held_logical).w beq.s loc_1169E ; if not holding right, branch bclr #Status_Facing,status(a0) add.w d5,d0 ; accelerate right in the air cmp.w d6,d0 ; compare new speed with top speed blt.s loc_1169E ; 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 loc_1169E ; if speed was already greater than the maximum, branch move.w d6,d0 loc_1169E: move.w d0,x_vel(a0) Sonic_Jump_ResetScr: cmpi.w #$60,(a5) ; is screen in its default position? beq.s Sonic_JumpPeakDecelerate ; if yes, branch bhs.s loc_116AC ; depending on the sign of the difference, addq.w #4,(a5) ; either add 2 loc_116AC: subq.w #2,(a5) ; or subtract 2 Sonic_JumpPeakDecelerate: cmpi.w #-$400,y_vel(a0) ; is Sonic moving faster than -$400 upwards? blo.s locret_116DC ; if yes, return move.w x_vel(a0),d0 move.w d0,d1 asr.w #5,d1 ; d1 = x_velocity / 32 beq.s locret_116DC ; return if d1 is 0 bmi.s Sonic_JumpPeakDecelerateLeft ; branch if moving left sub.w d1,d0 ; reduce x velocity by d1 bcc.s loc_116CA move.w #0,d0 loc_116CA: move.w d0,x_vel(a0) rts ; --------------------------------------------------------------------------- Sonic_JumpPeakDecelerateLeft: sub.w d1,d0 ; reduce x velocity by d1 bcs.s loc_116D8 move.w #0,d0 loc_116D8: move.w d0,x_vel(a0) locret_116DC: rts ; End of function Sonic_ChgJumpDir ; --------------------------------------------------------------------------- ; Subroutine to prevent Sonic from leaving the boundaries of a level ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Player_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 Player_Boundary_Sides ; if yes, branch move.w (Camera_max_X_pos).w,d0 addi.w #$128,d0 cmp.w d1,d0 blo.s Player_Boundary_Sides Player_Boundary_CheckBottom: tst.b (Disable_death_plane).w bne.s locret_11720 tst.b (Reverse_gravity_flag).w bne.s loc_11722 move.w (Camera_max_Y_pos).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 ; has Sonic touched the bottom boundary? blt.s Player_Boundary_Bottom ; if yes, branch locret_11720: rts ; --------------------------------------------------------------------------- loc_11722: move.w (Camera_min_Y_pos).w,d0 cmp.w y_pos(a0),d0 blt.s locret_11720 Player_Boundary_Bottom: jmp (Kill_Character).l ; --------------------------------------------------------------------------- Player_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,ground_vel(a0) bra.s Player_Boundary_CheckBottom ; End of function Player_LevelBound ; =============== S U B R O U T I N E ======================================= SonicKnux_Roll: tst.b status_secondary(a0) bmi.s locret_1177E move.b (Ctrl_1_held_logical).w,d0 andi.b #button_left_mask|button_right_mask,d0 ; is left/right being pressed? bne.s locret_1177E ; if yes, branch btst #button_down,(Ctrl_1_logical).w ; is down being pressed? beq.s Player_ChkWalk ; if not, branch move.w ground_vel(a0),d0 bpl.s loc_1176A neg.w d0 loc_1176A: cmpi.w #$100,d0 ; is Sonic moving at $100 speed or faster? bhs.s Player_ChkRoll ; if so, branch btst #Status_OnObj,status(a0) bne.s locret_1177E move.b #8,anim(a0) ; enter ducking animation locret_1177E: rts ; --------------------------------------------------------------------------- Player_ChkWalk: cmpi.b #8,anim(a0) ; is Sonic ducking? bne.s locret_1177E move.b #0,anim(a0) ; if so, enter walking animation rts ; --------------------------------------------------------------------------- Player_ChkRoll: btst #Status_Roll,status(a0) ; is Sonic already rolling? beq.s Player_DoRoll ; if not, branch rts ; --------------------------------------------------------------------------- Player_DoRoll: bset #Status_Roll,status(a0) move.b #$E,y_radius(a0) move.b #7,x_radius(a0) move.b #2,anim(a0) ; enter roll animation addq.w #5,y_pos(a0) tst.b (Reverse_gravity_flag).w beq.s loc_117C2 subi.w #2*5,y_pos(a0) loc_117C2: move.w #sfx_Roll,d0 jsr (Play_SFX).l tst.w ground_vel(a0) bne.s locret_117D8 move.w #$200,ground_vel(a0) locret_117D8: rts ; End of function SonicKnux_Roll ; --------------------------------------------------------------------------- ; Subroutine allowing Sonic to jump ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Sonic_Jump: move.b (Ctrl_1_pressed_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 ; is A, B or C pressed? beq.w locret_118B2 ; if not, return moveq #0,d0 move.b angle(a0),d0 tst.b (Reverse_gravity_flag).w beq.s loc_117FC addi.b #$40,d0 neg.b d0 subi.b #$40,d0 loc_117FC: addi.b #$80,d0 movem.l a4-a6,-(sp) bsr.w CalcRoomOverHead movem.l (sp)+,a4-a6 cmpi.w #6,d1 ; does Sonic have enough room to jump? blt.w locret_118B2 ; if not, branch move.w #$680,d2 tst.b (Super_Sonic_Knux_flag).w beq.s loc_11822 move.w #$800,d2 ; set higher jump speed if super loc_11822: btst #Status_Underwater,status(a0) ; Test if underwater beq.s loc_1182E move.w #$380,d2 ; set lower jump speed if under loc_1182E: moveq #0,d0 move.b angle(a0),d0 subi.b #$40,d0 jsr (GetSineCosine).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 #Status_InAir,status(a0) bclr #Status_Push,status(a0) addq.l #4,sp move.b #1,jumping(a0) clr.b stick_to_convex(a0) move.w #sfx_Jump,d0 jsr (Play_SFX).l move.b default_y_radius(a0),y_radius(a0) move.b default_x_radius(a0),x_radius(a0) btst #Status_Roll,status(a0) bne.s Sonic_RollJump move.b #$E,y_radius(a0) move.b #7,x_radius(a0) move.b #2,anim(a0) ; use "jumping" animation bset #Status_Roll,status(a0) move.b y_radius(a0),d0 sub.b default_y_radius(a0),d0 ext.w d0 tst.b (Reverse_gravity_flag).w beq.s loc_118AE neg.w d0 loc_118AE: sub.w d0,y_pos(a0) locret_118B2: rts ; --------------------------------------------------------------------------- Sonic_RollJump: bset #Status_RollJump,status(a0) ; set the rolling+jumping flag rts ; End of function Sonic_Jump ; =============== S U B R O U T I N E ======================================= Sonic_JumpHeight: tst.b jumping(a0) ; is Sonic jumping? beq.s Sonic_UpVelCap ; if not, branch move.w #-$400,d1 btst #Status_Underwater,status(a0) ; is Sonic underwater? beq.s loc_118D2 ; if not, branch move.w #-$200,d1 ; Underwater-specific loc_118D2: cmp.w y_vel(a0),d1 ; is y speed greater than 4? (2 if underwater) ble.w Sonic_ShieldMoves ; if not, branch move.b (Ctrl_1_held_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 ; are buttons A, B or C being pressed? bne.s locret_118E8 ; if yes, branch move.w d1,y_vel(a0) ; cap jump height locret_118E8: rts ; --------------------------------------------------------------------------- Sonic_UpVelCap: tst.b spin_dash_flag(a0) ; is Sonic charging his spin dash? bne.s locret_118FE ; if yes, branch cmpi.w #-$FC0,y_vel(a0) ; is Sonic's Y speed faster (less than) than -15.75 (-$FC0)? bge.s locret_118FE ; if not, branch move.w #-$FC0,y_vel(a0) ; cap upward speed locret_118FE: rts ; --------------------------------------------------------------------------- Sonic_ShieldMoves: tst.b double_jump_flag(a0) ; is Sonic currently performing a double jump? bne.w locret_11A14 ; if yes, branch move.b (Ctrl_1_pressed_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 ; are buttons A, B, or C being pressed? beq.w locret_11A14 ; if not, branch bclr #Status_RollJump,status(a0) tst.b (Super_Sonic_Knux_flag).w ; check Super-state beq.s Sonic_FireShield ; if not in a super-state, branch bmi.w Sonic_HyperDash ; if Hyper, branch move.b #1,double_jump_flag(a0) rts ; --------------------------------------------------------------------------- Sonic_FireShield: btst #Status_Invincible,status_secondary(a0) ; first, does Sonic have invincibility? bne.w locret_11A14 ; if yes, branch btst #Status_FireShield,status_secondary(a0) ; does Sonic have a Fire Shield? beq.s Sonic_LightningShield ; if not, branch move.b #1,(Shield+anim).w move.b #1,double_jump_flag(a0) move.w #$800,d0 btst #Status_Facing,status(a0) ; is Sonic facing left? beq.s loc_11958 ; if not, branch neg.w d0 ; reverse speed value, moving Sonic left loc_11958: move.w d0,x_vel(a0) ; apply velocity... move.w d0,ground_vel(a0) ; ...both ground and air move.w #0,y_vel(a0) ; kill y-velocity move.w #$2000,(H_scroll_frame_offset).w bsr.w Reset_Player_Position_Array move.w #sfx_FireAttack,d0 jmp (Play_SFX).l ; --------------------------------------------------------------------------- Sonic_LightningShield: btst #Status_LtngShield,status_secondary(a0) ; does Sonic have a Lightning Shield? beq.s Sonic_BubbleShield ; if not, branch move.b #1,(Shield+anim).w move.b #1,double_jump_flag(a0) move.w #-$580,y_vel(a0) ; bounce Sonic up, creating the double jump effect clr.b jumping(a0) move.w #sfx_ElectricAttack,d0 jmp (Play_SFX).l ; --------------------------------------------------------------------------- Sonic_BubbleShield: btst #Status_BublShield,status_secondary(a0) ; does Sonic have a Bubble Shield? beq.s Sonic_CheckTransform ; if not, branch move.b #1,(Shield+anim).w move.b #1,double_jump_flag(a0) move.w #0,x_vel(a0) ; halt horizontal speed... move.w #0,ground_vel(a0) ; ...both ground and air move.w #$800,y_vel(a0) ; force Sonic down move.w #sfx_BubbleAttack,d0 jmp (Play_SFX).l ; --------------------------------------------------------------------------- ; Code that transforms Sonic into Super/Hyper Sonic ; if he has enough rings and emeralds ; --------------------------------------------------------------------------- Sonic_CheckTransform: cmpi.b #7,(Super_emerald_count).w ; does Sonic have all 7 Super Emeralds? bhs.s loc_119E8 ; if yes, branch cmpi.b #7,(Chaos_emerald_count).w ; does Sonic have all 7 Chaos Emeralds? blo.s Sonic_InstaShield ; if not, branch tst.b (Emeralds_converted_flag).w bne.s Sonic_InstaShield loc_119E8: cmpi.w #50,(Ring_count).w ; does Sonic have at least 50 rings? blo.s Sonic_InstaShield ; if not, perform Insta-Shield tst.b (Update_HUD_timer).w bne.s Sonic_Transform Sonic_InstaShield: btst #Status_Shield,status_secondary(a0) ; does Sonic have an S2 shield? (the elementals were already filtered out at this point) bne.s locret_11A14 ; if yes, branch move.b #1,(Shield+anim).w move.b #1,double_jump_flag(a0) move.w #sfx_InstaAttack,d0 jmp (Play_SFX).l ; --------------------------------------------------------------------------- locret_11A14: rts ; --------------------------------------------------------------------------- Sonic_Transform: move.b #1,(Super_palette_status).w ; set Super/Hyper palette status to 'fading' move.b #$F,(Palette_timer).w move.w #60,(Super_frame_count).w move.l #Map_SuperSonic,mappings(a0) move.b #$81,object_control(a0) move.b #$1F,anim(a0) ; enter 'transformation' animation cmpi.b #7,(Super_emerald_count).w ; does Sonic have all 7 Super Emeralds? blo.s .super ; if not, turn Super move.b #-1,(Super_Sonic_Knux_flag).w ; set flag to Hyper Sonic move.l #Obj_HyperSonic_Stars,(Invincibility_stars).w ; load Hyper Stars object move.l #Obj_HyperSonicKnux_Trail,(Super_stars).w ; load After-Images object bra.s .continued ; --------------------------------------------------------------------------- .super: move.b #1,(Super_Sonic_Knux_flag).w ; set flag to Super Sonic move.l #Obj_SuperSonicKnux_Stars,(Super_stars).w ; load Super Stars object .continued: move.w #$A00,Max_speed-Max_speed(a4) move.w #$30,Acceleration-Max_speed(a4) move.w #$100,Deceleration-Max_speed(a4) move.b #0,invincibility_timer(a0) bset #Status_Invincible,status_secondary(a0) moveq #signextendB(sfx_SuperTransform),d0 jsr (Play_SFX).l moveq #signextendB(mus_Invincibility),d0 ; play invincibility theme jmp (Play_Music).l ; --------------------------------------------------------------------------- Sonic_HyperDash: bsr.w HyperAttackTouchResponse move.w #$2000,(H_scroll_frame_offset).w bsr.w Reset_Player_Position_Array move.b #1,double_jump_flag(a0) move.b #1,(Invincibility_stars+anim).w ; This causes the screen flash, and sparks to come out of Sonic moveq #signextendB(sfx_Dash),d0 jsr (Play_SFX).l move.b (Ctrl_1_logical).w,d0 andi.w #button_up_mask|button_down_mask|button_left_mask|button_right_mask,d0 ; Get D-pad input beq.s .noInput ; Any values totalling $B or above are produced by holding ; both opposing directions on the D-pad, which is invalid cmpi.b #$B,d0 bhs.s .noInput lsl.w #2,d0 lea Sonic_HyperDash_Velocities-4(pc,d0.w),a1 move.w (a1)+,d0 move.w d0,x_vel(a0) move.w d0,ground_vel(a0) move.w (a1)+,d0 move.w d0,y_vel(a0) rts ; --------------------------------------------------------------------------- .noInput: ; If there's no directional input, we just dash forward move.w #$800,d0 ; Go right... btst #Status_Facing,status(a0) ; ...unless Sonic is facing left... beq.s .applySpeeds neg.w d0 ; ...in which case, go left .applySpeeds: move.w d0,x_vel(a0) move.w d0,ground_vel(a0) move.w #0,y_vel(a0) rts ; End of function Sonic_JumpHeight ; --------------------------------------------------------------------------- Sonic_HyperDash_Velocities: dc.w 0, -$800 ; up dc.w 0, $800 ; down dc.w 0, 0 ; up + down (shouldn't happen) dc.w -$800, 0 ; left dc.w -$800, -$800 ; left + up dc.w -$800, $800 ; left + down dc.w 0, 0 ; left + up + down (shouldn't happen) dc.w $800, 0 ; right dc.w $800, -$800 ; right + up dc.w $800, $800 ; right + down ; Everything after this would be bad button combinations ; --------------------------------------------------------------------------- Tails_Super: tst.b (Super_Tails_flag).w beq.w SonicKnux_SuperHyper.return bra.s SonicKnux_SuperHyper.continued ; =============== S U B R O U T I N E ======================================= SonicKnux_SuperHyper: tst.b (Super_Sonic_Knux_flag).w beq.w .return ; If not Super/Hyper, return .continued: tst.b (Update_HUD_timer).w ; Level over? beq.s .revertToNormal subq.w #1,(Super_frame_count).w bpl.w .return ; This should be a 'bhi'; currently counts down 61 frames move.w #60,(Super_frame_count).w tst.w (Ring_count).w beq.s .revertToNormal ; If rings depleted, return to normal ; This checks if the ring counter needs to be blanked ; for example, this ticks '10' down to ' 9' instead of '19' (yes, this does happen) ori.b #1,(Update_HUD_ring_count).w ; Update ring counter cmpi.w #1,(Ring_count).w beq.s .resetHUD cmpi.w #10,(Ring_count).w beq.s .resetHUD cmpi.w #100,(Ring_count).w bne.s .updateHUD .resetHUD: ori.b #$80,(Update_HUD_ring_count).w ; Re-init ring counter .updateHUD: subq.w #1,(Ring_count).w bne.s .return ; If rings aren't depleted, we're done here ; If rings depleted, return to normal .revertToNormal: move.b #2,(Super_palette_status).w move.w #$1E,(Palette_frame).w move.b #0,(Super_Sonic_Knux_flag).w move.b #0,(Super_Tails_flag).w move.b #-1,(Player_prev_frame).w tst.b character_id(a0) ; Is this Sonic? bne.s .notSonic move.l #Map_Sonic,mappings(a0) ; If so, load Sonic's normal mappings (was using Super/Hyper mappings) .notSonic: move.b #1,prev_anim(a0) move.b #1,invincibility_timer(a0) move.w #$600,Max_speed-Max_speed(a4) move.w #$C,Acceleration-Max_speed(a4) move.w #$80,Deceleration-Max_speed(a4) btst #Status_Underwater,status(a0) beq.s .return ; If underwater, apply corrected speed/acceleration/deceleration move.w #$300,Max_speed-Max_speed(a4) move.w #6,Acceleration-Max_speed(a4) move.w #$40,Deceleration-Max_speed(a4) .return: rts ; End of function SonicKnux_SuperHyper ; =============== S U B R O U T I N E ======================================= SonicKnux_Spindash: tst.b spin_dash_flag(a0) bne.s loc_11C5E cmpi.b #8,anim(a0) bne.s locret_11C5C move.b (Ctrl_1_pressed_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 beq.w locret_11C5C move.b #9,anim(a0) move.w #signextendB(sfx_Spindash),d0 jsr (Play_SFX).l addq.l #4,sp move.b #1,spin_dash_flag(a0) move.w #0,spin_dash_counter(a0) cmpi.b #12,air_left(a0) blo.s loc_11C24 move.b #2,anim(a6) loc_11C24: bsr.w Player_LevelBound bsr.w Call_Player_AnglePos tst.b (Background_collision_flag).w beq.s locret_11C5C bsr.w sub_F846 tst.w d1 bmi.w Kill_Character movem.l a4-a6,-(sp) bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_11C4C sub.w d1,x_pos(a0) loc_11C4C: bsr.w CheckRightWallDist tst.w d1 bpl.s loc_11C58 add.w d1,x_pos(a0) loc_11C58: movem.l (sp)+,a4-a6 locret_11C5C: rts ; --------------------------------------------------------------------------- loc_11C5E: move.b (Ctrl_1_held_logical).w,d0 btst #button_down,d0 bne.w loc_11D16 move.b #$E,y_radius(a0) move.b #7,x_radius(a0) move.b #2,anim(a0) addq.w #5,y_pos(a0) tst.b (Reverse_gravity_flag).w beq.s loc_11C8C subi.w #5*2,y_pos(a0) loc_11C8C: move.b #0,spin_dash_flag(a0) moveq #0,d0 move.b spin_dash_counter(a0),d0 add.w d0,d0 move.w word_11CF2(pc,d0.w),ground_vel(a0) tst.b (Super_Sonic_Knux_flag).w beq.s loc_11CAC move.w word_11D04(pc,d0.w),ground_vel(a0) loc_11CAC: move.w ground_vel(a0),d0 subi.w #$800,d0 add.w d0,d0 andi.w #$1F00,d0 neg.w d0 addi.w #$2000,d0 lea (H_scroll_frame_offset).w,a1 cmpa.w #Player_1,a0 beq.s loc_11CCE lea (H_scroll_frame_offset_P2).w,a1 loc_11CCE: move.w d0,(a1) btst #Status_Facing,status(a0) beq.s loc_11CDC neg.w ground_vel(a0) loc_11CDC: bset #Status_Roll,status(a0) move.b #0,anim(a6) moveq #signextendB(sfx_Dash),d0 jsr (Play_SFX).l bra.s loc_11D5E ; --------------------------------------------------------------------------- word_11CF2: dc.w $800 dc.w $880 dc.w $900 dc.w $980 dc.w $A00 dc.w $A80 dc.w $B00 dc.w $B80 dc.w $C00 word_11D04: dc.w $B00 dc.w $B80 dc.w $C00 dc.w $C80 dc.w $D00 dc.w $D80 dc.w $E00 dc.w $E80 dc.w $F00 ; --------------------------------------------------------------------------- loc_11D16: tst.w spin_dash_counter(a0) beq.s loc_11D2E move.w spin_dash_counter(a0),d0 lsr.w #5,d0 sub.w d0,spin_dash_counter(a0) bcc.s loc_11D2E move.w #0,spin_dash_counter(a0) loc_11D2E: move.b (Ctrl_1_pressed_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 beq.w loc_11D5E move.w #9<<8,anim(a0) ; and prev_anim move.w #signextendB(sfx_Spindash),d0 jsr (Play_SFX).l addi.w #$200,spin_dash_counter(a0) cmpi.w #$800,spin_dash_counter(a0) blo.s loc_11D5E move.w #$800,spin_dash_counter(a0) loc_11D5E: addq.l #4,sp cmpi.w #$60,(a5) beq.s loc_11D6C bcc.s loc_11D6A addq.w #4,(a5) loc_11D6A: subq.w #2,(a5) loc_11D6C: bsr.w Player_LevelBound bsr.w Call_Player_AnglePos tst.b (Background_collision_flag).w beq.s locret_11DA4 bsr.w sub_F846 tst.w d1 bmi.w Kill_Character movem.l a4-a6,-(sp) bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_11D94 sub.w d1,x_pos(a0) loc_11D94: bsr.w CheckRightWallDist tst.w d1 bpl.s loc_11DA0 add.w d1,x_pos(a0) loc_11DA0: movem.l (sp)+,a4-a6 locret_11DA4: rts ; End of function SonicKnux_Spindash ; --------------------------------------------------------------------------- ; Subroutine to slow Sonic walking up a slope ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Player_SlopeResist: move.b angle(a0),d0 addi.b #$60,d0 cmpi.b #-$40,d0 bhs.s locret_11DDA move.b angle(a0),d0 jsr (GetSineCosine).l muls.w #$20,d0 asr.l #8,d0 tst.w ground_vel(a0) beq.s loc_11DDC bmi.s loc_11DD6 tst.w d0 beq.s locret_11DD4 add.w d0,ground_vel(a0) locret_11DD4: rts ; --------------------------------------------------------------------------- loc_11DD6: add.w d0,ground_vel(a0) locret_11DDA: rts ; --------------------------------------------------------------------------- loc_11DDC: move.w d0,d1 bpl.s loc_11DE2 neg.w d1 loc_11DE2: cmpi.w #$D,d1 blo.s locret_11DDA add.w d0,ground_vel(a0) rts ; End of function Player_SlopeResist ; --------------------------------------------------------------------------- ; Subroutine to push Sonic down a slope while he's rolling ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Player_RollRepel: move.b angle(a0),d0 addi.b #$60,d0 cmpi.b #-$40,d0 bhs.s locret_11E28 move.b angle(a0),d0 jsr (GetSineCosine).l muls.w #$50,d0 asr.l #8,d0 tst.w ground_vel(a0) bmi.s loc_11E1E tst.w d0 bpl.s loc_11E18 asr.l #2,d0 loc_11E18: add.w d0,ground_vel(a0) rts ; --------------------------------------------------------------------------- loc_11E1E: tst.w d0 bmi.s loc_11E24 asr.l #2,d0 loc_11E24: add.w d0,ground_vel(a0) locret_11E28: rts ; End of function Player_RollRepel ; --------------------------------------------------------------------------- ; Subroutine to push Sonic down a slope ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Player_SlopeRepel: nop tst.b stick_to_convex(a0) bne.s locret_11E6E tst.w move_lock(a0) bne.s loc_11E86 move.b angle(a0),d0 addi.b #$18,d0 cmpi.b #$30,d0 blo.s locret_11E6E move.w ground_vel(a0),d0 bpl.s loc_11E4E neg.w d0 loc_11E4E: cmpi.w #$280,d0 bhs.s locret_11E6E move.w #30,move_lock(a0) move.b angle(a0),d0 addi.b #$30,d0 cmpi.b #$60,d0 blo.s loc_11E70 bset #Status_InAir,status(a0) locret_11E6E: rts ; --------------------------------------------------------------------------- loc_11E70: cmpi.b #$30,d0 blo.s loc_11E7E addi.w #$80,ground_vel(a0) rts ; --------------------------------------------------------------------------- loc_11E7E: subi.w #$80,ground_vel(a0) rts ; --------------------------------------------------------------------------- loc_11E86: subq.w #1,move_lock(a0) rts ; End of function Player_SlopeRepel ; --------------------------------------------------------------------------- ; Subroutine to return Sonic's angle to 0 as he jumps ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Player_JumpAngle: move.b angle(a0),d0 ; get Sonic's angle beq.s Player_JumpFlip ; if already 0, branch bpl.s loc_11E9C ; if higher than 0, branch addq.b #2,d0 ; increase angle bcc.s loc_11E9A moveq #0,d0 loc_11E9A: bra.s Player_JumpAngleSet ; --------------------------------------------------------------------------- loc_11E9C: subq.b #2,d0 ; decrease angle bcc.s Player_JumpAngleSet moveq #0,d0 Player_JumpAngleSet: move.b d0,angle(a0) ; End of function Player_JumpAngle ; continue straight to Player_JumpFlip ; --------------------------------------------------------------------------- ; Updates Sonic's secondary angle if he's tumbling ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= Player_JumpFlip: move.b flip_angle(a0),d0 beq.s locret_11EEA tst.w ground_vel(a0) bmi.s Player_JumpLeftFlip Player_JumpRightFlip: move.b flip_speed(a0),d1 add.b d1,d0 bcc.s loc_11EC8 subq.b #1,flips_remaining(a0) bcc.s loc_11EC8 move.b #0,flips_remaining(a0) moveq #0,d0 loc_11EC8: bra.s Player_JumpFlipSet ; --------------------------------------------------------------------------- Player_JumpLeftFlip: tst.b flip_type(a0) bmi.s Player_JumpRightFlip move.b flip_speed(a0),d1 sub.b d1,d0 bcc.s Player_JumpFlipSet subq.b #1,flips_remaining(a0) bcc.s Player_JumpFlipSet move.b #0,flips_remaining(a0) moveq #0,d0 Player_JumpFlipSet: move.b d0,flip_angle(a0) locret_11EEA: rts ; End of function Player_JumpAngle ; --------------------------------------------------------------------------- ; 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 ======================================= SonicKnux_DoLevelCollision: move.l (Primary_collision_addr).w,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s loc_11F00 move.l (Secondary_collision_addr).w,(Collision_addr).w loc_11F00: move.b lrb_solid_bit(a0),d5 move.w x_vel(a0),d1 move.w y_vel(a0),d2 jsr (GetArcTan).l subi.b #$20,d0 andi.b #$C0,d0 cmpi.b #$40,d0 beq.w Player_HitLeftWall cmpi.b #$80,d0 beq.w Player_HitCeilingAndWalls cmpi.b #$C0,d0 beq.w loc_12102 bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_11F44 sub.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Sonic since he hit a wall loc_11F44: bsr.w CheckRightWallDist tst.w d1 bpl.s loc_11F56 add.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Sonic since he hit a wall loc_11F56: bsr.w sub_11FD6 tst.w d1 bpl.s locret_11FD4 move.b y_vel(a0),d2 addq.b #8,d2 neg.b d2 cmp.b d2,d1 bge.s loc_11F6E cmp.b d2,d0 blt.s locret_11FD4 loc_11F6E: move.b d3,angle(a0) tst.b (Reverse_gravity_flag).w beq.s loc_11F7A neg.w d1 loc_11F7A: add.w d1,y_pos(a0) move.b d3,d0 addi.b #$20,d0 andi.b #$40,d0 bne.s loc_11FAE move.b d3,d0 addi.b #$10,d0 andi.b #$20,d0 beq.s loc_11F9C asr y_vel(a0) bra.s loc_11FC2 ; --------------------------------------------------------------------------- loc_11F9C: move.w #0,y_vel(a0) move.w x_vel(a0),ground_vel(a0) bsr.w Player_TouchFloor_Check_Spindash rts ; --------------------------------------------------------------------------- loc_11FAE: move.w #0,x_vel(a0) ; stop Sonic since he hit a wall cmpi.w #$FC0,y_vel(a0) ble.s loc_11FC2 move.w #$FC0,y_vel(a0) loc_11FC2: bsr.w Player_TouchFloor_Check_Spindash move.w y_vel(a0),ground_vel(a0) tst.b d3 bpl.s locret_11FD4 neg.w ground_vel(a0) locret_11FD4: rts ; End of function SonicKnux_DoLevelCollision ; =============== S U B R O U T I N E ======================================= sub_11FD6: tst.b (Reverse_gravity_flag).w beq.w Sonic_CheckFloor bsr.w Sonic_CheckCeiling addi.b #$40,d3 neg.b d3 subi.b #$40,d3 rts ; End of function sub_11FD6 ; =============== S U B R O U T I N E ======================================= sub_11FEE: tst.b (Reverse_gravity_flag).w beq.w Sonic_CheckCeiling bsr.w Sonic_CheckFloor addi.b #$40,d3 neg.b d3 subi.b #$40,d3 rts ; End of function sub_11FEE ; =============== S U B R O U T I N E ======================================= ChooseChkFloorEdge: tst.b (Reverse_gravity_flag).w beq.w ChkFloorEdge_Part2 bra.w ChkFloorEdge_ReverseGravity ; End of function ChooseChkFloorEdge ; --------------------------------------------------------------------------- Player_HitLeftWall: bsr.w CheckLeftWallDist tst.w d1 bpl.s Player_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),ground_vel(a0) Player_HitCeiling: bsr.w sub_11FEE tst.w d1 bpl.s loc_12068 ; branch if distance is positive (not inside ceiling) neg.w d1 cmpi.w #$14,d1 bhs.s loc_12054 tst.b (Reverse_gravity_flag).w beq.s loc_12042 neg.w d1 loc_12042: add.w d1,y_pos(a0) tst.w y_vel(a0) bpl.s locret_12052 move.w #0,y_vel(a0) ; stop Sonic in y since he hit a ceiling locret_12052: rts ; --------------------------------------------------------------------------- loc_12054: bsr.w CheckRightWallDist tst.w d1 bpl.s locret_12066 add.w d1,x_pos(a0) move.w #0,x_vel(a0) locret_12066: rts ; --------------------------------------------------------------------------- loc_12068: tst.b (WindTunnel_flag).w bne.s loc_12074 tst.w y_vel(a0) bmi.s locret_1209C loc_12074: bsr.w sub_11FD6 tst.w d1 bpl.s locret_1209C tst.b (Reverse_gravity_flag).w beq.s loc_12084 neg.w d1 loc_12084: add.w d1,y_pos(a0) move.b d3,angle(a0) move.w #0,y_vel(a0) move.w x_vel(a0),ground_vel(a0) bsr.w Player_TouchFloor_Check_Spindash locret_1209C: rts ; --------------------------------------------------------------------------- Player_HitCeilingAndWalls: bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_120B0 sub.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Sonic since he hit a wall loc_120B0: bsr.w CheckRightWallDist tst.w d1 bpl.s loc_120C2 add.w d1,x_pos(a0) move.w #0,x_vel(a0) ; stop Sonic since he hit a wall loc_120C2: bsr.w sub_11FEE tst.w d1 bpl.s locret_12100 tst.b (Reverse_gravity_flag).w beq.s loc_120D2 neg.w d1 loc_120D2: sub.w d1,y_pos(a0) move.b d3,d0 addi.b #$20,d0 andi.b #$40,d0 bne.s loc_120EA move.w #0,y_vel(a0) ; stop Sonic in y since he hit a ceiling rts ; --------------------------------------------------------------------------- loc_120EA: move.b d3,angle(a0) bsr.w Player_TouchFloor_Check_Spindash move.w y_vel(a0),ground_vel(a0) tst.b d3 bpl.s locret_12100 neg.w ground_vel(a0) locret_12100: rts ; --------------------------------------------------------------------------- loc_12102: bsr.w CheckRightWallDist tst.w d1 bpl.s loc_1211A add.w d1,x_pos(a0) move.w #0,x_vel(a0) move.w y_vel(a0),ground_vel(a0) loc_1211A: bsr.w sub_11FEE tst.w d1 bpl.s loc_1213C tst.b (Reverse_gravity_flag).w beq.s loc_1212A neg.w d1 loc_1212A: sub.w d1,y_pos(a0) tst.w y_vel(a0) bpl.s locret_1213A move.w #0,y_vel(a0) locret_1213A: rts ; --------------------------------------------------------------------------- loc_1213C: tst.b (WindTunnel_flag).w bne.s loc_12148 tst.w y_vel(a0) bmi.s locret_12170 loc_12148: bsr.w sub_11FD6 tst.w d1 bpl.s locret_12170 tst.b (Reverse_gravity_flag).w beq.s loc_12158 neg.w d1 loc_12158: add.w d1,y_pos(a0) move.b d3,angle(a0) move.w #0,y_vel(a0) move.w x_vel(a0),ground_vel(a0) bsr.w Player_TouchFloor_Check_Spindash locret_12170: rts ; =============== S U B R O U T I N E ======================================= Player_TouchFloor_Check_Spindash: tst.b spin_dash_flag(a0) bne.s loc_121D8 move.b #0,anim(a0) ; End of function Player_TouchFloor_Check_Spindash ; =============== S U B R O U T I N E ======================================= Player_TouchFloor: cmpi.b #1,character_id(a0) beq.w Tails_TouchFloor cmpi.b #2,character_id(a0) beq.w Knux_TouchFloor move.b y_radius(a0),d0 move.b default_y_radius(a0),y_radius(a0) move.b default_x_radius(a0),x_radius(a0) btst #Status_Roll,status(a0) beq.s loc_121D8 bclr #Status_Roll,status(a0) move.b #0,anim(a0) sub.b default_y_radius(a0),d0 ext.w d0 tst.b (Reverse_gravity_flag).w beq.s loc_121C4 neg.w d0 loc_121C4: move.w d0,-(sp) move.b angle(a0),d0 addi.b #$40,d0 bpl.s loc_121D2 neg.w (sp) loc_121D2: move.w (sp)+,d0 add.w d0,y_pos(a0) loc_121D8: bclr #Status_InAir,status(a0) bclr #Status_Push,status(a0) bclr #Status_RollJump,status(a0) move.b #0,jumping(a0) move.w #0,(Chain_bonus_counter).w move.b #0,flip_angle(a0) move.b #0,flip_type(a0) move.b #0,flips_remaining(a0) move.b #0,scroll_delay_counter(a0) tst.b double_jump_flag(a0) beq.s locret_12230 tst.b character_id(a0) bne.s loc_1222A tst.b (Super_Sonic_Knux_flag).w bne.s loc_1222A btst #Status_BublShield,status_secondary(a0) beq.s loc_1222A bsr.s BubbleShield_Bounce loc_1222A: move.b #0,double_jump_flag(a0) locret_12230: rts ; End of function Player_TouchFloor ; =============== S U B R O U T I N E ======================================= BubbleShield_Bounce: movem.l d1-d2,-(sp) move.w #$780,d2 btst #Status_Underwater,status(a0) beq.s loc_12246 move.w #$400,d2 loc_12246: moveq #0,d0 move.b angle(a0),d0 subi.b #$40,d0 jsr (GetSineCosine).l muls.w d2,d1 asr.l #8,d1 add.w d1,x_vel(a0) muls.w d2,d0 asr.l #8,d0 add.w d0,y_vel(a0) movem.l (sp)+,d1-d2 bset #Status_InAir,status(a0) bclr #Status_Push,status(a0) move.b #1,jumping(a0) clr.b stick_to_convex(a0) move.b #$E,y_radius(a0) move.b #7,x_radius(a0) move.b #2,anim(a0) bset #Status_Roll,status(a0) move.b y_radius(a0),d0 sub.b default_y_radius(a0),d0 ext.w d0 tst.b (Reverse_gravity_flag).w beq.s loc_122AA neg.w d0 loc_122AA: sub.w d0,y_pos(a0) move.b #2,(Shield+anim).w move.w #sfx_BubbleAttack,d0 jmp (Play_SFX).l ; End of function BubbleShield_Bounce ; --------------------------------------------------------------------------- loc_122BE: tst.w (Debug_mode_flag).w beq.s loc_122D8 btst #button_B,(Ctrl_1_pressed).w beq.s loc_122D8 move.w #1,(Debug_placement_mode).w clr.b (Ctrl_1_locked).w rts ; --------------------------------------------------------------------------- loc_122D8: jsr (MoveSprite_TestGravity2).l addi.w #$30,y_vel(a0) btst #6,status(a0) beq.s loc_122F2 subi.w #$20,y_vel(a0) loc_122F2: cmpi.w #-$100,(Camera_min_Y_pos).w bne.s loc_12302 move.w (Screen_Y_wrap_value).w,d0 and.w d0,y_pos(a0) loc_12302: bsr.w sub_12318 bsr.w Player_LevelBound bsr.w Sonic_RecordPos bsr.w sub_125E0 jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_12318: tst.b (Disable_death_plane).w bne.s loc_12344 tst.b (Reverse_gravity_flag).w bne.s loc_12336 move.w (Camera_max_Y_pos).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 blt.w loc_1238A bra.s loc_12344 ; --------------------------------------------------------------------------- loc_12336: move.w (Camera_min_Y_pos).w,d0 cmp.w y_pos(a0),d0 blt.s loc_12344 bra.w loc_1238A ; --------------------------------------------------------------------------- loc_12344: movem.l a4-a6,-(sp) bsr.w SonicKnux_DoLevelCollision movem.l (sp)+,a4-a6 btst #1,status(a0) bne.s locret_12388 moveq #0,d0 move.w d0,y_vel(a0) move.w d0,x_vel(a0) move.w d0,ground_vel(a0) move.b d0,object_control(a0) move.b #0,anim(a0) move.w #$100,priority(a0) move.b #2,routine(a0) move.b #2*60,invulnerability_timer(a0) move.b #0,spin_dash_flag(a0) locret_12388: rts ; --------------------------------------------------------------------------- loc_1238A: jmp (Kill_Character).l ; End of function sub_12318 ; --------------------------------------------------------------------------- loc_12390: tst.w (Debug_mode_flag).w beq.s loc_123AA btst #button_B,(Ctrl_1_pressed).w beq.s loc_123AA move.w #1,(Debug_placement_mode).w clr.b (Ctrl_1_locked).w rts ; --------------------------------------------------------------------------- loc_123AA: bsr.w sub_123C2 jsr (MoveSprite_TestGravity).l bsr.w Sonic_RecordPos bsr.w sub_125E0 jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_123C2: cmpa.w #Player_1,a0 bne.s loc_123D4 move.w (Camera_Y_pos).w,d0 move.b #1,(Scroll_lock).w bra.s loc_123DE ; --------------------------------------------------------------------------- loc_123D4: move.w (Camera_Y_pos).w,d0 move.b #1,(Scroll_lock_P2).w loc_123DE: move.b #0,spin_dash_flag(a0) tst.b (Reverse_gravity_flag).w beq.s loc_123FA subi.w #$10,d0 cmp.w y_pos(a0),d0 bge.w loc_12410 bra.w locret_124C6 ; --------------------------------------------------------------------------- loc_123FA: addi.w #$100,d0 tst.w (Competition_mode).w beq.s loc_12408 subi.w #$70,d0 loc_12408: cmp.w y_pos(a0),d0 bge.w locret_124C6 loc_12410: tst.w (Competition_mode).w bne.w loc_124C8 cmpi.b #1,character_id(a0) bne.s loc_12432 cmpi.w #2,(Player_mode).w beq.s loc_12432 move.b #2,routine(a0) bra.w sub_13ECA ; --------------------------------------------------------------------------- loc_12432: move.b #8,routine(a0) move.w #60,$3E(a0) move.b #0,(Respawn_table_keep).w addq.b #1,(Update_HUD_life_count).w subq.b #1,(Life_count).w bne.s loc_12498 move.w #0,$3E(a0) move.l #Obj_GameOver,(Reserved_object_3).w move.l #Obj_GameOver,(Dynamic_object_RAM).w move.b #0,(Reserved_object_3+mapping_frame).w move.b #1,(Dynamic_object_RAM+mapping_frame).w move.w a0,(Reserved_object_3+objoff_3E).w clr.b (Time_over_flag).w loc_12478: clr.b (Update_HUD_timer).w clr.b (Update_HUD_timer_P2).w move.b #8,routine(a0) move.w #mus_GameOver,d0 jsr (Play_Music).l moveq #3,d0 jmp (Load_PLC_2).l ; --------------------------------------------------------------------------- loc_12498: tst.b (Time_over_flag).w beq.s locret_124C6 move.w #0,$3E(a0) move.l #Obj_GameOver,(Reserved_object_3).w move.l #Obj_GameOver,(Dynamic_object_RAM).w move.b #2,(Reserved_object_3+mapping_frame).w move.b #3,(Dynamic_object_RAM+mapping_frame).w move.w a0,(Reserved_object_3+objoff_3E).w bra.s loc_12478 ; --------------------------------------------------------------------------- locret_124C6: rts ; --------------------------------------------------------------------------- loc_124C8: move.b #2,routine(a0) cmpa.w #Player_1,a0 bne.s loc_12502 move.b #0,(Scroll_lock).w 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 #1,(_unkF74A).w bra.s loc_1252A ; --------------------------------------------------------------------------- loc_12502: move.b #0,(Scroll_lock_P2).w move.w (Saved2_X_pos).w,x_pos(a0) move.w (Saved2_Y_pos).w,y_pos(a0) move.w (Saved2_art_tile).w,art_tile(a0) move.w (Saved2_solid_bits).w,top_solid_bit(a0) clr.w (Ring_count_P2).w move.b #1,(_unkF74B).w loc_1252A: move.b #0,object_control(a0) move.b #5,anim(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) move.w #0,ground_vel(a0) move.b #2,status(a0) move.w #0,move_lock(a0) move.w #0,spin_dash_counter(a0) clr.b speed_shoes_timer(a0) lea (Character_Speeds).l,a1 moveq #0,d0 move.b character_id(a0),d0 lsl.w #3,d0 lea (a1,d0.w),a1 move.w (a1)+,Max_speed-Max_speed(a4) move.w (a1)+,Acceleration-Max_speed(a4) move.w (a1)+,Deceleration-Max_speed(a4) rts ; End of function sub_123C2 ; --------------------------------------------------------------------------- loc_1257C: tst.w $3E(a0) beq.s locret_1258E subq.w #1,$3E(a0) bne.s locret_1258E move.w #1,(Restart_level_flag).w locret_1258E: rts ; --------------------------------------------------------------------------- loc_12590: tst.w (Camera_RAM).w bne.s loc_125A2 tst.w (V_scroll_amount).w bne.s loc_125A2 move.b #2,routine(a0) loc_125A2: bsr.w sub_125E0 jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_125AC: tst.w (Debug_mode_flag).w beq.s loc_125C6 btst #button_B,(Ctrl_1_pressed).w beq.s loc_125C6 move.w #1,(Debug_placement_mode).w clr.b (Ctrl_1_locked).w rts ; --------------------------------------------------------------------------- loc_125C6: jsr (MoveSprite_TestGravity2).l addi.w #$10,y_vel(a0) bsr.w Sonic_RecordPos bsr.w sub_125E0 jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_125E0: tst.w (Competition_mode).w bne.s loc_125F8 bsr.s Animate_Sonic tst.b (Reverse_gravity_flag).w beq.s loc_125F4 eori.b #2,render_flags(a0) loc_125F4: bra.w Sonic_Load_PLC ; --------------------------------------------------------------------------- loc_125F8: bsr.w Animate_SonicKnuckles_2P bra.w SonicKnuckles2P_Load_PLC ; End of function sub_125E0 ; =============== S U B R O U T I N E ======================================= Animate_Sonic: lea (AniSonic).l,a1 tst.b (Super_Sonic_Knux_flag).w beq.s loc_12612 lea (AniSuperSonic).l,a1 loc_12612: moveq #0,d0 move.b anim(a0),d0 cmp.b prev_anim(a0),d0 beq.s loc_12634 move.b d0,prev_anim(a0) move.b #0,anim_frame(a0) move.b #0,anim_frame_timer(a0) bclr #5,status(a0) loc_12634: add.w d0,d0 adda.w (a1,d0.w),a1 move.b (a1),d0 bmi.s loc_126A4 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_timer(a0) bpl.s locret_12672 move.b d0,anim_frame_timer(a0) loc_1265A: moveq #0,d1 move.b anim_frame(a0),d1 move.b 1(a1,d1.w),d0 cmpi.b #$FC,d0 bhs.s loc_12674 loc_1266A: move.b d0,mapping_frame(a0) addq.b #1,anim_frame(a0) locret_12672: rts ; --------------------------------------------------------------------------- loc_12674: addq.b #1,d0 bne.s loc_12684 move.b #0,anim_frame(a0) move.b 1(a1),d0 bra.s loc_1266A ; --------------------------------------------------------------------------- loc_12684: addq.b #1,d0 bne.s loc_12698 move.b 2(a1,d1.w),d0 sub.b d0,anim_frame(a0) sub.b d0,d1 move.b 1(a1,d1.w),d0 bra.s loc_1266A ; --------------------------------------------------------------------------- loc_12698: addq.b #1,d0 bne.s locret_126A2 move.b 2(a1,d1.w),anim(a0) locret_126A2: rts ; --------------------------------------------------------------------------- loc_126A4: addq.b #1,d0 bne.w loc_12A2A moveq #0,d0 tst.b flip_type(a0) bmi.w Anim_Tumble move.b flip_angle(a0),d0 bne.w Anim_Tumble moveq #0,d1 move.b angle(a0),d0 bmi.s loc_126C8 beq.s loc_126C8 subq.b #1,d0 loc_126C8: move.b status(a0),d2 andi.b #1,d2 bne.s loc_126D4 not.b d0 loc_126D4: addi.b #$10,d0 bpl.s loc_126DC moveq #3,d1 loc_126DC: andi.b #$FC,render_flags(a0) eor.b d1,d2 or.b d2,render_flags(a0) btst #5,status(a0) bne.w loc_12A72 lsr.b #4,d0 andi.b #6,d0 move.w ground_vel(a0),d2 bpl.s loc_12700 neg.w d2 loc_12700: tst.b status_secondary(a0) bpl.w loc_1270A add.w d2,d2 loc_1270A: tst.b (Super_Sonic_Knux_flag).w bne.s loc_12766 lea (AniSonic01).l,a1 cmpi.w #$600,d2 bhs.s loc_12724 lea (AniSonic00).l,a1 add.b d0,d0 loc_12724: 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 loc_12742 move.b #0,anim_frame(a0) move.b 1(a1),d0 loc_12742: move.b d0,mapping_frame(a0) add.b d3,mapping_frame(a0) subq.b #1,anim_frame_timer(a0) bpl.s locret_12764 neg.w d2 addi.w #$800,d2 bpl.s loc_1275A moveq #0,d2 loc_1275A: lsr.w #8,d2 move.b d2,anim_frame_timer(a0) addq.b #1,anim_frame(a0) locret_12764: rts ; --------------------------------------------------------------------------- loc_12766: lea (AniSuperSonic01).l,a1 cmpi.w #$800,d2 bhs.s loc_1277E lea (AniSuperSonic00).l,a1 add.b d0,d0 add.b d0,d0 bra.s loc_12780 ; --------------------------------------------------------------------------- loc_1277E: add.b d0,d0 loc_12780: 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 loc_1279C move.b #0,anim_frame(a0) move.b 1(a1),d0 loc_1279C: move.b d0,mapping_frame(a0) add.b d3,mapping_frame(a0) subq.b #1,anim_frame_timer(a0) bpl.s locret_127BE neg.w d2 addi.w #$800,d2 bpl.s loc_127B4 moveq #0,d2 loc_127B4: lsr.w #8,d2 move.b d2,anim_frame_timer(a0) addq.b #1,anim_frame(a0) locret_127BE: rts ; --------------------------------------------------------------------------- ;loc_127C0: Anim_Tumble: move.b flip_type(a0),d1 andi.w #$7F,d1 bne.w loc_12872 move.b flip_angle(a0),d0 moveq #0,d1 move.b status(a0),d2 andi.b #1,d2 bne.s Anim_TumbleLeft andi.b #$FC,render_flags(a0) tst.b flip_type(a0) bpl.s loc_12806 cmpi.b #$B,(Current_zone).w ; is this DEZ? beq.s loc_1280A ; if so, branch cmpi.b #4,(Current_zone).w ; is this FBZ? beq.s loc_1280A ; if so, branch ori.b #2,render_flags(a0) neg.b d0 addi.b #$8F,d0 bra.s loc_1280A ; --------------------------------------------------------------------------- loc_12806: addi.b #$B,d0 loc_1280A: divu.w #$16,d0 addi.b #$31,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_timer(a0) rts ; --------------------------------------------------------------------------- ;loc_1281E: Anim_TumbleLeft: andi.b #$FC,render_flags(a0) tst.b flip_type(a0) bpl.s loc_1284E cmpi.b #4,(Current_zone).w ; is this FBZ? beq.s loc_12842 ; if so, branch cmpi.b #$B,(Current_zone).w ; is this DEZ? beq.s loc_12842 ; if so, branch cmpi.b #7,(Current_zone).w ; is this MHZ? bne.s loc_1284E ; if not, branch loc_12842: ori.b #1,render_flags(a0) addi.b #$B,d0 bra.s loc_1285A ; --------------------------------------------------------------------------- loc_1284E: ori.b #3,render_flags(a0) neg.b d0 addi.b #$8F,d0 loc_1285A: divu.w #$16,d0 addi.b #$31,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_timer(a0) rts ; --------------------------------------------------------------------------- byte_1286E: dc.b 0, $3D, $49, $49 even ; --------------------------------------------------------------------------- loc_12872: move.b byte_1286E(pc,d1.w),d3 cmpi.b #1,d1 bne.s loc_128CA move.b flip_angle(a0),d0 moveq #0,d1 move.b status(a0),d2 andi.b #1,d2 bne.s loc_128A8 andi.b #$FC,render_flags(a0) addi.b #-8,d0 divu.w #$16,d0 add.b d3,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_timer(a0) rts ; --------------------------------------------------------------------------- loc_128A8: andi.b #$FC,render_flags(a0) ori.b #1,render_flags(a0) addi.b #-8,d0 divu.w #$16,d0 add.b d3,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_timer(a0) rts ; --------------------------------------------------------------------------- loc_128CA: cmpi.b #2,d1 bne.s loc_12920 move.b flip_angle(a0),d0 moveq #0,d1 move.b status(a0),d2 andi.b #1,d2 bne.s loc_128FC andi.b #$FC,render_flags(a0) addi.b #$B,d0 divu.w #$16,d0 add.b d3,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_timer(a0) rts ; --------------------------------------------------------------------------- loc_128FC: andi.b #$FC,render_flags(a0) ori.b #3,render_flags(a0) neg.b d0 addi.b #$8F,d0 divu.w #$16,d0 add.b d3,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_timer(a0) rts ; --------------------------------------------------------------------------- loc_12920: cmpi.b #3,d1 bne.s loc_1297C move.b flip_angle(a0),d0 moveq #0,d1 move.b status(a0),d2 andi.b #1,d2 bne.s loc_1295A andi.b #$FC,render_flags(a0) ori.b #2,render_flags(a0) neg.b d0 addi.b #$8F,d0 divu.w #$16,d0 add.b d3,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_timer(a0) rts ; --------------------------------------------------------------------------- loc_1295A: andi.b #$FC,render_flags(a0) ori.b #1,render_flags(a0) addi.b #$B,d0 divu.w #$16,d0 add.b d3,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_timer(a0) rts ; --------------------------------------------------------------------------- loc_1297C: cmpi.b #4,d1 bne.s loc_129F6 move.b flip_angle(a0),d0 moveq #0,d1 move.b status(a0),d2 andi.b #1,d2 bne.s loc_129BC andi.b #$FC,render_flags(a0) tst.b flip_type(a0) bpl.s loc_129A4 addi.b #$B,d0 bra.s loc_129A8 ; --------------------------------------------------------------------------- loc_129A4: addi.b #$B,d0 loc_129A8: divu.w #$16,d0 addi.b #$31,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_timer(a0) rts ; --------------------------------------------------------------------------- loc_129BC: andi.b #$FC,render_flags(a0) tst.b flip_type(a0) bpl.s loc_129D6 ori.b #3,render_flags(a0) neg.b d0 addi.b #$8F,d0 bra.s loc_129E2 ; --------------------------------------------------------------------------- loc_129D6: ori.b #3,render_flags(a0) neg.b d0 addi.b #$8F,d0 loc_129E2: divu.w #$16,d0 addi.b #$31,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_timer(a0) rts ; --------------------------------------------------------------------------- loc_129F6: move.b flip_angle(a0),d0 andi.b #$FC,render_flags(a0) moveq #0,d1 move.b status(a0),d2 andi.b #1,d2 beq.s loc_12A12 ori.b #1,render_flags(a0) loc_12A12: addi.b #$B,d0 divu.w #$16,d0 addi.b #$31,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_timer(a0) rts ; --------------------------------------------------------------------------- loc_12A2A: 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_timer(a0) bpl.w locret_12672 move.w ground_vel(a0),d2 bpl.s loc_12A4C neg.w d2 loc_12A4C: lea (AniSonic03).l,a1 cmpi.w #$600,d2 bhs.s loc_12A5E lea (AniSonic02).l,a1 loc_12A5E: neg.w d2 addi.w #$400,d2 bpl.s loc_12A68 moveq #0,d2 loc_12A68: lsr.w #8,d2 move.b d2,anim_frame_timer(a0) bra.w loc_1265A ; --------------------------------------------------------------------------- loc_12A72: subq.b #1,anim_frame_timer(a0) bpl.w locret_12672 move.w ground_vel(a0),d2 bmi.s loc_12A82 neg.w d2 loc_12A82: addi.w #$800,d2 bpl.s loc_12A8A moveq #0,d2 loc_12A8A: lsr.w #6,d2 move.b d2,anim_frame_timer(a0) lea (AniSonic04).l,a1 tst.b (Super_Sonic_Knux_flag).w beq.s loc_12AA2 lea (AniSuperSonic04).l,a1 loc_12AA2: bra.w loc_1265A ; End of function Animate_Sonic ; --------------------------------------------------------------------------- AniSonic: include "General/Sprites/Sonic/Anim - Sonic.asm" ; =============== S U B R O U T I N E ======================================= Sonic_Load_PLC: moveq #0,d0 move.b mapping_frame(a0),d0 Sonic_Load_PLC2: cmp.b (Player_prev_frame).w,d0 beq.s locret_12D20 move.b d0,(Player_prev_frame).w lea (PLC_Sonic).l,a2 tst.b (Super_Sonic_Knux_flag).w beq.s loc_12CD6 lea (PLC_SuperSonic).l,a2 loc_12CD6: add.w d0,d0 adda.w (a2,d0.w),a2 move.w (a2)+,d5 subq.w #1,d5 bmi.s locret_12D20 move.w #tiles_to_bytes(ArtTile_Player_1),d4 move.l #ArtUnc_Sonic,d6 cmpi.w #2*$DA,d0 blo.s loc_12CF8 move.l #ArtUnc_Sonic_Extra,d6 loc_12CF8: 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 add.l d6,d1 move.w d4,d2 add.w d3,d4 add.w d3,d4 jsr (Add_To_DMA_Queue).l dbf d5,loc_12CF8 locret_12D20: rts ; End of function Sonic_Load_PLC ; =============== S U B R O U T I N E ======================================= Perform_Player_DPLC: tst.b character_id(a1) beq.s Sonic_Load_PLC2 cmpi.b #1,character_id(a1) beq.w Tails_Load_PLC2 bra.w Knuckles_Load_PLC2 ; End of function Perform_Player_DPLC ; =============== S U B R O U T I N E ======================================= Animate_SonicKnuckles_2P: lea (AniSonic2P).l,a1 tst.b character_id(a0) beq.s loc_12D48 lea (AniKnuckles2P).l,a1 loc_12D48: moveq #0,d0 move.b anim(a0),d0 cmp.b prev_anim(a0),d0 beq.s loc_12D6A move.b d0,prev_anim(a0) move.b #0,anim_frame(a0) move.b #0,anim_frame_timer(a0) bclr #Status_Push,status(a0) loc_12D6A: add.w d0,d0 adda.w (a1,d0.w),a1 move.b (a1),d0 bmi.s loc_12DDA 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_timer(a0) bpl.s locret_12DA8 move.b d0,anim_frame_timer(a0) loc_12D90: moveq #0,d1 move.b anim_frame(a0),d1 move.b 1(a1,d1.w),d0 cmpi.b #$FC,d0 bhs.s loc_12DAA loc_12DA0: move.b d0,mapping_frame(a0) addq.b #1,anim_frame(a0) locret_12DA8: rts ; --------------------------------------------------------------------------- loc_12DAA: addq.b #1,d0 bne.s loc_12DBA move.b #0,anim_frame(a0) move.b 1(a1),d0 bra.s loc_12DA0 ; --------------------------------------------------------------------------- loc_12DBA: addq.b #1,d0 bne.s loc_12DCE move.b 2(a1,d1.w),d0 sub.b d0,anim_frame(a0) sub.b d0,d1 move.b 1(a1,d1.w),d0 bra.s loc_12DA0 ; --------------------------------------------------------------------------- loc_12DCE: addq.b #1,d0 bne.s locret_12DD8 move.b 2(a1,d1.w),anim(a0) locret_12DD8: rts ; --------------------------------------------------------------------------- loc_12DDA: addq.b #1,d0 bne.w loc_12EF4 moveq #0,d0 move.b flip_angle(a0),d0 bne.w loc_12E8E moveq #0,d1 move.b angle(a0),d0 bmi.s loc_12DF6 beq.s loc_12DF6 subq.b #1,d0 loc_12DF6: move.b status(a0),d2 andi.b #1,d2 bne.s loc_12E02 not.b d0 loc_12E02: addi.b #$10,d0 bpl.s loc_12E0A moveq #3,d1 loc_12E0A: andi.b #$FC,render_flags(a0) eor.b d1,d2 or.b d2,render_flags(a0) btst #Status_Push,status(a0) bne.w loc_12F3C lsr.b #5,d0 andi.b #3,d0 move.w ground_vel(a0),d2 bpl.s loc_12E2E neg.w d2 loc_12E2E: tst.b status_secondary(a0) bpl.w loc_12E38 add.w d2,d2 loc_12E38: move.b d0,d3 lea (AniSonic2P01).l,a1 cmpi.w #$600,d2 bhs.s loc_12E4E lea (AniSonic2P00).l,a1 add.b d0,d0 loc_12E4E: add.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 loc_12E6A move.b #0,anim_frame(a0) move.b 1(a1),d0 loc_12E6A: move.b d0,mapping_frame(a0) add.b d3,mapping_frame(a0) subq.b #1,anim_frame_timer(a0) bpl.s locret_12E8C neg.w d2 addi.w #$800,d2 bpl.s loc_12E82 moveq #0,d2 loc_12E82: lsr.w #8,d2 move.b d2,anim_frame_timer(a0) addq.b #1,anim_frame(a0) locret_12E8C: rts ; --------------------------------------------------------------------------- loc_12E8E: move.b flip_angle(a0),d0 moveq #0,d1 move.b status(a0),d2 andi.b #1,d2 bne.s loc_12EBC andi.b #$FC,render_flags(a0) addi.b #$16,d0 divu.w #$2C,d0 addi.b #$15,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_timer(a0) rts ; --------------------------------------------------------------------------- loc_12EBC: andi.b #$FC,render_flags(a0) tst.b flip_type(a0) bpl.s loc_12ED4 ori.b #1,render_flags(a0) addi.b #$16,d0 bra.s loc_12EE0 ; --------------------------------------------------------------------------- loc_12ED4: ori.b #3,render_flags(a0) neg.b d0 addi.b #$9A,d0 loc_12EE0: divu.w #$2C,d0 addi.b #$15,d0 move.b d0,mapping_frame(a0) move.b #0,anim_frame_timer(a0) rts ; --------------------------------------------------------------------------- loc_12EF4: subq.b #1,anim_frame_timer(a0) bpl.w locret_12DA8 move.w ground_vel(a0),d2 bpl.s loc_12F04 neg.w d2 loc_12F04: lea (AniSonic2P03).l,a1 cmpi.w #$600,d2 bhs.s loc_12F16 lea (AniSonic2P02).l,a1 loc_12F16: neg.w d2 addi.w #$400,d2 bpl.s loc_12F20 moveq #0,d2 loc_12F20: lsr.w #8,d2 move.b d2,anim_frame_timer(a0) move.b status(a0),d1 andi.b #1,d1 andi.b #$FC,render_flags(a0) or.b d1,render_flags(a0) bra.w loc_12D90 ; --------------------------------------------------------------------------- loc_12F3C: subq.b #1,anim_frame_timer(a0) bpl.w locret_12DA8 move.w ground_vel(a0),d2 bmi.s loc_12F4C neg.w d2 loc_12F4C: addi.w #$800,d2 bpl.s loc_12F54 moveq #0,d2 loc_12F54: lsr.w #6,d2 lea (AniSonic2P04).l,a1 tst.b character_id(a0) beq.s loc_12F6A lea (AniKnuckles2P04).l,a1 lsr.w #2,d2 loc_12F6A: move.b d2,anim_frame_timer(a0) move.b status(a0),d1 andi.b #1,d1 andi.b #$FC,render_flags(a0) or.b d1,render_flags(a0) bra.w loc_12D90 ; End of function Animate_SonicKnuckles_2P ; --------------------------------------------------------------------------- AniSonic2P: include "General/Sprites/Sonic/Anim - Sonic Knuckles 2P.asm" ; =============== S U B R O U T I N E ======================================= SonicKnuckles2P_Load_PLC: moveq #0,d0 move.b mapping_frame(a0),d0 lea (PLC_Sonic2P).l,a2 move.l #ArtUnc_Sonic2P,d6 tst.b character_id(a0) beq.s loc_130BE lea (PLC_Knuckles2P).l,a2 move.l #ArtUnc_Knuckles2P,d6 loc_130BE: add.w d0,d0 adda.w (a2,d0.w),a2 move.w (a2)+,d5 subq.w #1,d5 bmi.s locret_13100 move.w #tiles_to_bytes(ArtTile_Player_1),d4 cmpa.w #Player_1,a0 beq.s loc_130D8 move.w #tiles_to_bytes(ArtTile_Player_2),d4 loc_130D8: 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 add.l d6,d1 move.w d4,d2 add.w d3,d4 add.w d3,d4 jsr (Add_To_DMA_Queue).l dbf d5,loc_130D8 locret_13100: rts ; End of function SonicKnuckles2P_Load_PLC ; --------------------------------------------------------------------------- Obj_Tails2P: cmpa.w #Player_1,a0 bne.s loc_13130 lea (Max_speed).w,a4 lea (Distance_from_top).w,a5 lea (Dust).w,a6 move.b (Player_2+character_id).w,d0 cmp.b character_id(a0),d0 bne.s loc_13124 bchg #3,render_flags(a0) loc_13124: tst.w (Debug_placement_mode).w beq.s loc_1314C jmp (DebugMode).l ; --------------------------------------------------------------------------- loc_13130: lea (Max_speed_P2).w,a4 lea (Distance_from_top_P2).w,a5 lea (Dust_P2).w,a6 move.b (Player_1+character_id).w,d0 cmp.b character_id(a0),d0 bne.s loc_1314C bchg #4,render_flags(a0) loc_1314C: moveq #0,d0 move.b routine(a0),d0 move.w Tails2P_Index(pc,d0.w),d1 jmp Tails2P_Index(pc,d1.w) ; --------------------------------------------------------------------------- Tails2P_Index: dc.w loc_13166-Tails2P_Index dc.w loc_13274-Tails2P_Index dc.w loc_1569C-Tails2P_Index dc.w loc_1578E-Tails2P_Index dc.w loc_157E0-Tails2P_Index dc.w loc_157F4-Tails2P_Index ; --------------------------------------------------------------------------- loc_13166: addq.b #2,routine(a0) move.b #$B,y_radius(a0) move.b #5,x_radius(a0) move.b #$B,default_y_radius(a0) move.b #5,default_x_radius(a0) move.l #Map_Tails2P,mappings(a0) move.w #$100,priority(a0) move.b #$C,width_pixels(a0) move.b #$C,height_pixels(a0) move.b #$84,render_flags(a0) move.b #1,character_id(a0) lea (Character_Speeds).l,a1 moveq #0,d0 move.b character_id(a0),d0 lsl.w #3,d0 lea (a1,d0.w),a1 move.w (a1)+,Max_speed_P2-Max_speed_P2(a4) move.w (a1)+,Acceleration_P2-Max_speed_P2(a4) move.w (a1)+,Deceleration_P2-Max_speed_P2(a4) tst.b (Last_star_post_hit).w bne.w loc_13250 move.b #$C,top_solid_bit(a0) move.b #$D,lrb_solid_bit(a0) cmpa.w #Player_1,a0 bne.s loc_13218 move.w #make_art_tile(ArtTile_Player_1,0,0),art_tile(a0) cmpi.b #$12,(Current_zone).w bne.s loc_131F2 ori.w #high_priority,art_tile(a0) loc_131F2: 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 move.l #Obj_Tails2P_Tail,(Tails_tails_2P).w move.w a0,(Tails_tails_2P+$30).w bra.s loc_13250 ; --------------------------------------------------------------------------- loc_13218: move.w #make_art_tile(ArtTile_Player_2,0,0),art_tile(a0) cmpi.b #$12,(Current_zone).w bne.s loc_1322C ori.w #high_priority,art_tile(a0) loc_1322C: move.w x_pos(a0),(Saved2_X_pos).w move.w y_pos(a0),(Saved2_Y_pos).w move.w art_tile(a0),(Saved2_art_tile).w move.w top_solid_bit(a0),(Saved2_solid_bits).w move.l #Obj_Tails2P_Tail,(Tails_tails).w move.w a0,(Tails_tails+$30).w loc_13250: move.b #0,flips_remaining(a0) move.b #4,flip_speed(a0) move.b #30,air_left(a0) move.w #0,(Tails_CPU_routine).w move.w #10*60,(Tails_CPU_idle_timer).w move.w #0,(Tails_CPU_flight_timer).w loc_13274: tst.w (Debug_mode_flag).w beq.s loc_13294 cmpa.w #Player_1,a0 bne.s loc_13294 btst #button_B,(Ctrl_1_pressed).w beq.s loc_13294 move.w #1,(Debug_placement_mode).w clr.b (Ctrl_1_locked).w rts ; --------------------------------------------------------------------------- loc_13294: cmpa.w #Player_1,a0 bne.s loc_132B4 move.w (Ctrl_1_logical).w,(Ctrl_2_logical).w tst.b (Ctrl_1_locked).w bne.s loc_132C0 move.w (Ctrl_1).w,(Ctrl_2_logical).w move.w (Ctrl_1).w,(Ctrl_1_logical).w bra.s loc_132C0 ; --------------------------------------------------------------------------- loc_132B4: tst.b (Ctrl_2_locked).w bne.s loc_132C0 move.w (Ctrl_2).w,(Ctrl_2_logical).w loc_132C0: bsr.w Tails_Display btst #0,object_control(a0) bne.s loc_132DE moveq #0,d0 move.b status(a0),d0 andi.w #6,d0 move.w off_1332E(pc,d0.w),d1 jsr off_1332E(pc,d1.w) loc_132DE: cmpi.w #-$100,(Camera_min_Y_pos).w bne.s loc_132EE move.w (Screen_Y_wrap_value).w,d0 and.w d0,y_pos(a0) loc_132EE: move.w (Screen_X_wrap_value).w,d0 and.w d0,x_pos(a0) addi.w #$400,x_pos(a0) bsr.w Sonic_RecordPos move.b (Primary_Angle).w,next_tilt(a0) move.b (Secondary_Angle).w,tilt(a0) btst #1,object_control(a0) bne.s loc_1331C bsr.w Animate_Tails2P bsr.w Tails2P_Load_PLC loc_1331C: move.b object_control(a0),d0 andi.b #$A0,d0 bne.s locret_1332C jsr (TouchResponse_CompetitionMode).l locret_1332C: rts ; --------------------------------------------------------------------------- off_1332E: dc.w loc_13336-off_1332E dc.w loc_1335A-off_1332E dc.w loc_1346A-off_1332E dc.w loc_1348C-off_1332E ; --------------------------------------------------------------------------- loc_13336: bsr.w sub_13520 bsr.w Tails_Jump bsr.w Player_SlopeResist bsr.w Tails_InputAcceleration_Path bsr.w sub_134BA jsr (MoveSprite2).l bsr.w Player_AnglePos bsr.w Player_SlopeRepel rts ; --------------------------------------------------------------------------- loc_1335A: tst.b double_jump_flag(a0) bne.s loc_1338E bsr.w Tails_JumpHeight bsr.w Tails_InputAcceleration_Freespace jsr (MoveSprite).l btst #Status_Underwater,status(a0) beq.s loc_1337C subi.w #$28,y_vel(a0) loc_1337C: bsr.w Player_JumpAngle movem.l a4-a6,-(sp) bsr.w Tails_DoLevelCollision movem.l (sp)+,a4-a6 rts ; --------------------------------------------------------------------------- loc_1338E: bsr.w sub_133AE bsr.w Tails_InputAcceleration_Freespace jsr (MoveSprite2).l bsr.w Player_JumpAngle movem.l a4-a6,-(sp) bsr.w Tails_DoLevelCollision movem.l (sp)+,a4-a6 rts ; =============== S U B R O U T I N E ======================================= sub_133AE: move.b (Level_frame_counter+1).w,d0 andi.b #1,d0 beq.s loc_133C2 tst.b double_jump_property(a0) beq.s loc_133C2 subq.b #1,double_jump_property(a0) loc_133C2: cmpi.b #1,double_jump_flag(a0) beq.s loc_133EC cmpi.w #-$100,y_vel(a0) blt.s loc_133E4 subi.w #$20,y_vel(a0) addq.b #1,double_jump_flag(a0) cmpi.b #$20,double_jump_flag(a0) bne.s loc_133EA loc_133E4: move.b #1,double_jump_flag(a0) loc_133EA: bra.s loc_1341E ; --------------------------------------------------------------------------- loc_133EC: move.b (Ctrl_2_pressed_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 beq.s loc_13418 cmpi.w #-$100,y_vel(a0) blt.s loc_13418 tst.b double_jump_property(a0) beq.s loc_13418 btst #Status_Underwater,status(a0) beq.s loc_13412 tst.b (Flying_carrying_Sonic_flag).w bne.s loc_13418 loc_13412: move.b #2,double_jump_flag(a0) loc_13418: addi.w #8,y_vel(a0) loc_1341E: move.w (Camera_min_Y_pos).w,d0 addi.w #$10,d0 cmp.w y_pos(a0),d0 blt.s loc_13438 tst.w y_vel(a0) bpl.s loc_13438 move.w #0,y_vel(a0) loc_13438: tst.b double_jump_property(a0) bne.s loc_13454 move.b (Level_frame_counter+1).w,d0 addq.b #8,d0 andi.b #$F,d0 bne.s locret_13452 moveq #signextendB(sfx_FlyTired),d0 jsr (Play_SFX).l locret_13452: rts ; --------------------------------------------------------------------------- loc_13454: move.b (Level_frame_counter+1).w,d0 addq.b #8,d0 andi.b #$F,d0 bne.s locret_13468 moveq #signextendB(sfx_Flying),d0 jsr (Play_SFX).l locret_13468: rts ; End of function sub_133AE ; --------------------------------------------------------------------------- loc_1346A: tst.b spin_dash_flag(a0) bne.s loc_13474 bsr.w Tails_Jump loc_13474: bsr.w Player_RollRepel bsr.w Tails_RollSpeed jsr (MoveSprite2).l bsr.w Player_AnglePos bsr.w Player_SlopeRepel rts ; --------------------------------------------------------------------------- loc_1348C: bsr.w Tails_JumpHeight bsr.w Tails_InputAcceleration_Freespace jsr (MoveSprite).l btst #Status_Underwater,status(a0) beq.s loc_134A8 subi.w #$28,y_vel(a0) loc_134A8: bsr.w Player_JumpAngle movem.l a4-a6,-(sp) bsr.w Tails_DoLevelCollision movem.l (sp)+,a4-a6 rts ; =============== S U B R O U T I N E ======================================= sub_134BA: tst.b status_secondary(a0) bmi.s locret_134E0 move.w ground_vel(a0),d0 bpl.s loc_134C8 neg.w d0 loc_134C8: cmpi.w #$80,d0 blo.s locret_134E0 move.b (Ctrl_2_held_logical).w,d0 andi.b #button_left_mask|button_right_mask,d0 bne.s locret_134E0 btst #button_down,(Ctrl_2_held_logical).w bne.s loc_134E2 locret_134E0: rts ; --------------------------------------------------------------------------- loc_134E2: btst #Status_Roll,status(a0) beq.s loc_134EC rts ; --------------------------------------------------------------------------- loc_134EC: bset #Status_Roll,status(a0) move.b #7,y_radius(a0) move.b #3,x_radius(a0) move.b #2,anim(a0) addq.w #4,y_pos(a0) move.w #sfx_Roll,d0 jsr (Play_SFX).l tst.w ground_vel(a0) bne.s locret_1351E move.w #$200,ground_vel(a0) locret_1351E: rts ; End of function sub_134BA ; =============== S U B R O U T I N E ======================================= sub_13520: tst.b spin_dash_flag(a0) bne.s loc_13570 cmpi.b #8,anim(a0) bne.s locret_1356E move.b (Ctrl_2_pressed_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 beq.w locret_1356E move.b #9,anim(a0) move.w #signextendB(sfx_Spindash),d0 jsr (Play_SFX).l addq.l #4,sp move.b #1,spin_dash_flag(a0) move.w #0,spin_dash_counter(a0) cmpi.b #12,air_left(a0) blo.s loc_13566 move.b #2,anim(a6) loc_13566: bsr.w Tails_Check_Screen_Boundaries bsr.w Player_AnglePos locret_1356E: rts ; --------------------------------------------------------------------------- loc_13570: move.b (Ctrl_2_held_logical).w,d0 btst #button_down,d0 bne.w loc_13600 move.b #7,y_radius(a0) move.b #3,x_radius(a0) move.b #2,anim(a0) addq.w #4,y_pos(a0) move.b #0,spin_dash_flag(a0) moveq #0,d0 move.b spin_dash_counter(a0),d0 add.w d0,d0 move.w word_135EE(pc,d0.w),ground_vel(a0) move.w ground_vel(a0),d0 subi.w #$800,d0 add.w d0,d0 andi.w #$1F00,d0 neg.w d0 addi.w #$2000,d0 lea (H_scroll_frame_offset).w,a1 cmpa.w #Player_1,a0 beq.s loc_135C8 lea (H_scroll_frame_offset_P2).w,a1 loc_135C8: move.w d0,(a1) btst #Status_Facing,status(a0) beq.s loc_135D6 neg.w ground_vel(a0) loc_135D6: bset #Status_Roll,status(a0) move.b #0,anim(a6) move.w #signextendB(sfx_Dash),d0 jsr (Play_SFX).l bra.s loc_13648 ; --------------------------------------------------------------------------- word_135EE: dc.w $800 dc.w $880 dc.w $900 dc.w $980 dc.w $A00 dc.w $A80 dc.w $B00 dc.w $B80 dc.w $C00 ; --------------------------------------------------------------------------- loc_13600: tst.w spin_dash_counter(a0) beq.s loc_13618 move.w spin_dash_counter(a0),d0 lsr.w #5,d0 sub.w d0,spin_dash_counter(a0) bcc.s loc_13618 move.w #0,spin_dash_counter(a0) loc_13618: move.b (Ctrl_2_pressed_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 beq.w loc_13648 move.w #9<<8,anim(a0) ; and prev_anim move.w #signextendB(sfx_Spindash),d0 jsr (Play_SFX).l addi.w #$200,spin_dash_counter(a0) cmpi.w #$800,spin_dash_counter(a0) blo.s loc_13648 move.w #$800,spin_dash_counter(a0) loc_13648: addq.l #4,sp cmpi.w #$60,(a5) beq.s loc_13656 bcc.s loc_13654 addq.w #4,(a5) loc_13654: subq.w #2,(a5) loc_13656: bsr.w Player_AnglePos rts ; End of function sub_13520 ; --------------------------------------------------------------------------- Obj_Tails: lea (Max_speed_P2).w,a4 lea (Distance_from_top_P2).w,a5 lea (Dust_P2).w,a6 cmpi.w #2,(Player_mode).w bne.s Tails_Normal tst.w (Debug_placement_mode).w beq.s Tails_Normal cmpi.b #1,(Debug_placement_type).w beq.s loc_136A8 btst #button_B,(Ctrl_1_pressed).w beq.s loc_1368C move.w #0,(Debug_placement_mode).w loc_1368C: addq.b #1,mapping_frame(a0) cmpi.b #$FB,mapping_frame(a0) blo.s loc_1369E move.b #0,mapping_frame(a0) loc_1369E: bsr.w Tails_Load_PLC jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_136A8: jmp (DebugMode).l ; --------------------------------------------------------------------------- Tails_Normal: moveq #0,d0 move.b routine(a0),d0 move.w Tails_Index(pc,d0.w),d1 jmp Tails_Index(pc,d1.w) ; --------------------------------------------------------------------------- Tails_Index: dc.w Tails_Init-Tails_Index dc.w Tails_Control-Tails_Index dc.w loc_1569C-Tails_Index dc.w loc_1578E-Tails_Index dc.w loc_157E0-Tails_Index dc.w loc_157F4-Tails_Index dc.w loc_15810-Tails_Index ; --------------------------------------------------------------------------- Tails_Init: addq.b #2,routine(a0) move.b #$F,y_radius(a0) move.b #9,x_radius(a0) move.b #$F,default_y_radius(a0) move.b #9,default_x_radius(a0) move.l #Map_Tails,mappings(a0) move.w #$100,priority(a0) move.b #$18,width_pixels(a0) move.b #$18,height_pixels(a0) move.b #$84,render_flags(a0) move.b #1,character_id(a0) move.w #$600,Max_speed_P2-Max_speed_P2(a4) move.w #$C,Acceleration_P2-Max_speed_P2(a4) move.w #$80,Deceleration_P2-Max_speed_P2(a4) cmpi.w #2,(Player_mode).w bne.s loc_1375E tst.b (Last_star_post_hit).w bne.s Tails_Init_Continued move.w #make_art_tile(ArtTile_Player_2,0,0),art_tile(a0) move.b #$C,top_solid_bit(a0) move.b #$D,lrb_solid_bit(a0) cmpi.b #2,(Special_bonus_entry_flag).w beq.s Tails_Init_Continued 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 Tails_Init_Continued ; --------------------------------------------------------------------------- loc_1375E: move.w #make_art_tile(ArtTile_Player_2,0,0),art_tile(a0) move.w (Player_1+top_solid_bit).w,top_solid_bit(a0) tst.w (Player_1+art_tile).w bpl.s Tails_Init_Continued ori.w #high_priority,art_tile(a0) Tails_Init_Continued: move.b #0,flips_remaining(a0) move.b #4,flip_speed(a0) move.b #0,(Super_Tails_flag).w move.b #30,air_left(a0) cmpi.w #$20,(Tails_CPU_routine).w beq.s loc_137A4 cmpi.w #$12,(Tails_CPU_routine).w beq.s loc_137A4 move.w #0,(Tails_CPU_routine).w loc_137A4: move.w #0,(Tails_CPU_idle_timer).w move.w #0,(Tails_CPU_flight_timer).w move.l #Obj_Tails_Tail,(Tails_tails).w move.w a0,(Tails_tails+$30).w move.b (Last_star_post_hit).w,(Tails_CPU_star_post_flag).w rts ; --------------------------------------------------------------------------- Tails_Control: cmpi.w #2,(Player_mode).w bne.s loc_13808 tst.w (Debug_mode_flag).w beq.s loc_13808 bclr #button_A,(Ctrl_1_pressed).w beq.s loc_137E0 eori.b #1,(Reverse_gravity_flag).w loc_137E0: btst #button_B,(Ctrl_1_pressed).w beq.s loc_13808 move.w #1,(Debug_placement_mode).w clr.b (Ctrl_1_locked).w btst #button_C,(Ctrl_1_held).w beq.s locret_13806 move.w #2,(Debug_placement_mode).w move.b #0,anim(a0) locret_13806: rts ; --------------------------------------------------------------------------- loc_13808: cmpa.w #Player_1,a0 bne.s loc_13830 move.w (Ctrl_1_logical).w,(Ctrl_2_logical).w tst.b (Ctrl_1_locked).w bne.s loc_1384A move.w (Ctrl_1).w,(Ctrl_2_logical).w move.w (Ctrl_1).w,(Ctrl_1_logical).w cmpi.w #$1A,(Tails_CPU_routine).w bhs.s loc_13840 bra.s loc_1384A ; --------------------------------------------------------------------------- loc_13830: tst.b (Ctrl_2_locked).w beq.s loc_1383A bpl.s loc_13840 bra.s loc_1384A ; --------------------------------------------------------------------------- loc_1383A: move.w (Ctrl_2).w,(Ctrl_2_logical).w loc_13840: tst.w (Competition_mode).w bne.s loc_1384A bsr.w Tails_CPU_Control loc_1384A: btst #0,object_control(a0) beq.s loc_13872 move.b #0,double_jump_flag(a0) tst.b (Flying_carrying_Sonic_flag).w beq.s loc_1388C lea (Player_1).w,a1 clr.b object_control(a1) bset #Status_InAir,status(a1) clr.w (Flying_carrying_Sonic_flag).w bra.s loc_1388C ; --------------------------------------------------------------------------- loc_13872: movem.l a4-a6,-(sp) moveq #0,d0 move.b status(a0),d0 andi.w #6,d0 move.w Tails_Modes(pc,d0.w),d1 jsr Tails_Modes(pc,d1.w) movem.l (sp)+,a4-a6 loc_1388C: cmpi.w #-$100,(Camera_min_Y_pos).w bne.s loc_1389C move.w (Screen_Y_wrap_value).w,d0 and.w d0,y_pos(a0) loc_1389C: bsr.s Tails_Display bsr.w Tails_Super bsr.w Sonic_RecordPos bsr.w Tails_Water move.b (Primary_Angle).w,next_tilt(a0) move.b (Secondary_Angle).w,tilt(a0) tst.b (WindTunnel_flag_P2).w beq.s loc_138C8 tst.b anim(a0) bne.s loc_138C8 move.b prev_anim(a0),anim(a0) loc_138C8: btst #1,object_control(a0) bne.s loc_138E4 bsr.w Animate_Tails tst.b (Reverse_gravity_flag).w beq.s loc_138E0 eori.b #2,render_flags(a0) loc_138E0: bsr.w Tails_Load_PLC loc_138E4: move.b object_control(a0),d0 andi.b #$A0,d0 bne.s locret_138F4 jsr (TouchResponse).l locret_138F4: rts ; --------------------------------------------------------------------------- Tails_Modes: dc.w Tails_Stand_Path-Tails_Modes dc.w Tails_Stand_Freespace-Tails_Modes dc.w Tails_Spin_Path-Tails_Modes dc.w Tails_Spin_Freespace-Tails_Modes ; --------------------------------------------------------------------------- Tails_Display: move.b invulnerability_timer(a0),d0 beq.s loc_1390C subq.b #1,invulnerability_timer(a0) lsr.b #3,d0 bcc.s loc_13912 loc_1390C: jsr (Draw_Sprite).l loc_13912: btst #Status_Invincible,status_secondary(a0) beq.s loc_1394E tst.b invincibility_timer(a0) beq.s loc_1394E move.b (Level_frame_counter+1).w,d0 andi.b #7,d0 bne.s loc_1394E subq.b #1,invincibility_timer(a0) bne.s loc_1394E tst.b (Boss_flag).w bne.s loc_13948 cmpi.b #12,air_left(a0) blo.s loc_13948 move.w (Current_music).w,d0 jsr (Play_Music).l loc_13948: bclr #Status_Invincible,status_secondary(a0) loc_1394E: btst #Status_SpeedShoes,status_secondary(a0) beq.s locret_139A6 tst.b speed_shoes_timer(a0) beq.s locret_139A6 move.b (Level_frame_counter+1).w,d0 andi.b #7,d0 bne.s locret_139A6 subq.b #1,speed_shoes_timer(a0) bne.s locret_139A6 tst.w (Competition_mode).w bne.s loc_139A8 move.w #$600,Max_speed_P2-Max_speed_P2(a4) move.w #$C,Acceleration_P2-Max_speed_P2(a4) move.w #$80,Deceleration_P2-Max_speed_P2(a4) tst.b (Super_Tails_flag).w beq.s loc_13998 move.w #$800,Max_speed_P2-Max_speed_P2(a4) move.w #$18,Acceleration_P2-Max_speed_P2(a4) move.w #$C0,Deceleration_P2-Max_speed_P2(a4) loc_13998: bclr #Status_SpeedShoes,status_secondary(a0) moveq #0,d0 jmp (Change_Music_Tempo).l ; --------------------------------------------------------------------------- locret_139A6: rts ; --------------------------------------------------------------------------- loc_139A8: lea (Character_Speeds).l,a1 moveq #0,d0 move.b character_id(a0),d0 lsl.w #3,d0 lea (a1,d0.w),a1 move.w (a1)+,Max_speed_P2-Max_speed_P2(a4) move.w (a1)+,Acceleration_P2-Max_speed_P2(a4) move.w (a1)+,Deceleration_P2-Max_speed_P2(a4) bclr #Status_SpeedShoes,status_secondary(a0) rts ; =============== S U B R O U T I N E ======================================= Tails_CPU_Control: move.b (Ctrl_2_held_logical).w,d0 andi.b #$7F,d0 beq.s loc_139DC move.w #10*60,(Tails_CPU_idle_timer).w loc_139DC: lea (Player_1).w,a1 move.w (Tails_CPU_routine).w,d0 move.w Tails_CPU_Control_Index(pc,d0.w),d0 jmp Tails_CPU_Control_Index(pc,d0.w) ; End of function Tails_CPU_Control ; --------------------------------------------------------------------------- Tails_CPU_Control_Index: dc.w loc_13A10-Tails_CPU_Control_Index dc.w Tails_Catch_Up_Flying-Tails_CPU_Control_Index dc.w Tails_FlySwim_Unknown-Tails_CPU_Control_Index dc.w loc_13D4A-Tails_CPU_Control_Index dc.w loc_13F40-Tails_CPU_Control_Index dc.w locret_13FC0-Tails_CPU_Control_Index dc.w loc_13FC2-Tails_CPU_Control_Index dc.w loc_13FFA-Tails_CPU_Control_Index dc.w loc_1408A-Tails_CPU_Control_Index dc.w loc_140C6-Tails_CPU_Control_Index dc.w loc_140CE-Tails_CPU_Control_Index dc.w loc_14106-Tails_CPU_Control_Index dc.w loc_1414C-Tails_CPU_Control_Index dc.w loc_141F2-Tails_CPU_Control_Index dc.w loc_1421C-Tails_CPU_Control_Index dc.w loc_14254-Tails_CPU_Control_Index dc.w loc_1425C-Tails_CPU_Control_Index dc.w loc_14286-Tails_CPU_Control_Index ; --------------------------------------------------------------------------- loc_13A10: tst.b (Tails_CPU_star_post_flag).w bne.w loc_13AF4 cmpi.w #0,(Current_zone_and_act).w bne.s loc_13A32 bsr.w sub_13ECA move.w #$A,(Tails_CPU_routine).w move.b #$83,object_control(a0) rts ; --------------------------------------------------------------------------- loc_13A32: cmpi.w #$100,(Current_zone_and_act).w beq.w loc_13B12 cmpi.w #$200,(Current_zone_and_act).w beq.w loc_13B12 cmpi.w #$300,(Current_zone_and_act).w bne.s loc_13A74 move.w #$18,x_pos(a0) move.w #$600,y_pos(a0) loc_13A5A: move.w #0,(Tails_CPU_idle_timer).w move.w #0,(Tails_CPU_flight_timer).w move.b #2,status(a0) move.w #$C,(Tails_CPU_routine).w rts ; --------------------------------------------------------------------------- loc_13A74: cmpi.w #$500,(Current_zone_and_act).w bne.s loc_13A8E bsr.w sub_13ECA move.w #$A,(Tails_CPU_routine).w move.b #$83,object_control(a0) rts ; --------------------------------------------------------------------------- loc_13A8E: cmpi.w #$600,(Current_zone_and_act).w beq.w loc_13B12 cmpi.w #$700,(Current_zone_and_act).w bne.s loc_13AB4 tst.w (SK_alone_flag).w bne.s loc_13AB4 move.w #$D8,x_pos(a0) move.w #$500,y_pos(a0) bra.s loc_13A5A ; --------------------------------------------------------------------------- loc_13AB4: cmpi.w #$800,(Current_zone_and_act).w beq.w loc_13B18 cmpi.w #$900,(Current_zone_and_act).w beq.w loc_13B12 cmpi.w #$A00,(Current_zone_and_act).w bne.s loc_13AE2 bsr.w sub_13ECA move.w #$A,(Tails_CPU_routine).w move.b #$83,object_control(a0) rts ; --------------------------------------------------------------------------- loc_13AE2: cmpi.w #$1600,(Current_zone_and_act).w beq.w loc_13B12 cmpi.b #$17,(Current_zone).w beq.s loc_13B18 loc_13AF4: move.b #0,anim(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) move.w #0,ground_vel(a0) move.b #0,status(a0) loc_13B12: move.b #0,object_control(a0) loc_13B18: move.w #6,(Tails_CPU_routine).w move.w #0,(Tails_CPU_flight_timer).w rts ; --------------------------------------------------------------------------- Tails_Catch_Up_Flying: move.b (Ctrl_2_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask|button_start_mask,d0 bne.s loc_13B50 move.w (Level_frame_counter).w,d0 andi.w #$3F,d0 bne.w locret_13BF6 tst.b object_control(a1) bmi.w locret_13BF6 move.b status(a1),d0 andi.b #$80,d0 bne.w locret_13BF6 loc_13B50: move.w #4,(Tails_CPU_routine).w 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 tst.b (Reverse_gravity_flag).w beq.s loc_13B78 addi.w #2*$C0,d0 loc_13B78: move.w d0,y_pos(a0) ori.w #high_priority,art_tile(a0) move.w #$100,priority(a0) moveq #0,d0 move.w d0,x_vel(a0) move.w d0,y_vel(a0) move.w d0,ground_vel(a0) move.b d0,flip_type(a0) move.b d0,double_jump_flag(a0) move.b #2,status(a0) move.b #30,air_left(a0) move.b #$81,object_control(a0) move.b d0,flips_remaining(a0) move.b d0,flip_speed(a0) move.w d0,move_lock(a0) move.b d0,invulnerability_timer(a0) move.b d0,invincibility_timer(a0) move.b d0,speed_shoes_timer(a0) move.b d0,status_tertiary(a0) move.b d0,scroll_delay_counter(a0) move.w d0,next_tilt(a0) ; and tilt move.b d0,stick_to_convex(a0) move.b d0,spin_dash_flag(a0) move.b d0,spin_dash_flag(a0) move.w d0,spin_dash_counter(a0) move.b d0,jumping(a0) move.b d0,$41(a0) move.b #(8*60)/2,double_jump_property(a0) bsr.w Tails_Set_Flying_Animation locret_13BF6: rts ; --------------------------------------------------------------------------- Tails_FlySwim_Unknown: tst.b render_flags(a0) bmi.s loc_13C3A addq.w #1,(Tails_CPU_flight_timer).w cmpi.w #5*60,(Tails_CPU_flight_timer).w blo.s loc_13C50 move.w #0,(Tails_CPU_flight_timer).w move.w #2,(Tails_CPU_routine).w move.b #$81,object_control(a0) move.b #1< 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 ; dc.b 0 ; TailsAni_Victory -> dc.b $A ; TailsAni_Hang2 -> Hanging dc.b 0 ; TailsAni_Bubble -> dc.b 0,0,0 ; TailsAni_Death,2,3 -> dc.b 0 ; TailsAni_Slide2? -> 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 $B,$C ; TailsAni_Fly,2 -> Fly1,2 dc.b $B ; TailsAni_Carry -> Fly1 dc.b $C ; TailsAni_Ascend -> Fly2 dc.b $B ; TailsAni_Tired -> Fly1 dc.b 0,0 ; TailsAni_Swim,2 -> dc.b 0 ; TailsAni_Tired2 -> dc.b 0 ; TailsAni_Tired3 -> dc.b 0 dc.b 0 dc.b 0 dc.b 0 dc.b 0 dc.b 0 dc.b 0 dc.b 0 dc.b 0 even AniTails_Tail: include "General/Sprites/Tails/Anim - Tails Tail.asm" ; --------------------------------------------------------------------------- Obj_Tails2P_Tail: move.l #Map_Tails2P_Tail,mappings(a0) move.w #make_art_tile(ArtTile_Player_2_Tail,0,0),art_tile(a0) cmpa.w #Tails_tails,a0 beq.s loc_16214 move.w #make_art_tile($690,0,0),art_tile(a0) loc_16214: move.w #$100,priority(a0) move.b #$18,width_pixels(a0) move.b #$18,height_pixels(a0) move.b #4,render_flags(a0) move.l #loc_16232,(a0) loc_16232: movea.w $30(a0),a2 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) move.w priority(a2),priority(a0) andi.w #drawing_mask,art_tile(a0) tst.w art_tile(a2) bpl.s loc_16266 ori.w #high_priority,art_tile(a0) loc_16266: moveq #0,d0 move.b anim(a2),d0 btst #Status_Push,status(a2) beq.s loc_1627C cmpi.b #5,d0 beq.s loc_1627C moveq #4,d0 loc_1627C: cmp.b $34(a0),d0 beq.s loc_1628C move.b d0,$34(a0) move.b byte_162A0(pc,d0.w),anim(a0) loc_1628C: lea (AniTails2P_Tail).l,a1 bsr.w Animate_Tails_Tail2P bsr.w Tails2P_Tail_Load_PLC jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- byte_162A0: dc.b 0,0 dc.b 3 dc.b 3 dc.b 0 dc.b 1 dc.b 1 dc.b 1 dc.b 1 dc.b 0 dc.b 1,1,1 dc.b 0 dc.b 0,0 dc.b 0 dc.b 0 dc.b 0 dc.b 0 dc.b 0 dc.b 0 dc.b 0,0,0 dc.b 0 dc.b 0,0 dc.b 0 dc.b 0,0 dc.b 0 dc.b 0,0 even AniTails2P_Tail: include "General/Sprites/Tails/Anim - Tails 2P Tail.asm" ; --------------------------------------------------------------------------- Obj_MGZ2_BossTransition: cmpi.w #2,(Player_mode).w beq.w loc_163D0 move.w (Camera_X_pos).w,d0 addi.w #$40,d0 move.w d0,x_pos(a0) move.w (Camera_Y_pos).w,d0 addi.w #$100,d0 move.w d0,y_pos(a0) lea (Player_2).w,a1 tst.b render_flags(a1) bmi.s loc_16328 move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) subq.w #1,y_pos(a1) move.l #Obj_Tails,(Player_2).w move.w #$12,(Tails_CPU_routine).w move.w #0,(Flying_carrying_Sonic_flag).w loc_16328: move.w #$168,$30(a0) move.l #loc_16334,(a0) loc_16334: subq.w #1,$30(a0) bne.s loc_16340 move.l #loc_16340,(a0) loc_16340: tst.b (Flying_carrying_Sonic_flag).w bne.s loc_16384 lea (Player_1).w,a1 move.w y_pos(a0),d0 cmp.w y_pos(a1),d0 bhs.s loc_16384 move.w d0,y_pos(a1) move.w #0,x_vel(a1) move.w #0,y_vel(a1) move.w #0,ground_vel(a1) move.b #0,spin_dash_flag(a1) cmpi.w #$14,(Tails_CPU_routine).w blo.s loc_1637E move.w x_pos(a1),x_pos(a0) loc_1637E: move.b #2,routine(a1) loc_16384: tst.b (Player_1+render_flags).w bmi.s locret_163CE cmpi.b #2,(Player_1+routine).w bne.s locret_163CE lea (Player_2).w,a1 move.w y_pos(a0),d0 cmp.w y_pos(a1),d0 bhs.s locret_163CE move.w #$12,(Tails_CPU_routine).w tst.w $30(a0) bne.s locret_163CE move.w d0,y_pos(a1) move.b #2,routine(a1) move.b #0,object_control(a1) move.b #0,spin_dash_flag(a1) move.w x_pos(a0),x_pos(a1) move.w #$14,(Tails_CPU_routine).w locret_163CE: rts ; --------------------------------------------------------------------------- loc_163D0: move.w (Camera_X_pos).w,d0 addi.w #$40,d0 move.w d0,x_pos(a0) move.w (Camera_Y_pos).w,d0 addi.w #$100,d0 move.w d0,y_pos(a0) move.w #$168,$30(a0) move.l #loc_163F4,(a0) loc_163F4: subq.w #1,$30(a0) bne.s loc_1640A move.l #loc_1640A,(a0) lea (Player_1).w,a1 move.w x_pos(a0),x_pos(a1) loc_1640A: lea (Player_1).w,a1 move.w y_pos(a0),d0 cmp.w y_pos(a1),d0 bhs.s locret_16442 move.w d0,y_pos(a1) addq.w #8,y_pos(a1) tst.w $30(a0) bne.s locret_16442 move.w d0,y_pos(a1) move.b #2,routine(a1) move.b #0,object_control(a1) move.b #0,spin_dash_flag(a1) move.w #$1A,(Tails_CPU_routine).w locret_16442: rts ; --------------------------------------------------------------------------- Obj_Knuckles: lea (Max_speed).w,a4 lea (Distance_from_top).w,a5 lea (Dust).w,a6 tst.w (Debug_placement_mode).w beq.s Knuckles_Normal cmpi.b #1,(Debug_placement_type).w beq.s loc_16488 btst #button_B,(Ctrl_1_pressed).w beq.s loc_1646C move.w #0,(Debug_placement_mode).w loc_1646C: addq.b #1,mapping_frame(a0) cmpi.b #$FB,mapping_frame(a0) blo.s loc_1647E move.b #0,mapping_frame(a0) loc_1647E: bsr.w Knuckles_Load_PLC jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_16488: jmp (DebugMode).l ; --------------------------------------------------------------------------- Knuckles_Normal: moveq #0,d0 move.b routine(a0),d0 move.w Knuckles_Index(pc,d0.w),d1 jmp Knuckles_Index(pc,d1.w) ; --------------------------------------------------------------------------- Knuckles_Index: dc.w Knuckles_Init-Knuckles_Index dc.w Knuckles_Control-Knuckles_Index dc.w loc_17BB6-Knuckles_Index dc.w loc_17C88-Knuckles_Index dc.w loc_17CBA-Knuckles_Index dc.w loc_17CCE-Knuckles_Index dc.w loc_17CEA-Knuckles_Index ; --------------------------------------------------------------------------- Knuckles_Init: addq.b #2,routine(a0) move.b #$13,y_radius(a0) move.b #9,x_radius(a0) move.b #$13,default_y_radius(a0) move.b #9,default_x_radius(a0) move.l #Map_Knuckles,mappings(a0) move.w #$100,priority(a0) move.b #$18,width_pixels(a0) move.b #$18,height_pixels(a0) move.b #4,render_flags(a0) move.b #2,character_id(a0) move.w #$600,Max_speed-Max_speed(a4) move.w #$C,Acceleration-Max_speed(a4) move.w #$80,Deceleration-Max_speed(a4) tst.b (Last_star_post_hit).w bne.s Knuckles_Init_Continued move.w #make_art_tile(ArtTile_Player_1,0,0),art_tile(a0) move.b #$C,top_solid_bit(a0) move.b #$D,lrb_solid_bit(a0) cmpi.b #2,(Special_bonus_entry_flag).w beq.s Knuckles_Init_Continued 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 Knuckles_Init_Continued: move.b #0,flips_remaining(a0) move.b #4,flip_speed(a0) move.b #0,(Super_Sonic_Knux_flag).w move.b #30,air_left(a0) subi.w #$20,x_pos(a0) addi.w #4,y_pos(a0) jsr (Reset_Player_Position_Array).l addi.w #$20,x_pos(a0) subi.w #4,y_pos(a0) rts ; --------------------------------------------------------------------------- Knuckles_Control: tst.w (Debug_mode_flag).w beq.s loc_165A2 bclr #button_A,(Ctrl_1_pressed).w beq.s loc_16580 eori.b #1,(Reverse_gravity_flag).w loc_16580: btst #button_B,(Ctrl_1_pressed).w beq.s loc_165A2 move.w #1,(Debug_placement_mode).w clr.b (Ctrl_1_locked).w btst #button_C,(Ctrl_1_held).w beq.s locret_165A0 move.w #2,(Debug_placement_mode).w locret_165A0: rts ; --------------------------------------------------------------------------- loc_165A2: tst.b (Ctrl_1_locked).w bne.s loc_165AE move.w (Ctrl_1).w,(Ctrl_1_logical).w loc_165AE: btst #0,object_control(a0) beq.s loc_165BE move.b #0,double_jump_flag(a0) bra.s loc_165D8 ; --------------------------------------------------------------------------- loc_165BE: movem.l a4-a6,-(sp) moveq #0,d0 move.b status(a0),d0 andi.w #6,d0 move.w Knux_Modes(pc,d0.w),d1 jsr Knux_Modes(pc,d1.w) movem.l (sp)+,a4-a6 loc_165D8: cmpi.w #-$100,(Camera_min_Y_pos).w bne.s loc_165E8 move.w (Screen_Y_wrap_value).w,d0 and.w d0,y_pos(a0) loc_165E8: bsr.s Knuckles_Display bsr.w SonicKnux_SuperHyper bsr.w Sonic_RecordPos bsr.w Knuckles_Water move.b (Primary_Angle).w,next_tilt(a0) move.b (Secondary_Angle).w,tilt(a0) tst.b (WindTunnel_flag).w beq.s loc_16614 tst.b anim(a0) bne.s loc_16614 move.b prev_anim(a0),anim(a0) loc_16614: btst #1,object_control(a0) bne.s loc_16630 bsr.w Animate_Knuckles tst.b (Reverse_gravity_flag).w beq.s loc_1662C eori.b #2,render_flags(a0) loc_1662C: bsr.w Knuckles_Load_PLC loc_16630: move.b object_control(a0),d0 andi.b #$A0,d0 bne.s locret_16640 jsr (TouchResponse).l locret_16640: rts ; --------------------------------------------------------------------------- Knux_Modes: dc.w Knux_Stand_Path-Knux_Modes dc.w Knux_Stand_Freespace-Knux_Modes dc.w Knux_Spin_Path-Knux_Modes dc.w Knux_Spin_Freespace-Knux_Modes ; =============== S U B R O U T I N E ======================================= Knuckles_Display: move.b invulnerability_timer(a0),d0 beq.s loc_16658 subq.b #1,invulnerability_timer(a0) lsr.b #3,d0 bcc.s loc_1665E loc_16658: jsr (Draw_Sprite).l loc_1665E: btst #Status_Invincible,status_secondary(a0) beq.s loc_1669A tst.b invincibility_timer(a0) beq.s loc_1669A move.b (Level_frame_counter+1).w,d0 andi.b #7,d0 bne.s loc_1669A subq.b #1,invincibility_timer(a0) bne.s loc_1669A tst.b (Boss_flag).w bne.s loc_16694 cmpi.b #12,air_left(a0) blo.s loc_16694 move.w (Current_music).w,d0 jsr (Play_Music).l loc_16694: bclr #Status_Invincible,status_secondary(a0) loc_1669A: btst #Status_SpeedShoes,status_secondary(a0) beq.s locret_166EC tst.b speed_shoes_timer(a0) beq.s locret_166EC move.b (Level_frame_counter+1).w,d0 andi.b #7,d0 bne.s locret_166EC subq.b #1,speed_shoes_timer(a0) bne.s locret_166EC move.w #$600,Max_speed-Max_speed(a4) move.w #$C,Acceleration-Max_speed(a4) move.w #$80,Deceleration-Max_speed(a4) tst.b (Super_Sonic_Knux_flag).w beq.s loc_166DE move.w #$800,Max_speed-Max_speed(a4) move.w #$18,Acceleration-Max_speed(a4) move.w #$C0,Deceleration-Max_speed(a4) loc_166DE: bclr #Status_SpeedShoes,status_secondary(a0) moveq #0,d0 jmp (Change_Music_Tempo).l ; --------------------------------------------------------------------------- locret_166EC: rts ; End of function Knuckles_Display ; =============== S U B R O U T I N E ======================================= Knuckles_Water: tst.b (Water_flag).w bne.s loc_166F6 locret_166F4: rts ; --------------------------------------------------------------------------- loc_166F6: move.w (Water_level).w,d0 cmp.w y_pos(a0),d0 bge.s loc_1676E bset #Status_Underwater,status(a0) bne.s locret_166F4 addq.b #1,(Water_entered_counter).w movea.l a0,a1 bsr.w Player_ResetAirTimer move.l #Obj_AirCountdown,(Breathing_bubbles).w move.b #$81,(Breathing_bubbles+subtype).w move.l a0,(Breathing_bubbles+$40).w move.w #$300,Max_speed-Max_speed(a4) move.w #6,Acceleration-Max_speed(a4) move.w #$40,Deceleration-Max_speed(a4) tst.b (Super_Sonic_Knux_flag).w beq.s loc_1674A move.w #$400,Max_speed-Max_speed(a4) move.w #$C,Acceleration-Max_speed(a4) move.w #$60,Deceleration-Max_speed(a4) loc_1674A: tst.b object_control(a0) bne.s locret_166F4 asr x_vel(a0) asr y_vel(a0) asr y_vel(a0) beq.s locret_166F4 move.w #1<<8,anim(a6) ; and prev_anim move.w #sfx_Splash,d0 jmp (Play_SFX).l ; --------------------------------------------------------------------------- loc_1676E: bclr #Status_Underwater,status(a0) beq.w locret_166F4 addq.b #1,(Water_entered_counter).w movea.l a0,a1 bsr.w Player_ResetAirTimer move.w #$600,Max_speed-Max_speed(a4) move.w #$C,Acceleration-Max_speed(a4) move.w #$80,Deceleration-Max_speed(a4) tst.b (Super_Sonic_Knux_flag).w beq.s loc_167A8 move.w #$800,Max_speed-Max_speed(a4) move.w #$18,Acceleration-Max_speed(a4) move.w #$C0,Deceleration-Max_speed(a4) loc_167A8: cmpi.b #4,routine(a0) beq.s loc_167C4 tst.b object_control(a0) bne.s loc_167C4 move.w y_vel(a0),d0 cmpi.w #-$400,d0 blt.s loc_167C4 asl y_vel(a0) loc_167C4: cmpi.b #$1C,anim(a0) beq.w locret_166F4 tst.w y_vel(a0) beq.w locret_166F4 move.w #1<<8,anim(a6) ; and prev_anim cmpi.w #-$1000,y_vel(a0) bgt.s loc_167EA move.w #-$1000,y_vel(a0) loc_167EA: move.w #sfx_Splash,d0 jmp (Play_SFX).l ; End of function Knuckles_Water ; --------------------------------------------------------------------------- Knux_Stand_Path: bsr.w SonicKnux_Spindash bsr.w Knux_Jump bsr.w Player_SlopeResist bsr.w Knux_InputAcceleration_Path bsr.w SonicKnux_Roll bsr.w Player_LevelBound jsr (MoveSprite_TestGravity2).l bsr.w Call_Player_AnglePos bsr.w Player_SlopeRepel tst.b (Background_collision_flag).w beq.s locret_1684A bsr.w sub_F846 tst.w d1 bmi.w Kill_Character movem.l a4-a6,-(sp) bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_1683A sub.w d1,x_pos(a0) loc_1683A: bsr.w CheckRightWallDist tst.w d1 bpl.s loc_16846 add.w d1,x_pos(a0) loc_16846: movem.l (sp)+,a4-a6 locret_1684A: rts ; --------------------------------------------------------------------------- Knux_Stand_Freespace: tst.b double_jump_flag(a0) bne.s Knux_Glide_Freespace bsr.w Knux_JumpHeight bsr.w Knux_ChgJumpDir bsr.w Player_LevelBound jsr (MoveSprite_TestGravity).l btst #Status_Underwater,status(a0) beq.s loc_16872 subi.w #$28,y_vel(a0) loc_16872: bsr.w Player_JumpAngle bsr.w SonicKnux_DoLevelCollision rts ; --------------------------------------------------------------------------- Knux_Glide_Freespace: bsr.w Knuckles_Move_Glide bsr.w Player_LevelBound jsr (MoveSprite_TestGravity2).l bsr.w Knuckles_Glide locret_1688E: rts ; =============== S U B R O U T I N E ======================================= Knuckles_Glide: move.b double_jump_flag(a0),d0 beq.s locret_1688E cmpi.b #2,d0 beq.w Knuckles_Fall_From_Glide cmpi.b #3,d0 beq.w Knuckles_Sliding cmpi.b #4,d0 beq.w Knuckles_Wall_Climb cmpi.b #5,d0 beq.w Knuckles_Climb_Ledge ; This function updates 'Gliding_collision_flags'. bsr.w Knux_DoLevelCollision_CheckRet btst #Status_InAir,(Gliding_collision_flags).w beq.s Knux_Gliding_HitFloor btst #Status_Push,(Gliding_collision_flags).w bne.w Knuckles_Gliding_HitWall move.b (Ctrl_1_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 bne.s .continueGliding ; The player has let go of the jump button, so exit the gliding state ; and enter the falling state. move.b #2,double_jump_flag(a0) move.b #$21,anim(a0) bclr #Status_Facing,status(a0) tst.w x_vel(a0) bpl.s .skip1 bset #Status_Facing,status(a0) .skip1: ; Divide Knuckles' X velocity by 4. asr.w x_vel(a0) asr.w x_vel(a0) move.b default_y_radius(a0),y_radius(a0) move.b default_x_radius(a0),x_radius(a0) rts ; --------------------------------------------------------------------------- ; loc_1690A: .continueGliding: bra.w Knuckles_Set_Gliding_Animation ; --------------------------------------------------------------------------- Knux_Gliding_HitFloor: bclr #Status_Facing,status(a0) tst.w x_vel(a0) bpl.s + bset #Status_Facing,status(a0) + move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 beq.s loc_1693E move.w ground_vel(a0),x_vel(a0) move.w #0,y_vel(a0) bra.w Knux_TouchFloor ; --------------------------------------------------------------------------- loc_1693E: move.b #3,double_jump_flag(a0) move.b #$CC,mapping_frame(a0) move.b #$7F,anim_frame_timer(a0) move.b #0,anim_frame(a0) ; The drowning countdown uses the dust clouds' VRAM, so don't create ; dust if Knuckles is drowning. cmpi.b #12,air_left(a0) blo.s + ; Create dust clouds. move.b #6,routine(a6) move.b #$15,mapping_frame(a6) + rts ; --------------------------------------------------------------------------- Knuckles_Gliding_HitWall: tst.b (Disable_wall_grab).w bmi.w .fail move.b lrb_solid_bit(a0),d5 move.b double_jump_property(a0),d0 addi.b #$40,d0 bpl.s .right ;.left: bset #Status_Facing,status(a0) bsr.w CheckLeftCeilingDist or.w d0,d1 bne.s .checkFloorLeft addq.w #1,x_pos(a0) bra.s .success .right: bclr #Status_Facing,status(a0) bsr.w CheckRightCeilingDist or.w d0,d1 bne.w .checkFloorRight ; loc_169A6: .success: moveq #signextendB(sfx_Grab),d0 ; If Hyper Knuckles glides into a wall at a high-enough ; speed, then make the screen shake and harm all enemies ; on-screen. tst.b (Super_Sonic_Knux_flag).w bpl.s .noQuake cmpi.w #$480,ground_vel(a0) blo.s .noQuake move.w #$14,(Glide_screen_shake).w bsr.w HyperAttackTouchResponse moveq #signextendB(sfx_Thump),d0 ; loc_169C2: .noQuake: jsr (Play_SFX).l move.w #0,ground_vel(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) move.b #4,double_jump_flag(a0) move.b #$B7,mapping_frame(a0) move.b #$7F,anim_frame_timer(a0) move.b #0,anim_frame(a0) move.b #3,double_jump_property(a0) ; 'x_pos+2' holds the X coordinate that Knuckles was at when he first ; latched onto the wall. move.w x_pos(a0),x_pos+2(a0) rts ; --------------------------------------------------------------------------- ; loc_16A00: .checkFloorLeft: ; This adds the Y radius to the X coordinate... ; This appears to be a bug, but, luckily, the X and Y radius are both ; 10, so this is harmless. move.w x_pos(a0),d3 move.b y_radius(a0),d0 ext.w d0 sub.w d0,d3 subq.w #1,d3 tst.b (Reverse_gravity_flag).w bne.s .reverseGravity ; loc_16A14: .checkFloorCommon: move.w y_pos(a0),d2 subi.w #11,d2 jsr (ChkFloorEdge_Part3).l tst.w d1 bmi.s .fail cmpi.w #12,d1 bhs.s .fail add.w d1,y_pos(a0) bra.w .success ; --------------------------------------------------------------------------- ; loc_16A34: .reverseGravity: move.w y_pos(a0),d2 addi.w #11,d2 eori.w #$F,d2 jsr (ChkFloorEdge_ReverseGravity_Part2).l tst.w d1 bmi.s .fail cmpi.w #12,d1 bhs.s .fail sub.w d1,y_pos(a0) bra.w .success ; --------------------------------------------------------------------------- ; loc_16A58: .checkFloorRight: ; This adds the Y radius to the X coordinate... ; This appears to be a bug, but, luckily, the X and Y radius are both ; 10, so this is harmless. move.w x_pos(a0),d3 move.b y_radius(a0),d0 ext.w d0 add.w d0,d3 addq.w #1,d3 tst.b (Reverse_gravity_flag).w bne.s Knuckles_Gliding_HitWall.reverseGravity bra.s .checkFloorCommon ; --------------------------------------------------------------------------- ; loc_16A6E: .fail: move.b #2,double_jump_flag(a0) move.b #$21,anim(a0) move.b default_y_radius(a0),y_radius(a0) move.b default_x_radius(a0),x_radius(a0) bset #Status_InAir,(Gliding_collision_flags).w rts ; --------------------------------------------------------------------------- Knuckles_Fall_From_Glide: bsr.w Knux_ChgJumpDir ; Apply gravity. addi.w #$38,y_vel(a0) ; Fall slower when underwater. btst #Status_Underwater,status(a0) beq.s .skip1 subi.w #$28,y_vel(a0) .skip1: ; This function updates 'Gliding_collision_flags'. bsr.w Knux_DoLevelCollision_CheckRet btst #Status_InAir,(Gliding_collision_flags).w bne.s .return ; Knuckles has touched the ground. move.w #0,ground_vel(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) move.b y_radius(a0),d0 sub.b default_y_radius(a0),d0 ext.w d0 tst.b (Reverse_gravity_flag).w beq.s .skip2 neg.w d0 .skip2: add.w d0,y_pos(a0) moveq #signextendB(sfx_GlideLand),d0 jsr (Play_SFX).l move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 beq.s .skip3 bra.w Knux_TouchFloor .skip3: bsr.w Knux_TouchFloor move.w #$F,move_lock(a0) move.b #$23,anim(a0) ; locret_16B04: .return: rts ; --------------------------------------------------------------------------- Knuckles_Sliding: move.b (Ctrl_1_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 beq.s .getUp tst.w x_vel(a0) bpl.s .goingRight ;.goingLeft: addi.w #$20,x_vel(a0) bmi.s .continueSliding2 bra.s .getUp ; --------------------------------------------------------------------------- ; loc_16B20: .continueSliding2: bra.s .continueSliding ; --------------------------------------------------------------------------- ; loc_16B22: .goingRight: subi.w #$20,x_vel(a0) bpl.s .continueSliding ; loc_16B2A: .getUp: move.w #0,ground_vel(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) move.b y_radius(a0),d0 sub.b default_y_radius(a0),d0 ext.w d0 tst.b (Reverse_gravity_flag).w beq.s .skip1 neg.w d0 .skip1: add.w d0,y_pos(a0) bsr.w Knux_TouchFloor move.w #$F,move_lock(a0) move.b #$22,anim(a0) rts ; --------------------------------------------------------------------------- ; loc_16B64: .continueSliding: bsr.w Knux_DoLevelCollision_CheckRet ; Get distance from floor in 'd1', and angle of floor in 'd3'. bsr.w sub_11FD6 ; If the distance from the floor is suddenly really high, then ; Knuckles must have slid off a ledge, so make him enter his falling ; state. cmpi.w #14,d1 bge.s .fail tst.b (Reverse_gravity_flag).w beq.s .skip2 neg.w d1 .skip2: add.w d1,y_pos(a0) move.b d3,angle(a0) ; Play the sliding sound every 8 frames. move.b (Level_frame_counter+1).w,d0 andi.b #7,d0 bne.s .skip3 moveq #signextendB(sfx_GroundSlide),d0 jsr (Play_SFX).l .skip3: rts ; --------------------------------------------------------------------------- ; loc_16B96: .fail: move.b #2,double_jump_flag(a0) move.b #$21,anim(a0) move.b default_y_radius(a0),y_radius(a0) move.b default_x_radius(a0),x_radius(a0) bset #Status_InAir,(Gliding_collision_flags).w rts ; --------------------------------------------------------------------------- Knuckles_Wall_Climb: tst.b (Disable_wall_grab).w bmi.w Knuckles_LetGoOfWall ; If Knuckles' X coordinate is no longer the same as when he first ; latched onto the wall, then detach him from the wall. This is ; probably intended to detach Knuckles from the wall if something ; physically pushes him away from it. move.w x_pos(a0),d0 cmp.w x_pos+2(a0),d0 bne.w Knuckles_LetGoOfWall ; If an object is now carrying Knuckles, then detach him from the ; wall. btst #Status_OnObj,status(a0) bne.w Knuckles_LetGoOfWall move.w #0,ground_vel(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) move.l (Primary_collision_addr).w,(Collision_addr).w cmpi.b #$D,lrb_solid_bit(a0) beq.s + move.l (Secondary_collision_addr).w,(Collision_addr).w + move.b lrb_solid_bit(a0),d5 moveq #0,d1 ; Climbing animation delta: make the animation pause. btst #button_up,(Ctrl_1_logical).w beq.w .notClimbingUp ;.climbingUp: tst.b (Reverse_gravity_flag).w bne.w .climbingUp_ReverseGravity ; Get Knuckles' distance from the wall in 'd1'. move.w y_pos(a0),d2 subi.w #11,d2 bsr.w GetDistanceFromWall ; If the wall is far away from Knuckles, then we must have reached a ; ledge, so make Knuckles climb up onto it. cmpi.w #4,d1 bge.w Knuckles_ClimbUp ; If Knuckles has encountered a small dip in the wall, then make him ; stop. tst.w d1 bne.w .notMoving ; Get Knuckles' distance from the ceiling in 'd1'. move.b lrb_solid_bit(a0),d5 move.w y_pos(a0),d2 subq.w #8,d2 move.w x_pos(a0),d3 bsr.w CheckCeilingDist_WithRadius ; Check if Knuckles has room above him. tst.w d1 bpl.s .moveUp ; Knuckles is bumping into the ceiling, so push him out. sub.w d1,y_pos(a0) moveq #1,d1 ; Climbing animation delta: make the animation play forwards. bra.w .finishMoving ; --------------------------------------------------------------------------- ; loc_16C4C: .moveUp: subq.w #1,y_pos(a0) ; Super Knuckles and Hyper Knuckles climb walls faster. tst.b (Super_Sonic_Knux_flag).w beq.s .notSuperOrHyper1 subq.w #1,y_pos(a0) .notSuperOrHyper1: moveq #1,d1 ; Climbing animation delta: make the animation play forwards. ; Don't let Knuckles climb through the level's upper boundary. move.w (Camera_min_Y_pos).w,d0 ; If the level wraps vertically, then don't bother with any of this. cmpi.w #-$100,d0 beq.w .finishMoving ; Check if Knuckles is over the level's top boundary. addi.w #16,d0 cmp.w y_pos(a0),d0 ble.w .finishMoving ; Knuckles is climbing over the level's top boundary: push him back ; down. move.w d0,y_pos(a0) bra.w .finishMoving ; --------------------------------------------------------------------------- ; loc_16C7C: .climbingDown_ReverseGravity: ; Knuckles is climbing down. ; ...I'm not sure what this code is for. cmpi.b #$BD,mapping_frame(a0) bne.s .skip3 move.b #$B7,mapping_frame(a0) subq.w #3,y_pos(a0) subq.w #3,x_pos(a0) btst #Status_Facing,status(a0) beq.s .skip3 addq.w #3*2,x_pos(a0) .skip3: ; Get Knuckles' distance from the wall in 'd1'. move.w y_pos(a0),d2 subi.w #11,d2 bsr.w GetDistanceFromWall ; If Knuckles is no longer against the wall (he has climbed off the ; bottom of it) then make him let go. tst.w d1 bne.w Knuckles_LetGoOfWall ; Get Knuckles' distance from the floor in 'd1'. move.b top_solid_bit(a0),d5 move.w y_pos(a0),d2 subi.w #9,d2 move.w x_pos(a0),d3 bsr.w CheckCeilingDist_WithRadius ; Check if Knuckles has room below him. tst.w d1 bpl.s .moveDown_ReverseGravity ; Knuckles has reached the floor. sub.w d1,y_pos(a0) move.b (Primary_Angle).w,d0 addi.b #$40,d0 neg.b d0 subi.b #$40,d0 move.b d0,angle(a0) move.w #0,ground_vel(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) bsr.w Knux_TouchFloor move.b #5,anim(a0) rts ; --------------------------------------------------------------------------- ; loc_16CFC: .moveDown_ReverseGravity: subq.w #1,y_pos(a0) ; Super Knuckles and Hyper Knuckles climb walls faster. tst.b (Super_Sonic_Knux_flag).w beq.s .notSuperOrHyper2 subq.w #1,y_pos(a0) .notSuperOrHyper2: moveq #-1,d1 ; Climbing animation delta: make the animation play backwards. bra.w .finishMoving ; --------------------------------------------------------------------------- ; loc_16D10: .notClimbingUp: btst #button_down,(Ctrl_1_logical).w beq.w .finishMoving ;.climbingDown: tst.b (Reverse_gravity_flag).w bne.w .climbingDown_ReverseGravity ; ...I'm not sure what this code is for. cmpi.b #$BD,mapping_frame(a0) bne.s .skip4 move.b #$B7,mapping_frame(a0) addq.w #3,y_pos(a0) subq.w #3,x_pos(a0) btst #Status_Facing,status(a0) beq.s .skip4 addq.w #3*2,x_pos(a0) .skip4: ; Get Knuckles' distance from the wall in 'd1'. move.w y_pos(a0),d2 addi.w #11,d2 bsr.w GetDistanceFromWall ; If Knuckles is no longer against the wall (he has climbed off the ; bottom of it) then make him let go. tst.w d1 bne.w Knuckles_LetGoOfWall ; Get Knuckles' distance from the floor in 'd1'. move.b top_solid_bit(a0),d5 move.w y_pos(a0),d2 addi.w #9,d2 move.w x_pos(a0),d3 bsr.w sub_F828 ; Check if Knuckles has room below him. tst.w d1 bpl.s .moveDown ; loc_16D6E: .reachedFloor: ; Knuckles has reached the floor. add.w d1,y_pos(a0) move.b (Primary_Angle).w,angle(a0) move.w #0,ground_vel(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) bsr.w Knux_TouchFloor move.b #5,anim(a0) rts ; --------------------------------------------------------------------------- ; loc_16D96: .moveDown: addq.w #1,y_pos(a0) ; Super Knuckles and Hyper Knuckles climb walls faster. tst.b (Super_Sonic_Knux_flag).w beq.s .notSuperOrHyper3 addq.w #1,y_pos(a0) .notSuperOrHyper3: moveq #-1,d1 ; Climbing animation delta: make the animation play backwards. bra.s .finishMoving ; --------------------------------------------------------------------------- ; loc_16DA8: .climbingUp_ReverseGravity: ; Get Knuckles' distance from the wall in 'd1'. move.w y_pos(a0),d2 addi.w #11,d2 bsr.w GetDistanceFromWall ; If the wall is far away from Knuckles, then we must have reached a ; ledge, so make Knuckles climb up onto it. cmpi.w #4,d1 bge.w Knuckles_ClimbUp ; If Knuckles has encountered a small dip in the wall, then make him ; stop. tst.w d1 bne.w .notMoving ; Get Knuckles' distance from the ceiling in 'd1'. move.b lrb_solid_bit(a0),d5 move.w y_pos(a0),d2 addq.w #8,d2 move.w x_pos(a0),d3 bsr.w sub_F828 ; Check if Knuckles has room above him. tst.w d1 bpl.s .moveUp_ReverseGravity ; Knuckles is bumping into the ceiling, so push him out. add.w d1,y_pos(a0) moveq #1,d1 ; Climbing animation delta: make the animation play forwards. bra.w .finishMoving ; --------------------------------------------------------------------------- ; loc_16DE2: .moveUp_ReverseGravity: addq.w #1,y_pos(a0) ; Super Knuckles and Hyper Knuckles climb walls faster. tst.b (Super_Sonic_Knux_flag).w beq.s .notSuperOrHyper4 addq.w #1,y_pos(a0) .notSuperOrHyper4: moveq #1,d1 ; Climbing animation delta: make the animation play forwards. ; Don't let Knuckles climb through the level's upper boundary. ; If the level wraps vertically, then don't bother with any of this. cmpi.w #-$100,(Camera_min_Y_pos).w beq.w .finishMoving ; Check if Knuckles is over the level's top boundary. move.w (Camera_max_Y_pos).w,d0 addi.w #$D0,d0 cmp.w y_pos(a0),d0 bge.w .finishMoving ; Knuckles is climbing over the level's top boundary: push him back ; down. move.w d0,y_pos(a0) ; loc_16E10: .finishMoving: ; This block of code was not here in KiS2. ; This code detaches Knuckles from the wall if there is ; ground directly below him. Note that this code specifically ; does not run if the player is holding up or down: this is ; because similar code already runs if either of those ; buttons are being held. Presumably, this check was added so ; that Knuckles would properly detach from the wall if a ; rising floor (think Marble Garden Zone Act 2) came up from ; under him. With that said, KiS2 lacks this logic, and yet ; Knuckles seems to detach from the wall in Hill Top Zone's ; rising wall section just fine, so I'm not sure whether this ; code was ever actually needed in the first place. move.b (Ctrl_1_held_logical).w,d0 andi.b #button_up_mask|button_down_mask,d0 bne.s .isMovingUpOrDown ; Get Knuckles' distance from the floor in 'd1'. move.b top_solid_bit(a0),d5 move.w y_pos(a0),d2 addi.w #9,d2 move.w x_pos(a0),d3 bsr.w sub_F828 ; Check if Knuckles has room below him. tst.w d1 bmi.w .reachedFloor ; Bug: 'd1' has been overwritten by 'sub_F828', but the code ; after this needs it for updating Knuckles' animation. This ; bug is the reason why Knuckles resets to his first climbing ; frame when the player is not holding up or down. .isMovingUpOrDown: ; If Knuckles has not moved, skip this. tst.w d1 beq.s .notMoving ; Only animate every 4 frames. subq.b #1,double_jump_property(a0) bpl.s .notMoving move.b #3,double_jump_property(a0) ; Add delta to animation frame. add.b mapping_frame(a0),d1 ; Make the animation loop. cmpi.b #$B7,d1 bhs.s .noLoop1 move.b #$BC,d1 .noLoop1: cmpi.b #$BC,d1 bls.s .noLoop2 move.b #$B7,d1 .noLoop2: ; Apply the frame. move.b d1,mapping_frame(a0) ; loc_16E60: .notMoving: move.b #$20,anim_frame_timer(a0) move.b #0,anim_frame(a0) move.w (Ctrl_1_logical).w,d0 andi.w #button_A_mask|button_B_mask|button_C_mask,d0 beq.s .hasNotJumped ; Knuckles has jumped off the wall. move.w #-$380,y_vel(a0) move.w #$400,x_vel(a0) bchg #Status_Facing,status(a0) bne.s .goingRight neg.w x_vel(a0) .goingRight: bset #Status_InAir,status(a0) move.b #1,jumping(a0) move.b #$E,y_radius(a0) move.b #7,x_radius(a0) move.b #2,anim(a0) bset #Status_Roll,status(a0) move.b #0,double_jump_flag(a0) ; locret_16EB8: .hasNotJumped: rts ; --------------------------------------------------------------------------- ; loc_16EBA: Knuckles_ClimbUp: move.b #5,double_jump_flag(a0) cmpi.b #$BD,mapping_frame(a0) beq.s + move.b #0,double_jump_property(a0) bsr.s Knuckles_DoLedgeClimbingAnimation + rts ; --------------------------------------------------------------------------- ; loc_16ED2: Knuckles_LetGoOfWall: move.b #2,double_jump_flag(a0) move.w #($21<<8)|$21,anim(a0) ; and prev_anim move.b #$CB,mapping_frame(a0) move.b #7,anim_frame_timer(a0) move.b #1,anim_frame(a0) move.b default_y_radius(a0),y_radius(a0) move.b default_x_radius(a0),x_radius(a0) rts ; End of function Knuckles_Glide ; =============== S U B R O U T I N E ======================================= ; sub_16EFE: Knuckles_DoLedgeClimbingAnimation: moveq #0,d0 move.b double_jump_property(a0),d0 lea Knuckles_ClimbLedge_Frames(pc,d0.w),a1 move.b (a1)+,mapping_frame(a0) move.b (a1)+,d0 ext.w d0 btst #Status_Facing,status(a0) beq.s + neg.w d0 + add.w d0,x_pos(a0) move.b (a1)+,d1 ext.w d1 tst.b (Reverse_gravity_flag).w beq.s + neg.w d1 + add.w d1,y_pos(a0) move.b (a1)+,anim_frame_timer(a0) addq.b #4,double_jump_property(a0) move.b #0,anim_frame(a0) rts ; End of function Knuckles_DoLedgeClimbingAnimation ; --------------------------------------------------------------------------- ; Strangely, the last frame uses frame $D2. It will never be seen, however, ; because it is immediately overwritten by Knuckles' waiting animation. Knuckles_ClimbLedge_Frames: ; mapping_frame, x_pos, y_pos, anim_frame_timer dc.b $BD, 3, -3, 6 dc.b $BE, 8, -10, 6 dc.b $BF, -8, -12, 6 dc.b $D2, 8, -5, 6 Knuckles_ClimbLedge_Frames_End: ; =============== S U B R O U T I N E ======================================= ; sub_16F4E: GetDistanceFromWall: move.b lrb_solid_bit(a0),d5 btst #Status_Facing,status(a0) bne.s .facingLeft ;.facingRight: move.w x_pos(a0),d3 bra.w loc_FAA4 ; --------------------------------------------------------------------------- ; loc_16F62: .facingLeft: move.w x_pos(a0),d3 subq.w #1,d3 bra.w loc_FDC8 ; End of function GetDistanceFromWall ; --------------------------------------------------------------------------- Knuckles_Climb_Ledge: tst.b anim_frame_timer(a0) bne.s locret_16FA6 bsr.w Knuckles_DoLedgeClimbingAnimation ; Have we reached the end of the ledge-climbing animation? cmpi.b #Knuckles_ClimbLedge_Frames_End-Knuckles_ClimbLedge_Frames,double_jump_property(a0) bne.s locret_16FA6 ; Yes. move.w #0,ground_vel(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) btst #Status_Facing,status(a0) beq.s + subq.w #1,x_pos(a0) + bsr.w Knux_TouchFloor move.b #5,anim(a0) locret_16FA6: rts ; =============== S U B R O U T I N E ======================================= Knuckles_Set_Gliding_Animation: move.b #$20,anim_frame_timer(a0) move.b #0,anim_frame(a0) move.w #($20<<8)|$20,anim(a0) ; and prev_anim bclr #Status_Push,status(a0) bclr #Status_Facing,status(a0) ; Update Knuckles' frame, depending on where he's facing. moveq #0,d0 move.b double_jump_property(a0),d0 addi.b #$10,d0 lsr.w #5,d0 move.b RawAni_Knuckles_GlideTurn(pc,d0.w),d1 move.b d1,mapping_frame(a0) cmpi.b #$C4,d1 bne.s + bset #Status_Facing,status(a0) move.b #$C0,mapping_frame(a0) + rts ; End of function Knuckles_Set_Gliding_Animation ; --------------------------------------------------------------------------- RawAni_Knuckles_GlideTurn: dc.b $C0 dc.b $C1 dc.b $C2 dc.b $C3 dc.b $C4 dc.b $C3 dc.b $C2 dc.b $C1 even ; =============== S U B R O U T I N E ======================================= Knuckles_Move_Glide: cmpi.b #1,double_jump_flag(a0) bne.w .doNotKillspeed move.w ground_vel(a0),d0 cmpi.w #$400,d0 bhs.s .mediumSpeed ;.lowSpeed: ; Increase Knuckles' speed. addq.w #8,d0 bra.s .applySpeed ; --------------------------------------------------------------------------- ; loc_1700E: .mediumSpeed: ; If Knuckles is at his speed limit, then don't increase his speed. cmpi.w #$1800,d0 bhs.s .applySpeed ; If Knuckles is turning, then don't increase his speed either. move.b double_jump_property(a0),d1 andi.b #$7F,d1 bne.s .applySpeed ; Increase Knuckles' speed. addq.w #4,d0 ; Super Knuckles and Hyper Knuckles glide faster. tst.b (Super_Sonic_Knux_flag).w beq.s .applySpeed addq.w #8,d0 ; loc_17028: .applySpeed: move.w d0,ground_vel(a0) move.b double_jump_property(a0),d0 btst #button_left,(Ctrl_1_logical).w beq.s .notHoldingLeft ;.holdingLeft: ; Playing is holding left. cmpi.b #$80,d0 beq.s .notHoldingLeft tst.b d0 bpl.s .doNotNegate1 neg.b d0 .doNotNegate1: addq.b #2,d0 bra.s .setNewTurningValue ; --------------------------------------------------------------------------- ; loc_17048: .notHoldingLeft: btst #button_right,(Ctrl_1_logical).w beq.s .notHoldingRight ;.holdingRight: ; Playing is holding right. tst.b d0 beq.s .notHoldingRight bmi.s .doNotNegate2 neg.b d0 .doNotNegate2: addq.b #2,d0 bra.s .setNewTurningValue ; --------------------------------------------------------------------------- ; loc_1705C: .notHoldingRight: move.b d0,d1 andi.b #$7F,d1 beq.s .setNewTurningValue addq.b #2,d0 ; loc_17066: .setNewTurningValue: move.b d0,double_jump_property(a0) move.b double_jump_property(a0),d0 jsr (GetSineCosine).l muls.w ground_vel(a0),d1 asr.l #8,d1 move.w d1,x_vel(a0) ; Is Knuckles is falling at a high speed, then create a parachute ; effect, where gliding makes Knuckles fall slower. cmpi.w #$80,y_vel(a0) blt.s .fallingSlow subi.w #$20,y_vel(a0) bra.s .fallingFast ; --------------------------------------------------------------------------- ; loc_1708E: .fallingSlow: ; Apply gravity. addi.w #$20,y_vel(a0) ; loc_17094: .fallingFast: ; If Knuckles is above the level's top boundary, then kill his ; horizontal speed. move.w (Camera_min_Y_pos).w,d0 cmpi.w #-$100,d0 beq.w .doNotKillspeed addi.w #$10,d0 cmp.w y_pos(a0),d0 ble.w .doNotKillspeed asr.w x_vel(a0) asr.w ground_vel(a0) ; loc_170B4: .doNotKillspeed: cmpi.w #$60,(a5) beq.s .doNotModifyBias bhs.s .goUp addq.w #2*2,(a5) .goUp: subq.w #2,(a5) ; locret_170C0: .doNotModifyBias: rts ; End of function Knuckles_Move_Glide ; --------------------------------------------------------------------------- Knux_Spin_Path: tst.b spin_dash_flag(a0) bne.s loc_170CC bsr.w Knux_Jump loc_170CC: bsr.w Player_RollRepel bsr.w Knux_RollSpeed bsr.w Player_LevelBound jsr (MoveSprite_TestGravity2).l bsr.w Call_Player_AnglePos bsr.w Player_SlopeRepel tst.b (Background_collision_flag).w beq.s locret_17116 bsr.w sub_F846 tst.w d1 bmi.w Kill_Character movem.l a4-a6,-(sp) bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_17106 sub.w d1,x_pos(a0) loc_17106: bsr.w CheckRightWallDist tst.w d1 bpl.s loc_17112 add.w d1,x_pos(a0) loc_17112: movem.l (sp)+,a4-a6 locret_17116: rts ; --------------------------------------------------------------------------- Knux_Spin_Freespace: bsr.w Knux_JumpHeight bsr.w Knux_ChgJumpDir bsr.w Player_LevelBound jsr (MoveSprite_TestGravity).l btst #Status_Underwater,status(a0) beq.s loc_17138 subi.w #$28,y_vel(a0) loc_17138: bsr.w Player_JumpAngle bsr.w SonicKnux_DoLevelCollision rts ; =============== S U B R O U T I N E ======================================= Knux_InputAcceleration_Path: move.w Max_speed-Max_speed(a4),d6 move.w Acceleration-Max_speed(a4),d5 move.w Deceleration-Max_speed(a4),d4 tst.b status_secondary(a0) bmi.w loc_17364 tst.w move_lock(a0) bne.w loc_1731C btst #button_left,(Ctrl_1_held_logical).w beq.s loc_17168 bsr.w sub_17428 loc_17168: btst #button_right,(Ctrl_1_held_logical).w beq.s loc_17174 bsr.w sub_174B4 loc_17174: move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 bne.w loc_1731C tst.w ground_vel(a0) bne.w loc_1731C bclr #Status_Push,status(a0) move.b #5,anim(a0) btst #Status_OnObj,status(a0) beq.w loc_1722C movea.w interact(a0),a1 tst.b status(a1) bmi.w loc_172A8 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 cmpi.w #2,d1 blt.s loc_171FE cmp.w d2,d1 bge.s loc_171D0 bra.w loc_172A8 ; --------------------------------------------------------------------------- loc_171D0: btst #Status_Facing,status(a0) bne.s loc_171E2 move.b #6,anim(a0) bra.w loc_1731C ; --------------------------------------------------------------------------- loc_171E2: bclr #Status_Facing,status(a0) move.b #0,anim_frame_timer(a0) move.b #4,anim_frame(a0) move.w #(6<<8)|6,anim(a0) ; and prev_anim bra.w loc_1731C ; --------------------------------------------------------------------------- loc_171FE: btst #Status_Facing,status(a0) beq.s loc_17210 move.b #6,anim(a0) bra.w loc_1731C ; --------------------------------------------------------------------------- loc_17210: bset #Status_Facing,status(a0) move.b #0,anim_frame_timer(a0) move.b #4,anim_frame(a0) move.w #(6<<8)|6,anim(a0) ; and prev_anim bra.w loc_1731C ; --------------------------------------------------------------------------- loc_1722C: move.w x_pos(a0),d3 bsr.w ChooseChkFloorEdge cmpi.w #$C,d1 blt.w loc_172A8 cmpi.b #3,next_tilt(a0) bne.s loc_17272 btst #Status_Facing,status(a0) bne.s loc_17256 move.b #6,anim(a0) bra.w loc_1731C ; --------------------------------------------------------------------------- loc_17256: bclr #Status_Facing,status(a0) move.b #0,anim_frame_timer(a0) move.b #4,anim_frame(a0) move.w #(6<<8)|6,anim(a0) ; and prev_anim bra.w loc_1731C ; --------------------------------------------------------------------------- loc_17272: cmpi.b #3,tilt(a0) bne.s loc_172A8 btst #Status_Facing,status(a0) beq.s loc_1728C move.b #6,anim(a0) bra.w loc_1731C ; --------------------------------------------------------------------------- loc_1728C: bset #Status_Facing,status(a0) move.b #0,anim_frame_timer(a0) move.b #4,anim_frame(a0) move.w #(6<<8)|6,anim(a0) ; and prev_anim bra.w loc_1731C ; --------------------------------------------------------------------------- loc_172A8: btst #button_down,(Ctrl_1_held_logical).w beq.s loc_172E2 move.b #8,anim(a0) addq.b #1,scroll_delay_counter(a0) cmpi.b #2*60,scroll_delay_counter(a0) blo.s loc_17322 move.b #2*60,scroll_delay_counter(a0) tst.b (Reverse_gravity_flag).w bne.s loc_172D8 cmpi.w #8,(a5) beq.s loc_1732E subq.w #2,(a5) bra.s loc_1732E ; --------------------------------------------------------------------------- loc_172D8: cmpi.w #$D8,(a5) beq.s loc_1732E addq.w #2,(a5) bra.s loc_1732E ; --------------------------------------------------------------------------- loc_172E2: btst #button_up,(Ctrl_1_logical).w beq.s loc_1731C move.b #7,anim(a0) addq.b #1,scroll_delay_counter(a0) cmpi.b #2*60,scroll_delay_counter(a0) blo.s loc_17322 move.b #2*60,scroll_delay_counter(a0) tst.b (Reverse_gravity_flag).w bne.s loc_17312 cmpi.w #$C8,(a5) beq.s loc_1732E addq.w #2,(a5) bra.s loc_1732E ; --------------------------------------------------------------------------- loc_17312: cmpi.w #$18,(a5) beq.s loc_1732E subq.w #2,(a5) bra.s loc_1732E ; --------------------------------------------------------------------------- loc_1731C: move.b #0,scroll_delay_counter(a0) loc_17322: cmpi.w #$60,(a5) beq.s loc_1732E bcc.s loc_1732C addq.w #4,(a5) loc_1732C: subq.w #2,(a5) loc_1732E: tst.b (Super_Sonic_Knux_flag).w beq.s loc_17338 move.w #$C,d5 loc_17338: move.b (Ctrl_1_logical).w,d0 andi.b #button_left_mask|button_right_mask,d0 bne.s loc_17364 move.w ground_vel(a0),d0 beq.s loc_17364 bmi.s loc_17358 sub.w d5,d0 bcc.s loc_17352 move.w #0,d0 loc_17352: move.w d0,ground_vel(a0) bra.s loc_17364 ; --------------------------------------------------------------------------- loc_17358: add.w d5,d0 bcc.s loc_17360 move.w #0,d0 loc_17360: move.w d0,ground_vel(a0) loc_17364: move.b angle(a0),d0 jsr (GetSineCosine).l muls.w ground_vel(a0),d1 asr.l #8,d1 move.w d1,x_vel(a0) muls.w ground_vel(a0),d0 asr.l #8,d0 move.w d0,y_vel(a0) loc_17382: btst #6,object_control(a0) bne.w locret_17426 move.b angle(a0),d0 andi.b #$3F,d0 beq.s loc_173A2 move.b angle(a0),d0 addi.b #$40,d0 bmi.w locret_17426 loc_173A2: move.b #$40,d1 tst.w ground_vel(a0) beq.s locret_17426 bmi.s loc_173B0 neg.w d1 loc_173B0: move.b angle(a0),d0 add.b d1,d0 move.w d0,-(sp) bsr.w sub_F61C move.w (sp)+,d0 tst.w d1 bpl.s locret_17426 asl.w #8,d1 cmpi.b #8,(Current_zone).w bne.s loc_173D2 tst.b d0 bpl.s loc_173D2 subq.b #1,d0 loc_173D2: addi.b #$20,d0 andi.b #$C0,d0 beq.s loc_17422 cmpi.b #$40,d0 beq.s loc_17408 cmpi.b #$80,d0 beq.s loc_17402 add.w d1,x_vel(a0) move.w #0,ground_vel(a0) btst #Status_Facing,status(a0) bne.s locret_17400 bset #Status_Push,status(a0) locret_17400: rts ; --------------------------------------------------------------------------- loc_17402: sub.w d1,y_vel(a0) rts ; --------------------------------------------------------------------------- loc_17408: sub.w d1,x_vel(a0) move.w #0,ground_vel(a0) btst #Status_Facing,status(a0) beq.s locret_17400 bset #Status_Push,status(a0) rts ; --------------------------------------------------------------------------- loc_17422: add.w d1,y_vel(a0) locret_17426: rts ; End of function Knux_InputAcceleration_Path ; =============== S U B R O U T I N E ======================================= sub_17428: move.w ground_vel(a0),d0 beq.s loc_17430 bpl.s loc_17462 loc_17430: bset #Status_Facing,status(a0) bne.s loc_17444 bclr #Status_Push,status(a0) move.b #1,prev_anim(a0) loc_17444: sub.w d5,d0 move.w d6,d1 neg.w d1 cmp.w d1,d0 bgt.s loc_17456 add.w d5,d0 cmp.w d1,d0 ble.s loc_17456 move.w d1,d0 loc_17456: move.w d0,ground_vel(a0) move.b #0,anim(a0) rts ; --------------------------------------------------------------------------- loc_17462: sub.w d4,d0 bcc.s loc_1746A move.w #-$80,d0 loc_1746A: move.w d0,ground_vel(a0) move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 bne.s locret_174B2 cmpi.w #$400,d0 blt.s locret_174B2 tst.b flip_type(a0) bmi.s locret_174B2 move.w #sfx_Skid,d0 jsr (Play_SFX).l move.b #$D,anim(a0) bclr #0,status(a0) cmpi.b #12,air_left(a0) blo.s locret_174B2 move.b #6,routine(a6) move.b #$15,mapping_frame(a6) locret_174B2: rts ; End of function sub_17428 ; =============== S U B R O U T I N E ======================================= sub_174B4: move.w ground_vel(a0),d0 bmi.s loc_174E8 bclr #Status_Facing,status(a0) beq.s loc_174CE bclr #Status_Push,status(a0) move.b #1,prev_anim(a0) loc_174CE: add.w d5,d0 cmp.w d6,d0 blt.s loc_174DC sub.w d5,d0 cmp.w d6,d0 bge.s loc_174DC move.w d6,d0 loc_174DC: move.w d0,ground_vel(a0) move.b #0,anim(a0) rts ; --------------------------------------------------------------------------- loc_174E8: add.w d4,d0 bcc.s loc_174F0 move.w #$80,d0 loc_174F0: move.w d0,ground_vel(a0) move.b angle(a0),d0 addi.b #$20,d0 andi.b #$C0,d0 bne.s locret_17538 cmpi.w #-$400,d0 bgt.s locret_17538 tst.b flip_type(a0) bmi.s locret_17538 move.w #sfx_Skid,d0 jsr (Play_SFX).l move.b #$D,anim(a0) bset #Status_Facing,status(a0) cmpi.b #12,air_left(a0) blo.s locret_17538 move.b #6,routine(a6) move.b #$15,mapping_frame(a6) locret_17538: rts ; End of function sub_174B4 ; =============== S U B R O U T I N E ======================================= Knux_RollSpeed: move.w Max_speed-Max_speed(a4),d6 asl.w #1,d6 move.w Acceleration-Max_speed(a4),d5 asr.w #1,d5 tst.b (Super_Sonic_Knux_flag).w beq.s loc_1754E move.w #6,d5 loc_1754E: move.w #$20,d4 tst.b spin_dash_flag(a0) bmi.w loc_175F8 tst.b status_secondary(a0) bmi.w loc_175F8 tst.w move_lock(a0) bne.s loc_17580 btst #button_left,(Ctrl_1_held_logical).w beq.s loc_17574 bsr.w sub_1763A loc_17574: btst #button_right,(Ctrl_1_held_logical).w beq.s loc_17580 bsr.w sub_1765E loc_17580: move.w ground_vel(a0),d0 beq.s loc_175A2 bmi.s loc_17596 sub.w d5,d0 bcc.s loc_17590 move.w #0,d0 loc_17590: move.w d0,ground_vel(a0) bra.s loc_175A2 ; --------------------------------------------------------------------------- loc_17596: add.w d5,d0 bcc.s loc_1759E move.w #0,d0 loc_1759E: move.w d0,ground_vel(a0) loc_175A2: move.w ground_vel(a0),d0 bpl.s loc_175AA neg.w d0 loc_175AA: cmpi.w #$80,d0 bhs.s loc_175F8 tst.b spin_dash_flag(a0) bne.s loc_175E6 bclr #Status_Roll,status(a0) move.b y_radius(a0),d0 move.b default_y_radius(a0),y_radius(a0) move.b default_x_radius(a0),x_radius(a0) move.b #5,anim(a0) sub.b default_y_radius(a0),d0 ext.w d0 tst.b (Reverse_gravity_flag).w beq.s loc_175E0 neg.w d0 loc_175E0: add.w d0,y_pos(a0) bra.s loc_175F8 ; --------------------------------------------------------------------------- loc_175E6: move.w #$400,ground_vel(a0) btst #Status_Facing,status(a0) beq.s loc_175F8 neg.w ground_vel(a0) loc_175F8: cmpi.w #$60,(a5) beq.s loc_17604 bcc.s loc_17602 addq.w #4,(a5) loc_17602: subq.w #2,(a5) loc_17604: move.b angle(a0),d0 jsr (GetSineCosine).l muls.w ground_vel(a0),d0 asr.l #8,d0 move.w d0,y_vel(a0) muls.w ground_vel(a0),d1 asr.l #8,d1 cmpi.w #$1000,d1 ble.s loc_17628 move.w #$1000,d1 loc_17628: cmpi.w #-$1000,d1 bge.s loc_17632 move.w #-$1000,d1 loc_17632: move.w d1,x_vel(a0) bra.w loc_17382 ; End of function Knux_RollSpeed ; =============== S U B R O U T I N E ======================================= sub_1763A: move.w ground_vel(a0),d0 beq.s loc_17642 bpl.s loc_17650 loc_17642: bset #Status_Facing,status(a0) move.b #2,anim(a0) rts ; --------------------------------------------------------------------------- loc_17650: sub.w d4,d0 bcc.s loc_17658 move.w #-$80,d0 loc_17658: move.w d0,ground_vel(a0) rts ; End of function sub_1763A ; =============== S U B R O U T I N E ======================================= sub_1765E: move.w ground_vel(a0),d0 bmi.s loc_17672 bclr #Status_Facing,status(a0) move.b #2,anim(a0) rts ; --------------------------------------------------------------------------- loc_17672: add.w d4,d0 bcc.s loc_1767A move.w #$80,d0 loc_1767A: move.w d0,ground_vel(a0) rts ; End of function sub_1765E ; =============== S U B R O U T I N E ======================================= ; sub_17680: Knux_ChgJumpDir: move.w Max_speed-Max_speed(a4),d6 move.w Acceleration-Max_speed(a4),d5 asl.w #1,d5 btst #Status_RollJump,status(a0) bne.s loc_176D4 move.w x_vel(a0),d0 btst #button_left,(Ctrl_1_held_logical).w beq.s loc_176B4 bset #Status_Facing,status(a0) sub.w d5,d0 move.w d6,d1 neg.w d1 cmp.w d1,d0 bgt.s loc_176B4 add.w d5,d0 cmp.w d1,d0 ble.s loc_176B4 move.w d1,d0 loc_176B4: btst #button_right,(Ctrl_1_held_logical).w beq.s loc_176D0 bclr #Status_Facing,status(a0) add.w d5,d0 cmp.w d6,d0 blt.s loc_176D0 sub.w d5,d0 cmp.w d6,d0 bge.s loc_176D0 move.w d6,d0 loc_176D0: move.w d0,x_vel(a0) loc_176D4: cmpi.w #$60,(a5) beq.s loc_176E0 bcc.s loc_176DE addq.w #4,(a5) loc_176DE: subq.w #2,(a5) loc_176E0: cmpi.w #-$400,y_vel(a0) blo.s locret_1770E move.w x_vel(a0),d0 move.w d0,d1 asr.w #5,d1 beq.s locret_1770E bmi.s loc_17702 sub.w d1,d0 bcc.s loc_176FC move.w #0,d0 loc_176FC: move.w d0,x_vel(a0) rts ; --------------------------------------------------------------------------- loc_17702: sub.w d1,d0 bcs.s loc_1770A move.w #0,d0 loc_1770A: move.w d0,x_vel(a0) locret_1770E: rts ; End of function Knux_ChgJumpDir ; =============== S U B R O U T I N E ======================================= Knux_Jump: move.b (Ctrl_1_pressed_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 beq.w locret_177E0 moveq #0,d0 move.b angle(a0),d0 tst.b (Reverse_gravity_flag).w beq.s loc_17732 addi.b #$40,d0 neg.b d0 subi.b #$40,d0 loc_17732: addi.b #$80,d0 movem.l a4-a6,-(sp) jsr (CalcRoomOverHead).l movem.l (sp)+,a4-a6 cmpi.w #6,d1 blt.w locret_177E0 move.w #$600,d2 btst #6,status(a0) beq.s loc_1775C move.w #$300,d2 loc_1775C: moveq #0,d0 move.b angle(a0),d0 subi.b #$40,d0 jsr (GetSineCosine).l muls.w d2,d1 asr.l #8,d1 add.w d1,x_vel(a0) muls.w d2,d0 asr.l #8,d0 add.w d0,y_vel(a0) bset #Status_InAir,status(a0) bclr #Status_Push,status(a0) addq.l #4,sp move.b #1,jumping(a0) clr.b stick_to_convex(a0) move.w #sfx_Jump,d0 jsr (Play_SFX).l move.b default_y_radius(a0),y_radius(a0) move.b default_x_radius(a0),x_radius(a0) btst #Status_Roll,status(a0) bne.s loc_177E2 move.b #$E,y_radius(a0) move.b #7,x_radius(a0) move.b #2,anim(a0) bset #Status_Roll,status(a0) move.b y_radius(a0),d0 sub.b default_y_radius(a0),d0 ext.w d0 tst.b (Reverse_gravity_flag).w beq.s loc_177DC neg.w d0 loc_177DC: sub.w d0,y_pos(a0) locret_177E0: rts ; --------------------------------------------------------------------------- loc_177E2: bset #Status_RollJump,status(a0) rts ; End of function Knux_Jump ; =============== S U B R O U T I N E ======================================= Knux_JumpHeight: tst.b jumping(a0) beq.s loc_17818 move.w #-$400,d1 btst #Status_Underwater,status(a0) beq.s loc_17800 move.w #-$200,d1 loc_17800: cmp.w y_vel(a0),d1 ble.w Knux_Test_For_Glide move.b (Ctrl_1_held_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 bne.s locret_17816 move.w d1,y_vel(a0) locret_17816: rts ; --------------------------------------------------------------------------- loc_17818: tst.b spin_dash_flag(a0) bne.s locret_1782C cmpi.w #-$FC0,y_vel(a0) bge.s locret_1782C move.w #-$FC0,y_vel(a0) locret_1782C: rts ; --------------------------------------------------------------------------- Knux_Test_For_Glide: tst.b double_jump_flag(a0) bne.w locret_178CC move.b (Ctrl_1_pressed_logical).w,d0 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 beq.w locret_178CC tst.b (Super_Sonic_Knux_flag).w bne.s loc_1786C cmpi.b #7,(Super_emerald_count).w bhs.s loc_1785E cmpi.b #7,(Chaos_emerald_count).w blo.s loc_1786C tst.b (Emeralds_converted_flag).w bne.s loc_1786C loc_1785E: cmpi.w #50,(Ring_count).w blo.s loc_1786C tst.b (Update_HUD_timer).w bne.s Knux_Transform loc_1786C: bclr #Status_Roll,status(a0) move.b #$A,y_radius(a0) move.b #$A,x_radius(a0) bclr #Status_RollJump,status(a0) move.b #1,double_jump_flag(a0) addi.w #$200,y_vel(a0) bpl.s loc_17898 move.w #0,y_vel(a0) loc_17898: moveq #0,d1 move.w #$400,d0 move.w d0,ground_vel(a0) btst #Status_Facing,status(a0) beq.s loc_178AE neg.w d0 moveq #-$80,d1 loc_178AE: move.w d0,x_vel(a0) move.b d1,double_jump_property(a0) move.w #0,angle(a0) move.b #0,(Gliding_collision_flags).w bset #Status_InAir,(Gliding_collision_flags).w bsr.w Knuckles_Set_Gliding_Animation locret_178CC: rts ; --------------------------------------------------------------------------- Knux_Transform: move.b #1,(Super_palette_status).w ; set Super/Hyper palette status to 'fading' move.b #$F,(Palette_timer).w move.w #60,(Super_frame_count).w move.b #$81,object_control(a0) move.b #$1F,anim(a0) ; enter 'transformation' animation cmpi.b #7,(Super_emerald_count).w ; does Knuckles have all 7 Super Emeralds? blo.s .super ; if not, turn Super move.b #-1,(Super_Sonic_Knux_flag).w ; set flag to Hyper Knuckles move.l #Obj_HyperSonicKnux_Trail,(Super_stars).w ; load After-Images object bra.s .continued ; --------------------------------------------------------------------------- .super: move.b #1,(Super_Sonic_Knux_flag).w ; set flag to Super Knuckles move.l #Obj_SuperSonicKnux_Stars,(Super_stars).w ; load Super Stars object .continued: move.w #$800,Max_speed-Max_speed(a4) move.w #$18,Acceleration-Max_speed(a4) move.w #$C0,Deceleration-Max_speed(a4) move.b #0,invincibility_timer(a0) bset #Status_Invincible,status_secondary(a0) moveq #signextendB(sfx_SuperTransform),d0 jsr (Play_SFX).l moveq #signextendB(mus_Invincibility),d0 ; play invincibility theme jmp (Play_Music).l ; End of function Knux_JumpHeight ; =============== S U B R O U T I N E ======================================= Knux_DoLevelCollision_CheckRet: move.l (Primary_collision_addr).w,(Collision_addr).w cmpi.b #$C,top_solid_bit(a0) beq.s loc_17952 move.l (Secondary_collision_addr).w,(Collision_addr).w loc_17952: move.b lrb_solid_bit(a0),d5 move.w x_vel(a0),d1 move.w y_vel(a0),d2 jsr (GetArcTan).l subi.b #$20,d0 andi.b #$C0,d0 cmpi.b #$40,d0 beq.w loc_179DA cmpi.b #$80,d0 beq.w loc_17A62 cmpi.b #$C0,d0 beq.w loc_17AB0 bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_1799C sub.w d1,x_pos(a0) move.w #0,x_vel(a0) bset #Status_Push,(Gliding_collision_flags).w loc_1799C: bsr.w CheckRightWallDist tst.w d1 bpl.s loc_179B4 add.w d1,x_pos(a0) move.w #0,x_vel(a0) bset #Status_Push,(Gliding_collision_flags).w loc_179B4: bsr.w sub_11FD6 tst.w d1 bpl.s locret_179D8 tst.b (Reverse_gravity_flag).w beq.s loc_179C4 neg.w d1 loc_179C4: add.w d1,y_pos(a0) move.b d3,angle(a0) move.w #0,y_vel(a0) bclr #Status_InAir,(Gliding_collision_flags).w locret_179D8: rts ; --------------------------------------------------------------------------- loc_179DA: bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_179F2 sub.w d1,x_pos(a0) move.w #0,x_vel(a0) bset #Status_Push,(Gliding_collision_flags).w loc_179F2: bsr.w sub_11FEE tst.w d1 bpl.s loc_17A36 neg.w d1 cmpi.w #$14,d1 bhs.s loc_17A1C tst.b (Reverse_gravity_flag).w beq.s loc_17A0A neg.w d1 loc_17A0A: add.w d1,y_pos(a0) tst.w y_vel(a0) bpl.s locret_17A1A move.w #0,y_vel(a0) locret_17A1A: rts ; --------------------------------------------------------------------------- loc_17A1C: bsr.w CheckRightWallDist tst.w d1 bpl.s locret_17A34 add.w d1,x_pos(a0) move.w #0,x_vel(a0) bset #Status_Push,(Gliding_collision_flags).w locret_17A34: rts ; --------------------------------------------------------------------------- loc_17A36: tst.w y_vel(a0) bmi.s locret_17A60 bsr.w sub_11FD6 tst.w d1 bpl.s locret_17A60 tst.b (Reverse_gravity_flag).w beq.s loc_17A4C neg.w d1 loc_17A4C: add.w d1,y_pos(a0) move.b d3,angle(a0) move.w #0,y_vel(a0) bclr #Status_InAir,(Gliding_collision_flags).w locret_17A60: rts ; --------------------------------------------------------------------------- loc_17A62: bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_17A7A sub.w d1,x_pos(a0) move.w #0,x_vel(a0) bset #Status_Push,(Gliding_collision_flags).w loc_17A7A: jsr (CheckRightWallDist).l tst.w d1 bpl.s loc_17A94 add.w d1,x_pos(a0) move.w #0,x_vel(a0) bset #Status_Push,(Gliding_collision_flags).w loc_17A94: bsr.w sub_11FEE tst.w d1 bpl.s locret_17AAE tst.b (Reverse_gravity_flag).w beq.s loc_17AA4 neg.w d1 loc_17AA4: sub.w d1,y_pos(a0) move.w #0,y_vel(a0) locret_17AAE: rts ; --------------------------------------------------------------------------- loc_17AB0: jsr (CheckRightWallDist).l tst.w d1 bpl.s loc_17ACA add.w d1,x_pos(a0) move.w #0,x_vel(a0) bset #Status_Push,(Gliding_collision_flags).w loc_17ACA: bsr.w sub_11FEE tst.w d1 bpl.s loc_17AEC tst.b (Reverse_gravity_flag).w beq.s loc_17ADA neg.w d1 loc_17ADA: sub.w d1,y_pos(a0) tst.w y_vel(a0) bpl.s locret_17AEA move.w #0,y_vel(a0) locret_17AEA: rts ; --------------------------------------------------------------------------- loc_17AEC: tst.w y_vel(a0) bmi.s locret_17B16 bsr.w sub_11FD6 tst.w d1 bpl.s locret_17B16 tst.b (Reverse_gravity_flag).w beq.s loc_17B02 neg.w d1 loc_17B02: add.w d1,y_pos(a0) move.b d3,angle(a0) move.w #0,y_vel(a0) bclr #Status_InAir,(Gliding_collision_flags).w locret_17B16: rts ; End of function Knux_DoLevelCollision_CheckRet ; --------------------------------------------------------------------------- ; unused/dead code Knux_TouchFloor_Check_Spindash: tst.b spin_dash_flag(a0) bne.s loc_17B6A move.b #0,anim(a0) ; End of function Knux_TouchFloor_Check_Spindash ; =============== S U B R O U T I N E ======================================= Knux_TouchFloor: move.b y_radius(a0),d0 move.b default_y_radius(a0),y_radius(a0) move.b default_x_radius(a0),x_radius(a0) btst #Status_Roll,status(a0) beq.s loc_17B6A bclr #Status_Roll,status(a0) move.b #0,anim(a0) sub.b default_y_radius(a0),d0 ext.w d0 tst.b (Reverse_gravity_flag).w beq.s loc_17B56 neg.w d0 loc_17B56: move.w d0,-(sp) move.b angle(a0),d0 addi.b #$40,d0 bpl.s loc_17B64 neg.w (sp) loc_17B64: move.w (sp)+,d0 add.w d0,y_pos(a0) loc_17B6A: bclr #Status_InAir,status(a0) bclr #Status_Push,status(a0) bclr #Status_RollJump,status(a0) move.b #0,jumping(a0) move.w #0,(Chain_bonus_counter).w move.b #0,flip_angle(a0) move.b #0,flip_type(a0) move.b #0,flips_remaining(a0) move.b #0,scroll_delay_counter(a0) move.b #0,double_jump_flag(a0) cmpi.b #$20,anim(a0) blo.s locret_17BB4 move.b #0,anim(a0) locret_17BB4: rts ; End of function Knux_TouchFloor ; --------------------------------------------------------------------------- loc_17BB6: tst.w (Debug_mode_flag).w beq.s loc_17BD0 btst #button_B,(Ctrl_1_pressed).w beq.s loc_17BD0 move.w #1,(Debug_placement_mode).w clr.b (Ctrl_1_locked).w rts ; --------------------------------------------------------------------------- loc_17BD0: jsr (MoveSprite_TestGravity2).l addi.w #$30,y_vel(a0) btst #Status_Underwater,status(a0) beq.s loc_17BEA subi.w #$20,y_vel(a0) loc_17BEA: cmpi.w #-$100,(Camera_min_Y_pos).w bne.s loc_17BFA move.w (Screen_Y_wrap_value).w,d0 and.w d0,y_pos(a0) loc_17BFA: bsr.w sub_17C10 bsr.w Player_LevelBound bsr.w Sonic_RecordPos bsr.w sub_17D1E jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_17C10: tst.b (Disable_death_plane).w bne.s loc_17C3C tst.b (Reverse_gravity_flag).w bne.s loc_17C2E move.w (Camera_max_Y_pos).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 blt.w loc_17C82 bra.s loc_17C3C ; --------------------------------------------------------------------------- loc_17C2E: move.w (Camera_min_Y_pos).w,d0 cmp.w y_pos(a0),d0 blt.s loc_17C3C bra.w loc_17C82 ; --------------------------------------------------------------------------- loc_17C3C: movem.l a4-a6,-(sp) bsr.w SonicKnux_DoLevelCollision movem.l (sp)+,a4-a6 btst #Status_InAir,status(a0) bne.s locret_17C80 moveq #0,d0 move.w d0,y_vel(a0) move.w d0,x_vel(a0) move.w d0,ground_vel(a0) move.b d0,object_control(a0) move.b #0,anim(a0) move.w #$100,priority(a0) move.b #2,routine(a0) move.b #2*60,invulnerability_timer(a0) move.b #0,spin_dash_flag(a0) locret_17C80: rts ; --------------------------------------------------------------------------- loc_17C82: jmp (Kill_Character).l ; End of function sub_17C10 ; --------------------------------------------------------------------------- loc_17C88: tst.w (Debug_mode_flag).w beq.s loc_17CA2 btst #button_B,(Ctrl_1_pressed).w beq.s loc_17CA2 move.w #1,(Debug_placement_mode).w clr.b (Ctrl_1_locked).w rts ; --------------------------------------------------------------------------- loc_17CA2: bsr.w sub_123C2 jsr (MoveSprite_TestGravity).l bsr.w Sonic_RecordPos bsr.w sub_17D1E jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_17CBA: tst.w $3E(a0) beq.s locret_17CCC subq.w #1,$3E(a0) bne.s locret_17CCC move.w #1,(Restart_level_flag).w locret_17CCC: rts ; --------------------------------------------------------------------------- loc_17CCE: tst.w (Camera_RAM).w bne.s loc_17CE0 tst.w (V_scroll_amount).w bne.s loc_17CE0 move.b #2,routine(a0) loc_17CE0: bsr.w sub_17D1E jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_17CEA: tst.w (Debug_mode_flag).w beq.s loc_17D04 btst #button_B,(Ctrl_1_pressed).w beq.s loc_17D04 move.w #1,(Debug_placement_mode).w clr.b (Ctrl_1_locked).w rts ; --------------------------------------------------------------------------- loc_17D04: jsr (MoveSprite_TestGravity2).l addi.w #$10,y_vel(a0) bsr.w Sonic_RecordPos bsr.w sub_17D1E jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_17D1E: bsr.s Animate_Knuckles tst.b (Reverse_gravity_flag).w beq.s loc_17D2C eori.b #2,render_flags(a0) loc_17D2C: bra.w Knuckles_Load_PLC ; End of function sub_17D1E ; =============== S U B R O U T I N E ======================================= Animate_Knuckles: lea (AniKnuckles).l,a1 moveq #0,d0 move.b anim(a0),d0 cmp.b prev_anim(a0),d0 beq.s loc_17D58 move.b d0,prev_anim(a0) move.b #0,anim_frame(a0) move.b #0,anim_frame_timer(a0) bclr #Status_Push,status(a0) loc_17D58: add.w d0,d0 adda.w (a1,d0.w),a1 move.b (a1),d0 bmi.s loc_17DC8 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_timer(a0) bpl.s locret_17D96 move.b d0,anim_frame_timer(a0) loc_17D7E: moveq #0,d1 move.b anim_frame(a0),d1 move.b 1(a1,d1.w),d0 cmpi.b #$FC,d0 bhs.s loc_17D98 loc_17D8E: move.b d0,mapping_frame(a0) addq.b #1,anim_frame(a0) locret_17D96: rts ; --------------------------------------------------------------------------- loc_17D98: addq.b #1,d0 bne.s loc_17DA8 move.b #0,anim_frame(a0) move.b 1(a1),d0 bra.s loc_17D8E ; --------------------------------------------------------------------------- loc_17DA8: addq.b #1,d0 bne.s loc_17DBC move.b 2(a1,d1.w),d0 sub.b d0,anim_frame(a0) sub.b d0,d1 move.b 1(a1,d1.w),d0 bra.s loc_17D8E ; --------------------------------------------------------------------------- loc_17DBC: addq.b #1,d0 bne.s locret_17DC6 move.b 2(a1,d1.w),anim(a0) locret_17DC6: rts ; --------------------------------------------------------------------------- loc_17DC8: addq.b #1,d0 bne.w loc_17E84 moveq #0,d0 tst.b flip_type(a0) bmi.w Anim_Tumble move.b flip_angle(a0),d0 bne.w Anim_Tumble moveq #0,d1 move.b angle(a0),d0 bmi.s loc_17DEC beq.s loc_17DEC subq.b #1,d0 loc_17DEC: move.b status(a0),d2 andi.b #1,d2 bne.s loc_17DF8 not.b d0 loc_17DF8: addi.b #$10,d0 bpl.s loc_17E00 moveq #3,d1 loc_17E00: andi.b #$FC,render_flags(a0) eor.b d1,d2 or.b d2,render_flags(a0) btst #Status_Push,status(a0) bne.w loc_17ECC lsr.b #4,d0 andi.b #6,d0 move.w ground_vel(a0),d2 bpl.s loc_17E24 neg.w d2 loc_17E24: tst.b status_secondary(a0) bpl.w loc_17E2E add.w d2,d2 loc_17E2E: lea (AniKnuckles01).l,a1 cmpi.w #$600,d2 bhs.s loc_17E42 lea (AniKnuckles00).l,a1 add.b d0,d0 loc_17E42: 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 loc_17E60 move.b #0,anim_frame(a0) move.b 1(a1),d0 loc_17E60: move.b d0,mapping_frame(a0) add.b d3,mapping_frame(a0) subq.b #1,anim_frame_timer(a0) bpl.s locret_17E82 neg.w d2 addi.w #$800,d2 bpl.s loc_17E78 moveq #0,d2 loc_17E78: lsr.w #8,d2 move.b d2,anim_frame_timer(a0) addq.b #1,anim_frame(a0) locret_17E82: rts ; --------------------------------------------------------------------------- loc_17E84: 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_timer(a0) bpl.w locret_17D96 move.w ground_vel(a0),d2 bpl.s loc_17EA6 neg.w d2 loc_17EA6: lea (AniKnuckles03).l,a1 cmpi.w #$600,d2 bhs.s loc_17EB8 lea (AniKnuckles02).l,a1 loc_17EB8: neg.w d2 addi.w #$400,d2 bpl.s loc_17EC2 moveq #0,d2 loc_17EC2: lsr.w #8,d2 move.b d2,anim_frame_timer(a0) bra.w loc_17D7E ; --------------------------------------------------------------------------- loc_17ECC: subq.b #1,anim_frame_timer(a0) bpl.w locret_17D96 move.w ground_vel(a0),d2 bmi.s loc_17EDC neg.w d2 loc_17EDC: addi.w #$800,d2 bpl.s loc_17EE4 moveq #0,d2 loc_17EE4: lsr.w #8,d2 move.b d2,anim_frame_timer(a0) lea (AniKnuckles04).l,a1 bra.w loc_17D7E ; End of function Animate_Knuckles ; --------------------------------------------------------------------------- AniKnuckles: include "General/Sprites/Knuckles/Anim - Knuckles.asm" ; =============== S U B R O U T I N E ======================================= Knuckles_Load_PLC: moveq #0,d0 move.b mapping_frame(a0),d0 Knuckles_Load_PLC2: cmp.b (Player_prev_frame).w,d0 beq.s locret_18162 move.b d0,(Player_prev_frame).w move.w #tiles_to_bytes(ArtTile_Player_1),d4 loc_18122: lea (PLC_Knuckles).l,a2 add.w d0,d0 adda.w (a2,d0.w),a2 move.w (a2)+,d5 subq.w #1,d5 bmi.s locret_18162 move.l #ArtUnc_Knux,d6 loc_1813A: 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 add.l d6,d1 move.w d4,d2 add.w d3,d4 add.w d3,d4 jsr (Add_To_DMA_Queue).l dbf d5,loc_1813A locret_18162: rts ; End of function Knuckles_Load_PLC ; --------------------------------------------------------------------------- ; Small bubbles from Sonic's face while underwater ; --------------------------------------------------------------------------- Obj_AirCountdown: moveq #0,d0 move.b routine(a0),d0 move.w AirCountdown_Index(pc,d0.w),d1 jmp AirCountdown_Index(pc,d1.w) ; --------------------------------------------------------------------------- AirCountdown_Index: dc.w AirCountdown_Init-AirCountdown_Index dc.w AirCountdown_Animate-AirCountdown_Index dc.w AirCountdown_ChkWater-AirCountdown_Index dc.w AirCountdown_Display-AirCountdown_Index dc.w AirCountdown_Delete-AirCountdown_Index dc.w AirCountdown_Countdown-AirCountdown_Index dc.w AirCountdown_AirLeft-AirCountdown_Index dc.w AirCountdown_DisplayNumber-AirCountdown_Index dc.w AirCountdown_Delete-AirCountdown_Index ; --------------------------------------------------------------------------- AirCountdown_Init: addq.b #2,routine(a0) move.l #Map_Bubbler,mappings(a0) tst.b parent+1(a0) beq.s loc_1819E move.l #Map_Bubbler2,mappings(a0) loc_1819E: move.w #make_art_tile($45C,0,0),art_tile(a0) move.b #$84,render_flags(a0) move.b #$10,width_pixels(a0) move.w #$80,priority(a0) move.b subtype(a0),d0 bpl.s loc_181CC addq.b #8,routine(a0) andi.w #$7F,d0 move.b d0,$37(a0) bra.w AirCountdown_Countdown ; --------------------------------------------------------------------------- loc_181CC: move.b d0,anim(a0) move.w x_pos(a0),$34(a0) move.w #-$100,y_vel(a0) AirCountdown_Animate: lea (Ani_AirCountdown).l,a1 jsr (Animate_Sprite).l AirCountdown_ChkWater: move.w (Water_level).w,d0 cmp.w y_pos(a0),d0 ; has bubble reached the water surface? blo.s AirCountdown_Wobble ; if not, branch ; pop the bubble: move.b #6,routine(a0) addq.b #7,anim(a0) cmpi.b #$D,anim(a0) beq.s AirCountdown_Display bcs.s AirCountdown_Display move.b #$D,anim(a0) bra.s AirCountdown_Display ; --------------------------------------------------------------------------- AirCountdown_Wobble: tst.w (WindTunnel_flag).w beq.s loc_18218 addq.w #4,$34(a0) loc_18218: move.b angle(a0),d0 addq.b #1,angle(a0) andi.w #$7F,d0 lea (AirCountdown_WobbleData).l,a1 move.b (a1,d0.w),d0 ext.w d0 add.w $34(a0),d0 move.w d0,x_pos(a0) bsr.w AirCountdown_ShowNumber jsr (MoveSprite2).l tst.b render_flags(a0) bpl.s loc_1824E jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_1824E: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- ; AirCountdown_Display and AirCountdown_DisplayNumber were split in this ; game, unlike Sonic 2, to fix a bug where the countdown numbers corrupted ; if they reached the surface of the water. ; (The start of ARZ Act 1 is a good place to see this). AirCountdown_Display: bsr.s AirCountdown_ShowNumber lea (Ani_AirCountdown).l,a1 jsr (Animate_Sprite).l bsr.w AirCountdown_Load_Art jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- AirCountdown_Delete: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- AirCountdown_AirLeft: movea.l $40(a0),a2 ; a2=character cmpi.b #12,air_left(a2) ; check air remaining bhi.s loc_182AC ; if higher than 12, branch subq.w #1,$3C(a0) bne.s AirCountdown_Display2 move.b #$E,routine(a0) addq.b #7,anim(a0) bra.s AirCountdown_Display ; --------------------------------------------------------------------------- AirCountdown_Display2: lea (Ani_AirCountdown).l,a1 jsr (Animate_Sprite).l bsr.w AirCountdown_Load_Art tst.b render_flags(a0) bpl.s loc_182AC jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_182AC: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- AirCountdown_DisplayNumber: movea.l $40(a0),a2 ; a2=character cmpi.b #12,air_left(a2) bhi.s AirCountdown_Delete bsr.s AirCountdown_ShowNumber lea (Ani_AirCountdown).l,a1 jsr (Animate_Sprite).l jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= AirCountdown_ShowNumber: tst.w $3C(a0) beq.s locret_1831C subq.w #1,$3C(a0) bne.s locret_1831C cmpi.b #7,anim(a0) bhs.s locret_1831C move.w #$F,$3C(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_pos(a0) move.w y_pos(a0),d0 sub.w (Camera_Y_pos).w,d0 addi.w #$80,d0 move.w d0,y_pos(a0) move.b #$C,routine(a0) locret_1831C: rts ; End of function AirCountdown_ShowNumber ; --------------------------------------------------------------------------- AirCountdown_WobbleData: dc.b 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 dc.b 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 dc.b 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2 dc.b 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 dc.b 0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2,-3,-3,-3,-3,-3 dc.b -3,-3,-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,-3 dc.b -3,-3,-3,-3,-3,-3,-2,-2,-2,-2,-2,-1,-1,-1,-1,-1 ; Amazing, this S1 leftover is *still* here. ; 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 dc.b 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 dc.b 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2 dc.b 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 dc.b 0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2,-3,-3,-3,-3,-3 dc.b -3,-3,-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,-3 dc.b -3,-3,-3,-3,-3,-3,-2,-2,-2,-2,-2,-1,-1,-1,-1,-1 ; =============== S U B R O U T I N E ======================================= AirCountdown_Load_Art: moveq #0,d1 move.b mapping_frame(a0),d1 cmpi.b #9,d1 blo.s locret_18464 cmpi.b #$13,d1 bhs.s locret_18464 cmp.b $32(a0),d1 beq.s locret_18464 move.b d1,$32(a0) subi.w #9,d1 move.w d1,d0 add.w d1,d1 add.w d0,d1 lsl.w #6,d1 addi.l #ArtUnc_AirCountdown,d1 move.w #tiles_to_bytes(ArtTile_DashDust),d2 tst.b parent+1(a0) beq.s loc_1845A move.w #tiles_to_bytes(ArtTile_DashDust_P2),d2 loc_1845A: move.w #$60,d3 jsr (Add_To_DMA_Queue).l locret_18464: rts ; End of function AirCountdown_Load_Art ; --------------------------------------------------------------------------- AirCountdown_Countdown: movea.l $40(a0),a2 ; a2=character tst.w $30(a0) bne.w loc_1857C cmpi.b #6,routine(a2) bhs.w locret_18680 btst #Status_BublShield,status_secondary(a2) bne.w locret_18680 tst.b (Super_Sonic_Knux_flag).w bmi.w locret_18680 btst #Status_Underwater,status(a2) beq.w locret_18680 subq.w #1,$3C(a0) bpl.w loc_18594 move.w #60-1,$3C(a0) move.w #1,$3A(a0) jsr (Random_Number).l andi.w #1,d0 move.b d0,$38(a0) moveq #0,d0 move.b air_left(a2),d0 ; check air remaining cmpi.w #25,d0 beq.s AirCountdown_WarnSound ; play ding sound if air is 25 cmpi.w #20,d0 beq.s AirCountdown_WarnSound ; play ding sound if air is 20 cmpi.w #15,d0 beq.s AirCountdown_WarnSound ; play ding sound if air is 15 cmpi.w #12,d0 bhi.s AirCountdown_ReduceAir bne.s loc_184E8 tst.b parent+1(a0) bne.s loc_184E8 moveq #signextendB(mus_Drowning),d0 jsr (Play_Music).l loc_184E8: subq.b #1,$36(a0) bpl.s AirCountdown_ReduceAir move.b $37(a0),$36(a0) bset #7,$3A(a0) bra.s AirCountdown_ReduceAir ; --------------------------------------------------------------------------- AirCountdown_WarnSound: tst.b parent+1(a0) bne.s AirCountdown_ReduceAir moveq #signextendB(sfx_AirDing),d0 jsr (Play_SFX).l AirCountdown_ReduceAir: subq.b #1,air_left(a2) bcc.w loc_18592 move.b #$81,object_control(a2) move.w #sfx_Drown,d0 jsr (Play_SFX).l move.b #$A,$38(a0) move.w #1,$3A(a0) move.w #$78,$30(a0) movea.l a2,a1 bsr.w Player_ResetAirTimer move.l a0,-(sp) movea.l a2,a0 bsr.w Player_TouchFloor move.b #$17,anim(a0) bset #Status_InAir,status(a0) bset #7,art_tile(a0) move.w #0,y_vel(a0) move.w #0,x_vel(a0) move.w #0,ground_vel(a0) move.b #$C,routine(a0) movea.l (sp)+,a0 cmpa.w #Player_1,a2 bne.s locret_1857A move.b #1,(Deform_lock).w locret_1857A: rts ; --------------------------------------------------------------------------- loc_1857C: move.b #$17,anim(a2) subq.w #1,$30(a0) bne.s loc_18590 move.b #6,routine(a2) rts ; --------------------------------------------------------------------------- loc_18590: bra.s loc_18594 ; --------------------------------------------------------------------------- loc_18592: bra.s AirCountdown_MakeItem ; --------------------------------------------------------------------------- loc_18594: tst.w $3A(a0) beq.w locret_18680 subq.w #1,$3E(a0) bpl.w locret_18680 AirCountdown_MakeItem: jsr (Random_Number).l andi.w #$F,d0 addq.w #8,d0 move.w d0,$3E(a0) jsr (AllocateObject).l bne.w locret_18680 move.l (a0),(a1) ; load Obj_Air_Countdown move.w x_pos(a2),x_pos(a1) ; match its X position to Sonic moveq #6,d0 btst #Status_Facing,status(a2) beq.s loc_185D8 neg.w d0 move.b #$40,angle(a1) loc_185D8: add.w d0,x_pos(a1) move.w y_pos(a2),y_pos(a1) move.l $40(a0),$40(a1) move.b #6,subtype(a1) tst.w $30(a0) beq.w loc_1862A andi.w #7,$3E(a0) addi.w #0,$3E(a0) move.w y_pos(a2),d0 subi.w #$C,d0 move.w d0,y_pos(a1) jsr (Random_Number).l move.b d0,angle(a1) move.w (Level_frame_counter).w,d0 andi.b #3,d0 bne.s loc_18676 move.b #$E,subtype(a1) bra.s loc_18676 ; --------------------------------------------------------------------------- ; has something to do with making bubbles come out less regularly ; when Sonic is almost drowning loc_1862A: btst #7,$3A(a0) beq.s loc_18676 moveq #0,d2 move.b air_left(a2),d2 cmpi.b #12,d2 bhs.s loc_18676 lsr.w #1,d2 jsr (Random_Number).l andi.w #3,d0 bne.s loc_1865E bset #6,$3A(a0) bne.s loc_18676 move.b d2,subtype(a1) move.w #$1C,$3C(a1) loc_1865E: tst.b $38(a0) bne.s loc_18676 bset #6,$3A(a0) bne.s loc_18676 move.b d2,subtype(a1) move.w #$1C,$3C(a1) loc_18676: subq.b #1,$38(a0) bpl.s locret_18680 clr.w $3A(a0) locret_18680: rts ; =============== S U B R O U T I N E ======================================= Player_ResetAirTimer: cmpi.b #12,air_left(a1) bhi.s loc_186BC ; branch if countdown hasn't started yet cmpa.w #Player_1,a1 bne.s loc_186BC ; branch if it isn't player 1 move.w (Current_music).w,d0 ; prepare to play current level's music btst #Status_Invincible,status_secondary(a1) beq.s loc_186A0 ; branch if Sonic is not invincible move.w #mus_Invincibility,d0 ; prepare to play invincibility music loc_186A0: tst.b (Super_Sonic_Knux_flag).w beq.w loc_186AC ; branch if it isn't Super/Hyper move.w #mus_Invincibility,d0 ; prepare to play Super Sonic music (same as invincibility in this game) loc_186AC: tst.b (Boss_flag).w beq.s loc_186B6 ; branch if not in a boss fight move.w #mus_MinibossK,d0 ; prepare to play boss music loc_186B6: jsr (Play_Music).l loc_186BC: move.b #30,air_left(a1) ; reset air to full rts ; End of function Player_ResetAirTimer ; --------------------------------------------------------------------------- Ani_AirCountdown: include "General/Sprites/Dash Dust/Anim - Air Countdown.asm" ; --------------------------------------------------------------------------- Obj_S2Shield: moveq #0,d0 move.b routine(a0),d0 move.w Obj_S2Shield_Index(pc,d0.w),d1 jmp Obj_S2Shield_Index(pc,d1.w) ; --------------------------------------------------------------------------- Obj_S2Shield_Index: dc.w Obj_S2Shield_Init-Obj_S2Shield_Index dc.w Obj_S2Shield_Main-Obj_S2Shield_Index ; --------------------------------------------------------------------------- Obj_S2Shield_Init: addq.b #2,routine(a0) move.l #Map_S2Shield,mappings(a0) move.b #4,render_flags(a0) move.w #$80,priority(a0) move.b #$18,width_pixels(a0) move.w #make_art_tile(ArtTile_Shield,0,0),art_tile(a0) Obj_S2Shield_Main: movea.w parent(a0),a2 btst #Status_Invincible,status_secondary(a2) bne.s locret_187D6 btst #Status_Shield,status_secondary(a2) beq.s Obj_S2Shield_Destroy 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 Obj_S2Shield_Display ori.w #high_priority,art_tile(a0) Obj_S2Shield_Display: lea (Ani_S2Shield).l,a1 jsr (Animate_Sprite).l jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_187D6: rts ; --------------------------------------------------------------------------- Obj_S2Shield_Destroy: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- off_187DE: dc.l byte_189ED dc.b 0, $B dc.l byte_18A02 dc.b $16, $D dc.l byte_18A1B dc.b $2C, $D ; --------------------------------------------------------------------------- Obj_Invincibility: move.l #ArtUnc_Invincibility,d1 move.w #tiles_to_bytes(ArtTile_Shield),d2 move.w #$200,d3 jsr (Add_To_DMA_Queue).l moveq #0,d2 lea off_187DE-6(pc),a2 lea (a0),a1 moveq #4-1,d1 loc_1880E: move.l #Obj_188E8,(a1) move.l #Map_Invincibility,mappings(a1) move.w #make_art_tile(ArtTile_Shield,0,0),art_tile(a1) move.w #$80,priority(a1) move.b #4,render_flags(a1) bset #6,render_flags(a1) move.b #$10,width_pixels(a1) move.w #2,mainspr_childsprites(a1) move.w parent(a0),parent(a1) move.b d2,$36(a1) addq.w #1,d2 move.l (a2)+,$30(a1) move.w (a2)+,$34(a1) lea next_object(a1),a1 dbf d1,loc_1880E move.l #loc_18868,(a0) move.b #4,$34(a0) loc_18868: tst.b (Super_Sonic_Knux_flag).w bne.w Delete_Current_Sprite tst.b (Super_Tails_flag).w bne.w Delete_Current_Sprite movea.w parent(a0),a1 btst #Status_Invincible,status_secondary(a1) beq.w Delete_Current_Sprite 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_189E0(pc),a3 moveq #0,d5 loc_188A0: move.w $38(a0),d2 move.b (a3,d2.w),d5 bpl.s loc_188B0 clr.w $38(a0) bra.s loc_188A0 ; --------------------------------------------------------------------------- loc_188B0: addq.w #1,$38(a0) lea byte_189A0(pc),a6 move.b $34(a0),d6 jsr sub_1898A(pc) move.w d2,(a2)+ move.w d3,(a2)+ move.w d5,(a2)+ addi.w #$20,d6 jsr sub_1898A(pc) move.w d2,(a2)+ move.w d3,(a2)+ move.w d5,(a2)+ moveq #$12,d0 btst #Status_Facing,status(a1) beq.s loc_188E0 neg.w d0 loc_188E0: add.b d0,$34(a0) bra.w Draw_Sprite ; --------------------------------------------------------------------------- Obj_188E8: tst.b (Super_Sonic_Knux_flag).w bne.w Delete_Current_Sprite tst.b (Super_Tails_flag).w bne.w Delete_Current_Sprite movea.w parent(a0),a1 btst #Status_Invincible,status_secondary(a1) beq.w Delete_Current_Sprite lea (Pos_table_index).w,a5 lea (Pos_table).w,a6 move.b $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 $30(a0),a3 loc_18936: move.w $38(a0),d2 move.b (a3,d2.w),d5 bpl.s loc_18946 clr.w $38(a0) bra.s loc_18936 ; --------------------------------------------------------------------------- loc_18946: swap d5 add.b $35(a0),d2 move.b (a3,d2.w),d5 addq.w #1,$38(a0) lea byte_189A0(pc),a6 move.b $34(a0),d6 jsr sub_1898A(pc) move.w d2,(a2)+ move.w d3,(a2)+ move.w d5,(a2)+ addi.w #$20,d6 swap d5 jsr sub_1898A(pc) move.w d2,(a2)+ move.w d3,(a2)+ move.w d5,(a2)+ moveq #2,d0 btst #Status_Facing,status(a1) beq.s loc_18982 neg.w d0 loc_18982: add.b d0,$34(a0) bra.w Draw_Sprite ; =============== S U B R O U T I N E ======================================= sub_1898A: 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 ; End of function sub_1898A ; --------------------------------------------------------------------------- byte_189A0: dc.b $F, 0 dc.b $F, 3 dc.b $E, 6 dc.b $D, 8 dc.b $B, $B dc.b 8, $D dc.b 6, $E dc.b 3, $F dc.b 0, $10 dc.b -4, $F dc.b -7, $E dc.b -9, $D dc.b -$C, $B dc.b -$E, 8 dc.b -$F, 6 dc.b -$10, 3 dc.b -$10, 0 dc.b -$10, -4 dc.b -$F, -7 dc.b -$E, -9 dc.b -$C, -$C dc.b -9, -$E dc.b -7, -$F dc.b -4,-$10 dc.b -1,-$10 dc.b 3,-$10 dc.b 6, -$F dc.b 8, -$E dc.b $B, -$C dc.b $D, -9 dc.b $E, -7 dc.b $F, -4 byte_189E0: dc.b 8, 5, 7, 6, 6, 7, 5, 8, 6, 7, 7, 6, $FF byte_189ED: dc.b 8, 7, 6, 5, 4, 3, 4, 5, 6, 7, $FF, 3, 4, 5, 6, 7, 8, 7, 6, 5 dc.b 4 byte_18A02: dc.b 8, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7, $FF, 2, 3, 4, 5, 6, 7, 8 dc.b 7, 6, 5, 4, 3 byte_18A1B: dc.b 7, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5, 6, $FF, 1, 2, 3, 4, 5, 6, 7 dc.b 6, 5, 4, 3, 2 even Ani_S2Shield: include "General/Sprites/Shields/Anim - S2 Shield.asm" Map_S2Shield: include "General/Sprites/Shields/Map - S2 Shield.asm" Map_Invincibility: include "General/Sprites/Shields/Map - Invincibility.asm" ; --------------------------------------------------------------------------- Obj_DashDust: moveq #0,d0 move.b routine(a0),d0 move.w DashDust_Index(pc,d0.w),d1 jmp DashDust_Index(pc,d1.w) ; --------------------------------------------------------------------------- DashDust_Index: dc.w loc_18B54-DashDust_Index dc.w loc_18BAA-DashDust_Index dc.w loc_18CB2-DashDust_Index dc.w loc_18CB6-DashDust_Index ; --------------------------------------------------------------------------- loc_18B54: addq.b #2,routine(a0) move.l #Map_DashDust,mappings(a0) ori.b #4,render_flags(a0) move.w #$80,priority(a0) move.b #$10,width_pixels(a0) move.w #make_art_tile(ArtTile_DashDust,0,0),art_tile(a0) move.w #Player_1,parent(a0) move.w #tiles_to_bytes(ArtTile_DashDust),vram_art(a0) cmpa.w #Dust,a0 beq.s loc_18BAA move.b #1,$38(a0) cmpi.w #2,(Player_mode).w beq.s loc_18BAA move.w #make_art_tile(ArtTile_DashDust_P2,0,0),art_tile(a0) move.w #Player_2,parent(a0) move.w #tiles_to_bytes(ArtTile_DashDust_P2),vram_art(a0) loc_18BAA: movea.w parent(a0),a2 moveq #0,d0 move.b anim(a0),d0 add.w d0,d0 move.w off_18BBE(pc,d0.w),d1 jmp off_18BBE(pc,d1.w) ; --------------------------------------------------------------------------- off_18BBE: dc.w loc_18C94-off_18BBE dc.w loc_18BC8-off_18BBE dc.w loc_18C20-off_18BBE dc.w loc_18C84-off_18BBE dc.w loc_18BEC-off_18BBE ; --------------------------------------------------------------------------- loc_18BC8: move.w (Water_level).w,y_pos(a0) tst.b prev_anim(a0) bne.w loc_18C94 move.w x_pos(a2),x_pos(a0) move.b #0,status(a0) andi.w #drawing_mask,art_tile(a0) bra.w loc_18C94 ; --------------------------------------------------------------------------- loc_18BEC: tst.b prev_anim(a0) bne.s loc_18C04 move.w x_pos(a2),x_pos(a0) move.b #0,status(a0) andi.w #drawing_mask,art_tile(a0) loc_18C04: lea (Ani_DashSplashDrown).l,a1 jsr (Animate_Sprite).l move.l #ArtUnc_SplashDrown,d6 bsr.w SplashDrown_Load_DPLC jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_18C20: cmpi.b #12,air_left(a2) blo.w loc_18CAA cmpi.b #4,routine(a2) bhs.s loc_18CAA tst.b spin_dash_flag(a2) beq.s loc_18CAA 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) moveq #4,d1 tst.b (Reverse_gravity_flag).w beq.s loc_18C60 ori.b #2,status(a0) neg.w d1 loc_18C60: tst.b $38(a0) beq.s loc_18C6A sub.w d1,y_pos(a0) loc_18C6A: tst.b prev_anim(a0) bne.s loc_18C94 andi.w #drawing_mask,art_tile(a0) tst.w art_tile(a2) bpl.s loc_18C94 ori.w #high_priority,art_tile(a0) bra.s loc_18C94 ; --------------------------------------------------------------------------- loc_18C84: cmpi.b #12,air_left(a2) blo.s loc_18CAA btst #6,status(a0) bne.s loc_18CAA loc_18C94: lea (Ani_DashSplashDrown).l,a1 jsr (Animate_Sprite).l bsr.w DashDust_Load_DPLC jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_18CAA: move.b #0,anim(a0) rts ; --------------------------------------------------------------------------- loc_18CB2: bra.w Delete_Current_Sprite ; --------------------------------------------------------------------------- loc_18CB6: movea.w parent(a0),a2 moveq #$10,d1 cmpi.b #$D,anim(a2) beq.s loc_18CE4 cmpi.b #2,character_id(a2) bne.s loc_18CD6 moveq #6,d1 cmpi.b #3,double_jump_flag(a2) beq.s loc_18CE4 loc_18CD6: move.b #2,routine(a0) move.b #0,$36(a0) rts ; --------------------------------------------------------------------------- loc_18CE4: subq.b #1,$36(a0) bpl.s loc_18D66 move.b #3,$36(a0) btst #Status_Underwater,status(a2) bne.s loc_18D66 bsr.w AllocateObject bne.s loc_18D66 move.l (a0),(a1) move.w x_pos(a2),x_pos(a1) move.w y_pos(a2),y_pos(a1) tst.b $38(a0) beq.s loc_18D14 subq.w #4,d1 loc_18D14: tst.b (Reverse_gravity_flag).w beq.s loc_18D1C neg.w d1 loc_18D1C: add.w d1,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.w #$80,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_18D66 ori.w #high_priority,art_tile(a1) loc_18D66: bsr.s DashDust_Load_DPLC rts ; =============== S U B R O U T I N E ======================================= DashDust_Load_DPLC: move.l #ArtUnc_DashDust,d6 SplashDrown_Load_DPLC: moveq #0,d0 move.b mapping_frame(a0),d0 cmp.b $34(a0),d0 beq.s locret_18DBE move.b d0,$34(a0) lea (DPLC_DashSplashDrown).l,a2 add.w d0,d0 adda.w (a2,d0.w),a2 move.w (a2)+,d5 subq.w #1,d5 bmi.s locret_18DBE move.w vram_art(a0),d4 loc_18D96: 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 add.l d6,d1 move.w d4,d2 add.w d3,d4 add.w d3,d4 jsr (Add_To_DMA_Queue).l dbf d5,loc_18D96 locret_18DBE: rts ; End of function DashDust_Load_DPLC ; --------------------------------------------------------------------------- Ani_DashSplashDrown: include "General/Sprites/Dash Dust/Anim - Dash Dust.asm" Map_DashDust: include "General/Sprites/Dash Dust/Map - Dash Dust.asm" DPLC_DashSplashDrown: include "General/Sprites/Dash Dust/DPLC - Dash Dust.asm" ; --------------------------------------------------------------------------- Obj_DashDust2P: moveq #0,d0 move.b routine(a0),d0 move.w DashDust2P_Index(pc,d0.w),d1 jmp DashDust2P_Index(pc,d1.w) ; --------------------------------------------------------------------------- DashDust2P_Index: dc.w loc_18F9C-DashDust2P_Index dc.w loc_18FD2-DashDust2P_Index dc.w loc_19060-DashDust2P_Index dc.w loc_19064-DashDust2P_Index ; --------------------------------------------------------------------------- loc_18F9C: addq.b #2,routine(a0) move.l #Map_DashDust2P,mappings(a0) ori.b #4,render_flags(a0) move.w #$80,priority(a0) move.b #$10,width_pixels(a0) move.w #make_art_tile(ArtTile_DashDust,0,0),art_tile(a0) move.w #Player_1,parent(a0) cmpa.w #Dust,a0 beq.s loc_18FD2 move.w #Player_2,parent(a0) loc_18FD2: movea.w parent(a0),a2 moveq #0,d0 move.b anim(a0),d0 add.w d0,d0 move.w off_18FE6(pc,d0.w),d1 jmp off_18FE6(pc,d1.w) ; --------------------------------------------------------------------------- off_18FE6: dc.w loc_18FEE-off_18FE6 dc.w loc_18FEE-off_18FE6 dc.w loc_18FF6-off_18FE6 dc.w loc_1903E-off_18FE6 ; --------------------------------------------------------------------------- loc_18FEE: move.b #0,mapping_frame(a0) bra.s loc_19046 ; --------------------------------------------------------------------------- loc_18FF6: cmpi.b #12,air_left(a2) blo.s loc_19058 cmpi.b #4,routine(a2) bhs.s loc_19058 tst.b spin_dash_flag(a2) beq.s loc_19058 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 prev_anim(a0) bne.s loc_19046 andi.w #drawing_mask,art_tile(a0) tst.w art_tile(a2) bpl.s loc_19046 ori.w #high_priority,art_tile(a0) bra.s loc_19046 ; --------------------------------------------------------------------------- loc_1903E: cmpi.b #12,air_left(a2) blo.s loc_19058 loc_19046: lea (Ani_DashDust2P).l,a1 jsr (Animate_Sprite).l jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_19058: move.b #0,anim(a0) rts ; --------------------------------------------------------------------------- loc_19060: bra.w Delete_Current_Sprite ; --------------------------------------------------------------------------- loc_19064: movea.w parent(a0),a2 cmpi.b #$D,anim(a2) beq.s loc_1907E move.b #2,routine(a0) move.b #0,$36(a0) rts ; --------------------------------------------------------------------------- loc_1907E: move.b #0,mapping_frame(a0) subq.b #1,$36(a0) bpl.s locret_190F0 move.b #3,$36(a0) bsr.w AllocateObject bne.s locret_190F0 move.l (a0),(a1) move.w x_pos(a2),x_pos(a1) move.w y_pos(a2),y_pos(a1) addi.w #$C,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.w #$80,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 locret_190F0 ori.w #high_priority,art_tile(a1) locret_190F0: rts ; --------------------------------------------------------------------------- Ani_DashDust2P: include "General/Sprites/Dash Dust/Anim - Dash Dust 2P.asm" Map_DashDust2P: include "General/Sprites/Dash Dust/Map - Dash Dust 2P.asm" ; --------------------------------------------------------------------------- Obj_SuperSonicKnux_Stars: move.l #ArtUnc_SuperSonic_Stars,d1 move.w #tiles_to_bytes(ArtTile_Shield),d2 move.w #$1A0,d3 jsr (Add_To_DMA_Queue).l move.l #Map_SuperSonic_Stars,mappings(a0) move.b #4,render_flags(a0) move.w #$80,priority(a0) move.b #$18,width_pixels(a0) move.b #$18,height_pixels(a0) move.w #make_art_tile(ArtTile_Shield,0,0),art_tile(a0) btst #7,(Player_1+art_tile).w beq.s loc_1919E bset #7,art_tile(a0) loc_1919E: move.l #loc_191A4,(a0) loc_191A4: tst.b (Super_Sonic_Knux_flag).w beq.w loc_19230 tst.b anim(a0) beq.s loc_191B6 bsr.w sub_19236 loc_191B6: tst.b $34(a0) beq.s loc_19200 subq.b #1,anim_frame_timer(a0) bpl.s loc_191E8 move.b #1,anim_frame_timer(a0) addq.b #1,mapping_frame(a0) cmpi.b #6,mapping_frame(a0) blo.s loc_191E8 move.b #0,mapping_frame(a0) move.b #0,$34(a0) move.b #1,$35(a0) rts ; --------------------------------------------------------------------------- loc_191E8: tst.b $35(a0) bne.s loc_191FA loc_191EE: move.w (Player_1+x_pos).w,x_pos(a0) move.w (Player_1+y_pos).w,y_pos(a0) loc_191FA: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_19200: tst.b (Player_1+object_control).w bne.s loc_19222 move.w (Player_1+ground_vel).w,d0 bpl.s loc_1920E neg.w d0 loc_1920E: cmpi.w #$800,d0 blo.s loc_19222 move.b #0,mapping_frame(a0) move.b #1,$34(a0) bra.s loc_191EE ; --------------------------------------------------------------------------- loc_19222: move.b #0,$34(a0) move.b #0,$35(a0) rts ; --------------------------------------------------------------------------- loc_19230: jmp (Delete_Current_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_19236: move.b #0,anim(a0) lea (Player_1).w,a2 moveq #$10-1,d5 move.w #$488,d4 loc_19246: bsr.w AllocateObject bne.w locret_192BE move.l #Obj_SuperSonicKnux_Stars_Timer,(a1) move.w x_pos(a2),x_pos(a1) move.w y_pos(a2),y_pos(a1) move.l #Map_SuperSonic_Stars2,mappings(a1) move.w #make_art_tile($79C,0,1),art_tile(a1) move.b #$84,render_flags(a1) move.w #$380,priority(a1) move.b #8,width_pixels(a1) move.b #8,height_pixels(a1) tst.w d4 bmi.s loc_192AE move.w d4,d0 jsr (GetSineCosine).l 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 loc_192AE subi.w #$80,d4 bcc.s loc_192AE move.w #$488,d4 loc_192AE: move.w d2,x_vel(a1) move.w d3,y_vel(a1) neg.w d2 neg.w d4 dbf d5,loc_19246 locret_192BE: rts ; End of function sub_19236 ; --------------------------------------------------------------------------- Obj_SuperSonicKnux_Stars_Timer: tst.b render_flags(a0) bmi.s loc_192CC jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- loc_192CC: addq.b #1,mapping_frame(a0) andi.b #3,mapping_frame(a0) bsr.w MoveSprite2 bra.w Draw_Sprite ; --------------------------------------------------------------------------- Map_SuperSonic_Stars: include "General/Sprites/Shields/Map - Super Sonic Stars.asm" ; --------------------------------------------------------------------------- Obj_HyperSonic_Stars: lea (ArtKosM_HyperSonicStars).l,a1 move.w #tiles_to_bytes(ArtTile_Shield),d2 jsr (Queue_Kos_Module).l lea (a0),a1 moveq #0,d0 moveq #0,d2 moveq #4-1,d1 .createObject: move.l #Obj_HyperSonic_Stars_Init,(a1) move.b d0,angle(a1) addi.b #$40,d0 addq.b #1,d2 move.b d2,anim_frame_timer(a1) lea next_object(a1),a1 dbf d1,.createObject Obj_HyperSonic_Stars_Init: ; Wait for art to finish loading before we display tst.b (Kos_modules_left).w beq.s .artDoneLoading .return: rts ; --------------------------------------------------------------------------- .artDoneLoading: subq.b #1,anim_frame_timer(a0) bne.s .return move.l #Map_HyperSonicStars,mappings(a0) move.b #4,render_flags(a0) move.w #$80,priority(a0) move.b #$18,width_pixels(a0) move.b #$18,height_pixels(a0) move.w #make_art_tile(ArtTile_Shield,0,0),art_tile(a0) move.b #6,mapping_frame(a0) cmpa.w #Invincibility_stars,a0 beq.s .isParent move.l #Obj_HyperSonic_Stars_Main.child,(a0) bra.s Obj_HyperSonic_Stars_Main.child ; --------------------------------------------------------------------------- .isParent: move.l #Obj_HyperSonic_Stars_Main,(a0) Obj_HyperSonic_Stars_Main: tst.b anim(a0) beq.s .child clr.b anim(a0) move.w (Player_1+x_pos).w,x_pos(a0) move.w (Player_1+y_pos).w,y_pos(a0) moveq #2,d2 bsr.w Obj_LightningShield_CreateSpark_Part2 move.b #4,(Hyper_Sonic_flash_timer).w .child: tst.b (Super_Sonic_Knux_flag).w beq.w loc_19486 subq.b #1,anim_frame_timer(a0) bpl.s loc_1941C move.b #1,anim_frame_timer(a0) addq.b #1,mapping_frame(a0) cmpi.b #3,mapping_frame(a0) blo.s loc_1941C move.b #0,mapping_frame(a0) moveq #0,d0 move.w d0,$30(a0) move.w d0,$34(a0) loc_1941C: move.b angle(a0),d0 addi.b #-$10,angle(a0) jsr (GetSineCosine).l asl.w #3,d0 asl.w #3,d1 move.w d0,x_vel(a0) move.w d1,y_vel(a0) move.w x_vel(a0),d0 add.w d0,$30(a0) move.w y_vel(a0),d1 add.w d1,$34(a0) move.b $30(a0),d2 ext.w d2 btst #Status_Facing,(Player_1+status).w beq.s loc_19458 neg.w d2 loc_19458: move.b $34(a0),d3 ext.w d3 add.w (Player_1+x_pos).w,d2 add.w (Player_1+y_pos).w,d3 move.w d2,x_pos(a0) move.w d3,y_pos(a0) andi.w #drawing_mask,art_tile(a0) tst.b (Player_1+art_tile).w bpl.s loc_19480 ori.w #high_priority,art_tile(a0) loc_19480: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_19486: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- Map_HyperSonicStars: include "General/Sprites/Sonic/Map - Hyper Sonic Stars.asm" ; --------------------------------------------------------------------------- Obj_InstaShield: ; Init move.l #Map_InstaShield,mappings(a0) move.l #DPLC_InstaShield,shield_plc(a0) ; Used by PLCLoad_Shields move.l #ArtUnc_InstaShield,shield_art(a0) ; Used by PLCLoad_Shields move.b #4,render_flags(a0) move.w #$80,priority(a0) move.b #$18,width_pixels(a0) move.b #$18,height_pixels(a0) move.w #make_art_tile(ArtTile_Shield,0,0),art_tile(a0) move.w #tiles_to_bytes(ArtTile_Shield),vram_art(a0) ; Used by PLCLoad_Shields btst #7,(Player_1+art_tile).w beq.s .nothighpriority bset #7,art_tile(a0) .nothighpriority: move.w #1,anim(a0) ; Clear anim and set prev_anim to 1 move.b #-1,shield_prev_frame(a0) ; Reset shield_prev_frame (used by PLCLoad_Shields) move.l #Obj_InstaShield_Main,(a0) Obj_InstaShield_Main: movea.w parent(a0),a2 btst #Status_Invincible,status_secondary(a2) ; Is the player invincible? bne.s locret_195A4 ; If so, return move.w x_pos(a2),x_pos(a0) ; Inherit player's x_pos move.w y_pos(a2),y_pos(a0) ; Inherit player's y_pos move.b status(a2),status(a0) ; Inherit status andi.b #1,status(a0) ; Limit inheritance to 'orientation' bit tst.b (Reverse_gravity_flag).w beq.s .normalgravity ori.b #2,status(a0) ; Reverse the vertical mirror render flag bit (on if off beforehand and vice versa) .normalgravity: andi.w #drawing_mask,art_tile(a0) tst.w art_tile(a2) bpl.s .nothighpriority ori.w #high_priority,art_tile(a0) .nothighpriority: lea (Ani_InstaShield).l,a1 jsr (Animate_Sprite).l cmpi.b #7,mapping_frame(a0) ; Has it reached then end of its animation? bne.s .notover ; If not, branch tst.b double_jump_flag(a2) ; Is it in its attacking state? beq.s .notover ; If not, branch move.b #2,double_jump_flag(a2) ; Mark attack as over .notover: tst.b mapping_frame(a0) ; Is this the first frame? beq.s .loadnewDPLC ; If so, branch and load the DPLC for this and the next few frames cmpi.b #3,mapping_frame(a0) ; Is this the third frame? bne.s .skipDPLC ; If not, branch as we don't need to load another DPLC yet .loadnewDPLC: bsr.w PLCLoad_Shields .skipDPLC: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_195A4: rts ; --------------------------------------------------------------------------- Obj_FireShield: ; Init move.l #Map_FireShield,mappings(a0) move.l #DPLC_FireShield,shield_plc(a0) ; Used by PLCLoad_Shields move.l #ArtUnc_FireShield,shield_art(a0) ; Used by PLCLoad_Shields move.b #4,render_flags(a0) move.w #$80,priority(a0) move.b #$18,width_pixels(a0) move.b #$18,height_pixels(a0) move.w #make_art_tile(ArtTile_Shield,0,0),art_tile(a0) move.w #tiles_to_bytes(ArtTile_Shield),vram_art(a0) ; Used by PLCLoad_Shields btst #7,(Player_1+art_tile).w beq.s loc_195F0 bset #7,art_tile(a0) loc_195F0: move.w #1,anim(a0) ; Clear anim and set prev_anim to 1 move.b #-1,shield_prev_frame(a0) ; Reset shield_prev_frame (used by PLCLoad_Shields) move.l #Obj_FireShield_Main,(a0) Obj_FireShield_Main: movea.w parent(a0),a2 btst #Status_Invincible,status_secondary(a2) ; Is player invincible? bne.w locret_19690 ; If so, do not display and do not update variables cmpi.b #$1C,anim(a2) ; Is player in their 'blank' animation? beq.s locret_19690 ; If so, do not display and do not update variables btst #Status_Shield,status_secondary(a2) ; Should the player still have a shield? beq.w Obj_FireShield_Destroy ; If not, change to Insta-Shield btst #Status_Underwater,status(a2) ; Is player underwater? bne.s Obj_FireShield_DestroyUnderwater ; If so, branch move.w x_pos(a2),x_pos(a0) move.w y_pos(a2),y_pos(a0) tst.b anim(a0) ; Is shield in its 'dashing' state? bne.s .nothighpriority ; If so, do not update orientation or allow changing of the priority art_tile bit move.b status(a2),status(a0) ; Inherit status andi.b #1,status(a0) ; Limit inheritance to 'orientation' bit tst.b (Reverse_gravity_flag).w beq.s .normalgravity ori.b #2,status(a0) ; If in reverse gravity, reverse the vertical mirror render flag bit (on if off beforehand and vice versa) .normalgravity: andi.w #drawing_mask,art_tile(a0) tst.w art_tile(a2) bpl.s .nothighpriority ori.w #high_priority,art_tile(a0) .nothighpriority: lea (Ani_FireShield).l,a1 jsr (Animate_Sprite).l move.w #$80,priority(a0) ; Layer shield over player sprite cmpi.b #$F,mapping_frame(a0) ; Are these the frames that display in front of the player? blo.s .overplayer ; If so, branch move.w #$200,priority(a0) ; If not, layer shield behind player sprite .overplayer: bsr.w PLCLoad_Shields jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_19690: rts ; --------------------------------------------------------------------------- Obj_FireShield_DestroyUnderwater: andi.b #$8E,status_secondary(a2) ; Sets Status_Shield, Status_FireShield, Status_LtngShield, and Status_BublShield to 0 jsr (AllocateObject).l ; Set up for a new object bne.w Obj_FireShield_Destroy ; If that can't happen, branch move.l #Obj_FireShield_Dissipate,(a1) ; Create dissipate object move.w x_pos(a0),x_pos(a1) ; Put it at shields' x_pos move.w y_pos(a0),y_pos(a1) ; Put it at shields' y_pos Obj_FireShield_Destroy: andi.b #$8E,status_secondary(a2) ; Sets Status_Shield, Status_FireShield, Status_LtngShield, and Status_BublShield to 0 move.l #Obj_InstaShield,(a0) ; Replace the Fire Shield with the Insta-Shield rts ; --------------------------------------------------------------------------- Obj_LightningShield: ; init ; Load Spark art move.l #ArtUnc_LightningShield_Sparks,d1 ; Load art source move.w #tiles_to_bytes(ArtTile_Shield_Sparks),d2 ; Load art destination move.w #(ArtUnc_LightningShield_Sparks_end-ArtUnc_LightningShield_Sparks)/2,d3 ; Size of art (in words) jsr (Add_To_DMA_Queue).l move.l #Map_LightningShield,mappings(a0) move.l #DPLC_LightningShield,shield_plc(a0) ; Used by PLCLoad_Shields move.l #ArtUnc_LightningShield,shield_art(a0) ; Used by PLCLoad_Shields move.b #4,render_flags(a0) move.w #$80,priority(a0) move.b #$18,width_pixels(a0) move.b #$18,height_pixels(a0) move.w #make_art_tile(ArtTile_Shield,0,0),art_tile(a0) move.w #tiles_to_bytes(ArtTile_Shield),vram_art(a0) ; Used by PLCLoad_Shields btst #7,(Player_1+art_tile).w beq.s .nothighpriority bset #7,art_tile(a0) .nothighpriority: move.w #1,anim(a0) ; Clear anim and set prev_anim to 1 move.b #-1,shield_prev_frame(a0) ; Reset shield_prev_frame (used by PLCLoad_Shields) move.l #Obj_LightningShield_Main,(a0) Obj_LightningShield_Main: movea.w parent(a0),a2 btst #Status_Invincible,status_secondary(a2) ; Is player invincible? bne.w locret_197C4 ; If so, do not display and do not update variables cmpi.b #$1C,anim(a2) ; Is player in their 'blank' animation? beq.s locret_197C4 ; If so, do not display and do not update variables btst #Status_Shield,status_secondary(a2) ; Should the player still have a shield? beq.s Obj_LightningShield_Destroy ; If not, change to Insta-Shield btst #Status_Underwater,status(a2) ; Is player underwater? bne.s Obj_LightningShield_DestroyUnderwater ; If so, branch move.w x_pos(a2),x_pos(a0) move.w y_pos(a2),y_pos(a0) move.b status(a2),status(a0) ; Inherit status andi.b #1,status(a0) ; Limit inheritance to 'orientation' bit tst.b (Reverse_gravity_flag).w beq.s .normalgravity ori.b #2,status(a0) ; If in reverse gravity, reverse the vertical mirror render flag bit (on if off beforehand and vice versa) .normalgravity: andi.w #drawing_mask,art_tile(a0) tst.w art_tile(a2) bpl.s .nothighpriority ori.w #high_priority,art_tile(a0) .nothighpriority: tst.b anim(a0) ; Is shield in its 'double jump' state? beq.s Obj_LightningShield_Display ; Is not, branch and display bsr.s Obj_LightningShield_CreateSpark ; Create sparks clr.b anim(a0) ; Once done, return to non-'double jump' state Obj_LightningShield_Display: lea (Ani_LightningShield).l,a1 jsr (Animate_Sprite).l move.w #$80,priority(a0) ; Layer shield over player sprite cmpi.b #$E,mapping_frame(a0) ; Are these the frames that display in front of the player? blo.s .overplayer ; If so, branch move.w #$200,priority(a0) ; If not, layer shield behind player sprite .overplayer: bsr.w PLCLoad_Shields jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_197C4: rts ; --------------------------------------------------------------------------- Obj_LightningShield_DestroyUnderwater: tst.w (Palette_fade_timer).w beq.s Obj_LightningShield_FlashWater Obj_LightningShield_Destroy: andi.b #$8E,status_secondary(a2) ; Sets Status_Shield, Status_FireShield, Status_LtngShield, and Status_BublShield to 0 move.l #Obj_InstaShield,(a0) ; Replace the Lightning Shield with the Insta-Shield rts ; --------------------------------------------------------------------------- Obj_LightningShield_FlashWater: move.l #Obj_LightningShield_DestroyUnderwater2,(a0) andi.b #$8E,status_secondary(a2) ; Sets Status_Shield, Status_FireShield, Status_LtngShield, and Status_BublShield to 0 ; Flashes the underwater palette white lea (Water_palette).w,a1 lea (Target_water_palette).w,a2 move.w #bytesToLcnt($80),d0 ; Size of Water_palette/4-1 loc_197F2: move.l (a1),(a2)+ ; Backup palette entries move.l #$0EEE0EEE,(a1)+ ; Overwrite palette entries with white dbf d0,loc_197F2 ; Loop until entire thing is overwritten move.w #0,-$40(a1) ; Set the first colour in the third palette line to black move.b #3,anim_frame_timer(a0) rts ; =============== S U B R O U T I N E ======================================= Obj_LightningShield_CreateSpark: moveq #1,d2 Obj_LightningShield_CreateSpark_Part2: lea (SparkVelocities).l,a2 moveq #4-1,d1 .loop: bsr.w AllocateObject ; Find free object slot bne.s .end ; If one can't be found, return move.l #Obj_LightningShield_Spark,(a1) ; Make new object a Spark move.w x_pos(a0),x_pos(a1) ; (Spark) Inherit x_pos from source object (Lightning Shield, Hyper Sonic Stars) move.w y_pos(a0),y_pos(a1) ; (Spark) Inherit y_pos from source object (Lightning Shield, Hyper Sonic Stars) move.l mappings(a0),mappings(a1) ; (Spark) Inherit mappings from source object (Lightning Shield, Hyper Sonic Stars) move.w art_tile(a0),art_tile(a1) ; (Spark) Inherit art_tile from source object (Lightning Shield, Hyper Sonic Stars) move.b #4,render_flags(a1) move.w #$80,priority(a1) move.b #8,width_pixels(a1) move.b #8,height_pixels(a1) move.b d2,anim(a1) move.w (a2)+,x_vel(a1) ; (Spark) Give x_vel (unique to each of the four Sparks) move.w (a2)+,y_vel(a1) ; (Spark) Give y_vel (unique to each of the four Sparks) dbf d1,.loop .end: rts ; End of function Obj_LightningShield_CreateSpark ; --------------------------------------------------------------------------- SparkVelocities: dc.w -$200, -$200 dc.w $200, -$200 dc.w -$200, $200 dc.w $200, $200 ; --------------------------------------------------------------------------- Obj_LightningShield_Spark: jsr (MoveSprite2).l addi.w #$18,y_vel(a0) lea (Ani_LightningShield).l,a1 jsr (Animate_Sprite).l tst.b routine(a0) ; Changed by Animate_Sprite bne.s Obj_LightningShield_Spark_Delete jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Obj_LightningShield_Spark_Delete: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- Obj_LightningShield_DestroyUnderwater2: subq.b #1,anim_frame_timer(a0) ; Is it time to end the white flash? bpl.s .end ; If not, return move.l #Obj_InstaShield,(a0) ; Replace Lightning Shield with Insta-Shield lea (Target_water_palette).w,a1 lea (Water_palette).w,a2 move.w #bytesToLcnt($80),d0 ; Size of Water_palette/4-1 .loop: move.l (a1)+,(a2)+ ; Restore backed-up underwater palette dbf d0,.loop ; Loop until entire thing is restored .end: rts ; --------------------------------------------------------------------------- Obj_BubbleShield: ; Init move.l #Map_BubbleShield,mappings(a0) move.l #DPLC_BubbleShield,shield_plc(a0) ; Used by PLCLoad_Shields move.l #ArtUnc_BubbleShield,shield_art(a0) ; Used by PLCLoad_Shields move.b #4,render_flags(a0) move.w #$80,priority(a0) move.b #$18,width_pixels(a0) move.b #$18,height_pixels(a0) move.w #make_art_tile(ArtTile_Shield,0,0),art_tile(a0) move.w #tiles_to_bytes(ArtTile_Shield),vram_art(a0) ; Used by PLCLoad_Shields btst #7,(Player_1+art_tile).w beq.s .nothighpriority bset #7,art_tile(a0) .nothighpriority: move.w #1,anim(a0) ; Clear anim and set prev_anim to 1 move.b #-1,shield_prev_frame(a0) ; Reset shield_prev_frame (used by PLCLoad_Shields) movea.w parent(a0),a1 bsr.w Player_ResetAirTimer move.l #Obj_BubbleShield_Main,(a0) Obj_BubbleShield_Main: movea.w parent(a0),a2 btst #Status_Invincible,status_secondary(a2) ; Is player invincible? bne.s locret_1998A ; If so, do not display and do not update variables cmpi.b #$1C,anim(a2) ; Is player in their 'blank' animation? beq.s locret_1998A ; If so, do not display and do not update variables btst #Status_Shield,status_secondary(a2) ; Should the player still have a shield? beq.s Obj_BubbleShield_Destroy ; If not, change to Insta-Shield move.w x_pos(a2),x_pos(a0) move.w y_pos(a2),y_pos(a0) move.b status(a2),status(a0) ; Inherit status andi.b #1,status(a0) ; Limit inheritance to 'orientation' bit tst.b (Reverse_gravity_flag).w beq.s .normalgravity ori.b #2,status(a0) ; Reverse the vertical mirror render flag bit (on if off beforehand and vice versa) .normalgravity: andi.w #drawing_mask,art_tile(a0) tst.w art_tile(a2) bpl.s .nothighpriority ori.w #high_priority,art_tile(a0) .nothighpriority: lea (Ani_BubbleShield).l,a1 jsr (Animate_Sprite).l bsr.w PLCLoad_Shields jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_1998A: rts ; --------------------------------------------------------------------------- Obj_BubbleShield_Destroy: andi.b #$8E,status_secondary(a2) ; Sets Status_Shield, Status_FireShield, Status_LtngShield, and Status_BublShield to 0 move.l #Obj_InstaShield,(a0) ; Replace the Bubble Shield with the Insta-Shield rts ; =============== S U B R O U T I N E ======================================= PLCLoad_Shields: moveq #0,d0 move.b mapping_frame(a0),d0 cmp.b shield_prev_frame(a0),d0 beq.s locret_199E8 move.b d0,shield_prev_frame(a0) movea.l shield_plc(a0),a2 add.w d0,d0 adda.w (a2,d0.w),a2 move.w (a2)+,d5 subq.w #1,d5 bmi.s locret_199E8 move.w vram_art(a0),d4 PLCLoad_Shields_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 add.l shield_art(a0),d1 move.w d4,d2 add.w d3,d4 add.w d3,d4 jsr (Add_To_DMA_Queue).l dbf d5,PLCLoad_Shields_ReadEntry locret_199E8: rts ; End of function PLCLoad_Shields ; --------------------------------------------------------------------------- Ani_InstaShield: include "General/Sprites/Shields/Anim - Insta-Shield.asm" Ani_FireShield: include "General/Sprites/Shields/Anim - Fire Shield.asm" Ani_LightningShield: include "General/Sprites/Shields/Anim - Lightning Shield.asm" Ani_BubbleShield: include "General/Sprites/Shields/Anim - Bubble Shield.asm" Map_FireShield: include "General/Sprites/Shields/Map - Fire Shield.asm" DPLC_FireShield: include "General/Sprites/Shields/DPLC - Fire Shield.asm" Map_LightningShield: include "General/Sprites/Shields/Map - Lightning Shield.asm" DPLC_LightningShield: include "General/Sprites/Shields/DPLC - Lightning Shield.asm" Map_BubbleShield: include "General/Sprites/Shields/Map - Bubble Shield.asm" DPLC_BubbleShield: include "General/Sprites/Shields/DPLC - Bubble Shield.asm" Map_InstaShield: include "General/Sprites/Shields/Map - Insta-Shield.asm" DPLC_InstaShield: include "General/Sprites/Shields/DPLC - Insta-Shield.asm" ; --------------------------------------------------------------------------- superTailsBirds_target_found = $30 superTailsBirds_search_delay = $32 superTailsBirds_angle = $34 superTailsBirds_target_address = $42 Obj_SuperTailsBirds: lea (ArtKosM_SuperTailsBirds).l,a1 move.w #tiles_to_bytes(ArtTile_Player_1),d2 jsr (Queue_Kos_Module).l lea (a0),a1 moveq #0,d0 moveq #4-1,d1 .loop: move.l #Obj_SuperTailsBirds_Init,(a1) move.b d0,superTailsBirds_angle(a1) addi.b #$40,d0 ; 90 degrees lea next_object(a1),a1 dbf d1,.loop Obj_SuperTailsBirds_Init: ; Wait for the object's art to finish loading tst.b (Kos_modules_left).w beq.s .art_done_loading rts ; --------------------------------------------------------------------------- .art_done_loading: move.l #Map_SuperTails_Birds,mappings(a0) move.b #4,render_flags(a0) move.w #$80,priority(a0) move.b #8,width_pixels(a0) move.b #8,height_pixels(a0) move.w #make_art_tile(ArtTile_Player_1,0,1),art_tile(a0) move.w (Player_1+x_pos).w,x_pos(a0) move.w (Player_1+y_pos).w,y_pos(a0) subi.w #$C0,x_pos(a0) subi.w #$C0,y_pos(a0) move.w #0,x_vel(a0) move.w #0,y_vel(a0) move.l #Obj_SuperTailsBirds_Main,(a0) Obj_SuperTailsBirds_Main: tst.b (Super_Tails_flag).w bne.s .tails_still_super ; Tails has returned to normal - make the birds fly away moveq #0,d0 move.w d0,(Player_2+x_pos).w move.w d0,(Player_2+y_pos).w move.b d0,(Player_2+anim).w tst.b superTailsBirds_target_found(a0) beq.s .no_target movea.w superTailsBirds_target_address(a0),a1 move.b d0,$2D(a1) ; Seems to be for indicating whether an object has been 'locked-onto' or not .no_target: move.b d0,superTailsBirds_target_found(a0) move.b #60*2,superTailsBirds_search_delay(a0) ; Only search for enemies every two seconds (probably to reduce lag) move.l #Obj_SuperTailsBirds_FlyAway,(a0) .tails_still_super: bsr.s Obj_SuperTailsBirds_GetDestination .move: bsr.w Obj_SuperTailsBirds_Move addi.b #2,superTailsBirds_angle(a0) ; Update which way the sprite faces tst.w x_vel(a0) beq.s .x_flip_done bpl.s .face_right bset #0,render_flags(a0) bra.s .x_flip_done ; --------------------------------------------------------------------------- .face_right: bclr #0,render_flags(a0) .x_flip_done: ; Update whether the sprite should be upside down andi.b #~2,render_flags(a0) tst.b (Reverse_gravity_flag).w beq.s .not_upside_down ori.b #2,render_flags(a0) .not_upside_down: subq.b #1,anim_frame_timer(a0) bpl.s .timer_not_over move.b #1,anim_frame_timer(a0) addq.b #1,mapping_frame(a0) andi.b #1,mapping_frame(a0) .timer_not_over: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Obj_SuperTailsBirds_FlyAway: ; Set bird's destination to top-left of the screen move.w (Player_1+x_pos).w,d2 move.w (Player_1+y_pos).w,d3 subi.w #$C0,d2 subi.w #$C0,d3 tst.b render_flags(a0) bmi.s Obj_SuperTailsBirds_Main.move jmp (Delete_Current_Sprite).l ; If sprite is off-screen, delete it ; =============== S U B R O U T I N E ======================================= Obj_SuperTailsBirds_GetDestination: tst.b superTailsBirds_target_found(a0) bne.s .fly_towards_enemy tst.b superTailsBirds_search_delay(a0) beq.s .look_for_target subq.b #1,superTailsBirds_search_delay(a0) bra.s .fly_around_tails ; --------------------------------------------------------------------------- .look_for_target: bsr.w Obj_SuperTailsBirds_FindTarget tst.w d1 bne.s .fly_towards_enemy .fly_around_tails: move.b superTailsBirds_angle(a0),d0 jsr (GetSineCosine).l asr.w #3,d0 asr.w #4,d1 move.w (Player_1+x_pos).w,d2 move.w (Player_1+y_pos).w,d3 subi.w #$20,d3 tst.b (Reverse_gravity_flag).w beq.s .not_upside_down addi.w #$20*2,d3 .not_upside_down: add.w d0,d2 add.w d1,d3 rts ; --------------------------------------------------------------------------- .fly_towards_enemy: movea.w superTailsBirds_target_address(a0),a1 move.w x_pos(a1),d2 move.w y_pos(a1),d3 tst.b render_flags(a1) bpl.s .enemy_off_screen move.w x_pos(a0),d0 sub.w d2,d0 addi.w #$C,d0 cmpi.w #$18,d0 bhs.s .enemy_out_of_range move.w y_pos(a0),d1 sub.w d3,d1 addi.w #$C,d1 cmpi.w #$18,d1 bhs.s .enemy_out_of_range bsr.s .hit_enemy .enemy_off_screen: move.b #0,$2D(a1) move.b #0,superTailsBirds_target_found(a0) move.b #60*2,superTailsBirds_search_delay(a0) .enemy_out_of_range: rts ; End of function Obj_SuperTailsBirds_GetDestination ; =============== S U B R O U T I N E ======================================= .hit_enemy: move.b collision_flags(a1),d0 beq.s .no_collision ; If object has no collision, give up andi.b #$C0,d0 beq.s .enemy cmpi.b #$C0,d0 beq.s .special .no_collision: rts ; --------------------------------------------------------------------------- .enemy: tst.b collision_property(a1) beq.s .destroy_enemy ; Boss move.b collision_flags(a1),$25(a1) move.w #Player_2,d0 move.b d0,$1C(a1) move.b #0,collision_flags(a1) subq.b #1,collision_property(a1) bne.s .skip bset #7,status(a1) .skip: bra.s .done ; --------------------------------------------------------------------------- .destroy_enemy: jmp (HyperTouch_DestroyEnemy).l ; --------------------------------------------------------------------------- .special: ori.b #2,collision_property(a1) .done: move.w x_pos(a0),(Player_2+x_pos).w move.w y_pos(a0),(Player_2+y_pos).w move.b #2,(Player_2+anim).w rts ; End of function sub_1A31E ; =============== S U B R O U T I N E ======================================= Obj_SuperTailsBirds_Move: ; Update the bird's x_vel move.w #$20,d1 cmp.w x_pos(a0),d2 bge.s .go_right neg.w d1 tst.w x_vel(a0) bmi.s .x_vel_done ; Going the wrong way - make it turn around faster add.w d1,d1 add.w d1,d1 bra.s .x_vel_done ; --------------------------------------------------------------------------- .go_right: tst.w x_vel(a0) bpl.s .x_vel_done ; Going the wrong way - make it turn around faster add.w d1,d1 add.w d1,d1 .x_vel_done: add.w d1,x_vel(a0) ; Update the bird's y_vel and.w (Screen_Y_wrap_value).w,d3 move.w #$20,d1 sub.w y_pos(a0),d3 bcc.s loc_1A3CA cmpi.w #-$500,d3 ble.s loc_1A3D0 loc_1A3B4: cmpi.w #-$1000,y_vel(a0) ble.s loc_1A3D8 loc_1A3BC: neg.w d1 tst.w y_vel(a0) bmi.s loc_1A3E2 ; Going the wrong way - make it turn around faster add.w d1,d1 add.w d1,d1 bra.s loc_1A3E2 ; --------------------------------------------------------------------------- loc_1A3CA: cmpi.w #$500,d3 bge.s loc_1A3B4 loc_1A3D0: cmpi.w #$1000,y_vel(a0) bge.s loc_1A3BC loc_1A3D8: tst.w y_vel(a0) bpl.s loc_1A3E2 ; Going the wrong way - make it turn around faster add.w d1,d1 add.w d1,d1 loc_1A3E2: add.w d1,y_vel(a0) jsr (MoveSprite2).l move.w (Level_repeat_offset).w,d0 sub.w d0,x_pos(a0) move.w (Screen_Y_wrap_value).w,d0 and.w d0,y_pos(a0) rts ; End of function sub_1A37A ; =============== S U B R O U T I N E ======================================= Obj_SuperTailsBirds_FindTarget: moveq #0,d1 lea (Collision_response_list).w,a4 move.w (a4)+,d6 beq.s .return moveq #0,d0 addq.b #2,(_unkF66C).w cmp.b (_unkF66C).w,d6 bhi.s .noreset move.b #0,(_unkF66C).w .noreset: move.b (_unkF66C).w,d0 sub.w d0,d6 lea (a4,d0.w),a4 .loop: movea.w (a4)+,a1 move.b collision_flags(a1),d0 beq.s .ignore_object bsr.s .check_if_object_valid .ignore_object: subq.w #2,d6 bne.s .loop .return: rts ; End of function Obj_SuperTailsBirds_FindTarget ; =============== S U B R O U T I N E ======================================= .check_if_object_valid: tst.b render_flags(a1) bpl.s .invalid tst.b $2D(a1) bne.s .invalid andi.b #$C0,d0 beq.s .valid cmpi.b #$C0,d0 beq.s .valid .invalid: rts ; --------------------------------------------------------------------------- .valid: move.b #-1,$2D(a1) move.w a1,superTailsBirds_target_address(a0) move.b #1,superTailsBirds_target_found(a0) moveq #1,d1 moveq #2,d6 rts ; End of function sub_1A434 ; --------------------------------------------------------------------------- Map_SuperTails_Birds: include "General/Sprites/Tails/Map - Super Tails birds.asm" ; --------------------------------------------------------------------------- dc.l byte_189ED dc.b 0, $B dc.l byte_18A02 dc.b $16, $D dc.l byte_18A1B dc.b $2C, $D ; --------------------------------------------------------------------------- Obj_HyperSonicKnux_Trail: ; init move.l #Map_Knuckles,mappings(a0) ; Load Knuckles' mappings cmpi.w #3,(Player_mode).w ; Are we playing as Knuckles? beq.s .playingasknux ; If so, branch move.l #Map_SuperSonic,mappings(a0) ; If not, you must be Hyper Sonic, load Super/Hyper Sonic mappings .playingasknux: move.w #make_art_tile(ArtTile_Player_1,0,0),art_tile(a0) move.w #$100,priority(a0) move.b #$18,width_pixels(a0) move.b #$18,height_pixels(a0) move.b #4,render_flags(a0) move.l #Obj_HyperSonicKnux_Trail_Main,(a0) Obj_HyperSonicKnux_Trail_Main: tst.b (Super_Sonic_Knux_flag).w ; Are we in non-super/hyper state? beq.w Delete_Current_Sprite ; If so, branch and delete moveq #$C,d1 ; This will be subtracted from Pos_table_index, giving the object an older entry btst #0,(Level_frame_counter+1).w ; Even frame? (Think of it as 'every other number' logic) beq.s .evenframe ; If so, branch moveq #$14,d1 ; On every other frame, use a different number to subtract, giving the object an even older entry .evenframe: move.w (Pos_table_index).w,d0 lea (Pos_table).w,a1 sub.b d1,d0 lea (a1,d0.w),a1 move.w (a1)+,x_pos(a0) ; Use previous player x_pos move.w (a1)+,y_pos(a0) ; Use previous player y_pos lea (Stat_table).w,a1 move.b 3(a1,d0.w),art_tile(a0) move.b (Player_1+mapping_frame).w,mapping_frame(a0) ; Use player's current mapping_frame move.b (Player_1+render_flags).w,render_flags(a0) ; Use player's current render_flags move.w (Player_1+priority).w,priority(a0) ; Use player's current priority bra.w Draw_Sprite ; --------------------------------------------------------------------------- Obj_Ring: moveq #0,d0 move.b routine(a0),d0 move.w Ring_Index(pc,d0.w),d1 jmp Ring_Index(pc,d1.w) ; --------------------------------------------------------------------------- Ring_Index: dc.w Obj_RingInit-Ring_Index dc.w Obj_RingAnimate-Ring_Index dc.w Obj_RingCollect-Ring_Index dc.w Obj_RingSparkle-Ring_Index dc.w Obj_RingDelete-Ring_Index ; --------------------------------------------------------------------------- Obj_RingInit: addq.b #2,routine(a0) move.l #Map_Ring,mappings(a0) move.w #make_art_tile(ArtTile_Ring,1,1),art_tile(a0) move.b #4,render_flags(a0) move.w #$100,priority(a0) move.b #$47,collision_flags(a0) move.b #8,width_pixels(a0) tst.w (Competition_mode).w beq.s Obj_RingAnimate move.w #make_art_tile($3D2,3,0),art_tile(a0) Obj_RingAnimate: move.b (Rings_frame).w,mapping_frame(a0) bra.w Sprite_CheckDeleteTouch3 ; --------------------------------------------------------------------------- Obj_RingCollect: addq.b #2,routine(a0) move.b #0,collision_flags(a0) move.w #$80,priority(a0) bsr.s GiveRing Obj_RingSparkle: lea (Ani_RingSparkle).l,a1 bsr.w Animate_Sprite bra.w Draw_Sprite ; --------------------------------------------------------------------------- Obj_RingDelete: bra.w Delete_Current_Sprite ; =============== S U B R O U T I N E ======================================= GiveRing: cmpi.w #999,(Total_ring_count).w ; did Sonic collect 999 or more rings? bhs.s GiveRing_1P ; if yes, branch addq.w #1,(Total_ring_count).w ; add 1 to the number of collected rings GiveRing_1P: move.w #sfx_RingRight,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_Play_SFX ; if yes, play the ring sound addq.w #1,(Ring_count).w ; add 1 to the ring count ori.b #1,(Update_HUD_ring_count).w ; set flag to update the ring counter in the HUD cmpi.w #100,(Ring_count).w ; does the player 1 have less than 100 rings? blo.s JmpTo_Play_SFX ; if yes, play the ring sound bset #1,(Extra_life_flags).w ; test and set the flag for the first extra life beq.s loc_1A5D8 ; if it was clear before, branch cmpi.w #200,(Ring_count).w ; does the player 1 have less than 200 rings? blo.s JmpTo_Play_SFX ; 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_Play_SFX ; if it was set before, play the ring sound loc_1A5D8: addq.b #1,(Life_count).w ; add 1 to the life count addq.b #1,(Update_HUD_life_count).w ; add 1 to the displayed life count moveq #signextendB(mus_ExtraLife),d0 ; prepare to play the extra life jingle jmp (Play_Music).l ; Sonic 2 wound up putting music in the stereo sound queue, this would have fixed it ; --------------------------------------------------------------------------- JmpTo_Play_SFX: jmp (Play_SFX).l ; --------------------------------------------------------------------------- rts ; --------------------------------------------------------------------------- GiveRing_Tails: cmpi.w #999,(Total_ring_count_P2).w bhs.s loc_1A5FC addq.w #1,(Total_ring_count_P2).w loc_1A5FC: cmpi.w #999,(Ring_count_P2).w bhs.s loc_1A608 addq.w #1,(Ring_count_P2).w loc_1A608: tst.w (Competition_mode).w beq.s GiveRing_1P ori.b #1,(_unkFEBE).w move.w #sfx_RingRight,d0 cmpi.w #100,(Ring_count_P2).w blo.s loc_1A644 bset #1,(Extra_life_flags_P2).w beq.s loc_1A638 cmpi.w #200,(Ring_count_P2).w blo.s loc_1A644 bset #2,(Extra_life_flags_P2).w bne.s loc_1A644 loc_1A638: addq.b #1,(Life_count_P2).w moveq #signextendB(mus_ExtraLife),d0 jmp (Play_Music).l ; --------------------------------------------------------------------------- loc_1A644: jmp (Play_SFX).l ; End of function GiveRing ; --------------------------------------------------------------------------- Obj_Bouncing_Ring: moveq #0,d0 move.b routine(a0),d0 move.w Bouncing_Ring_Index(pc,d0.w),d1 jmp Bouncing_Ring_Index(pc,d1.w) ; --------------------------------------------------------------------------- Bouncing_Ring_Index: dc.w loc_1A67A-Bouncing_Ring_Index dc.w loc_1A75C-Bouncing_Ring_Index dc.w loc_1A7C2-Bouncing_Ring_Index dc.w loc_1A7D6-Bouncing_Ring_Index dc.w loc_1A7E4-Bouncing_Ring_Index ; --------------------------------------------------------------------------- Obj_Bouncing_Ring_Reverse_Gravity: moveq #0,d0 move.b routine(a0),d0 move.w Bouncing_Ring_Reverse_Gravity_Index(pc,d0.w),d1 jmp Bouncing_Ring_Reverse_Gravity_Index(pc,d1.w) ; --------------------------------------------------------------------------- Bouncing_Ring_Reverse_Gravity_Index: dc.w loc_1A67A-Bouncing_Ring_Reverse_Gravity_Index dc.w loc_1A7E8-Bouncing_Ring_Reverse_Gravity_Index dc.w loc_1A7C2-Bouncing_Ring_Reverse_Gravity_Index dc.w loc_1A7D6-Bouncing_Ring_Reverse_Gravity_Index dc.w loc_1A7E4-Bouncing_Ring_Reverse_Gravity_Index ; --------------------------------------------------------------------------- loc_1A67A: move.l #Obj_Bouncing_Ring,d6 tst.b (Reverse_gravity_flag).w beq.s loc_1A68C move.l #Obj_Bouncing_Ring_Reverse_Gravity,d6 loc_1A68C: movea.l a0,a1 moveq #0,d5 move.w (Ring_count).w,d5 tst.b $3F(a0) beq.s loc_1A69E move.w (Ring_count_P2).w,d5 loc_1A69E: moveq #$20,d0 cmp.w d0,d5 blo.s loc_1A6A6 move.w d0,d5 loc_1A6A6: subq.w #1,d5 move.w #$288,d4 bra.s loc_1A6B6 ; --------------------------------------------------------------------------- loc_1A6AE: bsr.w AllocateObjectAfterCurrent bne.w loc_1A738 loc_1A6B6: move.l d6,(a1) 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 #Map_Ring,mappings(a1) move.w #make_art_tile(ArtTile_Ring,1,1),art_tile(a1) move.b #$84,render_flags(a1) move.w #$180,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 loc_1A728 move.w d4,d0 jsr (GetSineCosine).l 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 loc_1A728 subi.w #$80,d4 bcc.s loc_1A728 move.w #$288,d4 loc_1A728: move.w d2,x_vel(a1) move.w d3,y_vel(a1) neg.w d2 neg.w d4 dbf d5,loc_1A6AE loc_1A738: move.w #signextendB(sfx_RingLoss),d0 jsr (Play_SFX).l move.w #0,(Ring_count).w move.b #$80,(Update_HUD_ring_count).w move.b #0,(Extra_life_flags).w tst.b (Reverse_gravity_flag).w bne.w loc_1A7E8 loc_1A75C: move.b (Ring_spill_anim_frame).w,mapping_frame(a0) bsr.w MoveSprite2 addi.w #$18,y_vel(a0) bmi.s loc_1A7B0 move.b (V_int_run_count+3).w,d0 add.b d7,d0 andi.b #7,d0 bne.s loc_1A7B0 tst.b render_flags(a0) bpl.s loc_1A79C jsr (RingCheckFloorDist).l tst.w d1 bpl.s loc_1A79C 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_1A79C: tst.b (Ring_spill_anim_counter).w beq.s loc_1A7E4 move.w (Camera_max_Y_pos).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 blo.s loc_1A7E4 loc_1A7B0: jsr (Add_SpriteToCollisionResponseList).l move.w (Level_repeat_offset).w,d0 sub.w d0,x_pos(a0) bra.w Draw_Sprite ; --------------------------------------------------------------------------- loc_1A7C2: addq.b #2,routine(a0) move.b #0,collision_flags(a0) move.w #$80,priority(a0) bsr.w GiveRing loc_1A7D6: lea (Ani_RingSparkle).l,a1 bsr.w Animate_Sprite bra.w Draw_Sprite ; --------------------------------------------------------------------------- loc_1A7E4: bra.w Delete_Current_Sprite ; --------------------------------------------------------------------------- loc_1A7E8: move.b (Ring_spill_anim_frame).w,mapping_frame(a0) bsr.w MoveSprite_TestGravity2 addi.w #$18,y_vel(a0) bmi.s loc_1A83C move.b (V_int_run_count+3).w,d0 add.b d7,d0 andi.b #7,d0 bne.s loc_1A83C tst.b render_flags(a0) bpl.s loc_1A828 jsr (RingCheckFloorDist_ReverseGravity).l tst.w d1 bpl.s loc_1A828 sub.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_1A828: tst.b (Ring_spill_anim_counter).w beq.s loc_1A7E4 move.w (Camera_max_Y_pos).w,d0 addi.w #$E0,d0 cmp.w y_pos(a0),d0 blo.s loc_1A7E4 loc_1A83C: jsr (Add_SpriteToCollisionResponseList).l move.w (Level_repeat_offset).w,d0 sub.w d0,x_pos(a0) bra.w Draw_Sprite ; --------------------------------------------------------------------------- Obj_Attracted_Ring: ; init move.l #Map_Ring,mappings(a0) move.w #make_art_tile(ArtTile_Ring,1,1),art_tile(a0) move.b #4,render_flags(a0) move.w #$100,priority(a0) move.b #$47,collision_flags(a0) move.b #8,width_pixels(a0) move.b #8,height_pixels(a0) move.b #8,y_radius(a0) move.b #8,x_radius(a0) move.l #loc_1A88C,(a0) loc_1A88C: tst.b routine(a0) bne.s AttractedRing_GiveRing bsr.w AttractedRing_Move btst #Status_LtngShield,(Player_1+status_secondary).w ; Does player still have a lightning shield? bne.s Obj_Attracted_RingAnimate move.l #Obj_Bouncing_Ring,(a0) ; If not, change object move.b #2,routine(a0) move.b #-1,(Ring_spill_anim_counter).w Obj_Attracted_RingAnimate: subq.b #1,anim_frame_timer(a0) bpl.s loc_1A8C6 move.b #3,anim_frame_timer(a0) addq.b #1,mapping_frame(a0) andi.b #3,mapping_frame(a0) loc_1A8C6: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_1A8E4 jsr (Add_SpriteToCollisionResponseList).l bra.w Draw_Sprite ; --------------------------------------------------------------------------- loc_1A8E4: move.w respawn_addr(a0),d0 beq.s loc_1A8F0 movea.w d0,a2 bclr #7,(a2) loc_1A8F0: ; Bug: probably meant to be $30(a0), as Test_Ring_Collisions_AttractRing ; stores the ring's address in the ring status table there move.w $30,d0 beq.s loc_1A8FC movea.w d0,a2 move.w #0,(a2) loc_1A8FC: bra.w Delete_Current_Sprite ; --------------------------------------------------------------------------- AttractedRing_GiveRing: move.b #0,collision_flags(a0) move.w #$80,priority(a0) subq.w #1,(Perfect_rings_left).w bsr.w GiveRing move.l #loc_1A920,(a0) move.b #0,routine(a0) loc_1A920: tst.b routine(a0) bne.s loc_1A934 lea (Ani_RingSparkle).l,a1 bsr.w Animate_Sprite bra.w Draw_Sprite ; --------------------------------------------------------------------------- loc_1A934: bra.w Delete_Current_Sprite ; =============== S U B R O U T I N E ======================================= AttractedRing_Move: ; Move on X axis move.w #$30,d1 move.w (Player_1+x_pos).w,d0 cmp.w x_pos(a0),d0 bhs.s AttractedRing_MoveRight ; If ring is to the left of the player, branch neg.w d1 tst.w x_vel(a0) bmi.s AttractedRing_ApplyMovementX add.w d1,d1 add.w d1,d1 bra.s AttractedRing_ApplyMovementX ; --------------------------------------------------------------------------- AttractedRing_MoveRight: tst.w x_vel(a0) bpl.s AttractedRing_ApplyMovementX add.w d1,d1 add.w d1,d1 AttractedRing_ApplyMovementX: add.w d1,x_vel(a0) ; Move on Y axis move.w #$30,d1 move.w (Player_1+y_pos).w,d0 cmp.w y_pos(a0),d0 bhs.s AttractedRing_MoveUp ; If ring is below the player, branch neg.w d1 tst.w y_vel(a0) bmi.s AttractedRing_ApplyMovementY add.w d1,d1 add.w d1,d1 bra.s AttractedRing_ApplyMovementY ; --------------------------------------------------------------------------- AttractedRing_MoveUp: tst.w y_vel(a0) bpl.s AttractedRing_ApplyMovementY add.w d1,d1 add.w d1,d1 AttractedRing_ApplyMovementY: add.w d1,y_vel(a0) jmp (MoveSprite2).l ; End of function AttractedRing_Move ; --------------------------------------------------------------------------- Ani_RingSparkle: include "General/Sprites/Ring/Anim - Ring Sparkle.asm" Map_Ring: include "General/Sprites/Ring/Map - Ring.asm" ; --------------------------------------------------------------------------- Obj_SlotRing: moveq #0,d0 move.b routine(a0),d0 move.w SlotRing_Index(pc,d0.w),d1 jmp SlotRing_Index(pc,d1.w) ; --------------------------------------------------------------------------- SlotRing_Index: dc.w loc_1AA02-SlotRing_Index dc.w loc_1AA56-SlotRing_Index dc.w loc_1AA62-SlotRing_Index ; --------------------------------------------------------------------------- loc_1AA02: moveq #0,d1 move.w $3C(a0),d1 swap d1 move.l $34(a0),d0 sub.l d1,d0 asr.l #4,d0 sub.l d0,$34(a0) move.w $34(a0),x_pos(a0) moveq #0,d1 move.w $3E(a0),d1 swap d1 move.l $38(a0),d0 sub.l d1,d0 asr.l #4,d0 sub.l d0,$38(a0) move.w $38(a0),y_pos(a0) lea Ani_Ring(pc),a1 bsr.w Animate_Sprite subq.w #1,$40(a0) bne.w Draw_Sprite movea.l $2E(a0),a1 subq.w #1,(a1) bsr.w GiveRing addi.b #2,routine(a0) loc_1AA56: lea Ani_RingSparkle(pc),a1 bsr.w Animate_Sprite bra.w Draw_Sprite ; --------------------------------------------------------------------------- loc_1AA62: bra.w Delete_Current_Sprite ; --------------------------------------------------------------------------- Ani_Ring: include "General/Sprites/Ring/Anim - Ring.asm" ; =============== S U B R O U T I N E ======================================= Init_SpriteTable: clr.w (Spritemask_flag).w if Sprite_table_page_flip_pending<>(Current_sprite_table_page+2) clr.w (Current_sprite_table_page).w clr.w (Sprite_table_page_flip_pending).w else clr.l (Current_sprite_table_page).w ; Clears both Current_sprite_table_page and Sprite_table_page_flip_pending! endif tst.w (Competition_mode).w beq.s loc_1AA9E lea (Sprite_table).w,a0 bsr.s Init_SpriteTable2 bsr.s Init_SpriteTable_2Player lea (Sprite_table_alternate).l,a0 bsr.s Init_SpriteTable2 bsr.s Init_SpriteTable_2Player lea (Sprite_table_P2).l,a0 bsr.s Init_SpriteTable2 lea (Sprite_table_P2_alternate).l,a0 bra.s Init_SpriteTable2 ; --------------------------------------------------------------------------- loc_1AA9E: lea (Sprite_table).w,a0 ; End of function Init_SpriteTable ; =============== S U B R O U T I N E ======================================= Init_SpriteTable2: moveq #0,d0 moveq #1,d1 moveq #$50-1,d7 .loop: move.w d0,(a0) move.b d1,3(a0) addq.w #1,d1 addq.w #8,a0 dbf d7,.loop move.b d0,-5(a0) rts ; End of function Init_SpriteTable2 ; =============== S U B R O U T I N E ======================================= Init_SpriteTable_2Player: lea -$280(a0),a0 move.l #$EB0301,(a0)+ move.l #1,(a0)+ move.l #$EB0302,(a0)+ move.l #0,(a0) rts ; End of function Init_SpriteTable_2Player ; =============== S U B R O U T I N E ======================================= Process_Sprites: tst.b (Teleport_active_flag).w bne.s locret_1AB0C lea (Object_RAM).w,a0 tst.w (Competition_mode).w bne.s loc_1AAFA cmpi.b #$C,(Player_1+routine).w beq.s loc_1AAFA cmpi.b #6,(Player_1+routine).w bhs.s loc_1AB0E loc_1AAFA: moveq #(Object_RAM_end-Object_RAM)/object_size-1,d7 ; End of function Process_Sprites ; =============== S U B R O U T I N E ======================================= sub_1AAFC: move.l (a0),d0 beq.s loc_1AB04 movea.l d0,a1 jsr (a1) loc_1AB04: lea next_object(a0),a0 dbf d7,sub_1AAFC locret_1AB0C: rts ; End of function sub_1AAFC ; --------------------------------------------------------------------------- loc_1AB0E: ; this is broken? moveq #((Dynamic_object_RAM+object_size)-Object_RAM)/object_size-1,d7 bsr.s sub_1AAFC moveq #((Level_object_RAM+object_size)-(Dynamic_object_RAM+object_size))/object_size-1,d7 bsr.s sub_1AB1A moveq #(Object_RAM_end-(Level_object_RAM+object_size))/object_size-1,d7 bra.s sub_1AAFC ; =============== S U B R O U T I N E ======================================= sub_1AB1A: move.l (a0),d0 beq.s loc_1AB28 tst.b render_flags(a0) bpl.s loc_1AB28 jsr Draw_Sprite(pc) loc_1AB28: lea next_object(a0),a0 dbf d7,sub_1AB1A rts ; End of function sub_1AB1A ; --------------------------------------------------------------------------- ; 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 ======================================= MoveSprite: move.w x_vel(a0),d0 ; load x speed ext.l d0 lsl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position add.l d0,x_pos(a0) ; 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 lsl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position add.l d0,y_pos(a0) ; add old y speed to y position ; note this affects the subpixel position y_sub(a0) = 2+y_pos(a0) rts ; End of function MoveSprite ; --------------------------------------------------------------------------- ; 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 ======================================= MoveSprite2: move.w x_vel(a0),d0 ; load horizontal speed ext.l d0 lsl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position add.l d0,x_pos(a0) ; 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 lsl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position add.l d0,y_pos(a0) ; add to y-axis position ; note this affects the subpixel position y_sub(a0) = 2+y_pos(a0) rts ; End of function MoveSprite2 ; =============== S U B R O U T I N E ======================================= MoveSprite_TestGravity: tst.b (Reverse_gravity_flag).w beq.s MoveSprite move.w x_vel(a0),d0 ; load x speed ext.l d0 lsl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position add.l d0,x_pos(a0) ; 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) neg.w d0 ; reverse it ext.l d0 lsl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position add.l d0,y_pos(a0) ; add old y speed to y position ; note this affects the subpixel position y_sub(a0) = 2+y_pos(a0) rts ; End of function MoveSprite_TestGravity ; =============== S U B R O U T I N E ======================================= MoveSprite_TestGravity2: tst.b (Reverse_gravity_flag).w beq.s MoveSprite2 move.w x_vel(a0),d0 ; load horizontal speed ext.l d0 lsl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position add.l d0,x_pos(a0) ; 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 neg.w d0 ; reverse it ext.l d0 lsl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position add.l d0,y_pos(a0) ; add to y-axis position ; note this affects the subpixel position y_sub(a0) = 2+y_pos(a0) rts ; End of function MoveSprite_TestGravity2 ; =============== S U B R O U T I N E ======================================= Delete_Current_Sprite: movea.l a0,a1 ; End of function Delete_Current_Sprite ; =============== S U B R O U T I N E ======================================= Delete_Referenced_Sprite: moveq #bytesToLcnt(object_size-2),d0 moveq #0,d1 .loop: move.l d1,(a1)+ dbf d0,.loop move.w d1,(a1)+ rts ; End of function Delete_Referenced_Sprite ; =============== S U B R O U T I N E ======================================= Draw_Sprite: lea (Sprite_table_input).w,a1 adda.w priority(a0),a1 loc_1ABCE: cmpi.w #$7E,(a1) bhs.s loc_1ABDC addq.w #2,(a1) adda.w (a1),a1 move.w a0,(a1) locret_1ABDA: rts ; --------------------------------------------------------------------------- loc_1ABDC: cmpa.w #Sprite_table_input+($80*7),a1 beq.s locret_1ABDA adda.w #$80,a1 bra.s loc_1ABCE ; End of function Draw_Sprite ; =============== S U B R O U T I N E ======================================= Animate_Sprite: moveq #0,d0 move.b anim(a0),d0 cmp.b prev_anim(a0),d0 beq.s loc_1AC00 move.b d0,prev_anim(a0) clr.b anim_frame(a0) clr.b anim_frame_timer(a0) loc_1AC00: subq.b #1,anim_frame_timer(a0) bcc.s locret_1AC36 add.w d0,d0 adda.w (a1,d0.w),a1 move.b (a1),anim_frame_timer(a0) moveq #0,d1 move.b anim_frame(a0),d1 move.b 1(a1,d1.w),d0 bmi.s loc_1AC38 loc_1AC1C: 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) locret_1AC36: rts ; --------------------------------------------------------------------------- loc_1AC38: addq.b #1,d0 ; Code FF - Repeat animation from beginning bne.s loc_1AC48 move.b #0,anim_frame(a0) move.b 1(a1),d0 bra.s loc_1AC1C ; --------------------------------------------------------------------------- loc_1AC48: addq.b #1,d0 ; Code FE - Repeat animation from earlier point bne.s loc_1AC5C move.b 2(a1,d1.w),d0 sub.b d0,anim_frame(a0) sub.b d0,d1 move.b 1(a1,d1.w),d0 bra.s loc_1AC1C ; --------------------------------------------------------------------------- loc_1AC5C: addq.b #1,d0 ; Code FD - Start new animation bne.s loc_1AC68 move.b 2(a1,d1.w),anim(a0) rts ; --------------------------------------------------------------------------- loc_1AC68: addq.b #1,d0 ; Code FC - Increment routine counter bne.s loc_1AC7A addq.b #2,routine(a0) clr.b anim_frame_timer(a0) addq.b #1,anim_frame(a0) rts ; --------------------------------------------------------------------------- loc_1AC7A: addq.b #1,d0 ; Code FB - Move offscreen bne.s locret_1AC86 move.w #$7F00,x_pos(a0) rts ; --------------------------------------------------------------------------- locret_1AC86: rts ; End of function Animate_Sprite ; =============== S U B R O U T I N E ======================================= Animate_SpriteIrregularDelay: moveq #0,d0 move.b anim(a0),d0 cmp.b prev_anim(a0),d0 beq.s loc_1ACA0 move.b d0,prev_anim(a0) clr.b anim_frame(a0) clr.b anim_frame_timer(a0) loc_1ACA0: subq.b #1,anim_frame_timer(a0) bcc.s locret_1ACDA add.w d0,d0 adda.w (a1,d0.w),a1 moveq #0,d1 move.b anim_frame(a0),d1 add.w d1,d1 move.b (a1,d1.w),d0 bmi.s loc_1ACDC loc_1ACBA: move.b 1(a1,d1.w),anim_frame_timer(a0) 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) locret_1ACDA: rts ; --------------------------------------------------------------------------- loc_1ACDC: addq.b #1,d0 bne.s loc_1ACEA ; Bug: S3 did not clear d1, making loc_1ACBA run a frame short with each loop. ; This was fixed, but apart from the Blue Spheres title, the only other effect ; is that the wink animation on the S3 title now runs a frame too long. moveq #0,d1 move.b d1,anim_frame(a0) move.b (a1),d0 bra.s loc_1ACBA ; --------------------------------------------------------------------------- loc_1ACEA: addq.b #1,d0 bne.s loc_1AD00 move.b 1(a1,d1.w),d0 sub.b d0,anim_frame(a0) add.w d0,d0 sub.b d0,d1 move.b (a1,d1.w),d0 bra.s loc_1ACBA ; --------------------------------------------------------------------------- loc_1AD00: addq.b #1,d0 bne.s loc_1AD0C move.b 1(a1,d1.w),anim(a0) rts ; --------------------------------------------------------------------------- loc_1AD0C: addq.b #1,d0 bne.s locret_1AD1E addq.b #2,routine(a0) clr.b anim_frame_timer(a0) addq.b #1,anim_frame(a0) rts ; --------------------------------------------------------------------------- locret_1AD1E: rts ; End of function Animate_SpriteIrregularDelay ; =============== S U B R O U T I N E ======================================= Render_Sprites: tst.w (Competition_mode).w bne.w Render_Sprites_CompetitionMode moveq #$50-1,d7 moveq #0,d6 lea (Sprite_table_input).w,a5 lea (Camera_X_pos_copy).w,a3 lea (Sprite_table).w,a6 tst.b (Level_started_flag).w beq.s loc_1AD4A jsr (Render_HUD).l jsr (Render_Rings).l loc_1AD4A: tst.w (a5) beq.w Render_Sprites_NextLevel lea 2(a5),a4 loc_1AD54: movea.w (a4)+,a0 ; a0=object andi.b #$7F,render_flags(a0) ; clear on-screen flag move.b render_flags(a0),d6 move.w x_pos(a0),d0 move.w y_pos(a0),d1 btst #6,d6 ; is the multi-draw flag set? bne.w loc_1AE58 ; if it is, branch btst #2,d6 ; is this to be positioned by screen coordinates? beq.s loc_1ADB2 ; if it is, branch moveq #0,d2 move.b width_pixels(a0),d2 sub.w (a3),d0 move.w d0,d3 add.w d2,d3 ; is the object right edge to the left of the screen? bmi.s Render_Sprites_NextObj ; if it is, branch move.w d0,d3 sub.w d2,d3 cmpi.w #320,d3 ; is the object left edge to the right of the screen? bge.s Render_Sprites_NextObj ; if it is, branch addi.w #128,d0 sub.w 4(a3),d1 move.b height_pixels(a0),d2 add.w d2,d1 and.w (Screen_Y_wrap_value).w,d1 move.w d2,d3 add.w d2,d2 addi.w #224,d2 cmp.w d2,d1 bhs.s Render_Sprites_NextObj ; if the object is below the screen addi.w #128,d1 sub.w d3,d1 loc_1ADB2: ori.b #$80,render_flags(a0) ; set on-screen flag tst.w d7 bmi.s Render_Sprites_NextObj movea.l mappings(a0),a1 moveq #0,d4 btst #5,d6 ; is the static mappings flag set? bne.s loc_1ADD8 ; if it is, branch move.b mapping_frame(a0),d4 add.w d4,d4 adda.w (a1,d4.w),a1 move.w (a1)+,d4 subq.w #1,d4 ; get number of pieces bmi.s Render_Sprites_NextObj ; if there are 0 pieces, branch loc_1ADD8: move.w art_tile(a0),d5 jsr sub_1AF6C(pc) Render_Sprites_NextObj: subq.w #2,(a5) ; decrement object count bne.w loc_1AD54 ; if there are objects left, repeat Render_Sprites_NextLevel: cmpa.l #Sprite_table_input,a5 bne.s loc_1ADFC cmpi.b #9,(Current_zone).w ; LRZ? bne.s loc_1ADFC jsr (sub_1CB68).l loc_1ADFC: lea $80(a5),a5 ; load next priority level cmpa.l #Player_1,a5 blo.w loc_1AD4A move.w d7,d6 bmi.s loc_1AE18 moveq #0,d0 loc_1AE10: move.w d0,(a6) addq.w #8,a6 dbf d7,loc_1AE10 loc_1AE18: subi.w #$4F,d6 neg.w d6 move.b d6,(Sprites_drawn).w tst.w (Spritemask_flag).w beq.s locret_1AE56 cmpi.b #6,(Player_1+routine).w bhs.s loc_1AE34 clr.w (Spritemask_flag).w loc_1AE34: lea (Sprite_table-4).w,a0 move.w #$7C0,d0 moveq #$4F-1,d1 loc_1AE3E: addq.w #8,a0 cmp.w (a0),d0 dbeq d1,loc_1AE3E bne.s locret_1AE56 move.w #1,2(a0) clr.w $A(a0) subq.w #1,d1 bpl.s loc_1AE3E locret_1AE56: rts ; --------------------------------------------------------------------------- loc_1AE58: btst #2,d6 ; is this to be positioned by screen coordinates? bne.s loc_1AEA2 ; if it is, branch moveq #0,d2 ; check if object is within X bounds move.b width_pixels(a0),d2 subi.w #128,d0 move.w d0,d3 add.w d2,d3 bmi.w Render_Sprites_NextObj move.w d0,d3 sub.w d2,d3 cmpi.w #320,d3 bge.w Render_Sprites_NextObj addi.w #128,d0 ; check if object is within Y bounds move.b height_pixels(a0),d2 subi.w #128,d1 move.w d1,d3 add.w d2,d3 bmi.w Render_Sprites_NextObj move.w d1,d3 sub.w d2,d3 cmpi.w #224,d3 bge.w Render_Sprites_NextObj addi.w #128,d1 bra.s loc_1AEE4 ; --------------------------------------------------------------------------- loc_1AEA2: moveq #0,d2 move.b width_pixels(a0),d2 sub.w (a3),d0 move.w d0,d3 add.w d2,d3 bmi.w Render_Sprites_NextObj move.w d0,d3 sub.w d2,d3 cmpi.w #320,d3 bge.w Render_Sprites_NextObj addi.w #128,d0 sub.w 4(a3),d1 move.b height_pixels(a0),d2 add.w d2,d1 and.w (Screen_Y_wrap_value).w,d1 move.w d2,d3 add.w d2,d2 addi.w #224,d2 cmp.w d2,d1 bhs.w Render_Sprites_NextObj addi.w #128,d1 sub.w d3,d1 loc_1AEE4: ori.b #$80,render_flags(a0) tst.w d7 bmi.w Render_Sprites_NextObj move.w art_tile(a0),d5 movea.l mappings(a0),a2 moveq #0,d4 move.b mapping_frame(a0),d4 beq.s loc_1AF1C add.w d4,d4 lea (a2),a1 adda.w (a1,d4.w),a1 move.w (a1)+,d4 subq.w #1,d4 bmi.s loc_1AF1C move.w d6,d3 jsr sub_1B070(pc) move.w d3,d6 tst.w d7 bmi.w Render_Sprites_NextObj loc_1AF1C: move.w mainspr_childsprites(a0),d3 subq.w #1,d3 bcs.w Render_Sprites_NextObj lea sub2_x_pos(a0),a0 loc_1AF2A: move.w (a0)+,d0 move.w (a0)+,d1 btst #2,d6 beq.s loc_1AF46 sub.w (a3),d0 addi.w #128,d0 sub.w 4(a3),d1 addi.w #128,d1 and.w (Screen_Y_wrap_value).w,d1 loc_1AF46: addq.w #1,a0 moveq #0,d4 move.b (a0)+,d4 add.w d4,d4 lea (a2),a1 adda.w (a1,d4.w),a1 move.w (a1)+,d4 subq.w #1,d4 bmi.s loc_1AF62 move.w d6,-(sp) jsr sub_1B070(pc) move.w (sp)+,d6 loc_1AF62: tst.w d7 dbmi d3,loc_1AF2A bra.w Render_Sprites_NextObj ; End of function Render_Sprites ; =============== S U B R O U T I N E ======================================= sub_1AF6C: lsr.b #1,d6 bcs.s loc_1AF9E lsr.b #1,d6 bcs.w loc_1B038 loc_1AF76: move.b (a1)+,d2 ext.w d2 add.w d1,d2 move.w d2,(a6)+ move.b (a1)+,(a6)+ addq.w #1,a6 move.w (a1)+,d2 add.w d5,d2 move.w d2,(a6)+ move.w (a1)+,d2 add.w d0,d2 andi.w #$1FF,d2 bne.s loc_1AF94 addq.w #1,d2 loc_1AF94: move.w d2,(a6)+ subq.w #1,d7 dbmi d4,loc_1AF76 rts ; --------------------------------------------------------------------------- loc_1AF9E: lsr.b #1,d6 bcs.s loc_1AFE8 loc_1AFA2: move.b (a1)+,d2 ext.w d2 add.w d1,d2 move.w d2,(a6)+ move.b (a1)+,d6 move.b d6,(a6)+ addq.w #1,a6 move.w (a1)+,d2 add.w d5,d2 eori.w #$800,d2 move.w d2,(a6)+ move.w (a1)+,d2 neg.w d2 move.b byte_1AFD8(pc,d6.w),d6 sub.w d6,d2 add.w d0,d2 andi.w #$1FF,d2 bne.s loc_1AFCE addq.w #1,d2 loc_1AFCE: move.w d2,(a6)+ subq.w #1,d7 dbmi d4,loc_1AFA2 rts ; --------------------------------------------------------------------------- byte_1AFD8: dc.b 8, 8, 8, 8 dc.b $10, $10, $10, $10 dc.b $18, $18, $18, $18 dc.b $20, $20, $20, $20 even ; --------------------------------------------------------------------------- loc_1AFE8: move.b (a1)+,d2 ext.w d2 neg.w d2 move.b (a1),d6 move.b byte_1B028(pc,d6.w),d6 sub.w d6,d2 add.w d1,d2 move.w d2,(a6)+ move.b (a1)+,d6 move.b d6,(a6)+ addq.w #1,a6 move.w (a1)+,d2 add.w d5,d2 eori.w #$1800,d2 move.w d2,(a6)+ move.w (a1)+,d2 neg.w d2 move.b byte_1AFD8(pc,d6.w),d6 sub.w d6,d2 add.w d0,d2 andi.w #$1FF,d2 bne.s loc_1B01E addq.w #1,d2 loc_1B01E: move.w d2,(a6)+ subq.w #1,d7 dbmi d4,loc_1AFE8 rts ; --------------------------------------------------------------------------- byte_1B028: dc.b 8, $10, $18, $20 dc.b 8, $10, $18, $20 dc.b 8, $10, $18, $20 dc.b 8, $10, $18, $20 even ; --------------------------------------------------------------------------- loc_1B038: move.b (a1)+,d2 ext.w d2 neg.w d2 move.b (a1)+,d6 move.b d6,2(a6) move.b byte_1B028(pc,d6.w),d6 sub.w d6,d2 add.w d1,d2 move.w d2,(a6)+ addq.w #2,a6 move.w (a1)+,d2 add.w d5,d2 eori.w #$1000,d2 move.w d2,(a6)+ move.w (a1)+,d2 add.w d0,d2 andi.w #$1FF,d2 bne.s loc_1B066 addq.w #1,d2 loc_1B066: move.w d2,(a6)+ subq.w #1,d7 dbmi d4,loc_1B038 rts ; End of function sub_1AF6C ; =============== S U B R O U T I N E ======================================= sub_1B070: lsr.b #1,d6 bcs.s loc_1B0C2 lsr.b #1,d6 bcs.w loc_1B19C loc_1B07A: move.b (a1)+,d2 ext.w d2 add.w d1,d2 cmpi.w #-32+128,d2 bls.s loc_1B0BA cmpi.w #224+128,d2 bhs.s loc_1B0BA move.w d2,(a6)+ move.b (a1)+,(a6)+ addq.w #1,a6 move.w (a1)+,d2 add.w d5,d2 move.w d2,(a6)+ move.w (a1)+,d2 add.w d0,d2 cmpi.w #-32+128,d2 bls.s loc_1B0B2 cmpi.w #320+128,d2 bhs.s loc_1B0B2 move.w d2,(a6)+ subq.w #1,d7 dbmi d4,loc_1B07A rts ; --------------------------------------------------------------------------- loc_1B0B2: subq.w #6,a6 dbf d4,loc_1B07A rts ; --------------------------------------------------------------------------- loc_1B0BA: addq.w #5,a1 dbf d4,loc_1B07A rts ; --------------------------------------------------------------------------- loc_1B0C2: lsr.b #1,d6 bcs.s loc_1B12C loc_1B0C6: move.b (a1)+,d2 ext.w d2 add.w d1,d2 cmpi.w #-32+128,d2 bls.s loc_1B114 cmpi.w #224+128,d2 bhs.s loc_1B114 move.w d2,(a6)+ move.b (a1)+,d6 move.b d6,(a6)+ addq.w #1,a6 move.w (a1)+,d2 add.w d5,d2 eori.w #$800,d2 move.w d2,(a6)+ move.w (a1)+,d2 neg.w d2 move.b byte_1B11C(pc,d6.w),d6 sub.w d6,d2 add.w d0,d2 cmpi.w #-32+128,d2 bls.s loc_1B10C cmpi.w #320+128,d2 bhs.s loc_1B10C move.w d2,(a6)+ subq.w #1,d7 dbmi d4,loc_1B0C6 rts ; --------------------------------------------------------------------------- loc_1B10C: subq.w #6,a6 dbf d4,loc_1B0C6 rts ; --------------------------------------------------------------------------- loc_1B114: addq.w #5,a1 dbf d4,loc_1B0C6 rts ; --------------------------------------------------------------------------- byte_1B11C: dc.b 8, 8, 8, 8 dc.b $10, $10, $10, $10 dc.b $18, $18, $18, $18 dc.b $20, $20, $20, $20 even ; --------------------------------------------------------------------------- loc_1B12C: move.b (a1)+,d2 ext.w d2 neg.w d2 move.b (a1),d6 move.b byte_1B18C(pc,d6.w),d6 sub.w d6,d2 add.w d1,d2 cmpi.w #-32+128,d2 bls.s loc_1B184 cmpi.w #224+128,d2 bhs.s loc_1B184 move.w d2,(a6)+ move.b (a1)+,d6 move.b d6,(a6)+ addq.w #1,a6 move.w (a1)+,d2 add.w d5,d2 eori.w #$1800,d2 move.w d2,(a6)+ move.w (a1)+,d2 neg.w d2 move.b byte_1B11C(pc,d6.w),d6 sub.w d6,d2 add.w d0,d2 cmpi.w #-32+128,d2 bls.s loc_1B17C cmpi.w #320+128,d2 bhs.s loc_1B17C move.w d2,(a6)+ subq.w #1,d7 dbmi d4,loc_1B12C rts ; --------------------------------------------------------------------------- loc_1B17C: subq.w #6,a6 dbf d4,loc_1B12C rts ; --------------------------------------------------------------------------- loc_1B184: addq.w #5,a1 dbf d4,loc_1B12C rts ; --------------------------------------------------------------------------- byte_1B18C: dc.b 8, $10, $18, $20 dc.b 8, $10, $18, $20 dc.b 8, $10, $18, $20 dc.b 8, $10, $18, $20 even ; --------------------------------------------------------------------------- loc_1B19C: move.b (a1)+,d2 ext.w d2 neg.w d2 move.b (a1)+,d6 move.b d6,2(a6) move.b byte_1B18C(pc,d6.w),d6 sub.w d6,d2 add.w d1,d2 cmpi.w #-32+128,d2 bls.s loc_1B1EC cmpi.w #224+128,d2 bhs.s loc_1B1EC move.w d2,(a6)+ addq.w #2,a6 move.w (a1)+,d2 add.w d5,d2 eori.w #$1000,d2 move.w d2,(a6)+ move.w (a1)+,d2 add.w d0,d2 cmpi.w #-32+128,d2 bls.s loc_1B1E4 cmpi.w #320+128,d2 bhs.s loc_1B1E4 move.w d2,(a6)+ subq.w #1,d7 dbmi d4,loc_1B19C rts ; --------------------------------------------------------------------------- loc_1B1E4: subq.w #6,a6 dbf d4,loc_1B19C rts ; --------------------------------------------------------------------------- loc_1B1EC: addq.w #4,a1 dbf d4,loc_1B19C rts ; End of function sub_1B070 ; --------------------------------------------------------------------------- Render_Sprites_CompetitionMode: moveq #($50-2)-1,d7 moveq #0,d6 lea (Sprite_table_input).w,a5 lea (Camera_X_pos_copy).w,a3 ; Unlike in Sonic 2, the sprite tables are page-flipped in two-player mode. ; This fixes a race-condition where incomplete sprite tables can be uploaded ; to the VDP on lag frames, causing corrupted sprites to appear. ; Modify the back buffer. lea (Sprite_table+$10).w,a6 tst.w (Current_sprite_table_page).w beq.s loc_1B210 lea (Sprite_table_alternate+$10).l,a6 loc_1B210: tst.b (Level_started_flag).w beq.s loc_1B21C jsr (Render_HUD_P1).l loc_1B21C: move.b 1(a5),(a5) beq.w loc_1B2C8 lea 2(a5),a4 loc_1B228: movea.w (a4)+,a0 andi.b #$7F,render_flags(a0) move.b render_flags(a0),d6 btst #4,d6 bne.w loc_1B2C2 move.w x_pos(a0),d0 move.w y_pos(a0),d1 btst #6,d6 bne.w loc_1B3EC btst #2,d6 beq.s loc_1B294 moveq #0,d2 sub.w (a3),d0 move.b width_pixels(a0),d2 add.w d2,d0 and.w (Screen_X_wrap_value).w,d0 move.w d2,d3 add.w d2,d2 addi.w #320,d2 cmp.w d2,d0 bhs.s loc_1B2C2 addi.w #128,d0 sub.w d3,d0 moveq #0,d2 sub.w 4(a3),d1 move.b height_pixels(a0),d2 add.w d2,d1 and.w (Screen_Y_wrap_value).w,d1 move.w d2,d3 add.w d2,d2 addi.w #224/2,d2 cmp.w d2,d1 bhs.s loc_1B2C2 addi.w #128,d1 sub.w d3,d1 loc_1B294: ori.b #$80,render_flags(a0) tst.w d7 bmi.s loc_1B2C2 movea.l mappings(a0),a1 moveq #0,d4 btst #5,d6 bne.s loc_1B2BA move.b mapping_frame(a0),d4 add.w d4,d4 adda.w (a1,d4.w),a1 move.w (a1)+,d4 subq.w #1,d4 bmi.s loc_1B2C2 loc_1B2BA: move.w art_tile(a0),d5 jsr sub_1AF6C(pc) loc_1B2C2: subq.b #2,(a5) bne.w loc_1B228 loc_1B2C8: lea $80(a5),a5 cmpa.l #Player_1,a5 blo.w loc_1B21C tst.w d7 bmi.s loc_1B2E4 moveq #0,d0 loc_1B2DC: move.w d0,(a6) addq.w #8,a6 dbf d7,loc_1B2DC loc_1B2E4: move.l (Sprite_table_input+2+($80*2)).w,d0 cmpi.l #((Player_1&$FFFF)<<16)|(Player_2&$FFFF),d0 bne.s loc_1B2F6 swap d0 move.l d0,(Sprite_table_input+2+($80*2)).w loc_1B2F6: moveq #$50-1,d7 lea (Sprite_table_input).w,a5 lea (Camera_X_pos_P2_copy).w,a3 ; Unlike in Sonic 2, the sprite tables are page-flipped in two-player mode. ; This fixes a race-condition where incomplete sprite tables can be uploaded ; to the VDP on lag frames, causing corrupted sprites to appear. ; Modify the back buffer. lea (Sprite_table_P2).l,a6 tst.w (Current_sprite_table_page).w beq.s loc_1B312 lea (Sprite_table_P2_alternate).l,a6 loc_1B312: tst.b (Level_started_flag).w beq.s loc_1B31E jsr (Render_HUD_P2).l loc_1B31E: tst.b 1(a5) beq.w loc_1B3CA lea 2(a5),a4 loc_1B32A: movea.w (a4)+,a0 move.b render_flags(a0),d6 btst #3,d6 bne.w loc_1B3C2 move.w x_pos(a0),d0 move.w y_pos(a0),d1 btst #6,d6 bne.w loc_1B4B8 btst #2,d6 beq.s loc_1B390 moveq #0,d2 sub.w (a3),d0 move.b width_pixels(a0),d2 add.w d2,d0 and.w (Screen_X_wrap_value).w,d0 move.w d2,d3 add.w d2,d2 addi.w #320,d2 cmp.w d2,d0 bhs.s loc_1B3C2 addi.w #128,d0 sub.w d3,d0 moveq #0,d2 sub.w 4(a3),d1 move.b height_pixels(a0),d2 add.w d2,d1 and.w (Screen_Y_wrap_value).w,d1 move.w d2,d3 add.w d2,d2 addi.w #224/2,d2 cmp.w d2,d1 bhs.s loc_1B3C2 addi.w #128,d1 sub.w d3,d1 loc_1B390: addi.w #224/2,d1 ori.b #$80,render_flags(a0) tst.w d7 bmi.s loc_1B3C2 movea.l mappings(a0),a1 moveq #0,d4 btst #5,d6 bne.s loc_1B3BA move.b mapping_frame(a0),d4 add.w d4,d4 adda.w (a1,d4.w),a1 move.w (a1)+,d4 subq.w #1,d4 bmi.s loc_1B3C2 loc_1B3BA: move.w art_tile(a0),d5 jsr sub_1AF6C(pc) loc_1B3C2: subq.b #2,1(a5) bne.w loc_1B32A loc_1B3CA: lea $80(a5),a5 cmpa.l #Player_1,a5 blo.w loc_1B31E tst.w d7 bmi.s loc_1B3E6 moveq #0,d0 loc_1B3DE: move.w d0,(a6) addq.w #8,a6 dbf d7,loc_1B3DE loc_1B3E6: ; The new sprite tables are complete: signal a page flip to ; allow them to be uploaded to the VDP! st.b (Sprite_table_page_flip_pending).w rts ; --------------------------------------------------------------------------- loc_1B3EC: moveq #0,d2 sub.w (a3),d0 move.b width_pixels(a0),d2 add.w d2,d0 and.w (Screen_X_wrap_value).w,d0 move.w d2,d3 add.w d2,d2 addi.w #320,d2 cmp.w d2,d0 bhs.w loc_1B2C2 addi.w #128,d0 sub.w d3,d0 moveq #0,d2 sub.w 4(a3),d1 move.b height_pixels(a0),d2 add.w d2,d1 and.w (Screen_Y_wrap_value).w,d1 move.w d2,d3 add.w d2,d2 addi.w #224/2,d2 cmp.w d2,d1 bhs.w loc_1B2C2 addi.w #128,d1 sub.w d3,d1 ori.b #$80,render_flags(a0) tst.w d7 bmi.w loc_1B2C2 move.w art_tile(a0),d5 movea.l mappings(a0),a2 moveq #0,d4 move.b mapping_frame(a0),d4 beq.s loc_1B46A add.w d4,d4 lea (a2),a1 adda.w (a1,d4.w),a1 move.w (a1)+,d4 subq.w #1,d4 bmi.s loc_1B46A move.w d6,d3 jsr sub_1B070(pc) move.w d3,d6 tst.w d7 bmi.w loc_1B2C2 loc_1B46A: move.w mainspr_childsprites(a0),d3 subq.w #1,d3 bcs.w loc_1B2C2 lea sub2_x_pos(a0),a0 loc_1B478: move.w (a0)+,d0 sub.w (a3),d0 addi.w #128,d0 and.w (Screen_X_wrap_value).w,d0 move.w (a0)+,d1 sub.w 4(a3),d1 addi.w #128,d1 and.w (Screen_Y_wrap_value).w,d1 addq.w #1,a0 moveq #0,d4 move.b (a0)+,d4 add.w d4,d4 lea (a2),a1 adda.w (a1,d4.w),a1 move.w (a1)+,d4 subq.w #1,d4 bmi.s loc_1B4AE move.w d6,-(sp) jsr sub_1B070(pc) move.w (sp)+,d6 loc_1B4AE: tst.w d7 dbmi d3,loc_1B478 bra.w loc_1B2C2 ; --------------------------------------------------------------------------- loc_1B4B8: moveq #0,d2 sub.w (a3),d0 move.b width_pixels(a0),d2 add.w d2,d0 and.w (Screen_X_wrap_value).w,d0 move.w d2,d3 add.w d2,d2 addi.w #320,d2 cmp.w d2,d0 bhs.w loc_1B3C2 addi.w #128,d0 sub.w d3,d0 moveq #0,d2 sub.w 4(a3),d1 move.b height_pixels(a0),d2 add.w d2,d1 and.w (Screen_Y_wrap_value).w,d1 move.w d2,d3 add.w d2,d2 addi.w #224/2,d2 cmp.w d2,d1 bhs.w loc_1B3C2 addi.w #240,d1 sub.w d3,d1 ori.b #$80,render_flags(a0) tst.w d7 bmi.w loc_1B3C2 move.w art_tile(a0),d5 movea.l mappings(a0),a2 moveq #0,d4 move.b mapping_frame(a0),d4 beq.s loc_1B536 add.w d4,d4 lea (a2),a1 adda.w (a1,d4.w),a1 move.w (a1)+,d4 subq.w #1,d4 bmi.s loc_1B536 move.w d6,d3 jsr sub_1B070(pc) move.w d3,d6 tst.w d7 bmi.w loc_1B3C2 loc_1B536: move.w mainspr_childsprites(a0),d3 subq.w #1,d3 bcs.w loc_1B3C2 lea sub2_x_pos(a0),a0 loc_1B544: move.w (a0)+,d0 sub.w (a3),d0 addi.w #128,d0 and.w (Screen_X_wrap_value).w,d0 move.w (a0)+,d1 sub.w 4(a3),d1 addi.w #128,d1 and.w (Screen_Y_wrap_value).w,d1 addi.w #224/2,d1 addq.w #1,a0 moveq #0,d4 move.b (a0)+,d4 add.w d4,d4 lea (a2),a1 adda.w (a1,d4.w),a1 move.w (a1)+,d4 subq.w #1,d4 bmi.s loc_1B57E move.w d6,-(sp) jsr sub_1B070(pc) move.w (sp)+,d6 loc_1B57E: tst.w d7 dbmi d3,loc_1B544 bra.w loc_1B3C2 ; --------------------------------------------------------------------------- Sprite_OnScreen_Test: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_1B5A0 bra.w Draw_Sprite ; --------------------------------------------------------------------------- loc_1B5A0: move.w respawn_addr(a0),d0 beq.s loc_1B5AC movea.w d0,a2 bclr #7,(a2) loc_1B5AC: bra.w Delete_Current_Sprite ; --------------------------------------------------------------------------- Sprite_OnScreen_Test2: andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_1B5C4 bra.w Draw_Sprite ; --------------------------------------------------------------------------- loc_1B5C4: move.w respawn_addr(a0),d0 beq.s loc_1B5D0 movea.w d0,a2 bclr #7,(a2) loc_1B5D0: bra.w Delete_Current_Sprite ; =============== S U B R O U T I N E ======================================= Delete_Sprite_If_Not_In_Range: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_1B5EA rts ; --------------------------------------------------------------------------- loc_1B5EA: move.w respawn_addr(a0),d0 beq.s loc_1B5F6 movea.w d0,a2 bclr #7,(a2) loc_1B5F6: bra.w Delete_Current_Sprite ; End of function Delete_Sprite_If_Not_In_Range ; --------------------------------------------------------------------------- tst.w (Competition_mode).w bne.s loc_1B628 move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_1B618 bra.w Draw_Sprite ; --------------------------------------------------------------------------- loc_1B618: move.w respawn_addr(a0),d0 beq.s loc_1B624 movea.w d0,a2 bclr #7,(a2) loc_1B624: bra.w Delete_Current_Sprite ; --------------------------------------------------------------------------- loc_1B628: move.w x_pos(a0),d0 andi.w #$FF00,d0 move.w d0,d1 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$300,d0 bhi.w loc_1B642 bra.w Draw_Sprite ; --------------------------------------------------------------------------- loc_1B642: sub.w (_unkF7DC).w,d1 cmpi.w #$300,d1 bhi.w loc_1B652 bra.w Draw_Sprite ; --------------------------------------------------------------------------- loc_1B652: move.w respawn_addr(a0),d0 beq.s loc_1B65E movea.w d0,a2 bclr #7,(a2) loc_1B65E: bra.w Delete_Current_Sprite ; --------------------------------------------------------------------------- Sprite_CheckDeleteTouch3: move.w x_pos(a0),d0 loc_1B666: andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_1B680 jsr (Add_SpriteToCollisionResponseList).l bra.w Draw_Sprite ; --------------------------------------------------------------------------- loc_1B680: move.w respawn_addr(a0),d0 beq.s loc_1B68C movea.w d0,a2 bclr #7,(a2) loc_1B68C: bra.w Delete_Current_Sprite ; =============== S U B R O U T I N E ======================================= Load_Sprites: moveq #0,d0 move.b (Object_load_routine).w,d0 jmp Load_Sprites_Index(pc,d0.w) ; End of function Load_Sprites ; --------------------------------------------------------------------------- Load_Sprites_Index: bra.w loc_1B6A8 ; --------------------------------------------------------------------------- bra.w loc_1B7F2 ; --------------------------------------------------------------------------- bra.w loc_1B7F2 ; --------------------------------------------------------------------------- rts ; --------------------------------------------------------------------------- loc_1B6A8: move.l #Sprite_ListingK,d0 move.b (Current_zone).w,d1 cmpi.b #$16,d1 bhs.s loc_1B6CA cmpi.b #$E,d1 bhs.s loc_1B6C4 cmpi.b #7,d1 bhs.s loc_1B6CA loc_1B6C4: move.l #Sprite_Listing3,d0 loc_1B6CA: move.l d0,(Object_index_addr).w addq.b #4,(Object_load_routine).w tst.b (Respawn_table_keep).w bne.s loc_1B6E8 lea (Object_respawn_table).w,a0 moveq #0,d0 move.w #bytesToLcnt($300),d1 loc_1B6E2: move.l d0,(a0)+ dbf d1,loc_1B6E2 loc_1B6E8: move.w (Current_zone_and_act).w,d0 ror.b #1,d0 lsr.w #5,d0 lea (SpriteLocPtrs).l,a0 movea.l (a0,d0.w),a0 cmpi.w #$1701,(Current_zone_and_act).w beq.s loc_1B720 cmpi.b #$16,(Current_zone).w bhs.s loc_1B76A cmpi.b #$14,(Current_zone).w beq.s loc_1B76A cmpi.b #$13,(Current_zone).w bhs.s loc_1B720 tst.w (Competition_mode).w beq.s loc_1B76A loc_1B720: addq.b #8,(Object_load_routine).w jsr AllocateObject(pc) bne.s loc_1B74C lea (_unkF712).w,a3 movea.l (Object_index_addr).w,a4 move.w #$800,d6 cmpi.w #$1701,(Current_zone_and_act).w bne.s loc_1B742 move.w #$1780,d6 loc_1B742: cmp.w (a0),d6 bls.s loc_1B74C jsr sub_1BA0C(pc) beq.s loc_1B742 loc_1B74C: clr.w (Camera_X_pos_coarse_back).w cmpi.w #$1701,(Current_zone_and_act).w bne.s locret_1B768 move.w (Camera_X_pos).w,d1 subi.w #$80,d1 andi.w #$FF80,d1 move.w d1,(Camera_X_pos_coarse_back).w locret_1B768: rts ; --------------------------------------------------------------------------- loc_1B76A: move.l a0,(Object_load_addr_front).w move.l a0,(Object_load_addr_back).w lea (Object_respawn_table).w,a3 cmpi.b #$14,(Current_zone).w bne.s loc_1B78E lea (Object_respawn_table_2).w,a3 moveq #bytesToLcnt($200),d6 loc_1B784: clr.l (a3)+ dbf d6,loc_1B784 lea (Object_respawn_table_2).w,a3 loc_1B78E: move.w (Camera_X_pos).w,d6 subi.w #$80,d6 bcc.s loc_1B79A moveq #0,d6 loc_1B79A: andi.w #$FF80,d6 movea.l (Object_load_addr_front).w,a0 loc_1B7A2: cmp.w (a0),d6 bls.s loc_1B7AC addq.w #6,a0 addq.w #1,a3 bra.s loc_1B7A2 ; --------------------------------------------------------------------------- loc_1B7AC: move.l a0,(Object_load_addr_front).w move.w a3,(Object_respawn_index_front).w lea (Object_respawn_table).w,a3 cmpi.b #$14,(Current_zone).w bne.s loc_1B7C4 lea (Object_respawn_table_2).w,a3 loc_1B7C4: movea.l (Object_load_addr_back).w,a0 subi.w #$80,d6 bcs.s loc_1B7D8 loc_1B7CE: cmp.w (a0),d6 bls.s loc_1B7D8 addq.w #6,a0 addq.w #1,a3 bra.s loc_1B7CE ; --------------------------------------------------------------------------- loc_1B7D8: move.l a0,(Object_load_addr_back).w move.w a3,(Object_respawn_index_back).w move.w #-1,(Camera_X_pos_coarse).w move.w (Camera_Y_pos).w,d0 andi.w #$FF80,d0 move.w d0,(Camera_Y_pos_coarse).w loc_1B7F2: move.w (Camera_Y_pos).w,d1 subi.w #$80,d1 andi.w #$FF80,d1 move.w d1,(Camera_Y_pos_coarse_back).w move.w (Camera_X_pos).w,d1 subi.w #$80,d1 andi.w #$FF80,d1 move.w d1,(Camera_X_pos_coarse_back).w movea.l (Object_index_addr).w,a4 tst.w (Camera_min_Y_pos).w bpl.s loc_1B84A lea loc_1BA40(pc),a6 move.w (Camera_Y_pos).w,d3 andi.w #$FF80,d3 move.w d3,d4 addi.w #$200,d4 subi.w #$80,d3 bpl.s loc_1B83A and.w (Screen_Y_wrap_value).w,d3 bra.s loc_1B864 ; --------------------------------------------------------------------------- loc_1B83A: move.w (Screen_Y_wrap_value).w,d0 addq.w #1,d0 cmp.w d0,d4 bls.s loc_1B860 and.w (Screen_Y_wrap_value).w,d4 bra.s loc_1B864 ; --------------------------------------------------------------------------- loc_1B84A: move.w (Camera_Y_pos).w,d3 andi.w #$FF80,d3 move.w d3,d4 addi.w #$200,d4 subi.w #$80,d3 bpl.s loc_1B860 moveq #0,d3 loc_1B860: lea loc_1BA92(pc),a6 loc_1B864: move.w #$FFF,d5 move.w (Camera_X_pos).w,d6 andi.w #$FF80,d6 cmp.w (Camera_X_pos_coarse).w,d6 beq.w loc_1B91A bge.s loc_1B8D2 move.w d6,(Camera_X_pos_coarse).w movea.l (Object_load_addr_back).w,a0 movea.w (Object_respawn_index_back).w,a3 subi.w #$80,d6 bcs.s loc_1B8A8 jsr AllocateObject(pc) bne.s loc_1B8A8 loc_1B892: cmp.w -6(a0),d6 bge.s loc_1B8A8 subq.w #6,a0 subq.w #1,a3 jsr (a6) bne.s loc_1B8A4 subq.w #6,a0 bra.s loc_1B892 ; --------------------------------------------------------------------------- loc_1B8A4: addq.w #6,a0 addq.w #1,a3 loc_1B8A8: move.l a0,(Object_load_addr_back).w move.w a3,(Object_respawn_index_back).w movea.l (Object_load_addr_front).w,a0 movea.w (Object_respawn_index_front).w,a3 addi.w #$300,d6 loc_1B8BC: cmp.w -6(a0),d6 bgt.s loc_1B8C8 subq.w #6,a0 subq.w #1,a3 bra.s loc_1B8BC ; --------------------------------------------------------------------------- loc_1B8C8: move.l a0,(Object_load_addr_front).w move.w a3,(Object_respawn_index_front).w bra.s loc_1B91A ; --------------------------------------------------------------------------- loc_1B8D2: move.w d6,(Camera_X_pos_coarse).w movea.l (Object_load_addr_front).w,a0 movea.w (Object_respawn_index_front).w,a3 addi.w #$280,d6 jsr AllocateObject(pc) bne.s loc_1B8F2 loc_1B8E8: cmp.w (a0),d6 bls.s loc_1B8F2 jsr (a6) addq.w #1,a3 beq.s loc_1B8E8 loc_1B8F2: move.l a0,(Object_load_addr_front).w move.w a3,(Object_respawn_index_front).w movea.l (Object_load_addr_back).w,a0 movea.w (Object_respawn_index_back).w,a3 subi.w #$300,d6 bcs.s loc_1B912 loc_1B908: cmp.w (a0),d6 bls.s loc_1B912 addq.w #6,a0 addq.w #1,a3 bra.s loc_1B908 ; --------------------------------------------------------------------------- loc_1B912: move.l a0,(Object_load_addr_back).w move.w a3,(Object_respawn_index_back).w loc_1B91A: move.w (Camera_Y_pos).w,d6 andi.w #$FF80,d6 move.w d6,d3 cmp.w (Camera_Y_pos_coarse).w,d6 beq.w loc_1B9FA bge.s loc_1B956 tst.w (Camera_min_Y_pos).w bpl.s loc_1B94C tst.w d6 bne.s loc_1B940 cmpi.w #$80,(Camera_Y_pos_coarse).w bne.s loc_1B968 loc_1B940: subi.w #$80,d3 bpl.s loc_1B982 and.w (Screen_Y_wrap_value).w,d3 bra.s loc_1B982 ; --------------------------------------------------------------------------- loc_1B94C: subi.w #$80,d3 bmi.w loc_1B9FA bra.s loc_1B982 ; --------------------------------------------------------------------------- loc_1B956: tst.w (Camera_min_Y_pos).w bpl.s loc_1B978 tst.w (Camera_Y_pos_coarse).w bne.s loc_1B968 cmpi.w #$80,d6 bne.s loc_1B940 loc_1B968: addi.w #$180,d3 cmp.w (Screen_Y_wrap_value).w,d3 blo.s loc_1B982 and.w (Screen_Y_wrap_value).w,d3 bra.s loc_1B982 ; --------------------------------------------------------------------------- loc_1B978: addi.w #$180,d3 cmp.w (Screen_Y_wrap_value).w,d3 bhi.s loc_1B9FA loc_1B982: jsr AllocateObject(pc) bne.s loc_1B9FA move.w d3,d4 addi.w #$80,d4 move.w #$FFF,d5 movea.l (Object_load_addr_back).w,a0 movea.w (Object_respawn_index_back).w,a3 move.l (Object_load_addr_front).w,d7 sub.l a0,d7 beq.s loc_1B9FA addq.w #2,a0 loc_1B9A4: tst.b (a3) bmi.s loc_1B9F2 move.w (a0),d1 and.w d5,d1 cmp.w d3,d1 blo.s loc_1B9F2 cmp.w d4,d1 bhi.s loc_1B9F2 bset #7,(a3) move.w -2(a0),x_pos(a1) move.w (a0),d1 move.w d1,d2 and.w d5,d1 move.w d1,y_pos(a1) rol.w #3,d2 andi.w #3,d2 move.b d2,render_flags(a1) move.b d2,status(a1) move.b 2(a0),d2 add.w d2,d2 add.w d2,d2 move.l (a4,d2.w),(a1) move.b 3(a0),subtype(a1) move.w a3,respawn_addr(a1) jsr CreateNewSprite4(pc) bne.s loc_1B9FA loc_1B9F2: addq.w #6,a0 addq.w #1,a3 subq.w #6,d7 bne.s loc_1B9A4 loc_1B9FA: move.w d6,(Camera_Y_pos_coarse).w rts ; --------------------------------------------------------------------------- bset #7,(a3) beq.s sub_1BA0C addq.w #6,a0 moveq #0,d1 rts ; =============== S U B R O U T I N E ======================================= sub_1BA0C: move.w (a0)+,x_pos(a1) move.w (a0)+,d1 move.w d1,d2 andi.w #$FFF,d1 move.w d1,y_pos(a1) rol.w #3,d2 andi.w #3,d2 move.b d2,render_flags(a1) move.b d2,status(a1) move.b (a0)+,d2 add.w d2,d2 add.w d2,d2 move.l (a4,d2.w),(a1) move.b (a0)+,subtype(a1) move.w a3,respawn_addr(a1) bra.w CreateNewSprite4 ; --------------------------------------------------------------------------- loc_1BA40: tst.b (a3) bpl.s loc_1BA4A addq.w #6,a0 moveq #0,d1 rts ; --------------------------------------------------------------------------- loc_1BA4A: move.w (a0)+,d7 move.w (a0)+,d1 move.w d1,d2 bmi.s loc_1BA62 and.w d5,d1 cmp.w d3,d1 bhs.s loc_1BA64 cmp.w d4,d1 bls.s loc_1BA64 addq.w #2,a0 moveq #0,d1 rts ; --------------------------------------------------------------------------- loc_1BA62: and.w d5,d1 loc_1BA64: bset #7,(a3) move.w d7,x_pos(a1) move.w d1,y_pos(a1) rol.w #3,d2 andi.w #3,d2 move.b d2,render_flags(a1) move.b d2,status(a1) move.b (a0)+,d2 add.w d2,d2 add.w d2,d2 move.l (a4,d2.w),(a1) move.b (a0)+,subtype(a1) move.w a3,respawn_addr(a1) bra.s CreateNewSprite4 ; --------------------------------------------------------------------------- loc_1BA92: tst.b (a3) bpl.s loc_1BA9C addq.w #6,a0 moveq #0,d1 rts ; --------------------------------------------------------------------------- loc_1BA9C: move.w (a0)+,d7 move.w (a0)+,d1 move.w d1,d2 bmi.s loc_1BAB4 and.w d5,d1 cmp.w d3,d1 blo.s loc_1BAAE cmp.w d4,d1 bls.s loc_1BAB6 loc_1BAAE: addq.w #2,a0 moveq #0,d1 rts ; --------------------------------------------------------------------------- loc_1BAB4: and.w d5,d1 loc_1BAB6: bset #7,(a3) move.w d7,x_pos(a1) move.w d1,y_pos(a1) rol.w #3,d2 andi.w #3,d2 move.b d2,render_flags(a1) move.b d2,status(a1) move.b (a0)+,d2 add.w d2,d2 add.w d2,d2 move.l (a4,d2.w),(a1) move.b (a0)+,subtype(a1) move.w a3,respawn_addr(a1) CreateNewSprite4: subq.w #1,d0 bmi.s locret_1BAF0 loc_1BAE6: lea next_object(a1),a1 tst.l (a1) dbeq d0,loc_1BAE6 locret_1BAF0: rts ; End of function sub_1BA0C ; =============== S U B R O U T I N E ======================================= ; Create_New_Sprite: AllocateObject: lea (Dynamic_object_RAM).w,a1 moveq #((Dynamic_object_RAM_end-Dynamic_object_RAM)/object_size)-1,d0 bra.s AllocateObjectAfterCurrent.loop ; --------------------------------------------------------------------------- ; Create_New_Sprite3: AllocateObjectAfterCurrent: movea.l a0,a1 move.w #Dynamic_object_RAM_end,d0 sub.w a0,d0 lsr.w #6,d0 ; Divide by $40... even though SSTs are $4A bytes long in this game move.b .lookup(pc,d0.w),d0 ; Use a look-up table to get the right loop counter bmi.s .return .loop: lea next_object(a1),a1 tst.l (a1) dbeq d0,.loop .return: rts .lookup: .a set Dynamic_object_RAM .b set Dynamic_object_RAM_end .c set .b ; begin from bottom of array and decrease backwards ; There's a mistake here: this division should be rounded up, ; otherwise the first object slot might not get an entry. rept (.b-.a)/$40 ; repeat for all slots, minus exception .c set .c-$40 ; address for previous $40 (also skip last part) dc.b (.b-.c-1)/object_size-1 ; write possible slots according to object_size division + hack + dbf hack endm even ; End of function AllocateObject ; --------------------------------------------------------------------------- Clear_SpriteRingMem: lea (Dynamic_object_RAM).w,a1 moveq #((Dynamic_object_RAM_end-Dynamic_object_RAM)/object_size)-1,d1 loc_1BB84: lea next_object(a1),a1 tst.l (a1) beq.s loc_1BB98 move.w respawn_addr(a1),d0 beq.s loc_1BB98 movea.w d0,a2 bclr #7,(a2) loc_1BB98: dbf d1,loc_1BB84 lea (Ring_consumption_table).w,a2 move.w (a2)+,d1 subq.w #1,d1 bcs.s locret_1BBBC loc_1BBA6: move.w (a2)+,d0 beq.s loc_1BBA6 movea.w d0,a1 move.w #-1,(a1) clr.w -2(a2) subq.w #1,(Ring_consumption_table).w dbf d1,loc_1BBA6 locret_1BBBC: rts ; --------------------------------------------------------------------------- ; =============== S U B R O U T I N E ======================================= ; Changes the coarse back- and forward-camera edges to match new Camera_X value. ; Also seeks to appropriate object locations in the level's object layout, so ; that Load_Sprites will correctly load the objects again. Seek_Object_Manager: move.w (Camera_X_pos).w,d6 addi.w #$400,d6 andi.w #$FF80,d6 cmp.w (Camera_X_pos_coarse).w,d6 beq.w locret_1BC5E bge.s loc_1BC1C move.w d6,(Camera_X_pos_coarse).w movea.l (Object_load_addr_back).w,a1 movea.w (Object_respawn_index_back).w,a3 subi.w #$80,d6 bcs.s loc_1BBF2 loc_1BBE6: cmp.w -6(a1),d6 bge.s loc_1BBF2 subq.w #6,a1 subq.w #1,a3 bra.s loc_1BBE6 ; --------------------------------------------------------------------------- loc_1BBF2: move.l a1,(Object_load_addr_back).w move.w a3,(Object_respawn_index_back).w movea.l (Object_load_addr_front).w,a1 movea.w (Object_respawn_index_front).w,a3 addi.w #$300,d6 loc_1BC06: cmp.w -6(a1),d6 bgt.s loc_1BC12 subq.w #6,a1 subq.w #1,a3 bra.s loc_1BC06 ; --------------------------------------------------------------------------- loc_1BC12: move.l a1,(Object_load_addr_front).w move.w a3,(Object_respawn_index_front).w bra.s locret_1BC5E ; --------------------------------------------------------------------------- loc_1BC1C: move.w d6,(Camera_X_pos_coarse).w movea.l (Object_load_addr_front).w,a1 movea.w (Object_respawn_index_front).w,a3 addi.w #$280,d6 loc_1BC2C: cmp.w (a1),d6 bls.s loc_1BC36 addq.w #6,a1 addq.w #1,a3 bra.s loc_1BC2C ; --------------------------------------------------------------------------- loc_1BC36: move.l a1,(Object_load_addr_front).w move.w a3,(Object_respawn_index_front).w movea.l (Object_load_addr_back).w,a1 movea.w (Object_respawn_index_back).w,a3 subi.w #$300,d6 bcs.s loc_1BC56 loc_1BC4C: cmp.w (a1),d6 bls.s loc_1BC56 addq.w #6,a1 addq.w #1,a3 bra.s loc_1BC4C ; --------------------------------------------------------------------------- loc_1BC56: move.l a1,(Object_load_addr_back).w move.w a3,(Object_respawn_index_back).w locret_1BC5E: rts ; =============== S U B R O U T I N E ======================================= Get_LevelSizeStart: clr.b (Deform_lock).w clr.b (_unkEE08).w clr.b (Scroll_lock).w clr.b (Scroll_lock_P2).w clr.b (Fast_V_scroll_flag).w moveq #0,d0 move.b d0,(Dynamic_resize_routine).w move.w d0,(_unkF660).w move.w d0,(_unkF662).w move.w (Current_zone_and_act).w,d0 ror.b #1,d0 lsr.w #4,d0 lea LevelSizes(pc,d0.w),a0 move.l (a0)+,d0 move.l d0,(Camera_min_X_pos).w move.l d0,(Camera_target_min_X_pos).w move.l d0,(Camera_min_X_pos_P2).w move.l (a0)+,d0 move.l d0,(Camera_min_Y_pos).w move.l d0,(Camera_target_min_Y_pos).w move.l d0,(Camera_min_Y_pos_P2).w move.w #$60,(Distance_from_top).w move.w #$60,(Distance_from_top_P2).w move.w #-1,(Screen_X_wrap_value).w move.w #-1,(Screen_Y_wrap_value).w bra.w loc_1BE46 ; --------------------------------------------------------------------------- LevelSizes: ; xstart xend ystart yend ; Level dc.w $1308, $6000, 0, $390 ; AIZ1 dc.w 0, $4640, 0, $590 ; AIZ2 dc.w 0, $6000, 0, $1000 ; HCZ1 dc.w 0, $6000, 0, $1000 ; HCZ2 dc.w 0, $6000, -$100, $1000 ; MGZ1 dc.w 0, $6000, 0, $1000 ; MGZ2 dc.w 0, $6000, 0, $B20 ; CNZ1 dc.w 0, $6000, $580, $1000 ; CNZ2 dc.w 0, $2E60, 0, $B00 ; FBZ1 dc.w 0, $6000, 0, $B00 ; FBZ2 dc.w 0, $7000, -$100, $800 ; ICZ1 dc.w 0, $7000, 0, $B20 ; ICZ2 dc.w 0, $6000, 0, $1000 ; LBZ1 dc.w 0, $6000, 0, $B20 ; LBZ2 dc.w 0, $4298, 0, $AA0 ; MHZ1 dc.w $98, $3C90, $620, $9A0 ; MHZ2 dc.w 0, $4310, 0, $B20 ; SOZ1 dc.w 0, $6000, -$100, $800 ; SOZ2 dc.w 0, $2CC0, 0, $B20 ; LRZ1 dc.w $940, $3EC0, 0, $B20 ; LRZ2 dc.w 0, $19A0, -$100, $1000 ; SSZ1 dc.w 0, $6000, 0, $400 ; SSZ2 dc.w 0, $6000, 0, $B20 ; DEZ1 dc.w 0, $6000, 0, $F10 ; DEZ2 dc.w 0, $6000, 0, $1000 ; DDZ dc.w 0, $6000, 0, $1000 ; DDZ dc.w 0, $6000, 0, $1000 ; AIZ Intro (?) dc.w 0, $6000, 0, $1000 ; Ending scene dc.w 0, $12C0, $100, $190 ; ALZ dc.w 0, $12C0, $100, $190 ; ALZ dc.w 0, $12C0, $200, $390 ; BPZ dc.w 0, $12C0, $200, $390 ; BPZ dc.w 0, $12C0, $100, $190 ; DPZ dc.w 0, $12C0, $100, $190 ; DPZ dc.w 0, $12C0, -$100, $1000 ; CGZ dc.w 0, $12C0, 0, $90 ; CGZ dc.w 0, $12C0, $100, $190 ; EMZ dc.w 0, $12C0, $100, $190 ; EMZ dc.w $60, $60, 0, $240 ; Gumball dc.w $60, $60, 0, $240 ; Gumball dc.w 0, $140, 0, $F00 ; Pachinko dc.w 0, $140, 0, $F00 ; Pachinko dc.w 0, $6000, 0, $1000 ; Slots dc.w 0, $6000, 0, $1000 ; Slots dc.w 0, $EC0, 0, $430 ; LRZ Boss dc.w 0, $1880, 0, $B20 ; HPZ dc.w 0, $6000, $20, $20 ; DEZ Boss dc.w $1500, $1640, $320, $320 ; Special Stage Arena (HPZ) ; --------------------------------------------------------------------------- loc_1BE46: tst.b (Last_star_post_hit).w beq.s loc_1BE5E jsr (Load_Starpost_Settings).l move.w (Player_1+x_pos).w,d1 move.w (Player_1+y_pos).w,d0 bra.w loc_1BF74 ; --------------------------------------------------------------------------- loc_1BE5E: move.w (Current_zone_and_act).w,d0 ror.b #1,d0 lsr.w #5,d0 lea (Sonic_Start_Locations).l,a1 cmpi.w #3,(Player_mode).w bne.s loc_1BE7A lea (Knux_Start_Locations).l,a1 loc_1BE7A: lea (a1,d0.w),a1 moveq #0,d1 move.w (a1)+,d1 move.w d1,(Player_1+x_pos).w moveq #0,d0 move.w (a1),d0 move.w d0,(Player_1+y_pos).w tst.b (Last_star_post_hit).w bne.w loc_1BF74 cmpi.w #0,(Current_zone_and_act).w bne.s loc_1BEC6 cmpi.w #2,(Player_mode).w bhs.s loc_1BEC6 move.w #$40,d1 ; If in Angel Island Zone and playing as Sonic, the start position is overridden for the intro move.w d1,(Player_1+x_pos).w move.w #$420,d0 move.w d0,(Player_1+y_pos).w move.w #0,d1 move.w d1,(Camera_min_X_pos).w move.w d1,(Camera_target_min_X_pos).w move.w d1,(Camera_min_X_pos_P2).w loc_1BEC6: cmpi.w #$500,(Current_zone_and_act).w bne.s loc_1BF1E cmpi.w #2,(Player_mode).w blo.s loc_1BF1E bne.s loc_1BF1E move.w #$35A0,d1 ; If in Ice Cap Act 1 and playing as Tails, move.w d1,(Camera_min_X_pos).w ; we use a different start position and different level sizes move.w d1,(Camera_target_min_X_pos).w ; to skip the snowboarding sequence move.w d1,(Camera_min_X_pos_P2).w move.w #$3780,d1 move.w d1,(Player_1+x_pos).w move.w #$36F0,d1 move.w d1,(Camera_X_pos).w move.w d1,(Camera_X_pos_P2).w move.w #$1E0,d0 move.w d0,(Player_1+y_pos).w move.w #$200,d0 move.w d0,(Camera_min_Y_pos).w move.w d0,(Camera_target_min_Y_pos).w move.w d0,(Camera_min_Y_pos_P2).w move.w d0,(Camera_Y_pos).w move.w d0,(Camera_Y_pos_P2).w rts ; --------------------------------------------------------------------------- loc_1BF1E: cmpi.w #$700,(Current_zone_and_act).w bne.s loc_1BF48 cmpi.w #3,(Player_mode).w bhs.s loc_1BF48 tst.w (SK_alone_flag).w bne.s loc_1BF48 move.w #$C0,d2 ; If playing as Sonic/Tails in MHZ 1 with Sonic 3 locked on, modify level size move.w d2,(Camera_min_X_pos).w move.w d2,(Camera_target_min_X_pos).w move.w d2,(Camera_min_X_pos_P2).w move.w #$160,d1 loc_1BF48: cmpi.w #$1601,(Current_zone_and_act).w beq.s loc_1BF70 cmpi.w #$B00,(Current_zone_and_act).w beq.s loc_1BF70 cmpi.w #$900,(Current_zone_and_act).w beq.s loc_1BF68 cmpi.w #$300,(Current_zone_and_act).w bne.s loc_1BF74 loc_1BF68: cmpi.w #3,(Player_mode).w bne.s loc_1BF74 loc_1BF70: addi.w #$B0,d1 ; Only if in Hidden Palace, in Death Egg 1, in Lava Reef 1 as Knuckles, in Carnival Night 1 as Knuckles ; This is likely for level intros that start behind the camera loc_1BF74: subi.w #$A0,d1 bcc.s loc_1BF7C moveq #0,d1 loc_1BF7C: tst.w (Competition_mode).w bne.s loc_1BF8C move.w (Camera_max_X_pos).w,d2 cmp.w d2,d1 blo.s loc_1BF8C move.w d2,d1 loc_1BF8C: move.w d1,(Camera_X_pos).w move.w d1,(Camera_X_pos_P2).w subi.w #$60,d0 bcc.s loc_1BF9C moveq #0,d0 loc_1BF9C: cmp.w (Camera_max_Y_pos).w,d0 blt.s loc_1BFA6 move.w (Camera_max_Y_pos).w,d0 loc_1BFA6: move.w d0,(Camera_Y_pos).w move.w d0,(Camera_Y_pos_P2).w rts ; End of function Get_LevelSizeStart ; =============== S U B R O U T I N E ======================================= DeformBgLayer: tst.b (Deform_lock).w beq.s loc_1BFB8 rts ; --------------------------------------------------------------------------- loc_1BFB8: clr.w (Camera_RAM).w clr.w (V_scroll_amount).w clr.w (H_scroll_amount_P2).w clr.w (V_scroll_amount_P2).w tst.w (Competition_mode).w bne.w loc_1C02C tst.b (Scroll_lock).w bne.s loc_1C028 lea (Player_1).w,a0 tst.b (Scroll_force_positions).w beq.s loc_1BFF0 move.b #0,(Scroll_force_positions).w move.w #0,(H_scroll_frame_offset).w lea (Palette_frame_Tails).w,a0 loc_1BFF0: lea (Camera_X_pos).w,a1 lea (Camera_min_X_pos).w,a2 lea (Camera_RAM).w,a4 lea (H_scroll_frame_offset).w,a5 lea (Pos_table).w,a6 bsr.w MoveCameraX lea (Camera_Y_pos).w,a1 lea (Camera_min_X_pos).w,a2 lea (V_scroll_amount).w,a4 move.w (Distance_from_top).w,d3 cmpi.w #2,(Player_mode).w bne.s loc_1C024 move.w (Distance_from_top_P2).w,d3 loc_1C024: bsr.w MoveCameraY loc_1C028: bra.w Do_ResizeEvents ; --------------------------------------------------------------------------- loc_1C02C: tst.b (Scroll_lock).w bne.s loc_1C06E lea (Player_1).w,a0 lea (Camera_X_pos).w,a1 lea (Camera_min_X_pos).w,a2 lea (Camera_RAM).w,a4 lea (H_scroll_frame_offset).w,a5 lea (Pos_table).w,a6 bsr.w MoveCameraX_2P lea (Camera_Y_pos).w,a1 lea (Camera_min_X_pos).w,a2 lea (V_scroll_amount).w,a4 move.w (Distance_from_top).w,d3 cmpi.w #2,(Player_mode).w bne.s loc_1C06A move.w (Distance_from_top_P2).w,d3 loc_1C06A: bsr.w MoveCameraY loc_1C06E: tst.b (Scroll_lock_P2).w bne.s loc_1C0A4 lea (Player_2).w,a0 lea (Camera_X_pos_P2).w,a1 lea (Camera_min_X_pos_P2).w,a2 lea (H_scroll_amount_P2).w,a4 lea (H_scroll_frame_offset_P2).w,a5 lea (Stat_table).w,a6 bsr.w MoveCameraX_2P lea (Camera_Y_pos_P2).w,a1 lea (Camera_min_X_pos_P2).w,a2 lea (V_scroll_amount_P2).w,a4 move.w (Distance_from_top_P2).w,d3 bsr.w MoveCameraY loc_1C0A4: bra.w Do_ResizeEvents ; End of function DeformBgLayer ; =============== S U B R O U T I N E ======================================= MoveCameraX: move.w (a1),d4 tst.b (Teleport_active_flag).w bne.s locret_1C0E6 move.w (a5),d1 beq.s loc_1C0D2 subi.w #$100,d1 move.w d1,(a5) moveq #0,d1 move.b (a5),d1 lsl.b #2,d1 addq.b #4,d1 move.w 2(a5),d0 sub.b d1,d0 move.w (a6,d0.w),d0 andi.w #$7FFF,d0 bra.s loc_1C0D6 ; --------------------------------------------------------------------------- loc_1C0D2: move.w x_pos(a0),d0 loc_1C0D6: sub.w (a1),d0 subi.w #$90,d0 blt.s loc_1C0E8 subi.w #$10,d0 bge.s loc_1C0FC clr.w (a4) locret_1C0E6: rts ; --------------------------------------------------------------------------- loc_1C0E8: cmpi.w #-$18,d0 bgt.s loc_1C0F2 move.w #-$18,d0 loc_1C0F2: add.w (a1),d0 cmp.w (a2),d0 bgt.s loc_1C112 move.w (a2),d0 bra.s loc_1C112 ; --------------------------------------------------------------------------- loc_1C0FC: cmpi.w #$18,d0 blo.s loc_1C106 move.w #$18,d0 loc_1C106: add.w (a1),d0 cmp.w 2(a2),d0 blt.s loc_1C112 move.w 2(a2),d0 loc_1C112: move.w d0,d1 sub.w (a1),d1 asl.w #8,d1 move.w d0,(a1) move.w d1,(a4) rts ; End of function MoveCameraX ; =============== S U B R O U T I N E ======================================= MoveCameraY: moveq #0,d1 move.w y_pos(a0),d0 sub.w (a1),d0 cmpi.w #-$100,(Camera_min_Y_pos).w bne.s loc_1C132 and.w (Screen_Y_wrap_value).w,d0 loc_1C132: btst #Status_Roll,status(a0) beq.s loc_1C13C subq.w #5,d0 loc_1C13C: move.w d3,d1 tst.w (Competition_mode).w beq.s loc_1C146 lsr.w #1,d1 loc_1C146: btst #Status_InAir,status(a0) beq.s loc_1C164 addi.w #$20,d0 sub.w d1,d0 bcs.s loc_1C1B0 subi.w #$40,d0 bcc.s loc_1C1B0 tst.b (Camera_max_Y_pos_changing).w bne.s loc_1C1C2 bra.s loc_1C16E ; --------------------------------------------------------------------------- loc_1C164: sub.w d1,d0 bne.s loc_1C172 tst.b (Camera_max_Y_pos_changing).w bne.s loc_1C1C2 loc_1C16E: clr.w (a4) rts ; --------------------------------------------------------------------------- loc_1C172: cmpi.w #$60,d3 bne.s loc_1C19E tst.b (Fast_V_scroll_flag).w bne.s loc_1C1B0 move.w ground_vel(a0),d1 bpl.s loc_1C186 neg.w d1 loc_1C186: cmpi.w #$800,d1 bhs.s loc_1C1B0 move.w #$600,d1 cmpi.w #6,d0 bgt.s loc_1C1FA cmpi.w #-6,d0 blt.s loc_1C1D8 bra.s loc_1C1C8 ; --------------------------------------------------------------------------- loc_1C19E: move.w #$200,d1 cmpi.w #2,d0 bgt.s loc_1C1FA cmpi.w #-2,d0 blt.s loc_1C1D8 bra.s loc_1C1C8 ; --------------------------------------------------------------------------- loc_1C1B0: move.w #$1800,d1 cmpi.w #$18,d0 bgt.s loc_1C1FA cmpi.w #-$18,d0 blt.s loc_1C1D8 bra.s loc_1C1C8 ; --------------------------------------------------------------------------- loc_1C1C2: moveq #0,d0 move.b d0,(Camera_max_Y_pos_changing).w loc_1C1C8: moveq #0,d1 move.w d0,d1 add.w (a1),d1 tst.w d0 bpl.w loc_1C202 bra.w loc_1C1E2 ; --------------------------------------------------------------------------- loc_1C1D8: neg.w d1 ext.l d1 asl.l #8,d1 add.l (a1),d1 swap d1 loc_1C1E2: cmp.w 4(a2),d1 bgt.s loc_1C21A cmpi.w #-$100,d1 bgt.s loc_1C1F4 and.w (Screen_Y_wrap_value).w,d1 bra.s loc_1C21A ; --------------------------------------------------------------------------- loc_1C1F4: move.w 4(a2),d1 bra.s loc_1C21A ; --------------------------------------------------------------------------- loc_1C1FA: ext.l d1 asl.l #8,d1 add.l (a1),d1 swap d1 loc_1C202: cmp.w 6(a2),d1 blt.s loc_1C21A move.w (Screen_Y_wrap_value).w,d3 addq.w #1,d3 sub.w d3,d1 bcs.s loc_1C216 sub.w d3,(a1) bra.s loc_1C21A ; --------------------------------------------------------------------------- loc_1C216: move.w 6(a2),d1 loc_1C21A: move.w (a1),d4 swap d1 move.l d1,d3 sub.l (a1),d3 ror.l #8,d3 move.w d3,(a4) move.l d1,(a1) tst.w (Competition_mode).w beq.s locret_1C236 swap d1 and.w (Screen_Y_wrap_value).w,d1 move.w d1,(a1) locret_1C236: rts ; End of function MoveCameraY ; =============== S U B R O U T I N E ======================================= MoveCameraX_2P: move.w (a1),d4 tst.b (Teleport_active_flag).w bne.s locret_1C27C move.w (a5),d1 beq.s loc_1C262 subi.w #$100,d1 move.w d1,(a5) moveq #0,d1 move.b (a5),d1 lsl.b #2,d1 addq.b #4,d1 move.w 2(a5),d0 sub.b d1,d0 move.w (a6,d0.w),d0 andi.w #$7FFF,d0 bra.s loc_1C266 ; --------------------------------------------------------------------------- loc_1C262: move.w x_pos(a0),d0 loc_1C266: move.w (Screen_X_wrap_value).w,d2 sub.w (a1),d0 and.w d2,d0 subi.w #$90,d0 blt.s loc_1C27E subi.w #$10,d0 bge.s loc_1C28C clr.w (a4) locret_1C27C: rts ; --------------------------------------------------------------------------- loc_1C27E: cmpi.w #-$10,d0 bgt.s loc_1C288 move.w #-$10,d0 loc_1C288: add.w (a1),d0 bra.s loc_1C298 ; --------------------------------------------------------------------------- loc_1C28C: cmpi.w #$10,d0 blo.s loc_1C296 move.w #$10,d0 loc_1C296: add.w (a1),d0 loc_1C298: move.w d0,d1 sub.w (a1),d1 asl.w #8,d1 and.w d2,d0 addi.w #$400,d0 move.w d0,(a1) move.w d1,(a4) rts ; End of function MoveCameraX_2P ; =============== S U B R O U T I N E ======================================= j_LevelSetup: jmp (LevelSetup).l ; End of function j_LevelSetup ; =============== S U B R O U T I N E ======================================= LoadLevelLoadBlock2: move.w (Current_zone_and_act).w,d0 bne.s loc_1C2C8 cmpi.w #2,(Player_mode).w bhs.s loc_1C2C4 tst.b (Last_star_post_hit).w beq.s loc_1C2C8 loc_1C2C4: move.w #$D00,d0 loc_1C2C8: ror.b #1,d0 lsr.w #4,d0 andi.w #$1F8,d0 move.w d0,d1 add.w d0,d0 add.w d1,d0 lea (LevelLoadBlock).l,a2 lea (a2,d0.w),a2 move.l a2,-(sp) addq.w #8,a2 move.l (a2)+,d0 andi.l #$FFFFFF,d0 move.l d0,d7 movea.l d0,a0 lea (Block_table).w,a1 jsr (Kos_Decomp).l move.l (a2)+,d0 andi.l #$FFFFFF,d0 cmp.l d0,d7 beq.s loc_1C30E movea.l d0,a0 jsr (Kos_Decomp).l loc_1C30E: move.l (a2)+,d0 andi.l #$FFFFFF,d0 move.l d0,d7 movea.l d0,a0 lea (RAM_start).l,a1 jsr (Kos_Decomp).l move.l (a2)+,d0 andi.l #$FFFFFF,d0 cmp.l d0,d7 beq.s loc_1C33A movea.l d0,a0 jsr (Kos_Decomp).l loc_1C33A: bsr.w Load_Level movea.l (sp)+,a2 move.b (a2),d1 addq.w #4,a2 moveq #0,d0 move.b (a2),d0 beq.s loc_1C354 cmp.b d0,d1 beq.s loc_1C354 jsr (Load_PLC).l loc_1C354: addq.w #4,a2 moveq #0,d0 move.b (a2),d0 jsr (LoadPalette).l rts ; End of function LoadLevelLoadBlock2 ; =============== S U B R O U T I N E ======================================= Load_Level: moveq #0,d0 move.w (Current_zone_and_act).w,d0 ror.b #1,d0 lsr.w #5,d0 andi.w #$FC,d0 lea (LevelPtrs).l,a0 movea.l (a0,d0.w),a0 lea (Level_layout_header).w,a1 move.w #bytesToWcnt($1000),d2 .loop: move.w (a0)+,(a1)+ dbf d2,.loop rts ; End of function Load_Level ; --------------------------------------------------------------------------- Do_ResizeEvents: moveq #0,d0 move.w (Current_zone_and_act).w,d0 ror.b #1,d0 lsr.w #6,d0 ; Bug: this clamps the array index too hard, causing Competition and bonus ; stages to execute resize routines meant for the early game levels andi.w #$3E,d0 move.w LevelResizeArray(pc,d0.w),d0 jsr LevelResizeArray(pc,d0.w) moveq #2,d1 move.w (Camera_target_max_Y_pos).w,d0 sub.w (Camera_max_Y_pos).w,d0 beq.s locret_1C3CE bcc.s loc_1C3D0 neg.w d1 move.w (Camera_Y_pos).w,d0 cmp.w (Camera_target_max_Y_pos).w,d0 bls.s loc_1C3C4 move.w d0,(Camera_max_Y_pos).w andi.w #$FFFE,(Camera_max_Y_pos).w loc_1C3C4: add.w d1,(Camera_max_Y_pos).w move.b #1,(Camera_max_Y_pos_changing).w locret_1C3CE: rts ; --------------------------------------------------------------------------- loc_1C3D0: move.w (Camera_Y_pos).w,d0 addi.w #8,d0 cmp.w (Camera_max_Y_pos).w,d0 blo.s loc_1C3EA btst #1,(Player_1+status).w beq.s loc_1C3EA add.w d1,d1 add.w d1,d1 loc_1C3EA: add.w d1,(Camera_max_Y_pos).w move.b #1,(Camera_max_Y_pos_changing).w rts ; --------------------------------------------------------------------------- LevelResizeArray: dc.w AIZ1_Resize-LevelResizeArray dc.w AIZ2_Resize-LevelResizeArray dc.w HCZ1_Resize-LevelResizeArray dc.w HCZ2_Resize-LevelResizeArray dc.w MGZ1_Resize-LevelResizeArray dc.w MGZ2_Resize-LevelResizeArray dc.w CNZ1_Resize-LevelResizeArray dc.w CNZ2_Resize-LevelResizeArray dc.w FBZ1_Resize-LevelResizeArray dc.w FBZ2_Resize-LevelResizeArray dc.w ICZ1_Resize-LevelResizeArray dc.w ICZ2_Resize-LevelResizeArray dc.w LBZ1_Resize-LevelResizeArray dc.w LBZ2_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray dc.w No_Resize-LevelResizeArray ; --------------------------------------------------------------------------- AIZ1_Resize: moveq #0,d0 move.b (Dynamic_resize_routine).w,d0 move.w AIZ1_Resize_Index(pc,d0.w),d0 jmp AIZ1_Resize_Index(pc,d0.w) ; --------------------------------------------------------------------------- AIZ1_Resize_Index: dc.w loc_1C46E-AIZ1_Resize_Index dc.w loc_1C4D0-AIZ1_Resize_Index dc.w loc_1C550-AIZ1_Resize_Index dc.w loc_1C5C6-AIZ1_Resize_Index dc.w loc_1C602-AIZ1_Resize_Index ; --------------------------------------------------------------------------- loc_1C46E: move.b #1,(AIZ1_palette_cycle_flag).w cmpi.w #$1000,(Camera_X_pos).w blo.s locret_1C4CE move.b #0,(AIZ1_palette_cycle_flag).w move.w (Camera_X_pos).w,(Camera_min_X_pos).w cmpi.w #$1308,(Camera_X_pos).w blo.s locret_1C4CE tst.b (Last_star_post_hit).w bne.s loc_1C4A6 cmpi.w #2,(Player_mode).w bhs.s loc_1C4A6 moveq #$B,d0 jsr (Load_PLC).l loc_1C4A6: moveq #$2A,d0 jsr (LoadPalette_Immediate).l cmpi.w #3,(Player_mode).w bne.s loc_1C4C4 lea (Normal_palette_line_4+$10).w,a1 lea (word_4FAE4).l,a2 move.l (a2)+,(a1)+ move.l (a2),(a1) loc_1C4C4: move.w #2,(Tails_CPU_routine).w addq.b #2,(Dynamic_resize_routine).w locret_1C4CE: rts ; --------------------------------------------------------------------------- loc_1C4D0: move.w #$1308,(Camera_min_X_pos).w cmpi.w #$1400,(Camera_X_pos).w blo.s locret_1C54E tst.b (Last_star_post_hit).w bne.s loc_1C522 cmpi.w #2,(Player_mode).w bhs.s loc_1C522 lea (AIZ1_16x16_MainLevel_Kos).l,a1 lea (Block_table+$268).w,a2 jsr (Queue_Kos).l lea (AIZ1_8x8_MainLevel_KosM).l,a1 move.w #tiles_to_bytes($0BE),d2 jsr (Queue_Kos_Module).l st (Events_fg_5).w move.w #$500,(Anim_Counters).w move.w #$500,(Anim_Counters+2).w move.w #$500,(Anim_Counters+4).w loc_1C522: move.b #1,(Last_star_post_hit).w move.w #$13A0,(Saved_X_pos).w move.w #$41A,(Saved_Y_pos).w jsr (Save_Level_Data).l move.l #0,(Saved_timer).w moveq #8,d0 jsr (Load_PLC).l addq.b #2,(Dynamic_resize_routine).w locret_1C54E: rts ; --------------------------------------------------------------------------- loc_1C550: lea (word_1C60A).l,a1 bsr.w Resize_MaxYFromX move.w #0,(Camera_min_Y_pos).w move.w #$20E,(Target_palette_line_3+$1E).w tst.b (Game_mode).w bmi.s loc_1C578 tst.w (Palette_fade_timer).w bne.s loc_1C578 move.w #$20E,(Normal_palette_line_3+$1E).w loc_1C578: cmpi.w #$2B00,(Camera_X_pos).w blo.s loc_1C586 move.w #4,(Normal_palette_line_3+$1E).w loc_1C586: cmpi.w #$2C00,(Camera_X_pos).w blo.s loc_1C594 move.w #$2E0,(Camera_min_Y_pos).w loc_1C594: cmpi.w #$2D80,(Camera_X_pos).w blo.s locret_1C5C4 move.w #$C02,d0 cmpi.w #3,(Player_mode).w bne.s loc_1C5AE move.w (word_4FAEA).l,d0 loc_1C5AE: move.w d0,(Normal_palette_line_3+$1E).w move.w #$2D80,(Camera_min_X_pos).w moveq #$5A,d0 jsr (Load_PLC).l addq.b #2,(Dynamic_resize_routine).w locret_1C5C4: rts ; --------------------------------------------------------------------------- loc_1C5C6: lea (word_1C60A).l,a1 bsr.w Resize_MaxYFromX move.w (Camera_X_pos).w,(Camera_min_X_pos).w cmpi.w #$2E00,(Camera_X_pos).w blo.s locret_1C600 tst.b (Kos_modules_left).w bne.s locret_1C600 lea (AIZ1_8x8_Flames_KosM).l,a1 move.w #tiles_to_bytes($500),d2 jsr (Queue_Kos_Module).l moveq #$C,d0 jsr (Load_PLC).l addq.b #2,(Dynamic_resize_routine).w locret_1C600: rts ; --------------------------------------------------------------------------- loc_1C602: move.w (Camera_X_pos).w,(Camera_min_X_pos).w rts ; --------------------------------------------------------------------------- word_1C60A: dc.w $8390, $1650 dc.w $83B0, $1B00 dc.w $8430, $2000 dc.w $84C0, $2B00 dc.w $83B0, $2D80 dc.w $82E0, $FFFF ; --------------------------------------------------------------------------- AIZ2_Resize: moveq #0,d0 move.b (Dynamic_resize_routine).w,d0 move.w AIZ2_Resize_Index(pc,d0.w),d0 jmp AIZ2_Resize_Index(pc,d0.w) ; --------------------------------------------------------------------------- AIZ2_Resize_Index: dc.w loc_1C64E-AIZ2_Resize_Index ; 0 dc.w AIZ2_SonicResize1-AIZ2_Resize_Index ; 2 dc.w AIZ2_SonicResize2-AIZ2_Resize_Index ; 4 dc.w AIZ2_SonicResize3-AIZ2_Resize_Index ; 6 dc.w AIZ2_SonicResize4-AIZ2_Resize_Index ; 8 dc.w AIZ2_SonicResize5-AIZ2_Resize_Index ; A dc.w AIZ2_SonicResize6-AIZ2_Resize_Index ; C dc.w AIZ2_SonicResize7-AIZ2_Resize_Index ; E dc.w AIZ2_SonicResizeEnd-AIZ2_Resize_Index ; 10 dc.w AIZ2_KnuxResize1-AIZ2_Resize_Index ; 12 dc.w AIZ2_KnuxResize2-AIZ2_Resize_Index ; 14 dc.w AIZ2_KnuxResize3-AIZ2_Resize_Index ; 16 dc.w AIZ2_KnuxResize4-AIZ2_Resize_Index ; 18 dc.w AIZ2_KnuxResize5-AIZ2_Resize_Index ; 1A dc.w AIZ2_KnuxResizeEnd-AIZ2_Resize_Index ; 1C ; --------------------------------------------------------------------------- loc_1C64E: cmpi.w #3,(Player_mode).w bne.s loc_1C660 move.b #$12,(Dynamic_resize_routine).w ; If playing as Knuckles bra.w AIZ2_KnuxResize1 ; --------------------------------------------------------------------------- loc_1C660: addq.b #2,(Dynamic_resize_routine).w AIZ2_SonicResize1: cmpi.w #$2E0,(Camera_X_pos).w blo.s locret_1C68E move.w #$590,d0 move.w d0,(Camera_max_Y_pos).w move.w d0,(Camera_target_max_Y_pos).w addq.b #2,(Dynamic_resize_routine).w ; Set level height to normal when past the open field cmpi.w #1,(Apparent_zone_and_act).w ; If non-internal level is not AIZ2, then the miniboss hasn't been defeated yet bne.s locret_1C68E move.w #$F50,(Camera_min_X_pos).w ; Put $F50 as the start X addq.b #2,(Dynamic_resize_routine).w locret_1C68E: rts ; --------------------------------------------------------------------------- AIZ2_SonicResize2: move.w #$590,d0 cmpi.w #$ED0,(Camera_X_pos).w blo.s loc_1C6A0 move.w #$2B8,d0 ; Set level height to 2B8 when boss is approached. loc_1C6A0: move.w d0,(Camera_max_Y_pos).w move.w d0,(Camera_target_max_Y_pos).w cmpi.w #$F50,(Camera_X_pos).w blo.s locret_1C6DA move.w #$F50,(Camera_min_X_pos).w ; When boss has been reached, lock the screen tst.w (Debug_placement_mode).w ; If in debug mode, don't load boss bne.s loc_1C6D6 jsr (AllocateObject).l bne.s loc_1C6D6 move.l #Obj_AIZMiniboss,(a1) ; Make the miniboss move.w #$11F0,x_pos(a1) move.w #$289,y_pos(a1) ; Set the position for Sonic's area area loc_1C6D6: addq.b #2,(Dynamic_resize_routine).w locret_1C6DA: rts ; --------------------------------------------------------------------------- AIZ2_SonicResize3: cmpi.w #$1500,(Camera_X_pos).w blo.s locret_1C6F4 move.w #$630,(Camera_max_Y_pos).w ; Set the level height to $630 when playing as Sonic past $1500 move.w #$630,(Camera_target_max_Y_pos).w addq.b #2,(Dynamic_resize_routine).w locret_1C6F4: rts ; --------------------------------------------------------------------------- AIZ2_SonicResize4: cmpi.w #$3C00,(Camera_X_pos).w blo.s locret_1C744 tst.b (Kos_modules_left).w ; When $3C00 X is passed bne.s locret_1C744 lea (AIZ2_16x16_BomberShip_Kos).l,a1 ; If KosM queue is clear lea (Block_table+$AB8).w,a2 jsr (Queue_Kos).l lea (AIZ2_8x8_BomberShip_KosM).l,a1 move.w #tiles_to_bytes($1FC),d2 jsr (Queue_Kos_Module).l lea (ArtKosM_AIZ2Bombership2_8x8).l,a1 move.w #tiles_to_bytes($500),d2 jsr (Queue_Kos_Module).l ; Load all battleship art moveq #$30,d0 jsr (LoadPalette_Immediate).l ; Load palette st (Events_fg_5).w ; Send signal to background event addq.b #2,(Dynamic_resize_routine).w locret_1C744: rts ; --------------------------------------------------------------------------- AIZ2_SonicResize5: cmpi.w #$3F00,(Camera_X_pos).w blo.s locret_1C75E move.w #$15A,d0 ; When past $3F00 X, set top of level to $15A move.w d0,(Camera_min_Y_pos).w move.w d0,(Camera_target_min_Y_pos).w addq.b #2,(Dynamic_resize_routine).w locret_1C75E: rts ; --------------------------------------------------------------------------- AIZ2_SonicResize6: cmpi.w #$4000,(Camera_X_pos).w blo.s locret_1C778 move.w #$15A,d0 move.w d0,(Camera_max_Y_pos).w ; When past $4000 X, set bottom of level to $15A move.w d0,(Camera_target_max_Y_pos).w addq.b #2,(Dynamic_resize_routine).w locret_1C778: rts ; --------------------------------------------------------------------------- AIZ2_SonicResize7: cmpi.w #$4160,(Camera_X_pos).w blo.s AIZ2_SonicResizeEnd st (Events_fg_4).w ; When past $4160, send signal to screen event to start the battleship sequence addq.b #2,(Dynamic_resize_routine).w AIZ2_SonicResizeEnd: rts ; --------------------------------------------------------------------------- AIZ2_KnuxResize1: cmpi.w #$2E0,(Camera_X_pos).w blo.s locret_1C7B6 move.w #$590,d0 move.w d0,(Camera_max_Y_pos).w move.w d0,(Camera_target_max_Y_pos).w ; Set level height to normal when past the open field addq.b #2,(Dynamic_resize_routine).w cmpi.w #1,(Apparent_zone_and_act).w bne.s locret_1C7B6 move.w #$1040,(Camera_min_X_pos).w ; Knuckles boss is slightly more to the right than Sonic's addq.b #2,(Dynamic_resize_routine).w locret_1C7B6: rts ; --------------------------------------------------------------------------- AIZ2_KnuxResize2: move.w #$590,d0 cmpi.w #$E80,(Camera_X_pos).w blo.s loc_1C7C8 move.w #$450,d0 loc_1C7C8: move.w d0,(Camera_max_Y_pos).w move.w d0,(Camera_target_max_Y_pos).w cmpi.w #$1040,(Camera_X_pos).w blo.s locret_1C808 move.w #$1040,(Camera_min_X_pos).w tst.w (Debug_placement_mode).w bne.s loc_1C7FE jsr (AllocateObject).l bne.s loc_1C7FE move.l #Obj_AIZMiniboss,(a1) move.w #$11D0,x_pos(a1) ; Knuckles' version of the boss is further down obviously move.w #$420,y_pos(a1) loc_1C7FE: move.w #$F80,(Target_water_level).w addq.b #2,(Dynamic_resize_routine).w locret_1C808: rts ; --------------------------------------------------------------------------- AIZ2_KnuxResize3: cmpi.w #$11A0,(Camera_X_pos).w blo.s locret_1C81C move.w #$820,(Camera_target_max_Y_pos).w ; Set level height to $820 when playing as Knuckles addq.b #2,(Dynamic_resize_routine).w locret_1C81C: rts ; --------------------------------------------------------------------------- AIZ2_KnuxResize4: cmpi.w #$3B80,(Camera_X_pos).w blo.s locret_1C868 tst.b (Kos_modules_left).w bne.s locret_1C868 lea (AIZ2_16x16_BomberShip_Kos).l,a1 lea (Block_table+$AB8).w,a2 jsr (Queue_Kos).l lea (AIZ2_8x8_BomberShip_KosM).l,a1 move.w #tiles_to_bytes($1FC),d2 jsr (Queue_Kos_Module).l ; I'm guessing the art here is for the trees and/or the waterfall in the boss arena moveq #$30,d0 jsr (LoadPalette_Immediate).l move.w #$3B80,(Camera_min_X_pos).w move.w #$5DA,(Camera_target_max_Y_pos).w st (Events_fg_5).w ; Set the flag for the background event addq.b #2,(Dynamic_resize_routine).w locret_1C868: rts ; --------------------------------------------------------------------------- AIZ2_KnuxResize5: move.w #$3F80,d0 cmp.w (Camera_X_pos).w,d0 bhi.s AIZ2_KnuxResizeEnd move.w d0,(Camera_min_X_pos).w addq.b #2,(Dynamic_resize_routine).w AIZ2_KnuxResizeEnd: rts ; --------------------------------------------------------------------------- HCZ1_Resize: moveq #0,d0 move.b (Dynamic_resize_routine).w,d0 move.w HCZ1_Resize_Index(pc,d0.w),d0 jmp HCZ1_Resize_Index(pc,d0.w) ; --------------------------------------------------------------------------- HCZ1_Resize_Index: dc.w loc_1C892-HCZ1_Resize_Index dc.w loc_1C8B8-HCZ1_Resize_Index dc.w locret_1C8F4-HCZ1_Resize_Index ; --------------------------------------------------------------------------- loc_1C892: cmpi.w #$360,(Camera_X_pos).w bhs.s locret_1C8B6 cmpi.w #$3E0,(Camera_Y_pos).w blo.s locret_1C8B6 lea (Normal_palette_line_4+$10).w,a1 ; Bug: this should be $680 move.w #$B80,(a1)+ move.w #$240,(a1)+ move.w #$220,(a1)+ addq.b #2,(Dynamic_resize_routine).w locret_1C8B6: rts ; --------------------------------------------------------------------------- loc_1C8B8: cmpi.w #$360,(Camera_X_pos).w bhs.s loc_1C8CE cmpi.w #$3E0,(Camera_Y_pos).w bhs.s locret_1C8F2 subq.b #2,(Dynamic_resize_routine).w bra.s loc_1C8E2 ; --------------------------------------------------------------------------- loc_1C8CE: cmpi.w #$500,(Camera_Y_pos).w blo.s locret_1C8F2 cmpi.w #$900,(Camera_X_pos).w blo.s locret_1C8F2 addq.b #2,(Dynamic_resize_routine).w loc_1C8E2: lea (Normal_palette_line_4+$10).w,a1 move.w #$CEE,(a1)+ move.w #$ACE,(a1)+ move.w #$8A,(a1)+ locret_1C8F2: rts ; --------------------------------------------------------------------------- locret_1C8F4: rts ; --------------------------------------------------------------------------- HCZ2_Resize: moveq #0,d0 move.b (Dynamic_resize_routine).w,d0 move.w HCZ2_Resize_Index(pc,d0.w),d0 jmp HCZ2_Resize_Index(pc,d0.w) ; --------------------------------------------------------------------------- HCZ2_Resize_Index: dc.w loc_1C908-HCZ2_Resize_Index dc.w locret_1C91A-HCZ2_Resize_Index ; --------------------------------------------------------------------------- loc_1C908: cmpi.w #$C00,(Camera_X_pos).w blo.s locret_1C918 st (Events_fg_5).w addq.b #2,(Dynamic_resize_routine).w locret_1C918: rts ; --------------------------------------------------------------------------- locret_1C91A: rts ; --------------------------------------------------------------------------- MGZ1_Resize: ; Bug: MGZ1 uses a dynamic resize routine meant for MGZ2 ; This causes the act 2 boss to spawn in out-of-bounds act 1 MGZ2_Resize: moveq #0,d0 move.b (Dynamic_resize_routine).w,d0 move.w MGZ2_Resize_Index(pc,d0.w),d0 jmp MGZ2_Resize_Index(pc,d0.w) ; --------------------------------------------------------------------------- MGZ2_Resize_Index: dc.w loc_1C930-MGZ2_Resize_Index dc.w loc_1C96E-MGZ2_Resize_Index dc.w locret_1C9C8-MGZ2_Resize_Index ; --------------------------------------------------------------------------- loc_1C930: move.w (Camera_Y_pos).w,d0 cmpi.w #$600,d0 blo.s locret_1C96C cmpi.w #$700,d0 bhs.s locret_1C96C cmpi.w #$3A00,(Camera_X_pos).w blo.s locret_1C96C move.w #$6A0,d0 move.w d0,(Camera_min_Y_pos).w move.w d0,(Camera_target_min_Y_pos).w move.w d0,(Camera_max_Y_pos).w move.w d0,(Camera_target_max_Y_pos).w move.w #$3C80,d0 move.w d0,(Camera_max_X_pos).w move.w d0,(Camera_target_max_X_pos).w addq.b #2,(Dynamic_resize_routine).w locret_1C96C: rts ; --------------------------------------------------------------------------- loc_1C96E: cmpi.w #$3A00,(Camera_X_pos).w blo.s loc_1C9A8 move.w #$3C80,d0 cmp.w (Camera_X_pos).w,d0 bhi.s locret_1C9C6 move.w d0,(Camera_min_X_pos).w move.w d0,(Camera_target_min_X_pos).w jsr (AllocateObject).l bne.s loc_1C9A2 move.l #Obj_MGZEndBoss,(a1) move.w #$3D20,x_pos(a1) move.w #$668,y_pos(a1) loc_1C9A2: addq.b #2,(Dynamic_resize_routine).w rts ; --------------------------------------------------------------------------- loc_1C9A8: move.l #$1000,d0 move.l d0,(Camera_min_Y_pos).w move.l d0,(Camera_target_min_Y_pos).w move.w #$6000,d0 move.w d0,(Camera_max_X_pos).w move.w d0,(Camera_target_max_X_pos).w subq.b #2,(Dynamic_resize_routine).w locret_1C9C6: rts ; --------------------------------------------------------------------------- locret_1C9C8: rts ; --------------------------------------------------------------------------- CNZ1_Resize: CNZ2_Resize: FBZ1_Resize: FBZ2_Resize: rts ; --------------------------------------------------------------------------- ICZ1_Resize: moveq #0,d0 move.b (Dynamic_resize_routine).w,d0 move.w ICZ1_Resize_Index(pc,d0.w),d0 jmp ICZ1_Resize_Index(pc,d0.w) ; --------------------------------------------------------------------------- ICZ1_Resize_Index: dc.w loc_1C9E0-ICZ1_Resize_Index dc.w loc_1C9FA-ICZ1_Resize_Index dc.w locret_1CA0C-ICZ1_Resize_Index ; --------------------------------------------------------------------------- loc_1C9E0: cmpi.w #$3700,(Camera_X_pos).w blo.s locret_1C9F8 cmpi.w #$68C,(Camera_Y_pos).w blo.s locret_1C9F8 st (Events_fg_5).w addq.b #2,(Dynamic_resize_routine).w locret_1C9F8: rts ; --------------------------------------------------------------------------- loc_1C9FA: cmpi.w #$3940,(Camera_X_pos).w blo.s locret_1CA0A st (Events_fg_5).w addq.b #2,(Dynamic_resize_routine).w locret_1CA0A: rts ; --------------------------------------------------------------------------- locret_1CA0C: rts ; --------------------------------------------------------------------------- ICZ2_Resize: moveq #0,d0 move.b (Dynamic_resize_routine).w,d0 move.w ICZ2_Resize_Index(pc,d0.w),d0 jmp ICZ2_Resize_Index(pc,d0.w) ; --------------------------------------------------------------------------- ICZ2_Resize_Index: dc.w loc_1CA20-ICZ2_Resize_Index dc.w locret_1CA3C-ICZ2_Resize_Index ; --------------------------------------------------------------------------- loc_1CA20: cmpi.w #$740,(Camera_X_pos).w blo.s locret_1CA3A cmpi.w #$400,(Camera_Y_pos).w bhs.s locret_1CA3A move.w #$740,(Camera_min_X_pos).w addq.b #2,(Dynamic_resize_routine).w locret_1CA3A: rts ; --------------------------------------------------------------------------- locret_1CA3C: rts ; --------------------------------------------------------------------------- LBZ1_Resize: rts ; --------------------------------------------------------------------------- LBZ2_Resize: moveq #0,d0 move.b (Dynamic_resize_routine).w,d0 move.w LBZ2_Resize_Index(pc,d0.w),d0 jmp LBZ2_Resize_Index(pc,d0.w) ; --------------------------------------------------------------------------- LBZ2_Resize_Index: dc.w loc_1CA52-LBZ2_Resize_Index dc.w locret_1CAAA-LBZ2_Resize_Index ; --------------------------------------------------------------------------- loc_1CA52: cmpi.w #$3BC0,(Camera_X_pos).w blo.s locret_1CAA8 cmpi.w #$500,(Camera_Y_pos).w blo.s locret_1CAA8 addq.b #2,(Dynamic_resize_routine).w lea (LBZ2_16x16_DeathEgg_Kos).l,a1 lea (Block_table).w,a2 jsr (Queue_Kos).l lea (LBZ2_128x128_DeathEgg_Kos).l,a1 lea (RAM_start).l,a2 jsr (Queue_Kos).l lea (LBZ2_8x8_DeathEgg_KosM).l,a1 move.w #tiles_to_bytes($000),d2 jsr (Queue_Kos_Module).l lea (ArtKosM_LBZ2DeathEgg2_8x8).l,a1 move.w #tiles_to_bytes(ArtTile_Explosion),d2 jsr (Queue_Kos_Module).l locret_1CAA8: rts ; --------------------------------------------------------------------------- locret_1CAAA: rts ; --------------------------------------------------------------------------- No_Resize: rts ; =============== S U B R O U T I N E ======================================= Resize_MaxYFromX: move.w (Camera_X_pos).w,d0 loc_1CAB2: move.l (a1)+,d1 cmp.w d1,d0 bhi.s loc_1CAB2 swap d1 tst.w d1 bpl.s loc_1CAC6 andi.w #$7FFF,d1 move.w d1,(Camera_max_Y_pos).w loc_1CAC6: move.w d1,(Camera_target_max_Y_pos).w rts ; End of function Resize_MaxYFromX ; =============== S U B R O U T I N E ======================================= Draw_LRZ_Special_Rock_Sprites: moveq #0,d0 move.b (LRZ_rocks_routine).w,d0 move.w Draw_LRZ_Special_Rock_Sprites_Index(pc,d0.w),d0 jmp Draw_LRZ_Special_Rock_Sprites_Index(pc,d0.w) ; --------------------------------------------------------------------------- Draw_LRZ_Special_Rock_Sprites_Index: dc.w loc_1CADE-Draw_LRZ_Special_Rock_Sprites_Index dc.w loc_1CB20-Draw_LRZ_Special_Rock_Sprites_Index ; --------------------------------------------------------------------------- loc_1CADE: addq.b #2,(LRZ_rocks_routine).w lea (LRZ1_Rock_Placement).l,a1 tst.b (Current_act).w beq.s loc_1CAF4 lea (LRZ2_Rock_Placement).l,a1 loc_1CAF4: move.w (Camera_X_pos).w,d4 subq.w #8,d4 bhi.s loc_1CB02 moveq #1,d4 bra.s loc_1CB02 ; --------------------------------------------------------------------------- loc_1CB00: addq.l #6,a1 loc_1CB02: cmp.w 2(a1),d4 bhi.s loc_1CB00 move.l a1,(LRZ_rocks_addr_front).w addi.w #$150,d4 bra.s loc_1CB14 ; --------------------------------------------------------------------------- loc_1CB12: addq.l #6,a1 loc_1CB14: cmp.w 2(a1),d4 bhi.s loc_1CB12 move.l a1,(LRZ_rocks_addr_back).w rts ; --------------------------------------------------------------------------- loc_1CB20: movea.l (LRZ_rocks_addr_front).w,a1 move.w (Camera_X_pos).w,d4 subq.w #8,d4 bhi.s loc_1CB32 moveq #1,d4 bra.s loc_1CB32 ; --------------------------------------------------------------------------- loc_1CB30: addq.l #6,a1 loc_1CB32: cmp.w 2(a1),d4 bhi.s loc_1CB30 bra.s loc_1CB3C ; --------------------------------------------------------------------------- loc_1CB3A: subq.l #6,a1 loc_1CB3C: cmp.w -4(a1),d4 bls.s loc_1CB3A move.l a1,(LRZ_rocks_addr_front).w movea.l (LRZ_rocks_addr_back).w,a2 addi.w #$150,d4 bra.s loc_1CB52 ; --------------------------------------------------------------------------- loc_1CB50: addq.l #6,a2 loc_1CB52: cmp.w 2(a2),d4 bhi.s loc_1CB50 bra.s loc_1CB5C ; --------------------------------------------------------------------------- loc_1CB5A: subq.l #6,a2 loc_1CB5C: cmp.w -4(a2),d4 bls.s loc_1CB5A move.l a2,(LRZ_rocks_addr_back).w rts ; End of function Draw_LRZ_Special_Rock_Sprites ; =============== S U B R O U T I N E ======================================= sub_1CB68: movea.l (LRZ_rocks_addr_front).w,a0 move.l (LRZ_rocks_addr_back).w,d2 sub.l a0,d2 beq.s locret_1CBBC lea LRZ_Rock_SpriteData(pc),a1 move.w #120,d3 move.w 4(a3),d4 move.w #240,d5 loc_1CB84: move.w 4(a0),d1 sub.w d4,d1 addq.w #8,d1 cmp.w d5,d1 bhs.s loc_1CBB6 add.w d3,d1 move.w 2(a0),d0 sub.w (a3),d0 addi.w #128,d0 move.w (a0),d6 lsl.w #3,d6 lea (a1,d6.w),a2 add.w (a2)+,d1 move.w d1,(a6)+ move.w (a2)+,d6 move.b d6,(a6) addq.w #2,a6 move.w (a2)+,(a6)+ add.w (a2)+,d0 move.w d0,(a6)+ subq.w #1,d7 loc_1CBB6: addq.l #6,a0 subq.w #6,d2 bne.s loc_1CB84 locret_1CBBC: rts ; End of function sub_1CB68 ; --------------------------------------------------------------------------- LRZ_Rock_SpriteData: binclude "Levels/LRZ/Misc/Rock Sprite Attribute Data.bin" even ; --------------------------------------------------------------------------- Obj_PathSwap: move.l #Map_PathSwap,mappings(a0) move.w #make_art_tile(ArtTile_Ring,1,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$40,width_pixels(a0) move.b #$40,height_pixels(a0) move.w #$280,priority(a0) move.b subtype(a0),d0 btst #2,d0 beq.s loc_1CD3C andi.w #7,d0 move.b d0,mapping_frame(a0) andi.w #3,d0 add.w d0,d0 move.w word_1CD34(pc,d0.w),$32(a0) move.w y_pos(a0),d1 lea (Player_1).w,a1 cmp.w y_pos(a1),d1 bhs.s loc_1CD06 move.b #1,$34(a0) loc_1CD06: lea (Player_2).w,a1 cmp.w y_pos(a1),d1 bhs.s loc_1CD16 move.b #1,$35(a0) loc_1CD16: move.l #loc_1CEF2,(a0) tst.w (Competition_mode).w beq.w loc_1CEF2 move.l #loc_1CF1A,(a0) move.w #make_art_tile($3D2,3,0),art_tile(a0) bra.w loc_1CF1A ; --------------------------------------------------------------------------- word_1CD34: dc.w $20, $40, $80, $100 ; --------------------------------------------------------------------------- loc_1CD3C: andi.w #3,d0 move.b d0,mapping_frame(a0) add.w d0,d0 move.w word_1CD34(pc,d0.w),$32(a0) move.w x_pos(a0),d1 lea (Player_1).w,a1 cmp.w x_pos(a1),d1 bhs.s loc_1CD60 move.b #1,$34(a0) loc_1CD60: lea (Player_2).w,a1 cmp.w x_pos(a1),d1 bhs.s loc_1CD70 move.b #1,$35(a0) loc_1CD70: move.l #loc_1CD8A,(a0) tst.w (Competition_mode).w beq.s loc_1CD8A move.l #loc_1CDB2,(a0) move.w #make_art_tile($3D2,3,0),art_tile(a0) bra.s loc_1CDB2 ; --------------------------------------------------------------------------- loc_1CD8A: tst.w (Debug_placement_mode).w bne.w loc_1CDAC move.w x_pos(a0),d1 lea $34(a0),a2 lea (Player_1).w,a1 bsr.s sub_1CDDA lea (Player_2).w,a1 bsr.s sub_1CDDA jmp (Delete_Sprite_If_Not_In_Range).l ; --------------------------------------------------------------------------- loc_1CDAC: jmp (Sprite_OnScreen_Test).l ; --------------------------------------------------------------------------- loc_1CDB2: move.w x_pos(a0),d1 lea $34(a0),a2 lea (Player_1).w,a1 bsr.s sub_1CDDA lea (Player_2).w,a1 bsr.s sub_1CDDA lea (Breathing_bubbles).w,a1 tst.w (Debug_mode_flag).w beq.w sub_1CDDA bsr.s sub_1CDDA jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_1CDDA: tst.b (a2)+ bne.w loc_1CE6C cmp.w x_pos(a1),d1 bhi.w locret_1CEF0 move.b #1,-1(a2) move.w y_pos(a0),d2 move.w d2,d3 move.w $32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w y_pos(a1),d4 cmp.w d2,d4 blt.w locret_1CEF0 cmp.w d3,d4 bge.w locret_1CEF0 move.b subtype(a0),d0 bpl.s loc_1CE1C btst #Status_InAir,status(a1) bne.w locret_1CEF0 loc_1CE1C: move.w x_pos(a1),d2 sub.w d1,d2 bcc.s loc_1CE26 neg.w d2 loc_1CE26: cmpi.w #$40,d2 bhs.w locret_1CEF0 btst #0,render_flags(a0) bne.s loc_1CE54 move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) btst #3,d0 beq.s loc_1CE54 move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_1CE54: andi.w #drawing_mask,art_tile(a1) btst #5,d0 beq.w locret_1CEF0 ori.w #high_priority,art_tile(a1) bra.w locret_1CEF0 ; --------------------------------------------------------------------------- loc_1CE6C: cmp.w x_pos(a1),d1 bls.w locret_1CEF0 move.b #0,-1(a2) move.w y_pos(a0),d2 move.w d2,d3 move.w $32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w y_pos(a1),d4 cmp.w d2,d4 blt.w locret_1CEF0 cmp.w d3,d4 bge.w locret_1CEF0 move.b subtype(a0),d0 bpl.s loc_1CEA8 btst #Status_InAir,status(a1) bne.w locret_1CEF0 loc_1CEA8: move.w x_pos(a1),d2 sub.w d1,d2 bcc.s loc_1CEB2 neg.w d2 loc_1CEB2: cmpi.w #$40,d2 bhs.s locret_1CEF0 btst #0,render_flags(a0) bne.s loc_1CEDE move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) btst #4,d0 beq.s loc_1CEDE move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_1CEDE: andi.w #drawing_mask,art_tile(a1) btst #6,d0 beq.s locret_1CEF0 ori.w #high_priority,art_tile(a1) locret_1CEF0: rts ; End of function sub_1CDDA ; --------------------------------------------------------------------------- loc_1CEF2: tst.w (Debug_placement_mode).w bne.w loc_1CF14 move.w y_pos(a0),d1 lea $34(a0),a2 lea (Player_1).w,a1 bsr.s sub_1CF42 lea (Player_2).w,a1 bsr.s sub_1CF42 jmp (Delete_Sprite_If_Not_In_Range).l ; --------------------------------------------------------------------------- loc_1CF14: jmp (Sprite_OnScreen_Test).l ; --------------------------------------------------------------------------- loc_1CF1A: move.w y_pos(a0),d1 lea $34(a0),a2 lea (Player_1).w,a1 bsr.s sub_1CF42 lea (Player_2).w,a1 bsr.s sub_1CF42 lea (Breathing_bubbles).w,a1 tst.w (Debug_mode_flag).w beq.w sub_1CF42 bsr.s sub_1CF42 jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_1CF42: tst.b (a2)+ bne.w loc_1CFD4 cmp.w y_pos(a1),d1 bhi.w locret_1D058 move.b #1,-1(a2) move.w x_pos(a0),d2 move.w d2,d3 move.w $32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w x_pos(a1),d4 cmp.w d2,d4 blt.w locret_1D058 cmp.w d3,d4 bge.w locret_1D058 move.b subtype(a0),d0 bpl.s loc_1CF84 btst #Status_InAir,status(a1) bne.w locret_1D058 loc_1CF84: move.w y_pos(a1),d2 sub.w d1,d2 bcc.s loc_1CF8E neg.w d2 loc_1CF8E: cmpi.w #$40,d2 bhs.w locret_1D058 btst #0,render_flags(a0) bne.s loc_1CFBC move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) btst #3,d0 beq.s loc_1CFBC move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_1CFBC: andi.w #drawing_mask,art_tile(a1) btst #5,d0 beq.w locret_1D058 ori.w #high_priority,art_tile(a1) bra.w locret_1D058 ; --------------------------------------------------------------------------- loc_1CFD4: cmp.w y_pos(a1),d1 bls.w locret_1D058 move.b #0,-1(a2) move.w x_pos(a0),d2 move.w d2,d3 move.w $32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w x_pos(a1),d4 cmp.w d2,d4 blt.w locret_1D058 cmp.w d3,d4 bge.w locret_1D058 move.b subtype(a0),d0 bpl.s loc_1D010 btst #Status_InAir,status(a1) bne.w locret_1D058 loc_1D010: move.w y_pos(a1),d2 sub.w d1,d2 bcc.s loc_1D01A neg.w d2 loc_1D01A: cmpi.w #$40,d2 bhs.s locret_1D058 btst #0,render_flags(a0) bne.s loc_1D046 move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) btst #4,d0 beq.s loc_1D046 move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_1D046: andi.w #drawing_mask,art_tile(a1) btst #6,d0 beq.s locret_1D058 ori.w #high_priority,art_tile(a1) locret_1D058: rts ; End of function sub_1CF42 ; --------------------------------------------------------------------------- Map_PathSwap: include "General/Sprites/Level Misc/Map - Path Swap.asm" ; --------------------------------------------------------------------------- Obj_SOZPathSwap: move.l #Map_PathSwap,mappings(a0) move.w #make_art_tile(ArtTile_Ring,1,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$40,width_pixels(a0) move.b #$40,height_pixels(a0) move.w #$280,priority(a0) move.b subtype(a0),d0 btst #2,d0 beq.s loc_1D180 andi.w #7,d0 move.b d0,mapping_frame(a0) andi.w #3,d0 add.w d0,d0 move.w word_1D178(pc,d0.w),$32(a0) move.w y_pos(a0),d1 lea (Player_1).w,a1 cmp.w y_pos(a1),d1 bhs.s loc_1D15E move.b #1,$34(a0) loc_1D15E: lea (Player_2).w,a1 cmp.w y_pos(a1),d1 bhs.s loc_1D16E move.b #1,$35(a0) loc_1D16E: move.l #loc_1D390,(a0) bra.w loc_1D390 ; --------------------------------------------------------------------------- word_1D178: dc.w $20, $40, $80, $100 ; --------------------------------------------------------------------------- loc_1D180: andi.w #3,d0 move.b d0,mapping_frame(a0) add.w d0,d0 move.w word_1D178(pc,d0.w),$32(a0) move.w x_pos(a0),d1 lea (Player_1).w,a1 cmp.w x_pos(a1),d1 bhs.s loc_1D1A4 move.b #1,$34(a0) loc_1D1A4: lea (Player_2).w,a1 cmp.w x_pos(a1),d1 bhs.s loc_1D1B4 move.b #1,$35(a0) loc_1D1B4: move.l #loc_1D1BA,(a0) loc_1D1BA: tst.w (Debug_placement_mode).w bne.w loc_1D1DC move.w x_pos(a0),d1 lea $34(a0),a2 lea (Player_1).w,a1 bsr.s sub_1D1E2 lea (Player_2).w,a1 bsr.s sub_1D1E2 jmp (Delete_Sprite_If_Not_In_Range).l ; --------------------------------------------------------------------------- loc_1D1DC: jmp (Sprite_OnScreen_Test).l ; =============== S U B R O U T I N E ======================================= sub_1D1E2: tst.b (a2)+ bne.w loc_1D2BE cmp.w x_pos(a1),d1 bhi.w locret_1D38E move.b #1,-1(a2) move.w y_pos(a0),d2 move.w d2,d3 move.w $32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w y_pos(a1),d4 cmp.w d2,d4 blt.w locret_1D38E cmp.w d3,d4 bge.w locret_1D38E move.b subtype(a0),d0 bpl.s loc_1D224 btst #Status_InAir,status(a1) bne.w locret_1D38E loc_1D224: move.w x_pos(a1),d2 sub.w d1,d2 bcc.s loc_1D22E neg.w d2 loc_1D22E: cmpi.w #$40,d2 bhs.w locret_1D38E btst #0,render_flags(a0) bne.s loc_1D2A6 btst #3,d0 bne.s loc_1D276 cmpi.b #$C,top_solid_bit(a1) bne.s loc_1D254 move.b #0,1(a2) bra.s loc_1D268 ; --------------------------------------------------------------------------- loc_1D254: addq.b #1,1(a2) cmpi.b #2,1(a2) bne.s loc_1D268 move.b #0,1(a2) bra.s loc_1D2A6 ; --------------------------------------------------------------------------- loc_1D268: move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) bra.s loc_1D2A6 ; --------------------------------------------------------------------------- loc_1D276: cmpi.b #$C,top_solid_bit(a1) bne.s loc_1D286 move.b #0,1(a2) bra.s loc_1D2A6 ; --------------------------------------------------------------------------- loc_1D286: addq.b #1,1(a2) cmpi.b #2,1(a2) bne.s loc_1D29A move.b #0,1(a2) bra.s loc_1D2A6 ; --------------------------------------------------------------------------- loc_1D29A: move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_1D2A6: andi.w #drawing_mask,art_tile(a1) btst #5,d0 beq.w locret_1D38E ori.w #high_priority,art_tile(a1) bra.w locret_1D38E ; --------------------------------------------------------------------------- loc_1D2BE: cmp.w x_pos(a1),d1 bls.w locret_1D38E move.b #0,-1(a2) move.w y_pos(a0),d2 move.w d2,d3 move.w $32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w y_pos(a1),d4 cmp.w d2,d4 blt.w locret_1D38E cmp.w d3,d4 bge.w locret_1D38E move.b subtype(a0),d0 bpl.s loc_1D2FA btst #Status_InAir,status(a1) bne.w locret_1D38E loc_1D2FA: move.w x_pos(a1),d2 sub.w d1,d2 bcc.s loc_1D304 neg.w d2 loc_1D304: cmpi.w #$40,d2 bhs.w locret_1D38E btst #0,render_flags(a0) bne.s loc_1D37C btst #4,d0 bne.s loc_1D34C cmpi.b #$C,top_solid_bit(a1) bne.s loc_1D32A move.b #0,1(a2) bra.s loc_1D33E ; --------------------------------------------------------------------------- loc_1D32A: addq.b #1,1(a2) cmpi.b #2,1(a2) bne.s loc_1D33E move.b #0,1(a2) bra.s loc_1D37C ; --------------------------------------------------------------------------- loc_1D33E: move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) bra.s loc_1D37C ; --------------------------------------------------------------------------- loc_1D34C: cmpi.b #$C,top_solid_bit(a1) bne.s loc_1D35C move.b #0,1(a2) bra.s loc_1D37C ; --------------------------------------------------------------------------- loc_1D35C: addq.b #1,1(a2) cmpi.b #2,1(a2) bne.s loc_1D370 move.b #0,1(a2) bra.s loc_1D37C ; --------------------------------------------------------------------------- loc_1D370: move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_1D37C: andi.w #drawing_mask,art_tile(a1) btst #6,d0 beq.s locret_1D38E ori.w #high_priority,art_tile(a1) locret_1D38E: rts ; End of function sub_1D1E2 ; --------------------------------------------------------------------------- loc_1D390: tst.w (Debug_placement_mode).w bne.w loc_1D3B2 move.w y_pos(a0),d1 lea $34(a0),a2 lea (Player_1).w,a1 bsr.s sub_1D3B8 lea (Player_2).w,a1 bsr.s sub_1D3B8 jmp (Delete_Sprite_If_Not_In_Range).l ; --------------------------------------------------------------------------- loc_1D3B2: jmp (Sprite_OnScreen_Test).l ; =============== S U B R O U T I N E ======================================= sub_1D3B8: tst.b (a2)+ bne.w loc_1D494 cmp.w y_pos(a1),d1 bhi.w locret_1D564 move.b #1,-1(a2) move.w x_pos(a0),d2 move.w d2,d3 move.w $32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w x_pos(a1),d4 cmp.w d2,d4 blt.w locret_1D564 cmp.w d3,d4 bge.w locret_1D564 move.b subtype(a0),d0 bpl.s loc_1D3FA btst #Status_InAir,status(a1) bne.w locret_1D564 loc_1D3FA: move.w y_pos(a1),d2 sub.w d1,d2 bcc.s loc_1D404 neg.w d2 loc_1D404: cmpi.w #$40,d2 bhs.w locret_1D564 btst #0,render_flags(a0) bne.s loc_1D47C btst #3,d0 bne.s loc_1D44C cmpi.b #$C,top_solid_bit(a1) bne.s loc_1D42A move.b #0,1(a2) bra.s loc_1D43E ; --------------------------------------------------------------------------- loc_1D42A: addq.b #1,1(a2) cmpi.b #2,1(a2) bne.s loc_1D43E move.b #0,1(a2) bra.s loc_1D47C ; --------------------------------------------------------------------------- loc_1D43E: move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) bra.s loc_1D47C ; --------------------------------------------------------------------------- loc_1D44C: cmpi.b #$C,top_solid_bit(a1) bne.s loc_1D45C move.b #0,1(a2) bra.s loc_1D47C ; --------------------------------------------------------------------------- loc_1D45C: addq.b #1,1(a2) cmpi.b #2,1(a2) bne.s loc_1D470 move.b #0,1(a2) bra.s loc_1D47C ; --------------------------------------------------------------------------- loc_1D470: move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_1D47C: andi.w #drawing_mask,art_tile(a1) btst #5,d0 beq.w locret_1D564 ori.w #high_priority,art_tile(a1) bra.w locret_1D564 ; --------------------------------------------------------------------------- loc_1D494: cmp.w y_pos(a1),d1 bls.w locret_1D564 move.b #0,-1(a2) move.w x_pos(a0),d2 move.w d2,d3 move.w $32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w x_pos(a1),d4 cmp.w d2,d4 blt.w locret_1D564 cmp.w d3,d4 bge.w locret_1D564 move.b subtype(a0),d0 bpl.s loc_1D4D0 btst #Status_InAir,status(a1) bne.w locret_1D564 loc_1D4D0: move.w y_pos(a1),d2 sub.w d1,d2 bcc.s loc_1D4DA neg.w d2 loc_1D4DA: cmpi.w #$40,d2 bhs.w locret_1D564 btst #0,render_flags(a0) bne.s loc_1D552 btst #4,d0 bne.s loc_1D522 cmpi.b #$C,top_solid_bit(a1) bne.s loc_1D500 move.b #0,1(a2) bra.s loc_1D514 ; --------------------------------------------------------------------------- loc_1D500: addq.b #1,1(a2) cmpi.b #2,1(a2) bne.s loc_1D514 move.b #0,1(a2) bra.s loc_1D552 ; --------------------------------------------------------------------------- loc_1D514: move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) bra.s loc_1D552 ; --------------------------------------------------------------------------- loc_1D522: cmpi.b #$C,top_solid_bit(a1) bne.s loc_1D532 move.b #0,1(a2) bra.s loc_1D552 ; --------------------------------------------------------------------------- loc_1D532: addq.b #1,1(a2) cmpi.b #2,1(a2) bne.s loc_1D546 move.b #0,1(a2) bra.s loc_1D552 ; --------------------------------------------------------------------------- loc_1D546: move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_1D552: andi.w #drawing_mask,art_tile(a1) btst #6,d0 beq.s locret_1D564 ori.w #high_priority,art_tile(a1) locret_1D564: rts ; End of function sub_1D3B8 ; --------------------------------------------------------------------------- Obj_Monitor: moveq #0,d0 move.b routine(a0),d0 move.w Monitor_Index(pc,d0.w),d1 jmp Monitor_Index(pc,d1.w) ; --------------------------------------------------------------------------- Monitor_Index: dc.w Obj_MonitorInit-Monitor_Index dc.w Obj_MonitorMain-Monitor_Index dc.w Obj_MonitorBreak-Monitor_Index dc.w Obj_MonitorAnimate-Monitor_Index dc.w loc_1D61A-Monitor_Index ; --------------------------------------------------------------------------- Obj_MonitorInit: addq.b #2,routine(a0) ; => Obj_MonitorMain move.b #$F,y_radius(a0) move.b #$F,x_radius(a0) move.l #Map_Monitor,mappings(a0) move.w #make_art_tile(ArtTile_Monitors,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.w #$180,priority(a0) move.b #$E,width_pixels(a0) move.b #$10,height_pixels(a0) move.w respawn_addr(a0),d0 ; Get address in respawn table beq.s .notbroken ; If it's zero, it isn't remembered movea.w d0,a2 ; Load address into a2 btst #0,(a2) ; Is this monitor broken? beq.s .notbroken ; If not, branch move.b #$B,mapping_frame(a0) ; Use 'broken monitor' frame move.l #Sprite_OnScreen_Test,(a0) rts ; --------------------------------------------------------------------------- .notbroken: move.b #$46,collision_flags(a0) move.b subtype(a0),anim(a0) ; Subtype determines what powerup is inside Obj_MonitorMain: bsr.s Obj_MonitorFall move.w #$19,d1 ; Monitor's width move.w #$10,d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w SolidObject_Monitor_SonicKnux movem.l (sp)+,d1-d4 lea (Player_2).w,a1 moveq #p2_standing_bit,d6 bsr.w SolidObject_Monitor_Tails jsr (Add_SpriteToCollisionResponseList).l lea (Ani_Monitor).l,a1 bsr.w Animate_Sprite loc_1D61A: bra.w Sprite_OnScreen_Test ; --------------------------------------------------------------------------- Obj_MonitorAnimate: cmpi.b #$B,mapping_frame(a0) ; Is monitor broken? bne.s .notbroken ; If not, branch move.l #loc_1D61A,(a0) .notbroken: lea (Ani_Monitor).l,a1 bsr.w Animate_Sprite bra.w Sprite_OnScreen_Test ; =============== S U B R O U T I N E ======================================= Obj_MonitorFall: move.b routine_secondary(a0),d0 beq.s locret_1D694 btst #1,render_flags(a0) ; Is monitor upside down? bne.s Obj_MonitorFallUpsideDown ; If so, branch bsr.w MoveSprite tst.w y_vel(a0) ; Is monitor moving up? bmi.s locret_1D694 ; If so, return jsr (ObjCheckFloorDist).l tst.w d1 ; Is monitor in the ground? beq.s .inground ; If so, branch bpl.s locret_1D694 ; if not, return .inground: 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 rts ; --------------------------------------------------------------------------- Obj_MonitorFallUpsideDown: bsr.w MoveSprite2 subi.w #$38,y_vel(a0) tst.w y_vel(a0) ; Is monitor moving down? bpl.s locret_1D694 ; If so, return jsr (ObjCheckCeilingDist).l tst.w d1 ; Is monitor in the ground (ceiling)? beq.s .inground ; If so, branch bpl.s locret_1D694 ; if not, return .inground: sub.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 locret_1D694: rts ; End of function Obj_MonitorFall ; =============== S U B R O U T I N E ======================================= SolidObject_Monitor_SonicKnux: btst d6,status(a0) ; Is Sonic/Knux standing on the monitor? bne.s Monitor_ChkOverEdge ; If so, branch cmpi.b #2,anim(a1) ; Is Sonic/Knux in their rolling animation? beq.s locret_1D6BC ; If so, return cmpi.b #2,character_id(a1) ; Is character Knuckles? bne.s loc_1D6BE ; If not, branch cmpi.b #1,double_jump_flag(a1) ; Is Knuckles gliding? beq.s locret_1D6BC ; If so, return cmpi.b #3,double_jump_flag(a1) ; Is Knuckles sliding after gliding? bne.s loc_1D6BE ; If not, branch locret_1D6BC: rts ; --------------------------------------------------------------------------- loc_1D6BE: bra.w SolidObject_cont ; End of function SolidObject_Monitor_SonicKnux ; =============== S U B R O U T I N E ======================================= SolidObject_Monitor_Tails: btst d6,status(a0) ; Is Tails standing on the monitor? bne.s Monitor_ChkOverEdge ; If so, branch tst.w (Competition_mode).w ; Are we in competition mode? beq.w SolidObject_cont ; If not, branch cmpi.b #2,anim(a1) ; Is Tails in his rolling animation? bne.w SolidObject_cont ; If not, branch rts ; End of function SolidObject_Monitor_Tails ; --------------------------------------------------------------------------- Monitor_ChkOverEdge: move.w d1,d2 add.w d2,d2 btst #Status_InAir,status(a1) ; Is the character in the air? bne.s .notonmonitor ; If so, 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 .notonmonitor ; Branch, if character is behind the left edge of the monitor cmp.w d2,d0 blo.s Monitor_CharStandOn ; Branch, if character is not beyond the right edge of the monitor .notonmonitor: ; if the character isn't standing on the monitor bclr #Status_OnObj,status(a1) ; Clear 'on object' bit bset #Status_InAir,status(a1) ; Set 'in air' bit bclr d6,status(a0) ; Clear 'standing on' bit for the current character moveq #0,d4 rts ; --------------------------------------------------------------------------- Monitor_CharStandOn: move.w d4,d2 bsr.w MvSonicOnPtfm moveq #0,d4 rts ; --------------------------------------------------------------------------- Obj_MonitorBreak: move.b status(a0),d0 andi.b #standing_mask|pushing_mask,d0 ; Is someone touching the monitor? beq.s Obj_MonitorSpawnIcon ; If not, branch move.b d0,d1 andi.b #p1_standing|p1_pushing,d1 ; Is it the main character? beq.s .notmainchar ; If not, branch andi.b #$D7,(Player_1+status).w ori.b #1< loc_1E61A move.w x_pos(a0),x_pos(a1) ; Set explosion's position move.w y_pos(a0),y_pos(a1) .skipexplosioncreation: move.w respawn_addr(a0),d0 ; Get address in respawn table beq.s .notremembered ; If it's zero, it isn't remembered movea.w d0,a2 ; Load address into a2 bset #0,(a2) ; Mark monitor as destroyed .notremembered: move.b #$A,anim(a0) ; Display 'broken' animation move.l #Obj_MonitorAnimate,(a0) bra.w Draw_Sprite ; --------------------------------------------------------------------------- Obj_MonitorContents: moveq #0,d0 move.b routine(a0),d0 move.w MonitorContents_Index(pc,d0.w),d1 jmp MonitorContents_Index(pc,d1.w) ; --------------------------------------------------------------------------- MonitorContents_Index: dc.w loc_1D7CE-MonitorContents_Index dc.w loc_1D81A-MonitorContents_Index dc.w loc_1DB2E-MonitorContents_Index ; --------------------------------------------------------------------------- loc_1D7CE: addq.b #2,routine(a0) move.w #make_art_tile(ArtTile_Monitors,0,1),art_tile(a0) ori.b #$24,render_flags(a0) move.w #$180,priority(a0) move.b #8,width_pixels(a0) move.w #-$300,y_vel(a0) btst #1,render_flags(a0) beq.s loc_1D7FC neg.w y_vel(a0) loc_1D7FC: moveq #0,d0 move.b anim(a0),d0 addq.b #1,d0 move.b d0,mapping_frame(a0) movea.l #Map_Monitor,a1 add.b d0,d0 adda.w (a1,d0.w),a1 addq.w #2,a1 move.l a1,mappings(a0) loc_1D81A: bsr.s sub_1D820 bra.w Draw_Sprite ; =============== S U B R O U T I N E ======================================= sub_1D820: btst #1,render_flags(a0) bne.s loc_1D83C tst.w y_vel(a0) bpl.w loc_1D850 bsr.w MoveSprite2 addi.w #$18,y_vel(a0) rts ; --------------------------------------------------------------------------- loc_1D83C: tst.w y_vel(a0) bmi.w loc_1D850 bsr.w MoveSprite2 subi.w #$18,y_vel(a0) rts ; --------------------------------------------------------------------------- loc_1D850: addq.b #2,routine(a0) move.w #30-1,anim_frame_timer(a0) movea.w parent(a0),a1 lea (Monitors_broken).w,a2 cmpa.w #Player_1,a1 beq.s loc_1D86C lea (Monitors_broken_P2).w,a2 loc_1D86C: moveq #0,d0 move.b anim(a0),d0 add.w d0,d0 move.w off_1D87C(pc,d0.w),d0 jmp off_1D87C(pc,d0.w) ; End of function sub_1D820 ; --------------------------------------------------------------------------- off_1D87C: dc.w Monitor_Give_Eggman-off_1D87C dc.w Monitor_Give_1up-off_1D87C dc.w Monitor_Give_Eggman-off_1D87C dc.w Monitor_Give_Rings-off_1D87C dc.w Monitor_Give_SpeedShoes-off_1D87C dc.w Monitor_Give_FireShield-off_1D87C dc.w Monitor_Give_LightningShield-off_1D87C dc.w Monitor_Give_BubbleShield-off_1D87C dc.w Monitor_Give_Invincibility-off_1D87C dc.w Monitor_Give_SuperSonic-off_1D87C ; --------------------------------------------------------------------------- Monitor_Give_Eggman: addq.w #1,(a2) jmp (sub_24280).l ; --------------------------------------------------------------------------- Monitor_Give_1up: addq.w #1,(Monitors_broken).w addq.b #1,(Life_count).w addq.b #1,(Update_HUD_life_count).w moveq #signextendB(mus_ExtraLife),d0 jmp (Play_Music).l ; --------------------------------------------------------------------------- Monitor_Give_Rings: addq.w #1,(a2) lea (Ring_count).w,a2 lea (Update_HUD_ring_count).w,a3 lea (Extra_life_flags).w,a4 lea (Total_ring_count).w,a5 addi.w #10,(a5) cmpi.w #999,(a5) blo.s loc_1D8CC move.w #999,(a5) loc_1D8CC: addi.w #10,(a2) cmpi.w #999,(a2) blo.s loc_1D8DA move.w #999,(a2) loc_1D8DA: ori.b #1,(a3) cmpi.w #100,(a2) blo.s loc_1D8F6 bset #1,(a4) beq.s loc_1D8FE cmpi.w #200,(a2) blo.s loc_1D8F6 bset #2,(a4) beq.s loc_1D8FE loc_1D8F6: moveq #signextendB(sfx_RingRight),d0 jmp (Play_Music).l ; --------------------------------------------------------------------------- loc_1D8FE: cmpa.w #Player_1,a1 beq.w Monitor_Give_1up bra.w Monitor_Give_Eggman ; --------------------------------------------------------------------------- Monitor_Give_SpeedShoes: addq.w #1,(a2) bset #Status_SpeedShoes,status_secondary(a1) move.b #(20*60)/8,speed_shoes_timer(a1) cmpa.w #Player_1,a1 bne.s loc_1D93A cmpi.w #2,(Player_mode).w beq.s loc_1D93A move.w #$C00,(Max_speed).w move.w #$18,(Acceleration).w move.w #$80,(Deceleration).w bra.s loc_1D94C ; --------------------------------------------------------------------------- loc_1D93A: move.w #$C00,(Max_speed_P2).w move.w #$18,(Acceleration_P2).w move.w #$80,(Deceleration_P2).w loc_1D94C: moveq #8,d0 jmp (Change_Music_Tempo).l ; --------------------------------------------------------------------------- Monitor_Give_FireShield: addq.w #1,(a2) andi.b #$8E,status_secondary(a1) bset #Status_Shield,status_secondary(a1) bset #Status_FireShield,status_secondary(a1) moveq #signextendB(sfx_FireShield),d0 jsr (Play_Music).l tst.b parent+1(a0) bne.s loc_1D984 move.l #Obj_FireShield,(Shield).w move.w a1,(Shield+parent).w rts ; --------------------------------------------------------------------------- loc_1D984: move.l #Obj_FireShield,(Shield_P2).w move.w a1,(Shield_P2+parent).w rts ; --------------------------------------------------------------------------- Monitor_Give_LightningShield: addq.w #1,(a2) andi.b #$8E,status_secondary(a1) bset #Status_Shield,status_secondary(a1) bset #Status_LtngShield,status_secondary(a1) moveq #signextendB(sfx_LightningShield),d0 jsr (Play_Music).l tst.b parent+1(a0) bne.s loc_1D9C2 move.l #Obj_LightningShield,(Shield).w move.w a1,(Shield+parent).w rts ; --------------------------------------------------------------------------- loc_1D9C2: move.l #Obj_LightningShield,(Shield_P2).w move.w a1,(Shield_P2+parent).w rts ; --------------------------------------------------------------------------- Monitor_Give_BubbleShield: addq.w #1,(a2) andi.b #$8E,status_secondary(a1) bset #Status_Shield,status_secondary(a1) bset #Status_BublShield,status_secondary(a1) moveq #signextendB(sfx_BubbleShield),d0 jsr (Play_Music).l tst.b parent+1(a0) bne.s loc_1DA00 move.l #Obj_BubbleShield,(Shield).w move.w a1,(Shield+parent).w rts ; --------------------------------------------------------------------------- loc_1DA00: move.l #Obj_BubbleShield,(Shield_P2).w move.w a1,(Shield_P2+parent).w rts ; --------------------------------------------------------------------------- Monitor_Give_Invincibility: addq.w #1,(a2) tst.b (Super_Sonic_Knux_flag).w bne.s locret_1DA5E tst.b (Super_Tails_flag).w bne.s locret_1DA5E bset #1,status_secondary(a1) move.b #(20*60)/8,invincibility_timer(a1) tst.b (Boss_flag).w bne.s loc_1DA3E cmpi.b #12,air_left(a1) bls.s loc_1DA3E moveq #signextendB(mus_Invincibility),d0 jsr (Play_Music).l loc_1DA3E: tst.b parent+1(a0) bne.s loc_1DA52 move.l #Obj_Invincibility,(Invincibility_stars).w move.w a1,(Invincibility_stars+parent).w rts ; --------------------------------------------------------------------------- loc_1DA52: move.l #Obj_Invincibility,(Invincibility_stars_P2).w move.w a1,(Invincibility_stars_P2+parent).w locret_1DA5E: rts ; --------------------------------------------------------------------------- Monitor_Give_SuperSonic: addq.w #1,(a2) addi.w #50,(Ring_count).w move.b #1,(Super_palette_status).w move.b #$F,(Palette_timer).w move.b #1,(Super_Sonic_Knux_flag).w ; Super move.w #60,(Super_frame_count).w move.w #$800,(Max_speed).w move.w #$18,(Acceleration).w move.w #$C0,(Deceleration).w move.b #$1F,(Player_1+anim).w cmpi.w #2,(Player_mode).w bne.s .notTails move.b #0,(Super_Sonic_Knux_flag).w ; Normal move.b #1,(Super_Tails_flag).w ; Super move.b #$29,(Player_1+anim).w move.w #$800,(Max_speed_P2).w move.w #$18,(Acceleration_P2).w move.w #$C0,(Deceleration_P2).w move.l #Obj_SuperTailsBirds,(Invincibility_stars).w bra.s .continued ; --------------------------------------------------------------------------- .notTails: bhs.s .hyperKnuckles move.l #Map_SuperSonic,(Player_1+mappings).w move.b #-1,(Super_Sonic_Knux_flag).w ; Hyper move.w #$A00,(Max_speed).w move.w #$30,(Acceleration).w move.w #$100,(Deceleration).w move.l #Obj_HyperSonic_Stars,(Invincibility_stars).w move.l #Obj_HyperSonicKnux_Trail,(Super_stars).w bra.s .continued ; --------------------------------------------------------------------------- .hyperKnuckles: ; Bug: Knuckles gets his Hyper after-images, but isn't actually marked as Hyper ;move.b #-1,(Super_Sonic_Knux_flag).w ; Hyper move.l #Obj_HyperSonicKnux_Trail,(Super_stars).w .continued: move.b #$81,(Player_1+object_control).w move.b #0,(Player_1+invincibility_timer).w bset #Status_Invincible,status_secondary(a1) moveq #signextendB(sfx_SuperTransform),d0 jsr (Play_SFX).l moveq #signextendB(mus_Invincibility),d0 ; play invincibility theme jmp (Play_Music).l ; --------------------------------------------------------------------------- rts ; --------------------------------------------------------------------------- loc_1DB2E: subq.w #1,anim_frame_timer(a0) bmi.w Delete_Current_Sprite bra.w Draw_Sprite ; --------------------------------------------------------------------------- Ani_Monitor: include "General/Sprites/Monitors/Anim - Monitor.asm" Map_Monitor: include "General/Sprites/Monitors/Map - Monitor.asm" ; =============== S U B R O U T I N E ======================================= SolidObjectFull: lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s SolidObjectFull_1P movem.l (sp)+,d1-d4 lea (Player_2).w,a1 tst.b render_flags(a1) bpl.w locret_1DCB4 addq.b #p2_standing_bit-p1_standing_bit,d6 ; End of function SolidObjectFull ; =============== S U B R O U T I N E ======================================= SolidObjectFull_1P: btst d6,status(a0) beq.w loc_1DF88 move.w d1,d2 add.w d2,d2 btst #Status_InAir,status(a1) bne.s loc_1DC98 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_1DC98 cmp.w d2,d0 blo.s loc_1DCAC loc_1DC98: bclr #Status_OnObj,status(a1) bset #Status_InAir,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_1DCAC: move.w d4,d2 bsr.w MvSonicOnPtfm moveq #0,d4 locret_1DCB4: rts ; End of function SolidObjectFull_1P ; =============== S U B R O U T I N E ======================================= SolidObjectFull2: lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s SolidObjectFull2_1P movem.l (sp)+,d1-d4 lea (Player_2).w,a1 addq.b #p2_standing_bit-p1_standing_bit,d6 ; End of function SolidObjectFull2 ; =============== S U B R O U T I N E ======================================= SolidObjectFull2_1P: btst d6,status(a0) beq.w SolidObject_cont move.w d1,d2 add.w d2,d2 btst #Status_InAir,status(a1) bne.s loc_1DCF0 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_1DCF0 cmp.w d2,d0 blo.s loc_1DD04 loc_1DCF0: bclr #Status_OnObj,status(a1) bset #Status_InAir,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_1DD04: move.w d4,d2 bsr.w MvSonicOnPtfm moveq #0,d4 rts ; End of function SolidObjectFull2_1P ; =============== S U B R O U T I N E ======================================= sub_1DD0E: lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s sub_1DD24 movem.l (sp)+,d1-d4 lea (Player_2).w,a1 addq.b #p2_standing_bit-p1_standing_bit,d6 ; End of function sub_1DD0E ; =============== S U B R O U T I N E ======================================= sub_1DD24: btst d6,status(a0) beq.w loc_1DECE move.w d1,d2 add.w d2,d2 btst #Status_InAir,status(a1) bne.s loc_1DD48 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_1DD48 cmp.w d2,d0 blo.s loc_1DD5C loc_1DD48: bclr #Status_OnObj,status(a1) bset #Status_InAir,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_1DD5C: move.w d4,d2 bsr.w SolidObjSloped2 move.w d6,d4 addi.b #$11,d4 bset d4,d6 moveq #0,d4 rts ; End of function sub_1DD24 ; --------------------------------------------------------------------------- lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s sub_1DD84 movem.l (sp)+,d1-d4 lea (Player_2).w,a1 addq.b #p2_standing_bit-p1_standing_bit,d6 ; =============== S U B R O U T I N E ======================================= sub_1DD84: btst d6,status(a0) beq.w loc_1DF28 move.w d1,d2 add.w d2,d2 btst #Status_InAir,status(a1) bne.s loc_1DDA8 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_1DDA8 cmp.w d2,d0 blo.s loc_1DDBC loc_1DDA8: bclr #Status_OnObj,status(a1) bset #Status_InAir,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_1DDBC: move.w d4,d2 bsr.w SolidObjSloped4 moveq #0,d4 rts ; End of function sub_1DD84 ; =============== S U B R O U T I N E ======================================= sub_1DDC6: lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s sub_1DDDC movem.l (sp)+,d1-d4 lea (Player_2).w,a1 addq.b #p2_standing_bit-p1_standing_bit,d6 ; End of function sub_1DDC6 ; =============== S U B R O U T I N E ======================================= sub_1DDDC: btst d6,status(a0) beq.w loc_1DECE move.w d1,d2 add.w d2,d2 btst #Status_InAir,status(a1) bne.s loc_1DE00 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_1DE00 cmp.w d2,d0 blo.s loc_1DE0E loc_1DE00: bclr #Status_OnObj,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_1DE0E: move.w d4,d2 bsr.w SolidObjSloped2 move.w d6,d4 addi.b #$11,d4 bset d4,d6 moveq #0,d4 rts ; End of function sub_1DDDC ; =============== S U B R O U T I N E ======================================= SolidObjectFull_Offset: lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s SolidObjectFull_Offset_1P movem.l (sp)+,d1-d4 lea (Player_2).w,a1 addq.b #p2_standing_bit-p1_standing_bit,d6 ; End of function SolidObjectFull_Offset ; =============== S U B R O U T I N E ======================================= SolidObjectFull_Offset_1P: btst d6,status(a0) beq.w loc_1DE8C btst #Status_InAir,status(a1) bne.s loc_1DE58 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_1DE58 add.w d1,d1 cmp.w d1,d0 blo.s loc_1DE6C loc_1DE58: bclr #Status_OnObj,status(a1) bset #Status_InAir,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_1DE6C: 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_1DE8C: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.w loc_1E0A2 move.w d1,d4 add.w d4,d4 cmp.w d4,d0 bhi.w loc_1E0A2 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 loc_1E0A2 move.w d2,d4 add.w d4,d4 cmp.w d4,d3 bhs.w loc_1E0A2 bra.w loc_1DFFE ; --------------------------------------------------------------------------- loc_1DECE: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.w loc_1E0A2 move.w d1,d3 add.w d3,d3 cmp.w d3,d0 bhi.w loc_1E0A2 move.w d0,d5 btst #0,render_flags(a0) beq.s loc_1DEF4 not.w d5 add.w d3,d5 loc_1DEF4: 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 loc_1E0A2 move.w d2,d4 add.w d4,d4 cmp.w d4,d3 bhs.w loc_1E0A2 bra.w loc_1DFFE ; --------------------------------------------------------------------------- loc_1DF28: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.w loc_1E0A2 move.w d1,d3 add.w d3,d3 cmp.w d3,d0 bhi.w loc_1E0A2 move.w d0,d5 btst #0,render_flags(a0) beq.s loc_1DF4E not.w d5 add.w d3,d5 loc_1DF4E: 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 loc_1E0A2 add.w d5,d2 move.w d2,d4 add.w d5,d4 cmp.w d4,d3 bhs.w loc_1E0A2 bra.w loc_1DFFE ; --------------------------------------------------------------------------- loc_1DF88: tst.b render_flags(a0) bpl.w loc_1E0A2 SolidObject_cont: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 move.w d1,d3 add.w d3,d3 cmp.w d3,d0 bhi.w loc_1E0A2 tst.b (Reverse_gravity_flag).w beq.s loc_1DFD6 move.b default_y_radius(a1),d4 ext.w d4 add.w d2,d4 move.b y_radius(a1),d3 ext.w d3 add.w d3,d2 move.w y_pos(a1),d3 sub.w y_pos(a0),d3 neg.w d3 addq.w #4,d3 add.w d2,d3 andi.w #$FFF,d3 add.w d2,d4 cmp.w d4,d3 bhs.w loc_1E0A2 bra.s loc_1DFFE ; --------------------------------------------------------------------------- loc_1DFD6: move.b default_y_radius(a1),d4 ext.w d4 add.w d2,d4 move.b y_radius(a1),d3 ext.w d3 add.w d3,d2 move.w y_pos(a1),d3 sub.w y_pos(a0),d3 addq.w #4,d3 add.w d2,d3 andi.w #$FFF,d3 add.w d2,d4 cmp.w d4,d3 bhs.w loc_1E0A2 loc_1DFFE: tst.b object_control(a1) bmi.w loc_1E0A2 cmpi.b #6,routine(a1) bhs.w loc_1E0D0 tst.w (Debug_placement_mode).w bne.w loc_1E0D0 move.w d0,d5 cmp.w d0,d1 bhs.s loc_1E026 add.w d1,d1 sub.w d1,d0 move.w d0,d5 neg.w d5 loc_1E026: move.w d3,d1 cmp.w d3,d2 bhs.s loc_1E034 subq.w #4,d3 sub.w d4,d3 move.w d3,d1 neg.w d1 loc_1E034: cmp.w d1,d5 bhi.w loc_1E0D4 cmpi.w #4,d1 bls.w loc_1E0D4 loc_1E042: tst.w d0 beq.s loc_1E06E bmi.s loc_1E050 tst.w x_vel(a1) bmi.s loc_1E06E bra.s loc_1E056 ; --------------------------------------------------------------------------- loc_1E050: tst.w x_vel(a1) bpl.s loc_1E06E loc_1E056: move.w #0,ground_vel(a1) move.w #0,x_vel(a1) tst.b status_tertiary(a1) bpl.s loc_1E06E bset #6,status_tertiary(a1) loc_1E06E: sub.w d0,x_pos(a1) btst #Status_InAir,status(a1) bne.s loc_1E094 move.l d6,d4 addq.b #pushing_bit_delta,d4 bset d4,status(a0) bset #Status_Push,status(a1) move.w d6,d4 addi.b #$D,d4 bset d4,d6 moveq #1,d4 rts ; --------------------------------------------------------------------------- loc_1E094: bsr.s sub_1E0C2 move.w d6,d4 addi.b #$D,d4 bset d4,d6 moveq #1,d4 rts ; --------------------------------------------------------------------------- loc_1E0A2: move.l d6,d4 addq.b #pushing_bit_delta,d4 btst d4,status(a0) beq.s loc_1E0D0 cmpi.b #2,anim(a1) beq.s sub_1E0C2 cmpi.b #9,anim(a1) beq.s sub_1E0C2 move.w #1,anim(a1) ; End of function SolidObjectFull_Offset_1P ; =============== S U B R O U T I N E ======================================= sub_1E0C2: move.l d6,d4 addq.b #pushing_bit_delta,d4 bclr d4,status(a0) bclr #Status_Push,status(a1) loc_1E0D0: moveq #0,d4 rts ; End of function sub_1E0C2 ; --------------------------------------------------------------------------- loc_1E0D4: tst.w d3 bmi.s loc_1E0E0 cmpi.w #$10,d3 blo.s loc_1E154 bra.s loc_1E0A2 ; --------------------------------------------------------------------------- loc_1E0E0: btst #Status_InAir,status(a1) bne.s loc_1E0F6 tst.w y_vel(a1) beq.s loc_1E126 bpl.s loc_1E10E tst.w d3 bpl.s loc_1E10E bra.s loc_1E0FC ; --------------------------------------------------------------------------- loc_1E0F6: move.w #0,ground_vel(a1) loc_1E0FC: tst.b (Reverse_gravity_flag).w beq.s loc_1E104 neg.w d3 loc_1E104: sub.w d3,y_pos(a1) move.w #0,y_vel(a1) loc_1E10E: tst.b status_tertiary(a1) bpl.s loc_1E11A bset #5,status_tertiary(a1) loc_1E11A: move.w d6,d4 addi.b #$F,d4 bset d4,d6 moveq #-2,d4 rts ; --------------------------------------------------------------------------- loc_1E126: btst #Status_InAir,status(a1) bne.s loc_1E10E move.w d0,d4 bpl.s loc_1E134 neg.w d4 loc_1E134: cmpi.w #$10,d4 blo.w loc_1E042 move.l a0,-(sp) movea.l a1,a0 jsr (Kill_Character).l movea.l (sp)+,a0 move.w d6,d4 addi.b #$F,d4 bset d4,d6 moveq #-2,d4 rts ; --------------------------------------------------------------------------- loc_1E154: 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_1E198 cmp.w d2,d1 bhs.s loc_1E198 subq.w #1,y_pos(a1) tst.b (Reverse_gravity_flag).w beq.s loc_1E17E neg.w d3 addq.w #2,y_pos(a1) loc_1E17E: sub.w d3,y_pos(a1) tst.w y_vel(a1) bmi.s loc_1E198 bsr.w RideObject_SetRide move.w d6,d4 addi.b #$11,d4 bset d4,d6 moveq #-1,d4 rts ; --------------------------------------------------------------------------- loc_1E198: moveq #0,d4 rts ; =============== S U B R O U T I N E ======================================= MvSonicOnPtfm: tst.b (Reverse_gravity_flag).w bne.s loc_1E1AA move.w y_pos(a0),d0 sub.w d3,d0 bra.s loc_1E1CA ; --------------------------------------------------------------------------- loc_1E1AA: move.w y_pos(a0),d0 add.w d3,d0 bra.s loc_1E1F4 ; --------------------------------------------------------------------------- ; This is hilarious. The unused S1 code was upgraded with an S3K feature tst.b (Reverse_gravity_flag).w beq.s loc_1E1C2 move.w y_pos(a0),d0 addi.w #9,d0 bra.s loc_1E1F4 ; --------------------------------------------------------------------------- loc_1E1C2: move.w y_pos(a0),d0 subi.w #9,d0 loc_1E1CA: tst.b object_control(a1) bmi.s locret_1E1F2 cmpi.b #6,routine(a1) bhs.s locret_1E1F2 tst.w (Debug_placement_mode).w bne.s locret_1E1F2 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) locret_1E1F2: rts ; --------------------------------------------------------------------------- loc_1E1F4: tst.b object_control(a1) bmi.s locret_1E21C cmpi.b #6,routine(a1) bhs.s locret_1E21C tst.w (Debug_placement_mode).w bne.s locret_1E21C moveq #0,d1 move.b y_radius(a1),d1 add.w d1,d0 move.w d0,y_pos(a1) sub.w x_pos(a0),d2 sub.w d2,x_pos(a1) locret_1E21C: rts ; End of function MvSonicOnPtfm ; =============== S U B R O U T I N E ======================================= SolidObjSloped: btst #Status_OnObj,status(a1) beq.s locret_1E280 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 btst #0,render_flags(a0) beq.s loc_1E23E not.w d0 add.w d1,d0 add.w d1,d0 loc_1E23E: bra.s loc_1E260 ; End of function SolidObjSloped ; =============== S U B R O U T I N E ======================================= SolidObjSloped2: btst #Status_OnObj,status(a1) beq.s locret_1E280 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_1E260 not.w d0 add.w d1,d0 loc_1E260: 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) locret_1E280: rts ; End of function SolidObjSloped2 ; =============== S U B R O U T I N E ======================================= SolidObjSloped4: btst #Status_OnObj,status(a1) beq.s locret_1E280 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 btst #0,render_flags(a0) beq.s loc_1E2A0 not.w d0 add.w d1,d0 loc_1E2A0: andi.w #$FFFE,d0 bra.s loc_1E260 ; End of function SolidObjSloped4 ; =============== S U B R O U T I N E ======================================= SolidObjectTop: lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s SolidObjectTop_1P movem.l (sp)+,d1-d4 lea (Player_2).w,a1 addq.b #p2_standing_bit-p1_standing_bit,d6 ; End of function SolidObjectTop ; =============== S U B R O U T I N E ======================================= SolidObjectTop_1P: btst d6,status(a0) beq.w loc_1E42E move.w d1,d2 add.w d2,d2 btst #Status_InAir,status(a1) bne.s loc_1E2E0 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_1E2E0 cmp.w d2,d0 blo.s loc_1E2F4 loc_1E2E0: bclr #Status_OnObj,status(a1) bset #Status_InAir,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_1E2F4: move.w d4,d2 bsr.w MvSonicOnPtfm moveq #0,d4 rts ; End of function SolidObjectTop_1P ; =============== S U B R O U T I N E ======================================= SolidObjectTopSloped2: lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s SolidObjectTopSloped2_1P movem.l (sp)+,d1-d4 lea (Player_2).w,a1 addq.b #p2_standing_bit-p1_standing_bit,d6 ; End of function SolidObjectTopSloped2 ; =============== S U B R O U T I N E ======================================= SolidObjectTopSloped2_1P: btst d6,status(a0) beq.w SolidObjCheckSloped2 move.w d1,d2 add.w d2,d2 btst #Status_InAir,status(a1) bne.s loc_1E338 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_1E338 cmp.w d2,d0 blo.s loc_1E34C loc_1E338: bclr #Status_OnObj,status(a1) bset #Status_InAir,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_1E34C: move.w d4,d2 bsr.w SolidObjSloped2 moveq #0,d4 rts ; End of function SolidObjectTopSloped2_1P ; =============== S U B R O U T I N E ======================================= SolidObjectTopSloped: lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s SolidObjectTopSloped_1P movem.l (sp)+,d1-d4 lea (Player_2).w,a1 addq.b #p2_standing_bit-p1_standing_bit,d6 ; End of function SolidObjectTopSloped ; =============== S U B R O U T I N E ======================================= SolidObjectTopSloped_1P: btst d6,status(a0) beq.w SolidObjCheckSloped move.w d1,d2 add.w d2,d2 btst #Status_InAir,status(a1) bne.s loc_1E390 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_1E390 cmp.w d2,d0 blo.s loc_1E3A4 loc_1E390: bclr #Status_OnObj,status(a1) bset #Status_InAir,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_1E3A4: move.w d4,d2 bsr.w SolidObjSloped moveq #0,d4 rts ; End of function SolidObjectTopSloped_1P ; --------------------------------------------------------------------------- lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.s sub_1E3C4 movem.l (sp)+,d1-d4 lea (Player_2).w,a1 addq.b #p2_standing_bit-p1_standing_bit,d6 ; =============== S U B R O U T I N E ======================================= sub_1E3C4: btst d6,status(a0) bne.s loc_1E3D6 btst #Status_OnObj,status(a1) bne.s loc_1E402 bra.w loc_1E42E ; --------------------------------------------------------------------------- loc_1E3D6: move.w d1,d2 add.w d2,d2 btst #Status_InAir,status(a1) bne.s loc_1E3F2 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_1E3F2 cmp.w d2,d0 blo.s loc_1E406 loc_1E3F2: bclr #Status_OnObj,status(a1) bset #Status_InAir,status(a1) bclr d6,status(a0) loc_1E402: moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_1E406: move.w d4,d2 bsr.w MvSonicOnPtfm moveq #0,d4 rts ; End of function sub_1E3C4 ; =============== S U B R O U T I N E ======================================= sub_1E410: tst.w y_vel(a1) bmi.w locret_1E4D4 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.w locret_1E4D4 cmp.w d2,d0 bhs.w locret_1E4D4 bra.s loc_1E44C ; --------------------------------------------------------------------------- loc_1E42E: tst.w y_vel(a1) bmi.w locret_1E4D4 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.w locret_1E4D4 add.w d1,d1 cmp.w d1,d0 bhs.w locret_1E4D4 loc_1E44C: tst.b (Reverse_gravity_flag).w bne.w loc_1E4D6 move.w y_pos(a0),d0 sub.w d3,d0 loc_1E45A: 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 locret_1E4D4 cmpi.w #-$10,d0 blo.w locret_1E4D4 tst.b object_control(a1) bmi.w locret_1E4D4 cmpi.b #6,routine(a1) bhs.w locret_1E4D4 add.w d0,d2 addq.w #3,d2 move.w d2,y_pos(a1) ; End of function sub_1E410 ; =============== S U B R O U T I N E ======================================= RideObject_SetRide: btst #Status_OnObj,status(a1) beq.s loc_1E4A0 movea.w interact(a1),a3 bclr d6,status(a3) loc_1E4A0: move.w a0,interact(a1) move.b #0,angle(a1) move.w #0,y_vel(a1) move.w x_vel(a1),ground_vel(a1) bset #Status_OnObj,status(a1) bset d6,status(a0) bclr #Status_InAir,status(a1) beq.s locret_1E4D4 move.l a0,-(sp) movea.l a1,a0 jsr (Player_TouchFloor).l movea.l (sp)+,a0 locret_1E4D4: rts ; End of function RideObject_SetRide ; --------------------------------------------------------------------------- loc_1E4D6: move.w y_pos(a0),d0 add.w d3,d0 move.w y_pos(a1),d2 move.b y_radius(a1),d1 ext.w d1 neg.w d1 add.w d2,d1 subq.w #4,d1 sub.w d0,d1 bhi.s locret_1E4D4 cmpi.w #-$10,d1 blo.s locret_1E4D4 tst.b object_control(a1) bmi.s locret_1E4D4 cmpi.b #6,routine(a1) bhs.s locret_1E4D4 sub.w d1,d2 subq.w #4,d2 move.w d2,y_pos(a1) bra.s RideObject_SetRide ; --------------------------------------------------------------------------- SolidObjCheckSloped2: tst.w y_vel(a1) bmi.w locret_1E4D4 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.s locret_1E4D4 add.w d1,d1 cmp.w d1,d0 bhs.s locret_1E4D4 btst #0,render_flags(a0) beq.s loc_1E534 not.w d0 add.w d1,d0 loc_1E534: 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 loc_1E45A ; --------------------------------------------------------------------------- SolidObjCheckSloped: tst.w y_vel(a1) bmi.w locret_1E4D4 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 add.w d1,d0 bmi.w locret_1E4D4 add.w d1,d1 cmp.w d1,d0 bhs.w locret_1E4D4 btst #0,render_flags(a0) beq.s loc_1E570 not.w d0 add.w d1,d0 loc_1E570: move.b (a2,d0.w),d3 ext.w d3 move.w y_pos(a0),d0 sub.w d3,d0 bra.w loc_1E45A ; =============== S U B R O U T I N E ======================================= CheckPlayerReleaseFromObj: lea (Player_1).w,a1 btst #p1_standing_bit,status(a0) beq.s loc_1E5AE jsr (SonicOnObjHitFloor).l tst.w d1 beq.s loc_1E598 bpl.s loc_1E5AE loc_1E598: lea (Player_1).w,a1 bclr #Status_OnObj,status(a1) bset #Status_InAir,status(a1) bclr #p1_standing_bit,status(a0) loc_1E5AE: lea (Player_2).w,a1 btst #p2_standing_bit,status(a0) beq.s loc_1E5DC jsr (SonicOnObjHitFloor).l tst.w d1 beq.s loc_1E5C6 bpl.s loc_1E5DC loc_1E5C6: lea (Player_2).w,a1 bclr #Status_OnObj,status(a1) bset #Status_InAir,status(a1) bclr #p2_standing_bit,status(a0) loc_1E5DC: moveq #0,d4 rts ; End of function CheckPlayerReleaseFromObj ; --------------------------------------------------------------------------- Obj_Explosion: ; this object is reused from prev title moveq #0,d0 move.b routine(a0),d0 move.w Explosion_Index(pc,d0.w),d1 jmp Explosion_Index(pc,d1.w) ; --------------------------------------------------------------------------- Explosion_Index: dc.w loc_1E5F6-Explosion_Index dc.w loc_1E61A-Explosion_Index dc.w loc_1E66E-Explosion_Index dc.w loc_1E626-Explosion_Index ; --------------------------------------------------------------------------- loc_1E5F6: addq.b #2,routine(a0) jsr (AllocateObject).l bne.s loc_1E61A move.l #Obj_Animal,(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w $3E(a0),$3E(a1) ;$3E is copied all the way from touch response in here (value didnt change for the varable same as sonic 2) loc_1E61A: moveq #signextendB(sfx_Break),d0 jsr (Play_SFX).l addq.b #2,routine(a0) loc_1E626: move.l #Map_Explosion,mappings(a0) move.w art_tile(a0),d0 andi.w #high_priority,d0 ori.w #ArtTile_Explosion,d0 move.w d0,art_tile(a0) move.b #4,render_flags(a0) move.w #$80,priority(a0) move.b #0,collision_flags(a0) move.b #$C,width_pixels(a0) move.b #$C,height_pixels(a0) move.b #3,anim_frame_timer(a0) move.b #0,mapping_frame(a0) move.l #loc_1E66E,(a0) loc_1E66E: subq.b #1,anim_frame_timer(a0) bpl.s loc_1E688 move.b #7,anim_frame_timer(a0) addq.b #1,mapping_frame(a0) cmpi.b #5,mapping_frame(a0) beq.w Delete_Current_Sprite loc_1E688: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Obj_FireShield_Dissipate: move.l #Map_Explosion,mappings(a0) move.w #make_art_tile(ArtTile_Explosion,0,0),art_tile(a0) move.b #4,render_flags(a0) move.w #$280,priority(a0) move.b #$C,width_pixels(a0) move.b #$C,height_pixels(a0) move.b #3,anim_frame_timer(a0) move.b #1,mapping_frame(a0) move.l #loc_1E6C6,(a0) loc_1E6C6: jsr (MoveSprite2).l subq.b #1,anim_frame_timer(a0) bpl.s loc_1E6E6 move.b #3,anim_frame_timer(a0) addq.b #1,mapping_frame(a0) cmpi.b #5,mapping_frame(a0) beq.w Delete_Current_Sprite loc_1E6E6: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_1E6EC: move.l #Map_Explosion,mappings(a0) move.w #make_art_tile(ArtTile_Explosion,0,1),art_tile(a0) move.b #4,render_flags(a0) move.w #$100,priority(a0) move.b #$C,width_pixels(a0) move.b #$C,height_pixels(a0) move.b #0,mapping_frame(a0) move.l #loc_1E71E,(a0) loc_1E71E: subq.b #1,anim_frame_timer(a0) bmi.s loc_1E726 rts ; --------------------------------------------------------------------------- loc_1E726: move.b #3,anim_frame_timer(a0) move.l #loc_1E732,(a0) loc_1E732: jsr (MoveSprite2).l subq.b #1,anim_frame_timer(a0) bpl.s loc_1E752 move.b #7,anim_frame_timer(a0) addq.b #1,mapping_frame(a0) cmpi.b #5,mapping_frame(a0) beq.w Delete_Current_Sprite loc_1E752: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Map_Explosion: include "General/Sprites/Enemy Misc/Map - Explosion.asm" ; --------------------------------------------------------------------------- Obj_AIZ1Tree: move.l #Map_AIZ1Tree,mappings(a0) move.w #$180,priority(a0) move.b #8,width_pixels(a0) move.b #4,render_flags(a0) move.w #make_art_tile($001,2,0),art_tile(a0) move.l #loc_1E7B0,(a0) loc_1E7B0: jmp (Sprite_OnScreen_Test).l ; --------------------------------------------------------------------------- Obj_AIZ1ZiplinePeg: move.l #Map_AIZ1ZiplinePeg,mappings(a0) move.w #$380,priority(a0) move.b #$20,width_pixels(a0) move.b #4,render_flags(a0) move.w #make_art_tile($324,2,0),art_tile(a0) move.l #loc_1E7DC,(a0) loc_1E7DC: jmp (Sprite_OnScreen_Test).l ; --------------------------------------------------------------------------- Obj_AutoSpin: move.l #Map_PathSwap,mappings(a0) move.w #make_art_tile(ArtTile_Ring,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$80,width_pixels(a0) move.b #$80,height_pixels(a0) move.w #$280,priority(a0) move.b subtype(a0),d0 btst #2,d0 beq.s loc_1E85C andi.w #7,d0 move.b d0,mapping_frame(a0) andi.w #3,d0 add.w d0,d0 move.w word_1E854(pc,d0.w),$32(a0) move.w y_pos(a0),d1 lea (Player_1).w,a1 cmp.w y_pos(a1),d1 bhs.s loc_1E83A move.b #1,$34(a0) loc_1E83A: lea (Player_2).w,a1 cmp.w y_pos(a1),d1 bhs.s loc_1E84A move.b #1,$35(a0) loc_1E84A: move.l #loc_1E9E6,(a0) bra.w loc_1E9E6 ; --------------------------------------------------------------------------- word_1E854: dc.w $20, $40, $80, $100 ; --------------------------------------------------------------------------- loc_1E85C: andi.w #3,d0 move.b d0,mapping_frame(a0) add.w d0,d0 move.w word_1E854(pc,d0.w),$32(a0) move.w x_pos(a0),d1 lea (Player_1).w,a1 cmp.w x_pos(a1),d1 bhs.s loc_1E880 move.b #1,$34(a0) loc_1E880: lea (Player_2).w,a1 cmp.w x_pos(a1),d1 bhs.s loc_1E890 move.b #1,$35(a0) loc_1E890: move.l #loc_1E896,(a0) loc_1E896: tst.w (Debug_placement_mode).w bne.s loc_1E8C0 move.w x_pos(a0),d1 lea $34(a0),a2 lea (Player_1).w,a1 bsr.s sub_1E8C6 lea (Player_2).w,a1 cmpi.w #4,(Tails_CPU_routine).w beq.w loc_1E8BA bsr.s sub_1E8C6 loc_1E8BA: jmp (Delete_Sprite_If_Not_In_Range).l ; --------------------------------------------------------------------------- loc_1E8C0: jmp (Sprite_OnScreen_Test).l ; =============== S U B R O U T I N E ======================================= sub_1E8C6: tst.b (a2)+ bne.s loc_1E944 cmp.w x_pos(a1),d1 bhi.w locret_1E9B4 move.b #1,-1(a2) move.w y_pos(a0),d2 move.w d2,d3 move.w $32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w y_pos(a1),d4 cmp.w d2,d4 blo.w locret_1E9B4 cmp.w d3,d4 bhs.w locret_1E9B4 btst #5,subtype(a0) beq.s loc_1E908 btst #Status_InAir,status(a1) bne.w locret_1E9B4 loc_1E908: btst #0,render_flags(a0) bne.s loc_1E934 btst #4,subtype(a0) bne.s loc_1E930 move.w #$580,ground_vel(a1) move.b #1,spin_dash_flag(a1) tst.b subtype(a0) bpl.s loc_1E930 move.b #$81,spin_dash_flag(a1) loc_1E930: bra.w loc_1E9B6 ; --------------------------------------------------------------------------- loc_1E934: btst #4,subtype(a0) bne.s locret_1E9B4 move.b #0,spin_dash_flag(a1) rts ; --------------------------------------------------------------------------- loc_1E944: cmp.w x_pos(a1),d1 bls.s locret_1E9B4 move.b #0,-1(a2) move.w y_pos(a0),d2 move.w d2,d3 move.w $32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w y_pos(a1),d4 cmp.w d2,d4 blo.s locret_1E9B4 cmp.w d3,d4 bhs.s locret_1E9B4 btst #5,subtype(a0) beq.s loc_1E97C btst #Status_InAir,status(a1) bne.w locret_1E9B4 loc_1E97C: btst #0,render_flags(a0) beq.s loc_1E9A6 btst #4,subtype(a0) bne.s loc_1E9A4 move.w #-$580,ground_vel(a1) move.b #1,spin_dash_flag(a1) tst.b subtype(a0) bpl.s loc_1E9A4 move.b #$81,spin_dash_flag(a1) loc_1E9A4: bra.s loc_1E9B6 ; --------------------------------------------------------------------------- loc_1E9A6: btst #4,subtype(a0) bne.s locret_1E9B4 move.b #0,spin_dash_flag(a1) locret_1E9B4: rts ; --------------------------------------------------------------------------- loc_1E9B6: btst #Status_Roll,status(a1) beq.s loc_1E9C0 rts ; --------------------------------------------------------------------------- loc_1E9C0: bset #Status_Roll,status(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #2,anim(a1) addq.w #5,y_pos(a1) moveq #signextendB(sfx_Roll),d0 jsr (Play_SFX).l rts ; End of function sub_1E8C6 ; --------------------------------------------------------------------------- loc_1E9E6: tst.w (Debug_placement_mode).w bne.s loc_1EA0E move.w y_pos(a0),d1 lea $34(a0),a2 lea (Player_1).w,a1 bsr.s sub_1EA14 lea (Player_2).w,a1 cmpi.w #4,(Tails_CPU_routine).w beq.s loc_1EA08 bsr.s sub_1EA14 loc_1EA08: jmp (Delete_Sprite_If_Not_In_Range).l ; --------------------------------------------------------------------------- loc_1EA0E: jmp (Sprite_OnScreen_Test).l ; =============== S U B R O U T I N E ======================================= sub_1EA14: tst.b (a2)+ bne.w loc_1EAB0 cmp.w y_pos(a1),d1 bhi.w locret_1EB30 move.b #1,-1(a2) move.w x_pos(a0),d2 move.w d2,d3 move.w $32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w x_pos(a1),d4 cmp.w d2,d4 blo.w locret_1EB30 cmp.w d3,d4 bhs.w locret_1EB30 btst #5,subtype(a0) beq.s loc_1EA58 btst #1,status(a1) bne.w locret_1EB30 loc_1EA58: btst #0,render_flags(a0) bne.s loc_1EA9E btst #4,subtype(a0) bne.s loc_1EA9A move.b #1,spin_dash_flag(a1) tst.b subtype(a0) bpl.s loc_1EA7A move.b #$81,spin_dash_flag(a1) loc_1EA7A: btst #6,subtype(a0) beq.s loc_1EA9A bclr #Status_InAir,status(a1) move.b #$40,angle(a1) move.w y_vel(a1),ground_vel(a1) move.w #0,x_vel(a1) loc_1EA9A: bra.w loc_1E9B6 ; --------------------------------------------------------------------------- loc_1EA9E: btst #4,subtype(a0) bne.w locret_1EB30 move.b #0,spin_dash_flag(a1) rts ; --------------------------------------------------------------------------- loc_1EAB0: cmp.w y_pos(a1),d1 bls.s locret_1EB30 move.b #0,-1(a2) move.w x_pos(a0),d2 move.w d2,d3 move.w $32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w x_pos(a1),d4 cmp.w d2,d4 blo.s locret_1EB30 cmp.w d3,d4 bhs.s locret_1EB30 btst #5,subtype(a0) beq.s loc_1EAE8 btst #Status_InAir,status(a1) bne.w locret_1EB30 loc_1EAE8: btst #0,render_flags(a0) beq.s loc_1EB22 btst #4,subtype(a0) bne.s loc_1EB1E move.b #1,spin_dash_flag(a1) tst.b subtype(a0) bpl.s loc_1EB0A move.b #$81,spin_dash_flag(a1) loc_1EB0A: btst #6,subtype(a0) beq.s loc_1EB1E bclr #Status_InAir,status(a1) move.b #$40,angle(a1) loc_1EB1E: bra.w loc_1E9B6 ; --------------------------------------------------------------------------- loc_1EB22: btst #4,subtype(a0) bne.s locret_1EB30 move.b #0,spin_dash_flag(a1) locret_1EB30: rts ; End of function sub_1EA14 ; --------------------------------------------------------------------------- byte_1EB32: dc.b $96 dc.b $94 dc.b $95 even ; --------------------------------------------------------------------------- Obj_S2LavaMarker: moveq #0,d0 move.b subtype(a0),d0 move.b byte_1EB32(pc,d0.w),collision_flags(a0) move.l #Map_S2LavaMarker,mappings(a0) tst.w (Debug_placement_mode).w beq.s loc_1EB58 move.l #Map_S2LavaMarkerDebug,mappings(a0) loc_1EB58: move.w #make_art_tile(ArtTile_Ring,0,1),art_tile(a0) move.b #$84,render_flags(a0) move.b #$80,width_pixels(a0) move.b #$80,height_pixels(a0) move.w #$200,priority(a0) move.b subtype(a0),mapping_frame(a0) move.l #loc_1EB82,(a0) loc_1EB82: tst.w (Competition_mode).w bne.s loc_1EB9C move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_1EBAA loc_1EB9C: tst.w (Debug_placement_mode).w beq.s locret_1EBA8 jsr (Draw_Sprite).l locret_1EBA8: rts ; --------------------------------------------------------------------------- loc_1EBAA: move.w respawn_addr(a0),d0 beq.s loc_1EBB6 movea.w d0,a2 bclr #7,(a2) loc_1EBB6: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- Map_S2LavaMarker: include "General/Sprites/Level Misc/Map - Lava Marker S2.asm" Map_S2LavaMarkerDebug: include "General/Sprites/Level Misc/Map - Lava Marker S2 Debug.asm" ; --------------------------------------------------------------------------- Obj_InvisibleBlock: move.l #Map_InvisibleBlock,mappings(a0) move.w #make_art_tile(ArtTile_Ring,0,1),art_tile(a0) ori.b #4,render_flags(a0) move.w #$200,priority(a0) bset #7,status(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,height_pixels(a0) tst.w (Competition_mode).w beq.s loc_1EC66 move.l #loc_1ECAA,(a0) bra.s loc_1ECAA ; --------------------------------------------------------------------------- loc_1EC66: move.l #loc_1EC6C,(a0) loc_1EC6C: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull2 move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_1EBAA tst.w (Debug_placement_mode).w beq.s locret_1ECA8 jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_1ECA8: rts ; --------------------------------------------------------------------------- loc_1ECAA: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bra.w SolidObjectFull2 ; --------------------------------------------------------------------------- Map_InvisibleBlock: include "General/Sprites/Level Misc/Map - Invisible Block.asm" ; --------------------------------------------------------------------------- byte_1ED1A: dc.b $14, $28, $20, 0 dc.b $24, $48, $30, 1 dc.b $34, $68, $40, 2 even ; --------------------------------------------------------------------------- Obj_HCZBreakableBar: move.l #Map_HCZBreakableBar,mappings(a0) move.w #make_art_tile($3CA,2,0),art_tile(a0) move.b #4,render_flags(a0) move.w #$200,priority(a0) moveq #0,d0 move.b subtype(a0),d0 move.w d0,d1 andi.b #$F,d0 mulu.w #60,d0 move.w d0,$30(a0) andi.w #$30,d1 lsr.w #2,d1 lea byte_1ED1A(pc,d1.w),a1 tst.b subtype(a0) bpl.s loc_1ED8E moveq #0,d0 move.b (a1)+,d0 move.w d0,$36(a0) move.b (a1)+,d0 move.w d0,$38(a0) move.b (a1)+,width_pixels(a0) move.b #4,height_pixels(a0) move.b (a1)+,d0 addq.b #4,d0 move.b d0,mapping_frame(a0) move.l #loc_1EF64,(a0) bra.w loc_1EF64 ; --------------------------------------------------------------------------- loc_1ED8E: moveq #0,d0 move.b (a1)+,d0 move.w d0,$36(a0) move.b (a1)+,d0 move.w d0,$38(a0) move.b #4,width_pixels(a0) move.b (a1)+,height_pixels(a0) move.b (a1)+,mapping_frame(a0) move.l #loc_1EDB0,(a0) loc_1EDB0: lea $32(a0),a2 tst.w $30(a0) beq.s loc_1EDC6 tst.w (a2) beq.s loc_1EDC6 subq.w #1,$30(a0) beq.w loc_1EEEC loc_1EDC6: lea (Player_1).w,a1 move.w (Ctrl_1).w,d1 moveq #0,d2 bsr.s sub_1EDEC addq.w #1,a2 lea (Player_2).w,a1 move.w (Ctrl_2).w,d1 moveq #1,d2 bsr.s sub_1EDEC tst.b $3A(a0) bne.w loc_1EEEC bra.w Sprite_OnScreen_Test ; =============== S U B R O U T I N E ======================================= sub_1EDEC: tst.b (a2) beq.s loc_1EE4E move.w y_pos(a0),d0 sub.w $36(a0),d0 btst #button_up+8,d1 beq.s loc_1EE0C subq.w #1,y_pos(a1) cmp.w y_pos(a1),d0 blo.s loc_1EE0C move.w d0,y_pos(a1) loc_1EE0C: add.w $38(a0),d0 btst #button_down+8,d1 beq.s loc_1EE24 addq.w #1,y_pos(a1) cmp.w y_pos(a1),d0 bhs.s loc_1EE24 move.w d0,y_pos(a1) loc_1EE24: andi.w #button_A_mask|button_B_mask|button_C_mask,d1 beq.w locret_1EEEA clr.b (a2) move.b #$3C,2(a2) bclr d2,(_unkF7C7).w andi.b #$FE,object_control(a1) btst #6,subtype(a0) bne.s locret_1EE4C move.b #1,$3A(a0) locret_1EE4C: rts ; --------------------------------------------------------------------------- loc_1EE4E: tst.b 2(a2) beq.s loc_1EE5A subq.b #1,2(a2) rts ; --------------------------------------------------------------------------- loc_1EE5A: moveq #0,d1 move.b height_pixels(a0),d1 move.w y_pos(a0),d0 sub.w d1,d0 move.w y_pos(a1),d2 cmp.w d0,d2 blo.s locret_1EEEA add.w d1,d0 add.w d1,d0 cmp.w d0,d2 bhs.s locret_1EEEA move.w x_pos(a0),d0 addi.w #$14,d0 cmp.w x_pos(a1),d0 bhs.s locret_1EEEA addi.w #$10,d0 cmp.w x_pos(a1),d0 blo.s locret_1EEEA cmpi.b #4,routine(a1) bhs.s locret_1EEEA tst.b object_control(a1) bne.s locret_1EEEA move.w y_pos(a0),d0 sub.w $36(a0),d0 cmp.w y_pos(a1),d0 blo.s loc_1EEAE move.w d0,y_pos(a1) loc_1EEAE: add.w $38(a0),d0 cmp.w y_pos(a1),d0 bhs.s loc_1EEBC move.w d0,y_pos(a1) loc_1EEBC: clr.w x_vel(a1) clr.w y_vel(a1) move.w x_pos(a0),d0 addi.w #$14,d0 move.w d0,x_pos(a1) bclr #Status_Facing,status(a1) move.b #$11,anim(a1) move.b #1,object_control(a1) bset d2,(_unkF7C7).w move.b #1,(a2) locret_1EEEA: rts ; End of function sub_1EDEC ; --------------------------------------------------------------------------- loc_1EEEC: tst.b $32(a0) beq.s loc_1EEF8 andi.b #$FE,(Player_1+object_control).w loc_1EEF8: tst.b $33(a0) beq.s loc_1EF04 andi.b #$FE,(Player_2+object_control).w loc_1EF04: clr.b (_unkF7C7).w clr.w $32(a0) move.l #loc_1EF3E,(a0) move.b #3,mapping_frame(a0) move.w #$400,x_vel(a0) move.w #0,y_vel(a0) lea (word_1F108).l,a4 lea (byte_1F0F0).l,a2 moveq #0,d1 move.b height_pixels(a0),d1 lsr.w #2,d1 subq.w #1,d1 bsr.w sub_1F188 loc_1EF3E: tst.b $3F(a0) beq.s loc_1EF4A subq.b #1,$3F(a0) bra.s loc_1EF56 ; --------------------------------------------------------------------------- loc_1EF4A: jsr (MoveSprite2).l addi.w #8,y_vel(a0) loc_1EF56: tst.b render_flags(a0) bpl.w loc_1EBAA jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_1EF64: lea $32(a0),a2 tst.w $30(a0) beq.s loc_1EF7A tst.w (a2) beq.s loc_1EF7A subq.w #1,$30(a0) beq.w loc_1F09A loc_1EF7A: lea (Player_1).w,a1 move.w (Ctrl_1).w,d1 moveq #0,d2 bsr.s sub_1EFA0 addq.w #1,a2 lea (Player_2).w,a1 move.w (Ctrl_2).w,d1 moveq #1,d2 bsr.s sub_1EFA0 tst.b $3A(a0) bne.w loc_1F09A bra.w Sprite_OnScreen_Test ; =============== S U B R O U T I N E ======================================= sub_1EFA0: tst.b (a2) beq.s loc_1F002 move.w x_pos(a0),d0 sub.w $36(a0),d0 btst #button_left+8,d1 beq.s loc_1EFC0 subq.w #1,x_pos(a1) cmp.w x_pos(a1),d0 blo.s loc_1EFC0 move.w d0,x_pos(a1) loc_1EFC0: add.w $38(a0),d0 btst #button_right+8,d1 beq.s loc_1EFD8 addq.w #1,x_pos(a1) cmp.w x_pos(a1),d0 bhs.s loc_1EFD8 move.w d0,x_pos(a1) loc_1EFD8: andi.w #button_A_mask|button_B_mask|button_C_mask,d1 beq.w locret_1F098 clr.b (a2) move.b #$3C,2(a2) bclr d2,(_unkF7C7).w andi.b #$FE,object_control(a1) btst #6,subtype(a0) bne.s locret_1F000 move.b #1,$3A(a0) locret_1F000: rts ; --------------------------------------------------------------------------- loc_1F002: tst.b 2(a2) beq.s loc_1F00E subq.b #1,2(a2) rts ; --------------------------------------------------------------------------- loc_1F00E: moveq #0,d1 move.b width_pixels(a0),d1 move.w x_pos(a0),d0 sub.w d1,d0 move.w x_pos(a1),d2 cmp.w d0,d2 blo.s locret_1F098 add.w d1,d0 add.w d1,d0 cmp.w d0,d2 bhs.s locret_1F098 move.w y_pos(a0),d0 subi.w #$14,d0 cmp.w y_pos(a1),d0 bhs.s locret_1F098 addi.w #$10,d0 cmp.w y_pos(a1),d0 blo.s locret_1F098 cmpi.b #4,routine(a1) bhs.s locret_1F098 tst.b object_control(a1) bne.s locret_1F098 move.w x_pos(a0),d0 sub.w $36(a0),d0 cmp.w x_pos(a1),d0 blo.s loc_1F062 move.w d0,x_pos(a1) loc_1F062: add.w $38(a0),d0 cmp.w x_pos(a1),d0 bhs.s loc_1F070 move.w d0,x_pos(a1) loc_1F070: clr.w x_vel(a1) clr.w y_vel(a1) move.w y_pos(a0),d0 subi.w #$14,d0 move.w d0,y_pos(a1) move.b #$14,anim(a1) move.b #1,object_control(a1) bset d2,(_unkF7C7).w move.b #1,(a2) locret_1F098: rts ; End of function sub_1EFA0 ; --------------------------------------------------------------------------- loc_1F09A: tst.b $32(a0) beq.s loc_1F0A6 andi.b #$FE,(Player_1+object_control).w loc_1F0A6: tst.b $33(a0) beq.s loc_1F0B2 andi.b #$FE,(Player_2+object_control).w loc_1F0B2: clr.b (_unkF7C7).w clr.w $32(a0) move.l #loc_1EF3E,(a0) move.b #7,mapping_frame(a0) move.w #0,x_vel(a0) move.w #-$400,y_vel(a0) lea (word_1F148).l,a4 lea (byte_1F0F0).l,a2 moveq #0,d1 move.b width_pixels(a0),d1 lsr.w #2,d1 subq.w #1,d1 bsr.w sub_1F188 bra.w loc_1EF3E ; --------------------------------------------------------------------------- byte_1F0F0: dc.b 7, 5, 2, 0, 1, 3, 4, 6, 7, 5, 2, 0, 1, 3, 4, 6, 8, 9, $A, $B dc.b $C, $D, $E, $F even word_1F108: dc.w 0, -$1C dc.w 0, -$14 dc.w 0, -$C dc.w 0, -4 dc.w 0, 4 dc.w 0, $C dc.w 0, $14 dc.w 0, $1C dc.w 0, $24 dc.w 0, -$24 dc.w 0, $2C dc.w 0, -$2C dc.w 0, $34 dc.w 0, -$34 dc.w 0, $3C dc.w 0, -$3C word_1F148: dc.w -$1C, 0 dc.w -$14, 0 dc.w -$C, 0 dc.w -4, 0 dc.w 4, 0 dc.w $C, 0 dc.w $14, 0 dc.w $1C, 0 dc.w $24, 0 dc.w -$24, 0 dc.w $2C, 0 dc.w -$2C, 0 dc.w $34, 0 dc.w -$34, 0 dc.w $3C, 0 dc.w -$3C, 0 ; =============== S U B R O U T I N E ======================================= sub_1F188: move.w x_pos(a0),d2 move.w y_pos(a0),d3 move.w priority(a0),d4 movea.l a0,a1 bra.s loc_1F1A0 ; --------------------------------------------------------------------------- loc_1F198: jsr (AllocateObjectAfterCurrent).l bne.s loc_1F1FA loc_1F1A0: move.l (a0),(a1) 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.w d4,priority(a1) move.b #4,width_pixels(a1) move.b #4,height_pixels(a1) move.b mapping_frame(a0),mapping_frame(a1) move.w x_vel(a0),x_vel(a1) move.w y_vel(a0),y_vel(a1) move.b (a2)+,$3F(a1) dbf d1,loc_1F198 loc_1F1FA: moveq #signextendB(sfx_Collapse),d0 jmp (Play_SFX).l ; End of function sub_1F188 ; --------------------------------------------------------------------------- Obj_HCZWaveSplash: move.l #Map_HCZWaveSplash,mappings(a0) move.w #make_art_tile($42E,0,1),art_tile(a0) move.b #4,render_flags(a0) move.b #$80,width_pixels(a0) move.b #8,height_pixels(a0) bset #6,render_flags(a0) move.w #1,mainspr_childsprites(a0) lea sub2_x_pos(a0),a2 move.w x_pos(a0),(a2) addi.w #$C0,(a2)+ move.w y_pos(a0),(a2)+ move.l #loc_1F244,(a0) loc_1F244: move.w (Camera_X_pos).w,d1 andi.w #$FFE0,d1 addi.w #$60,d1 btst #0,(Level_frame_counter+1).w beq.s loc_1F25C addi.w #$20,d1 loc_1F25C: move.w d1,x_pos(a0) move.w (Water_level).w,d1 move.w d1,y_pos(a0) lea sub2_x_pos(a0),a2 move.w x_pos(a0),(a2) addi.w #$C0,(a2)+ move.w y_pos(a0),(a2)+ tst.b $32(a0) bne.s loc_1F296 tst.b (Ctrl_1_pressed_logical).w bmi.s loc_1F28A tst.b (Ctrl_2_pressed_logical).w bpl.s loc_1F2A6 loc_1F28A: addq.b #3,mapping_frame(a0) move.b #1,$32(a0) bra.s loc_1F2C4 ; --------------------------------------------------------------------------- loc_1F296: tst.w (Game_paused).w bne.s loc_1F2C4 move.b #0,$32(a0) subq.b #3,mapping_frame(a0) loc_1F2A6: subq.b #1,anim_frame_timer(a0) bpl.s loc_1F2C4 move.b #9,anim_frame_timer(a0) addq.b #1,mapping_frame(a0) cmpi.b #4,mapping_frame(a0) blo.s loc_1F2C4 move.b #1,mapping_frame(a0) loc_1F2C4: move.b mapping_frame(a0),1(a2) bra.w Draw_Sprite ; --------------------------------------------------------------------------- Map_HCZWaveSplash: include "Levels/HCZ/Misc Object Data/Map - Wave Splash.asm" ; --------------------------------------------------------------------------- byte_1F38A: dc.b $10, $10 dc.b $20, $10 dc.b $30, $10 dc.b $40, $10 ; --------------------------------------------------------------------------- Obj_HCZBlock: moveq #0,d0 move.b subtype(a0),d0 move.b d0,mapping_frame(a0) add.w d0,d0 lea byte_1F38A(pc,d0.w),a1 move.b (a1)+,width_pixels(a0) move.b (a1)+,height_pixels(a0) move.l #Map_HCZBlock,mappings(a0) move.w #make_art_tile($3D4,2,0),art_tile(a0) ori.b #4,render_flags(a0) move.w #$280,priority(a0) move.l #loc_1F3CA,(a0) loc_1F3CA: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull2 bra.w Sprite_OnScreen_Test ; --------------------------------------------------------------------------- Obj_InvisibleShockBlock: bset #5,shield_reaction(a0) bra.s Obj_InvisibleHurtBlockHorizontal ; --------------------------------------------------------------------------- Obj_InvisibleLavaBlock: bset #4,shield_reaction(a0) Obj_InvisibleHurtBlockHorizontal: move.l #Map_InvisibleBlock,mappings(a0) move.w #make_art_tile(ArtTile_Ring,0,1),art_tile(a0) ori.b #4,render_flags(a0) move.w #$200,priority(a0) bset #7,status(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,height_pixels(a0) btst #0,status(a0) beq.s loc_1F448 move.l #loc_1F4C4,(a0) rts ; --------------------------------------------------------------------------- loc_1F448: btst #1,status(a0) beq.s loc_1F458 move.l #loc_1F528,(a0) rts ; --------------------------------------------------------------------------- loc_1F458: move.l #loc_1F45E,(a0) loc_1F45E: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull2 move.b status(a0),d6 andi.b #standing_mask,d6 beq.s loc_1F4A2 move.b d6,d0 andi.b #p1_standing,d0 beq.s loc_1F494 lea (Player_1).w,a1 bsr.w sub_1F58C loc_1F494: andi.b #p2_standing,d6 beq.s loc_1F4A2 lea (Player_2).w,a1 bsr.w sub_1F58C loc_1F4A2: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_1EBAA tst.w (Debug_placement_mode).w beq.s locret_1F4C2 jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_1F4C2: rts ; --------------------------------------------------------------------------- loc_1F4C4: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull2 swap d6 andi.w #3,d6 beq.s loc_1F506 move.b d6,d0 andi.b #1,d0 beq.s loc_1F4F8 lea (Player_1).w,a1 bsr.w sub_1F58C loc_1F4F8: andi.b #2,d6 beq.s loc_1F506 lea (Player_2).w,a1 bsr.w sub_1F58C loc_1F506: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_1EBAA tst.w (Debug_placement_mode).w beq.s locret_1F526 jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_1F526: rts ; --------------------------------------------------------------------------- loc_1F528: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull2 swap d6 andi.w #$C,d6 beq.s loc_1F56A move.b d6,d0 andi.b #4,d0 beq.s loc_1F55C lea (Player_1).w,a1 bsr.w sub_1F58C loc_1F55C: andi.b #8,d6 beq.s loc_1F56A lea (Player_2).w,a1 bsr.w sub_1F58C loc_1F56A: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_1EBAA tst.w (Debug_placement_mode).w beq.s locret_1F58A jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_1F58A: rts ; =============== S U B R O U T I N E ======================================= sub_1F58C: move.b shield_reaction(a0),d0 andi.b #$73,d0 and.b shield_reaction(a1),d0 bne.s locret_1F59E bsr.w sub_24280 locret_1F59E: rts ; End of function sub_1F58C ; --------------------------------------------------------------------------- Obj_InvisibleHurtBlockVertical: move.l #Map_InvisibleBlock,mappings(a0) move.w #make_art_tile(ArtTile_Ring,0,1),art_tile(a0) ori.b #4,render_flags(a0) move.w #$200,priority(a0) bset #7,status(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,height_pixels(a0) btst #0,status(a0) beq.s loc_1F5F0 move.l #loc_1F66C,(a0) rts ; --------------------------------------------------------------------------- loc_1F5F0: btst #1,status(a0) beq.s loc_1F600 move.l #loc_1F6D0,(a0) rts ; --------------------------------------------------------------------------- loc_1F600: move.l #loc_1F606,(a0) loc_1F606: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull2 move.b status(a0),d6 andi.b #standing_mask,d6 beq.s loc_1F64A move.b d6,d0 andi.b #p1_standing,d0 beq.s loc_1F63C lea (Player_1).w,a1 bsr.w sub_1F734 loc_1F63C: andi.b #p2_standing,d6 beq.s loc_1F64A lea (Player_2).w,a1 bsr.w sub_1F734 loc_1F64A: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_1EBAA tst.w (Debug_placement_mode).w beq.s locret_1F66A jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_1F66A: rts ; --------------------------------------------------------------------------- loc_1F66C: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull2 swap d6 andi.w #3,d6 beq.s loc_1F6AE move.b d6,d0 andi.b #1,d0 beq.s loc_1F6A0 lea (Player_1).w,a1 bsr.w sub_1F734 loc_1F6A0: andi.b #2,d6 beq.s loc_1F6AE lea (Player_2).w,a1 bsr.w sub_1F734 loc_1F6AE: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_1EBAA tst.w (Debug_placement_mode).w beq.s locret_1F6CE jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_1F6CE: rts ; --------------------------------------------------------------------------- loc_1F6D0: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull2 swap d6 andi.w #$C,d6 beq.s loc_1F712 move.b d6,d0 andi.b #4,d0 beq.s loc_1F704 lea (Player_1).w,a1 bsr.w sub_1F734 loc_1F704: andi.b #8,d6 beq.s loc_1F712 lea (Player_2).w,a1 bsr.w sub_1F734 loc_1F712: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_1EBAA tst.w (Debug_placement_mode).w beq.s locret_1F732 jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_1F732: rts ; =============== S U B R O U T I N E ======================================= sub_1F734: move.w d6,-(sp) move.l a0,-(sp) movea.l a1,a0 jsr (Kill_Character).l movea.l (sp)+,a0 move.w (sp)+,d6 rts ; End of function sub_1F734 ; --------------------------------------------------------------------------- Obj_AIZHollowTree: move.b #$D0,width_pixels(a0) move.l #loc_1F752,(a0) loc_1F752: bsr.w sub_1F7B8 move.b status(a0),d0 andi.b #standing_mask,d0 bne.s loc_1F7B2 tst.w $38(a0) beq.s loc_1F7B2 subq.w #1,$38(a0) bne.s loc_1F77A move.w #$1300,(Camera_min_X_pos).w move.w #$4000,(Camera_max_X_pos).w bra.s loc_1F7B2 ; --------------------------------------------------------------------------- loc_1F77A: cmpi.w #$1300,(Camera_min_X_pos).w beq.s loc_1F796 cmpi.w #$2D00,(Player_1+x_pos).w blo.s loc_1F792 move.w #$1300,(Camera_min_X_pos).w bra.s loc_1F796 ; --------------------------------------------------------------------------- loc_1F792: subq.w #4,(Camera_min_X_pos).w loc_1F796: cmpi.w #$4000,(Camera_max_X_pos).w beq.s loc_1F7B2 cmpi.w #$2D00,(Player_1+x_pos).w bhs.s loc_1F7AE move.w #$4000,(Camera_max_X_pos).w bra.s loc_1F7B2 ; --------------------------------------------------------------------------- loc_1F7AE: addq.w #4,(Camera_max_X_pos).w loc_1F7B2: jmp (Delete_Sprite_If_Not_In_Range).l ; =============== S U B R O U T I N E ======================================= sub_1F7B8: lea (Player_1).w,a1 lea $30(a0),a2 moveq #p1_standing_bit,d6 bsr.s sub_1F7CE lea (Player_2).w,a1 lea $34(a0),a2 ; Bug: if player 1 was riding the object, then d6 may have become dirty from ; a call to Perform_Player_DPLC, causing player 2 to behave erratically addq.b #p2_standing_bit-p1_standing_bit,d6 ; End of function sub_1F7B8 ; =============== S U B R O U T I N E ======================================= sub_1F7CE: btst d6,status(a0) bne.w loc_1F85C btst #Status_InAir,status(a1) bne.w locret_1F85A move.w x_pos(a1),d0 addi.w #$10,d0 sub.w x_pos(a0),d0 bcs.s locret_1F85A cmpi.w #$40,d0 bge.s locret_1F85A move.w y_pos(a1),d0 sub.w y_pos(a0),d0 cmpi.w #-$5A,d0 blt.s locret_1F85A cmpi.w #$A0,d0 bgt.s locret_1F85A cmpi.w #$600,x_vel(a1) blt.s locret_1F85A tst.b object_control(a1) bne.s locret_1F85A bsr.w RideObject_SetRide move.l #0,(a2) bset #6,object_control(a1) bset #1,object_control(a1) move.b #0,anim(a1) cmpa.w #Player_1,a1 bne.s locret_1F85A jsr (AllocateObjectAfterCurrent).l bne.w loc_1F848 move.l #Obj_AIZ1TreeRevealControl,(a1) loc_1F848: move.w #$2C60,(Camera_min_X_pos).w move.w #$2C60,(Camera_max_X_pos).w move.w #$3C,$38(a0) locret_1F85A: rts ; --------------------------------------------------------------------------- loc_1F85C: move.w ground_vel(a1),d0 bpl.s loc_1F864 neg.w d0 loc_1F864: cmpi.w #$600,d0 blo.w loc_1F8FE btst #Status_InAir,status(a1) bne.s loc_1F88C move.w y_pos(a1),d0 sub.w y_pos(a0),d0 addi.w #$90,d0 bmi.s AIZTree_FallOff cmpi.w #$130,d0 bls.w AIZTree_SetPlayerPos bra.s AIZTree_FallOff ; --------------------------------------------------------------------------- loc_1F88C: cmpi.w #$2C99,x_pos(a1) bhs.s loc_1F8A0 move.w #$2C99,x_pos(a1) move.w #$400,x_vel(a1) loc_1F8A0: cmpi.w #$2D66,x_pos(a1) blo.s AIZTree_FallOff move.w #$2D66,x_pos(a1) move.w #-$400,x_vel(a1) AIZTree_FallOff: bset #Status_InAir,status(a1) bclr #Status_Roll,status(a1) move.b #$13,y_radius(a1) move.b #9,x_radius(a1) move.w #1,anim(a1) bclr #Status_OnObj,status(a1) bclr d6,status(a0) move.b #0,flips_remaining(a1) move.b #4,flip_speed(a1) bclr #6,object_control(a1) bclr #1,object_control(a1) asr x_vel(a1) asr y_vel(a1) rts ; --------------------------------------------------------------------------- loc_1F8FE: cmpi.w #$400,(a2) bhs.s AIZTree_FallOff move.l d6,-(sp) move.l a1,-(sp) bsr.s AIZTree_SetPlayerPos movea.l (sp)+,a1 move.l (sp)+,d6 bra.s AIZTree_FallOff ; End of function sub_1F7CE ; --------------------------------------------------------------------------- bra.w loc_1F88C ; =============== S U B R O U T I N E ======================================= AIZTree_SetPlayerPos: btst #Status_OnObj,status(a1) beq.w locret_1F85A move.w ground_vel(a1),d0 ext.l d0 lsl.l #8,d0 add.l d0,(a2) bmi.s AIZTree_FallOff cmpi.w #$400,(a2) blo.s loc_1F93C move.w #$1300,(Camera_min_X_pos).w move.w #$4000,(Camera_max_X_pos).w loc_1F93C: move.w x_pos(a1),d2 move.w (a2),d0 lsr.w #1,d0 jsr (GetSineCosine).l muls.w #$7000,d0 swap d0 add.w x_pos(a0),d0 move.w d0,x_pos(a1) sub.w d2,d0 asl.w #8,d0 move.w d0,x_vel(a1) move.w y_pos(a1),d2 move.w (a2),d0 lsr.w #2,d0 neg.w d0 addi.w #$90,d0 add.w y_pos(a0),d0 move.w d0,y_pos(a1) sub.w d2,d0 asl.w #8,d0 move.w d0,y_vel(a1) moveq #0,d0 move.w (a2),d0 lsr.w #1,d0 divu.w #$B,d0 move.b AIZTree_PlayerFrames(pc,d0.w),mapping_frame(a1) moveq #0,d0 move.b mapping_frame(a1),d0 jmp (Perform_Player_DPLC).l ; End of function AIZTree_SetPlayerPos ; --------------------------------------------------------------------------- AIZTree_PlayerFrames: dc.b $69, $6A, $6B, $77, $6C, $6C, $6D, $6D, $6E, $6E, $6F, $6F, $70, $70, $71, $71, $72, $72, $73, $73 dc.b $74, $74, $75, $75, $76, $76, $77, $77, $6C, $6C, $6D, $6D, $6E, $6E, $6F, $6F, $70, $70, $71, $71 dc.b $72, $72, $73, $73, $74, $74, $75, $75, $6B, $6B, $6A, $6A, $69, $69 ; --------------------------------------------------------------------------- byte_1F9D0: dc.b $18, $27 dc.b $18, $17 dc.b $18, $F dc.b $E, $F dc.b $10, $28 dc.b $28, $10 dc.b $28, $10 dc.b $10, $20 ; --------------------------------------------------------------------------- Obj_AIZLRZEMZRock: moveq #0,d0 move.b subtype(a0),d0 move.w d0,d2 lsr.w #4,d0 andi.b #7,d0 move.b d0,mapping_frame(a0) add.w d0,d0 move.b byte_1F9D0(pc,d0.w),width_pixels(a0) move.b byte_1F9D0+1(pc,d0.w),d1 move.b d1,height_pixels(a0) move.b d1,y_radius(a0) move.l #Map_AIZRock,mappings(a0) move.w #make_art_tile($333,1,0),art_tile(a0) ori.b #4,render_flags(a0) move.w #$200,priority(a0) move.w x_pos(a0),$2E(a0) move.w #$40,$42(a0) cmpi.w #1,(Current_zone_and_act).w bne.s loc_1FA42 move.l #Map_AIZRock2,mappings(a0) move.w #make_art_tile($2E9,2,0),art_tile(a0) loc_1FA42: cmpi.w #$1200,(Current_zone_and_act).w bne.s loc_1FA5E move.l #Map_EMZRock,mappings(a0) move.w #make_art_tile($300,3,1),art_tile(a0) move.b #0,mapping_frame(a0) loc_1FA5E: cmpi.b #9,(Current_zone).w bne.s loc_1FA8C move.l #Map_LRZBreakableRock,mappings(a0) move.w #make_art_tile($0D3,2,0),art_tile(a0) addq.b #4,mapping_frame(a0) tst.b (Current_act).w beq.s loc_1FA8C move.l #Map_LRZBreakableRock2,mappings(a0) move.w #make_art_tile($40D,3,0),art_tile(a0) loc_1FA8C: andi.w #$F,d2 cmpi.w #$F,d2 bne.s loc_1FAA0 move.l #loc_20002,(a0) bra.w loc_20002 ; --------------------------------------------------------------------------- loc_1FAA0: move.l #loc_1FAF2,(a0) btst #2,subtype(a0) beq.s loc_1FAB8 move.l #loc_1FD08,(a0) bra.w loc_1FD08 ; --------------------------------------------------------------------------- loc_1FAB8: btst #3,subtype(a0) beq.s loc_1FACA move.l #loc_1FF48,(a0) bra.w loc_1FF48 ; --------------------------------------------------------------------------- loc_1FACA: move.w respawn_addr(a0),d0 beq.s loc_1FAF2 movea.w d0,a2 move.b (a2),d0 andi.w #$7F,d0 beq.s loc_1FAF2 sub.w d0,x_pos(a0) neg.w d0 addi.w #$40,d0 move.w d0,$42(a0) jsr (ObjCheckFloorDist).l add.w d1,y_pos(a0) loc_1FAF2: move.w (Chain_bonus_counter).w,$38(a0) move.b (Player_1+anim).w,$32(a0) move.b (Player_2+anim).w,$33(a0) move.b (Player_1+status).w,$3A(a0) move.b (Player_2+status).w,$3B(a0) moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsr (SolidObjectFull).l btst #1,subtype(a0) beq.s loc_1FB3A bsr.w sub_200A2 loc_1FB3A: btst #0,subtype(a0) beq.s loc_1FB4C move.b status(a0),d0 andi.b #standing_mask,d0 bne.s loc_1FB62 loc_1FB4C: tst.w (Competition_mode).w bne.s loc_1FB5C move.w $2E(a0),d0 jmp (Sprite_OnScreen_Test2).l ; --------------------------------------------------------------------------- loc_1FB5C: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_1FB62: cmpi.b #$18,d0 bne.s loc_1FB90 cmpi.b #2,$32(a0) beq.s loc_1FB78 cmpi.b #2,$33(a0) bne.s loc_1FB4C loc_1FB78: lea (Player_1).w,a1 move.b $32(a0),d0 bsr.s sub_1FBA8 lea (Player_2).w,a1 move.b $33(a0),d0 bsr.s sub_1FBA8 bra.w loc_1FBF8 ; --------------------------------------------------------------------------- loc_1FB90: move.b d0,d1 andi.b #8,d1 beq.s loc_1FBE0 cmpi.b #2,$32(a0) bne.s loc_1FB4C lea (Player_1).w,a1 bsr.s sub_1FBAE bra.s loc_1FBF8 ; =============== S U B R O U T I N E ======================================= sub_1FBA8: cmpi.b #2,d0 bne.s loc_1FBCC ; End of function sub_1FBA8 ; =============== S U B R O U T I N E ======================================= sub_1FBAE: bset #Status_Roll,status(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #2,anim(a1) move.w #-$300,y_vel(a1) loc_1FBCC: bset #Status_InAir,status(a1) bclr #Status_OnObj,status(a1) move.b #2,routine(a1) rts ; End of function sub_1FBAE ; --------------------------------------------------------------------------- loc_1FBE0: andi.b #$10,d0 beq.w loc_1FB4C cmpi.b #2,$33(a0) bne.w loc_1FB4C lea (Player_2).w,a1 bsr.s sub_1FBAE loc_1FBF8: move.w $38(a0),(Chain_bonus_counter).w andi.b #$E7,status(a0) tst.w (Competition_mode).w bne.w loc_1FC9C move.l #loc_1FC16,(a0) bsr.w sub_2011E loc_1FC16: cmpi.b #9,(Current_zone).w beq.s loc_1FC60 move.l #loc_1FC24,(a0) loc_1FC24: subq.b #1,anim_frame_timer(a0) bpl.s loc_1FC42 move.b #2,anim_frame_timer(a0) move.b mapping_frame(a0),d0 addq.b #1,d0 cmpi.b #7,d0 blo.s loc_1FC3E moveq #3,d0 loc_1FC3E: move.b d0,mapping_frame(a0) loc_1FC42: jsr (MoveSprite2).l addi.w #$18,y_vel(a0) tst.b render_flags(a0) bpl.s loc_1FC5A jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_1FC5A: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- loc_1FC60: move.l #loc_1FC66,(a0) loc_1FC66: subq.b #1,anim_frame_timer(a0) bpl.s loc_1FC84 move.b #7,anim_frame_timer(a0) move.b mapping_frame(a0),d0 addq.b #1,d0 andi.b #3,d0 add.b $3C(a0),d0 move.b d0,mapping_frame(a0) loc_1FC84: jsr (MoveSprite2).l addi.w #$18,y_vel(a0) tst.b render_flags(a0) bpl.s loc_1FC5A jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_1FC9C: bsr.s sub_1FCC8 move.b #3,mapping_frame(a0) move.l #loc_1FCAE,(a0) bsr.w sub_2011E loc_1FCAE: jsr (MoveSprite2).l addi.w #$18,y_vel(a0) tst.b render_flags(a0) bpl.w loc_1FC5A jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_1FCC8: jsr (AllocateObjectAfterCurrent).l bne.w locret_1FCF0 moveq #$48,d0 loc_1FCD4: move.w (a0,d0.w),(a1,d0.w) subq.w #2,d0 bcc.s loc_1FCD4 move.l (a0),$44(a1) move.l #loc_1FCF2,(a1) move.b #7,mapping_frame(a1) moveq #0,d0 locret_1FCF0: rts ; End of function sub_1FCC8 ; --------------------------------------------------------------------------- loc_1FCF2: tst.b render_flags(a0) bmi.s loc_1FD02 move.l $44(a0),(a0) move.b #0,mapping_frame(a0) loc_1FD02: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_1FD08: move.w (Player_1+x_vel).w,$30(a0) move.w (Player_2+x_vel).w,$36(a0) moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull swap d6 andi.w #3,d6 bne.s loc_1FD4E loc_1FD38: tst.w (Competition_mode).w bne.s loc_1FD48 move.w $2E(a0),d0 jmp (Sprite_OnScreen_Test2).l ; --------------------------------------------------------------------------- loc_1FD48: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_1FD4E: lea (Player_1).w,a1 move.w $30(a0),d1 move.w d6,d0 andi.w #1,d0 beq.w loc_1FDEA tst.b subtype(a0) bpl.s loc_1FD72 cmpi.b #2,character_id(a1) beq.s loc_1FDA4 bra.w loc_1FDEA ; --------------------------------------------------------------------------- loc_1FD72: tst.b (Super_Sonic_Knux_flag).w bne.s loc_1FDA4 cmpi.b #2,character_id(a1) beq.s loc_1FDA4 btst #Status_FireShield,status_secondary(a1) bne.s loc_1FD90 btst #p1_pushing_bit,status(a0) beq.s loc_1FDEA loc_1FD90: cmpi.b #2,anim(a1) bne.s loc_1FDEA move.w d1,d0 bpl.s loc_1FD9E neg.w d0 loc_1FD9E: cmpi.w #$480,d0 blo.s loc_1FDEA loc_1FDA4: bclr #p1_pushing_bit,status(a0) bsr.w sub_1FE34 btst #p2_pushing_bit,status(a0) beq.w loc_1FD38 lea (Player_2).w,a1 cmpi.b #2,character_id(a1) beq.s loc_1FDCE cmpi.b #2,anim(a1) bne.w loc_1FD38 loc_1FDCE: move.w $36(a0),x_vel(a1) move.w x_vel(a1),ground_vel(a1) bclr #p2_pushing_bit,status(a0) bclr #Status_Push,status(a1) bra.w loc_1FD38 ; --------------------------------------------------------------------------- loc_1FDEA: lea (Player_2).w,a1 move.w $36(a0),d1 btst #p2_pushing_bit,status(a0) beq.w loc_1FD38 tst.b subtype(a0) bpl.s loc_1FE0E cmpi.b #2,character_id(a1) beq.s loc_1FE2E bra.w loc_1FD38 ; --------------------------------------------------------------------------- loc_1FE0E: cmpi.b #2,character_id(a1) beq.s loc_1FE2E cmpi.b #2,anim(a1) bne.w loc_1FD38 move.w d1,d0 bpl.s loc_1FE26 neg.w d0 loc_1FE26: cmpi.w #$480,d0 blo.w loc_1FD38 loc_1FE2E: bclr #p2_pushing_bit,status(a0) ; =============== S U B R O U T I N E ======================================= sub_1FE34: bsr.w sub_1FF1E tst.w (Competition_mode).w bne.w loc_1FECE move.w d1,x_vel(a1) addq.w #4,x_pos(a1) lea (word_202F4).l,a4 move.w x_pos(a0),d0 cmp.w x_pos(a1),d0 blo.s loc_1FE64 subi.w #8,x_pos(a1) lea (word_20314).l,a4 loc_1FE64: move.w x_vel(a1),ground_vel(a1) bclr #Status_Push,status(a1) cmpi.b #2,character_id(a1) bne.s loc_1FE9E cmpi.b #1,double_jump_flag(a1) bne.s loc_1FE9E move.b #2,double_jump_flag(a1) move.b #$21,anim(a1) bclr #Status_Facing,status(a1) tst.w x_vel(a1) bpl.s loc_1FE9E bset #Status_Facing,status(a1) loc_1FE9E: moveq #0,d0 move.b mapping_frame(a0),d0 cmpi.b #9,(Current_zone).w bne.s loc_1FEBE subq.b #4,d0 move.l #loc_1FC66,(a0) add.w d0,d0 bsr.w sub_201DE bra.w loc_1FC66 ; --------------------------------------------------------------------------- loc_1FEBE: move.l #loc_1FC16,(a0) add.w d0,d0 bsr.w sub_2013A bra.w loc_1FC16 ; --------------------------------------------------------------------------- loc_1FECE: move.w d1,x_vel(a1) addq.w #4,x_pos(a1) lea (word_20370).l,a4 move.w x_pos(a0),d0 cmp.w x_pos(a1),d0 blo.s loc_1FEF2 subi.w #8,x_pos(a1) lea (word_20388).l,a4 loc_1FEF2: move.w x_vel(a1),ground_vel(a1) bclr #Status_Push,status(a1) bsr.w sub_1FCC8 move.l #loc_1FCAE,(a0) move.b #3,mapping_frame(a0) moveq #0,d0 move.b mapping_frame(a0),d0 add.w d0,d0 bsr.w sub_2013A bra.w loc_1FCAE ; End of function sub_1FE34 ; =============== S U B R O U T I N E ======================================= sub_1FF1E: bclr #p1_standing_bit,status(a0) beq.s loc_1FF32 bset #Status_InAir,(Player_1+status).w bclr #Status_OnObj,(Player_1+status).w loc_1FF32: bclr #p2_standing_bit,status(a0) beq.s locret_1FF46 bset #Status_InAir,(Player_2+status).w bclr #Status_OnObj,(Player_2+status).w locret_1FF46: rts ; End of function sub_1FF1E ; --------------------------------------------------------------------------- loc_1FF48: move.w (Player_1+y_vel).w,$30(a0) move.w (Player_2+y_vel).w,$36(a0) moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsr (SolidObjectFull).l swap d6 andi.w #4|8,d6 bne.s loc_1FF84 move.w $2E(a0),d0 jmp (Sprite_OnScreen_Test2).l ; --------------------------------------------------------------------------- loc_1FF84: move.b d6,d0 andi.b #4,d0 beq.s loc_1FFA8 lea (Player_1).w,a1 move.w $30(a0),y_vel(a1) andi.b #8,d6 beq.s loc_1FFC4 lea (Player_2).w,a1 move.w $36(a0),y_vel(a1) bra.s loc_1FFC4 ; --------------------------------------------------------------------------- loc_1FFA8: andi.b #8,d6 beq.s loc_1FFBA lea (Player_2).w,a1 move.w $36(a0),y_vel(a1) bra.s loc_1FFC4 ; --------------------------------------------------------------------------- loc_1FFBA: move.w $2E(a0),d0 jmp (Sprite_OnScreen_Test2).l ; --------------------------------------------------------------------------- loc_1FFC4: btst #p1_standing_bit,status(a0) beq.s loc_1FFDC lea (Player_1).w,a1 bset #Status_InAir,status(a1) bclr #Status_OnObj,status(a1) loc_1FFDC: btst #p2_standing_bit,status(a0) beq.s loc_1FFF4 lea (Player_2).w,a1 bset #Status_InAir,status(a1) bclr #Status_OnObj,status(a1) loc_1FFF4: move.l #loc_1FC16,(a0) bsr.w sub_2011E bra.w loc_1FC16 ; --------------------------------------------------------------------------- loc_20002: move.w (Chain_bonus_counter).w,$38(a0) moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsr (SolidObjectFull).l move.b status(a0),d0 andi.b #p1_standing,d0 bne.s loc_20036 loc_20030: jmp (Sprite_OnScreen_Test).l ; --------------------------------------------------------------------------- loc_20036: lea (Player_1).w,a1 cmpi.b #2,character_id(a1) bne.s loc_20030 bsr.s sub_20056 btst #p2_standing_bit,status(a0) beq.s loc_20088 lea (Player_2).w,a1 bsr.s sub_20056 bra.w loc_20088 ; =============== S U B R O U T I N E ======================================= sub_20056: bset #Status_Roll,status(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #2,anim(a1) move.w #-$300,y_vel(a1) bset #Status_InAir,status(a1) bclr #Status_OnObj,status(a1) move.b #2,routine(a1) rts ; End of function sub_20056 ; --------------------------------------------------------------------------- loc_20088: move.w $38(a0),(Chain_bonus_counter).w andi.b #$E7,status(a0) move.l #loc_1FC16,(a0) bsr.w sub_2011E bra.w loc_1FC16 ; =============== S U B R O U T I N E ======================================= sub_200A2: move.b status(a0),d3 andi.b #pushing_mask,d3 beq.w locret_200CA move.w x_pos(a0),d2 lea (Player_1).w,a1 move.b $3A(a0),d0 moveq #p1_pushing_bit,d6 bsr.s sub_200CC lea (Player_2).w,a1 move.b $3B(a0),d0 moveq #p2_pushing_bit,d6 bsr.s sub_200CC locret_200CA: rts ; End of function sub_200A2 ; =============== S U B R O U T I N E ======================================= sub_200CC: btst d6,d3 beq.s locret_2011C cmp.w x_pos(a1),d2 bhs.s locret_2011C btst #5,d0 beq.s locret_2011C subq.w #1,$40(a0) bpl.s locret_2011C move.w #$10,$40(a0) tst.w $42(a0) beq.s locret_2011C subq.w #1,$42(a0) subq.w #1,x_pos(a0) subq.w #1,x_pos(a1) jsr (ObjCheckFloorDist).l add.w d1,y_pos(a0) move.w respawn_addr(a0),d0 beq.s locret_2011C movea.w d0,a2 move.b $43(a0),d0 subi.b #$40,d0 neg.b d0 move.b d0,(a2) bset #7,(a2) locret_2011C: rts ; End of function sub_200CC ; =============== S U B R O U T I N E ======================================= sub_2011E: cmpi.b #9,(Current_zone).w beq.w loc_201C4 moveq #0,d0 move.b mapping_frame(a0),d0 add.w d0,d0 lea (off_202E4).l,a4 adda.w (a4,d0.w),a4 ; End of function sub_2011E ; =============== S U B R O U T I N E ======================================= sub_2013A: lea (off_2026E).l,a3 adda.w (a3,d0.w),a3 move.w (a3)+,d1 move.l (a0),d4 move.b render_flags(a0),d5 move.w x_pos(a0),d2 move.w y_pos(a0),d3 move.w #3,d6 movea.l a0,a1 bra.s loc_20162 ; --------------------------------------------------------------------------- loc_2015C: bsr.w AllocateObjectAfterCurrent bne.s loc_201BC loc_20162: move.l d4,(a1) move.l mappings(a0),mappings(a1) move.b d5,render_flags(a1) move.b (a3)+,d0 ext.w d0 add.w d2,d0 move.w d0,x_pos(a1) move.b (a3)+,d0 ext.w d0 add.w d3,d0 move.w d0,y_pos(a1) move.w art_tile(a0),art_tile(a1) ori.w #high_priority,art_tile(a1) move.w #$80,priority(a1) move.b #$18,width_pixels(a1) move.b #$18,width_pixels(a1) move.w (a4)+,x_vel(a1) move.w (a4)+,y_vel(a1) move.b d6,mapping_frame(a1) addq.b #1,d6 cmpi.b #7,d6 blo.s loc_201B8 move.w #3,d6 loc_201B8: dbf d1,loc_2015C loc_201BC: moveq #signextendB(sfx_Collapse),d0 jmp (Play_SFX).l ; End of function sub_2013A ; --------------------------------------------------------------------------- loc_201C4: move.l #loc_1FC66,(a0) moveq #0,d0 move.b mapping_frame(a0),d0 subq.b #4,d0 add.w d0,d0 lea (off_202E4).l,a4 adda.w (a4,d0.w),a4 ; =============== S U B R O U T I N E ======================================= sub_201DE: lea (off_2026E).l,a3 adda.w (a3,d0.w),a3 move.w (a3)+,d1 move.l (a0),d4 move.b render_flags(a0),d5 move.w x_pos(a0),d2 move.w y_pos(a0),d3 move.w #3,d6 movea.l a0,a1 bra.s loc_20206 ; --------------------------------------------------------------------------- loc_20200: bsr.w AllocateObjectAfterCurrent bne.s loc_20266 loc_20206: move.l d4,(a1) move.l mappings(a0),mappings(a1) move.b d5,render_flags(a1) move.b (a3)+,d0 ext.w d0 add.w d2,d0 move.w d0,x_pos(a1) move.b (a3)+,d0 ext.w d0 add.w d3,d0 move.w d0,y_pos(a1) move.w art_tile(a0),art_tile(a1) ori.w #high_priority,art_tile(a1) move.w #$80,priority(a1) move.b #$20,width_pixels(a1) move.b #$20,width_pixels(a1) move.w (a4)+,x_vel(a1) move.w (a4)+,y_vel(a1) move.b (a3)+,mapping_frame(a1) move.b mapping_frame(a1),d0 andi.b #$FC,d0 move.b d0,$3C(a1) move.b #7,anim_frame_timer(a1) dbf d1,loc_20200 loc_20266: moveq #signextendB(sfx_Collapse),d0 jmp (Play_SFX).l ; End of function sub_201DE ; --------------------------------------------------------------------------- off_2026E: dc.w word_2027E-off_2026E dc.w word_20290-off_2026E dc.w word_2029C-off_2026E dc.w word_202A6-off_2026E dc.w word_202B4-off_2026E dc.w word_202C8-off_2026E dc.w word_202C8-off_2026E dc.w word_202DC-off_2026E word_2027E: dc.w 8-1 dc.b -8, -$18 dc.b $B, -$1C dc.b -4, -$C dc.b $C, -4 dc.b -$C, 4 dc.b 4, $C dc.b -$C, $1C dc.b $C, $1C word_20290: dc.w 5-1 dc.b -4, -$C dc.b $B, -$C dc.b -4, -4 dc.b -$C, $C dc.b $C, $C word_2029C: dc.w 4-1 dc.b -4, -4 dc.b $C, -4 dc.b -$C, 4 dc.b $C, 4 word_202A6: dc.w 6-1 dc.b -8, -8 dc.b 8, -8 dc.b -8, 0 dc.b 8, 0 dc.b -8, 8 dc.b 8, 8 word_202B4: dc.w 6-1 dc.b 0, $10, 6 dc.b 0, 0, 7 dc.b -8, -$10, 1 dc.b 8, $20, 0 dc.b 0, -$18, 6 dc.b 0, $1B, 7 word_202C8: dc.w 6-1 dc.b 8, 3, 7 dc.b -8, -5, 1 dc.b -$10, 8, 1 dc.b -$18, 0, 7 dc.b 0, 0, 6 dc.b $18, 0, 6 word_202DC: dc.w 2-1 dc.b 0, $10, 1 dc.b 0, -$10, 0 off_202E4: dc.w word_202F4-off_202E4 dc.w word_20334-off_202E4 dc.w word_20348-off_202E4 dc.w word_20358-off_202E4 dc.w word_203A0-off_202E4 dc.w word_203C0-off_202E4 dc.w word_203C0-off_202E4 dc.w word_203A0-off_202E4 word_202F4: dc.w -$300, -$300 dc.w -$2C0, -$280 dc.w -$2C0, -$280 dc.w -$280, -$200 dc.w -$280, -$180 dc.w -$240, -$180 dc.w -$240, -$100 dc.w -$200, -$100 word_20314: dc.w $2C0, -$280 dc.w $300, -$300 dc.w $280, -$200 dc.w $2C0, -$280 dc.w $240, -$180 dc.w $280, -$180 dc.w $200, -$100 dc.w $240, -$100 word_20334: dc.w -$200, -$200 dc.w $200, -$200 dc.w -$100, -$1E0 dc.w -$1B0, -$1C0 dc.w $1C0, -$1C0 word_20348: dc.w -$100, -$200 dc.w $100, -$1E0 dc.w -$1B0, -$1C0 dc.w $1C0, -$1C0 word_20358: dc.w -$B0, -$1E0 dc.w $B0, -$1D0 dc.w -$80, -$200 dc.w $80, -$1E0 dc.w -$D8, -$1C0 dc.w $E0, -$1C0 word_20370: dc.w -$2C0, -$280 dc.w -$280, -$200 dc.w -$280, -$180 dc.w -$240, -$180 dc.w -$240, -$100 dc.w -$200, -$100 word_20388: dc.w $2C0, -$280 dc.w $280, -$200 dc.w $280, -$180 dc.w $240, -$180 dc.w $240, -$100 dc.w $200, -$100 word_203A0: dc.w -$300, -$300 dc.w -$2C0, -$280 dc.w -$2C0, -$280 dc.w -$280, -$200 dc.w -$280, -$180 dc.w -$240, -$180 dc.w -$240, -$100 dc.w -$200, -$100 word_203C0: dc.w $C0, -$1E0 dc.w -$80, -$1A0 dc.w -$A0, -$160 dc.w -$100, -$1E0 dc.w $40, -$1C0 dc.w $100, -$1E0 Map_LRZBreakableRock: include "Levels/LRZ/Misc Object Data/Map - Breakable Rock.asm" Map_LRZBreakableRock2: include "Levels/LRZ/Misc Object Data/Map - Breakable Rock 2.asm" ; --------------------------------------------------------------------------- Obj_CollapsingPlatform: move.l #Map_AIZCollapsingPlatform,mappings(a0) move.w #make_art_tile($001,2,0),art_tile(a0) cmpi.w #1,(Current_zone_and_act).w bne.s loc_20522 move.l #Map_AIZCollapsingPlatform2,mappings(a0) move.w #make_art_tile($001,2,0),art_tile(a0) loc_20522: move.l #byte_20CB6,$30(a0) move.l #byte_20E9E,$3C(a0) move.b #$3C,width_pixels(a0) move.b #$20,height_pixels(a0) cmpi.b #5,(Current_zone).w bne.s loc_20570 move.l #Map_ICZCollapsingBridge,mappings(a0) move.w #make_art_tile($001,2,0),art_tile(a0) move.l #byte_20CD4,$30(a0) move.l #byte_20EDE,$3C(a0) move.b #$30,width_pixels(a0) move.b #$30,height_pixels(a0) loc_20570: ori.b #4,render_flags(a0) move.w #$280,priority(a0) move.b #7,$38(a0) move.b subtype(a0),mapping_frame(a0) ori.b #$80,status(a0) move.l #loc_20594,(a0) loc_20594: tst.b $3A(a0) beq.s loc_205A6 tst.b $38(a0) beq.w ObjPlatformCollapse_CreateFragments subq.b #1,$38(a0) loc_205A6: move.b status(a0),d0 andi.b #standing_mask,d0 beq.s sub_205B6 move.b #1,$3A(a0) ; =============== S U B R O U T I N E ======================================= sub_205B6: moveq #0,d1 move.b width_pixels(a0),d1 movea.l $3C(a0),a2 move.w x_pos(a0),d4 jsr (SolidObjectTopSloped2).l bra.w Sprite_OnScreen_Test ; End of function sub_205B6 ; --------------------------------------------------------------------------- loc_205CE: subq.b #1,$38(a0) bne.s loc_205DA move.l #loc_20620,(a0) loc_205DA: bra.w Draw_Sprite ; --------------------------------------------------------------------------- loc_205DE: bsr.w sub_205B6 subq.b #1,$38(a0) bne.s locret_2061E move.l #loc_20620,(a0) lea (Player_1).w,a1 moveq #p1_standing_bit,d6 bsr.s sub_205FC lea (Player_2).w,a1 moveq #p2_standing_bit,d6 ; =============== S U B R O U T I N E ======================================= sub_205FC: btst d6,status(a0) beq.s locret_2061E bclr d6,status(a0) bclr #Status_OnObj,status(a1) bclr #Status_Push,status(a1) bset #Status_InAir,status(a1) move.b #1,prev_anim(a1) locret_2061E: rts ; End of function sub_205FC ; --------------------------------------------------------------------------- loc_20620: tst.b render_flags(a0) bpl.w Delete_Current_Sprite bsr.w MoveSprite bra.w Draw_Sprite ; --------------------------------------------------------------------------- Obj_CollapsingBridge: move.l #loc_2095E,(a0) ori.b #4,render_flags(a0) move.w #$280,priority(a0) cmpi.b #6,(Current_zone).w bne.s loc_206B8 move.b subtype(a0),d0 andi.w #$3F,d0 add.w d0,d0 add.w d0,d0 addq.w #8,d0 bcc.s loc_2065E move.b #-1,d0 loc_2065E: move.b d0,$38(a0) btst #6,subtype(a0) bne.s loc_20696 move.l #Map_LBZCollapsingBridge,mappings(a0) move.w #make_art_tile($001,2,0),art_tile(a0) move.b #$40,width_pixels(a0) move.b #$10,height_pixels(a0) move.l #LBZBridgeCollapse_TimerArray,$30(a0) move.l #LBZBridgeCollapse_TimerFlipArray,$34(a0) bra.s loc_206B8 ; --------------------------------------------------------------------------- loc_20696: move.l #Map_LBZCollapsingLedge,mappings(a0) move.w #make_art_tile($001,2,0),art_tile(a0) move.b #$20,width_pixels(a0) move.b #$30,height_pixels(a0) move.l #LBZLedgeCollapse_TimerArray,$30(a0) loc_206B8: cmpi.b #1,(Current_zone).w bne.w loc_20752 move.l #Map_HCZCollapsingBridge,mappings(a0) move.w #make_art_tile($001,2,1),art_tile(a0) move.b subtype(a0),d0 bpl.s loc_206EA move.b d0,d1 andi.b #$F,d1 move.b d1,$40(a0) move.l #loc_20AF6,(a0) andi.b #$70,d0 loc_206EA: move.b d0,d1 andi.w #$F,d0 lsl.w #4,d0 addq.w #8,d0 move.b d0,$38(a0) andi.w #$F0,d1 lsr.w #2,d1 lea byte_20722(pc,d1.w),a1 move.b (a1)+,width_pixels(a0) move.b (a1)+,height_pixels(a0) move.b (a1)+,mapping_frame(a0) move.b (a1)+,subtype(a0) add.w d1,d1 lea off_20732(pc,d1.w),a1 move.l (a1)+,$30(a0) move.l (a1)+,$34(a0) bra.s loc_20752 ; --------------------------------------------------------------------------- byte_20722: dc.b $40, $10, 0, $80 dc.b $50, $10, 3, $80 dc.b $40, $10, 6, 0 dc.b $50, $20, 9, $80 off_20732: dc.l byte_20D22, byte_20D32 dc.l byte_20D42, byte_20D56 dc.l byte_20D6A, byte_20D6A dc.l byte_20D79, byte_20D91 ; --------------------------------------------------------------------------- loc_20752: cmpi.b #2,(Current_zone).w bne.s loc_207D4 move.l #Map_MGZCollapsingBridge,mappings(a0) move.w #make_art_tile($001,2,0),art_tile(a0) move.b subtype(a0),d0 move.b d0,d1 andi.w #$F,d0 lsl.w #4,d0 addq.w #8,d0 move.b d0,$38(a0) andi.w #$F0,d1 lsr.w #2,d1 lea byte_207B0(pc,d1.w),a1 move.b (a1)+,width_pixels(a0) move.b (a1)+,height_pixels(a0) move.b (a1)+,mapping_frame(a0) move.b (a1)+,subtype(a0) add.w d1,d1 lea off_207BC(pc,d1.w),a1 move.l (a1)+,$30(a0) move.l (a1)+,$34(a0) cmpi.w #$10,d1 bne.s loc_207D4 move.l #loc_209D0,(a0) rts ; --------------------------------------------------------------------------- byte_207B0: dc.b $40, $20, 0, $80 dc.b $30, $20, 3, $80 dc.b $40, $20, 6, $80 off_207BC: dc.l byte_20DA9, byte_20DC9 dc.l byte_20DE9, byte_20E01 dc.l byte_20DA9, byte_20DC9 ; --------------------------------------------------------------------------- loc_207D4: cmpi.b #5,(Current_zone).w bne.s loc_20834 move.b subtype(a0),d0 bpl.s loc_207F6 move.b d0,d1 andi.b #$F,d1 move.b d1,$40(a0) move.l #loc_20AF6,(a0) andi.b #$70,d0 loc_207F6: move.b d0,d1 andi.w #$F,d0 lsl.w #4,d0 addq.w #8,d0 move.b d0,$38(a0) move.l #Map_ICZCollapsingBridge,mappings(a0) move.w #make_art_tile($001,2,0),art_tile(a0) move.b #$50,width_pixels(a0) move.b #$38,height_pixels(a0) move.l #byte_20E19,$30(a0) move.l #byte_20E45,$34(a0) move.b #3,mapping_frame(a0) loc_20834: cmpi.b #$16,(Current_zone).w bne.s loc_2084C move.l #Map_HPZCollapsingBridge,mappings(a0) move.w #make_art_tile($001,2,0),art_tile(a0) bra.s loc_20862 ; --------------------------------------------------------------------------- loc_2084C: cmpi.b #9,(Current_zone).w bne.s loc_208A6 move.l #Map_LRZCollapsingPlatform,mappings(a0) move.w #make_art_tile($090,2,0),art_tile(a0) loc_20862: move.b subtype(a0),d0 move.b d0,d1 andi.w #$F,d0 lsl.w #4,d0 addq.w #8,d0 move.b d0,$38(a0) andi.w #$70,d1 lsr.w #2,d1 lea byte_2089A(pc,d1.w),a1 move.b (a1)+,width_pixels(a0) move.b (a1)+,height_pixels(a0) move.b (a1)+,mapping_frame(a0) add.w d1,d1 lea off_2089E(pc,d1.w),a1 move.l (a1)+,$30(a0) move.l (a1)+,$34(a0) bra.s loc_208A6 ; --------------------------------------------------------------------------- byte_2089A: dc.b $20, $18, 0, $80 off_2089E: dc.l byte_20E85, byte_20E91 ; --------------------------------------------------------------------------- loc_208A6: cmpi.b #4,(Current_zone).w ; is this FBZ? bne.s loc_20904 ; if not, branch move.l #Map_FBZCollapsingBridge,mappings(a0) move.w #make_art_tile($001,2,0),art_tile(a0) move.b subtype(a0),d0 move.b d0,d1 andi.w #$F,d0 lsl.w #4,d0 addq.w #8,d0 move.b d0,$38(a0) andi.w #$F0,d1 lsr.w #2,d1 lea FBZBridgeSpriteAttribute(pc,d1.w),a1 move.b (a1)+,width_pixels(a0) move.b (a1)+,height_pixels(a0) move.b (a1)+,mapping_frame(a0) move.b (a1)+,subtype(a0) add.w d1,d1 lea off_208FC(pc,d1.w),a1 move.l (a1)+,$30(a0) move.l (a1)+,$34(a0) bra.s loc_20904 ; --------------------------------------------------------------------------- FBZBridgeSpriteAttribute: ; width, height, frame, subtype dc.b $40, $20, 0, $80 off_208FC: dc.l byte_20DA9, byte_20DC9 ; --------------------------------------------------------------------------- loc_20904: cmpi.b #8,(Current_zone).w ; is this zone 8? bne.s loc_2095E ; if not branch move.l #Map_SOZCollapsingBridge,mappings(a0) ; if yes, set its sprite properties move.w #make_art_tile($001,2,0),art_tile(a0) move.b subtype(a0),d0 move.b d0,d1 ; copy subtype andi.w #$F,d0 ; read first digit lsl.w #4,d0 ; multiply amount addq.w #8,d0 ; add 8 to it move.b d0,$38(a0) ; copy the amount we got into $38 (custom varable) andi.w #$70,d1 lsr.w #2,d1 lea byte_20952(pc,d1.w),a1 move.b (a1)+,width_pixels(a0) ; get wdith move.b (a1)+,height_pixels(a0) move.b (a1)+,mapping_frame(a0) add.w d1,d1 ; multyply by 2 lea off_20956(pc,d1.w),a1 move.l (a1)+,$30(a0) move.l (a1)+,$34(a0) bra.s loc_2095E ; --------------------------------------------------------------------------- byte_20952: dc.b $20, $30, 0, $80 off_20956: dc.l byte_20E71, byte_20E7B ; --------------------------------------------------------------------------- loc_2095E: tst.b $3A(a0) beq.s loc_209A8 tst.b $38(a0) bne.s loc_209A4 movea.l $30(a0),a4 tst.b subtype(a0) ; does this object have a subtype? bpl.s loc_209A0 ; if yes, branch to here move.b status(a0),d0 ; if bit 7 of subtype set, collapse platform in direction dependent on player position andi.b #standing_mask,d0 beq.s loc_209A0 move.w (Player_1+x_pos).w,d1 andi.b #8,d0 bne.s loc_2098C move.w (Player_2+x_pos).w,d1 loc_2098C: cmp.w x_pos(a0),d1 ; compare object x pos with player's x pos (Sonic, Tails, Knuckles) bhs.s loc_209A0 ; if it's higher whan player's x pos (x coordinates), then branch movea.l $34(a0),a4 ; if it's less, get pointer to a4 bchg #0,status(a0) ; reverse status (flipping for this case) addq.b #1,mapping_frame(a0) ; add 1 to mapping frame loc_209A0: bra.w CollapsingPtfmHandlePlayerAndSmash ; --------------------------------------------------------------------------- loc_209A4: subq.b #1,$38(a0) loc_209A8: move.b status(a0),d0 ; Check if player is standing on platform andi.b #standing_mask,d0 beq.s loc_209B8 move.b #1,$3A(a0) ; Turn on collapsing timer loc_209B8: moveq #0,d1 move.b width_pixels(a0),d1 move.w #$10,d3 move.w x_pos(a0),d4 jsr (SolidObjectTop).l bra.w Sprite_OnScreen_Test ; --------------------------------------------------------------------------- loc_209D0: moveq #0,d1 move.b width_pixels(a0),d1 move.w #$10,d3 move.w x_pos(a0),d4 jsr (SolidObjectTop).l move.b status(a0),d0 andi.b #standing_mask,d0 beq.s loc_20A52 move.b (Player_1+status_tertiary).w,d1 andi.b #8,d0 bne.s loc_209FC move.b (Player_2+status_tertiary).w,d1 loc_209FC: tst.b d1 bpl.s loc_20A52 bclr #p1_standing_bit,status(a0) beq.s loc_20A12 lea (Player_1).w,a1 bclr #Status_OnObj,status(a1) loc_20A12: bclr #p2_standing_bit,status(a0) beq.s loc_20A24 lea (Player_2).w,a1 bclr #Status_OnObj,status(a1) loc_20A24: lea (word_20A76).l,a4 addq.b #1,mapping_frame(a0) move.w #$80,priority(a0) move.l #loc_20A56,(a0) jsr (BreakObjectToPieces).l move.w respawn_addr(a0),d0 ; was obj spawned by layout? beq.s loc_20A50 ; if not, branch to function movea.w d0,a1 ; if yes, get addr of respawn_table bclr #7,(a1) ; set as unloaded clr.w respawn_addr(a0) ; clear that addr loc_20A50: bra.s loc_20A56 ; --------------------------------------------------------------------------- loc_20A52: bra.w Sprite_OnScreen_Test ; --------------------------------------------------------------------------- loc_20A56: jsr (MoveSprite2).l addi.w #$18,y_vel(a0) ; make object fall tst.b render_flags(a0) ; is sprite on screen? bpl.w loc_20A70 ; no delete jmp (Draw_Sprite).l ; if yes, then display ; --------------------------------------------------------------------------- loc_20A70: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- word_20A76: dc.w -$400, -$A00 dc.w -$300, -$A00 dc.w -$200, -$A00 dc.w -$100, -$A00 dc.w $100, -$A00 dc.w $200, -$A00 dc.w $300, -$A00 dc.w $400, -$A00 dc.w -$3C0, -$900 dc.w -$2C0, -$900 dc.w -$1C0, -$900 dc.w -$C0, -$900 dc.w $C0, -$900 dc.w $1C0, -$900 dc.w $2C0, -$900 dc.w $3C0, -$900 dc.w -$380, -$800 dc.w -$280, -$800 dc.w -$180, -$800 dc.w -$80, -$800 dc.w $80, -$800 dc.w $180, -$800 dc.w $280, -$800 dc.w $380, -$800 dc.w -$340, -$700 dc.w -$240, -$700 dc.w -$140, -$700 dc.w -$40, -$700 dc.w $40, -$700 dc.w $140, -$700 dc.w $240, -$700 dc.w $340, -$700 ; --------------------------------------------------------------------------- loc_20AF6: tst.b $3A(a0) beq.s loc_20B40 tst.b $38(a0) bne.s loc_20B3C movea.l $30(a0),a4 tst.b subtype(a0) bpl.s loc_20B38 move.b status(a0),d0 andi.b #standing_mask,d0 beq.s loc_20B38 move.w (Player_1+x_pos).w,d1 andi.b #8,d0 bne.s loc_20B24 move.w (Player_2+x_pos).w,d1 loc_20B24: cmp.w x_pos(a0),d1 bhs.s loc_20B38 movea.l $34(a0),a4 bchg #0,status(a0) addq.b #1,mapping_frame(a0) loc_20B38: bra.w CollapsingPtfmHandlePlayerAndSmash ; --------------------------------------------------------------------------- loc_20B3C: subq.b #1,$38(a0) loc_20B40: move.b $40(a0),d0 andi.w #$F,d0 lea (Level_trigger_array).w,a3 lea (a3,d0.w),a3 tst.b (a3) beq.s loc_20B5E move.b #1,$3A(a0) clr.w respawn_addr(a0) loc_20B5E: bra.w loc_209B8 ; --------------------------------------------------------------------------- Obj_PlatformCollapseWait: subq.b #1,$38(a0) bne.s loc_20B6E move.l #Obj_PlatformCollapseFall,(a0) loc_20B6E: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- Obj_PlatformCollapseFall: tst.b render_flags(a0) ; is obj on screen? bpl.s loc_20B86 ; if not, delete jsr (MoveSprite).l ; if yes, move sprite and display jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_20B86: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- Obj_PlatformCollapseWaitHandlePlayer: subq.b #1,$38(a0) bne.s loc_20B98 move.l #Obj_PlatformCollapseFall,(a0) loc_20B98: move.b $38(a0),d3 movea.l $30(a0),a2 moveq #0,d1 move.b width_pixels(a0),d1 lea (Player_1).w,a1 moveq #p1_standing_bit,d6 bsr.s Check_CollapsePlayerRelease lea (Player_2).w,a1 moveq #p2_standing_bit,d6 bsr.s Check_CollapsePlayerRelease bra.w Sprite_OnScreen_Test ; =============== S U B R O U T I N E ======================================= Check_CollapsePlayerRelease: btst d6,status(a0) beq.s locret_20C10 move.w d1,d2 add.w d2,d2 btst #Status_InAir,status(a1) bne.s loc_20BF4 move.w x_pos(a1),d0 ; gets player's range from object sub.w x_pos(a0),d0 add.w d1,d0 bmi.s loc_20BF4 cmp.w d2,d0 bhs.s loc_20BF4 btst #0,status(a0) beq.s loc_20BE8 neg.w d0 add.w d2,d0 loc_20BE8: lsr.w #4,d0 move.b (a2),d2 sub.b (a2,d0.w),d2 cmp.b d2,d3 bhi.s locret_20C10 loc_20BF4: bclr d6,status(a0) bclr #Status_OnObj,status(a1) bclr #Status_Push,status(a1) bset #Status_InAir,status(a1) move.b #1,prev_anim(a1) locret_20C10: rts ; End of function Check_CollapsePlayerRelease ; --------------------------------------------------------------------------- ; in s2disasm: Obj1F_CreateFragments CollapsingPtfmHandlePlayerAndSmash: move.l #Obj_PlatformCollapseWaitHandlePlayer,(a0) move.l #Obj_PlatformCollapseWait,d4 addq.b #1,mapping_frame(a0) bra.s ObjPlatformCollapse_SmashObject ; --------------------------------------------------------------------------- ObjPlatformCollapse_CreateFragments: move.l #loc_205DE,(a0) move.l #loc_205CE,d4 addq.b #2,mapping_frame(a0) movea.l $30(a0),a4 ObjPlatformCollapse_SmashObject: 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) ; set flag to "static mappings flag" move.b render_flags(a0),d5 ; get render type movea.l a0,a1 bra.s GetFragmentsSpriteProperties ; --------------------------------------------------------------------------- GetFragmentsSlotsloop: bsr.w AllocateObjectAfterCurrent bne.s FragmentsDrawAndPlaySfx addq.w #6,a3 ; in Sonic 2's mapping format, this is just addq.w #8,a3 due to different mapping format sizes (addq.w #5,a3 for Sonic 1) move.l d4,(a1) GetFragmentsSpriteProperties: 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.w priority(a0),priority(a1) move.b width_pixels(a0),width_pixels(a1) move.b height_pixels(a0),height_pixels(a1) move.b (a4)+,$38(a1) dbf d1,GetFragmentsSlotsloop FragmentsDrawAndPlaySfx: jsr (Draw_Sprite).l move.w respawn_addr(a0),d0 beq.s .CollapsingPtfmPlaySfx ; function when object isn't spawned by layout (plays sound anyway) movea.w d0,a1 bclr #7,(a1) clr.w respawn_addr(a0) .CollapsingPtfmPlaySfx: moveq #signextendB(sfx_Collapse),d0 jmp (Play_SFX).l ; --------------------------------------------------------------------------- byte_20CB6: dc.b $30, $2C, $28, $24, $20, $1C, $2E, $2A, $26, $22, $1E, $1A, $2C, $28, $24, $20, $1C, $18, $2A, $26 dc.b $22, $1E, $1A, $16, $28, $24, $20, $1C, $18, $14 byte_20CD4: dc.b $30, $2C, $28, $24, $20, $1C, $2E, $2A, $26, $22, $1E, $1A, $2C, $28, $24, $20, $1C, $18, $2A, $26 dc.b $22, $1E, $1A, $16, $28, $24, $20, $1C, $18, $14, $12, $10 LBZBridgeCollapse_TimerArray: dc.b $20, $1C, $18, $14, $10, $C, 8, 4, $1E, $1A, $16, $12, $E, $A, 6, 2 LBZBridgeCollapse_TimerFlipArray: dc.b $20, 4, 8, $C, $10, $14, $18, $1C, 2, 6, $A, $E, $12, $16, $1A, $1E LBZLedgeCollapse_TimerArray: dc.b $20, $18, $10, 8, $1E, $16, $E, 6, $1C, $14, $C, 4, $1A, $12 byte_20D22: dc.b $20, $1C, $18, $14, $10, $C, 8, 4, $1E, $1A, $16, $12, $E, $A, 6, 2 byte_20D32: dc.b $20, 4, 8, $C, $10, $14, $18, $1C, 2, 6, $A, $E, $12, $16, $1A, $1E byte_20D42: dc.b $28, $24, $20, $1C, $18, $14, $10, $C, 8, 4, $26, $22, $1E, $1A, $16, $12, $E, $A, 6, 2 byte_20D56: dc.b $28, 4, 8, $C, $10, $14, $18, $1C, $20, $24, 2, 6, $A, $E, $12, $16, $1A, $1E, $22, $26 byte_20D6A: dc.b $1C, 4, 8, $C, $10, $14, $18, 2, 6, $A, $E, $12, $16, $1A, $1E byte_20D79: dc.b $30, $2A, $24, $1E, $18, $12, $C, 6, $2E, $28, $22, $1C, $16, $10, $A, 4, $2C, $26, $20, $1A dc.b $14, $E, 8, 2 byte_20D91: dc.b $30, 6, $C, $12, $18, $1E, $24, $2A, 4, $A, $10, $16, $1C, $22, $28, $2E, 2, 8, $E, $14 dc.b $1A, $20, $26, $2C byte_20DA9: dc.b $40, $38, $30, $28, $20, $18, $10, 8, $3E, $36, $2E, $26, $1E, $16, $E, 6, $3C, $34, $2C, $24 dc.b $1C, $14, $C, 4, $3A, $32, $2A, $22, $1A, $12, $A, 2 byte_20DC9: dc.b $40, 8, $10, $18, $20, $28, $30, $38, 6, $E, $16, $1E, $26, $2E, $36, $3E, 4, $C, $14, $1C dc.b $24, $2C, $34, $3C, 2, $A, $12, $1A, $22, $2A, $32, $3A byte_20DE9: dc.b $30, $28, $20, $18, $10, 8, $2E, $26, $1E, $16, $E, 6, $2C, $24, $1C, $14, $C, 4, $2A, $22 dc.b $1A, $12, $A, 2 byte_20E01: dc.b $30, 8, $10, $18, $20, $28, 6, $E, $16, $1E, $26, $2E, 4, $C, $14, $1C, $24, $2C, 2, $A dc.b $12, $1A, $22, $2A byte_20E19: dc.b $28, $24, $20, $1C, $18, $14, $10, $C, 8, 4, $27, $23, $1F, $1B, $17, $13, $F, $B, 7, 3 dc.b $26, $22, $1E, $1A, $16, $12, $E, $A, 6, 2, $25, $21, $1D, $19, $15, $11, $D, 9, 5, 1 dc.b 4, 3, 2, 1 byte_20E45: dc.b $28, 4, 8, $C, $10, $14, $18, $1C, $20, $24, 3, 7, $B, $F, $13, $17, $1B, $1F, $23, $27 dc.b 2, 6, $A, $E, $12, $16, $1A, $1E, $22, $26, 1, 5, 9, $D, $11, $15, $19, $1D, $21, $25 dc.b 1, 2, 3, 4 byte_20E71: dc.b $20, $18, $10, 8, $1E, $16, $1C, $14, $1A, $12 byte_20E7B: dc.b $20, 8, $10, $18, 6, $E, 4, $C, 2, $A byte_20E85: dc.b $18, $12, $C, 6, $16, $10, $A, 4, $14, $E, 8, 2 byte_20E91: dc.b $18, 6, $C, $12, 4, $A, $10, $16, 2, 8, $E, $14, 0 byte_20E9E: dc.b $1F, $1F, $1F, $1F, $1F, $1F, $1F, $1F, $1F, $1F, $1F, $1F, $1F, $1F, $1F, $1F, $1F, $1F, $1F, $1F dc.b $1F, $1F, $1E, $1E, $1D, $1D, $1C, $1C, $1B, $1B, $1A, $1A, $19, $19, $18, $18, $17, $17, $16, $16 dc.b $15, $15, $14, $14, $13, $13, $12, $12, $11, $11, $10, $10, $F, $F, $E, $E, $E, $E, $E, $E dc.b $E, $E, $E, $E byte_20EDE: dc.b $30, $30, $30, $30, $30, $30, $30, $30, $30, $30, $30, $30, $2F, $2F, $2F, $2F, $2F, $2F, $2F, $2F dc.b $2F, $2F, $2F, $2F, $2E, $2E, $2E, $2E, $2E, $2E, $2E, $2E, $2D, $2D, $2D, $2D, $2D, $2D, $2D, $2D dc.b $2D, $2D, $2D, $2D, $2D, $2C, $2B, $2A Map_LRZCollapsingPlatform: include "Levels/LRZ/Misc Object Data/Map - Collapsing Platform.asm" Map_HPZCollapsingBridge: include "Levels/HPZ/Misc Object Data/Map - Collapsing Bridge.asm" Map_FBZCollapsingBridge: include "Levels/FBZ/Misc Object Data/Map - Collapsing Bridge.asm" Map_SOZCollapsingBridge: include "Levels/SOZ/Misc Object Data/Map - Collapsing Bridge.asm" ; --------------------------------------------------------------------------- Obj_BreakableWall: move.b #4,render_flags(a0) move.w #$280,priority(a0) move.l #loc_21568,(a0) move.b subtype(a0),d0 bpl.s loc_21340 tst.b (Level_trigger_array).w beq.s loc_21340 jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- loc_21340: andi.b #$F,d0 move.b d0,mapping_frame(a0) move.l #Map_AIZBreakableWall,mappings(a0) move.w #make_art_tile($001,2,0),art_tile(a0) move.b #$10,width_pixels(a0) move.b #$28,height_pixels(a0) move.l #word_2193A,$34(a0) move.l #word_2196A,$38(a0) cmpi.b #1,(Current_zone).w bne.s loc_213D6 move.l #Map_HCZBreakableWall,mappings(a0) move.w #make_art_tile($001,3,0),art_tile(a0) move.b #$10,width_pixels(a0) move.b #$20,height_pixels(a0) move.l #word_2199A,$34(a0) move.l #word_219BA,$38(a0) cmpi.b #2,mapping_frame(a0) bne.s loc_213D6 move.w #make_art_tile($350,2,0),art_tile(a0) move.b #$18,width_pixels(a0) move.b #$20,height_pixels(a0) move.l #word_2199A,$34(a0) move.l #word_219BA,$38(a0) move.l #loc_21818,(a0) rts ; --------------------------------------------------------------------------- loc_213D6: cmpi.b #2,(Current_zone).w bne.s loc_21428 move.l #Map_MGZBreakableWall,mappings(a0) move.w #make_art_tile($001,2,0),art_tile(a0) move.b #$20,width_pixels(a0) move.b #$28,height_pixels(a0) move.l #word_21A2A,$34(a0) move.l #word_219DA,$38(a0) btst #4,subtype(a0) beq.s loc_21418 move.l #loc_21818,(a0) rts ; --------------------------------------------------------------------------- loc_21418: cmpi.b #2,mapping_frame(a0) bne.s loc_21428 move.l #loc_2172E,(a0) rts ; --------------------------------------------------------------------------- loc_21428: cmpi.b #3,(Current_zone).w bne.s loc_2146A move.l #Map_CNZSOZBreakableWall,mappings(a0) move.w #make_art_tile($420,2,0),art_tile(a0) move.b #$10,width_pixels(a0) move.b #$20,height_pixels(a0) move.l #word_21A7A,$34(a0) move.l #word_21A9A,$38(a0) cmpi.b #2,mapping_frame(a0) bne.s loc_2146A move.l #loc_21818,(a0) rts ; --------------------------------------------------------------------------- loc_2146A: cmpi.b #6,(Current_zone).w bne.s loc_214A4 move.l #Map_LBZBreakableWall,mappings(a0) move.w #make_art_tile($2EA,1,0),art_tile(a0) move.b #$10,width_pixels(a0) move.b #$20,height_pixels(a0) move.l #word_2199A,$34(a0) move.l #word_219BA,$38(a0) move.l #loc_21818,(a0) rts ; --------------------------------------------------------------------------- loc_214A4: cmpi.b #7,(Current_zone).w bne.s loc_214DE move.l #Map_MHZBreakableWall,mappings(a0) move.w #make_art_tile($34B,2,0),art_tile(a0) move.b #$10,width_pixels(a0) move.b #$20,height_pixels(a0) move.l #word_21A7A,$34(a0) move.l #word_21A9A,$38(a0) move.l #loc_21818,(a0) rts ; --------------------------------------------------------------------------- loc_214DE: cmpi.b #8,(Current_zone).w bne.s loc_21536 move.l #Map_CNZSOZBreakableWall,mappings(a0) move.w #make_art_tile($48C,2,0),art_tile(a0) move.b #$10,width_pixels(a0) move.b #$20,height_pixels(a0) move.l #word_21A7A,$34(a0) move.l #word_21A9A,$38(a0) move.l #loc_21818,(a0) cmpi.b #4,mapping_frame(a0) bne.s locret_21534 move.b #$30,height_pixels(a0) move.l #word_2193A,$34(a0) move.l #word_2196A,$38(a0) locret_21534: rts ; --------------------------------------------------------------------------- loc_21536: cmpi.b #9,(Current_zone).w bne.s loc_21568 move.l #Map_LRZBreakableWall,mappings(a0) move.w #make_art_tile($40D,3,0),art_tile(a0) move.b #$10,width_pixels(a0) move.b #$20,height_pixels(a0) move.l #word_21A7A,$34(a0) move.l #word_21A9A,$38(a0) loc_21568: move.w (Player_1+x_vel).w,$30(a0) move.w (Player_2+x_vel).w,$32(a0) moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsr (SolidObjectFull).l tst.b subtype(a0) bpl.s loc_215A4 tst.b (Level_trigger_array).w beq.s loc_215AC jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- loc_215A4: swap d6 andi.w #3,d6 bne.s loc_215B2 loc_215AC: jmp (Sprite_OnScreen_Test).l ; --------------------------------------------------------------------------- loc_215B2: lea (Player_1).w,a1 move.w $30(a0),d1 move.w d6,d0 andi.w #1,d0 beq.s loc_2162A tst.b (Super_Sonic_Knux_flag).w bne.s loc_215F4 cmpi.b #2,character_id(a1) beq.s loc_215F4 btst #Status_FireShield,status_secondary(a1) bne.s loc_215E0 btst #p1_pushing_bit,status(a0) beq.s loc_2162A loc_215E0: cmpi.b #2,anim(a1) bne.s loc_2162A move.w d1,d0 bpl.s loc_215EE neg.w d0 loc_215EE: cmpi.w #$480,d0 blo.s loc_2162A loc_215F4: bclr #p1_pushing_bit,status(a0) bsr.s sub_2165A btst #p2_pushing_bit,status(a0) beq.s loc_215AC lea (Player_2).w,a1 cmpi.b #2,anim(a1) bne.s loc_215AC move.w $32(a0),x_vel(a1) move.w x_vel(a1),ground_vel(a1) bclr #p2_pushing_bit,status(a0) bclr #Status_Push,status(a1) bra.s loc_215AC ; --------------------------------------------------------------------------- loc_2162A: lea (Player_2).w,a1 move.w $32(a0),d1 btst #p2_pushing_bit,status(a0) beq.w loc_215AC cmpi.b #2,anim(a1) bne.w loc_215AC move.w d1,d0 bpl.s loc_2164C neg.w d0 loc_2164C: cmpi.w #$480,d0 blo.w loc_215AC bclr #p2_pushing_bit,status(a0) ; =============== S U B R O U T I N E ======================================= sub_2165A: move.w d1,x_vel(a1) addq.w #4,x_pos(a1) movea.l $34(a0),a4 move.w x_pos(a0),d0 cmp.w x_pos(a1),d0 blo.s loc_2167A subi.w #8,x_pos(a1) movea.l $38(a0),a4 loc_2167A: move.w x_vel(a1),ground_vel(a1) bclr #Status_Push,status(a1) ; set Sonic as not pushing an object move.l #loc_21692,(a0) addq.b #1,mapping_frame(a0) bsr.s BreakObjectToPieces loc_21692: jsr (MoveSprite2).l addi.w #$70,y_vel(a0) ; make obj fall tst.b render_flags(a0) bpl.s loc_216AA jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_216AA: jmp (Delete_Current_Sprite).l ; End of function sub_2165A ; =============== S U B R O U T I N E ======================================= BreakObjectToPieces: moveq #signextendB(sfx_Collapse),d0 jsr (Play_SFX).l move.w #$80,priority(a0) ; set priority again when being smashed BreakObjectToPieces2: moveq #0,d0 move.b mapping_frame(a0),d0 add.w d0,d0 movea.l mappings(a0),a3 ; get mapping pointer adda.w (a3,d0.w),a3 move.w (a3)+,d1 subq.w #1,d1 bset #5,render_flags(a0) ; set static mappings flag move.l (a0),d4 move.b render_flags(a0),d5 ; get render flags movea.l a0,a1 bra.s BreakObjectToPieces_InitObject ; --------------------------------------------------------------------------- ; loc_216E2: BreakObjectToPieces_Loop: jsr (AllocateObjectAfterCurrent).l bne.s locret_2172C addq.w #6,a3 ; add to mappings ; loc_216EC: BreakObjectToPieces_InitObject: move.l d4,(a1) ; get object pointer (in Sonic 1 and 2, this copies the object ID) move.l a3,mappings(a1) ; get mappings pointer move.b d5,render_flags(a1) ; get render flags move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.w art_tile(a0),art_tile(a1) ori.w #high_priority,art_tile(a1) ; change fragment's priority move.b priority(a0),priority(a1) ; copy priority move.b width_pixels(a0),width_pixels(a1) move.b height_pixels(a0),height_pixels(a1) move.w (a4)+,x_vel(a1) move.w (a4)+,y_vel(a1) dbf d1,BreakObjectToPieces_Loop locret_2172C: rts ; End of function BreakObjectToPieces ; --------------------------------------------------------------------------- loc_2172E: move.w (Player_1+x_vel).w,$30(a0) move.w (Player_2+x_vel).w,$32(a0) moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsr (SolidObjectFull).l swap d6 andi.b #3,d6 beq.w loc_217E8 move.b d6,d0 andi.b #1,d0 beq.s loc_217BC lea (Player_1).w,a1 bclr #6,$37(a1) beq.s loc_217BC move.w $30(a0),x_vel(a1) move.w x_vel(a1),ground_vel(a1) bclr #Status_Push,status(a1) bclr #p1_pushing_bit,status(a0) bsr.s sub_217EE andi.b #2,d6 beq.s loc_217E8 lea (Player_2).w,a1 bclr #6,$37(a1) beq.s loc_217E8 move.w $32(a0),x_vel(a1) move.w x_vel(a1),ground_vel(a1) bclr #Status_Push,status(a1) bclr #p2_pushing_bit,status(a0) bra.s loc_217E8 ; --------------------------------------------------------------------------- loc_217BC: andi.b #2,d6 beq.s loc_217E8 lea (Player_2).w,a1 bclr #6,$37(a1) beq.s loc_217E8 move.w $32(a0),x_vel(a1) move.w x_vel(a1),ground_vel(a1) bclr #Status_Push,status(a1) bclr #p2_pushing_bit,status(a0) bsr.s sub_217EE loc_217E8: jmp (Sprite_OnScreen_Test).l ; =============== S U B R O U T I N E ======================================= sub_217EE: movea.l $34(a0),a4 move.w x_pos(a0),d0 cmp.w x_pos(a1),d0 blo.s loc_21806 subi.w #8,x_pos(a1) movea.l $38(a0),a4 loc_21806: move.l #loc_21692,(a0) addq.b #1,mapping_frame(a0) bsr.w BreakObjectToPieces bra.w loc_21692 ; End of function sub_217EE ; --------------------------------------------------------------------------- loc_21818: move.w (Player_1+x_vel).w,$30(a0) move.w (Player_2+x_vel).w,$32(a0) moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsr (SolidObjectFull).l tst.b subtype(a0) bpl.s loc_21854 tst.b (Level_trigger_array).w beq.s loc_2185C jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- loc_21854: swap d6 andi.w #3,d6 bne.s loc_21862 loc_2185C: jmp (Sprite_OnScreen_Test).l ; --------------------------------------------------------------------------- loc_21862: lea (Player_1).w,a1 move.w $30(a0),d1 move.w d6,d0 andi.w #1,d0 beq.s loc_218B0 cmpi.b #2,character_id(a1) bne.s loc_218B0 bclr #p1_pushing_bit,status(a0) bsr.s sub_218CE btst #p2_pushing_bit,status(a0) beq.s loc_2185C lea (Player_2).w,a1 cmpi.b #2,character_id(a1) bne.s loc_2185C move.w $32(a0),x_vel(a1) move.w x_vel(a1),ground_vel(a1) bclr #p2_pushing_bit,status(a0) bclr #Status_Push,status(a1) bra.s loc_2185C ; --------------------------------------------------------------------------- loc_218B0: lea (Player_2).w,a1 move.w $32(a0),d1 btst #p2_pushing_bit,status(a0) beq.s loc_2185C cmpi.b #2,character_id(a1) bne.s loc_2185C bclr #p2_pushing_bit,status(a0) ; =============== S U B R O U T I N E ======================================= sub_218CE: move.w d1,x_vel(a1) addq.w #4,x_pos(a1) movea.l $34(a0),a4 move.w x_pos(a0),d0 cmp.w x_pos(a1),d0 blo.s loc_218EE subi.w #8,x_pos(a1) movea.l $38(a0),a4 loc_218EE: move.w x_vel(a1),ground_vel(a1) bclr #Status_Push,status(a1) cmpi.b #2,character_id(a1) bne.s loc_21928 cmpi.b #1,double_jump_flag(a1) bne.s loc_21928 move.b #2,double_jump_flag(a1) move.b #$21,anim(a1) bclr #Status_Facing,status(a1) tst.w x_vel(a1) bpl.s loc_21928 bset #Status_Facing,status(a1) loc_21928: move.l #loc_21692,(a0) addq.b #1,mapping_frame(a0) bsr.w BreakObjectToPieces bra.w loc_21692 ; End of function sub_218CE ; --------------------------------------------------------------------------- word_2193A: dc.w $400, -$500 dc.w $600, -$600 dc.w $600, -$100 dc.w $800, -$200 dc.w $680, 0 dc.w $880, 0 dc.w $600, $100 dc.w $800, $200 dc.w $400, $500 dc.w $600, $600 dc.w $300, $600 dc.w $500, $700 word_2196A: dc.w -$600, -$600 dc.w -$400, -$500 dc.w -$800, -$200 dc.w -$600, -$100 dc.w -$880, 0 dc.w -$680, 0 dc.w -$800, $200 dc.w -$600, $100 dc.w -$600, $600 dc.w -$400, $500 dc.w -$500, $700 dc.w -$300, $600 word_2199A: dc.w $400, -$500 dc.w $600, -$600 dc.w $600, -$100 dc.w $800, -$200 dc.w $600, $100 dc.w $800, $200 dc.w $400, $500 dc.w $600, $600 word_219BA: dc.w -$600, -$600 dc.w -$400, -$500 dc.w -$800, -$200 dc.w -$600, -$100 dc.w -$800, $200 dc.w -$600, $100 dc.w -$600, $600 dc.w -$400, $500 word_219DA: dc.w $400, -$500 dc.w $500, -$580 dc.w $600, -$600 dc.w $700, -$680 dc.w $600, -$100 dc.w $700, -$180 dc.w $800, -$200 dc.w $900, -$280 dc.w $680, 0 dc.w $780, 0 dc.w $880, 0 dc.w $980, 0 dc.w $600, $100 dc.w $700, $180 dc.w $800, $200 dc.w $900, $280 dc.w $400, $500 dc.w $500, $580 dc.w $600, $600 dc.w $700, $680 word_21A2A: dc.w -$700, -$680 dc.w -$600, -$600 dc.w -$500, -$580 dc.w -$400, -$500 dc.w -$900, -$280 dc.w -$800, -$200 dc.w -$700, -$180 dc.w -$600, -$100 dc.w -$980, 0 dc.w -$880, 0 dc.w -$780, 0 dc.w -$680, 0 dc.w -$900, $280 dc.w -$800, $200 dc.w -$700, $180 dc.w -$600, $100 dc.w -$700, $680 dc.w -$600, $600 dc.w -$500, $580 dc.w -$400, $500 word_21A7A: dc.w $400, -$500 dc.w $600, -$600 dc.w $600, -$100 dc.w $800, -$200 dc.w $600, $100 dc.w $800, $200 dc.w $400, $500 dc.w $600, $600 word_21A9A: dc.w -$600, -$600 dc.w -$400, -$500 dc.w -$800, -$200 dc.w -$600, -$100 dc.w -$800, $200 dc.w -$600, $100 dc.w -$600, $600 dc.w -$400, $500 Map_CNZSOZBreakableWall: include "Levels/CNZ/Misc Object Data/Map - (&SOZ) Breakable Wall.asm" Map_MHZBreakableWall: include "Levels/MHZ/Misc Object Data/Map - Breakable Wall.asm" Map_LRZBreakableWall: include "Levels/LRZ/Misc Object Data/Map - Breakable Wall.asm" ; --------------------------------------------------------------------------- Obj_AIZRideVine: movea.l a0,a1 move.l #loc_21D28,(a1) bsr.w sub_21D00 move.b #$21,mapping_frame(a1) move.w x_pos(a0),d2 move.w y_pos(a0),d3 moveq #0,d1 move.b subtype(a0),d1 andi.w #$7F,d1 lsl.w #4,d1 add.w d2,d1 move.w d1,$46(a0) moveq #3,d1 addq.w #1,d1 jsr (AllocateObjectAfterCurrent).l bne.w loc_21CFE move.w a1,$3E(a0) move.l #loc_21F80,(a1) move.w a0,$3C(a1) bra.s loc_21CD0 ; --------------------------------------------------------------------------- loc_21CB8: jsr (AllocateObjectAfterCurrent).l bne.w loc_21CFE move.l #loc_22014,(a1) move.w a2,$3C(a1) move.w a1,$3E(a2) loc_21CD0: movea.l a1,a2 bsr.s sub_21D00 move.w d2,x_pos(a1) move.w d3,y_pos(a1) addi.w #$10,d3 addq.w #1,$36(a0) move.w $36(a0),$36(a1) dbf d1,loc_21CB8 move.l #Obj_AIZRideVineHandle,(a1) move.b #$20,mapping_frame(a1) move.w a1,$40(a0) loc_21CFE: bra.s loc_21D28 ; =============== S U B R O U T I N E ======================================= sub_21D00: move.b #4,render_flags(a1) move.b #8,width_pixels(a1) move.b #8,height_pixels(a1) move.w #$200,priority(a1) move.l #Map_AIZMHZRideVine,mappings(a1) move.w #make_art_tile($41B,0,0),art_tile(a1) rts ; End of function sub_21D00 ; --------------------------------------------------------------------------- loc_21D28: movea.w $40(a0),a1 tst.w $32(a1) beq.s loc_21D48 move.l #loc_21D4C,(a0) movea.w $3E(a0),a1 move.w #1,$2E(a1) move.w #0,$38(a1) loc_21D48: bra.w loc_21F38 ; --------------------------------------------------------------------------- loc_21D4C: addi.l #$80000,x_pos(a0) addi.l #$20000,y_pos(a0) move.w x_pos(a0),d0 cmp.w $46(a0),d0 blo.w loc_21DEE tst.b subtype(a0) bpl.s loc_21DC2 move.l #loc_21DF2,(a0) move.w #$800,x_vel(a0) move.w #$200,y_vel(a0) move.l #Map_AnimatedStillSprites,mappings(a0) move.w #make_art_tile($2E9,3,0),art_tile(a0) move.b #8,width_pixels(a0) move.b #$C,height_pixels(a0) move.b #0,mapping_frame(a0) move.w #1,anim(a0) movea.w $40(a0),a1 lea $32(a1),a2 tst.b (a2) beq.s loc_21DB6 move.b #$81,(a2) loc_21DB6: addq.w #1,a2 tst.b (a2) beq.s loc_21DC0 move.b #$81,(a2) loc_21DC0: bra.s loc_21DEE ; --------------------------------------------------------------------------- loc_21DC2: move.l #loc_21E14,(a0) movea.w $3E(a0),a1 move.l #loc_21FE8,(a1) move.w #0,$3A(a1) movea.w $40(a0),a1 move.w #1,$30(a1) move.w #0,angle(a0) move.w #$400,$3A(a0) loc_21DEE: bra.w loc_21F38 ; --------------------------------------------------------------------------- loc_21DF2: jsr (MoveSprite).l tst.b render_flags(a0) bmi.s loc_21E04 move.w #$7FF0,x_pos(a0) loc_21E04: lea (Ani_AnimatedStillSprites).l,a1 jsr (Animate_Sprite).l bra.w loc_21F38 ; --------------------------------------------------------------------------- loc_21E14: movea.w $40(a0),a1 move.w $3A(a0),d0 move.b angle(a0),d1 ext.w d1 bpl.s loc_21E26 neg.w d1 loc_21E26: add.w d1,d1 sub.w d1,d0 sub.w d0,angle(a0) tst.w $32(a1) bne.s loc_21E68 move.b angle(a0),d0 addq.b #8,d0 cmpi.b #$10,d0 bhs.s loc_21E68 move.l #loc_21E6C,(a0) move.w #0,$42(a0) move.w #-$300,$44(a0) move.w #$1000,$38(a0) move.w #0,$2E(a0) movea.w $40(a0),a1 move.w #2,$30(a1) loc_21E68: bra.w loc_21F38 ; --------------------------------------------------------------------------- loc_21E6C: moveq #0,d2 move.b $38(a0),d2 move.w $44(a0),d0 move.w #0,d1 tst.w $2E(a0) bne.s loc_21EC4 add.w d2,d0 move.w d0,$44(a0) add.w d0,$42(a0) cmp.b $42(a0),d1 bgt.s loc_21EEE asr.w #4,d0 sub.w d0,$44(a0) move.w #1,$2E(a0) cmpi.w #$C00,$38(a0) beq.s loc_21EAC subi.w #$40,$38(a0) bra.s loc_21EEE ; --------------------------------------------------------------------------- loc_21EAC: move.l #loc_21F0A,(a0) move.w #0,$38(a0) movea.w $40(a0),a1 move.w #0,$30(a1) bra.s loc_21EEE ; --------------------------------------------------------------------------- loc_21EC4: sub.w d2,d0 move.w d0,$44(a0) add.w d0,$42(a0) cmp.b $42(a0),d1 ble.s loc_21EEE asr.w #4,d0 sub.w d0,$44(a0) move.w #0,$2E(a0) cmpi.w #$C00,$38(a0) beq.s loc_21EAC subi.w #$40,$38(a0) loc_21EEE: move.w $42(a0),d0 move.w d0,angle(a0) asr.w #3,d0 move.w d0,$3A(a0) movea.w $3E(a0),a1 move.w $3A(a0),$3A(a1) bra.w loc_21F38 ; --------------------------------------------------------------------------- loc_21F0A: move.b $38(a0),d0 addi.w #$200,$38(a0) jsr (GetSineCosine).l asl.w #2,d0 cmpi.w #$400,d0 bne.s loc_21F26 move.w #$3FF,d0 loc_21F26: move.w d0,angle(a0) move.w d0,$3A(a0) movea.w $3E(a0),a1 move.w $3A(a0),$3A(a1) loc_21F38: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_21F52 jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_21F52: move.w $36(a0),d2 subq.w #1,d2 bcs.s loc_21F6E movea.w $3E(a0),a2 loc_21F5E: movea.l a2,a1 movea.w $3E(a1),a2 jsr (Delete_Referenced_Sprite).l dbf d2,loc_21F5E loc_21F6E: move.w respawn_addr(a0),d0 beq.s loc_21F7A movea.w d0,a2 bclr #7,(a2) loc_21F7A: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- loc_21F80: tst.w $2E(a0) bne.s loc_21FA8 move.b $38(a0),d0 addi.w #$200,$38(a0) jsr (GetSineCosine).l asl.w #2,d0 cmpi.w #$400,d0 bne.s loc_21FA2 move.w #$3FF,d0 loc_21FA2: move.w d0,$3A(a0) bra.s loc_21FBE ; --------------------------------------------------------------------------- loc_21FA8: move.b $38(a0),d0 addi.w #$100,$38(a0) jsr (GetSineCosine).l asl.w #3,d0 move.w d0,$3A(a0) loc_21FBE: move.w $3A(a0),d0 move.w d0,angle(a0) move.b angle(a0),d0 addq.b #4,d0 lsr.b #3,d0 move.b d0,mapping_frame(a0) movea.w $3C(a0),a1 move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_21FE8: movea.w $3C(a0),a1 move.w angle(a1),angle(a0) move.b angle(a0),d0 addq.b #4,d0 lsr.b #3,d0 move.b d0,mapping_frame(a0) movea.w $3C(a0),a1 move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_22014: movea.w $3C(a0),a1 move.w $3A(a1),$3A(a0) move.w angle(a1),d0 add.w $3A(a0),d0 move.w d0,angle(a0) move.b angle(a0),d0 addq.b #4,d0 lsr.b #3,d0 move.b d0,mapping_frame(a0) bsr.w sub_22040 jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_22040: movea.w $3C(a0),a1 move.b angle(a1),d0 addq.b #4,d0 andi.b #$F8,d0 jsr (GetSineCosine).l neg.w d0 addi.w #8,d0 addi.w #8,d1 asr.w #4,d0 asr.w #4,d1 add.w x_pos(a1),d0 move.w d0,x_pos(a0) add.w y_pos(a1),d1 move.w d1,y_pos(a0) rts ; End of function sub_22040 ; --------------------------------------------------------------------------- Obj_AIZRideVineHandle: move.w x_pos(a0),d4 move.w y_pos(a0),d5 bsr.w sub_22040 cmp.w x_pos(a0),d4 beq.s loc_2208A move.w d4,$42(a0) loc_2208A: cmp.w y_pos(a0),d5 beq.s loc_22094 move.w d5,$44(a0) loc_22094: lea $32(a0),a2 lea (Player_1).w,a1 move.w (Ctrl_1_logical).w,d0 bsr.s sub_220C2 lea (Player_2).w,a1 addq.w #1,a2 move.w (Ctrl_2_logical).w,d0 bsr.s sub_220C2 tst.w $32(a0) beq.s loc_220BA tst.w $30(a0) bne.s locret_220C0 loc_220BA: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_220C0: rts ; =============== S U B R O U T I N E ======================================= sub_220C2: tst.b (a2) beq.w loc_222F4 bmi.w loc_2217E tst.b render_flags(a1) bpl.w loc_22190 cmpi.b #4,routine(a1) bhs.w loc_22190 move.b d0,d1 andi.b #button_A_mask|button_B_mask|button_C_mask,d1 beq.w loc_221EC clr.b object_control(a1) clr.b (a2) cmpi.w #1,$30(a0) beq.s loc_2215C move.w x_pos(a0),d1 sub.w $42(a0),d1 asl.w #7,d1 move.w d1,x_vel(a1) move.w y_pos(a0),d1 sub.w $44(a0),d1 asl.w #7,d1 move.w d1,y_vel(a1) move.b #$3C,2(a2) btst #button_left+8,d0 beq.s loc_22124 move.w #-$200,x_vel(a1) loc_22124: btst #button_right+8,d0 beq.s loc_22130 move.w #$200,x_vel(a1) loc_22130: addi.w #-$380,y_vel(a1) loc_22136: bset #Status_InAir,status(a1) move.b #1,jumping(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #2,anim(a1) bset #Status_Roll,status(a1) rts ; --------------------------------------------------------------------------- loc_2215C: move.b #$3C,2(a2) movea.w $3C(a0),a3 move.b angle(a3),d0 jsr (GetSineCosine).l asl.w #3,d1 move.w d1,x_vel(a1) asl.w #3,d0 move.w d0,y_vel(a1) bra.s loc_22136 ; --------------------------------------------------------------------------- loc_2217E: move.w #$300,x_vel(a1) move.w #$200,y_vel(a1) bset #Status_InAir,status(a1) loc_22190: clr.b object_control(a1) clr.b (a2) move.b #$3C,2(a2) rts ; End of function sub_220C2 ; =============== S U B R O U T I N E ======================================= sub_2219E: cmpa.w #Player_1,a1 bne.s locret_221E0 tst.b d0 beq.s locret_221E0 moveq #0,d1 move.b $25(a0),d1 cmp.b byte_221E2(pc,d1.w),d0 bne.s loc_221DA addq.b #1,$25(a0) move.b byte_221E2+1(pc,d1.w),d1 bne.s locret_221E0 moveq #0,d1 ; what the fuck subi.w #-Level_select_flag,d1 movea.w d1,a4 moveq #1,d1 move.b d1,(a4) move.b d1,Slow_motion_flag-Level_select_flag(a4) move.w d0,d1 moveq #signextendB(sfx_RingRight),d0 jsr (Play_SFX).l move.w d1,d0 loc_221DA: move.b #0,$25(a0) locret_221E0: rts ; End of function sub_2219E ; --------------------------------------------------------------------------- byte_221E2: dc.b button_left_mask dc.b button_left_mask dc.b button_left_mask dc.b button_right_mask dc.b button_right_mask dc.b button_right_mask dc.b button_up_mask dc.b button_up_mask dc.b button_up_mask dc.b 0 even ; --------------------------------------------------------------------------- loc_221EC: tst.w $30(a0) bne.s loc_22258 bsr.s sub_2219E move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$14,y_pos(a1) movea.w $3C(a0),a3 moveq #0,d0 move.b angle(a3),d0 btst #Status_Facing,status(a1) beq.s loc_2221A neg.b d0 loc_2221A: addq.b #8,d0 lsr.w #4,d0 move.b byte_22248(pc,d0.w),mapping_frame(a1) loc_22224: move.b status(a1),d1 andi.b #1,d1 andi.b #$FC,render_flags(a1) or.b d1,render_flags(a1) moveq #0,d0 move.b mapping_frame(a1),d0 move.l a2,-(sp) jsr (Perform_Player_DPLC).l movea.l (sp)+,a2 rts ; --------------------------------------------------------------------------- byte_22248: dc.b $91, $91, $90, $90, $90, $90, $90, $90, $92, $92, $92, $92, $92, $92, $91, $91 even ; --------------------------------------------------------------------------- loc_22258: movea.w $3C(a0),a3 moveq #0,d0 move.b angle(a3),d0 btst #Status_Facing,status(a1) beq.s loc_2226C neg.b d0 loc_2226C: addi.b #$10,d0 lsr.w #5,d0 add.w d0,d0 move.b byte_222D4(pc,d0.w),mapping_frame(a1) move.b #0,anim(a1) andi.w #$FFFE,d0 move.b byte_222E4(pc,d0.w),d2 move.b byte_222E4+1(pc,d0.w),d3 ext.w d2 ext.w d3 btst #Status_Facing,status(a1) beq.s loc_2229A neg.w d2 loc_2229A: movea.w $3C(a0),a3 move.b angle(a3),d0 addq.b #4,d0 andi.b #$F8,d0 jsr (GetSineCosine).l neg.w d0 addi.w #8,d0 addi.w #8,d1 asr.w #4,d0 asr.w #4,d1 add.w x_pos(a3),d0 add.w d2,d0 move.w d0,x_pos(a1) add.w y_pos(a3),d1 add.w d3,d1 move.w d1,y_pos(a1) bra.w loc_22224 ; --------------------------------------------------------------------------- byte_222D4: dc.b $78 dc.b $78 dc.b $7F dc.b $7F dc.b $7E dc.b $7E dc.b $7D dc.b $7D dc.b $7C dc.b $7C dc.b $7B dc.b $7B dc.b $7A dc.b $7A dc.b $79 dc.b $79 byte_222E4: dc.b 0, $18 dc.b -$12, $13 dc.b -$18, 0 dc.b -$12,-$13 dc.b 0,-$18 dc.b $12,-$13 dc.b $18, 0 dc.b $12, $13 even ; --------------------------------------------------------------------------- loc_222F4: tst.b 2(a2) beq.s loc_22302 subq.b #1,2(a2) bne.w locret_2237C loc_22302: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 addi.w #$10,d0 cmpi.w #$20,d0 bhs.w locret_2237C move.w y_pos(a1),d1 sub.w y_pos(a0),d1 cmpi.w #$18,d1 bhs.w locret_2237C tst.b object_control(a1) bne.s locret_2237C cmpi.b #4,routine(a1) bhs.s locret_2237C tst.w (Debug_placement_mode).w bne.s locret_2237C clr.w x_vel(a1) clr.w y_vel(a1) clr.w ground_vel(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$14,y_pos(a1) move.b #$14,anim(a1) move.b #0,spin_dash_flag(a1) move.b #3,object_control(a1) andi.b #$FD,render_flags(a1) move.b #1,(a2) moveq #signextendB(sfx_Grab),d0 jsr (Play_SFX).l locret_2237C: rts ; --------------------------------------------------------------------------- Obj_AIZGiantRideVine: movea.l a0,a1 move.l #loc_22442,(a1) bsr.w sub_2241A move.b #$21,mapping_frame(a1) move.w x_pos(a0),d2 move.w y_pos(a0),d3 move.b subtype(a0),d1 andi.w #$F,d1 jsr (AllocateObjectAfterCurrent).l bne.w loc_22418 move.w #-$1B0,$44(a1) move.w #$800,$38(a1) move.w a1,$3E(a0) move.l #loc_2248A,(a1) move.w a0,$3C(a1) move.b subtype(a0),d0 andi.b #$F0,d0 move.b d0,$42(a1) bra.s loc_223EA ; --------------------------------------------------------------------------- loc_223D2: jsr (AllocateObjectAfterCurrent).l bne.w loc_22418 move.l #loc_2251E,(a1) move.w a2,$3C(a1) move.w a1,$3E(a2) loc_223EA: movea.l a1,a2 bsr.s sub_2241A move.w d2,x_pos(a1) move.w d3,y_pos(a1) addi.w #$10,d3 addq.w #1,$36(a0) move.w $36(a0),$36(a1) dbf d1,loc_223D2 move.l #loc_2257E,(a1) move.b #$20,mapping_frame(a1) move.w a1,$40(a0) loc_22418: bra.s loc_22442 ; =============== S U B R O U T I N E ======================================= sub_2241A: move.b #4,render_flags(a1) move.b #8,width_pixels(a1) move.b #8,height_pixels(a1) move.w #$200,priority(a1) move.l #Map_AIZMHZRideVine,mappings(a1) move.w #make_art_tile($41B,0,0),art_tile(a1) rts ; End of function sub_2241A ; --------------------------------------------------------------------------- loc_22442: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_2245C jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_2245C: move.w $36(a0),d2 subq.w #1,d2 bcs.s loc_22478 movea.w $3E(a0),a2 loc_22468: movea.l a2,a1 movea.w $3E(a1),a2 jsr (Delete_Referenced_Sprite).l dbf d2,loc_22468 loc_22478: move.w respawn_addr(a0),d0 beq.s loc_22484 movea.w d0,a2 bclr #7,(a2) loc_22484: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- loc_2248A: tst.b (a0) bne.s loc_224BC move.b (AIZ_vine_angle).w,d0 add.b $42(a0),d0 jsr (GetSineCosine).l muls.w #$2C,d0 move.w d0,angle(a0) asr.w #3,d0 move.w d0,$3A(a0) move.b angle(a0),d0 addq.b #4,d0 lsr.b #3,d0 move.b d0,mapping_frame(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_224BC: moveq #0,d2 move.b $38(a0),d2 move.w $44(a0),d0 move.w #0,d1 tst.w $2E(a0) bne.s loc_224E8 add.w d2,d0 move.w d0,$44(a0) add.w d0,$42(a0) cmp.b $42(a0),d1 bgt.s loc_224FE move.w #1,$2E(a0) bra.s loc_224FE ; --------------------------------------------------------------------------- loc_224E8: sub.w d2,d0 move.w d0,$44(a0) add.w d0,$42(a0) cmp.b $42(a0),d1 ble.s loc_224FE move.w #0,$2E(a0) loc_224FE: move.w $42(a0),d0 move.w d0,angle(a0) asr.w #3,d0 move.w d0,$3A(a0) move.b angle(a0),d0 addq.b #4,d0 lsr.b #3,d0 move.b d0,mapping_frame(a0) jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_2251E: movea.w $3C(a0),a1 move.w $3A(a1),$3A(a0) move.w angle(a1),d0 add.w $3A(a0),d0 move.w d0,angle(a0) move.b angle(a0),d0 addq.b #4,d0 lsr.b #3,d0 move.b d0,mapping_frame(a0) bsr.w sub_2254A jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_2254A: movea.w $3C(a0),a1 move.b angle(a1),d0 addq.b #4,d0 andi.b #$F8,d0 jsr (GetSineCosine).l neg.w d0 addi.w #8,d0 addi.w #8,d1 asr.w #4,d0 asr.w #4,d1 add.w x_pos(a1),d0 move.w d0,x_pos(a0) add.w y_pos(a1),d1 move.w d1,y_pos(a0) rts ; End of function sub_2254A ; --------------------------------------------------------------------------- loc_2257E: move.w x_pos(a0),d4 move.w y_pos(a0),d5 bsr.w sub_2254A cmp.w x_pos(a0),d4 beq.s loc_22594 move.w d4,$42(a0) loc_22594: cmp.w y_pos(a0),d5 beq.s loc_2259E move.w d5,$44(a0) loc_2259E: lea $32(a0),a2 lea (Player_1).w,a1 move.w (Ctrl_1_logical).w,d0 bsr.w sub_220C2 lea (Player_2).w,a1 addq.w #1,a2 move.w (Ctrl_2_logical).w,d0 bsr.w sub_220C2 tst.w $32(a0) beq.s loc_225C8 tst.w $30(a0) bne.s locret_225CE loc_225C8: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_225CE: rts ; --------------------------------------------------------------------------- Obj_MHZSwingVine: movea.l a0,a1 move.l #loc_2267E,(a1) bsr.w sub_22656 move.b #$23,mapping_frame(a1) move.w x_pos(a0),d2 move.w y_pos(a0),d3 moveq #0,d1 addq.w #1,d1 jsr (AllocateObjectAfterCurrent).l bne.w loc_22654 move.w a1,$3E(a0) move.l #loc_2286C,(a1) move.w a0,$3C(a1) bra.s loc_2261A ; --------------------------------------------------------------------------- loc_22608: jsr (AllocateObjectAfterCurrent).l bne.w loc_22654 move.w a2,$3C(a1) move.w a1,$3E(a2) loc_2261A: movea.l a1,a2 bsr.s sub_22656 move.w d2,x_pos(a1) move.w d3,y_pos(a1) addi.w #$10,d3 addq.w #1,$36(a0) move.w $36(a0),$36(a1) dbf d1,loc_22608 move.l #loc_228CC,(a1) move.b #$22,mapping_frame(a1) move.w x_pos(a1),$42(a1) move.w y_pos(a1),$44(a1) move.w a1,$40(a0) loc_22654: bra.s loc_2267E ; =============== S U B R O U T I N E ======================================= sub_22656: move.b #4,render_flags(a1) move.b #8,width_pixels(a1) move.b #8,height_pixels(a1) move.w #$200,priority(a1) move.l #Map_AIZMHZRideVine,mappings(a1) move.w #make_art_tile($455,0,0),art_tile(a1) rts ; End of function sub_22656 ; --------------------------------------------------------------------------- loc_2267E: movea.w $40(a0),a1 tst.w $32(a1) beq.s loc_226AC bmi.s loc_22690 tst.b $33(a1) bpl.s loc_226AC loc_22690: move.l #loc_226B0,(a0) movea.w $40(a0),a1 move.w #1,$30(a1) move.w #0,angle(a0) move.w #$800,$3A(a0) loc_226AC: bra.w loc_22824 ; --------------------------------------------------------------------------- loc_226B0: movea.w $40(a0),a1 move.w $3A(a0),d0 move.b angle(a0),d1 ext.w d1 bpl.s loc_226C2 neg.w d1 loc_226C2: add.w d1,d1 sub.w d1,d0 sub.w d0,angle(a0) move.b angle(a0),d0 andi.b #$F8,d0 cmpi.b #$40,d0 bne.s loc_226E0 moveq #signextendB(sfx_GroundSlide),d0 jsr (Play_SFX).l loc_226E0: move.w #$200,priority(a0) tst.w angle(a0) bpl.s loc_226F2 move.w #$280,priority(a0) loc_226F2: tst.b $32(a1) beq.s loc_2270A move.b #1,(Scroll_force_positions).w move.w x_pos(a0),(Scroll_forced_X_pos).w move.w y_pos(a0),(Scroll_forced_Y_pos).w loc_2270A: tst.w $32(a1) bne.s loc_22744 move.b angle(a0),d0 addq.b #8,d0 cmpi.b #$10,d0 bhs.s loc_22744 move.l #loc_22748,(a0) move.w #0,$42(a0) move.w #-$300,$44(a0) move.w #$1000,$38(a0) move.w #0,$2E(a0) movea.w $40(a0),a1 move.w #2,$30(a1) loc_22744: bra.w loc_22824 ; --------------------------------------------------------------------------- loc_22748: moveq #0,d2 move.b $38(a0),d2 move.w $44(a0),d0 move.w #0,d1 tst.w $2E(a0) bne.s loc_227AC add.w d2,d0 move.w d0,$44(a0) add.w d0,$42(a0) cmp.b $42(a0),d1 bgt.s loc_227D6 asr.w #4,d0 sub.w d0,$44(a0) move.w #1,$2E(a0) cmpi.w #$C00,$38(a0) beq.s loc_22788 subi.w #$40,$38(a0) bra.s loc_227D6 ; --------------------------------------------------------------------------- loc_22788: move.l #loc_2267E,(a0) move.w #0,$38(a0) movea.w $40(a0),a1 move.w #0,$30(a1) move.w x_pos(a1),$42(a1) move.w y_pos(a1),$44(a1) bra.s loc_227D6 ; --------------------------------------------------------------------------- loc_227AC: sub.w d2,d0 move.w d0,$44(a0) add.w d0,$42(a0) cmp.b $42(a0),d1 ble.s loc_227D6 asr.w #4,d0 sub.w d0,$44(a0) move.w #0,$2E(a0) cmpi.w #$C00,$38(a0) beq.s loc_22788 subi.w #$40,$38(a0) loc_227D6: move.w $42(a0),d0 move.w d0,angle(a0) move.w #$200,priority(a0) tst.w angle(a0) bpl.s loc_227F0 move.w #$280,priority(a0) loc_227F0: asr.w #3,d0 move.w d0,$3A(a0) movea.w $3E(a0),a1 move.w $3A(a0),$3A(a1) movea.w $40(a0),a1 tst.w $32(a1) beq.s loc_22824 bmi.s loc_22812 tst.b $33(a1) bpl.s loc_22824 loc_22812: move.l #loc_226B0,(a0) move.w #1,$30(a1) move.w #$800,$3A(a0) loc_22824: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_2283E jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_2283E: move.w $36(a0),d2 subq.w #1,d2 bcs.s loc_2285A movea.w $3E(a0),a2 loc_2284A: movea.l a2,a1 movea.w $3E(a1),a2 jsr (Delete_Referenced_Sprite).l dbf d2,loc_2284A loc_2285A: move.w respawn_addr(a0),d0 beq.s loc_22866 movea.w d0,a2 bclr #7,(a2) loc_22866: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- loc_2286C: movea.w $3C(a0),a1 move.w angle(a1),angle(a0) move.b angle(a0),d0 addq.b #4,d0 lsr.b #3,d0 move.b d0,mapping_frame(a0) movea.w $3C(a0),a1 move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_22898: movea.w $3C(a0),a1 move.b angle(a1),d0 addq.b #4,d0 andi.b #$F8,d0 jsr (GetSineCosine).l neg.w d0 addi.w #8,d0 addi.w #8,d1 asr.w #4,d0 asr.w #4,d1 add.w x_pos(a1),d0 move.w d0,x_pos(a0) add.w y_pos(a1),d1 move.w d1,y_pos(a0) rts ; End of function sub_22898 ; --------------------------------------------------------------------------- loc_228CC: move.w x_pos(a0),d4 move.w y_pos(a0),d5 bsr.w sub_22898 cmp.w x_pos(a0),d4 beq.s loc_228E2 move.w d4,$42(a0) loc_228E2: cmp.w y_pos(a0),d5 beq.s loc_228EC move.w d5,$44(a0) loc_228EC: lea $32(a0),a2 lea (Player_1).w,a1 move.w (Ctrl_1_logical).w,d0 bsr.s loc_2291A lea (Player_2).w,a1 addq.w #1,a2 move.w (Ctrl_2_logical).w,d0 bsr.s loc_2291A tst.w $32(a0) beq.s loc_22912 tst.w $30(a0) bne.s locret_22918 loc_22912: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- locret_22918: rts ; --------------------------------------------------------------------------- loc_2291A: tst.b (a2) beq.w loc_22AF8 tst.b render_flags(a1) bpl.w loc_229E4 cmpi.b #4,routine(a1) bhs.w loc_229E4 tst.w (Debug_placement_mode).w bne.w loc_229E4 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 beq.w loc_229F2 clr.b object_control(a1) clr.b (a2) cmpi.w #1,$30(a0) beq.s loc_229B6 move.w x_pos(a0),d1 sub.w $42(a0),d1 asl.w #7,d1 move.w d1,x_vel(a1) move.w y_pos(a0),d1 sub.w $44(a0),d1 asl.w #7,d1 move.w d1,y_vel(a1) move.b #$3C,2(a2) btst #button_left+8,d0 beq.s loc_2297E move.w #-$200,x_vel(a1) loc_2297E: btst #button_right+8,d0 beq.s loc_2298A move.w #$200,x_vel(a1) loc_2298A: addi.w #-$380,y_vel(a1) loc_22990: bset #Status_InAir,status(a1) move.b #1,$40(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #2,anim(a1) bset #Status_Roll,status(a1) rts ; --------------------------------------------------------------------------- loc_229B6: move.b #$3C,2(a2) movea.w $3C(a0),a3 move.b angle(a3),d0 jsr (GetSineCosine).l asl.w #2,d1 move.w d1,d2 asl.w #1,d1 add.w d2,d1 move.w d1,x_vel(a1) asl.w #2,d0 move.w d0,d2 asl.w #1,d0 add.w d2,d0 move.w d0,y_vel(a1) bra.s loc_22990 ; --------------------------------------------------------------------------- loc_229E4: clr.b $2E(a1) clr.b (a2) move.b #$3C,2(a2) rts ; --------------------------------------------------------------------------- loc_229F2: tst.w $30(a0) bne.s loc_22A5C move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$14,y_pos(a1) movea.w $3C(a0),a3 moveq #0,d0 move.b angle(a3),d0 btst #Status_Facing,status(a1) beq.s loc_22A1E neg.b d0 loc_22A1E: addq.b #8,d0 lsr.w #4,d0 move.b byte_22A4C(pc,d0.w),mapping_frame(a1) loc_22A28: move.b status(a1),d1 andi.b #1,d1 andi.b #$FC,render_flags(a1) or.b d1,render_flags(a1) moveq #0,d0 move.b mapping_frame(a1),d0 move.l a2,-(sp) jsr (Perform_Player_DPLC).l movea.l (sp)+,a2 rts ; --------------------------------------------------------------------------- byte_22A4C: dc.b $91, $91, $90, $90, $90, $90, $90, $90, $92, $92, $92, $92, $92, $92, $91, $91 even ; --------------------------------------------------------------------------- loc_22A5C: movea.w $3C(a0),a3 moveq #0,d0 move.b angle(a3),d0 btst #Status_Facing,status(a1) beq.s loc_22A70 neg.b d0 loc_22A70: addi.b #$10,d0 lsr.w #5,d0 add.w d0,d0 move.b byte_22AD8(pc,d0.w),mapping_frame(a1) move.b #0,anim(a1) andi.w #$FFFE,d0 move.b byte_22AD8+$10(pc,d0.w),d2 move.b byte_22AE9(pc,d0.w),d3 ext.w d2 ext.w d3 btst #Status_Facing,status(a1) beq.s loc_22A9E neg.w d2 loc_22A9E: movea.w $3C(a0),a3 move.b angle(a3),d0 addq.b #4,d0 andi.b #$F8,d0 jsr (GetSineCosine).l neg.w d0 addi.w #8,d0 addi.w #8,d1 asr.w #4,d0 asr.w #4,d1 add.w x_pos(a3),d0 add.w d2,d0 move.w d0,x_pos(a1) add.w y_pos(a3),d1 add.w d3,d1 move.w d1,y_pos(a1) bra.w loc_22A28 ; --------------------------------------------------------------------------- byte_22AD8: dc.b $78 dc.b $78 dc.b $7F dc.b $7F dc.b $7E dc.b $7E dc.b $7D dc.b $7D dc.b $7C dc.b $7C dc.b $7B dc.b $7B dc.b $7A dc.b $7A dc.b $79 dc.b $79 dc.b 0 byte_22AE9: dc.b $18 dc.b -$12 dc.b $13 dc.b -$18 dc.b 0 dc.b -$12 dc.b -$13 dc.b 0 dc.b -$18 dc.b $12 dc.b -$13 dc.b $18 dc.b 0 dc.b $12 dc.b $13 even ; --------------------------------------------------------------------------- loc_22AF8: tst.b 2(a2) beq.s loc_22B06 subq.b #1,2(a2) bne.w locret_22B9C loc_22B06: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 addi.w #$10,d0 cmpi.w #$20,d0 bhs.w locret_22B9C move.w y_pos(a1),d1 sub.w y_pos(a0),d1 cmpi.w #$28,d1 bhs.w locret_22B9C move.w x_vel(a1),d0 cmpi.w #$400,d0 bge.s loc_22B3C cmpi.w #$18,d1 bhs.w locret_22B9C loc_22B3C: tst.b object_control(a1) bne.s locret_22B9C cmpi.b #4,routine(a1) bhs.s locret_22B9C tst.w (Debug_placement_mode).w bne.s locret_22B9C clr.w x_vel(a1) clr.w y_vel(a1) clr.w ground_vel(a1) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$14,y_pos(a1) move.b #$14,anim(a1) move.b #0,spin_dash_flag(a1) move.b #3,object_control(a1) andi.b #$FD,render_flags(a1) move.b #1,(a2) cmpi.w #$400,d0 blt.s loc_22B3C move.b #$81,(a2) moveq #signextendB(sfx_Grab),d0 jsr (Play_SFX).l locret_22B9C: rts ; --------------------------------------------------------------------------- Map_AIZMHZRideVine: include "Levels/AIZ/Misc Object Data/Map - (&MHZ) Ride Vine.asm" ; =============== S U B R O U T I N E ======================================= Obj_Spring: move.l #Map_Spring,mappings(a0) move.w #make_art_tile($4A4,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #$10,height_pixels(a0) move.w #$200,priority(a0) move.w x_pos(a0),$32(a0) move.w y_pos(a0),$34(a0) move.b subtype(a0),d0 lsr.w #3,d0 andi.w #$E,d0 move.w Spring_Index(pc,d0.w),d0 jmp Spring_Index(pc,d0.w) ; End of function Obj_Spring ; --------------------------------------------------------------------------- Spring_Index: dc.w Spring_Up-Spring_Index dc.w Spring_Horizontal-Spring_Index dc.w Spring_Down-Spring_Index dc.w Spring_UpDiag-Spring_Index dc.w Spring_DownDiag-Spring_Index ; =============== S U B R O U T I N E ======================================= sub_22D54: move.l #Map_Spring,mappings(a0) move.w #make_art_tile($4A4,0,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #$10,height_pixels(a0) move.w #$200,priority(a0) move.w x_pos(a0),$32(a0) move.w y_pos(a0),$34(a0) move.b subtype(a0),d0 lsr.w #3,d0 andi.w #$E,d0 move.w off_22DA0(pc,d0.w),d0 jsr off_22DA0(pc,d0.w) move.w #-$800,$30(a0) rts ; End of function sub_22D54 ; --------------------------------------------------------------------------- off_22DA0: dc.w Spring_Up-off_22DA0 dc.w Spring_Horizontal-off_22DA0 dc.w Spring_Down-off_22DA0 dc.w Spring_Horizontal-off_22DA0 dc.w Spring_Up-off_22DA0 dc.w Spring_Down-off_22DA0 dc.w Spring_Up-off_22DA0 dc.w Spring_Down-off_22DA0 ; --------------------------------------------------------------------------- Spring_Horizontal: move.b #2,anim(a0) move.b #3,mapping_frame(a0) move.w #make_art_tile($4B4,0,0),art_tile(a0) move.b #8,width_pixels(a0) move.l #Obj_Spring_Horizontal,(a0) tst.w (Competition_mode).w beq.w Spring_Common move.l #Map_2PSpring,mappings(a0) move.w #make_art_tile($3AD,0,0),art_tile(a0) move.l #Obj_2PSpring_Horizontal,(a0) bra.w Spring_Common ; --------------------------------------------------------------------------- Spring_Down: tst.b (Reverse_gravity_flag).w bne.w loc_22E96 bset #1,status(a0) loc_22DFC: move.b #6,mapping_frame(a0) move.l #Obj_Spring_Down,(a0) tst.w (Competition_mode).w beq.w Spring_Common move.l #Obj_2PSpring_Down,(a0) move.l #Map_2PSpring,mappings(a0) move.w #make_art_tile($391,0,0),art_tile(a0) bra.w Spring_Common ; --------------------------------------------------------------------------- Spring_UpDiag: move.b #4,anim(a0) move.b #7,mapping_frame(a0) move.w #make_art_tile($43A,0,0),art_tile(a0) cmpi.b #2,(Current_zone).w beq.s loc_22E4A cmpi.b #7,(Current_zone).w bne.s loc_22E50 loc_22E4A: move.w #make_art_tile($478,0,0),art_tile(a0) loc_22E50: move.l #Obj_Spring_UpDiag,(a0) bra.s Spring_Common ; --------------------------------------------------------------------------- Spring_DownDiag: move.b #4,anim(a0) move.b #$A,mapping_frame(a0) move.w #make_art_tile($43A,0,0),art_tile(a0) cmpi.b #2,(Current_zone).w beq.s loc_22E7A cmpi.b #7,(Current_zone).w bne.s loc_22E80 loc_22E7A: move.w #make_art_tile($478,0,0),art_tile(a0) loc_22E80: bset #1,status(a0) move.l #Obj_Spring_DownDiag,(a0) bra.s Spring_Common ; --------------------------------------------------------------------------- Spring_Up: tst.b (Reverse_gravity_flag).w bne.w loc_22DFC loc_22E96: move.l #Obj_Spring_Up,(a0) tst.w (Competition_mode).w beq.s Spring_Common move.l #Obj_2PSpring_Up,(a0) move.l #Map_2PSpring,mappings(a0) move.w #make_art_tile($391,0,0),art_tile(a0) cmpi.b #$12,(Current_zone).w bne.s Spring_Common ori.w #high_priority,art_tile(a0) Spring_Common: move.b subtype(a0),d0 andi.w #2,d0 move.w word_22EF0(pc,d0.w),$30(a0) btst #1,d0 beq.s locret_22EEE move.l #Map_Spring2,mappings(a0) tst.w (Competition_mode).w beq.s locret_22EEE move.l #Map_Spring3,mappings(a0) locret_22EEE: rts ; --------------------------------------------------------------------------- word_22EF0: dc.w -$1000 dc.w -$A00 ; --------------------------------------------------------------------------- Obj_Spring_Up: move.w #$1B,d1 move.w #8,d2 move.w #$10,d3 move.w x_pos(a0),d4 lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w SolidObjectFull2_1P btst #p1_standing_bit,status(a0) beq.s loc_22F1C bsr.s sub_22F98 loc_22F1C: movem.l (sp)+,d1-d4 lea (Player_2).w,a1 moveq #p2_standing_bit,d6 bsr.w SolidObjectFull2_1P btst #p2_standing_bit,status(a0) beq.s loc_22F34 bsr.s sub_22F98 loc_22F34: lea (Ani_Spring).l,a1 jsr (Animate_Sprite).l jmp (Sprite_OnScreen_Test).l ; --------------------------------------------------------------------------- Obj_2PSpring_Up: move.w #$13,d1 move.w #8,d2 move.w #$10,d3 move.w x_pos(a0),d4 lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w SolidObjectFull2_1P btst #p1_standing_bit,status(a0) beq.s loc_22F6E bsr.s sub_22F98 loc_22F6E: movem.l (sp)+,d1-d4 lea (Player_2).w,a1 moveq #p2_standing_bit,d6 bsr.w SolidObjectFull2_1P btst #p2_standing_bit,status(a0) beq.s loc_22F86 bsr.s sub_22F98 loc_22F86: lea (Ani_Spring).l,a1 jsr (Animate_Sprite).l jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_22F98: move.w #1<<8,anim(a0) ; and prev_anim addq.w #8,y_pos(a1) tst.b (Reverse_gravity_flag).w beq.s loc_22FAE subi.w #2*8,y_pos(a1) loc_22FAE: move.w $30(a0),y_vel(a1) bset #1,status(a1) bclr #3,status(a1) clr.b jumping(a1) clr.b spin_dash_flag(a1) move.b #$10,anim(a1) move.b #2,routine(a1) move.b subtype(a0),d0 bpl.s loc_22FE0 move.w #0,x_vel(a1) loc_22FE0: btst #0,d0 beq.s loc_23020 move.w #1,ground_vel(a1) move.b #1,flip_angle(a1) move.b #0,anim(a1) move.b #0,flips_remaining(a1) move.b #4,flip_speed(a1) btst #1,d0 bne.s loc_23010 move.b #1,flips_remaining(a1) loc_23010: btst #0,status(a1) beq.s loc_23020 neg.b flip_angle(a1) neg.w ground_vel(a1) loc_23020: andi.b #$C,d0 cmpi.b #4,d0 bne.s loc_23036 move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) loc_23036: cmpi.b #8,d0 bne.s loc_23048 move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_23048: moveq #signextendB(sfx_Spring),d0 jmp (Play_SFX).l ; End of function sub_22F98 ; --------------------------------------------------------------------------- Obj_Spring_Horizontal: move.w #$13,d1 move.w #$E,d2 move.w #$F,d3 move.w x_pos(a0),d4 lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w SolidObjectFull2_1P swap d6 andi.w #1,d6 beq.s loc_23092 move.b status(a0),d1 move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcs.s loc_23088 eori.b #1,d1 loc_23088: andi.b #1,d1 bne.s loc_23092 bsr.w sub_23190 loc_23092: movem.l (sp)+,d1-d4 lea (Player_2).w,a1 moveq #p2_standing_bit,d6 bsr.w SolidObjectFull2_1P swap d6 andi.w #2,d6 beq.s loc_230C4 move.b status(a0),d1 move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcs.s loc_230BA eori.b #1,d1 loc_230BA: andi.b #1,d1 bne.s loc_230C4 bsr.w sub_23190 loc_230C4: bsr.w sub_2326C lea (Ani_Spring).l,a1 jsr (Animate_Sprite).l move.w $32(a0),d0 jmp (Sprite_OnScreen_Test2).l ; --------------------------------------------------------------------------- Obj_2PSpring_Horizontal: move.w #$F,d1 move.w #$C,d2 move.w #$D,d3 move.w x_pos(a0),d4 lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w SolidObjectFull2_1P swap d6 andi.w #1,d6 beq.s loc_2311E move.b status(a0),d1 move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcs.s loc_23116 eori.b #1,d1 loc_23116: andi.b #1,d1 bne.s loc_2311E bsr.s sub_23160 loc_2311E: movem.l (sp)+,d1-d4 lea (Player_2).w,a1 moveq #p2_standing_bit,d6 bsr.w SolidObjectFull2_1P swap d6 andi.w #2,d6 beq.s loc_2314E move.b status(a0),d1 move.w x_pos(a0),d0 sub.w x_pos(a1),d0 bcs.s loc_23146 eori.b #1,d1 loc_23146: andi.b #1,d1 bne.s loc_2314E bsr.s sub_23160 loc_2314E: lea (Ani_Spring).l,a1 jsr (Animate_Sprite).l jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_23160: move.w #3<<8,anim(a0) ; and prev_anim move.w $30(a0),x_vel(a1) addq.w #4,x_pos(a1) bset #Status_Facing,status(a1) btst #0,status(a0) bne.s loc_2318E bclr #Status_Facing,status(a1) subi.w #2*4,x_pos(a1) neg.w x_vel(a1) loc_2318E: bra.s loc_231BE ; End of function sub_23160 ; =============== S U B R O U T I N E ======================================= sub_23190: move.w #3<<8,anim(a0) ; and prev_anim move.w $30(a0),x_vel(a1) addq.w #8,x_pos(a1) bset #Status_Facing,status(a1) btst #0,status(a0) bne.s loc_231BE bclr #Status_Facing,status(a1) subi.w #2*8,x_pos(a1) neg.w x_vel(a1) loc_231BE: move.w #$F,$32(a1) move.w x_vel(a1),ground_vel(a1) btst #Status_Roll,status(a1) bne.s loc_231D8 move.b #0,anim(a1) loc_231D8: move.b subtype(a0),d0 bpl.s loc_231E4 move.w #0,y_vel(a1) loc_231E4: btst #0,d0 beq.s loc_23224 move.w #1,ground_vel(a1) move.b #1,flip_angle(a1) move.b #0,anim(a1) move.b #1,flips_remaining(a1) move.b #8,flip_speed(a1) btst #1,d0 bne.s loc_23214 move.b #3,flips_remaining(a1) loc_23214: btst #Status_Facing,status(a1) beq.s loc_23224 neg.b flip_angle(a1) neg.w ground_vel(a1) loc_23224: andi.b #$C,d0 cmpi.b #4,d0 bne.s loc_2323A move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) loc_2323A: cmpi.b #8,d0 bne.s loc_2324C move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_2324C: bclr #p1_pushing_bit,status(a0) bclr #p2_pushing_bit,status(a0) bclr #Status_Push,status(a1) move.b #0,double_jump_flag(a1) moveq #signextendB(sfx_Spring),d0 jmp (Play_SFX).l ; End of function sub_23190 ; =============== S U B R O U T I N E ======================================= sub_2326C: cmpi.b #3,anim(a0) beq.w locret_23324 move.w x_pos(a0),d0 move.w d0,d1 addi.w #$28,d1 btst #0,status(a0) beq.s loc_2328E move.w d0,d1 subi.w #$28,d0 loc_2328E: move.w y_pos(a0),d2 move.w d2,d3 subi.w #$18,d2 addi.w #$18,d3 lea (Player_1).w,a1 btst #1,status(a1) bne.s loc_232E2 move.w ground_vel(a1),d4 btst #0,status(a0) beq.s loc_232B6 neg.w d4 loc_232B6: tst.w d4 bmi.s loc_232E2 move.w x_pos(a1),d4 cmp.w d0,d4 blo.w loc_232E2 cmp.w d1,d4 bhs.w loc_232E2 move.w y_pos(a1),d4 cmp.w d2,d4 blo.w loc_232E2 cmp.w d3,d4 bhs.w loc_232E2 move.w d0,-(sp) bsr.w sub_23190 move.w (sp)+,d0 loc_232E2: lea (Player_2).w,a1 btst #Status_InAir,status(a1) bne.s locret_23324 move.w ground_vel(a1),d4 btst #0,status(a0) beq.s loc_232FC neg.w d4 loc_232FC: tst.w d4 bmi.s locret_23324 move.w x_pos(a1),d4 cmp.w d0,d4 blo.w locret_23324 cmp.w d1,d4 bhs.w locret_23324 move.w y_pos(a1),d4 cmp.w d2,d4 blo.w locret_23324 cmp.w d3,d4 bhs.w locret_23324 bsr.w sub_23190 locret_23324: rts ; End of function sub_2326C ; --------------------------------------------------------------------------- Obj_Spring_Down: move.w #$1B,d1 move.w #8,d2 move.w #9,d3 move.w x_pos(a0),d4 lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w SolidObjectFull2_1P cmpi.w #-2,d4 bne.s loc_2334C bsr.s sub_233CA loc_2334C: movem.l (sp)+,d1-d4 lea (Player_2).w,a1 moveq #p2_standing_bit,d6 bsr.w SolidObjectFull2_1P cmpi.w #-2,d4 bne.s loc_23362 bsr.s sub_233CA loc_23362: lea (Ani_Spring).l,a1 jsr (Animate_Sprite).l jmp (Sprite_OnScreen_Test).l ; --------------------------------------------------------------------------- Obj_2PSpring_Down: move.w #$13,d1 move.w #8,d2 move.w #9,d3 move.w x_pos(a0),d4 lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w SolidObjectFull2_1P cmpi.w #-2,d4 bne.s loc_2339E subq.w #4,y_pos(a1) bsr.s loc_233DA loc_2339E: movem.l (sp)+,d1-d4 lea (Player_2).w,a1 moveq #p2_standing_bit,d6 bsr.w SolidObjectFull2_1P cmpi.w #-2,d4 bne.s loc_233B8 subq.w #4,y_pos(a1) bsr.s loc_233DA loc_233B8: lea (Ani_Spring).l,a1 jsr (Animate_Sprite).l jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_233CA: subq.w #8,y_pos(a1) tst.b (Reverse_gravity_flag).w beq.s loc_233DA addi.w #2*8,y_pos(a1) loc_233DA: move.w #1<<8,anim(a0) ; and prev_anim move.w $30(a0),y_vel(a1) neg.w y_vel(a1) cmpi.w #$1000,y_vel(a1) bne.s loc_233F8 move.w #$D00,y_vel(a1) loc_233F8: move.b subtype(a0),d0 bpl.s loc_23404 move.w #0,x_vel(a1) loc_23404: btst #0,d0 beq.s loc_23444 move.w #1,ground_vel(a1) move.b #1,flip_angle(a1) move.b #0,anim(a1) move.b #0,flips_remaining(a1) move.b #4,flip_speed(a1) btst #1,d0 bne.s loc_23434 move.b #1,flips_remaining(a1) loc_23434: btst #Status_Facing,status(a1) beq.s loc_23444 neg.b flip_angle(a1) neg.w ground_vel(a1) loc_23444: andi.b #$C,d0 cmpi.b #4,d0 bne.s loc_2345A move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) loc_2345A: cmpi.b #8,d0 bne.s loc_2346C move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_2346C: bset #Status_InAir,status(a1) bclr #Status_OnObj,status(a1) clr.b jumping(a1) move.b #2,routine(a1) move.b #0,double_jump_flag(a1) moveq #signextendB(sfx_Spring),d0 jmp (Play_SFX).l ; End of function sub_233CA ; --------------------------------------------------------------------------- Obj_Spring_UpDiag: move.w #$1B,d1 move.w #$10,d2 move.w x_pos(a0),d4 lea byte_236EA(pc),a2 lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w sub_1DD24 btst #p1_standing_bit,status(a0) beq.s loc_234B8 bsr.s sub_234E6 loc_234B8: movem.l (sp)+,d1-d4 lea (Player_2).w,a1 moveq #p2_standing_bit,d6 bsr.w sub_1DD24 btst #p2_standing_bit,status(a0) beq.s loc_234D0 bsr.s sub_234E6 loc_234D0: lea (Ani_Spring).l,a1 jsr (Animate_Sprite).l move.w $32(a0),d0 jmp (Sprite_OnScreen_Test2).l ; =============== S U B R O U T I N E ======================================= sub_234E6: btst #0,status(a0) bne.s loc_234FC move.w x_pos(a0),d0 subq.w #4,d0 cmp.w x_pos(a1),d0 blo.s loc_2350A rts ; --------------------------------------------------------------------------- loc_234FC: move.w x_pos(a0),d0 addq.w #4,d0 cmp.w x_pos(a1),d0 bhs.s loc_2350A rts ; --------------------------------------------------------------------------- loc_2350A: move.w #5<<8,anim(a0) ; and prev_anim move.w $30(a0),y_vel(a1) move.w $30(a0),x_vel(a1) addq.w #6,y_pos(a1) addq.w #6,x_pos(a1) bset #Status_Facing,status(a1) btst #0,status(a0) bne.s loc_23542 bclr #Status_Facing,status(a1) subi.w #2*6,x_pos(a1) neg.w x_vel(a1) loc_23542: bset #Status_InAir,status(a1) bclr #Status_OnObj,status(a1) clr.b jumping(a1) move.b #$10,anim(a1) move.b #2,routine(a1) move.b subtype(a0),d0 btst #0,d0 beq.s loc_235A2 move.w #1,ground_vel(a1) move.b #1,flip_angle(a1) move.b #0,anim(a1) move.b #1,flips_remaining(a1) move.b #8,flip_speed(a1) btst #1,d0 bne.s loc_23592 move.b #3,flips_remaining(a1) loc_23592: btst #0,status(a1) beq.s loc_235A2 neg.b flip_angle(a1) neg.w ground_vel(a1) loc_235A2: andi.b #$C,d0 cmpi.b #4,d0 bne.s loc_235B8 move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) loc_235B8: cmpi.b #8,d0 bne.s loc_235CA move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_235CA: moveq #signextendB(sfx_Spring),d0 jmp (Play_SFX).l ; End of function sub_234E6 ; --------------------------------------------------------------------------- Obj_Spring_DownDiag: move.w #$1B,d1 move.w #$10,d2 move.w x_pos(a0),d4 lea byte_23706(pc),a2 lea (Player_1).w,a1 moveq #p1_standing_bit,d6 movem.l d1-d4,-(sp) bsr.w sub_1DD24 cmpi.w #-2,d4 bne.s loc_235F8 bsr.s sub_23624 loc_235F8: movem.l (sp)+,d1-d4 lea (Player_2).w,a1 moveq #p2_standing_bit,d6 bsr.w sub_1DD24 cmpi.w #-2,d4 bne.s loc_2360E bsr.s sub_23624 loc_2360E: lea (Ani_Spring).l,a1 jsr (Animate_Sprite).l move.w $32(a0),d0 jmp (Sprite_OnScreen_Test2).l ; =============== S U B R O U T I N E ======================================= sub_23624: move.w #5<<8,anim(a0) ; and prev_anim move.w $30(a0),y_vel(a1) neg.w y_vel(a1) move.w $30(a0),x_vel(a1) subq.w #6,y_pos(a1) addq.w #6,x_pos(a1) bset #Status_Facing,status(a1) btst #0,status(a0) bne.s loc_23660 bclr #Status_Facing,status(a1) subi.w #2*6,x_pos(a1) neg.w x_vel(a1) loc_23660: bset #Status_InAir,status(a1) bclr #Status_OnObj,status(a1) clr.b jumping(a1) move.b #2,routine(a1) move.b subtype(a0),d0 btst #0,d0 beq.s loc_236BA move.w #1,ground_vel(a1) move.b #1,flip_angle(a1) move.b #0,anim(a1) move.b #1,flips_remaining(a1) move.b #8,flip_speed(a1) btst #1,d0 bne.s loc_236AA move.b #3,flips_remaining(a1) loc_236AA: btst #Status_Facing,status(a1) beq.s loc_236BA neg.b flip_angle(a1) neg.w ground_vel(a1) loc_236BA: andi.b #$C,d0 cmpi.b #4,d0 bne.s loc_236D0 move.b #$C,top_solid_bit(a1) move.b #$D,lrb_solid_bit(a1) loc_236D0: cmpi.b #8,d0 bne.s loc_236E2 move.b #$E,top_solid_bit(a1) move.b #$F,lrb_solid_bit(a1) loc_236E2: moveq #signextendB(sfx_Spring),d0 jmp (Play_SFX).l ; End of function sub_23624 ; --------------------------------------------------------------------------- byte_236EA: dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $E dc.b $C dc.b $A dc.b 8 dc.b 6 dc.b 4 dc.b 2 dc.b 0 dc.b -2 dc.b -4 dc.b -4 dc.b -4 dc.b -4 dc.b -4 dc.b -4 dc.b -4 byte_23706: dc.b -$C dc.b -$10 dc.b -$10 dc.b -$10 dc.b -$10 dc.b -$10 dc.b -$10 dc.b -$10 dc.b -$10 dc.b -$10 dc.b -$10 dc.b -$10 dc.b -$E dc.b -$C dc.b -$A dc.b -8 dc.b -6 dc.b -4 dc.b -2 dc.b 0 dc.b 2 dc.b 4 dc.b 4 dc.b 4 dc.b 4 dc.b 4 dc.b 4 dc.b 4 even Ani_Spring: include "General/Sprites/Level Misc/Anim - Spring.asm" Map_Spring: include "General/Sprites/Level Misc/Map - Spring.asm" Map_2PSpring: include "General/Sprites/Level Misc/Map - 2P Spring.asm" ; --------------------------------------------------------------------------- Obj_RetractingSpring: bsr.w Obj_Spring move.b subtype(a0),d0 lsr.w #3,d0 andi.w #$E,d0 move.w RetractingSpring_Index(pc,d0.w),d1 jmp RetractingSpring_Index(pc,d1.w) ; --------------------------------------------------------------------------- RetractingSpring_Index: dc.w loc_23A04-RetractingSpring_Index dc.w loc_23A20-RetractingSpring_Index dc.w loc_23A3C-RetractingSpring_Index dc.w loc_23A58-RetractingSpring_Index dc.w loc_23A88-RetractingSpring_Index ; --------------------------------------------------------------------------- loc_23A04: move.l #loc_23A0A,(a0) loc_23A0A: bsr.w sub_23AB8 moveq #0,d0 move.b $36(a0),d0 add.w $34(a0),d0 move.w d0,y_pos(a0) bra.w Obj_Spring_Up ; --------------------------------------------------------------------------- loc_23A20: move.l #loc_23A26,(a0) loc_23A26: bsr.w sub_23AB8 moveq #0,d0 move.b $36(a0),d0 add.w $32(a0),d0 move.w d0,x_pos(a0) bra.w Obj_Spring_Horizontal ; --------------------------------------------------------------------------- loc_23A3C: move.l #loc_23A42,(a0) loc_23A42: bsr.w sub_23AB8 moveq #0,d0 move.b $36(a0),d0 add.w $34(a0),d0 move.w d0,y_pos(a0) bra.w Obj_Spring_Down ; --------------------------------------------------------------------------- loc_23A58: move.l #loc_23A5E,(a0) loc_23A5E: bsr.w sub_23AB8 moveq #0,d0 move.b $36(a0),d0 move.w d0,d1 btst #0,status(a0) bne.s loc_23A74 neg.w d0 loc_23A74: add.w $32(a0),d0 move.w d0,x_pos(a0) add.w $34(a0),d1 move.w d1,y_pos(a0) bra.w Obj_Spring_UpDiag ; --------------------------------------------------------------------------- loc_23A88: move.l #loc_23A8E,(a0) loc_23A8E: bsr.w sub_23AB8 moveq #0,d0 move.b $36(a0),d0 move.w d0,d1 btst #0,status(a0) beq.s loc_23AA4 neg.w d0 loc_23AA4: add.w $32(a0),d0 move.w d0,x_pos(a0) add.w $34(a0),d1 move.w d1,y_pos(a0) bra.w Obj_Spring_DownDiag ; =============== S U B R O U T I N E ======================================= sub_23AB8: tst.w $3A(a0) beq.s loc_23AD4 subq.w #1,$3A(a0) bne.s locret_23B16 tst.b render_flags(a0) bpl.s locret_23B16 moveq #signextendB(sfx_SpikeMove),d0 jsr (Play_SFX).l bra.s locret_23B16 ; --------------------------------------------------------------------------- loc_23AD4: tst.w $38(a0) beq.s loc_23AF6 subi.w #$800,$36(a0) bcc.s locret_23B16 move.w #0,$36(a0) move.w #0,$38(a0) move.w #60,$3A(a0) bra.s locret_23B16 ; --------------------------------------------------------------------------- loc_23AF6: addi.w #$800,$36(a0) cmpi.w #$2000,$36(a0) blo.s locret_23B16 move.w #$2000,$36(a0) move.w #1,$38(a0) move.w #60,$3A(a0) locret_23B16: rts ; End of function sub_23AB8 ; --------------------------------------------------------------------------- byte_23B18: dc.b $C, 8, 0, 1 dc.b $C, 8, 0, 0 dc.b $C, 8, 0, 1 dc.b 8, $C, 1, 0 dc.b $C, 8, 2, 1 dc.b $C, 8, 3, 1 dc.b $C, 8, 2, 1 dc.b $C, 8, 3, 1 even ; --------------------------------------------------------------------------- Obj_2PRetractingSpring: jsr (AllocateObjectAfterCurrent).l bne.w loc_23C0E move.l #loc_23ED0,(a1) move.l #Map_2PRetractingSpring,mappings(a1) move.w #make_art_tile($391,0,0),art_tile(a1) cmpi.b #$12,(Current_zone).w bne.s loc_23B66 move.l #Map_2PRetractingSpring_2,mappings(a1) loc_23B66: move.b subtype(a0),d0 move.b d0,subtype(a1) lsr.b #2,d0 andi.w #$1C,d0 lea byte_23B18(pc,d0.w),a2 move.b (a2)+,width_pixels(a1) move.b (a2)+,height_pixels(a1) move.b (a2)+,d0 move.b d0,mapping_frame(a1) bne.s loc_23B8E move.l #loc_23F2A,(a1) loc_23B8E: andi.b #$F0,subtype(a0) move.b (a2)+,d1 or.b d1,subtype(a0) move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) moveq #0,d2 moveq #0,d3 cmpi.b #1,d0 bne.s loc_23BC0 moveq #$C,d2 btst #0,status(a0) bne.s loc_23BBC neg.w d2 loc_23BBC: add.w d2,x_pos(a1) loc_23BC0: cmpi.b #2,d0 bne.s loc_23BCC moveq #$B,d3 add.w d3,y_pos(a1) loc_23BCC: cmpi.b #3,d0 bne.s loc_23BD8 moveq #-$B,d3 add.w d3,y_pos(a1) loc_23BD8: move.w d2,$30(a1) move.w d3,$32(a1) bclr #1,status(a0) beq.s loc_23BEE move.b #1,$3C(a0) loc_23BEE: move.b status(a0),status(a1) move.b render_flags(a0),render_flags(a1) ori.b #4,render_flags(a1) move.w #$200,priority(a1) move.w a0,$3E(a1) move.w a1,$3E(a0) loc_23C0E: bsr.w sub_22D54 loc_23C12: move.b subtype(a0),d0 lsr.w #3,d0 andi.w #$E,d0 move.w off_23C24(pc,d0.w),d1 jmp off_23C24(pc,d1.w) ; --------------------------------------------------------------------------- off_23C24: dc.w loc_23C34-off_23C24 dc.w loc_23C50-off_23C24 dc.w loc_23C6C-off_23C24 dc.w loc_23C88-off_23C24 dc.w loc_23CA4-off_23C24 dc.w loc_23CC0-off_23C24 dc.w loc_23CA4-off_23C24 dc.w loc_23CC0-off_23C24 ; --------------------------------------------------------------------------- loc_23C34: move.l #loc_23C3A,(a0) loc_23C3A: bsr.w sub_23CDC moveq #0,d0 move.b $36(a0),d0 add.w $34(a0),d0 move.w d0,y_pos(a0) bra.w Obj_2PSpring_Up ; --------------------------------------------------------------------------- loc_23C50: move.l #loc_23C56,(a0) loc_23C56: bsr.w sub_23CDC moveq #0,d0 move.b $36(a0),d0 add.w $32(a0),d0 move.w d0,x_pos(a0) bra.w Obj_2PSpring_Horizontal ; --------------------------------------------------------------------------- loc_23C6C: move.l #loc_23C72,(a0) loc_23C72: bsr.w sub_23CDC moveq #0,d0 move.b $36(a0),d0 add.w $34(a0),d0 move.w d0,y_pos(a0) bra.w Obj_2PSpring_Down ; --------------------------------------------------------------------------- loc_23C88: move.l #loc_23C8E,(a0) loc_23C8E: bsr.w sub_23CDC moveq #0,d0 move.b $36(a0),d0 add.w $34(a0),d0 move.w d0,y_pos(a0) bra.w Obj_2PSpring_Horizontal ; --------------------------------------------------------------------------- loc_23CA4: move.l #loc_23CAA,(a0) loc_23CAA: bsr.w sub_23CDC moveq #0,d0 move.b $36(a0),d0 add.w $32(a0),d0 move.w d0,x_pos(a0) bra.w Obj_2PSpring_Up ; --------------------------------------------------------------------------- loc_23CC0: move.l #loc_23CC6,(a0) loc_23CC6: bsr.w sub_23CDC moveq #0,d0 move.b $36(a0),d0 add.w $32(a0),d0 move.w d0,x_pos(a0) bra.w Obj_2PSpring_Down ; =============== S U B R O U T I N E ======================================= sub_23CDC: tst.b subtype(a0) bmi.s loc_23D42 tst.w $3A(a0) beq.s loc_23CFE subq.w #1,$3A(a0) bne.s locret_23D40 tst.b render_flags(a0) bpl.s locret_23D40 moveq #signextendB(sfx_SpikeMove),d0 jsr (Play_SFX).l bra.s locret_23D40 ; --------------------------------------------------------------------------- loc_23CFE: tst.w $38(a0) beq.s loc_23D20 subi.w #$800,$36(a0) bcc.s locret_23D40 move.w #0,$36(a0) move.w #0,$38(a0) move.w #60,$3A(a0) bra.s locret_23D40 ; --------------------------------------------------------------------------- loc_23D20: addi.w #$800,$36(a0) cmpi.w #$1800,$36(a0) blo.s locret_23D40 move.w #$1800,$36(a0) move.w #1,$38(a0) move.w #60,$3A(a0) locret_23D40: rts ; --------------------------------------------------------------------------- loc_23D42: tst.b $3C(a0) beq.w loc_23E0C tst.w $3A(a0) beq.s loc_23D62 subq.w #1,$3A(a0) bne.w locret_23E0A move.w #0,$38(a0) bra.w locret_23E0A ; --------------------------------------------------------------------------- loc_23D62: tst.w $38(a0) bne.w loc_23DF0 tst.w $36(a0) beq.w locret_23E0A subi.w #$800,$36(a0) bhi.w locret_23E0A move.w #0,$36(a0) move.b subtype(a0),d0 andi.b #$F0,d0 cmpi.b #$E0,d0 bne.s loc_23DBC addi.w #$16,y_pos(a0) bchg #1,status(a0) bchg #1,render_flags(a0) andi.b #$F,subtype(a0) ori.b #$F0,subtype(a0) move.l #loc_23C12,(a0) movea.w $3E(a0),a1 neg.w $32(a1) loc_23DBC: cmpi.b #$F0,d0 bne.s loc_23DEE subi.w #$16,y_pos(a0) bchg #1,status(a0) bchg #1,render_flags(a0) andi.b #$F,subtype(a0) ori.b #$E0,subtype(a0) move.l #loc_23C12,(a0) movea.w $3E(a0),a1 neg.w $32(a1) loc_23DEE: bra.s locret_23E0A ; --------------------------------------------------------------------------- loc_23DF0: addi.w #$800,$36(a0) cmpi.w #$1800,$36(a0) blo.s locret_23E0A move.w #$1800,$36(a0) move.w #3*60,$3A(a0) locret_23E0A: rts ; --------------------------------------------------------------------------- loc_23E0C: tst.w $3A(a0) beq.s loc_23E24 subq.w #1,$3A(a0) bne.w locret_23ECE move.w #0,$38(a0) bra.w locret_23ECE ; --------------------------------------------------------------------------- loc_23E24: tst.w $38(a0) beq.s loc_23E44 subi.w #$800,$36(a0) bcc.w locret_23ECE move.w #0,$36(a0) move.w #3*60,$3A(a0) bra.w locret_23ECE ; --------------------------------------------------------------------------- loc_23E44: cmpi.w #$1800,$36(a0) beq.w locret_23ECE addi.w #$800,$36(a0) cmpi.w #$1800,$36(a0) blo.s locret_23ECE move.w #$1800,$36(a0) move.b subtype(a0),d0 andi.b #$F0,d0 cmpi.b #$E0,d0 bne.s loc_23E9C addi.w #$16,y_pos(a0) bchg #1,status(a0) bchg #1,render_flags(a0) andi.b #$F,subtype(a0) ori.b #$F0,subtype(a0) move.l #loc_23C12,(a0) movea.w $3E(a0),a1 neg.w $32(a1) loc_23E9C: cmpi.b #$F0,d0 bne.s locret_23ECE subi.w #$16,y_pos(a0) bchg #1,status(a0) bchg #1,render_flags(a0) andi.b #$F,subtype(a0) ori.b #$E0,subtype(a0) move.l #loc_23C12,(a0) movea.w $3E(a0),a1 neg.w $32(a1) locret_23ECE: rts ; End of function sub_23CDC ; --------------------------------------------------------------------------- loc_23ED0: movea.w $3E(a0),a1 move.w x_pos(a1),d2 move.w y_pos(a1),d3 add.w $30(a0),d2 add.w $32(a0),d3 move.w d2,x_pos(a0) move.w d3,y_pos(a0) move.b subtype(a0),d1 bpl.s loc_23F06 andi.w #$F,d1 lea (Level_trigger_array).w,a3 tst.b (a3,d1.w) beq.s loc_23F06 move.w #1,$38(a1) loc_23F06: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #7,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsr (SolidObjectFull).l jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_23F2A: move.b subtype(a0),d1 bpl.s locret_23F48 andi.w #$F,d1 lea (Level_trigger_array).w,a3 tst.b (a3,d1.w) beq.s locret_23F48 movea.w $3E(a0),a1 move.w #1,$38(a1) locret_23F48: rts ; --------------------------------------------------------------------------- Map_2PRetractingSpring: include "General/Sprites/Level Misc/Map - 2P Retracting Spring.asm" ; --------------------------------------------------------------------------- byte_23F74: dc.b $10, $10 dc.b $20, $10 dc.b $30, $10 dc.b $40, $10 dc.b $10, $10 dc.b $10, $20 dc.b $10, $30 dc.b $10, $40 even ; --------------------------------------------------------------------------- Obj_Spikes: ori.b #4,render_flags(a0) move.w #$200,priority(a0) move.b subtype(a0),d0 andi.w #$F0,d0 lsr.w #3,d0 tst.w (Competition_mode).w bne.w loc_24034 lea byte_23F74(pc,d0.w),a1 move.b (a1)+,width_pixels(a0) move.b (a1)+,height_pixels(a0) move.l #loc_24090,(a0) move.l #Map_Spikes,mappings(a0) move.w #make_art_tile($49C,0,0),art_tile(a0) cmpi.b #4,(Current_zone).w bne.s loc_23FD0 move.w #make_art_tile($200,0,0),art_tile(a0) loc_23FD0: lsr.w #1,d0 move.b d0,mapping_frame(a0) cmpi.b #4,d0 blo.s loc_23FE8 move.l #loc_240E2,(a0) move.w #make_art_tile($494,0,0),art_tile(a0) loc_23FE8: move.b status(a0),d0 tst.b (Reverse_gravity_flag).w beq.s loc_23FF6 eori.b #2,d0 loc_23FF6: andi.b #2,d0 beq.s loc_24002 move.l #loc_2413E,(a0) loc_24002: move.w #$20,$3C(a0) move.w x_pos(a0),$30(a0) move.w y_pos(a0),$32(a0) move.b subtype(a0),d0 andi.b #$F,d0 add.b d0,d0 move.b d0,$2C(a0) rts ; --------------------------------------------------------------------------- byte_24024: dc.b $C, $C dc.b $18, $C dc.b $24, $C dc.b $30, $C dc.b $C, $C dc.b $C, $18 dc.b $C, $24 dc.b $C, $30 ; --------------------------------------------------------------------------- loc_24034: lea byte_24024(pc,d0.w),a1 move.b (a1)+,width_pixels(a0) move.b (a1)+,height_pixels(a0) move.l #loc_2418E,(a0) move.l #Map_2PSpikes,mappings(a0) move.w #make_art_tile($391,0,0),art_tile(a0) lsr.w #1,d0 move.b d0,mapping_frame(a0) cmpi.b #4,d0 blo.s loc_24066 move.l #loc_241DC,(a0) loc_24066: btst #1,status(a0) beq.s loc_24074 move.l #loc_24234,(a0) loc_24074: move.w x_pos(a0),$30(a0) move.w y_pos(a0),$32(a0) move.b subtype(a0),d0 andi.b #$F,d0 add.b d0,d0 move.b d0,subtype(a0) rts ; --------------------------------------------------------------------------- loc_24090: bsr.w sub_242B6 moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull move.b status(a0),d6 andi.b #standing_mask,d6 beq.s loc_240D8 move.b d6,d0 andi.b #p1_standing,d0 beq.s loc_240CA lea (Player_1).w,a1 bsr.w sub_24280 loc_240CA: andi.b #p2_standing,d6 beq.s loc_240D8 lea (Player_2).w,a1 bsr.w sub_24280 loc_240D8: move.w $30(a0),d0 jmp (Sprite_OnScreen_Test2).l ; --------------------------------------------------------------------------- loc_240E2: bsr.w sub_242B6 moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull swap d6 andi.w #1|2,d6 beq.s loc_24134 move.b d6,d0 andi.b #1,d0 beq.s loc_24120 lea (Player_1).w,a1 bsr.w sub_24280 bclr #p1_pushing_bit,status(a0) loc_24120: andi.b #2,d6 beq.s loc_24134 lea (Player_2).w,a1 bsr.w sub_24280 bclr #p2_pushing_bit,status(a0) loc_24134: move.w $30(a0),d0 jmp (Sprite_OnScreen_Test2).l ; --------------------------------------------------------------------------- loc_2413E: bsr.w sub_242B6 moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull swap d6 andi.w #4|8,d6 beq.s loc_24184 move.b d6,d0 andi.b #4,d0 beq.s loc_24176 lea (Player_1).w,a1 bsr.w sub_24280 loc_24176: andi.b #8,d6 beq.s loc_24184 lea (Player_2).w,a1 bsr.w sub_24280 loc_24184: move.w $30(a0),d0 jmp (Sprite_OnScreen_Test2).l ; --------------------------------------------------------------------------- loc_2418E: bsr.w sub_243BA moveq #0,d1 move.b width_pixels(a0),d1 addi.w #7,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull move.b status(a0),d6 andi.b #standing_mask,d6 beq.s loc_241D6 move.b d6,d0 andi.b #p1_standing,d0 beq.s loc_241C8 lea (Player_1).w,a1 bsr.w sub_24280 loc_241C8: andi.b #p2_standing,d6 beq.s loc_241D6 lea (Player_2).w,a1 bsr.w sub_24280 loc_241D6: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_241DC: bsr.w sub_243BA moveq #0,d1 move.b width_pixels(a0),d1 addi.w #7,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull swap d6 andi.w #1|2,d6 beq.s loc_2422E move.b d6,d0 andi.b #1,d0 beq.s loc_2421A lea (Player_1).w,a1 bsr.w sub_24280 bclr #p1_pushing_bit,status(a0) loc_2421A: andi.b #2,d6 beq.s loc_2422E lea (Player_2).w,a1 bsr.w sub_24280 bclr #p2_pushing_bit,status(a0) loc_2422E: jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_24234: bsr.w sub_243BA moveq #0,d1 move.b width_pixels(a0),d1 addi.w #7,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 bsr.w SolidObjectFull swap d6 andi.w #4|8,d6 beq.s loc_2427A move.b d6,d0 andi.b #4,d0 beq.s loc_2426C lea (Player_1).w,a1 bsr.w sub_24280 loc_2426C: andi.b #8,d6 beq.s loc_2427A lea (Player_2).w,a1 bsr.w sub_24280 loc_2427A: jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_24280: btst #Status_Invincible,status_secondary(a1) bne.s locret_242B4 tst.b invulnerability_timer(a1) bne.s locret_242B4 cmpi.b #4,routine(a1) bhs.s locret_242B4 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 locret_242B4: rts ; End of function sub_24280 ; =============== S U B R O U T I N E ======================================= sub_242B6: moveq #0,d0 move.b subtype(a0),d0 move.w off_242C4(pc,d0.w),d1 jmp off_242C4(pc,d1.w) ; End of function sub_242B6 ; --------------------------------------------------------------------------- off_242C4: dc.w locret_242CC-off_242C4 dc.w loc_242CE-off_242C4 dc.w loc_242E2-off_242C4 dc.w loc_24356-off_242C4 ; --------------------------------------------------------------------------- locret_242CC: rts ; --------------------------------------------------------------------------- loc_242CE: bsr.w sub_242F6 moveq #0,d0 move.b $34(a0),d0 add.w $32(a0),d0 move.w d0,y_pos(a0) rts ; --------------------------------------------------------------------------- loc_242E2: bsr.w sub_242F6 moveq #0,d0 move.b $34(a0),d0 add.w $30(a0),d0 move.w d0,x_pos(a0) rts ; =============== S U B R O U T I N E ======================================= sub_242F6: tst.w $38(a0) beq.s loc_24312 subq.w #1,$38(a0) bne.s locret_24354 tst.b render_flags(a0) bpl.s locret_24354 moveq #signextendB(sfx_SpikeMove),d0 jsr (Play_SFX).l bra.s locret_24354 ; --------------------------------------------------------------------------- loc_24312: tst.w $36(a0) beq.s loc_24334 subi.w #$800,$34(a0) bcc.s locret_24354 move.w #0,$34(a0) move.w #0,$36(a0) move.w #60,$38(a0) bra.s locret_24354 ; --------------------------------------------------------------------------- loc_24334: addi.w #$800,$34(a0) cmpi.w #$2000,$34(a0) blo.s locret_24354 move.w #$2000,$34(a0) move.w #1,$36(a0) move.w #60,$38(a0) locret_24354: rts ; End of function sub_242F6 ; --------------------------------------------------------------------------- loc_24356: move.b status(a0),d3 andi.b #pushing_mask,d3 beq.s loc_2437C move.w x_pos(a0),d2 lea (Player_1).w,a1 move.b $3E(a0),d0 moveq #5,d6 bsr.s sub_2438A lea (Player_2).w,a1 move.b $3F(a0),d0 moveq #6,d6 bsr.s sub_2438A loc_2437C: move.b (Player_1+status).w,$3E(a0) move.b (Player_2+status).w,$3F(a0) rts ; =============== S U B R O U T I N E ======================================= sub_2438A: btst d6,d3 beq.s locret_243B8 cmp.w x_pos(a1),d2 blo.s locret_243B8 btst #5,d0 beq.s locret_243B8 subq.w #1,$3A(a0) bpl.s locret_243B8 move.w #$10,$3A(a0) tst.w $3C(a0) beq.s locret_243B8 subq.w #1,$3C(a0) addq.w #1,x_pos(a0) addq.w #1,x_pos(a1) locret_243B8: rts ; End of function sub_2438A ; =============== S U B R O U T I N E ======================================= sub_243BA: moveq #0,d0 move.b subtype(a0),d0 move.w word_243C8(pc,d0.w),d1 jmp word_243C8(pc,d1.w) ; End of function sub_243BA ; --------------------------------------------------------------------------- word_243C8: dc.w locret_242CC-word_243C8 dc.w loc_243CE-word_243C8 dc.w loc_243E2-word_243C8 ; --------------------------------------------------------------------------- loc_243CE: bsr.w sub_243F6 moveq #0,d0 move.b $34(a0),d0 add.w $32(a0),d0 move.w d0,y_pos(a0) rts ; --------------------------------------------------------------------------- loc_243E2: bsr.w sub_243F6 moveq #0,d0 move.b $34(a0),d0 add.w $30(a0),d0 move.w d0,x_pos(a0) rts ; =============== S U B R O U T I N E ======================================= sub_243F6: tst.w $38(a0) beq.s loc_24412 subq.w #1,$38(a0) bne.s locret_24454 tst.b render_flags(a0) bpl.s locret_24454 moveq #signextendB(sfx_SpikeMove),d0 jsr (Play_SFX).l bra.s locret_24454 ; --------------------------------------------------------------------------- loc_24412: tst.w $36(a0) beq.s loc_24434 subi.w #$800,$34(a0) bcc.s locret_24454 move.w #0,$34(a0) move.w #0,$36(a0) move.w #60,$38(a0) bra.s locret_24454 ; --------------------------------------------------------------------------- loc_24434: addi.w #$800,$34(a0) cmpi.w #$1800,$34(a0) blo.s locret_24454 move.w #$1800,$34(a0) move.w #1,$36(a0) move.w #60,$38(a0) locret_24454: rts ; End of function sub_243F6 ; --------------------------------------------------------------------------- Map_Spikes: include "General/Sprites/Level Misc/Map - Spikes.asm" Map_2PSpikes: include "General/2P Zone/Map - Spikes.asm" ; =============== S U B R O U T I N E ======================================= Init_ArtScaling: moveq #0,d1 move.w d1,(_unkF740).w movea.w d1,a0 movea.w d1,a1 movea.w d1,a2 movea.w d1,a3 movea.w d1,a4 movea.w d1,a5 lea (H_scroll_buffer).w,a6 move.w #($1000/$100)-1,d1 .loop: rept 10 movem.l a0-a5,-(a6) endm movem.l a0-a3,-(a6) dbf d1,.loop rts ; End of function Init_ArtScaling ; --------------------------------------------------------------------------- word_2464A: dc.w $100 dc.w $FC dc.w $90 dc.w $90 dc.w $40 dc.w $40 dc.w $40 dc.w $3C dc.w $3C dc.w $3C dc.w $3C dc.w $3C dc.w $10 dc.w $10 dc.w $10 dc.w $10 dc.w $10 dc.w $10 dc.w $10 dc.w $10 dc.w $10 dc.w $10 dc.w $10 dc.w $10 dc.w $10 dc.w $10 dc.w $10 dc.w $10 dc.w $C dc.w $C dc.w $C dc.w $C ; =============== S U B R O U T I N E ======================================= sub_2468A: moveq #0,d1 move.b $40(a0),d1 cmpi.b #$1C,d1 blo.s loc_2469A move.b #$1C,d1 ; Maximum 28 different "scales" loc_2469A: move.b d1,mapping_frame(a0) ; Scale level correlates with mapping frame add.w d1,d1 move.w word_2464A(pc,d1.w),d1 move.w (_unkF740).w,d2 add.w d1,d2 cmpi.w #$80,d2 bhi.s loc_246D2 sub.w d1,d2 movem.l d1/d5-a0/a2/a4,-(sp) lea (Kos_decomp_buffer).w,a2 add.w d2,d0 move.w d0,art_tile(a0) lsl.w #5,d2 adda.w d2,a2 bsr.s sub_246DA movem.l (sp)+,d1/d5-a0/a2/a4 add.w d1,(_unkF740).w rts ; --------------------------------------------------------------------------- rts ; --------------------------------------------------------------------------- loc_246D2: bclr #7,render_flags(a0) rts ; End of function sub_2468A ; =============== S U B R O U T I N E ======================================= sub_246DA: moveq #0,d0 move.b $40(a0),d0 ; Scale factor moveq #0,d1 move.b anim(a0),d1 movea.l $42(a0),a1 ; Scaled art address ror.w #4,d1 adda.l d1,a1 movea.l a1,a0 adda.w #$1000,a0 addi.w #4,d0 move.w d0,d4 lsr.w #3,d4 move.w d0,d5 ror.w #3,d5 andi.w #$E000,d5 move.w #$F0,d6 swap d6 move.w #$F,d7 swap d7 tst.w d4 beq.w loc_249BA ; If modified scale factor smaller than 8, branch cmpi.w #1,d4 bne.s loc_2472A ; If modified scale factor is not between 8-$10, branch tst.w d5 beq.w loc_2493E ; If modified scale factor is 8, branch cmpi.w #$2000,d5 beq.w loc_248B8 ; If modified scale factor is 9, branch loc_2472A: move.w d4,d2 ; All other instances. Scale factor/8 to d2 swap d2 move.w d5,d2 lsr.l #8,d2 ; Combine with other scale factor to create final result: Scale factor << 5 move.l #$400000,d0 divu.w d2,d0 lsr.w #8,d0 lsr.w #3,d0 subq.w #1,d0 ; Divide 400000 by modified scale factor << 5, subtract 1 movea.w d0,a5 ; Note the result in a5 moveq #0,d2 moveq #0,d3 lea loc_2479C(pc),a6 loc_2474A: move.w #$20-1,d7 loc_2474E: swap d7 swap d3 move.w #0,d2 move.w #0,d3 movea.l a2,a4 move.w a5,d6 bmi.s loc_24770 loc_24760: swap d6 jsr (a6) swap d6 dbf d6,loc_24760 cmpi.w #$40,d2 bhs.s loc_24778 loc_24770: swap d6 jsr sub_24802(pc) swap d6 loc_24778: swap d3 add.w d5,d3 bcc.s loc_24782 adda.w #$40,a1 loc_24782: move.w d4,d0 lsl.w #6,d0 adda.w d0,a1 cmpa.l a0,a1 bhs.s locret_2479A addq.w #4,a2 swap d7 dbf d7,loc_2474E lea $380(a2),a2 bra.s loc_2474A ; --------------------------------------------------------------------------- locret_2479A: rts ; --------------------------------------------------------------------------- loc_2479C: rept 4 move.b (a1,d2.w),d0 add.w d5,d3 addx.w d4,d2 move.b (a1,d2.w),d1 add.w d5,d3 addx.w d4,d2 and.b d6,d0 and.b d7,d1 or.b d1,d0 move.b d0,(a4)+ endm lea $7C(a4),a4 rts ; =============== S U B R O U T I N E ======================================= sub_24802: rept 4 move.b (a1,d2.w),d0 add.w d5,d3 addx.w d4,d2 cmpi.w #$40,d2 blo.s loc_24814 move.b #0,d0 loc_24814: move.b (a1,d2.w),d1 add.w d5,d3 addx.w d4,d2 cmpi.w #$40,d2 blo.s loc_24826 move.b #0,d1 loc_24826: and.b d6,d0 and.b d7,d1 or.b d1,d0 move.b d0,(a4)+ endm lea $7C(a4),a4 rts ; End of function sub_24802 ; --------------------------------------------------------------------------- loc_248B8: moveq #0,d3 lsl.w #6,d4 lea loc_24906(pc),a6 move.w #2-1,d7 loc_248C4: swap d7 move.w #$20-1,d6 loc_248CA: swap d6 movea.l a1,a3 movea.l a2,a4 rept 7 jsr (a6) endm move.b (a3)+,d0 and.b d6,d0 move.b d0,(a4)+ add.w d5,d3 bcc.s loc_248EC lea $40(a1),a1 loc_248EC: adda.w d4,a1 cmpa.l a0,a1 bhs.s locret_24904 addq.w #4,a2 swap d6 dbf d6,loc_248CA lea $380(a2),a2 swap d7 dbf d7,loc_248C4 locret_24904: rts ; --------------------------------------------------------------------------- loc_24906: rept 3 move.b (a3)+,d0 move.b (a3)+,d1 and.b d6,d0 and.b d7,d1 or.b d1,d0 move.b d0,(a4)+ endm move.b (a3)+,d0 move.b (a3)+,d1 addq.w #1,a3 and.b d6,d0 and.b d7,d1 or.b d1,d0 move.b d0,(a4)+ lea $7C(a4),a4 rts ; --------------------------------------------------------------------------- loc_2493E: moveq #0,d3 lsl.w #6,d4 lea loc_24984(pc),a6 move.w #2-1,d7 loc_2494A: swap d7 move.w #$20-1,d6 loc_24950: swap d6 movea.l a1,a3 movea.l a2,a4 rept 8 jsr (a6) endm add.w d5,d3 bcc.s loc_2496E lea $40(a1),a1 loc_2496E: adda.w d4,a1 addq.w #4,a2 swap d6 dbf d6,loc_24950 lea $380(a2),a2 swap d7 dbf d7,loc_2494A rts ; --------------------------------------------------------------------------- loc_24984: rept 4 move.b (a3)+,d0 move.b (a3)+,d1 and.b d6,d0 and.b d7,d1 or.b d1,d0 move.b d0,(a4)+ endm lea $7C(a4),a4 rts ; --------------------------------------------------------------------------- loc_249BA: cmpi.w #$E000,d5 bne.w loc_24A3C lea loc_24A10(pc),a6 moveq #0,d3 lsl.w #6,d4 move.w #3-1,d7 loc_249CE: swap d7 move.w #$20-1,d6 loc_249D4: swap d6 movea.l a1,a3 movea.l a2,a4 rept 9 jsr (a6) endm move.b (a3),(a4) add.w d5,d3 bcc.s loc_249F6 lea $40(a1),a1 loc_249F6: adda.w d4,a1 cmpa.l a0,a1 bhs.s locret_24A0E addq.w #4,a2 swap d6 dbf d6,loc_249D4 lea $580(a2),a2 swap d7 dbf d7,loc_249CE locret_24A0E: rts ; --------------------------------------------------------------------------- loc_24A10: move.b (a3)+,(a4)+ rept 3 move.b (a3)+,d0 move.b (a3)+,d1 and.b d6,d0 and.b d7,d1 or.b d1,d0 move.b d0,(a4)+ endm lea $7C(a4),a4 rts ; --------------------------------------------------------------------------- loc_24A3C: cmpi.w #$C000,d5 bne.w loc_24AC6 moveq #0,d3 lsl.w #6,d4 lea loc_24AA4(pc),a6 move.w #4-1,d7 loc_24A50: swap d7 move.w #$20-1,d6 loc_24A56: swap d6 movea.l a1,a3 movea.l a2,a4 rept 10 jsr (a6) endm move.b (a3)+,(a4)+ move.b (a3)+,d0 move.b (a3)+,d1 and.b d6,d0 and.b d7,d1 or.b d1,d0 move.b d0,(a4)+ move.b (a3),d0 move.b d0,(a4) add.w d5,d3 bcc.s loc_24A8A lea $40(a1),a1 loc_24A8A: adda.w d4,a1 cmpa.l a0,a1 bhs.s locret_24AA2 addq.w #4,a2 swap d6 dbf d6,loc_24A56 lea $580(a2),a2 swap d7 dbf d7,loc_24A50 locret_24AA2: rts ; --------------------------------------------------------------------------- loc_24AA4: rept 2 move.b (a3)+,(a4)+ move.b (a3)+,d0 move.b (a3)+,d1 and.b d6,d0 and.b d7,d1 or.b d1,d0 move.b d0,(a4)+ endm lea $7C(a4),a4 rts ; --------------------------------------------------------------------------- loc_24AC6: cmpi.w #$A000,d5 bne.w loc_24B60 moveq #0,d3 lsl.w #6,d4 lea loc_24B4A(pc),a5 lea loc_24B32(pc),a6 move.w #4-1,d7 loc_24ADE: swap d7 move.w #$20-1,d6 loc_24AE4: swap d6 movea.l a1,a3 movea.l a2,a4 rept 6 jsr (a5) jsr (a6) endm move.w (a3)+,(a4)+ move.b (a3)+,d0 move.b (a3)+,d1 and.b d6,d0 and.b d7,d1 or.b d1,d0 move.b d0,(a4)+ add.w d5,d3 bcc.s loc_24B18 lea $40(a1),a1 loc_24B18: adda.w d4,a1 cmpa.l a0,a1 bhs.s locret_24B30 addq.w #4,a2 swap d6 dbf d6,loc_24AE4 lea $780(a2),a2 swap d7 dbf d7,loc_24ADE locret_24B30: rts ; --------------------------------------------------------------------------- loc_24B32: move.b (a3)+,(a4)+ move.b (a3)+,(a4)+ move.b (a3)+,d0 move.b (a3)+,d1 and.b d6,d0 and.b d7,d1 or.b d1,d0 move.b d0,(a4)+ move.b (a3)+,(a4)+ lea $7C(a4),a4 rts ; --------------------------------------------------------------------------- loc_24B4A: move.w (a3)+,(a4)+ move.b (a3)+,d0 move.b (a3)+,d1 and.b d6,d0 and.b d7,d1 or.b d1,d0 move.b d0,(a4)+ move.b (a3)+,(a4)+ lea $7C(a4),a4 rts ; --------------------------------------------------------------------------- loc_24B60: moveq #0,d3 lsl.w #6,d4 moveq #4-1,d7 loc_24B66: move.w #$20-1,d6 loc_24B6A: movea.l a1,a3 movea.l a2,a4 rept 16 move.l (a3)+,(a4) lea $80(a4),a4 endm add.w d5,d3 bcc.s loc_24BD6 lea $40(a1),a1 loc_24BD6: adda.w d4,a1 addq.w #4,a2 dbf d6,loc_24B6A lea $780(a2),a2 dbf d7,loc_24B66 rts ; --------------------------------------------------------------------------- Map_ScaledArt: include "General/Sprites/Level Misc/Map - Scaled Art.asm" ; --------------------------------------------------------------------------- Obj_TwistedRamp: lea (Player_1).w,a1 bsr.s sub_24D9A lea (Player_2).w,a1 bsr.s sub_24D9A move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.s loc_24D88 rts ; --------------------------------------------------------------------------- loc_24D88: move.w respawn_addr(a0),d0 beq.s loc_24D94 movea.w d0,a2 bclr #7,(a2) loc_24D94: jmp (Delete_Current_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_24D9A: btst #Status_InAir,status(a1) bne.w locret_24E32 move.w x_pos(a1),d0 addi.w #$10,d0 sub.w x_pos(a0),d0 bcs.w locret_24E32 cmpi.w #$20,d0 bge.w locret_24E32 move.w y_pos(a1),d0 sub.w y_pos(a0),d0 cmpi.w #-$14,d0 blt.s locret_24E32 cmpi.w #$20,d0 bgt.s locret_24E32 tst.b object_control(a1) bne.s locret_24E32 btst #0,status(a0) bne.s loc_24DEE cmpi.w #$400,x_vel(a1) blt.s locret_24E32 addi.w #$400,x_vel(a1) bra.s loc_24DFC ; --------------------------------------------------------------------------- loc_24DEE: cmpi.w #-$400,x_vel(a1) bgt.s locret_24E32 subi.w #$400,x_vel(a1) loc_24DFC: move.w #-$700,y_vel(a1) bset #Status_InAir,status(a1) move.b #2,routine(a1) move.w #1,ground_vel(a1) move.b #1,flip_angle(a1) move.b #0,anim(a1) move.b #0,flips_remaining(a1) move.b #4,flip_speed(a1) move.b #5,flip_type(a1) locret_24E32: rts ; End of function sub_24D9A ; --------------------------------------------------------------------------- byte_24E34: dc.b $20, 8, 0 even dc.b $20, 8, 1 even ; --------------------------------------------------------------------------- Obj_LBZMovingPlatform: move.l #Map_LBZMovingPlatform,mappings(a0) move.w #make_art_tile($3C3,2,0),art_tile(a0) move.b #4,render_flags(a0) move.w #$180,priority(a0) moveq #0,d0 move.b subtype(a0),d0 bpl.s loc_24E6E andi.w #$7F,d0 lsl.w #4,d0 move.w d0,$38(a0) moveq #$17,d0 move.b d0,subtype(a0) loc_24E6E: lsr.w #2,d0 andi.w #$1C,d0 lea byte_24E34(pc,d0.w),a2 move.b (a2)+,width_pixels(a0) move.b (a2)+,height_pixels(a0) move.b (a2)+,mapping_frame(a0) move.w x_pos(a0),$30(a0) move.w x_pos(a0),$32(a0) move.w y_pos(a0),$34(a0) move.b status(a0),$2E(a0) move.w #$280,$42(a0) move.w x_pos(a0),$44(a0) moveq #0,d0 move.b subtype(a0),d0 andi.w #$F,d0 subq.w #8,d0 bcs.s loc_24EDE cmpi.w #4,d0 bhs.s loc_24ED2 lsl.w #2,d0 lea (Oscillating_table+$2C).w,a2 lea (a2,d0.w),a2 tst.w (a2) bpl.s loc_24EDE bchg #0,$2E(a0) bra.s loc_24EDE ; --------------------------------------------------------------------------- loc_24ED2: move.w #$380,$42(a0) addi.w #$100,$44(a0) loc_24EDE: move.b subtype(a0),d0 andi.b #$F,d0 add.b d0,d0 move.b d0,subtype(a0) move.l #loc_24EF2,(a0) loc_24EF2: move.w x_pos(a0),-(sp) moveq #0,d0 move.b subtype(a0),d0 move.w LBZMovingPlatformIndex(pc,d0.w),d1 jsr LBZMovingPlatformIndex(pc,d1.w) move.w (sp)+,d4 tst.b render_flags(a0) bpl.s loc_24F1C moveq #0,d1 move.b width_pixels(a0),d1 move.w #9,d3 jsr (SolidObjectTop).l loc_24F1C: move.w $44(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmp.w $42(a0),d0 bhi.w loc_24F36 jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_24F36: tst.b $3D(a0) beq.s loc_24F46 movea.w $3E(a0),a1 jsr (Delete_Referenced_Sprite).l loc_24F46: move.w respawn_addr(a0),d0 beq.s loc_24F52 movea.w d0,a2 bclr #7,(a2) loc_24F52: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- LBZMovingPlatformIndex: dc.w Platform_Stationary-LBZMovingPlatformIndex dc.w Platform_Horizontal64-LBZMovingPlatformIndex dc.w Platform_Horizontal128-LBZMovingPlatformIndex dc.w Platform_Vertical64-LBZMovingPlatformIndex dc.w Platform_Vertical128-LBZMovingPlatformIndex dc.w Platform_DiagonalUp-LBZMovingPlatformIndex dc.w Platform_DiagonalDown-LBZMovingPlatformIndex dc.w Platform_DiagonalLift-LBZMovingPlatformIndex dc.w Platform_Square32-LBZMovingPlatformIndex dc.w Platform_Square96-LBZMovingPlatformIndex dc.w Platform_Square160-LBZMovingPlatformIndex dc.w Platform_Square224-LBZMovingPlatformIndex dc.w Platform_Horizontal256-LBZMovingPlatformIndex dc.w Platform_FallingDelayed-LBZMovingPlatformIndex dc.w Platform_Falling-LBZMovingPlatformIndex FloatingPlatformIndex: dc.w Platform_Stationary-FloatingPlatformIndex dc.w Platform_Horizontal64-FloatingPlatformIndex dc.w Platform_Horizontal128-FloatingPlatformIndex dc.w Platform_Vertical64-FloatingPlatformIndex dc.w Platform_Vertical128-FloatingPlatformIndex dc.w Platform_DiagonalUp-FloatingPlatformIndex dc.w Platform_DiagonalDown-FloatingPlatformIndex dc.w Platform_Rising-FloatingPlatformIndex dc.w Platform_Square32-FloatingPlatformIndex dc.w Platform_Square96-FloatingPlatformIndex dc.w Platform_Square160-FloatingPlatformIndex dc.w Platform_Square224-FloatingPlatformIndex dc.w Platform_Horizontal256-FloatingPlatformIndex ; --------------------------------------------------------------------------- Platform_Stationary: move.b status(a0),d0 andi.b #standing_mask,d0 bne.s loc_24FA6 tst.b $3A(a0) beq.s loc_24FB2 subq.b #4,$3A(a0) bra.s loc_24FB2 ; --------------------------------------------------------------------------- loc_24FA6: cmpi.b #$40,$3A(a0) beq.s loc_24FB2 addq.b #4,$3A(a0) loc_24FB2: move.b $3A(a0),d0 jsr (GetSineCosine).l asr.w #6,d0 add.w $34(a0),d0 move.w d0,y_pos(a0) rts ; --------------------------------------------------------------------------- Platform_Horizontal64: move.w #64,d1 moveq #0,d0 move.b (Oscillating_table+$0A).w,d0 bra.s sub_24FDE ; --------------------------------------------------------------------------- Platform_Horizontal128: move.w #128,d1 moveq #0,d0 move.b (Oscillating_table+$1E).w,d0 ; =============== S U B R O U T I N E ======================================= sub_24FDE: btst #0,status(a0) beq.s loc_24FEA neg.w d0 add.w d1,d0 loc_24FEA: move.w $30(a0),d1 add.w d0,d1 move.w d1,x_pos(a0) rts ; End of function sub_24FDE ; --------------------------------------------------------------------------- Platform_Vertical64: move.w #64,d1 moveq #0,d0 move.b (Oscillating_table+$0A).w,d0 bra.s loc_2500C ; --------------------------------------------------------------------------- Platform_Vertical128: move.w #128,d1 moveq #0,d0 move.b (Oscillating_table+$1E).w,d0 loc_2500C: btst #0,status(a0) beq.s loc_25018 neg.w d0 add.w d1,d0 loc_25018: move.w $34(a0),d1 sub.w d0,d1 move.w d1,y_pos(a0) rts ; --------------------------------------------------------------------------- Platform_DiagonalUp: move.w #128,d1 moveq #0,d0 move.b (Oscillating_table+$1E).w,d0 bsr.s sub_24FDE move.w #64,d1 moveq #0,d0 move.b (Oscillating_table+$1E).w,d0 lsr.b #1,d0 bra.s loc_2500C ; --------------------------------------------------------------------------- Platform_DiagonalDown: move.w #128,d1 moveq #0,d0 move.b (Oscillating_table+$1E).w,d0 neg.w d0 add.w d1,d0 bsr.s sub_24FDE move.w #64,d1 moveq #0,d0 move.b (Oscillating_table+$1E).w,d0 lsr.b #1,d0 bra.s loc_2500C ; --------------------------------------------------------------------------- Platform_DiagonalLift: move.b status(a0),d0 andi.b #standing_mask,d0 bne.s loc_2507C move.w $38(a0),d2 move.w $36(a0),d1 beq.s locret_250AA subq.w #4,d1 bcc.s loc_25076 moveq #0,d1 loc_25076: move.w d1,$36(a0) bra.s loc_25090 ; --------------------------------------------------------------------------- loc_2507C: move.w $38(a0),d2 move.w $36(a0),d1 addq.w #2,d1 cmp.w d2,d1 blo.s loc_2508C move.w d2,d1 loc_2508C: move.w d1,$36(a0) loc_25090: move.w $32(a0),d0 sub.w d1,d0 move.w d0,x_pos(a0) move.w d0,$30(a0) lsr.w #1,d1 move.w $34(a0),d0 sub.w d1,d0 move.w d0,y_pos(a0) locret_250AA: rts ; --------------------------------------------------------------------------- Platform_Horizontal256: move.w #$7F,d2 tst.b $3C(a0) bne.s loc_250D2 move.w $40(a0),d1 addq.w #4,d1 move.w d1,$40(a0) add.w d1,$36(a0) cmp.b $36(a0),d2 bhi.s loc_250EC move.b #1,$3C(a0) bra.s loc_250EC ; --------------------------------------------------------------------------- loc_250D2: move.w $40(a0),d1 subq.w #4,d1 move.w d1,$40(a0) add.w d1,$36(a0) cmp.b $36(a0),d2 bls.s loc_250EC move.b #0,$3C(a0) loc_250EC: moveq #0,d0 move.b $36(a0),d0 btst #0,status(a0) beq.s loc_250FE neg.w d0 add.w d2,d0 loc_250FE: add.w $30(a0),d0 move.w d0,x_pos(a0) rts ; --------------------------------------------------------------------------- Platform_FallingDelayed: tst.w $3A(a0) bne.s loc_25120 move.b status(a0),d0 andi.b #$18,d0 beq.s locret_2511E move.w #30,$3A(a0) locret_2511E: rts ; --------------------------------------------------------------------------- loc_25120: subq.w #1,$3A(a0) bne.s locret_2511E move.w #32,$3A(a0) addq.b #2,subtype(a0) rts ; --------------------------------------------------------------------------- Platform_Falling: tst.w $3A(a0) beq.s loc_25160 subq.w #1,$3A(a0) bne.s loc_25160 bclr #p1_standing_bit,status(a0) beq.s loc_2514C lea (Player_1).w,a1 bsr.s sub_25194 loc_2514C: bclr #p2_standing_bit,status(a0) beq.s loc_2515A lea (Player_2).w,a1 bsr.s sub_25194 loc_2515A: move.l #Obj_FallingPlatformIntangible,(a0) loc_25160: 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 #$38,y_vel(a0) move.w (Camera_max_Y_pos).w,d0 addi.w #$120,d0 cmp.w y_pos(a0),d0 bhs.s locret_25192 move.w #$7F00,x_pos(a0) move.w #$7F00,$44(a0) locret_25192: rts ; =============== S U B R O U T I N E ======================================= sub_25194: bset #Status_InAir,status(a1) bclr #Status_OnObj,status(a1) move.b #2,routine(a1) move.w y_vel(a0),y_vel(a1) rts ; End of function sub_25194 ; --------------------------------------------------------------------------- Obj_FallingPlatformIntangible: 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 #$38,y_vel(a0) move.w (Camera_max_Y_pos).w,d0 addi.w #$120,d0 cmp.w y_pos(a0),d0 bhs.s loc_251E0 move.w #$7F00,x_pos(a0) move.w #$7F00,$44(a0) loc_251E0: bra.w loc_24F1C ; --------------------------------------------------------------------------- Platform_Rising: tst.b $3C(a0) bne.s loc_25202 move.b status(a0),d0 andi.b #standing_mask,d0 beq.s locret_25200 move.b #1,$3C(a0) move.b #$C,$1E(a0) locret_25200: rts ; --------------------------------------------------------------------------- loc_25202: jsr (MoveSprite2).l moveq #8,d1 move.w $34(a0),d0 subi.w #$80,d0 cmp.w y_pos(a0),d0 bhs.s loc_2521E neg.w d1 add.w d1,y_vel(a0) loc_2521E: jsr (ObjCheckCeilingDist).l tst.w d1 bpl.s loc_25236 sub.w d1,y_pos(a0) clr.b $3C(a0) clr.w y_vel(a0) rts ; --------------------------------------------------------------------------- loc_25236: btst #p1_standing_bit,status(a0) beq.s loc_25256 move.l a0,-(sp) lea (Player_1).w,a0 jsr (sub_F846).l tst.w d1 bpl.s loc_25254 jsr (Kill_Character).l loc_25254: movea.l (sp)+,a0 loc_25256: btst #p2_standing_bit,status(a0) beq.s locret_25276 move.l a0,-(sp) lea (Player_2).w,a0 jsr (sub_F846).l tst.w d1 bpl.s loc_25274 jsr (Kill_Character).l loc_25274: movea.l (sp)+,a0 locret_25276: rts ; --------------------------------------------------------------------------- Platform_Square32: move.w #32/2,d1 moveq #0,d0 move.b (Oscillating_table+$2A).w,d0 lsr.w #1,d0 move.w (Oscillating_table+$2C).w,d3 bra.s loc_252B8 ; --------------------------------------------------------------------------- Platform_Square96: move.w #96/2,d1 moveq #0,d0 move.b (Oscillating_table+$2E).w,d0 move.w (Oscillating_table+$30).w,d3 bra.s loc_252B8 ; --------------------------------------------------------------------------- Platform_Square160: move.w #160/2,d1 moveq #0,d0 move.b (Oscillating_table+$32).w,d0 move.w (Oscillating_table+$34).w,d3 bra.s loc_252B8 ; --------------------------------------------------------------------------- Platform_Square224: move.w #224/2,d1 moveq #0,d0 move.b (Oscillating_table+$36).w,d0 move.w (Oscillating_table+$38).w,d3 loc_252B8: tst.w d3 bne.s loc_252C6 addq.b #1,$2E(a0) andi.b #3,$2E(a0) loc_252C6: move.b $2E(a0),d2 andi.b #3,d2 bne.s loc_252E6 sub.w d1,d0 add.w $30(a0),d0 move.w d0,x_pos(a0) neg.w d1 add.w $34(a0),d1 move.w d1,y_pos(a0) rts ; --------------------------------------------------------------------------- loc_252E6: subq.b #1,d2 bne.s loc_25304 subq.w #1,d1 sub.w d1,d0 neg.w d0 add.w $34(a0),d0 move.w d0,y_pos(a0) addq.w #1,d1 add.w $30(a0),d1 move.w d1,x_pos(a0) rts ; --------------------------------------------------------------------------- loc_25304: subq.b #1,d2 bne.s loc_25322 subq.w #1,d1 sub.w d1,d0 neg.w d0 add.w $30(a0),d0 move.w d0,x_pos(a0) addq.w #1,d1 add.w $34(a0),d1 move.w d1,y_pos(a0) rts ; --------------------------------------------------------------------------- loc_25322: sub.w d1,d0 add.w $34(a0),d0 move.w d0,y_pos(a0) neg.w d1 add.w $30(a0),d1 move.w d1,x_pos(a0) rts ; --------------------------------------------------------------------------- Map_LBZMovingPlatform: include "Levels/LBZ/Misc Object Data/Map - Moving Platform.asm" ; --------------------------------------------------------------------------- Obj_LBZUnusedBarPlatform: jsr (AllocateObjectAfterCurrent).l bne.w loc_253BE move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b status(a0),status(a1) move.l #Map_LBZUnusedBarPlatform,mappings(a1) move.w #make_art_tile($2EA,2,0),art_tile(a1) move.b #4,render_flags(a1) move.w #$180,priority(a1) move.b #$20,width_pixels(a1) move.b #$10,height_pixels(a1) move.w a0,$3E(a1) move.l #loc_253C2,(a1) move.w a1,$3E(a0) move.b #1,$3D(a0) loc_253BE: bra.w Obj_LBZMovingPlatform ; --------------------------------------------------------------------------- loc_253C2: move.w x_pos(a0),d4 movea.w $3E(a0),a1 move.w x_pos(a1),x_pos(a0) move.w y_pos(a1),y_pos(a0) sub.w x_pos(a1),d4 bsr.s sub_253E2 jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_253E2: lea $33(a0),a2 lea (Player_2).w,a1 move.w (Ctrl_2).w,d0 bsr.s sub_253FA lea (Player_1).w,a1 subq.w #1,a2 move.w (Ctrl_1).w,d0 ; End of function sub_253E2 ; =============== S U B R O U T I N E ======================================= sub_253FA: tst.b (a2) beq.w loc_25476 tst.b render_flags(a1) bpl.s loc_25456 cmpi.b #4,routine(a1) bhs.s loc_25456 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 beq.w loc_25464 clr.b object_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 loc_25430 move.b #$3C,2(a2) loc_25430: btst #button_left+8,d0 beq.s loc_2543C move.w #-$200,x_vel(a1) loc_2543C: btst #button_right+8,d0 beq.s loc_25448 move.w #$200,x_vel(a1) loc_25448: move.w #-$380,y_vel(a1) bset #1,status(a1) rts ; --------------------------------------------------------------------------- loc_25456: clr.b object_control(a1) clr.b (a2) move.b #$3C,2(a2) rts ; --------------------------------------------------------------------------- loc_25464: sub.w d4,x_pos(a1) move.w y_pos(a0),y_pos(a1) addi.w #$24,y_pos(a1) rts ; --------------------------------------------------------------------------- loc_25476: tst.b 2(a2) beq.s loc_25484 subq.b #1,2(a2) bne.w locret_254E8 loc_25484: move.w x_pos(a1),d0 sub.w x_pos(a0),d0 addi.w #$1C,d0 cmpi.w #$38,d0 bhs.w locret_254E8 move.w y_pos(a1),d1 sub.w y_pos(a0),d1 subi.w #$18,d1 cmpi.w #$18,d1 bhs.w locret_254E8 tst.b object_control(a1) bne.s locret_254E8 cmpi.b #4,routine(a1) bhs.s locret_254E8 tst.w (Debug_placement_mode).w bne.s locret_254E8 clr.w x_vel(a1) clr.w y_vel(a1) clr.w ground_vel(a1) move.w y_pos(a0),y_pos(a1) addi.w #$24,y_pos(a1) move.b #$14,anim(a1) move.b #1,object_control(a1) move.b #1,(a2) locret_254E8: rts ; End of function sub_253FA ; --------------------------------------------------------------------------- Map_LBZUnusedBarPlatform: include "Levels/LBZ/Misc Object Data/Map - Unused Bar Platform.asm" ; --------------------------------------------------------------------------- byte_254FA: dc.b $20, $20, 0 even dc.b $18, $C, 0 even dc.b $20, $14, 0 even ; --------------------------------------------------------------------------- Obj_FloatingPlatform: cmpi.w #0,(Current_zone_and_act).w bne.s loc_2551C move.l #Map_AIZFloatingPlatform,mappings(a0) move.w #make_art_tile($3F7,2,0),art_tile(a0) loc_2551C: cmpi.w #1,(Current_zone_and_act).w bne.s loc_25532 move.l #Map_AIZFloatingPlatform,mappings(a0) move.w #make_art_tile($440,2,0),art_tile(a0) loc_25532: cmpi.b #1,(Current_zone).w bne.s loc_25548 move.l #Map_HCZFloatingPlatform,mappings(a0) move.w #make_art_tile($41D,2,0),art_tile(a0) loc_25548: cmpi.b #2,(Current_zone).w bne.s loc_2555E move.l #Map_MGZFloatingPlatform,mappings(a0) move.w #make_art_tile($001,2,0),art_tile(a0) loc_2555E: move.b #4,render_flags(a0) move.w #$180,priority(a0) moveq #0,d0 move.b subtype(a0),d0 lsr.w #2,d0 andi.w #$1C,d0 lea byte_254FA(pc,d0.w),a2 move.b (a2)+,width_pixels(a0) move.b (a2)+,height_pixels(a0) move.b (a2)+,mapping_frame(a0) move.w x_pos(a0),$30(a0) move.w x_pos(a0),$32(a0) move.w y_pos(a0),$34(a0) move.b status(a0),$2E(a0) move.w #$280,$42(a0) move.w x_pos(a0),$44(a0) moveq #0,d0 move.b subtype(a0),d0 andi.w #$F,d0 subq.w #8,d0 bcs.s loc_255E0 cmpi.w #4,d0 bhs.s loc_255D4 lsl.w #2,d0 lea (Oscillating_table+$2C).w,a2 lea (a2,d0.w),a2 tst.w (a2) bpl.s loc_255E0 bchg #0,$2E(a0) bra.s loc_255E0 ; --------------------------------------------------------------------------- loc_255D4: move.w #$380,$42(a0) addi.w #$100,$44(a0) loc_255E0: move.b subtype(a0),d0 andi.b #$F,d0 add.b d0,d0 move.b d0,subtype(a0) move.l #loc_255F4,(a0) loc_255F4: move.w x_pos(a0),-(sp) moveq #0,d0 move.b subtype(a0),d0 lea (FloatingPlatformIndex).l,a1 move.w (a1,d0.w),d1 jsr (a1,d1.w) move.w (sp)+,d4 tst.b render_flags(a0) bpl.s loc_25628 moveq #0,d1 move.b width_pixels(a0),d1 moveq #0,d3 move.b height_pixels(a0),d3 addq.w #1,d3 jsr (SolidObjectTop).l loc_25628: move.w $44(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmp.w $42(a0),d0 bhi.w loc_25642 jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_25642: move.w respawn_addr(a0),d0 beq.s loc_2564E movea.w d0,a2 bclr #7,(a2) loc_2564E: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- Map_MGZFloatingPlatform: include "Levels/MGZ/Misc Object Data/Map - Floating Platform.asm" Map_HCZFloatingPlatform: include "Levels/HCZ/Misc Object Data/Map - Floating Platform.asm" Map_AIZFloatingPlatform: include "Levels/AIZ/Misc Object Data/Map - Floating Platform.asm" ; --------------------------------------------------------------------------- Obj_HCZSnakeBlocks: move.l #Map_HCZFloatingPlatform,mappings(a0) move.w #make_art_tile($028,0,0),art_tile(a0) move.b #4,render_flags(a0) move.w #$180,priority(a0) move.b #$10,width_pixels(a0) move.b #$10,height_pixels(a0) move.b #1,mapping_frame(a0) move.w x_pos(a0),$30(a0) move.w y_pos(a0),$34(a0) move.b status(a0),$2E(a0) moveq #1,d0 move.b subtype(a0),d1 bpl.s loc_25706 neg.w d0 loc_25706: move.b d0,$40(a0) andi.b #$7F,d1 move.b d1,angle(a0) move.w #$280,$42(a0) move.w x_pos(a0),$44(a0) move.l #loc_25724,(a0) loc_25724: bsr.s sub_25770 moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsr (SolidObjectFull).l move.w $44(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmp.w $42(a0),d0 bhi.w loc_2575E jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_2575E: move.w respawn_addr(a0),d0 beq.s loc_2576A movea.w d0,a2 bclr #7,(a2) loc_2576A: jmp (Delete_Current_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_25770: move.b $40(a0),d0 bpl.s loc_2579A add.b d0,angle(a0) bcs.s loc_25786 subq.b #1,$2E(a0) andi.b #3,$2E(a0) loc_25786: move.w #$40,d2 move.b angle(a0),d0 cmpi.b #$80,d0 bhs.s loc_257BC move.b #$80,d0 bra.s loc_257BC ; --------------------------------------------------------------------------- loc_2579A: add.b d0,angle(a0) bne.s loc_257AA addq.b #1,$2E(a0) andi.b #3,$2E(a0) loc_257AA: move.w #$40,d2 move.b angle(a0),d0 cmpi.b #$80,d0 bhs.s loc_257BC move.b #$80,d0 loc_257BC: jsr (GetSineCosine).l asr.w #2,d1 move.b $2E(a0),d3 andi.b #3,d3 bne.s loc_257E2 add.w $30(a0),d1 move.w d1,x_pos(a0) neg.w d2 add.w $34(a0),d2 move.w d2,y_pos(a0) rts ; --------------------------------------------------------------------------- loc_257E2: subq.b #1,d3 bne.s loc_257F8 add.w $34(a0),d1 move.w d1,y_pos(a0) add.w $30(a0),d2 move.w d2,x_pos(a0) rts ; --------------------------------------------------------------------------- loc_257F8: subq.b #1,d3 bne.s loc_25810 neg.w d1 add.w $30(a0),d1 move.w d1,x_pos(a0) add.w $34(a0),d2 move.w d2,y_pos(a0) rts ; --------------------------------------------------------------------------- loc_25810: neg.w d1 add.w $34(a0),d1 move.w d1,y_pos(a0) neg.w d2 add.w $30(a0),d2 move.w d2,x_pos(a0) rts ; End of function sub_25770 ; --------------------------------------------------------------------------- byte_25826: dc.b $20, $20, 0 even dc.b $20, $20, 1 even ; --------------------------------------------------------------------------- Obj_LRZSolidMovingPlatforms: move.l #Map_LRZSolidMovingPlatforms,mappings(a0) move.w #make_art_tile($090,2,0),art_tile(a0) move.b #4,render_flags(a0) move.w #$180,priority(a0) moveq #0,d0 move.b subtype(a0),d0 lsr.w #2,d0 andi.w #$1C,d0 lea byte_25826(pc,d0.w),a2 move.b (a2)+,width_pixels(a0) move.b (a2)+,height_pixels(a0) move.b (a2)+,mapping_frame(a0) move.w x_pos(a0),$30(a0) move.w y_pos(a0),$34(a0) move.b subtype(a0),d0 andi.w #$F,d0 add.w d0,d0 move.w off_258BC(pc,d0.w),d0 lea off_258BC(pc,d0.w),a1 move.l a1,$42(a0) move.l #loc_2588C,(a0) loc_2588C: move.w x_pos(a0),-(sp) movea.l $42(a0),a1 jsr (a1) move.w (sp)+,d4 moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 jsr (SolidObjectFull).l move.w $30(a0),d0 jmp (Sprite_OnScreen_Test2).l ; --------------------------------------------------------------------------- off_258BC: dc.w locret_258CE-off_258BC dc.w loc_258D0-off_258BC dc.w loc_258DC-off_258BC dc.w loc_25924-off_258BC dc.w loc_258FA-off_258BC dc.w loc_25906-off_258BC dc.w loc_25938-off_258BC dc.w loc_2594C-off_258BC dc.w loc_25960-off_258BC ; --------------------------------------------------------------------------- locret_258CE: rts ; --------------------------------------------------------------------------- loc_258D0: moveq #0,d0 move.b (Oscillating_table+$0A).w,d0 subi.w #$20,d0 bra.s loc_258E6 ; --------------------------------------------------------------------------- loc_258DC: moveq #0,d0 move.b (Oscillating_table+$1E).w,d0 subi.w #$40,d0 loc_258E6: btst #0,status(a0) beq.s loc_258F0 neg.w d0 loc_258F0: add.w $30(a0),d0 move.w d0,x_pos(a0) rts ; --------------------------------------------------------------------------- loc_258FA: moveq #0,d0 move.b (Oscillating_table+$0A).w,d0 subi.w #$20,d0 bra.s loc_25910 ; --------------------------------------------------------------------------- loc_25906: moveq #0,d0 move.b (Oscillating_table+$1E).w,d0 subi.w #$40,d0 loc_25910: btst #0,status(a0) beq.s loc_2591A neg.w d0 loc_2591A: add.w $34(a0),d0 move.w d0,y_pos(a0) rts ; --------------------------------------------------------------------------- loc_25924: move.w #$5F,d2 bsr.s sub_25974 subi.w #$60,d0 add.w $30(a0),d0 move.w d0,x_pos(a0) rts ; --------------------------------------------------------------------------- loc_25938: move.w #$5F,d2 bsr.s sub_25974 subi.w #$60,d0 add.w $34(a0),d0 move.w d0,y_pos(a0) rts ; --------------------------------------------------------------------------- loc_2594C: move.w #$7F,d2 bsr.s sub_25974 subi.w #$80,d0 add.w $30(a0),d0 move.w d0,x_pos(a0) rts ; --------------------------------------------------------------------------- loc_25960: move.w #$7F,d2 bsr.s sub_25974 subi.w #$80,d0 add.w $34(a0),d0 move.w d0,y_pos(a0) rts ; =============== S U B R O U T I N E ======================================= sub_25974: tst.b $3C(a0) bne.s loc_25996 move.w $40(a0),d1 addq.w #4,d1 move.w d1,$40(a0) add.w d1,$36(a0) cmp.b $36(a0),d2 bhi.s loc_259B0 move.b #1,$3C(a0) bra.s loc_259B0 ; --------------------------------------------------------------------------- loc_25996: move.w $40(a0),d1 subq.w #4,d1 move.w d1,$40(a0) add.w d1,$36(a0) cmp.b $36(a0),d2 bls.s loc_259B0 move.b #0,$3C(a0) loc_259B0: moveq #0,d0 move.b $36(a0),d0 btst #0,status(a0) beq.s locret_259C2 neg.w d0 add.w d2,d0 locret_259C2: rts ; End of function sub_25974 ; --------------------------------------------------------------------------- Map_LRZSolidMovingPlatforms: include "Levels/LRZ/Misc Object Data/Map - Solid Moving Platforms.asm" ; --------------------------------------------------------------------------- dc.b $20, $10, 0 even ; --------------------------------------------------------------------------- Obj_DEZFloatingPlatform: move.l #Map_DEZFloatingPlatform,mappings(a0) move.w #make_art_tile($33A,1,0),art_tile(a0) move.b #4,render_flags(a0) move.w #$200,priority(a0) move.b #$20,width_pixels(a0) move.b #$10,height_pixels(a0) move.w x_pos(a0),$30(a0) move.w y_pos(a0),$34(a0) move.b subtype(a0),d0 andi.w #$F,d0 add.w d0,d0 move.w word_25AB8(pc,d0.w),d0 lea word_25AB8(pc,d0.w),a1 move.l a1,$42(a0) move.l #loc_25A7E,(a0) loc_25A7E: move.w x_pos(a0),-(sp) movea.l $42(a0),a1 jsr (a1) move.w (sp)+,d4 moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 jsr (SolidObjectFull).l addq.b #1,mapping_frame(a0) andi.b #1,mapping_frame(a0) move.w $30(a0),d0 jmp (Sprite_OnScreen_Test2).l ; --------------------------------------------------------------------------- word_25AB8: dc.w locret_258CE-word_25AB8 dc.w loc_258D0-word_25AB8 dc.w loc_258DC-word_25AB8 dc.w loc_25924-word_25AB8 dc.w loc_258FA-word_25AB8 dc.w loc_25906-word_25AB8 dc.w loc_25938-word_25AB8 dc.w loc_2594C-word_25AB8 dc.w loc_25960-word_25AB8 ; --------------------------------------------------------------------------- Map_DEZFloatingPlatform: include "Levels/DEZ/Misc Object Data/Map - Floating Platform.asm" ; --------------------------------------------------------------------------- byte_25AF0: dc.b $10, $18, $20, $38, $40, $68 even ; --------------------------------------------------------------------------- Obj_LBZUnusedElevator: move.l #Map_LBZUnusedElevator,mappings(a0) move.w #make_art_tile($3C3,2,0),art_tile(a0) move.b #4,render_flags(a0) move.w #$200,priority(a0) move.b #$30,width_pixels(a0) move.b #8,height_pixels(a0) move.w y_pos(a0),$32(a0) move.w #$8000,$16(a0) moveq #0,d0 move.b subtype(a0),d0 lsr.w #4,d0 andi.w #$F,d0 move.b byte_25AF0(pc,d0.w),d0 lsl.w #3,d0 move.w d0,$38(a0) sub.w d0,y_pos(a0) btst #0,status(a0) beq.s loc_25B56 add.w d0,d0 add.w d0,y_pos(a0) move.b #1,$34(a0) loc_25B56: move.l #loc_25B5C,(a0) loc_25B5C: move.w $36(a0),d0 move.w off_25B92(pc,d0.w),d1 jsr off_25B92(pc,d1.w) tst.b render_flags(a0) bpl.s loc_25B8C moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsr (SolidObjectFull).l loc_25B8C: jmp (Sprite_OnScreen_Test).l ; --------------------------------------------------------------------------- off_25B92: dc.w loc_25B9A-off_25B92 dc.w loc_25BB8-off_25B92 dc.w loc_25BE4-off_25B92 dc.w loc_25C02-off_25B92 ; --------------------------------------------------------------------------- loc_25B9A: move.b subtype(a0),d0 andi.w #$F,d0 lea (Level_trigger_array).w,a3 tst.b (a3,d0.w) beq.s locret_25BB6 move.w #$8000,$16(a0) addq.w #2,$36(a0) locret_25BB6: rts ; --------------------------------------------------------------------------- loc_25BB8: bsr.w sub_25C2E tst.w y_vel(a0) bne.s locret_25BE2 addq.w #2,$36(a0) move.w d0,y_pos(a0) move.w $38(a0),d0 sub.w d0,y_pos(a0) btst #0,status(a0) bne.s locret_25BE2 add.w d0,d0 add.w d0,y_pos(a0) rts ; --------------------------------------------------------------------------- locret_25BE2: rts ; --------------------------------------------------------------------------- loc_25BE4: move.b subtype(a0),d0 andi.w #$F,d0 lea (Level_trigger_array).w,a3 tst.b (a3,d0.w) bne.s locret_25C00 move.w #$8000,$16(a0) addq.w #2,$36(a0) locret_25C00: rts ; --------------------------------------------------------------------------- loc_25C02: bsr.w sub_25C2E tst.w y_vel(a0) bne.s locret_25C2C clr.w $36(a0) move.w d0,y_pos(a0) move.w $38(a0),d0 sub.w d0,y_pos(a0) btst #0,status(a0) beq.s locret_25C2C add.w d0,d0 add.w d0,y_pos(a0) rts ; --------------------------------------------------------------------------- locret_25C2C: rts ; =============== S U B R O U T I N E ======================================= sub_25C2E: move.w y_pos(a0),d2 moveq #8,d1 tst.b $34(a0) bne.s loc_25C7C add.w d1,y_vel(a0) move.w y_vel(a0),d0 ext.l d0 lsl.l #8,d0 add.l d0,y_pos(a0) move.w $32(a0),d0 cmp.w y_pos(a0),d0 bhi.s locret_25CBC beq.s loc_25C6C sub.w d0,d2 neg.w d2 add.w d0,d2 move.w d2,y_pos(a0) neg.w $16(a0) move.b #1,$34(a0) bra.s locret_25CBC ; --------------------------------------------------------------------------- loc_25C6C: neg.w $16(a0) add.w d1,y_vel(a0) move.b #1,$34(a0) bra.s locret_25CBC ; --------------------------------------------------------------------------- loc_25C7C: sub.w d1,y_vel(a0) move.w y_vel(a0),d0 ext.l d0 lsl.l #8,d0 add.l d0,y_pos(a0) move.w $32(a0),d0 cmp.w y_pos(a0),d0 blo.s locret_25CBC beq.s loc_25CAE sub.w d0,d2 neg.w d2 add.w d0,d2 move.w d2,y_pos(a0) neg.w $16(a0) move.b #0,$34(a0) bra.s locret_25CBC ; --------------------------------------------------------------------------- loc_25CAE: neg.w $16(a0) sub.w d1,y_vel(a0) move.b #0,$34(a0) locret_25CBC: rts ; End of function sub_25C2E ; --------------------------------------------------------------------------- Obj_LBZExplodingTrigger: move.l #Map_LBZExplodingTrigger,mappings(a0) move.w #make_art_tile($433,2,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #$10,height_pixels(a0) move.w #$280,priority(a0) move.b #$C6,collision_flags(a0) move.l #loc_25CF0,(a0) loc_25CF0: move.b collision_property(a0),d0 beq.w loc_25D26 move.b subtype(a0),d0 andi.w #$F,d0 lea (Level_trigger_array).w,a3 lea (a3,d0.w),a3 moveq #0,d3 lea (Player_1).w,a1 bclr #0,collision_property(a0) beq.s loc_25D18 bsr.s sub_25D2C loc_25D18: lea (Player_2).w,a1 bclr #1,collision_property(a0) beq.s loc_25D26 bsr.s sub_25D2C loc_25D26: jmp (Sprite_CheckDeleteTouch3).l ; =============== S U B R O U T I N E ======================================= sub_25D2C: cmpi.b #2,anim(a1) bne.s locret_25D52 neg.w x_vel(a1) neg.w y_vel(a1) bchg d3,(a3) move.l #Obj_Explosion,(a0) move.b #2,routine(a0) clr.b collision_flags(a0) clr.b collision_property(a0) locret_25D52: rts ; End of function sub_25D2C ; --------------------------------------------------------------------------- Obj_MGZDashTrigger: move.l #Map_MGZDashTrigger,mappings(a0) move.w #make_art_tile($35F,1,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.b #$10,height_pixels(a0) move.w #$280,priority(a0) bset #6,render_flags(a0) move.w #1,mainspr_childsprites(a0) lea sub2_x_pos(a0),a2 move.w x_pos(a0),(a2)+ move.w y_pos(a0),(a2)+ move.w #0,(a2)+ move.l #loc_25D9C,(a0) loc_25D9C: move.w #$1B,d1 move.w #$10,d2 move.w x_pos(a0),d4 lea (byte_25F0E).l,a2 jsr (sub_1DD0E).l swap d6 andi.w #$33,d6 beq.s loc_25E22 move.b d6,d0 andi.b #$11,d0 beq.s loc_25DF0 lea (Player_1).w,a1 cmpi.b #9,anim(a1) bne.s loc_25DF0 move.w #$3C,$30(a0) move.b #1,$32(a0) move.b status(a1),d0 add.b status(a0),d0 andi.b #1,d0 bne.s loc_25DF0 move.b #-1,$32(a0) loc_25DF0: andi.b #$22,d6 beq.s loc_25E22 lea (Player_2).w,a1 cmpi.b #9,anim(a1) bne.s loc_25E22 move.w #$3C,$30(a0) move.b #1,$32(a0) move.b status(a1),d0 add.b status(a0),d0 andi.b #1,d0 bne.s loc_25E22 move.b #-1,$32(a0) loc_25E22: tst.w $30(a0) beq.s loc_25EA0 move.b subtype(a0),d0 andi.w #$F,d0 lea (Level_trigger_array).w,a3 lea (a3,d0.w),a3 subq.w #1,$30(a0) bne.s loc_25E4A move.b #0,(a3) move.b #0,mapping_frame(a0) bra.s loc_25EA0 ; --------------------------------------------------------------------------- loc_25E4A: move.b #1,(a3) move.b status(a0),d6 andi.w #standing_mask,d6 beq.s loc_25E72 move.w d6,d0 andi.w #p1_standing,d0 beq.s loc_25E66 lea (Player_1).w,a1 bsr.s sub_25EA6 loc_25E66: andi.w #p2_standing,d6 beq.s loc_25E72 lea (Player_2).w,a1 bsr.s sub_25EA6 loc_25E72: subq.b #1,anim_frame_timer(a0) bpl.s loc_25E8C move.b #1,anim_frame_timer(a0) move.b $32(a0),d0 add.b d0,$1D(a0) andi.b #3,$1D(a0) loc_25E8C: tst.b mapping_frame(a0) beq.s loc_25E9A move.b #0,mapping_frame(a0) bra.s loc_25EA0 ; --------------------------------------------------------------------------- loc_25E9A: move.b #4,mapping_frame(a0) loc_25EA0: jmp (Sprite_OnScreen_Test).l ; =============== S U B R O U T I N E ======================================= sub_25EA6: move.w x_pos(a0),d1 subi.w #$10,d1 btst #0,status(a0) beq.s loc_25EBA addi.w #2*$10,d1 loc_25EBA: move.w y_pos(a0),d2 addi.w #$10,d2 sub.w x_pos(a1),d1 sub.w y_pos(a1),d2 jsr (GetArcTan).l jsr (GetSineCosine).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 #Status_InAir,status(a1) bclr #Status_RollJump,status(a1) bclr #Status_Push,status(a1) clr.b jumping(a1) clr.b spin_dash_flag(a1) moveq #signextendB(sfx_SmallBumpers),d0 jsr (Play_SFX).l rts ; End of function sub_25EA6 ; --------------------------------------------------------------------------- byte_25F0E: dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $10 dc.b $F dc.b $F dc.b $E dc.b $E dc.b $D dc.b $C dc.b $A dc.b 8 dc.b 6 dc.b 4 dc.b 0 dc.b -4 dc.b -8 dc.b -$A dc.b -$A dc.b -$A dc.b -$A dc.b -$A dc.b -$A even ; --------------------------------------------------------------------------- byte_25F2A: ; X offset, Y offset, X width, Y width, init routine counter, init mapping frame, second routine counter, second mapping frame dc.b $48, 0, 8, $40, 0, 0, $A, 8 dc.b 0, $48, $40, 8, 0, 8, $A, $10 dc.b -$48, 0, 8, $40, 0, 0, $A, 8 dc.b 0, $48, $40, 8, 0, $10, $A, $18 dc.b 0, $48, $40, 8, 6, 8, 4, $10 dc.b $48, 0, 8, $40, 6, 0, 4, 8 dc.b 0, $48, $40, 8, 6, $10, 4, $18 dc.b -$48, 0, 8, $40, 6, 0, 4, 8 ; --------------------------------------------------------------------------- Obj_LBZTriggerBridge: move.b subtype(a0),d0 move.b d0,d1 andi.w #$F,d1 tst.b $34(a0) bne.s loc_25F86 lea (Level_trigger_array).w,a3 tst.b (a3,d0.w) beq.s loc_25F86 addq.w #4,d0 loc_25F86: lsr.b #1,d0 andi.w #$38,d0 lea byte_25F2A(pc,d0.w),a1 move.l #Map_LBZTriggerBridge,mappings(a0) move.w #make_art_tile($3C3,2,0),art_tile(a0) move.b #4,render_flags(a0) move.w #$200,priority(a0) move.w x_pos(a0),$30(a0) move.w y_pos(a0),$32(a0) move.b (a1)+,d0 ext.w d0 add.w $30(a0),d0 move.w d0,x_pos(a0) move.b (a1)+,d0 ext.w d0 add.w $32(a0),d0 move.w d0,y_pos(a0) move.b (a1)+,width_pixels(a0) move.b (a1)+,height_pixels(a0) moveq #0,d0 move.b (a1)+,d0 move.w d0,$36(a0) move.b (a1)+,mapping_frame(a0) tst.b $34(a0) beq.s loc_25FF8 move.b (a1)+,d0 move.w d0,$36(a0) move.b (a1)+,mapping_frame(a0) move.b #0,$34(a0) loc_25FF8: move.l #loc_25FFE,(a0) loc_25FFE: move.w $36(a0),d0 move.w off_26038(pc,d0.w),d1 jsr off_26038(pc,d1.w) tst.b render_flags(a0) bpl.s loc_2602E moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsr (SolidObjectFull2).l loc_2602E: move.w $30(a0),d0 jmp (Sprite_OnScreen_Test2).l ; --------------------------------------------------------------------------- off_26038: dc.w loc_26044-off_26038 dc.w loc_2609E-off_26038 dc.w loc_260B0-off_26038 dc.w loc_260D2-off_26038 dc.w loc_2609E-off_26038 dc.w loc_260C0-off_26038 ; --------------------------------------------------------------------------- loc_26044: move.b subtype(a0),d0 andi.w #$F,d0 lea (Level_trigger_array).w,a3 tst.b (a3,d0.w) beq.s locret_2609C addq.b #1,mapping_frame(a0) move.w #7,$38(a0) addq.w #2,$36(a0) jsr (AllocateObjectAfterCurrent).l bne.w locret_2609C move.l #Obj_LBZTriggerBridge,(a1) move.w $30(a0),x_pos(a1) move.w $32(a0),y_pos(a1) move.b subtype(a0),d0 addi.b #$40,d0 andi.b #$7F,d0 move.b d0,subtype(a1) move.w #8,$38(a1) move.b #1,$34(a1) locret_2609C: rts ; --------------------------------------------------------------------------- loc_2609E: addq.b #1,mapping_frame(a0) subq.w #1,$38(a0) bne.s locret_260AE move.w #$7FFF,x_pos(a0) locret_260AE: rts ; --------------------------------------------------------------------------- loc_260B0: subq.b #1,mapping_frame(a0) subq.w #1,$38(a0) bne.s locret_260BE addq.w #2,$36(a0) locret_260BE: rts ; --------------------------------------------------------------------------- loc_260C0: subq.b #1,mapping_frame(a0) subq.w #1,$38(a0) bne.s locret_260D0 move.w #0,$36(a0) locret_260D0: rts ; --------------------------------------------------------------------------- loc_260D2: move.b subtype(a0),d0 andi.w #$F,d0 lea (Level_trigger_array).w,a3 tst.b (a3,d0.w) bne.s locret_2612A addq.b #1,mapping_frame(a0) move.w #7,$38(a0) addq.w #2,$36(a0) jsr (AllocateObjectAfterCurrent).l bne.w locret_2612A move.l #Obj_LBZTriggerBridge,(a1) move.w $30(a0),x_pos(a1) move.w $32(a0),y_pos(a1) move.b subtype(a0),d0 addi.b #$40,d0 andi.b #$7F,d0 move.b d0,subtype(a1) move.w #8,$38(a1) move.b #1,$34(a1) locret_2612A: rts ; --------------------------------------------------------------------------- word_2612C: dc.w $1000 dc.w $A00 ; --------------------------------------------------------------------------- Obj_LBZPlayerLauncher: move.l #Map_LBZPlayerLauncher,mappings(a0) move.w #make_art_tile($3C3,2,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #$20,width_pixels(a0) move.w #$80,priority(a0) move.b subtype(a0),d0 andi.w #2,d0 move.w word_2612C(pc,d0.w),$34(a0) move.l #loc_26164,(a0) loc_26164: 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 (Player_1).w,a1 btst #Status_InAir,status(a1) bne.s loc_261B8 move.w x_pos(a1),d4 cmp.w d0,d4 blo.w loc_261B8 cmp.w d1,d4 bhs.w loc_261B8 move.w y_pos(a1),d4 cmp.w d2,d4 blo.w loc_261B8 cmp.w d3,d4 bhs.w loc_261B8 move.w d0,-(sp) lea $38(a0),a2 bsr.w sub_261F2 move.w (sp)+,d0 loc_261B8: lea (Player_2).w,a1 btst #Status_InAir,status(a1) bne.s loc_261EC move.w x_pos(a1),d4 cmp.w d0,d4 blo.w loc_261EC cmp.w d1,d4 bhs.w loc_261EC move.w y_pos(a1),d4 cmp.w d2,d4 blo.w loc_261EC cmp.w d3,d4 bhs.w loc_261EC lea $3A(a0),a2 bsr.w sub_261F2 loc_261EC: jmp (Sprite_OnScreen_Test).l ; =============== S U B R O U T I N E ======================================= sub_261F2: tst.w (a2) bne.s loc_26220 move.l a1,-(sp) jsr (AllocateObjectAfterCurrent).l bne.w loc_2621E move.l #loc_2629C,(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.w a2,$3C(a1) loc_2621E: movea.l (sp)+,a1 loc_26220: addq.w #1,(a2) cmpi.w #4,(a2) beq.s loc_26244 move.w x_vel(a1),d0 btst #0,render_flags(a0) beq.s loc_26236 neg.w d0 loc_26236: tst.w d0 bpl.s locret_26242 asr ground_vel(a1) asr x_vel(a1) locret_26242: rts ; --------------------------------------------------------------------------- loc_26244: move.w x_vel(a1),d0 btst #0,status(a0) beq.s loc_26252 neg.w d0 loc_26252: cmpi.w #$1000,d0 bge.s loc_26294 move.w $34(a0),x_vel(a1) bclr #Status_Facing,status(a1) btst #0,status(a0) beq.s loc_26276 bset #Status_Facing,status(a1) neg.w x_vel(a1) loc_26276: move.w #15,move_lock(a1) move.w x_vel(a1),ground_vel(a1) bclr #p1_pushing_bit,status(a0) bclr #p2_pushing_bit,status(a0) bclr #Status_Push,status(a1) loc_26294: moveq #signextendB(sfx_Spring),d0 jmp (Play_SFX).l ; End of function sub_261F2 ; --------------------------------------------------------------------------- loc_2629C: move.l #Map_LBZPlayerLauncher,mappings(a0) move.w #make_art_tile($3C3,2,0),art_tile(a0) ori.b #4,render_flags(a0) move.b #8,width_pixels(a0) move.w #$80,priority(a0) move.w x_pos(a0),$30(a0) addi.w #$10,y_pos(a0) move.w y_pos(a0),$32(a0) move.b #1,mapping_frame(a0) move.b #$80,$40(a0) bset #6,render_flags(a0) move.w #4,mainspr_childsprites(a0) move.l #loc_262EC,(a0) loc_262EC: move.w $36(a0),d0 move.w off_26302(pc,d0.w),d1 jsr off_26302(pc,d1.w) bsr.w sub_26338 jmp (Sprite_OnScreen_Test).l ; --------------------------------------------------------------------------- off_26302: dc.w loc_26306-off_26302 dc.w loc_26322-off_26302 ; --------------------------------------------------------------------------- loc_26306: addi.b #$10,$40(a0) cmpi.b #$D0,$40(a0) bne.s locret_26320 movea.w $3C(a0),a2 move.w #0,(a2) addq.w #2,$36(a0) locret_26320: rts ; --------------------------------------------------------------------------- loc_26322: subi.b #4,$40(a0) cmpi.b #$80,$40(a0) bne.s locret_26336 move.w #$7F00,$30(a0) locret_26336: rts ; =============== S U B R O U T I N E ======================================= sub_26338: move.b $40(a0),d0 btst #0,render_flags(a0) beq.s loc_2634A neg.b d0 addi.b #$80,d0 loc_2634A: jsr (GetSineCosine).l move.w $32(a0),d2 move.w $30(a0),d3 moveq #0,d6 move.w mainspr_childsprites(a0),d6 subq.w #1,d6 bcs.s locret_263A8 swap d0 swap d1 asr.l #4,d0 asr.l #4,d1 moveq #0,d4 moveq #0,d5 add.l d0,d4 add.l d1,d5 lea sub2_x_pos(a0),a2 loc_26376: movem.l d4-d5,-(sp) swap d4 swap d5 add.w d2,d4 add.w d3,d5 move.w d5,(a2)+ move.w d4,(a2)+ movem.l (sp)+,d4-d5 add.l d0,d4 add.l d1,d5 addq.w #1,a2 move.b #1,(a2)+ dbf d6,loc_26376 swap d4 swap d5 add.w d2,d4 add.w d3,d5 move.w d5,x_pos(a0) move.w d4,y_pos(a0) locret_263A8: rts ; End of function sub_26338 ; =============== S U B R O U T I N E ======================================= sub_263AA: move.l #Map_LBZFlameThrower,mappings(a1) move.w #make_art_tile($3AC,2,0),art_tile(a1) move.b #$10,width_pixels(a1) move.b #$10,height_pixels(a1) ori.b #4,render_flags(a1) move.w #$200,priority(a1) rts ; End of function sub_263AA ; --------------------------------------------------------------------------- Obj_LBZFlameThrower: movea.l a0,a1 bsr.s sub_263AA move.l #loc_263DC,(a0) loc_263DC: move.b (V_int_run_count+3).w,d0 add.b subtype(a0),d0 andi.b #$7F,d0 bne.s loc_2643C jsr (AllocateObjectAfterCurrent).l bne.w loc_2643C move.l #Obj_AutoSpin460,(a1) bsr.s sub_263AA move.w x_pos(a0),x_pos(a1) move.w y_pos(a0),y_pos(a1) move.b status(a0),status(a1) move.b #$9D,collision_flags(a1) bset #4,shield_reaction(a1) addi.w #$40,x_pos(a1) btst #0,status(a0) beq.s loc_2642E subi.w #2*$40,x_pos(a1) loc_2642E: tst.b render_flags(a0) bpl.s loc_2643C moveq #signextendB(sfx_FireAttack),d0 jsr (Play_SFX).l loc_2643C: moveq #0,d1 move.b width_pixels(a0),d1 addi.w #$B,d1 moveq #0,d2 move.b height_pixels(a0),d2 move.w d2,d3 addq.w #1,d3 move.w x_pos(a0),d4 jsr (SolidObjectFull).l jmp (Sprite_OnScreen_Test).l ; --------------------------------------------------------------------------- Obj_AutoSpin460: lea (Ani_LBZFlameThrower).l,a1 jsr (Animate_Sprite).l tst.b routine(a0) beq.s loc_26478 move.w #$7FFF,x_pos(a0) loc_26478: jmp (Sprite_CheckDeleteTouch3).l ; --------------------------------------------------------------------------- Ani_LBZFlameThrower: include "Levels/LBZ/Misc Object Data/Anim - Flame Thrower.asm" LBZRideGrapple_Range: dc.w $A08, $C78 ; 0 dc.w $1208, $14F8 ; 1 dc.w $1A08, $1BB8 ; 2 dc.w $1C48, $2078 ; 3 dc.w $2688, $2878 ; 4 dc.w $2988, $2DF8 ; 5 dc.w $2F88, $3178 ; 6 dc.w $E68, $1098 ; 7 dc.w $CE8, $1498 ; 8 dc.w $E68, $1398 ; 9 dc.w $20E8, $2418 ; A dc.w $2B08, $2E98 ; B dc.w $39E8, $3C98 ; C ; --------------------------------------------------------------------------- Obj_LBZRideGrapple: move.b #4,render_flags(a0) move.b #$10,width_pixels(a0) move.w #$80,priority(a0) move.b #$20,height_pixels(a0) move.w x_pos(a0),$38(a0) move.b subtype(a0),d0 andi.w #$7F,d0 lsl.w #2,d0 move.l LBZRideGrapple_Range(pc,d0.w),$34(a0) move.l #Map_LBZRideGrapple,mappings(a0) move.w #make_art_tile($433,1,0),art_tile(a0) jsr (AllocateObjectAfterCurrent).l bne.s loc_26566 move.l #loc_2668E,(a1) 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) move.w priority(a0),priority(a1) bset #6,render_flags(a1) move.b #$10,width_pixels(a1) move.b #$20,height_pixels(a1) moveq #6,d1 move.w d1,mainspr_childsprites(a1) subq.b #1,d1 lea sub2_x_pos(a1),a2 loc_2654C: move.w x_pos(a1),(a2)+ move.w y_pos(a1),(a2)+ move.w #1,(a2)+ dbf d1,loc_2654C move.b #2,mapping_frame(a1) move.w a1,$3C(a0) loc_26566: move.l #loc_2656C,(a0) loc_2656C: bsr.w sub_2682E bsr.w sub_26694 tst.w $30(a0) beq.s loc_26588 cmpi.w #$28,$3A(a0) bne.s loc_26588 move.l #loc_265DC,(a0) loc_26588: move.w x_pos(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_265A2 jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_265A2: move.w $38(a0),d0 andi.w #$FF80,d0 sub.w (Camera_X_pos_coarse_back).w,d0 cmpi.w #$280,d0 bhi.w loc_265BC jmp (Draw_Sprite).l ; --------------------------------------------------------------------------- loc_265BC: move.w respawn_addr(a0),d0 beq.s loc_265C8 movea.w d0,a2 bclr #7,(a2) loc_265C8: move.w $3C(a0),d0 beq.s loc_265D6 movea.w d0,a1 jsr (Delete_Referenced_Sprite).l loc_265D6: jmp (Delete_Current_Sprite).l ; --------------------------------------------------------------------------- loc_265DC: jsr (MoveSprite2).l btst #0,status(a0) beq.s loc_265FE subi.w #$20,x_vel(a0) tst.w x_vel(a0) bmi.s loc_26610 subi.w #$60,x_vel(a0) bra.s loc_26610 ; --------------------------------------------------------------------------- loc_265FE: addi.w #$20,x_vel(a0) tst.w x_vel(a0) bpl.s loc_26610 addi.w #$60,x_vel(a0) loc_26610: move.w x_pos(a0),d0 move.w $34(a0),d1 cmp.w d1,d0 bhi.s loc_2662E move.w d1,x_pos(a0) bsr.s sub_26654 tst.w x_vel(a0) bpl.s loc_2662E move.w #0,x_vel(a0) loc_2662E: move.w $36(a0),d1 cmp.w d1,d0 blo.s loc_26648 move.w d1,x_pos(a0) bsr.s sub_26654 tst.w x_vel(a0) bmi.s loc_26648 move.w #0,x_vel(a0) loc_26648: bsr.w sub_2682E bsr.w sub_26694 bra.w loc_26588 ; =============== S U B R O U T I N E ======================================= sub_26654: tst.b subtype(a0) bmi.s locret_2668C lea $30(a0),a2 lea (Player_1).w,a1 bsr.s sub_2666A lea (Player_2).w,a1 addq.w #1,a2 ; End of function sub_26654 ; =============== S U B R O U T I N E ======================================= sub_2666A: tst.b (a2) beq.s locret_2668C move.w x_vel(a0),x_vel(a1) move.w #0,y_vel(a1) bset #Status_InAir,status(a1) clr.b object_control(a1) clr.b (a2) move.b #$3C,2(a2) locret_2668C: rts ; End of function sub_2666A ; --------------------------------------------------------------------------- loc_2668E: jmp (Draw_Sprite).l ; =============== S U B R O U T I N E ======================================= sub_26694: movea.w $3C(a0),a3 lea $31(a0),a2 lea (Player_2).w,a1 move.w (Ctrl_2_logical).w,d0 bsr.s sub_266B0 lea (Player_1).w,a1 subq.w #1,a2 move.w (Ctrl_1_logical).w,d0 ; End of function sub_26694 ; =============== S U B R O U T I N E ======================================= sub_266B0: tst.b (a2) beq.w loc_267A4 tst.b render_flags(a1) bpl.s loc_26718 cmpi.b #4,routine(a1) bhs.s loc_26718 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 beq.w loc_26726 clr.b $2E(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 loc_266E6 move.b #$3C,2(a2) loc_266E6: move.w x_vel(a0),x_vel(a1) move.w #-$380,y_vel(a1) bset #Status_InAir,status(a1) move.b #1,jumping(a1) move.b #$E,y_radius(a1) move.b #7,x_radius(a1) move.b #2,anim(a1) bset #Status_Roll,status(a1) rts ; --------------------------------------------------------------------------- loc_26718: clr.b object_control(a1) clr.b (a2) move.b #$3C,2(a2) rts ; --------------------------------------------------------------------------- loc_26726: btst #button_left+8,d0 beq.s loc_26732 bset #Status_Facing,status(a1) loc_26732: btst #button_right+8,d0 beq.s loc_2673E bclr #Status_Facing,status(a1) loc_2673E: move.b status(a1),status(a0) move.b status(a1),d0 andi.b #1<