; Sonic the Hedgehog 2 disassembled binary
; Nemesis, 2004: Created original disassembly for SNASM68K
; Aurochs, 2005: Translated to AS and annotated
; Xenowhirl, 2007: More annotation, overall cleanup, Z80 disassembly
; ---------------------------------------------------------------------------
; NOTES:
;
; Set your editor's tab width to 8 characters wide for viewing this file.
;
; It is highly suggested that you read the AS User's Manual before diving too
; far into this disassembly. At least read the section on nameless temporary
; symbols. Your brain may melt if you don't know how those work.
;
; See s2.notes.txt for more comments about this disassembly and other useful info.
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; ASSEMBLY OPTIONS:
;
padToPowerOfTwo = 1
; | If 1, pads the end of the ROM to the next power of two bytes (for real hardware)
;
allOptimizations = 0
; | If 1, enables all optimizations
;
skipChecksumCheck = 0|allOptimizations
; | If 1, disables the unnecessary (and slow) bootup checksum calculation
;
zeroOffsetOptimization = 0|allOptimizations
; | If 1, makes a handful of zero-offset instructions smaller
;
removeJmpTos = 0|allOptimizations
; | If 1, many unnecessary JmpTos are removed, improving performance
;
addsubOptimize = 0|allOptimizations
; | If 1, some add/sub instructions are optimized to addq/subq
;
relativeLea = 1|allOptimizations
; | If 1, makes some instructions use pc-relative addressing, instead of absolute long
;
useFullWaterTables = 0
; | If 1, zone offset tables for water levels cover all level slots instead of only slots 8-$F
; | Set to 1 if you've shifted level IDs around or you want water in levels with a level slot below 8
gameRevision = 1
; | If 0, a REV00 ROM is built
; | If 1, a REV01 ROM is built, which contains some fixes
; | If 2, a (probable) REV02 ROM is built, which contains more fixes
; | (Bit-perfect REV02 requires removeJmpTos & addsubOptimize be set to 1,
; | and also requires relativeLea to be 0)
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; AS-specific macros and assembler settings
CPU 68000
include "s2.macrosetup.asm"
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equates section - Names for variables.
include "s2.constants.asm"
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; simplifying macros and functions
include "s2.macros.asm"
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; start of ROM
StartOfRom:
if * <> 0
fatal "StartOfRom was $\{*} but it should be 0"
endif
;Vectors:
dc.l System_Stack, EntryPoint, ErrorTrap, ErrorTrap; 4
dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 8
dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 12
dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 16
dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 20
dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 24
dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 28
dc.l H_Int, ErrorTrap, V_Int, ErrorTrap; 32
dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 36
dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 40
dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 44
dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 48
dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 52
dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 56
dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 60
dc.l ErrorTrap, ErrorTrap, ErrorTrap, ErrorTrap; 64
; byte_100:
Header:
dc.b "SEGA GENESIS " ; Console name
dc.b "(C)SEGA 1992.SEP" ; Copyright/Date
dc.b "SONIC THE HEDGEHOG 2 " ; Domestic name
dc.b "SONIC THE HEDGEHOG 2 " ; International name
if gameRevision=0
dc.b "GM 00001051-00" ; Version (REV00)
elseif gameRevision=1
dc.b "GM 00001051-01" ; Version (REV01)
else;if gameRevision=2
dc.b "GM 00001051-02" ; Version (REV02)
endif
; word_18E
Checksum:
dc.w $D951 ; Checksum (patched later if incorrect)
dc.b "J " ; I/O Support
dc.l StartOfRom ; ROM Start
; dword_1A4
ROMEndLoc:
dc.l EndOfRom-1 ; ROM End
dc.l RAM_Start&$FFFFFF ; RAM Start
dc.l (RAM_End-1)&$FFFFFF ; RAM End
dc.b " " ; Backup RAM ID
dc.l $20202020 ; Backup RAM start address
dc.l $20202020 ; Backup RAM end address
dc.b " " ; Modem support
dc.b " " ; Notes
dc.b "JUE " ; Country
EndOfHeader:
; ===========================================================================
; Crash/Freeze the 68000. Note that the Z80 continues to run, so the music keeps playing.
; loc_200:
ErrorTrap:
nop
nop
bra.s ErrorTrap
; ===========================================================================
; loc_206:
EntryPoint:
tst.l (HW_Port_1_Control-1).l ; test ports A and B control
bne.s PortA_Ok
tst.w (HW_Expansion_Control-1).l ; test port C control
; loc_214:
PortA_Ok:
bne.s PortC_OK ; skip the VDP and Z80 setup code if port A, B or C is ok...?
lea SetupValues(pc),a5
movem.w (a5)+,d5-d7
movem.l (a5)+,a0-a4
move.b HW_Version-Z80_Bus_Request(a1),d0 ; get hardware version
andi.b #$F,d0
beq.s SkipSecurity ; branch if hardware is older than Genesis III
move.l #'SEGA',Security_Addr-Z80_Bus_Request(a1) ; satisfy the TMSS
; loc_234:
SkipSecurity:
move.w (a4),d0 ; check if VDP works
moveq #0,d0
movea.l d0,a6
move.l a6,usp ; set usp to $0
moveq #VDPInitValues_End-VDPInitValues-1,d1 ; run the following loop $18 times
; loc_23E:
VDPInitLoop:
move.b (a5)+,d5 ; add $8000 to value
move.w d5,(a4) ; move value to VDP register
add.w d7,d5 ; next register
dbf d1,VDPInitLoop
move.l (a5)+,(a4) ; set VRAM write mode
move.w d0,(a3) ; clear the screen
move.w d7,(a1) ; stop the Z80
move.w d7,(a2) ; reset the Z80
; loc_250:
WaitForZ80:
btst d0,(a1) ; has the Z80 stopped?
bne.s WaitForZ80 ; if not, branch
moveq #Z80StartupCodeEnd-Z80StartupCodeBegin-1,d2
; loc_256:
Z80InitLoop:
move.b (a5)+,(a0)+
dbf d2,Z80InitLoop
move.w d0,(a2)
move.w d0,(a1) ; start the Z80
move.w d7,(a2) ; reset the Z80
; loc_262:
ClrRAMLoop:
move.l d0,-(a6)
dbf d6,ClrRAMLoop ; clear the entire RAM
move.l (a5)+,(a4) ; set VDP display mode and increment
move.l (a5)+,(a4) ; set VDP to CRAM write
moveq #bytesToLcnt($80),d3
; loc_26E:
ClrCRAMLoop:
move.l d0,(a3)
dbf d3,ClrCRAMLoop ; clear the CRAM
move.l (a5)+,(a4)
moveq #bytesToLcnt($50),d4
; loc_278: ClrVDPStuff:
ClrVSRAMLoop:
move.l d0,(a3)
dbf d4,ClrVSRAMLoop
moveq #PSGInitValues_End-PSGInitValues-1,d5
; loc_280:
PSGInitLoop:
move.b (a5)+,PSG_input-VDP_data_port(a3) ; reset the PSG
dbf d5,PSGInitLoop
move.w d0,(a2)
movem.l (a6),d0-a6 ; clear all registers
move #$2700,sr ; set the sr
; loc_292:
PortC_OK: ;;
bra.s GameProgram
; ===========================================================================
; byte_294:
SetupValues:
dc.w $8000,bytesToLcnt($10000),$100
dc.l Z80_RAM
dc.l Z80_Bus_Request
dc.l Z80_Reset
dc.l VDP_data_port, VDP_control_port
VDPInitValues: ; values for VDP registers
dc.b 4 ; Command $8004 - HInt off, Enable HV counter read
dc.b $14 ; Command $8114 - Display off, VInt off, DMA on, PAL off
dc.b $30 ; Command $8230 - Scroll A Address $C000
dc.b $3C ; Command $833C - Window Address $F000
dc.b 7 ; Command $8407 - Scroll B Address $E000
dc.b $6C ; Command $856C - Sprite Table Address $D800
dc.b 0 ; Command $8600 - Null
dc.b 0 ; Command $8700 - Background color Pal 0 Color 0
dc.b 0 ; Command $8800 - Null
dc.b 0 ; Command $8900 - Null
dc.b $FF ; Command $8AFF - Hint timing $FF scanlines
dc.b 0 ; Command $8B00 - Ext Int off, VScroll full, HScroll full
dc.b $81 ; Command $8C81 - 40 cell mode, shadow/highlight off, no interlace
dc.b $37 ; Command $8D37 - HScroll Table Address $DC00
dc.b 0 ; Command $8E00 - Null
dc.b 1 ; Command $8F01 - VDP auto increment 1 byte
dc.b 1 ; Command $9001 - 64x32 cell scroll size
dc.b 0 ; Command $9100 - Window H left side, Base Point 0
dc.b 0 ; Command $9200 - Window V upside, Base Point 0
dc.b $FF ; Command $93FF - DMA Length Counter $FFFF
dc.b $FF ; Command $94FF - See above
dc.b 0 ; Command $9500 - DMA Source Address $0
dc.b 0 ; Command $9600 - See above
dc.b $80 ; Command $9780 - See above + VRAM fill mode
VDPInitValues_End:
dc.l vdpComm($0000,VRAM,DMA) ; value for VRAM write mode
; Z80 instructions (not the sound driver; that gets loaded later)
Z80StartupCodeBegin: ; loc_2CA:
if (*)+$26 < $10000
save
CPU Z80 ; start assembling Z80 code
phase 0 ; pretend we're at address 0
xor a ; clear a to 0
ld bc,((Z80_RAM_End-Z80_RAM)-zStartupCodeEndLoc)-1 ; prepare to loop this many times
ld de,zStartupCodeEndLoc+1 ; initial destination address
ld hl,zStartupCodeEndLoc ; initial source address
ld sp,hl ; set the address the stack starts at
ld (hl),a ; set first byte of the stack to 0
ldir ; loop to fill the stack (entire remaining available Z80 RAM) with 0
pop ix ; clear ix
pop iy ; clear iy
ld i,a ; clear i
ld r,a ; clear r
pop de ; clear de
pop hl ; clear hl
pop af ; clear af
ex af,af' ; swap af with af'
exx ; swap bc/de/hl with their shadow registers too
pop bc ; clear bc
pop de ; clear de
pop hl ; clear hl
pop af ; clear af
ld sp,hl ; clear sp
di ; clear iff1 (for interrupt handler)
im 1 ; interrupt handling mode = 1
ld (hl),0E9h ; replace the first instruction with a jump to itself
jp (hl) ; jump to the first instruction (to stay there forever)
zStartupCodeEndLoc:
dephase ; stop pretending
restore
padding off ; unfortunately our flags got reset so we have to set them again...
else ; due to an address range limitation I could work around but don't think is worth doing so:
message "Warning: using pre-assembled Z80 startup code."
dc.w $AF01,$D91F,$1127,$0021,$2600,$F977,$EDB0,$DDE1,$FDE1,$ED47,$ED4F,$D1E1,$F108,$D9C1,$D1E1,$F1F9,$F3ED,$5636,$E9E9
endif
Z80StartupCodeEnd:
dc.w $8104 ; value for VDP display mode
dc.w $8F02 ; value for VDP increment
dc.l vdpComm($0000,CRAM,WRITE) ; value for CRAM write mode
dc.l vdpComm($0000,VSRAM,WRITE) ; value for VSRAM write mode
PSGInitValues:
dc.b $9F,$BF,$DF,$FF ; values for PSG channel volumes
PSGInitValues_End:
; ===========================================================================
even
; loc_300:
GameProgram:
tst.w (VDP_control_port).l
; loc_306:
CheckSumCheck:
if gameRevision>0
move.w (VDP_control_port).l,d1
btst #1,d1
bne.s CheckSumCheck ; wait until DMA is completed
endif
btst #6,(HW_Expansion_Control).l
beq.s ChecksumTest
cmpi.l #'init',(Checksum_fourcc).w ; has checksum routine already run?
beq.w GameInit
; loc_328:
ChecksumTest:
if skipChecksumCheck=0 ; checksum code
movea.l #EndOfHeader,a0 ; start checking bytes after the header ($200)
movea.l #ROMEndLoc,a1 ; stop at end of ROM
move.l (a1),d0
moveq #0,d1
; loc_338:
ChecksumLoop:
add.w (a0)+,d1
cmp.l a0,d0
bhs.s ChecksumLoop
movea.l #Checksum,a1 ; read the checksum
cmp.w (a1),d1 ; compare correct checksum to the one in ROM
bne.w ChecksumError ; if they don't match, branch
endif
;checksum_good:
lea (System_Stack).w,a6
moveq #0,d7
move.w #bytesToLcnt($200),d6
- move.l d7,(a6)+
dbf d6,-
move.b (HW_Version).l,d0
andi.b #$C0,d0
move.b d0,(Graphics_Flags).w
move.l #'init',(Checksum_fourcc).w ; set flag so checksum won't be run again
; loc_370:
GameInit:
lea (RAM_Start&$FFFFFF).l,a6
moveq #0,d7
move.w #bytesToLcnt(System_Stack&$FFFF),d6
; loc_37C:
GameClrRAM:
move.l d7,(a6)+
dbf d6,GameClrRAM
bsr.w VDPSetupGame
bsr.w JmpTo_SoundDriverLoad
bsr.w JoypadInit
move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen
; loc_394:
MainGameLoop:
move.b (Game_Mode).w,d0
andi.w #$3C,d0
jsr GameModesArray(pc,d0.w)
bra.s MainGameLoop
; ===========================================================================
; loc_3A2:
GameModesArray: ;;
GameMode_SegaScreen: bra.w SegaScreen ; SEGA screen mode
GameMode_TitleScreen: bra.w TitleScreen ; Title screen mode
GameMode_Demo: bra.w Level ; Demo mode
GameMode_Level: bra.w Level ; Zone play mode
GameMode_SpecialStage: bra.w SpecialStage ; Special stage play mode
GameMode_ContinueScreen:bra.w ContinueScreen ; Continue mode
GameMode_2PResults: bra.w TwoPlayerResults ; 2P results mode
GameMode_2PLevelSelect: bra.w LevelSelectMenu2P ; 2P level select mode
GameMode_EndingSequence:bra.w JmpTo_EndingSequence ; End sequence mode
GameMode_OptionsMenu: bra.w OptionsMenu ; Options mode
GameMode_LevelSelect: bra.w LevelSelectMenu ; Level select mode
; ===========================================================================
if skipChecksumCheck=0 ; checksum error code
; loc_3CE:
ChecksumError:
move.l d1,-(sp)
bsr.w VDPSetupGame
move.l (sp)+,d1
move.l #vdpComm($0000,CRAM,WRITE),(VDP_control_port).l
moveq #$3F,d7
; loc_3E2:
Checksum_Red:
move.w #$E,(VDP_data_port).l
dbf d7,Checksum_Red
; loc_3EE:
ChecksumFailed_Loop:
bra.s ChecksumFailed_Loop
endif
; ===========================================================================
; loc_3F0:
LevelSelectMenu2P: ;;
jmp (MenuScreen).l
; ===========================================================================
; loc_3F6:
JmpTo_EndingSequence
jmp (EndingSequence).l
; ===========================================================================
; loc_3FC:
OptionsMenu: ;;
jmp (MenuScreen).l
; ===========================================================================
; loc_402:
LevelSelectMenu: ;;
jmp (MenuScreen).l
; ===========================================================================
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; vertical and horizontal interrupt handlers
; VERTICAL INTERRUPT HANDLER:
V_Int:
movem.l d0-a6,-(sp)
tst.b (Vint_routine).w
beq.w Vint_Lag
- move.w (VDP_control_port).l,d0
andi.w #8,d0
beq.s -
move.l #vdpComm($0000,VSRAM,WRITE),(VDP_control_port).l
move.l (Vscroll_Factor).w,(VDP_data_port).l
btst #6,(Graphics_Flags).w
beq.s +
move.w #$700,d0
- dbf d0,- ; wait here in a loop doing nothing for a while...
+
move.b (Vint_routine).w,d0
move.b #VintID_Lag,(Vint_routine).w
move.w #1,(Hint_flag).w
andi.w #$3E,d0
move.w Vint_SwitchTbl(pc,d0.w),d0
jsr Vint_SwitchTbl(pc,d0.w)
VintRet:
addq.l #1,(Vint_runcount).w
movem.l (sp)+,d0-a6
rte
; ===========================================================================
Vint_SwitchTbl: offsetTable
Vint_Lag_ptr offsetTableEntry.w Vint_Lag ; 0
Vint_SEGA_ptr: offsetTableEntry.w Vint_SEGA ; 2
Vint_Title_ptr: offsetTableEntry.w Vint_Title ; 4
Vint_Unused6_ptr: offsetTableEntry.w Vint_Unused6 ; 6
Vint_Level_ptr: offsetTableEntry.w Vint_Level ; 8
Vint_S2SS_ptr: offsetTableEntry.w Vint_S2SS ; $A
Vint_TitleCard_ptr: offsetTableEntry.w Vint_TitleCard ; $C
Vint_UnusedE_ptr: offsetTableEntry.w Vint_UnusedE ; $E
Vint_Pause_ptr: offsetTableEntry.w Vint_Pause ; $10
Vint_Fade_ptr: offsetTableEntry.w Vint_Fade ; $12
Vint_PCM_ptr: offsetTableEntry.w Vint_PCM ; $14
Vint_Menu_ptr: offsetTableEntry.w Vint_Menu ; $16
Vint_Ending_ptr: offsetTableEntry.w Vint_Ending ; $18
Vint_CtrlDMA_ptr: offsetTableEntry.w Vint_CtrlDMA ; $1A
; ===========================================================================
;VintSub0
Vint_Lag:
cmpi.b #GameModeID_TitleCard|GameModeID_Demo,(Game_Mode).w ; pre-level Demo Mode?
beq.s loc_4C4
cmpi.b #GameModeID_TitleCard|GameModeID_Level,(Game_Mode).w ; pre-level Zone play mode?
beq.s loc_4C4
cmpi.b #GameModeID_Demo,(Game_Mode).w ; Demo Mode?
beq.s loc_4C4
cmpi.b #GameModeID_Level,(Game_Mode).w ; Zone play mode?
beq.s loc_4C4
stopZ80 ; stop the Z80
bsr.w sndDriverInput ; give input to the sound driver
startZ80 ; start the Z80
bra.s VintRet
; ---------------------------------------------------------------------------
loc_4C4:
tst.b (Water_flag).w
beq.w Vint0_noWater
move.w (VDP_control_port).l,d0
btst #6,(Graphics_Flags).w
beq.s +
move.w #$700,d0
- dbf d0,- ; do nothing for a while...
+
move.w #1,(Hint_flag).w
stopZ80
tst.b (Water_fullscreen_flag).w
bne.s loc_526
dma68kToVDP Normal_palette,$0000,palette_line_size*4,CRAM
bra.s loc_54A
; ---------------------------------------------------------------------------
loc_526:
dma68kToVDP Underwater_palette,$0000,palette_line_size*4,CRAM
loc_54A:
move.w (Hint_counter_reserve).w,(a5)
move.w #$8200|(VRAM_Plane_A_Name_Table/$400),(VDP_control_port).l ; Set scroll A PNT base to $C000
bsr.w sndDriverInput
startZ80
bra.w VintRet
; ---------------------------------------------------------------------------
Vint0_noWater:
move.w (VDP_control_port).l,d0
move.l #vdpComm($0000,VSRAM,WRITE),(VDP_control_port).l
move.l (Vscroll_Factor).w,(VDP_data_port).l
btst #6,(Graphics_Flags).w
beq.s +
move.w #$700,d0
- dbf d0,- ; do nothing for a while...
+
move.w #1,(Hint_flag).w
move.w (Hint_counter_reserve).w,(VDP_control_port).l
move.w #$8200|(VRAM_Plane_A_Name_Table/$400),(VDP_control_port).l ; Set scroll A PNT base to $C000
move.l (Vscroll_Factor_P2).w,(Vscroll_Factor_P2_HInt).w
stopZ80
dma68kToVDP Sprite_Table,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM
bsr.w sndDriverInput
startZ80
bra.w VintRet
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; This subroutine copies the H scroll table buffer (in main RAM) to the H scroll
; table (in VRAM).
;VintSub2
Vint_SEGA:
bsr.w Do_ControllerPal
dma68kToVDP Horiz_Scroll_Buf,VRAM_Horiz_Scroll_Table,VRAM_Horiz_Scroll_Table_Size,VRAM
jsrto (SegaScr_VInt).l, JmpTo_SegaScr_VInt
tst.w (Demo_Time_left).w
beq.w + ; rts
subq.w #1,(Demo_Time_left).w
+
rts
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;VintSub14
Vint_PCM:
move.b (Vint_runcount+3).w,d0
andi.w #$F,d0
bne.s +
stopZ80
bsr.w ReadJoypads
startZ80
+
tst.w (Demo_Time_left).w
beq.w + ; rts
subq.w #1,(Demo_Time_left).w
+
rts
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;VintSub4
Vint_Title:
bsr.w Do_ControllerPal
bsr.w ProcessDPLC
tst.w (Demo_Time_left).w
beq.w + ; rts
subq.w #1,(Demo_Time_left).w
+
rts
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;VintSub6
Vint_Unused6:
bsr.w Do_ControllerPal
rts
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;VintSub10
Vint_Pause:
cmpi.b #GameModeID_SpecialStage,(Game_Mode).w ; Special Stage?
beq.w Vint_Pause_specialStage
;VintSub8
Vint_Level:
stopZ80
bsr.w ReadJoypads
tst.b (Teleport_timer).w
beq.s loc_6F8
lea (VDP_control_port).l,a5
tst.w (Game_paused).w
bne.w loc_748
subq.b #1,(Teleport_timer).w
bne.s +
move.b #0,(Teleport_flag).w
+
cmpi.b #$10,(Teleport_timer).w
blo.s loc_6F8
lea (VDP_data_port).l,a6
move.l #vdpComm($0000,CRAM,WRITE),(VDP_control_port).l
move.w #$EEE,d0
move.w #$1F,d1
- move.w d0,(a6)
dbf d1,-
move.l #vdpComm($0042,CRAM,WRITE),(VDP_control_port).l
move.w #$1F,d1
- move.w d0,(a6)
dbf d1,-
bra.s loc_748
; ---------------------------------------------------------------------------
loc_6F8:
tst.b (Water_fullscreen_flag).w
bne.s loc_724
dma68kToVDP Normal_palette,$0000,palette_line_size*4,CRAM
bra.s loc_748
; ---------------------------------------------------------------------------
loc_724:
dma68kToVDP Underwater_palette,$0000,palette_line_size*4,CRAM
loc_748:
move.w (Hint_counter_reserve).w,(a5)
move.w #$8200|(VRAM_Plane_A_Name_Table/$400),(VDP_control_port).l ; Set scroll A PNT base to $C000
dma68kToVDP Horiz_Scroll_Buf,VRAM_Horiz_Scroll_Table,VRAM_Horiz_Scroll_Table_Size,VRAM
dma68kToVDP Sprite_Table,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM
bsr.w ProcessDMAQueue
bsr.w sndDriverInput
startZ80
movem.l (Camera_RAM).w,d0-d7
movem.l d0-d7,(Camera_RAM_copy).w
movem.l (Camera_X_pos_P2).w,d0-d7
movem.l d0-d7,(Camera_P2_copy).w
movem.l (Scroll_flags).w,d0-d3
movem.l d0-d3,(Scroll_flags_copy).w
move.l (Vscroll_Factor_P2).w,(Vscroll_Factor_P2_HInt).w
cmpi.b #$5C,(Hint_counter_reserve+1).w
bhs.s Do_Updates
move.b #1,(Do_Updates_in_H_int).w
rts
; ---------------------------------------------------------------------------
; Subroutine to run a demo for an amount of time
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_7E6: Demo_Time:
Do_Updates:
jsrto (LoadTilesAsYouMove).l, JmpTo_LoadTilesAsYouMove
jsr (HudUpdate).l
bsr.w ProcessDPLC2
tst.w (Demo_Time_left).w ; is there time left on the demo?
beq.w + ; if not, branch
subq.w #1,(Demo_Time_left).w ; subtract 1 from time left
+
rts
; End of function Do_Updates
; ---------------------------------------------------------------------------
;Vint10_specialStage
Vint_Pause_specialStage:
stopZ80
bsr.w ReadJoypads
jsr (sndDriverInput).l
tst.b (SS_Last_Alternate_HorizScroll_Buf).w
beq.s loc_84A
dma68kToVDP SS_Horiz_Scroll_Buf_2,VRAM_SS_Horiz_Scroll_Table,VRAM_SS_Horiz_Scroll_Table_Size,VRAM
bra.s loc_86E
; ---------------------------------------------------------------------------
loc_84A:
dma68kToVDP SS_Horiz_Scroll_Buf_1,VRAM_SS_Horiz_Scroll_Table,VRAM_SS_Horiz_Scroll_Table_Size,VRAM
loc_86E:
startZ80
rts
; ========================================================================>>>
;VintSubA
Vint_S2SS:
stopZ80
bsr.w ReadJoypads
bsr.w SSSet_VScroll
dma68kToVDP Normal_palette,$0000,palette_line_size*4,CRAM
dma68kToVDP SS_Sprite_Table,VRAM_SS_Sprite_Attribute_Table,VRAM_SS_Sprite_Attribute_Table_Size,VRAM
tst.b (SS_Alternate_HorizScroll_Buf).w
beq.s loc_906
dma68kToVDP SS_Horiz_Scroll_Buf_2,VRAM_SS_Horiz_Scroll_Table,VRAM_SS_Horiz_Scroll_Table_Size,VRAM
bra.s loc_92A
; ---------------------------------------------------------------------------
loc_906:
dma68kToVDP SS_Horiz_Scroll_Buf_1,VRAM_SS_Horiz_Scroll_Table,VRAM_SS_Horiz_Scroll_Table_Size,VRAM
loc_92A:
tst.b (SSTrack_Orientation).w ; Is the current track frame flipped?
beq.s ++ ; Branch if not
moveq #0,d0
move.b (SSTrack_drawing_index).w,d0 ; Get drawing position
cmpi.b #4,d0 ; Have we finished drawing and streaming track frame?
bge.s ++ ; Branch if yes (nothing to draw)
add.b d0,d0 ; Convert to index
tst.b (SS_Alternate_PNT).w ; [(SSTrack_drawing_index) * 2] = subroutine
beq.s + ; Branch if not using the alternate Plane A name table
addi_.w #8,d0 ; ([(SSTrack_drawing_index) * 2] + 8) = subroutine
+
move.w SS_PNTA_Transfer_Table(pc,d0.w),d0
jsr SS_PNTA_Transfer_Table(pc,d0.w)
+
bsr.w SSRun_Animation_Timers
addi_.b #1,(SSTrack_drawing_index).w ; Run track timer
move.b (SSTrack_drawing_index).w,d0 ; Get new timer value
cmp.b d1,d0 ; Is it less than the player animation timer?
blt.s +++ ; Branch if so
move.b #0,(SSTrack_drawing_index).w ; Start drawing new frame
lea (VDP_control_port).l,a6
tst.b (SS_Alternate_PNT).w ; Are we using the alternate address for plane A?
beq.s + ; Branch if not
move.w #$8200|(VRAM_SS_Plane_A_Name_Table1/$400),(a6) ; Set PNT A base to $C000
bra.s ++
; ===========================================================================
;off_97A
SS_PNTA_Transfer_Table: offsetTable
offsetTableEntry.w loc_A50 ; 0
offsetTableEntry.w loc_A76 ; 1
offsetTableEntry.w loc_A9C ; 2
offsetTableEntry.w loc_AC2 ; 3
offsetTableEntry.w loc_9B8 ; 4
offsetTableEntry.w loc_9DE ; 5
offsetTableEntry.w loc_A04 ; 6
offsetTableEntry.w loc_A2A ; 7
; ===========================================================================
+
move.w #$8200|(VRAM_SS_Plane_A_Name_Table2/$400),(a6) ; Set PNT A base to $8000
+
eori.b #1,(SS_Alternate_PNT).w ; Toggle flag
+
bsr.w ProcessDMAQueue
jsr (sndDriverInput).l
startZ80
bsr.w ProcessDPLC2
tst.w (Demo_Time_left).w
beq.w + ; rts
subq.w #1,(Demo_Time_left).w
+
rts
; ---------------------------------------------------------------------------
; (!)
; Each of these functions copies one fourth of pattern name table A into VRAM
; from a buffer in main RAM. $700 bytes are copied each frame, with the target
; are in VRAM depending on the current drawing position.
loc_9B8:
dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table1 + 0 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM
rts
; ---------------------------------------------------------------------------
loc_9DE:
dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table1 + 1 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM
rts
; ---------------------------------------------------------------------------
loc_A04:
dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table1 + 2 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM
rts
; ---------------------------------------------------------------------------
loc_A2A:
dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table1 + 3 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM
rts
; ---------------------------------------------------------------------------
loc_A50:
dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table2 + 0 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM
rts
; ---------------------------------------------------------------------------
loc_A76:
dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table2 + 1 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM
rts
; ---------------------------------------------------------------------------
loc_A9C:
dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table2 + 2 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM
rts
; ---------------------------------------------------------------------------
loc_AC2:
dma68kToVDP PNT_Buffer,VRAM_SS_Plane_A_Name_Table2 + 3 * (PNT_Buffer_End-PNT_Buffer),PNT_Buffer_End-PNT_Buffer,VRAM
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_AE8
SSSet_VScroll:
move.w (VDP_control_port).l,d0
move.l #vdpComm($0000,VSRAM,WRITE),(VDP_control_port).l
move.l (Vscroll_Factor).w,(VDP_data_port).l
rts
; End of function SSSet_VScroll
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_B02
SSRun_Animation_Timers:
move.w (SS_Cur_Speed_Factor).w,d0 ; Get current speed factor
cmp.w (SS_New_Speed_Factor).w,d0 ; Has the speed factor changed?
beq.s + ; Branch if yes
move.l (SS_New_Speed_Factor).w,(SS_Cur_Speed_Factor).w ; Save new speed factor
move.b #0,(SSTrack_duration_timer).w ; Reset timer
+
subi_.b #1,(SSTrack_duration_timer).w ; Run track timer
bgt.s + ; Branch if not expired yet
lea (SSAnim_Base_Duration).l,a0
move.w (SS_Cur_Speed_Factor).w,d0 ; The current speed factor is an index
lsr.w #1,d0
move.b (a0,d0.w),d1
move.b d1,(SS_player_anim_frame_timer).w ; New player animation length (later halved)
move.b d1,(SSTrack_duration_timer).w ; New track timer
subq.b #1,(SS_player_anim_frame_timer).w ; Subtract one
rts
; ---------------------------------------------------------------------------
+
move.b (SS_player_anim_frame_timer).w,d1 ; Get current player animatino length
addq.b #1,d1 ; Increase it
rts
; End of function SSRun_Animation_Timers
; ===========================================================================
;byte_B46
SSAnim_Base_Duration:
dc.b 60
dc.b 30 ; 1
dc.b 15 ; 2
dc.b 10 ; 3
dc.b 8 ; 4
dc.b 6 ; 5
dc.b 5 ; 6
dc.b 0 ; 7
; ===========================================================================
;VintSub1A
Vint_CtrlDMA:
stopZ80
jsr (ProcessDMAQueue).l
startZ80
rts
; ===========================================================================
;VintSubC
Vint_TitleCard:
stopZ80
bsr.w ReadJoypads
tst.b (Water_fullscreen_flag).w
bne.s loc_BB2
dma68kToVDP Normal_palette,$0000,palette_line_size*4,CRAM
bra.s loc_BD6
; ---------------------------------------------------------------------------
loc_BB2:
dma68kToVDP Underwater_palette,$0000,palette_line_size*4,CRAM
loc_BD6:
move.w (Hint_counter_reserve).w,(a5)
dma68kToVDP Horiz_Scroll_Buf,VRAM_Horiz_Scroll_Table,VRAM_Horiz_Scroll_Table_Size,VRAM
dma68kToVDP Sprite_Table,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM
bsr.w ProcessDMAQueue
jsr (DrawLevelTitleCard).l
jsr (sndDriverInput).l
startZ80
movem.l (Camera_RAM).w,d0-d7
movem.l d0-d7,(Camera_RAM_copy).w
movem.l (Scroll_flags).w,d0-d1
movem.l d0-d1,(Scroll_flags_copy).w
move.l (Vscroll_Factor_P2).w,(Vscroll_Factor_P2_HInt).w
bsr.w ProcessDPLC
rts
; ===========================================================================
;VintSubE
Vint_UnusedE:
bsr.w Do_ControllerPal
addq.b #1,(VIntSubE_RunCount).w
move.b #VintID_UnusedE,(Vint_routine).w
rts
; ===========================================================================
;VintSub12
Vint_Fade:
bsr.w Do_ControllerPal
move.w (Hint_counter_reserve).w,(a5)
bra.w ProcessDPLC
; ===========================================================================
;VintSub18
Vint_Ending:
stopZ80
bsr.w ReadJoypads
dma68kToVDP Normal_palette,$0000,palette_line_size*4,CRAM
dma68kToVDP Sprite_Table,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM
dma68kToVDP Horiz_Scroll_Buf,VRAM_Horiz_Scroll_Table,VRAM_Horiz_Scroll_Table_Size,VRAM
bsr.w ProcessDMAQueue
bsr.w sndDriverInput
movem.l (Camera_RAM).w,d0-d7
movem.l d0-d7,(Camera_RAM_copy).w
movem.l (Scroll_flags).w,d0-d3
movem.l d0-d3,(Scroll_flags_copy).w
jsrto (LoadTilesAsYouMove).l, JmpTo_LoadTilesAsYouMove
startZ80
move.w (Ending_VInt_Subrout).w,d0
beq.s + ; rts
clr.w (Ending_VInt_Subrout).w
move.w off_D3C-2(pc,d0.w),d0
jsr off_D3C(pc,d0.w)
+
rts
; ===========================================================================
off_D3C: offsetTable
offsetTableEntry.w (+) ; 1
offsetTableEntry.w (++) ; 2
; ===========================================================================
+
dmaFillVRAM 0,VRAM_EndSeq_Plane_A_Name_Table,VRAM_EndSeq_Plane_Table_Size ; VRAM Fill $C000 with $2000 zeros
rts
; ---------------------------------------------------------------------------
+
dmaFillVRAM 0,VRAM_EndSeq_Plane_B_Name_Table2,VRAM_EndSeq_Plane_Table_Size
dmaFillVRAM 0,VRAM_EndSeq_Plane_A_Name_Table,VRAM_EndSeq_Plane_Table_Size
lea (VDP_control_port).l,a6
move.w #$8B00,(a6) ; EXT-INT off, V scroll by screen, H scroll by screen
move.w #$8400|(VRAM_EndSeq_Plane_B_Name_Table2/$2000),(a6) ; PNT B base: $4000
move.w #$9011,(a6) ; Scroll table size: 64x64
lea (Chunk_Table).l,a1
move.l #vdpComm(VRAM_EndSeq_Plane_A_Name_Table + planeLocH40($16,$21),VRAM,WRITE),d0 ;$50AC0003
moveq #$16,d1
moveq #$E,d2
jsrto (PlaneMapToVRAM_H40).l, PlaneMapToVRAM_H40
rts
; ===========================================================================
;VintSub16
Vint_Menu:
stopZ80
bsr.w ReadJoypads
dma68kToVDP Normal_palette,$0000,palette_line_size*4,CRAM
dma68kToVDP Sprite_Table,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM
dma68kToVDP Horiz_Scroll_Buf,VRAM_Horiz_Scroll_Table,VRAM_Horiz_Scroll_Table_Size,VRAM
bsr.w ProcessDMAQueue
bsr.w sndDriverInput
startZ80
bsr.w ProcessDPLC
tst.w (Demo_Time_left).w
beq.w + ; rts
subq.w #1,(Demo_Time_left).w
+
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_E98
Do_ControllerPal:
stopZ80
bsr.w ReadJoypads
tst.b (Water_fullscreen_flag).w
bne.s loc_EDA
dma68kToVDP Normal_palette,$0000,palette_line_size*4,CRAM
bra.s loc_EFE
; ---------------------------------------------------------------------------
loc_EDA:
dma68kToVDP Underwater_palette,$0000,palette_line_size*4,CRAM
loc_EFE:
dma68kToVDP Sprite_Table,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM
dma68kToVDP Horiz_Scroll_Buf,VRAM_Horiz_Scroll_Table,VRAM_Horiz_Scroll_Table_Size,VRAM
bsr.w sndDriverInput
startZ80
rts
; End of function sub_E98
; ||||||||||||||| E N D O F V - I N T |||||||||||||||||||||||||||||||||||
; ===========================================================================
; Start of H-INT code
H_Int:
tst.w (Hint_flag).w
beq.w +
tst.w (Two_player_mode).w
beq.w PalToCRAM
move.w #0,(Hint_flag).w
move.l a5,-(sp)
move.l d0,-(sp)
- move.w (VDP_control_port).l,d0 ; loop start: Make sure V_BLANK is over
andi.w #4,d0
beq.s - ; loop end
move.w (VDP_Reg1_val).w,d0
andi.b #$BF,d0
move.w d0,(VDP_control_port).l ; Display disable
move.w #$8200|(VRAM_Plane_A_Name_Table_2P/$400),(VDP_control_port).l ; PNT A base: $A000
move.l #vdpComm($0000,VSRAM,WRITE),(VDP_control_port).l
move.l (Vscroll_Factor_P2_HInt).w,(VDP_data_port).l
stopZ80
dma68kToVDP Sprite_Table_2,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM
startZ80
- move.w (VDP_control_port).l,d0
andi.w #4,d0
beq.s -
move.w (VDP_Reg1_val).w,d0
ori.b #$40,d0
move.w d0,(VDP_control_port).l ; Display enable
move.l (sp)+,d0
movea.l (sp)+,a5
+
rte
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; game code
; ---------------------------------------------------------------------------
; loc_1000:
PalToCRAM:
move #$2700,sr
move.w #0,(Hint_flag).w
movem.l a0-a1,-(sp)
lea (VDP_data_port).l,a1
lea (Underwater_palette).w,a0 ; load palette from RAM
move.l #vdpComm($0000,CRAM,WRITE),4(a1) ; set VDP to write to CRAM address $00
rept 32
move.l (a0)+,(a1) ; move palette to CRAM (all 64 colors at once)
endm
move.w #$8ADF,4(a1) ; Write %1101 %1111 to register 10 (interrupt every 224th line)
movem.l (sp)+,a0-a1
tst.b (Do_Updates_in_H_int).w
bne.s loc_1072
rte
; ===========================================================================
loc_1072:
clr.b (Do_Updates_in_H_int).w
movem.l d0-a6,-(sp)
bsr.w Do_Updates
movem.l (sp)+,d0-a6
rte
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Input our music/sound selection to the sound driver.
sndDriverInput:
lea (Music_to_play&$00FFFFFF).l,a0
lea (Z80_RAM+zComRange).l,a1 ; $A01B80
cmpi.b #$80,zAbsVar.QueueToPlay-zComRange(a1) ; If this (zReadyFlag) isn't $80, the driver is processing a previous sound request.
bne.s loc_10C4 ; So we'll wait until at least the next frame before putting anything in there.
_move.b 0(a0),d0
beq.s loc_10A4
_clr.b 0(a0)
bra.s loc_10AE
; ---------------------------------------------------------------------------
loc_10A4:
move.b 4(a0),d0 ; If there was something in Music_to_play_2, check what that was. Else, just go to the loop.
beq.s loc_10C4
clr.b 4(a0)
loc_10AE: ; Check that the sound is not FE or FF
move.b d0,d1 ; If it is, we need to put it in $A01B83 as $7F or $80 respectively
subi.b #MusID_Pause,d1
bcs.s loc_10C0
addi.b #$7F,d1
move.b d1,zAbsVar.StopMusic-zComRange(a1)
bra.s loc_10C4
; ---------------------------------------------------------------------------
loc_10C0:
move.b d0,zAbsVar.QueueToPlay-zComRange(a1)
loc_10C4:
moveq #4-1,d1
; FFE4 (Music_to_play_2) goes to 1B8C (zMusicToPlay),
- move.b 1(a0,d1.w),d0 ; FFE3 (unk_FFE3) goes to 1B8B, (unknown)
beq.s + ; FFE2 (SFX_to_play_2) goes to 1B8A (zSFXToPlay2),
tst.b zAbsVar.SFXToPlay-zComRange(a1,d1.w) ; FFE1 (SFX_to_play) goes to 1B89 (zSFXToPlay).
bne.s +
clr.b 1(a0,d1.w)
move.b d0,zAbsVar.SFXToPlay-zComRange(a1,d1.w)
+
dbf d1,-
rts
; End of function sndDriverInput
if ~~removeJmpTos
; sub_10E0:
JmpTo_LoadTilesAsYouMove
jmp (LoadTilesAsYouMove).l
JmpTo_SegaScr_VInt
jmp (SegaScr_VInt).l
align 4
endif
; ---------------------------------------------------------------------------
; Subroutine to initialize joypads
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_10EC:
JoypadInit:
stopZ80
moveq #$40,d0
move.b d0,(HW_Port_1_Control).l ; init port 1 (joypad 1)
move.b d0,(HW_Port_2_Control).l ; init port 2 (joypad 2)
move.b d0,(HW_Expansion_Control).l ; init port 3 (extra)
startZ80
rts
; End of function JoypadInit
; ---------------------------------------------------------------------------
; Subroutine to read joypad input, and send it to the RAM
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_111C:
ReadJoypads:
lea (Ctrl_1).w,a0 ; address where joypad states are written
lea (HW_Port_1_Data).l,a1 ; first joypad port
bsr.s Joypad_Read ; do the first joypad
addq.w #2,a1 ; do the second joypad
; End of function ReadJoypads
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_112A:
Joypad_Read:
move.b #0,(a1)
nop
nop
move.b (a1),d0
lsl.b #2,d0
andi.b #$C0,d0
move.b #$40,(a1)
nop
nop
move.b (a1),d1
andi.b #$3F,d1
or.b d1,d0
not.b d0
move.b (a0),d1
eor.b d0,d1
move.b d0,(a0)+
and.b d0,d1
move.b d1,(a0)+
rts
; End of function Joypad_Read
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_1158:
VDPSetupGame:
lea (VDP_control_port).l,a0
lea (VDP_data_port).l,a1
lea (VDPSetupArray).l,a2
moveq #bytesToWcnt(VDPSetupArray_End-VDPSetupArray),d7
; loc_116C:
VDP_Loop:
move.w (a2)+,(a0)
dbf d7,VDP_Loop ; set the VDP registers
move.w (VDPSetupArray+2).l,d0
move.w d0,(VDP_Reg1_val).w
move.w #$8ADF,(Hint_counter_reserve).w ; H-INT every 224th scanline
moveq #0,d0
move.l #vdpComm($0000,VSRAM,WRITE),(VDP_control_port).l
move.w d0,(a1)
move.w d0,(a1)
move.l #vdpComm($0000,CRAM,WRITE),(VDP_control_port).l
move.w #bytesToWcnt(palette_line_size*4),d7
; loc_11A0:
VDP_ClrCRAM:
move.w d0,(a1)
dbf d7,VDP_ClrCRAM
clr.l (Vscroll_Factor).w
clr.l (unk_F61A).w
move.l d1,-(sp)
dmaFillVRAM 0,$0000,$10000 ; fill entire VRAM with 0
move.l (sp)+,d1
rts
; End of function VDPSetupGame
; ===========================================================================
; word_11E2:
VDPSetupArray:
dc.w $8004 ; H-INT disabled
dc.w $8134 ; Genesis mode, DMA enabled, VBLANK-INT enabled
dc.w $8200|(VRAM_Plane_A_Name_Table/$400) ; PNT A base: $C000
dc.w $8328 ; PNT W base: $A000
dc.w $8400|(VRAM_Plane_B_Name_Table/$2000) ; PNT B base: $E000
dc.w $8500|(VRAM_Sprite_Attribute_Table/$200) ; Sprite attribute table base: $F800
dc.w $8600
dc.w $8700 ; Background palette/color: 0/0
dc.w $8800
dc.w $8900
dc.w $8A00 ; H-INT every scanline
dc.w $8B00 ; EXT-INT off, V scroll by screen, H scroll by screen
dc.w $8C81 ; H res 40 cells, no interlace, S/H disabled
dc.w $8D00|(VRAM_Horiz_Scroll_Table/$400) ; H scroll table base: $FC00
dc.w $8E00
dc.w $8F02 ; VRAM pointer increment: $0002
dc.w $9001 ; Scroll table size: 64x32
dc.w $9100 ; Disable window
dc.w $9200 ; Disable window
VDPSetupArray_End:
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_1208:
ClearScreen:
stopZ80
dmaFillVRAM 0,$0000,$40 ; Fill first $40 bytes of VRAM with 0
dmaFillVRAM 0,VRAM_Plane_A_Name_Table,VRAM_Plane_Table_Size ; Clear Plane A pattern name table
dmaFillVRAM 0,VRAM_Plane_B_Name_Table,VRAM_Plane_Table_Size ; Clear Plane B pattern name table
tst.w (Two_player_mode).w
beq.s +
dmaFillVRAM 0,VRAM_Plane_A_Name_Table_2P,VRAM_Plane_Table_Size
+
clr.l (Vscroll_Factor).w
clr.l (unk_F61A).w
; Bug: These '+4's shouldn't be here; clearRAM accidentally clears an additional 4 bytes
clearRAM Sprite_Table,Sprite_Table_End+4
clearRAM Horiz_Scroll_Buf,Horiz_Scroll_Buf_End+4
startZ80
rts
; End of function ClearScreen
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; JumpTo load the sound driver
; sub_130A:
JmpTo_SoundDriverLoad
nop
jmp (SoundDriverLoad).l
; End of function JmpTo_SoundDriverLoad
; ===========================================================================
; unused mostly-leftover subroutine to load the sound driver
; SoundDriverLoadS1:
move.w #$100,(Z80_Bus_Request).l ; stop the Z80
move.w #$100,(Z80_Reset).l ; reset the Z80
lea (Z80_RAM).l,a1
move.b #$F3,(a1)+ ; di
move.b #$F3,(a1)+ ; di
move.b #$C3,(a1)+ ; jp
move.b #0,(a1)+ ; jp address low byte
move.b #0,(a1)+ ; jp address high byte
move.w #0,(Z80_Reset).l
nop
nop
nop
nop
move.w #$100,(Z80_Reset).l ; reset the Z80
move.w #0,(Z80_Bus_Request).l ; start the Z80
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; If Music_to_play is clear, move d0 into Music_to_play,
; else move d0 into Music_to_play_2.
; sub_135E:
PlayMusic:
tst.b (Music_to_play).w
bne.s +
move.b d0,(Music_to_play).w
rts
+
move.b d0,(Music_to_play_2).w
rts
; End of function PlayMusic
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_1370
PlaySound:
move.b d0,(SFX_to_play).w
rts
; End of function PlaySound
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; play a sound in alternating speakers (as in the ring collection sound)
; sub_1376:
PlaySoundStereo:
move.b d0,(SFX_to_play_2).w
rts
; End of function PlaySoundStereo
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; play a sound if the source is onscreen
; sub_137C:
PlaySoundLocal:
tst.b render_flags(a0)
bpl.s + ; rts
move.b d0,(SFX_to_play).w
+
rts
; End of function PlaySoundLocal
; ---------------------------------------------------------------------------
; Subroutine to pause the game
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_1388:
PauseGame:
nop
tst.b (Life_count).w ; do you have any lives left?
beq.w Unpause ; if not, branch
tst.w (Game_paused).w ; is game already paused?
bne.s + ; if yes, branch
move.b (Ctrl_1_Press).w,d0 ; is Start button pressed?
or.b (Ctrl_2_Press).w,d0 ; (either player)
andi.b #button_start_mask,d0
beq.s Pause_DoNothing ; if not, branch
+
move.w #1,(Game_paused).w ; freeze time
move.b #MusID_Pause,(Music_to_play).w ; pause music
; loc_13B2:
Pause_Loop:
move.b #VintID_Pause,(Vint_routine).w
bsr.w WaitForVint
tst.b (Slow_motion_flag).w ; is slow-motion cheat on?
beq.s Pause_ChkStart ; if not, branch
btst #button_A,(Ctrl_1_Press).w ; is button A pressed?
beq.s Pause_ChkBC ; if not, branch
move.b #GameModeID_TitleScreen,(Game_Mode).w ; => TitleScreen
nop
bra.s Pause_Resume
; ===========================================================================
; loc_13D4:
Pause_ChkBC:
btst #button_B,(Ctrl_1_Held).w ; is button B pressed?
bne.s Pause_SlowMo ; if yes, branch
btst #button_C,(Ctrl_1_Press).w ; is button C pressed?
bne.s Pause_SlowMo ; if yes, branch
; loc_13E4:
Pause_ChkStart:
move.b (Ctrl_1_Press).w,d0 ; is Start button pressed?
or.b (Ctrl_2_Press).w,d0 ; (either player)
andi.b #button_start_mask,d0
beq.s Pause_Loop ; if not, branch
; loc_13F2:
Pause_Resume:
move.b #MusID_Unpause,(Music_to_play).w
; loc_13F8:
Unpause:
move.w #0,(Game_paused).w
; return_13FE:
Pause_DoNothing:
rts
; ===========================================================================
; loc_1400:
Pause_SlowMo:
move.w #1,(Game_paused).w
move.b #MusID_Unpause,(Music_to_play).w
rts
; End of function PauseGame
; ---------------------------------------------------------------------------
; Subroutine to transfer a plane map to VRAM
; ---------------------------------------------------------------------------
; control register:
; CD1 CD0 A13 A12 A11 A10 A09 A08 (D31-D24)
; A07 A06 A05 A04 A03 A02 A01 A00 (D23-D16)
; ? ? ? ? ? ? ? ? (D15-D8)
; CD5 CD4 CD3 CD2 ? ? A15 A14 (D7-D0)
;
; A00-A15 - address
; CD0-CD3 - code
; CD4 - 1 if VRAM copy DMA mode. 0 otherwise.
; CD5 - DMA operation
;
; Bits CD3-CD0:
; 0000 - VRAM read
; 0001 - VRAM write
; 0011 - CRAM write
; 0100 - VSRAM read
; 0101 - VSRAM write
; 1000 - CRAM read
;
; d0 = control register
; d1 = width
; d2 = heigth
; a1 = source address
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_140E: ShowVDPGraphics: PlaneMapToVRAM:
PlaneMapToVRAM_H40:
lea (VDP_data_port).l,a6
move.l #vdpCommDelta(planeLocH40(0,1)),d4 ; $800000
- move.l d0,VDP_control_port-VDP_data_port(a6) ; move d0 to VDP_control_port
move.w d1,d3
- move.w (a1)+,(a6) ; from source address to destination in VDP
dbf d3,- ; next tile
add.l d4,d0 ; increase destination address by $80 (1 line)
dbf d2,-- ; next line
rts
; End of function PlaneMapToVRAM_H40
; ---------------------------------------------------------------------------
; Alternate subroutine to transfer a plane map to VRAM
; (used for Special Stage background)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_142E: ShowVDPGraphics2: PlaneMapToVRAM2:
PlaneMapToVRAM_H80_SpecialStage:
lea (VDP_data_port).l,a6
move.l #vdpCommDelta(planeLocH80(0,1)),d4 ; $1000000
- move.l d0,VDP_control_port-VDP_data_port(a6)
move.w d1,d3
- move.w (a1)+,(a6)
dbf d3,-
add.l d4,d0
dbf d2,--
rts
; End of function PlaneMapToVRAM_H80_SpecialStage
; ---------------------------------------------------------------------------
; Subroutine for queueing VDP commands (seems to only queue transfers to VRAM),
; to be issued the next time ProcessDMAQueue is called.
; Can be called a maximum of 18 times before the buffer needs to be cleared
; by issuing the commands (this subroutine DOES check for overflow)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_144E: DMA_68KtoVRAM: QueueCopyToVRAM: QueueVDPCommand: Add_To_DMA_Queue:
QueueDMATransfer:
movea.l (VDP_Command_Buffer_Slot).w,a1
cmpa.w #VDP_Command_Buffer_Slot,a1
beq.s QueueDMATransfer_Done ; return if there's no more room in the buffer
; piece together some VDP commands and store them for later...
move.w #$9300,d0 ; command to specify DMA transfer length & $00FF
move.b d3,d0
move.w d0,(a1)+ ; store command
move.w #$9400,d0 ; command to specify DMA transfer length & $FF00
lsr.w #8,d3
move.b d3,d0
move.w d0,(a1)+ ; store command
move.w #$9500,d0 ; command to specify source address & $0001FE
lsr.l #1,d1
move.b d1,d0
move.w d0,(a1)+ ; store command
move.w #$9600,d0 ; command to specify source address & $01FE00
lsr.l #8,d1
move.b d1,d0
move.w d0,(a1)+ ; store command
move.w #$9700,d0 ; command to specify source address & $FE0000
lsr.l #8,d1
;andi.b #$7F,d1 ; this instruction safely allows source to be in RAM; S3K added this
move.b d1,d0
move.w d0,(a1)+ ; store command
andi.l #$FFFF,d2 ; command to specify destination address and begin DMA
lsl.l #2,d2
lsr.w #2,d2
swap d2
ori.l #vdpComm($0000,VRAM,DMA),d2 ; set bits to specify VRAM transfer
move.l d2,(a1)+ ; store command
move.l a1,(VDP_Command_Buffer_Slot).w ; set the next free slot address
cmpa.w #VDP_Command_Buffer_Slot,a1
beq.s QueueDMATransfer_Done ; return if there's no more room in the buffer
move.w #0,(a1) ; put a stop token at the end of the used part of the buffer
; return_14AA:
QueueDMATransfer_Done:
rts
; End of function QueueDMATransfer
; ---------------------------------------------------------------------------
; Subroutine for issuing all VDP commands that were queued
; (by earlier calls to QueueDMATransfer)
; Resets the queue when it's done
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_14AC: CopyToVRAM: IssueVDPCommands: Process_DMA: Process_DMA_Queue:
ProcessDMAQueue:
lea (VDP_control_port).l,a5
lea (VDP_Command_Buffer).w,a1
; loc_14B6:
ProcessDMAQueue_Loop:
move.w (a1)+,d0
beq.s ProcessDMAQueue_Done ; branch if we reached a stop token
; issue a set of VDP commands...
move.w d0,(a5) ; transfer length
move.w (a1)+,(a5) ; transfer length
move.w (a1)+,(a5) ; source address
move.w (a1)+,(a5) ; source address
move.w (a1)+,(a5) ; source address
move.w (a1)+,(a5) ; destination
move.w (a1)+,(a5) ; destination
cmpa.w #VDP_Command_Buffer_Slot,a1
bne.s ProcessDMAQueue_Loop ; loop if we haven't reached the end of the buffer
; loc_14CE:
ProcessDMAQueue_Done:
move.w #0,(VDP_Command_Buffer).w
move.l #VDP_Command_Buffer,(VDP_Command_Buffer_Slot).w
rts
; End of function ProcessDMAQueue
; ---------------------------------------------------------------------------
; START OF NEMESIS DECOMPRESSOR
; For format explanation see http://info.sonicretro.org/Nemesis_compression
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Nemesis decompression to VRAM
; sub_14DE: NemDecA:
NemDec:
movem.l d0-a1/a3-a5,-(sp)
lea (NemDec_WriteAndStay).l,a3 ; write all data to the same location
lea (VDP_data_port).l,a4 ; specifically, to the VDP data port
bra.s NemDecMain
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Nemesis decompression to RAM
; input: a4 = starting address of destination
; sub_14F0: NemDecB:
NemDecToRAM:
movem.l d0-a1/a3-a5,-(sp)
lea (NemDec_WriteAndAdvance).l,a3 ; advance to the next location after each write
; sub_14FA:
NemDecMain:
lea (Decomp_Buffer).w,a1
move.w (a0)+,d2
lsl.w #1,d2
bcc.s +
adda.w #NemDec_WriteAndStay_XOR-NemDec_WriteAndStay,a3
+ lsl.w #2,d2
movea.w d2,a5
moveq #8,d3
moveq #0,d2
moveq #0,d4
bsr.w NemDecPrepare
move.b (a0)+,d5
asl.w #8,d5
move.b (a0)+,d5
move.w #$10,d6
bsr.s NemDecRun
movem.l (sp)+,d0-a1/a3-a5
rts
; End of function NemDec
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; part of the Nemesis decompressor
; sub_1528:
NemDecRun:
move.w d6,d7
subq.w #8,d7
move.w d5,d1
lsr.w d7,d1
cmpi.b #-4,d1
bhs.s loc_1574
andi.w #$FF,d1
add.w d1,d1
move.b (a1,d1.w),d0
ext.w d0
sub.w d0,d6
cmpi.w #9,d6
bhs.s +
addq.w #8,d6
asl.w #8,d5
move.b (a0)+,d5
+ move.b 1(a1,d1.w),d1
move.w d1,d0
andi.w #$F,d1
andi.w #$F0,d0
loc_155E:
lsr.w #4,d0
loc_1560:
lsl.l #4,d4
or.b d1,d4
subq.w #1,d3
bne.s NemDec_WriteIter_Part2
jmp (a3) ; dynamic jump! to NemDec_WriteAndStay, NemDec_WriteAndAdvance, NemDec_WriteAndStay_XOR, or NemDec_WriteAndAdvance_XOR
; ===========================================================================
; loc_156A:
NemDec_WriteIter:
moveq #0,d4
moveq #8,d3
; loc_156E:
NemDec_WriteIter_Part2:
dbf d0,loc_1560
bra.s NemDecRun
; ===========================================================================
loc_1574:
subq.w #6,d6
cmpi.w #9,d6
bhs.s +
addq.w #8,d6
asl.w #8,d5
move.b (a0)+,d5
+
subq.w #7,d6
move.w d5,d1
lsr.w d6,d1
move.w d1,d0
andi.w #$F,d1
andi.w #$70,d0
cmpi.w #9,d6
bhs.s loc_155E
addq.w #8,d6
asl.w #8,d5
move.b (a0)+,d5
bra.s loc_155E
; End of function NemDecRun
; ===========================================================================
; loc_15A0:
NemDec_WriteAndStay:
move.l d4,(a4)
subq.w #1,a5
move.w a5,d4
bne.s NemDec_WriteIter
rts
; ---------------------------------------------------------------------------
; loc_15AA:
NemDec_WriteAndStay_XOR:
eor.l d4,d2
move.l d2,(a4)
subq.w #1,a5
move.w a5,d4
bne.s NemDec_WriteIter
rts
; ===========================================================================
; loc_15B6:
NemDec_WriteAndAdvance:
move.l d4,(a4)+
subq.w #1,a5
move.w a5,d4
bne.s NemDec_WriteIter
rts
if *-NemDec_WriteAndAdvance > NemDec_WriteAndStay_XOR-NemDec_WriteAndStay
fatal "the code in NemDec_WriteAndAdvance must not be larger than the code in NemDec_WriteAndStay"
endif
org NemDec_WriteAndAdvance+NemDec_WriteAndStay_XOR-NemDec_WriteAndStay
; ---------------------------------------------------------------------------
; loc_15C0:
NemDec_WriteAndAdvance_XOR:
eor.l d4,d2
move.l d2,(a4)+
subq.w #1,a5
move.w a5,d4
bne.s NemDec_WriteIter
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Part of the Nemesis decompressor
; sub_15CC:
NemDecPrepare:
move.b (a0)+,d0
- cmpi.b #$FF,d0
bne.s +
rts
; ---------------------------------------------------------------------------
+ move.w d0,d7
loc_15D8:
move.b (a0)+,d0
cmpi.b #$80,d0
bhs.s -
move.b d0,d1
andi.w #$F,d7
andi.w #$70,d1
or.w d1,d7
andi.w #$F,d0
move.b d0,d1
lsl.w #8,d1
or.w d1,d7
moveq #8,d1
sub.w d0,d1
bne.s loc_1606
move.b (a0)+,d0
add.w d0,d0
move.w d7,(a1,d0.w)
bra.s loc_15D8
; ---------------------------------------------------------------------------
loc_1606:
move.b (a0)+,d0
lsl.w d1,d0
add.w d0,d0
moveq #1,d5
lsl.w d1,d5
subq.w #1,d5
- move.w d7,(a1,d0.w)
addq.w #2,d0
dbf d5,-
bra.s loc_15D8
; End of function NemDecPrepare
; ---------------------------------------------------------------------------
; END OF NEMESIS DECOMPRESSOR
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; ---------------------------------------------------------------------------
; Subroutine to load pattern load cues (aka to queue pattern load requests)
; ---------------------------------------------------------------------------
; ARGUMENTS
; d0 = index of PLC list (see ArtLoadCues)
; NOTICE: This subroutine does not check for buffer overruns. The programmer
; (or hacker) is responsible for making sure that no more than
; 16 load requests are copied into the buffer.
; _________DO NOT PUT MORE THAN 16 LOAD REQUESTS IN A LIST!__________
; (or if you change the size of Plc_Buffer, the limit becomes (Plc_Buffer_Only_End-Plc_Buffer)/6)
; sub_161E: PLCLoad:
LoadPLC:
movem.l a1-a2,-(sp)
lea (ArtLoadCues).l,a1
add.w d0,d0
move.w (a1,d0.w),d0
lea (a1,d0.w),a1
lea (Plc_Buffer).w,a2
- tst.l (a2)
beq.s + ; if it's zero, exit this loop
addq.w #6,a2
bra.s -
+
move.w (a1)+,d0
bmi.s + ; if it's negative, skip the next loop
- move.l (a1)+,(a2)+
move.w (a1)+,(a2)+
dbf d0,-
+
movem.l (sp)+,a1-a2 ; a1=object
rts
; End of function LoadPLC
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Queue pattern load requests, but clear the PLQ first
; ARGUMENTS
; d0 = index of PLC list (see ArtLoadCues)
; NOTICE: This subroutine does not check for buffer overruns. The programmer
; (or hacker) is responsible for making sure that no more than
; 16 load requests are copied into the buffer.
; _________DO NOT PUT MORE THAN 16 LOAD REQUESTS IN A LIST!__________
; (or if you change the size of Plc_Buffer, the limit becomes (Plc_Buffer_Only_End-Plc_Buffer)/6)
; sub_1650:
LoadPLC2:
movem.l a1-a2,-(sp)
lea (ArtLoadCues).l,a1
add.w d0,d0
move.w (a1,d0.w),d0
lea (a1,d0.w),a1
bsr.s ClearPLC
lea (Plc_Buffer).w,a2
move.w (a1)+,d0
bmi.s + ; if it's negative, skip the next loop
- move.l (a1)+,(a2)+
move.w (a1)+,(a2)+
dbf d0,-
+
movem.l (sp)+,a1-a2
rts
; End of function LoadPLC2
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Clear the pattern load queue ($FFF680 - $FFF700)
ClearPLC:
lea (Plc_Buffer).w,a2
moveq #bytesToLcnt(Plc_Buffer_End-Plc_Buffer),d0
- clr.l (a2)+
dbf d0,-
rts
; End of function ClearPLC
; ---------------------------------------------------------------------------
; Subroutine to use graphics listed in a pattern load cue
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_168A:
RunPLC_RAM:
tst.l (Plc_Buffer).w
beq.s ++ ; rts
tst.w (Plc_Buffer_Reg18).w
bne.s ++ ; rts
movea.l (Plc_Buffer).w,a0
lea_ NemDec_WriteAndStay,a3
nop
lea (Decomp_Buffer).w,a1
move.w (a0)+,d2
bpl.s +
adda.w #NemDec_WriteAndStay_XOR-NemDec_WriteAndStay,a3
+
andi.w #$7FFF,d2
move.w d2,(Plc_Buffer_Reg18).w
bsr.w NemDecPrepare
move.b (a0)+,d5
asl.w #8,d5
move.b (a0)+,d5
moveq #$10,d6
moveq #0,d0
move.l a0,(Plc_Buffer).w
move.l a3,(Plc_Buffer_Reg0).w
move.l d0,(Plc_Buffer_Reg4).w
move.l d0,(Plc_Buffer_Reg8).w
move.l d0,(Plc_Buffer_RegC).w
move.l d5,(Plc_Buffer_Reg10).w
move.l d6,(Plc_Buffer_Reg14).w
+
rts
; End of function RunPLC_RAM
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Process one PLC from the queue
; sub_16E0:
ProcessDPLC:
tst.w (Plc_Buffer_Reg18).w
beq.w + ; rts
move.w #6,(Plc_Buffer_Reg1A).w
moveq #0,d0
move.w (Plc_Buffer+4).w,d0
addi.w #$C0,(Plc_Buffer+4).w
bra.s ProcessDPLC_Main
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Process one PLC from the queue
; loc_16FC:
ProcessDPLC2:
tst.w (Plc_Buffer_Reg18).w
beq.s + ; rts
move.w #3,(Plc_Buffer_Reg1A).w
moveq #0,d0
move.w (Plc_Buffer+4).w,d0
addi.w #$60,(Plc_Buffer+4).w
; loc_1714:
ProcessDPLC_Main:
lea (VDP_control_port).l,a4
lsl.l #2,d0 ; set up target VRAM address
lsr.w #2,d0
ori.w #vdpComm($0000,VRAM,WRITE)>>16,d0
swap d0
move.l d0,(a4)
subq.w #4,a4
movea.l (Plc_Buffer).w,a0
movea.l (Plc_Buffer_Reg0).w,a3
move.l (Plc_Buffer_Reg4).w,d0
move.l (Plc_Buffer_Reg8).w,d1
move.l (Plc_Buffer_RegC).w,d2
move.l (Plc_Buffer_Reg10).w,d5
move.l (Plc_Buffer_Reg14).w,d6
lea (Decomp_Buffer).w,a1
- movea.w #8,a5
bsr.w NemDec_WriteIter
subq.w #1,(Plc_Buffer_Reg18).w
beq.s ProcessDPLC_Pop
subq.w #1,(Plc_Buffer_Reg1A).w
bne.s -
move.l a0,(Plc_Buffer).w
move.l a3,(Plc_Buffer_Reg0).w
move.l d0,(Plc_Buffer_Reg4).w
move.l d1,(Plc_Buffer_Reg8).w
move.l d2,(Plc_Buffer_RegC).w
move.l d5,(Plc_Buffer_Reg10).w
move.l d6,(Plc_Buffer_Reg14).w
+
rts
; ===========================================================================
; pop one request off the buffer so that the next one can be filled
; loc_177A:
ProcessDPLC_Pop:
lea (Plc_Buffer).w,a0
moveq #bytesToLcnt(Plc_Buffer_Only_End-Plc_Buffer-6),d0
- move.l 6(a0),(a0)+
dbf d0,-
rts
; End of function ProcessDPLC
; ---------------------------------------------------------------------------
; Subroutine to execute a pattern load cue directly from the ROM
; rather than loading them into the queue first
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
RunPLC_ROM:
lea (ArtLoadCues).l,a1
add.w d0,d0
move.w (a1,d0.w),d0
lea (a1,d0.w),a1
move.w (a1)+,d1
- movea.l (a1)+,a0
moveq #0,d0
move.w (a1)+,d0
lsl.l #2,d0
lsr.w #2,d0
ori.w #vdpComm($0000,VRAM,WRITE)>>16,d0
swap d0
move.l d0,(VDP_control_port).l
bsr.w NemDec
dbf d1,-
rts
; End of function RunPLC_ROM
; ---------------------------------------------------------------------------
; Enigma Decompression Algorithm
; ARGUMENTS:
; d0 = starting art tile (added to each 8x8 before writing to destination)
; a0 = source address
; a1 = destination address
; For format explanation see http://info.sonicretro.org/Enigma_compression
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; EniDec_17BC:
EniDec:
movem.l d0-d7/a1-a5,-(sp)
movea.w d0,a3 ; store starting art tile
move.b (a0)+,d0
ext.w d0
movea.w d0,a5 ; store first byte, extended to word
move.b (a0)+,d4 ; store second byte
lsl.b #3,d4 ; multiply by 8
movea.w (a0)+,a2 ; store third and fourth byte
adda.w a3,a2 ; add starting art tile
movea.w (a0)+,a4 ; store fifth and sixth byte
adda.w a3,a4 ; add starting art tile
move.b (a0)+,d5 ; store seventh byte
asl.w #8,d5 ; shift up by a byte
move.b (a0)+,d5 ; store eighth byte in lower register byte
moveq #16,d6 ; 16 bits = 2 bytes
EniDec_Loop:
moveq #7,d0 ; process 7 bits at a time
move.w d6,d7
sub.w d0,d7
move.w d5,d1
lsr.w d7,d1
andi.w #$7F,d1 ; keep only lower 7 bits
move.w d1,d2
cmpi.w #$40,d1 ; is bit 6 set?
bhs.s + ; if it is, branch
moveq #6,d0 ; if not, process 6 bits instead of 7
lsr.w #1,d2 ; bitfield now becomes TTSSSS instead of TTTSSSS
+
bsr.w EniDec_ChkGetNextByte
andi.w #$F,d2 ; keep only lower nybble
lsr.w #4,d1 ; store upper nybble (max value = 7)
add.w d1,d1
jmp EniDec_JmpTable(pc,d1.w)
; End of function EniDec
; ===========================================================================
EniDec_Sub0:
move.w a2,(a1)+ ; write to destination
addq.w #1,a2 ; increment
dbf d2,EniDec_Sub0 ; repeat
bra.s EniDec_Loop
; ===========================================================================
EniDec_Sub4:
move.w a4,(a1)+ ; write to destination
dbf d2,EniDec_Sub4 ; repeat
bra.s EniDec_Loop
; ===========================================================================
EniDec_Sub8:
bsr.w EniDec_GetInlineCopyVal
- move.w d1,(a1)+
dbf d2,-
bra.s EniDec_Loop
; ===========================================================================
EniDec_SubA:
bsr.w EniDec_GetInlineCopyVal
- move.w d1,(a1)+
addq.w #1,d1
dbf d2,-
bra.s EniDec_Loop
; ===========================================================================
EniDec_SubC:
bsr.w EniDec_GetInlineCopyVal
- move.w d1,(a1)+
subq.w #1,d1
dbf d2,-
bra.s EniDec_Loop
; ===========================================================================
EniDec_SubE:
cmpi.w #$F,d2
beq.s EniDec_End
- bsr.w EniDec_GetInlineCopyVal
move.w d1,(a1)+
dbf d2,-
bra.s EniDec_Loop
; ===========================================================================
; Enigma_JmpTable:
EniDec_JmpTable:
bra.s EniDec_Sub0
bra.s EniDec_Sub0
bra.s EniDec_Sub4
bra.s EniDec_Sub4
bra.s EniDec_Sub8
bra.s EniDec_SubA
bra.s EniDec_SubC
bra.s EniDec_SubE
; ===========================================================================
EniDec_End:
subq.w #1,a0
cmpi.w #16,d6 ; were we going to start on a completely new byte?
bne.s + ; if not, branch
subq.w #1,a0
+
move.w a0,d0
lsr.w #1,d0 ; are we on an odd byte?
bcc.s + ; if not, branch
addq.w #1,a0 ; ensure we're on an even byte
+
movem.l (sp)+,d0-d7/a1-a5
rts
; S U B R O U T I N E
EniDec_GetInlineCopyVal:
move.w a3,d3 ; store starting art tile
move.b d4,d1
add.b d1,d1
bcc.s + ; if d4 was < $80
subq.w #1,d6 ; get next bit number
btst d6,d5 ; is the bit set?
beq.s + ; if not, branch
ori.w #high_priority,d3 ; set high priority bit
+
add.b d1,d1
bcc.s + ; if d4 was < $40
subq.w #1,d6 ; get next bit number
btst d6,d5
beq.s +
addi.w #palette_line_2,d3 ; set second palette line bit
+
add.b d1,d1
bcc.s + ; if d4 was < $20
subq.w #1,d6 ; get next bit number
btst d6,d5
beq.s +
addi.w #palette_line_1,d3 ; set first palette line bit
+
add.b d1,d1
bcc.s + ; if d4 was < $10
subq.w #1,d6 ; get next bit number
btst d6,d5
beq.s +
ori.w #flip_y,d3 ; set Y-flip bit
+
add.b d1,d1
bcc.s + ; if d4 was < 8
subq.w #1,d6
btst d6,d5
beq.s +
ori.w #flip_x,d3 ; set X-flip bit
+
move.w d5,d1
move.w d6,d7 ; get remaining bits
sub.w a5,d7 ; subtract minimum bit number
bcc.s + ; if we're beyond that, branch
move.w d7,d6
addi.w #16,d6 ; 16 bits = 2 bytes
neg.w d7 ; calculate bit deficit
lsl.w d7,d1 ; make space for this many bits
move.b (a0),d5 ; get next byte
rol.b d7,d5 ; make the upper X bits the lower X bits
add.w d7,d7
and.w EniDec_AndVals-2(pc,d7.w),d5 ; only keep X lower bits
add.w d5,d1 ; compensate for the bit deficit
-
move.w a5,d0
add.w d0,d0
and.w EniDec_AndVals-2(pc,d0.w),d1 ; only keep as many bits as required
add.w d3,d1 ; add starting art tile
move.b (a0)+,d5 ; get current byte, move onto next byte
lsl.w #8,d5 ; shift up by a byte
move.b (a0)+,d5 ; store next byte in lower register byte
rts
; ===========================================================================
+
beq.s + ; if the exact number of bits are leftover, branch
lsr.w d7,d1 ; remove unneeded bits
move.w a5,d0
add.w d0,d0
and.w EniDec_AndVals-2(pc,d0.w),d1 ; only keep as many bits as required
add.w d3,d1 ; add starting art tile
move.w a5,d0 ; store number of bits used up by inline copy
bra.s EniDec_ChkGetNextByte ; move onto next byte
; ===========================================================================
+
moveq #16,d6 ; 16 bits = 2 bytes
bra.s -
; End of function EniDec_GetInlineCopyVal
; ===========================================================================
; word_190A:
EniDec_AndVals:
dc.w 1, 3, 7, $F
dc.w $1F, $3F, $7F, $FF
dc.w $1FF, $3FF, $7FF, $FFF
dc.w $1FFF,$3FFF,$7FFF,$FFFF
; ===========================================================================
EniDec_ChkGetNextByte:
sub.w d0,d6
cmpi.w #9,d6
bhs.s + ; rts
addq.w #8,d6 ; 8 bits = 1 byte
asl.w #8,d5 ; shift up by a byte
move.b (a0)+,d5 ; store next byte in lower register byte
+
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; ---------------------------------------------------------------------------
; KOSINSKI DECOMPRESSION PROCEDURE
; (sometimes called KOZINSKI decompression)
; This is the only procedure in the game that stores variables on the stack.
; ARGUMENTS:
; a0 = source address
; a1 = destination address
; For format explanation see http://info.sonicretro.org/Kosinski_compression
; ---------------------------------------------------------------------------
; KozDec_193A:
KosDec:
subq.l #2,sp
move.b (a0)+,1(sp)
move.b (a0)+,(sp)
move.w (sp),d5
moveq #$F,d4
-
lsr.w #1,d5
move sr,d6
dbf d4,+
move.b (a0)+,1(sp)
move.b (a0)+,(sp)
move.w (sp),d5
moveq #$F,d4
+
move d6,ccr
bcc.s +
move.b (a0)+,(a1)+
bra.s -
; ---------------------------------------------------------------------------
+
moveq #0,d3
lsr.w #1,d5
move sr,d6
dbf d4,+
move.b (a0)+,1(sp)
move.b (a0)+,(sp)
move.w (sp),d5
moveq #$F,d4
+
move d6,ccr
bcs.s +++
lsr.w #1,d5
dbf d4,+
move.b (a0)+,1(sp)
move.b (a0)+,(sp)
move.w (sp),d5
moveq #$F,d4
+
roxl.w #1,d3
lsr.w #1,d5
dbf d4,+
move.b (a0)+,1(sp)
move.b (a0)+,(sp)
move.w (sp),d5
moveq #$F,d4
+
roxl.w #1,d3
addq.w #1,d3
moveq #-1,d2
move.b (a0)+,d2
bra.s ++
; ---------------------------------------------------------------------------
+
move.b (a0)+,d0
move.b (a0)+,d1
moveq #-1,d2
move.b d1,d2
lsl.w #5,d2
move.b d0,d2
andi.w #7,d1
beq.s ++
move.b d1,d3
addq.w #1,d3
/
move.b (a1,d2.w),d0
move.b d0,(a1)+
dbf d3,-
bra.s --
; ---------------------------------------------------------------------------
+
move.b (a0)+,d1
beq.s +
cmpi.b #1,d1
beq.w --
move.b d1,d3
bra.s -
; ---------------------------------------------------------------------------
+
addq.l #2,sp
rts
; End of function KosDec
; ===========================================================================
if gameRevision<2
nop
endif
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_19DC:
PalCycle_Load:
bsr.w PalCycle_SuperSonic
moveq #0,d2
moveq #0,d0
move.b (Current_Zone).w,d0 ; use level number as index into palette cycles
add.w d0,d0 ; (multiply by element size = 2 bytes)
move.w PalCycle(pc,d0.w),d0 ; load animated palettes offset index into d0
jmp PalCycle(pc,d0.w) ; jump to PalCycle + offset index
; ---------------------------------------------------------------------------
rts
; End of function PalCycle_Load
; ===========================================================================
; off_19F4:
PalCycle: zoneOrderedOffsetTable 2,1
zoneOffsetTableEntry.w PalCycle_EHZ ; 0
zoneOffsetTableEntry.w PalCycle_Null ; 1
zoneOffsetTableEntry.w PalCycle_WZ ; 2
zoneOffsetTableEntry.w PalCycle_Null ; 3
zoneOffsetTableEntry.w PalCycle_MTZ ; 4
zoneOffsetTableEntry.w PalCycle_MTZ ; 5
zoneOffsetTableEntry.w PalCycle_WFZ ; 6
zoneOffsetTableEntry.w PalCycle_HTZ ; 7
zoneOffsetTableEntry.w PalCycle_HPZ ; 8
zoneOffsetTableEntry.w PalCycle_Null ; 9
zoneOffsetTableEntry.w PalCycle_OOZ ; 10
zoneOffsetTableEntry.w PalCycle_MCZ ; 11
zoneOffsetTableEntry.w PalCycle_CNZ ; 12
zoneOffsetTableEntry.w PalCycle_CPZ ; 13
zoneOffsetTableEntry.w PalCycle_CPZ ; 14
zoneOffsetTableEntry.w PalCycle_ARZ ; 15
zoneOffsetTableEntry.w PalCycle_WFZ ; 16
zoneTableEnd
; ===========================================================================
; return_1A16:
PalCycle_Null:
rts
; ===========================================================================
PalCycle_EHZ:
lea (CyclingPal_EHZ_ARZ_Water).l,a0
subq.w #1,(PalCycle_Timer).w
bpl.s + ; rts
move.w #7,(PalCycle_Timer).w
move.w (PalCycle_Frame).w,d0
addq.w #1,(PalCycle_Frame).w
andi.w #3,d0
lsl.w #3,d0
move.l (a0,d0.w),(Normal_palette_line2+6).w
move.l 4(a0,d0.w),(Normal_palette_line2+$1C).w
+ rts
; ===========================================================================
; PalCycle_Level2:
PalCycle_WZ:
subq.w #1,(PalCycle_Timer).w
bpl.s ++ ; rts
move.w #2,(PalCycle_Timer).w
lea (CyclingPal_WoodConveyor).l,a0
move.w (PalCycle_Frame).w,d0
subq.w #2,(PalCycle_Frame).w
bcc.s +
move.w #6,(PalCycle_Frame).w
+ lea (Normal_palette_line4+6).w,a1
move.l (a0,d0.w),(a1)+
move.l 4(a0,d0.w),(a1)
+ rts
; ===========================================================================
PalCycle_MTZ:
subq.w #1,(PalCycle_Timer).w
bpl.s ++
move.w #$11,(PalCycle_Timer).w
lea (CyclingPal_MTZ1).l,a0
move.w (PalCycle_Frame).w,d0
addq.w #2,(PalCycle_Frame).w
cmpi.w #$C,(PalCycle_Frame).w
blo.s +
move.w #0,(PalCycle_Frame).w
+ lea (Normal_palette_line3+$A).w,a1
move.w (a0,d0.w),(a1)
+
subq.w #1,(PalCycle_Timer2).w
bpl.s ++
move.w #2,(PalCycle_Timer2).w
lea (CyclingPal_MTZ2).l,a0
move.w (PalCycle_Frame2).w,d0
addq.w #2,(PalCycle_Frame2).w
cmpi.w #6,(PalCycle_Frame2).w
blo.s +
move.w #0,(PalCycle_Frame2).w
+ lea (Normal_palette_line3+2).w,a1
move.l (a0,d0.w),(a1)+
move.w 4(a0,d0.w),(a1)
+
subq.w #1,(PalCycle_Timer3).w
bpl.s ++ ; rts
move.w #9,(PalCycle_Timer3).w
lea (CyclingPal_MTZ3).l,a0
move.w (PalCycle_Frame3).w,d0
addq.w #2,(PalCycle_Frame3).w
cmpi.w #$14,(PalCycle_Frame3).w
blo.s +
move.w #0,(PalCycle_Frame3).w
+ lea (Normal_palette_line3+$1E).w,a1
move.w (a0,d0.w),(a1)
+ rts
; ===========================================================================
PalCycle_HTZ:
lea (CyclingPal_Lava).l,a0
subq.w #1,(PalCycle_Timer).w
bpl.s + ; rts
move.w #0,(PalCycle_Timer).w
move.w (PalCycle_Frame).w,d0
addq.w #1,(PalCycle_Frame).w
andi.w #$F,d0
move.b PalCycle_HTZ_LavaDelayData(pc,d0.w),(PalCycle_Timer+1).w
lsl.w #3,d0
move.l (a0,d0.w),(Normal_palette_line2+6).w
move.l 4(a0,d0.w),(Normal_palette_line2+$1C).w
+ rts
; ===========================================================================
; byte_1B40:
PalCycle_HTZ_LavaDelayData: ; number of frames between changes of the lava palette
dc.b $B, $B, $B, $A
dc.b 8, $A, $B, $B
dc.b $B, $B, $D, $F
dc.b $D, $B, $B, $B
; ===========================================================================
PalCycle_HPZ:
subq.w #1,(PalCycle_Timer).w
bpl.s ++ ; rts
move.w #4,(PalCycle_Timer).w
lea (CyclingPal_HPZWater).l,a0
move.w (PalCycle_Frame).w,d0
subq.w #2,(PalCycle_Frame).w
bcc.s +
move.w #6,(PalCycle_Frame).w
+ lea (Normal_palette_line4+$12).w,a1
move.l (a0,d0.w),(a1)+
move.l 4(a0,d0.w),(a1)
lea (CyclingPal_HPZUnderwater).l,a0
lea (Underwater_palette_line4+$12).w,a1
move.l (a0,d0.w),(a1)+
move.l 4(a0,d0.w),(a1)
+ rts
; ===========================================================================
PalCycle_OOZ:
subq.w #1,(PalCycle_Timer).w
bpl.s + ; rts
move.w #7,(PalCycle_Timer).w
lea (CyclingPal_Oil).l,a0
move.w (PalCycle_Frame).w,d0
addq.w #2,(PalCycle_Frame).w
andi.w #6,(PalCycle_Frame).w
lea (Normal_palette_line3+$14).w,a1
move.l (a0,d0.w),(a1)+
move.l 4(a0,d0.w),(a1)
+ rts
; ===========================================================================
PalCycle_MCZ:
tst.b (Current_Boss_ID).w
bne.s + ; rts
subq.w #1,(PalCycle_Timer).w
bpl.s + ; rts
move.w #1,(PalCycle_Timer).w
lea (CyclingPal_Lantern).l,a0
move.w (PalCycle_Frame).w,d0
addq.w #2,(PalCycle_Frame).w
andi.w #6,(PalCycle_Frame).w
move.w (a0,d0.w),(Normal_palette_line2+$16).w
+ rts
; ===========================================================================
PalCycle_CNZ:
subq.w #1,(PalCycle_Timer).w
bpl.w CNZ_SkipToBossPalCycle
move.w #7,(PalCycle_Timer).w
lea (CyclingPal_CNZ1).l,a0
move.w (PalCycle_Frame).w,d0
addq.w #2,(PalCycle_Frame).w
cmpi.w #6,(PalCycle_Frame).w
blo.s +
move.w #0,(PalCycle_Frame).w
+
lea (a0,d0.w),a0
lea (Normal_palette).w,a1
_move.w 0(a0),$4A(a1)
move.w 6(a0),$4C(a1)
move.w $C(a0),$4E(a1)
move.w $12(a0),$56(a1)
move.w $18(a0),$58(a1)
move.w $1E(a0),$5A(a1)
lea (CyclingPal_CNZ3).l,a0
lea (a0,d0.w),a0
_move.w 0(a0),$64(a1)
move.w 6(a0),$66(a1)
move.w $C(a0),$68(a1)
lea (CyclingPal_CNZ4).l,a0
move.w (PalCycle_Frame_CNZ).w,d0
addq.w #2,(PalCycle_Frame_CNZ).w
cmpi.w #$24,(PalCycle_Frame_CNZ).w
blo.s +
move.w #0,(PalCycle_Frame_CNZ).w
+
lea (Normal_palette_line4+$12).w,a1
move.w 4(a0,d0.w),(a1)+
move.w 2(a0,d0.w),(a1)+
move.w (a0,d0.w),(a1)+
CNZ_SkipToBossPalCycle:
tst.b (Current_Boss_ID).w
beq.w +++ ; rts
subq.w #1,(PalCycle_Timer2).w
bpl.w +++ ; rts
move.w #3,(PalCycle_Timer2).w
move.w (PalCycle_Frame2).w,d0
addq.w #2,(PalCycle_Frame2).w
cmpi.w #6,(PalCycle_Frame2).w
blo.s +
move.w #0,(PalCycle_Frame2).w
+ lea (CyclingPal_CNZ1_B).l,a0
lea (a0,d0.w),a0
lea (Normal_palette).w,a1
_move.w 0(a0),$24(a1)
move.w 6(a0),$26(a1)
move.w $C(a0),$28(a1)
lea (CyclingPal_CNZ2_B).l,a0
move.w (PalCycle_Frame3).w,d0
addq.w #2,(PalCycle_Frame3).w
cmpi.w #$14,(PalCycle_Frame3).w
blo.s +
move.w #0,(PalCycle_Frame3).w
+ move.w (a0,d0.w),$3C(a1)
lea (CyclingPal_CNZ3_B).l,a0
move.w (PalCycle_Frame2_CNZ).w,d0
addq.w #2,(PalCycle_Frame2_CNZ).w
andi.w #$E,(PalCycle_Frame2_CNZ).w
move.w (a0,d0.w),$3E(a1)
+ rts
; ===========================================================================
PalCycle_CPZ:
subq.w #1,(PalCycle_Timer).w
bpl.s +++ ; rts
move.w #7,(PalCycle_Timer).w
lea (CyclingPal_CPZ1).l,a0
move.w (PalCycle_Frame).w,d0
addq.w #6,(PalCycle_Frame).w
cmpi.w #$36,(PalCycle_Frame).w
blo.s +
move.w #0,(PalCycle_Frame).w
+ lea (Normal_palette_line4+$18).w,a1
move.l (a0,d0.w),(a1)+
move.w 4(a0,d0.w),(a1)
lea (CyclingPal_CPZ2).l,a0
move.w (PalCycle_Frame2).w,d0
addq.w #2,(PalCycle_Frame2).w
cmpi.w #$2A,(PalCycle_Frame2).w
blo.s +
move.w #0,(PalCycle_Frame2).w
+ move.w (a0,d0.w),(Normal_palette_line4+$1E).w
lea (CyclingPal_CPZ3).l,a0
move.w (PalCycle_Frame3).w,d0
addq.w #2,(PalCycle_Frame3).w
andi.w #$1E,(PalCycle_Frame3).w
move.w (a0,d0.w),(Normal_palette_line3+$1E).w
+ rts
; ===========================================================================
PalCycle_ARZ:
lea (CyclingPal_EHZ_ARZ_Water).l,a0
subq.w #1,(PalCycle_Timer).w
bpl.s + ; rts
move.w #5,(PalCycle_Timer).w
move.w (PalCycle_Frame).w,d0
addq.w #1,(PalCycle_Frame).w
andi.w #3,d0
lsl.w #3,d0
lea (Normal_palette_line3+4).w,a1
move.l (a0,d0.w),(a1)+
move.l 4(a0,d0.w),(a1)
+ rts
; ===========================================================================
PalCycle_WFZ:
subq.w #1,(PalCycle_Timer).w
bpl.s +++
move.w #1,(PalCycle_Timer).w
lea (CyclingPal_WFZFire).l,a0
tst.b (WFZ_SCZ_Fire_Toggle).w
beq.s +
move.w #5,(PalCycle_Timer).w
lea (CyclingPal_WFZBelt).l,a0
+ move.w (PalCycle_Frame).w,d0
addq.w #8,(PalCycle_Frame).w
cmpi.w #$20,(PalCycle_Frame).w
blo.s +
move.w #0,(PalCycle_Frame).w
+ lea (Normal_palette_line3+$E).w,a1
move.l (a0,d0.w),(a1)+
move.l 4(a0,d0.w),(a1)
+ subq.w #1,(PalCycle_Timer2).w
bpl.s ++ ; subq.w
move.w #3,(PalCycle_Timer2).w
lea (CyclingPal_WFZ1).l,a0
move.w (PalCycle_Frame2).w,d0
addq.w #2,(PalCycle_Frame2).w
cmpi.w #$44,(PalCycle_Frame2).w
blo.s + ; move.w
move.w #0,(PalCycle_Frame2).w
+ move.w (a0,d0.w),(Normal_palette_line3+$1C).w
+
subq.w #1,(PalCycle_Timer3).w
bpl.s ++ ; rts
move.w #5,(PalCycle_Timer3).w
lea (CyclingPal_WFZ2).l,a0
move.w (PalCycle_Frame3).w,d0
addq.w #2,(PalCycle_Frame3).w
cmpi.w #$18,(PalCycle_Frame3).w
blo.s +
move.w #0,(PalCycle_Frame3).w
+ move.w (a0,d0.w),(Normal_palette_line3+$1E).w
+ rts
; ===========================================================================
; ----------------------------------------------------------------------------
; word_1E5A:
BINCLUDE "art/palettes/Title Water.bin"; S1 Title Screen Water palette (unused)
; word_1E7A:
CyclingPal_EHZ_ARZ_Water:
BINCLUDE "art/palettes/EHZ ARZ Water.bin"; Emerald Hill/Aquatic Ruin Rotating Water palette
; word_1E9A:
CyclingPal_Lava:
BINCLUDE "art/palettes/Hill Top Lava.bin"; Hill Top Lava palette
; word_1F1A:
CyclingPal_WoodConveyor:
BINCLUDE "art/palettes/Wood Conveyor.bin"; Wood Conveyor Belts palette
; byte_1F2A:
CyclingPal_MTZ1:
BINCLUDE "art/palettes/MTZ Cycle 1.bin"; Metropolis Cycle #1 palette
; word_1F36:
CyclingPal_MTZ2:
BINCLUDE "art/palettes/MTZ Cycle 2.bin"; Metropolis Cycle #2 palette
; word_1F42:
CyclingPal_MTZ3:
BINCLUDE "art/palettes/MTZ Cycle 3.bin"; Metropolis Cycle #3 palette
; word_1F56:
CyclingPal_HPZWater:
BINCLUDE "art/palettes/HPZ Water Cycle.bin"; Hidden Palace Water Cycle
; word_1F66:
CyclingPal_HPZUnderwater:
BINCLUDE "art/palettes/HPZ Underwater Cycle.bin"; Hidden Palace Underwater Cycle
; word_1F76:
CyclingPal_Oil:
BINCLUDE "art/palettes/OOZ Oil.bin"; Oil Ocean Oil palette
; word_1F86:
CyclingPal_Lantern:
BINCLUDE "art/palettes/MCZ Lantern.bin"; Mystic Cave Lanterns
; word_1F8E:
CyclingPal_CNZ1:
BINCLUDE "art/palettes/CNZ Cycle 1.bin"; Casino Night Cycles 1 & 2
; word_1FB2:
CyclingPal_CNZ3:
BINCLUDE "art/palettes/CNZ Cycle 3.bin"; Casino Night Cycle 3
; word_1FC4:
CyclingPal_CNZ4:
BINCLUDE "art/palettes/CNZ Cycle 4.bin"; Casino Night Cycle 4
; word_1FEC:
CyclingPal_CNZ1_B:
BINCLUDE "art/palettes/CNZ Boss Cycle 1.bin"; Casino Night Boss Cycle 1
; word_1FFE:
CyclingPal_CNZ2_B:
BINCLUDE "art/palettes/CNZ Boss Cycle 2.bin"; Casino Night Boss Cycle 2
; word_2012:
CyclingPal_CNZ3_B:
BINCLUDE "art/palettes/CNZ Boss Cycle 3.bin"; Casino Night Boss Cycle 3
; word_2022:
CyclingPal_CPZ1:
BINCLUDE "art/palettes/CPZ Cycle 1.bin"; Chemical Plant Cycle 1
; word_2058:
CyclingPal_CPZ2:
BINCLUDE "art/palettes/CPZ Cycle 2.bin"; Chemical Plant Cycle 2
; word_2082:
CyclingPal_CPZ3:
BINCLUDE "art/palettes/CPZ Cycle 3.bin"; Chemical Plant Cycle 3
; word_20A2:
CyclingPal_WFZFire:
BINCLUDE "art/palettes/WFZ Fire Cycle.bin"; Wing Fortress Fire Cycle palette
; word_20C2:
CyclingPal_WFZBelt:
BINCLUDE "art/palettes/WFZ Conveyor Cycle.bin"; Wing Fortress Conveyor Belt Cycle palette
; word_20E2: CyclingPal_CPZ4:
CyclingPal_WFZ1:
BINCLUDE "art/palettes/WFZ Cycle 1.bin"; Wing Fortress Flashing Light Cycle 1
; word_2126:
CyclingPal_WFZ2:
BINCLUDE "art/palettes/WFZ Cycle 2.bin"; Wing Fortress Flashing Light Cycle 2
; ----------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_213E:
PalCycle_SuperSonic:
move.b (Super_Sonic_palette).w,d0
beq.s ++ ; rts ; return, if Sonic isn't super
bmi.w PalCycle_SuperSonic_normal ; branch, if fade-in is done
subq.b #1,d0
bne.s PalCycle_SuperSonic_revert ; branch for values greater than 1
; fade from Sonic's to Super Sonic's palette
; run frame timer
subq.b #1,(Palette_timer).w
bpl.s ++ ; rts
move.b #3,(Palette_timer).w
; increment palette frame and update Sonic's palette
lea (CyclingPal_SSTransformation).l,a0
move.w (Palette_frame).w,d0
addq.w #8,(Palette_frame).w ; 1 palette entry = 1 word, Sonic uses 4 shades of blue
cmpi.w #$30,(Palette_frame).w ; has palette cycle reached the 6th frame?
blo.s + ; if not, branch
move.b #-1,(Super_Sonic_palette).w ; mark fade-in as done
move.b #0,(MainCharacter+obj_control).w ; restore Sonic's movement
+
lea (Normal_palette+4).w,a1
move.l (a0,d0.w),(a1)+
move.l 4(a0,d0.w),(a1)
; note: the fade in for Sonic's underwater palette is missing.
; branch to the code below (*) to fix this
/ rts
; ===========================================================================
; loc_2188:
PalCycle_SuperSonic_revert: ; runs the fade in transition backwards
; run frame timer
subq.b #1,(Palette_timer).w
bpl.s - ; rts
move.b #3,(Palette_timer).w
; decrement palette frame and update Sonic's palette
lea (CyclingPal_SSTransformation).l,a0
move.w (Palette_frame).w,d0
subq.w #8,(Palette_frame).w ; previous frame
bcc.s + ; branch, if it isn't the first frame
move.b #0,(Palette_frame).w
move.b #0,(Super_Sonic_palette).w ; stop palette cycle
+
lea (Normal_palette+4).w,a1
move.l (a0,d0.w),(a1)+
move.l 4(a0,d0.w),(a1)
; underwater palettes (*)
lea (CyclingPal_CPZUWTransformation).l,a0
cmpi.b #chemical_plant_zone,(Current_Zone).w
beq.s +
cmpi.b #aquatic_ruin_zone,(Current_Zone).w
bne.s - ; rts
lea (CyclingPal_ARZUWTransformation).l,a0
+ lea (Underwater_palette+4).w,a1
move.l (a0,d0.w),(a1)+
move.l 4(a0,d0.w),(a1)
rts
; ===========================================================================
; loc_21E6:
PalCycle_SuperSonic_normal:
; run frame timer
subq.b #1,(Palette_timer).w
bpl.s - ; rts
move.b #7,(Palette_timer).w
; increment palette frame and update Sonic's palette
lea (CyclingPal_SSTransformation).l,a0
move.w (Palette_frame).w,d0
addq.w #8,(Palette_frame).w ; next frame
cmpi.w #$78,(Palette_frame).w ; is it the last frame?
blo.s + ; if not, branch
move.w #$30,(Palette_frame).w ; reset frame counter (Super Sonic's normal palette cycle starts at $30. Everything before that is for the palette fade)
+
lea (Normal_palette+4).w,a1
move.l (a0,d0.w),(a1)+
move.l 4(a0,d0.w),(a1)
; underwater palettes
lea (CyclingPal_CPZUWTransformation).l,a0
cmpi.b #chemical_plant_zone,(Current_Zone).w
beq.s +
cmpi.b #aquatic_ruin_zone,(Current_Zone).w
bne.w - ; rts
lea (CyclingPal_ARZUWTransformation).l,a0
+ lea (Underwater_palette+4).w,a1
move.l (a0,d0.w),(a1)+
move.l 4(a0,d0.w),(a1)
rts
; End of function PalCycle_SuperSonic
; ===========================================================================
;----------------------------------------------------------------------------
;Palette for transformation to Super Sonic
;----------------------------------------------------------------------------
; Pal_2246:
CyclingPal_SSTransformation:
BINCLUDE "art/palettes/Super Sonic transformation.bin"
;----------------------------------------------------------------------------
;Palette for transformation to Super Sonic while underwater in CPZ
;----------------------------------------------------------------------------
; Pal_22C6:
CyclingPal_CPZUWTransformation:
BINCLUDE "art/palettes/CPZWater SS transformation.bin"
;----------------------------------------------------------------------------
;Palette for transformation to Super Sonic while underwater in ARZ
;----------------------------------------------------------------------------
; Pal_2346:
CyclingPal_ARZUWTransformation:
BINCLUDE "art/palettes/ARZWater SS transformation.bin"
; ---------------------------------------------------------------------------
; Subroutine to fade in from black
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_23C6: Pal_FadeTo:
Pal_FadeFromBlack:
move.w #$3F,(Palette_fade_range).w
moveq #0,d0
lea (Normal_palette).w,a0
move.b (Palette_fade_start).w,d0
adda.w d0,a0
moveq #0,d1
move.b (Palette_fade_length).w,d0
; loc_23DE: Pal_ToBlack:
.palettewrite:
move.w d1,(a0)+
dbf d0,.palettewrite ; fill palette with $000 (black)
move.w #$15,d4
.nextframe:
move.b #VintID_Fade,(Vint_routine).w
bsr.w WaitForVint
bsr.s .UpdateAllColours
bsr.w RunPLC_RAM
dbf d4,.nextframe
rts
; End of function Pal_FadeFromBlack
; ---------------------------------------------------------------------------
; Subroutine to update all colours once
; ---------------------------------------------------------------------------
; sub_23FE: Pal_FadeIn:
.UpdateAllColours:
; Update above-water palette
moveq #0,d0
lea (Normal_palette).w,a0
lea (Target_palette).w,a1
move.b (Palette_fade_start).w,d0
adda.w d0,a0
adda.w d0,a1
move.b (Palette_fade_length).w,d0
.nextcolour:
bsr.s .UpdateColour
dbf d0,.nextcolour
tst.b (Water_flag).w
beq.s .skipunderwater
; Update underwater palette
moveq #0,d0
lea (Underwater_palette).w,a0
lea (Underwater_target_palette).w,a1
move.b (Palette_fade_start).w,d0
adda.w d0,a0
adda.w d0,a1
move.b (Palette_fade_length).w,d0
.nextcolour2:
bsr.s .UpdateColour
dbf d0,.nextcolour2
.skipunderwater:
rts
; ---------------------------------------------------------------------------
; Subroutine to update a single colour once
; ---------------------------------------------------------------------------
; sub_243E: Pal_AddColor:
.UpdateColour:
move.w (a1)+,d2
move.w (a0),d3
cmp.w d2,d3
beq.s .updatenone
;.updateblue:
move.w d3,d1
addi.w #$200,d1 ; increase blue value
cmp.w d2,d1 ; has blue reached threshold level?
bhi.s .updategreen ; if yes, branch
move.w d1,(a0)+ ; update palette
rts
; loc_2454: Pal_AddGreen:
.updategreen:
move.w d3,d1
addi.w #$20,d1 ; increase green value
cmp.w d2,d1
bhi.s .updatered
move.w d1,(a0)+ ; update palette
rts
; loc_2462: Pal_AddRed:
.updatered:
addq.w #2,(a0)+ ; increase red value
rts
; loc_2466: Pal_AddNone:
.updatenone:
addq.w #2,a0
rts
; ---------------------------------------------------------------------------
; Subroutine to fade out to black
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_246A: Pal_FadeFrom:
Pal_FadeToBlack:
move.w #$3F,(Palette_fade_range).w
move.w #$15,d4
.nextframe:
move.b #VintID_Fade,(Vint_routine).w
bsr.w WaitForVint
bsr.s .UpdateAllColours
bsr.w RunPLC_RAM
dbf d4,.nextframe
rts
; End of function Pal_FadeToBlack
; ---------------------------------------------------------------------------
; Subroutine to update all colours once
; ---------------------------------------------------------------------------
; sub_248A: Pal_FadeOut:
.UpdateAllColours:
; Update above-water palette
moveq #0,d0
lea (Normal_palette).w,a0
move.b (Palette_fade_start).w,d0
adda.w d0,a0
move.b (Palette_fade_length).w,d0
.nextcolour:
bsr.s .UpdateColour
dbf d0,.nextcolour
; Notice how this one lacks a check for
; if Water_flag is set, unlike Pal_FadeFromBlack?
; Update underwater palette
moveq #0,d0
lea (Underwater_palette).w,a0
move.b (Palette_fade_start).w,d0
adda.w d0,a0
move.b (Palette_fade_length).w,d0
.nextcolour2:
bsr.s .UpdateColour
dbf d0,.nextcolour2
rts
; ---------------------------------------------------------------------------
; Subroutine to update a single colour once
; ---------------------------------------------------------------------------
; sub_24B8: Pal_DecColor:
.UpdateColour:
move.w (a0),d2
beq.s .updatenone
;.updatered:
move.w d2,d1
andi.w #$E,d1
beq.s .updategreen
subq.w #2,(a0)+ ; decrease red value
rts
; loc_24C8: Pal_DecGreen:
.updategreen:
move.w d2,d1
andi.w #$E0,d1
beq.s .updateblue
subi.w #$20,(a0)+ ; decrease green value
rts
; loc_24D6: Pal_DecBlue:
.updateblue:
move.w d2,d1
andi.w #$E00,d1
beq.s .updatenone
subi.w #$200,(a0)+ ; decrease blue value
rts
; loc_24E4: Pal_DecNone:
.updatenone:
addq.w #2,a0
rts
; ---------------------------------------------------------------------------
; Subroutine to fade in from white
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_24E8: Pal_MakeWhite:
Pal_FadeFromWhite:
move.w #$3F,(Palette_fade_range).w
moveq #0,d0
lea (Normal_palette).w,a0
move.b (Palette_fade_start).w,d0
adda.w d0,a0
move.w #$EEE,d1
move.b (Palette_fade_length).w,d0
.palettewrite:
move.w d1,(a0)+
dbf d0,.palettewrite
move.w #$15,d4
.nextframe:
move.b #VintID_Fade,(Vint_routine).w
bsr.w WaitForVint
bsr.s .UpdateAllColours
bsr.w RunPLC_RAM
dbf d4,.nextframe
rts
; End of function Pal_FadeFromWhite
; ---------------------------------------------------------------------------
; Subroutine to update all colours once
; ---------------------------------------------------------------------------
; sub_2522: Pal_WhiteToBlack:
.UpdateAllColours:
; Update above-water palette
moveq #0,d0
lea (Normal_palette).w,a0
lea (Target_palette).w,a1
move.b (Palette_fade_start).w,d0
adda.w d0,a0
adda.w d0,a1
move.b (Palette_fade_length).w,d0
.nextcolour:
bsr.s .UpdateColour
dbf d0,.nextcolour
tst.b (Water_flag).w
beq.s .skipunderwater
; Update underwater palette
moveq #0,d0
lea (Underwater_palette).w,a0
lea (Underwater_target_palette).w,a1
move.b (Palette_fade_start).w,d0
adda.w d0,a0
adda.w d0,a1
move.b (Palette_fade_length).w,d0
.nextcolour2:
bsr.s .UpdateColour
dbf d0,.nextcolour2
.skipunderwater:
rts
; ---------------------------------------------------------------------------
; Subroutine to update a single colour once
; ---------------------------------------------------------------------------
; sub_2562: Pal_DecColor2:
.UpdateColour:
move.w (a1)+,d2
move.w (a0),d3
cmp.w d2,d3
beq.s .updatenone
;.updateblue:
move.w d3,d1
subi.w #$200,d1 ; decrease blue value
bcs.s .updategreen
cmp.w d2,d1
blo.s .updategreen
move.w d1,(a0)+
rts
; loc_257A: Pal_DecGreen2:
.updategreen:
move.w d3,d1
subi.w #$20,d1 ; decrease green value
bcs.s .updatered
cmp.w d2,d1
blo.s .updatered
move.w d1,(a0)+
rts
; loc_258A: Pal_DecRed2:
.updatered:
subq.w #2,(a0)+ ; decrease red value
rts
; loc_258E: Pal_DecNone2:
.updatenone:
addq.w #2,a0
rts
; ---------------------------------------------------------------------------
; Subroutine to fade out to white (used when you enter a special stage)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_2592: Pal_MakeFlash:
Pal_FadeToWhite:
move.w #$3F,(Palette_fade_range).w
move.w #$15,d4
.nextframe:
move.b #VintID_Fade,(Vint_routine).w
bsr.w WaitForVint
bsr.s .UpdateAllColours
bsr.w RunPLC_RAM
dbf d4,.nextframe
rts
; End of function Pal_FadeToWhite
; ---------------------------------------------------------------------------
; Subroutine to update all colours once
; ---------------------------------------------------------------------------
; sub_25B2: Pal_ToWhite:
.UpdateAllColours:
; Update above-water palette
moveq #0,d0
lea (Normal_palette).w,a0
move.b (Palette_fade_start).w,d0
adda.w d0,a0
move.b (Palette_fade_length).w,d0
.nextcolour:
bsr.s .UpdateColour
dbf d0,.nextcolour
; Notice how this one lacks a check for
; if Water_flag is set, unlike Pal_FadeFromWhite?
; Update underwater palette
moveq #0,d0
lea (Underwater_palette).w,a0
move.b (Palette_fade_start).w,d0
adda.w d0,a0
move.b (Palette_fade_length).w,d0
.nextcolour2:
bsr.s .UpdateColour
dbf d0,.nextcolour2
rts
; ---------------------------------------------------------------------------
; Subroutine to update a single colour once
; ---------------------------------------------------------------------------
; sub_25E0: Pal_AddColor2:
.UpdateColour:
move.w (a0),d2
cmpi.w #$EEE,d2
beq.s .updatenone
;.updatered:
move.w d2,d1
andi.w #$E,d1
cmpi.w #$E,d1
beq.s .updategreen
addq.w #2,(a0)+ ; increase red value
rts
; loc_25F8: Pal_AddGreen2:
.updategreen:
move.w d2,d1
andi.w #$E0,d1
cmpi.w #$E0,d1
beq.s .updateblue
addi.w #$20,(a0)+ ; increase green value
rts
; loc_260A: Pal_AddBlue2:
.updateblue:
move.w d2,d1
andi.w #$E00,d1
cmpi.w #$E00,d1
beq.s .updatenone
addi.w #$200,(a0)+ ; increase blue value
rts
; loc_261C: Pal_AddNone2:
.updatenone:
addq.w #2,a0
rts
; End of function Pal_AddColor2
; Unused - dead code/data for old SEGA screen:
; ===========================================================================
; PalCycle_Sega:
tst.b (PalCycle_Timer+1).w
bne.s loc_2680
lea (Normal_palette_line2).w,a1
lea (Pal_Sega1).l,a0
moveq #5,d1
move.w (PalCycle_Frame).w,d0
loc_2636:
bpl.s loc_2640
addq.w #2,a0
subq.w #1,d1
addq.w #2,d0
bra.s loc_2636
; ===========================================================================
loc_2640:
move.w d0,d2
andi.w #$1E,d2
bne.s loc_264A
addq.w #2,d0
loc_264A:
cmpi.w #$60,d0
bhs.s loc_2654
move.w (a0)+,(a1,d0.w)
loc_2654:
addq.w #2,d0
dbf d1,loc_2640
move.w (PalCycle_Frame).w,d0
addq.w #2,d0
move.w d0,d2
andi.w #$1E,d2
bne.s loc_266A
addq.w #2,d0
loc_266A:
cmpi.w #$64,d0
blt.s loc_2678
move.w #$401,(PalCycle_Timer).w
moveq #-$C,d0
loc_2678:
move.w d0,(PalCycle_Frame).w
moveq #1,d0
rts
; ===========================================================================
loc_2680:
subq.b #1,(PalCycle_Timer).w
bpl.s loc_26D2
move.b #4,(PalCycle_Timer).w
move.w (PalCycle_Frame).w,d0
addi.w #$C,d0
cmpi.w #$30,d0
blo.s loc_269E
moveq #0,d0
rts
; ===========================================================================
loc_269E:
move.w d0,(PalCycle_Frame).w
lea (Pal_Sega2).l,a0
lea (a0,d0.w),a0
lea (Normal_palette+4).w,a1
move.l (a0)+,(a1)+
move.l (a0)+,(a1)+
move.w (a0)+,(a1)
lea (Normal_palette_line2).w,a1
moveq #0,d0
moveq #$2C,d1
loc_26BE:
move.w d0,d2
andi.w #$1E,d2
bne.s loc_26C8
addq.w #2,d0
loc_26C8:
move.w (a0),(a1,d0.w)
addq.w #2,d0
dbf d1,loc_26BE
loc_26D2:
moveq #1,d0
rts
; ===========================================================================
;----------------------------------------------------------------------------
; Unused palette for the Sega logo
;----------------------------------------------------------------------------
; Pal_26D6:
Pal_Sega1: BINCLUDE "art/palettes/Unused Sega logo.bin"
;----------------------------------------------------------------------------
; Unused palette for the Sega logo (fading?)
;----------------------------------------------------------------------------
; Pal_26E2:
Pal_Sega2: BINCLUDE "art/palettes/Unused Sega logo 2.bin"
; end of dead code/data
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_2712: PalLoad1:
PalLoad_ForFade:
lea (PalPointers).l,a1
lsl.w #3,d0
adda.w d0,a1
movea.l (a1)+,a2
movea.w (a1)+,a3
adda.w #Target_palette-Normal_palette,a3
move.w (a1)+,d7
- move.l (a2)+,(a3)+
dbf d7,-
rts
; End of function PalLoad_ForFade
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_272E: PalLoad2:
PalLoad_Now:
lea (PalPointers).l,a1
lsl.w #3,d0
adda.w d0,a1
movea.l (a1)+,a2
movea.w (a1)+,a3
move.w (a1)+,d7
- move.l (a2)+,(a3)+
dbf d7,-
rts
; End of function PalLoad_Now
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_2746: PalLoad3_Water:
PalLoad_Water_Now:
lea (PalPointers).l,a1
lsl.w #3,d0
adda.w d0,a1
movea.l (a1)+,a2
movea.w (a1)+,a3
suba.l #Normal_palette-Underwater_palette,a3
move.w (a1)+,d7
- move.l (a2)+,(a3)+
dbf d7,-
rts
; End of function PalLoad_Water_Now
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_2764: PalLoad4_Water:
PalLoad_Water_ForFade:
lea (PalPointers).l,a1
lsl.w #3,d0
adda.w d0,a1
movea.l (a1)+,a2
movea.w (a1)+,a3
suba.l #Normal_palette-Underwater_target_palette,a3
move.w (a1)+,d7
- move.l (a2)+,(a3)+
dbf d7,-
rts
; End of function PalLoad_Water_ForFade
; ===========================================================================
;----------------------------------------------------------------------------
; Palette pointers
; (PALETTE DESCRIPTOR ARRAY)
; This struct array defines the palette to use for each level.
;----------------------------------------------------------------------------
palptr macro ptr,lineno
dc.l ptr ; Pointer to palette
dc.w (Normal_palette+lineno*palette_line_size)&$FFFF ; Location in ram to load palette into
dc.w bytesToLcnt(ptr_End-ptr) ; Size of palette in (bytes / 4)
endm
PalPointers:
PalPtr_SEGA: palptr Pal_SEGA, 0
PalPtr_Title: palptr Pal_Title, 1
PalPtr_MenuB: palptr Pal_MenuB, 0
PalPtr_BGND: palptr Pal_BGND, 0
PalPtr_EHZ: palptr Pal_EHZ, 1
PalPtr_EHZ2: palptr Pal_EHZ, 1
PalPtr_WZ: palptr Pal_WZ, 1
PalPtr_EHZ3: palptr Pal_EHZ, 1
PalPtr_MTZ: palptr Pal_MTZ, 1
PalPtr_MTZ2: palptr Pal_MTZ, 1
PalPtr_WFZ: palptr Pal_WFZ, 1
PalPtr_HTZ: palptr Pal_HTZ, 1
PalPtr_HPZ: palptr Pal_HPZ, 1
PalPtr_EHZ4: palptr Pal_EHZ, 1
PalPtr_OOZ: palptr Pal_OOZ, 1
PalPtr_MCZ: palptr Pal_MCZ, 1
PalPtr_CNZ: palptr Pal_CNZ, 1
PalPtr_CPZ: palptr Pal_CPZ, 1
PalPtr_DEZ: palptr Pal_DEZ, 1
PalPtr_ARZ: palptr Pal_ARZ, 1
PalPtr_SCZ: palptr Pal_SCZ, 1
PalPtr_HPZ_U: palptr Pal_HPZ_U, 0
PalPtr_CPZ_U: palptr Pal_CPZ_U, 0
PalPtr_ARZ_U: palptr Pal_ARZ_U, 0
PalPtr_SS: palptr Pal_SS, 0
PalPtr_MCZ_B: palptr Pal_MCZ_B, 1
PalPtr_CNZ_B: palptr Pal_CNZ_B, 1
PalPtr_SS1: palptr Pal_SS1, 3
PalPtr_SS2: palptr Pal_SS2, 3
PalPtr_SS3: palptr Pal_SS3, 3
PalPtr_SS4: palptr Pal_SS4, 3
PalPtr_SS5: palptr Pal_SS5, 3
PalPtr_SS6: palptr Pal_SS6, 3
PalPtr_SS7: palptr Pal_SS7, 3
PalPtr_SS1_2p: palptr Pal_SS1_2p,3
PalPtr_SS2_2p: palptr Pal_SS2_2p,3
PalPtr_SS3_2p: palptr Pal_SS3_2p,3
PalPtr_OOZ_B: palptr Pal_OOZ_B, 1
PalPtr_Menu: palptr Pal_Menu, 0
PalPtr_Result: palptr Pal_Result,0
; ----------------------------------------------------------------------------
; This macro defines Pal_ABC and Pal_ABC_End, so palptr can compute the size of
; the palette automatically
; path2 is used for the Sonic and Tails palette, which has 2 palette lines
palette macro {INTLABEL},path,path2
__LABEL__ label *
BINCLUDE "art/palettes/path"
if "path2"<>""
BINCLUDE "art/palettes/path2"
endif
__LABEL___End label *
endm
Pal_SEGA: palette Sega screen.bin ; SEGA screen palette (Sonic and initial background)
Pal_Title: palette Title screen.bin ; Title screen Palette
Pal_MenuB: palette S2B Level Select.bin ; Leftover S2B level select palette
Pal_BGND: palette SonicAndTails.bin,SonicAndTails2.bin ; "Sonic and Miles" background palette (also usually the primary palette line)
Pal_EHZ: palette EHZ.bin ; Emerald Hill Zone palette
Pal_WZ: palette Wood Zone.bin ; Wood Zone palette
Pal_MTZ: palette MTZ.bin ; Metropolis Zone palette
Pal_WFZ: palette WFZ.bin ; Wing Fortress Zone palette
Pal_HTZ: palette HTZ.bin ; Hill Top Zone palette
Pal_HPZ: palette HPZ.bin ; Hidden Palace Zone palette
Pal_HPZ_U: palette HPZ underwater.bin ; Hidden Palace Zone underwater palette
Pal_OOZ: palette OOZ.bin ; Oil Ocean Zone palette
Pal_MCZ: palette MCZ.bin ; Mystic Cave Zone palette
Pal_CNZ: palette CNZ.bin ; Casino Night Zone palette
Pal_CPZ: palette CPZ.bin ; Chemical Plant Zone palette
Pal_CPZ_U: palette CPZ underwater.bin ; Chemical Plant Zone underwater palette
Pal_DEZ: palette DEZ.bin ; Death Egg Zone palette
Pal_ARZ: palette ARZ.bin ; Aquatic Ruin Zone palette
Pal_ARZ_U: palette ARZ underwater.bin ; Aquatic Ruin Zone underwater palette
Pal_SCZ: palette SCZ.bin ; Sky Chase Zone palette
Pal_MCZ_B: palette MCZ Boss.bin ; Mystic Cave Zone boss palette
Pal_CNZ_B: palette CNZ Boss.bin ; Casino Night Zone boss palette
Pal_OOZ_B: palette OOZ Boss.bin ; Oil Ocean Zone boss palette
Pal_Menu: palette Menu.bin ; Menu palette
Pal_SS: palette Special Stage Main.bin ; Special Stage palette
Pal_SS1: palette Special Stage 1.bin ; Special Stage 1 palette
Pal_SS2: palette Special Stage 2.bin ; Special Stage 2 palette
Pal_SS3: palette Special Stage 3.bin ; Special Stage 3 palette
Pal_SS4: palette Special Stage 4.bin ; Special Stage 4 palette
Pal_SS5: palette Special Stage 5.bin ; Special Stage 5 palette
Pal_SS6: palette Special Stage 6.bin ; Special Stage 6 palette
Pal_SS7: palette Special Stage 7.bin ; Special Stage 7 palette
Pal_SS1_2p:palette Special Stage 1 2p.bin ; Special Stage 1 2p palette
Pal_SS2_2p:palette Special Stage 2 2p.bin ; Special Stage 2 2p palette
Pal_SS3_2p:palette Special Stage 3 2p.bin ; Special Stage 3 2p palette
Pal_Result:palette Special Stage Results Screen.bin ; Special Stage Results Screen palette
; ===========================================================================
if gameRevision<2
nop
endif
; ---------------------------------------------------------------------------
; Subroutine to perform vertical synchronization
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_3384: DelayProgram:
WaitForVint:
move #$2300,sr
- tst.b (Vint_routine).w
bne.s -
rts
; End of function WaitForVint
; ---------------------------------------------------------------------------
; Subroutine to generate a pseudo-random number in d0
; d0 = (RNG & $FFFF0000) | ((RNG*41 & $FFFF) + ((RNG*41 & $FFFF0000) >> 16))
; RNG = ((RNG*41 + ((RNG*41 & $FFFF) << 16)) & $FFFF0000) | (RNG*41 & $FFFF)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_3390:
RandomNumber:
move.l (RNG_seed).w,d1
bne.s +
move.l #$2A6D365A,d1 ; if the RNG is 0, reset it to this crazy number
; set the high word of d0 to be the high word of the RNG
; and multiply the RNG by 41
+ move.l d1,d0
asl.l #2,d1
add.l d0,d1
asl.l #3,d1
add.l d0,d1
; add the low word of the RNG to the high word of the RNG
; and set the low word of d0 to be the result
move.w d1,d0
swap d1
add.w d1,d0
move.w d0,d1
swap d1
move.l d1,(RNG_seed).w
rts
; End of function RandomNumber
; ---------------------------------------------------------------------------
; Subroutine to calculate sine and cosine of an angle
; d0 = input byte = angle (360 degrees == 256)
; d0 = output word = 255 * sine(angle)
; d1 = output word = 255 * cosine(angle)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_33B6:
CalcSine:
andi.w #$FF,d0
add.w d0,d0
addi.w #$80,d0
move.w Sine_Data(pc,d0.w),d1 ; cos
subi.w #$80,d0
move.w Sine_Data(pc,d0.w),d0 ; sin
rts
; End of function CalcSine
; ===========================================================================
; word_33CE:
Sine_Data: BINCLUDE "misc/sinewave.bin"
; ---------------------------------------------------------------------------
; Subroutine to calculate arctangent of y/x
; d1 = input x
; d2 = input y
; d0 = output angle (360 degrees == 256)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_364E:
CalcAngle:
movem.l d3-d4,-(sp)
moveq #0,d3
moveq #0,d4
move.w d1,d3
move.w d2,d4
or.w d3,d4
beq.s CalcAngle_Zero ; special case return if x and y are both 0
move.w d2,d4
absw.w d3 ; calculate absolute value of x
absw.w d4 ; calculate absolute value of y
cmp.w d3,d4
bhs.w +
lsl.l #8,d4
divu.w d3,d4
moveq #0,d0
move.b Angle_Data(pc,d4.w),d0
bra.s ++
+
lsl.l #8,d3
divu.w d4,d3
moveq #$40,d0
sub.b Angle_Data(pc,d3.w),d0
+
tst.w d1
bpl.w +
neg.w d0
addi.w #$80,d0
+
tst.w d2
bpl.w +
neg.w d0
addi.w #$100,d0
+
movem.l (sp)+,d3-d4
rts
; ===========================================================================
; loc_36AA:
CalcAngle_Zero:
move.w #$40,d0
movem.l (sp)+,d3-d4
rts
; End of function CalcAngle
; ===========================================================================
; byte_36B4:
Angle_Data: BINCLUDE "misc/angles.bin"
; ===========================================================================
if gameRevision<2
nop
endif
; loc_37B8:
SegaScreen:
move.b #MusID_Stop,d0
bsr.w PlayMusic ; stop music
bsr.w ClearPLC
bsr.w Pal_FadeToBlack
clearRAM Misc_Variables,Misc_Variables_End
clearRAM SegaScr_Object_RAM,SegaScr_Object_RAM_End ; fill object RAM with 0
lea (VDP_control_port).l,a6
move.w #$8004,(a6) ; H-INT disabled
move.w #$8200|(VRAM_SegaScr_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000
move.w #$8400|(VRAM_SegaScr_Plane_B_Name_Table/$2000),(a6) ; PNT B base: $A000
move.w #$8700,(a6) ; Background palette/color: 0/0
move.w #$8B03,(a6) ; EXT-INT disabled, V scroll by screen, H scroll by line
move.w #$8C81,(a6) ; H res 40 cells, no interlace, S/H disabled
move.w #$9003,(a6) ; Scroll table size: 128x32 ($2000 bytes)
clr.b (Water_fullscreen_flag).w
clr.w (Two_player_mode).w
move #$2700,sr
move.w (VDP_Reg1_val).w,d0
andi.b #$BF,d0
move.w d0,(VDP_control_port).l
bsr.w ClearScreen
dmaFillVRAM 0,VRAM_SegaScr_Plane_A_Name_Table,VRAM_SegaScr_Plane_Table_Size ; clear Plane A pattern name table
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Sega_Logo),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_SEGA).l,a0
bsr.w NemDec
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Trails),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_IntroTrails).l,a0
bsr.w NemDec
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtUnc_Giant_Sonic),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_SilverSonic).l,a0 ; ?? seems unused here
bsr.w NemDec
lea (Chunk_Table).l,a1
lea (MapEng_SEGA).l,a0
move.w #make_art_tile(ArtTile_VRAM_Start,0,0),d0
bsr.w EniDec
lea (Chunk_Table).l,a1
move.l #vdpComm(VRAM_SegaScr_Plane_B_Name_Table,VRAM,WRITE),d0
moveq #$27,d1 ; 40 cells wide
moveq #$1B,d2 ; 28 cells tall
bsr.w PlaneMapToVRAM_H80_Sega
tst.b (Graphics_Flags).w ; are we on a Japanese Mega Drive?
bmi.s SegaScreen_Contin ; if not, branch
; load an extra sprite to hide the TM (trademark) symbol on the SEGA screen
lea (SegaHideTM).w,a1
move.b #ObjID_SegaHideTM,id(a1) ; load objB1 at $FFFFB080
move.b #$4E,subtype(a1) ; <== ObjB1_SubObjData
; loc_38CE:
SegaScreen_Contin:
moveq #PalID_SEGA,d0
bsr.w PalLoad_Now
move.w #-$A,(PalCycle_Frame).w
move.w #0,(PalCycle_Timer).w
move.w #0,(SegaScr_VInt_Subrout).w
move.w #0,(SegaScr_PalDone_Flag).w
lea (SegaScreenObject).w,a1
move.b #ObjID_SonicOnSegaScr,id(a1) ; load objB0 (sega screen?) at $FFFFB040
move.b #$4C,subtype(a1) ; <== ObjB0_SubObjData
move.w #4*60,(Demo_Time_left).w ; 4 seconds
move.w (VDP_Reg1_val).w,d0
ori.b #$40,d0
move.w d0,(VDP_control_port).l
; loc_390E:
Sega_WaitPalette:
move.b #VintID_SEGA,(Vint_routine).w
bsr.w WaitForVint
jsrto (RunObjects).l, JmpTo_RunObjects
jsr (BuildSprites).l
tst.b (SegaScr_PalDone_Flag).w
beq.s Sega_WaitPalette
move.b #SndID_SegaSound,d0
bsr.w PlaySound ; play "SEGA" sound
move.b #VintID_SEGA,(Vint_routine).w
bsr.w WaitForVint
move.w #3*60,(Demo_Time_left).w ; 3 seconds
; loc_3940:
Sega_WaitEnd:
move.b #VintID_PCM,(Vint_routine).w
bsr.w WaitForVint
tst.w (Demo_Time_left).w
beq.s Sega_GotoTitle
move.b (Ctrl_1_Press).w,d0 ; is Start button pressed?
or.b (Ctrl_2_Press).w,d0 ; (either player)
andi.b #button_start_mask,d0
beq.s Sega_WaitEnd ; if not, branch
; loc_395E:
Sega_GotoTitle:
clr.w (SegaScr_PalDone_Flag).w
clr.w (SegaScr_VInt_Subrout).w
move.b #GameModeID_TitleScreen,(Game_Mode).w ; => TitleScreen
rts
; ---------------------------------------------------------------------------
; Subroutine that does the exact same thing as PlaneMapToVRAM_H80_SpecialStage
; (this one is used at the Sega screen)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_396E: ShowVDPGraphics3: PlaneMapToVRAM3:
PlaneMapToVRAM_H80_Sega:
lea (VDP_data_port).l,a6
move.l #vdpCommDelta(planeLocH80(0,1)),d4 ; $1000000
- move.l d0,VDP_control_port-VDP_data_port(a6)
move.w d1,d3
- move.w (a1)+,(a6)
dbf d3,-
add.l d4,d0
dbf d2,--
rts
; End of function PlaneMapToVRAM_H80_Sega
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
; sub_3990:
JmpTo_RunObjects
jmp (RunObjects).l
align 4
endif
; ===========================================================================
; loc_3998:
TitleScreen:
move.b #MusID_Stop,d0
bsr.w PlayMusic
bsr.w ClearPLC
bsr.w Pal_FadeToBlack
move #$2700,sr
lea (VDP_control_port).l,a6
move.w #$8004,(a6) ; H-INT disabled
move.w #$8200|(VRAM_TtlScr_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000
move.w #$8400|(VRAM_TtlScr_Plane_B_Name_Table/$2000),(a6) ; PNT B base: $E000
move.w #$9001,(a6) ; Scroll table size: 64x32
move.w #$9200,(a6) ; Disable window
move.w #$8B03,(a6) ; EXT-INT disabled, V scroll by screen, H scroll by line
move.w #$8720,(a6) ; Background palette/color: 2/0
clr.b (Water_fullscreen_flag).w
move.w #$8C81,(a6) ; H res 40 cells, no interlace, S/H disabled
bsr.w ClearScreen
clearRAM Sprite_Table_Input,Sprite_Table_Input_End ; fill $AC00-$AFFF with $0
clearRAM TtlScr_Object_RAM,TtlScr_Object_RAM_End ; fill object RAM ($B000-$D5FF) with $0
clearRAM Misc_Variables,Misc_Variables_End ; clear CPU player RAM and following variables
clearRAM Camera_RAM,Camera_RAM_End ; clear camera RAM and following variables
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_CreditText),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_CreditText).l,a0
bsr.w NemDec
lea (off_B2B0).l,a1
jsr (loc_B272).l
clearRAM Target_palette,Target_palette_End ; fill palette with 0 (black)
moveq #PalID_BGND,d0
bsr.w PalLoad_ForFade
bsr.w Pal_FadeFromBlack
move #$2700,sr
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Title),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_Title).l,a0
bsr.w NemDec
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_TitleSprites),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_TitleSprites).l,a0
bsr.w NemDec
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_MenuJunk),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_MenuJunk).l,a0
bsr.w NemDec
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Player1VS2),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_Player1VS2).l,a0
bsr.w NemDec
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_FontStuff_TtlScr),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_FontStuff).l,a0
bsr.w NemDec
move.b #0,(Last_star_pole_hit).w
move.b #0,(Last_star_pole_hit_2P).w
move.w #0,(Debug_placement_mode).w
move.w #0,(Demo_mode_flag).w
move.w #0,(unk_FFDA).w
move.w #0,(PalCycle_Timer).w
move.w #0,(Two_player_mode).w
move.b #0,(Level_started_flag).w
bsr.w Pal_FadeToBlack
move #$2700,sr
lea (Chunk_Table).l,a1
lea (MapEng_TitleScreen).l,a0
move.w #make_art_tile(ArtTile_ArtNem_Title,2,0),d0
bsr.w EniDec
lea (Chunk_Table).l,a1
move.l #vdpComm(VRAM_TtlScr_Plane_B_Name_Table,VRAM,WRITE),d0
moveq #$27,d1
moveq #$1B,d2
jsrto (PlaneMapToVRAM_H40).l, PlaneMapToVRAM_H40
lea (Chunk_Table).l,a1
lea (MapEng_TitleBack).l,a0
move.w #make_art_tile(ArtTile_ArtNem_Title,2,0),d0
bsr.w EniDec
lea (Chunk_Table).l,a1
move.l #vdpComm(VRAM_TtlScr_Plane_B_Name_Table + planeLocH40($28,0),VRAM,WRITE),d0
moveq #$17,d1
moveq #$1B,d2
jsrto (PlaneMapToVRAM_H40).l, PlaneMapToVRAM_H40
lea (Chunk_Table).l,a1
lea (MapEng_TitleLogo).l,a0
move.w #make_art_tile(ArtTile_ArtNem_Title,3,1),d0
bsr.w EniDec
lea (Chunk_Table+$858).l,a1
lea (CopyrightText).l,a2
moveq #bytesToWcnt(CopyrightText_End-CopyrightText),d6
- move.w (a2)+,(a1)+ ; load mappings for copyright 1992 sega message
dbf d6,-
lea (Chunk_Table).l,a1
move.l #vdpComm(VRAM_TtlScr_Plane_A_Name_Table,VRAM,WRITE),d0
moveq #$27,d1
moveq #$1B,d2
jsrto (PlaneMapToVRAM_H40).l, PlaneMapToVRAM_H40
clearRAM Normal_palette,Target_palette_End ; fill two palettes with 0 (black)
moveq #PalID_Title,d0
bsr.w PalLoad_ForFade
move.b #0,(Debug_mode_flag).w
move.w #0,(Two_player_mode).w
move.w #$280,(Demo_Time_left).w
clr.w (Ctrl_1).w
move.b #ObjID_IntroStars,(IntroSonic+id).w ; load Obj0E (flashing intro star)
move.b #2,(IntroSonic+subtype).w ; Sonic
jsr (RunObjects).l
jsr (BuildSprites).l
moveq #PLCID_Std1,d0
bsr.w LoadPLC2
move.w #0,(Correct_cheat_entries).w
move.w #0,(Correct_cheat_entries_2).w
nop
nop
nop
nop
nop
nop
move.w #4,(Sonic_Pos_Record_Index).w
move.w #0,(Sonic_Pos_Record_Buf).w
lea (Results_Data_2P).w,a1
moveq #bytesToWcnt(Results_Data_2P_End-Results_Data_2P),d0
- move.w #-1,(a1)+
dbf d0,-
move.w #-$280,(Camera_X_pos).w
move.w (VDP_Reg1_val).w,d0
ori.b #$40,d0
move.w d0,(VDP_control_port).l
bsr.w Pal_FadeFromBlack
; loc_3C14:
TitleScreen_Loop:
move.b #VintID_Title,(Vint_routine).w
bsr.w WaitForVint
jsr (RunObjects).l
jsrto (SwScrl_Title).l, JmpTo_SwScrl_Title
jsr (BuildSprites).l
; write alternating 0s and 4s, 80 times, at every 4th word,
; starting at Sprite_Table+6
lea (Sprite_Table+4).w,a1
moveq #0,d0
moveq #79,d6
- tst.w (a1)
bne.s +
bchg #2,d0
move.w d0,2(a1)
+ addq.w #8,a1
dbf d6,-
bsr.w RunPLC_RAM
bsr.w TailsNameCheat
tst.w (Demo_Time_left).w
beq.w TitleScreen_Demo
tst.b (IntroSonic+objoff_2F).w
beq.w TitleScreen_Loop
move.b (Ctrl_1_Press).w,d0
or.b (Ctrl_2_Press).w,d0
andi.b #button_start_mask,d0
beq.w TitleScreen_Loop ; loop until Start is pressed
move.b #GameModeID_Level,(Game_Mode).w ; => Level (Zone play mode)
move.b #3,(Life_count).w
move.b #3,(Life_count_2P).w
moveq #0,d0
move.w d0,(Ring_count).w
move.l d0,(Timer).w
move.l d0,(Score).w
move.w d0,(Ring_count_2P).w
move.l d0,(Timer_2P).w
move.l d0,(Score_2P).w
move.b d0,(Continue_count).w
move.l #5000,(Next_Extra_life_score).w
move.l #5000,(Next_Extra_life_score_2P).w
move.b #MusID_FadeOut,d0 ; prepare to stop music (fade out)
bsr.w PlaySound
moveq #0,d0
move.b (Title_screen_option).w,d0
bne.s TitleScreen_CheckIfChose2P ; branch if not a 1-player game
moveq #0,d0
move.w d0,(Two_player_mode_copy).w
move.w d0,(Two_player_mode).w
if emerald_hill_zone_act_1=0
move.w d0,(Current_ZoneAndAct).w ; emerald_hill_zone_act_1
else
move.w #emerald_hill_zone_act_1,(Current_ZoneAndAct).w
endif
tst.b (Level_select_flag).w ; has level select cheat been entered?
beq.s + ; if not, branch
btst #button_A,(Ctrl_1_Held).w ; is A held down?
beq.s + ; if not, branch
move.b #GameModeID_LevelSelect,(Game_Mode).w ; => LevelSelectMenu
rts
; ---------------------------------------------------------------------------
+
move.w d0,(Current_Special_StageAndAct).w
move.w d0,(Got_Emerald).w
move.l d0,(Got_Emeralds_array).w
move.l d0,(Got_Emeralds_array+4).w
rts
; ===========================================================================
; loc_3CF6:
TitleScreen_CheckIfChose2P:
subq.b #1,d0
bne.s TitleScreen_ChoseOptions
moveq #1,d1
move.w d1,(Two_player_mode_copy).w
move.w d1,(Two_player_mode).w
moveq #0,d0
move.w d0,(Got_Emerald).w
move.l d0,(Got_Emeralds_array).w
move.l d0,(Got_Emeralds_array+4).w
move.b #GameModeID_2PLevelSelect,(Game_Mode).w ; => LevelSelectMenu2P
move.b #emerald_hill_zone,(Current_Zone_2P).w
rts
; ---------------------------------------------------------------------------
; loc_3D20:
TitleScreen_ChoseOptions:
move.b #GameModeID_OptionsMenu,(Game_Mode).w ; => OptionsMenu
move.b #0,(Options_menu_box).w
rts
; ===========================================================================
; loc_3D2E:
TitleScreen_Demo:
move.b #MusID_FadeOut,d0
bsr.w PlaySound
move.w (Demo_number).w,d0
andi.w #7,d0
add.w d0,d0
move.w DemoLevels(pc,d0.w),d0
move.w d0,(Current_ZoneAndAct).w
addq.w #1,(Demo_number).w
cmpi.w #(DemoLevels_End-DemoLevels)/2,(Demo_number).w
blo.s +
move.w #0,(Demo_number).w
+
move.w #1,(Demo_mode_flag).w
move.b #GameModeID_Demo,(Game_Mode).w ; => Level (Demo mode)
cmpi.w #emerald_hill_zone_act_1,(Current_ZoneAndAct).w
bne.s +
move.w #1,(Two_player_mode).w
+
move.b #3,(Life_count).w
move.b #3,(Life_count_2P).w
moveq #0,d0
move.w d0,(Ring_count).w
move.l d0,(Timer).w
move.l d0,(Score).w
move.w d0,(Ring_count_2P).w
move.l d0,(Timer_2P).w
move.l d0,(Score_2P).w
move.l #5000,(Next_Extra_life_score).w
move.l #5000,(Next_Extra_life_score_2P).w
rts
; ===========================================================================
; word_3DAC:
DemoLevels:
dc.w emerald_hill_zone_act_1 ; EHZ (2P)
dc.w chemical_plant_zone_act_1 ; CPZ
dc.w aquatic_ruin_zone_act_1 ; ARZ
dc.w casino_night_zone_act_1 ; CNZ
DemoLevels_End:
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_3DB4:
TailsNameCheat:
lea (TailsNameCheat_Buttons).l,a0
move.w (Correct_cheat_entries).w,d0
adda.w d0,a0
move.b (Ctrl_1_Press).w,d0
andi.b #button_up_mask|button_down_mask|button_left_mask|button_right_mask,d0
beq.s ++ ; rts
cmp.b (a0),d0
bne.s +
addq.w #1,(Correct_cheat_entries).w
tst.b 1(a0) ; read the next entry
bne.s ++ ; if it's not zero, return
bchg #7,(Graphics_Flags).w ; turn on the cheat that changes MILES to "TAILS"
move.b #SndID_Ring,d0 ; play the ring sound for a successfully entered cheat
bsr.w PlaySound
+ move.w #0,(Correct_cheat_entries).w
+ rts
; End of function TailsNameCheat
; ===========================================================================
; byte_3DEE:
TailsNameCheat_Buttons:
dc.b button_up_mask
dc.b button_down_mask
dc.b button_down_mask
dc.b button_down_mask
dc.b button_up_mask
dc.b 0 ; end
; ---------------------------------------------------------------------------------
; Nemesis compressed art
; 10 blocks
; Player 1 2 VS Text
; ---------------------------------------------------------------------------------
; ArtNem_3DF4:
ArtNem_Player1VS2: BINCLUDE "art/nemesis/1Player2VS.bin"
charset '0','9',0 ; Add character set for numbers
charset '*',$A ; Add character for star
charset '@',$B ; Add character for copyright symbol
charset ':',$C ; Add character for colon
charset '.',$D ; Add character for period
charset 'A','Z',$E ; Add character set for letters
; word_3E82:
CopyrightText:
dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + '@',0,0) ; (C)
dc.w make_art_tile(ArtTile_VRAM_Start,0,0) ;
dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + '1',0,0) ; 1
dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + '9',0,0) ; 9
dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + '9',0,0) ; 9
dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + '2',0,0) ; 2
dc.w make_art_tile(ArtTile_VRAM_Start,0,0) ;
dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + 'S',0,0) ; S
dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + 'E',0,0) ; E
dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + 'G',0,0) ; G
dc.w make_art_tile(ArtTile_ArtNem_FontStuff_TtlScr + 'A',0,0) ; A
CopyrightText_End:
charset ; Revert character set
if ~~removeJmpTos
; sub_3E98:
JmpTo_SwScrl_Title
jmp (SwScrl_Title).l
align 4
endif
;----------------------------------------------------------------------------
; 1P Music Playlist
;----------------------------------------------------------------------------
; byte_3EA0:
MusicList: zoneOrderedTable 1,1
zoneTableEntry.b MusID_EHZ ; 0 ; EHZ
zoneTableEntry.b MusID_EHZ ; 1
zoneTableEntry.b MusID_MTZ ; 2
zoneTableEntry.b MusID_OOZ ; 3
zoneTableEntry.b MusID_MTZ ; 4 ; MTZ1,2
zoneTableEntry.b MusID_MTZ ; 5 ; MTZ3
zoneTableEntry.b MusID_WFZ ; 6 ; WFZ
zoneTableEntry.b MusID_HTZ ; 7 ; HTZ
zoneTableEntry.b MusID_HPZ ; 8
zoneTableEntry.b MusID_SCZ ; 9
zoneTableEntry.b MusID_OOZ ; 10 ; OOZ
zoneTableEntry.b MusID_MCZ ; 11 ; MCZ
zoneTableEntry.b MusID_CNZ ; 12 ; CNZ
zoneTableEntry.b MusID_CPZ ; 13 ; CPZ
zoneTableEntry.b MusID_DEZ ; 14 ; DEZ
zoneTableEntry.b MusID_ARZ ; 15 ; ARZ
zoneTableEntry.b MusID_SCZ ; 16 ; SCZ
zoneTableEnd
even
;----------------------------------------------------------------------------
; 2P Music Playlist
;----------------------------------------------------------------------------
; byte_3EB2:
MusicList2: zoneOrderedTable 1,1
zoneTableEntry.b MusID_EHZ_2P ; 0 ; EHZ 2P
zoneTableEntry.b MusID_EHZ ; 1
zoneTableEntry.b MusID_MTZ ; 2
zoneTableEntry.b MusID_OOZ ; 3
zoneTableEntry.b MusID_MTZ ; 4
zoneTableEntry.b MusID_MTZ ; 5
zoneTableEntry.b MusID_WFZ ; 6
zoneTableEntry.b MusID_HTZ ; 7
zoneTableEntry.b MusID_HPZ ; 8
zoneTableEntry.b MusID_SCZ ; 9
zoneTableEntry.b MusID_OOZ ; 10
zoneTableEntry.b MusID_MCZ_2P ; 11 ; MCZ 2P
zoneTableEntry.b MusID_CNZ_2P ; 12 ; CNZ 2P
zoneTableEntry.b MusID_CPZ ; 13
zoneTableEntry.b MusID_DEZ ; 14
zoneTableEntry.b MusID_ARZ ; 15
zoneTableEntry.b MusID_SCZ ; 16
zoneTableEnd
even
; ===========================================================================
; ---------------------------------------------------------------------------
; Level
; DEMO AND ZONE LOOP (MLS values $08, $0C; bit 7 set indicates that load routine is running)
; ---------------------------------------------------------------------------
; loc_3EC4:
Level:
bset #GameModeFlag_TitleCard,(Game_Mode).w ; add $80 to screen mode (for pre level sequence)
tst.w (Demo_mode_flag).w ; test the old flag for the credits demos (now unused)
bmi.s +
move.b #MusID_FadeOut,d0
bsr.w PlaySound ; fade out music
+
bsr.w ClearPLC
bsr.w Pal_FadeToBlack
tst.w (Demo_mode_flag).w
bmi.s Level_ClrRam
move #$2700,sr
bsr.w ClearScreen
jsr (LoadTitleCard).l ; load title card patterns
move #$2300,sr
moveq #0,d0
move.w d0,(Timer_frames).w
move.b (Current_Zone).w,d0
; multiply d0 by 12, the size of a level art load block
add.w d0,d0
add.w d0,d0
move.w d0,d1
add.w d0,d0
add.w d1,d0
lea (LevelArtPointers).l,a2
lea (a2,d0.w),a2
moveq #0,d0
move.b (a2),d0 ; PLC1 ID
beq.s +
bsr.w LoadPLC
+
moveq #PLCID_Std2,d0
bsr.w LoadPLC
bsr.w Level_SetPlayerMode
moveq #PLCID_Miles1up,d0
tst.w (Two_player_mode).w
bne.s +
cmpi.w #2,(Player_mode).w
bne.s Level_ClrRam
addq.w #PLCID_MilesLife-PLCID_Miles1up,d0
+
tst.b (Graphics_Flags).w
bpl.s +
addq.w #PLCID_Tails1up-PLCID_Miles1up,d0
+
bsr.w LoadPLC
; loc_3F48:
Level_ClrRam:
clearRAM Sprite_Table_Input,Sprite_Table_Input_End
clearRAM Object_RAM,Object_RAM_End ; clear object RAM
clearRAM MiscLevelVariables,MiscLevelVariables_End
clearRAM Misc_Variables,Misc_Variables_End
clearRAM Oscillating_Data,Oscillating_variables_End
; Bug: The '+C0' shouldn't be here; CNZ_saucer_data is only $40 bytes large
clearRAM CNZ_saucer_data,CNZ_saucer_data_End+$C0
cmpi.w #chemical_plant_zone_act_2,(Current_ZoneAndAct).w ; CPZ 2
beq.s Level_InitWater
cmpi.b #aquatic_ruin_zone,(Current_Zone).w ; ARZ
beq.s Level_InitWater
cmpi.b #hidden_palace_zone,(Current_Zone).w ; HPZ
bne.s +
Level_InitWater:
move.b #1,(Water_flag).w
move.w #0,(Two_player_mode).w
+
lea (VDP_control_port).l,a6
move.w #$8B03,(a6) ; EXT-INT disabled, V scroll by screen, H scroll by line
move.w #$8200|(VRAM_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000
move.w #$8400|(VRAM_Plane_B_Name_Table/$2000),(a6) ; PNT B base: $E000
move.w #$8500|(VRAM_Sprite_Attribute_Table/$200),(a6) ; Sprite attribute table base: $F800
move.w #$9001,(a6) ; Scroll table size: 64x32
move.w #$8004,(a6) ; H-INT disabled
move.w #$8720,(a6) ; Background palette/color: 2/0
move.w #$8C81,(a6) ; H res 40 cells, no interlace
tst.b (Debug_options_flag).w
beq.s ++
btst #button_C,(Ctrl_1_Held).w
beq.s +
move.w #$8C89,(a6) ; H res 40 cells, no interlace, S/H enabled
+
btst #button_A,(Ctrl_1_Held).w
beq.s +
move.b #1,(Debug_mode_flag).w
+
move.w #$8ADF,(Hint_counter_reserve).w ; H-INT every 223rd scanline
tst.w (Two_player_mode).w
beq.s +
move.w #$8A6B,(Hint_counter_reserve).w ; H-INT every 108th scanline
move.w #$8014,(a6) ; H-INT enabled
move.w #$8C87,(a6) ; H res 40 cells, double res interlace
+
move.w (Hint_counter_reserve).w,(a6)
clr.w (VDP_Command_Buffer).w
move.l #VDP_Command_Buffer,(VDP_Command_Buffer_Slot).w
tst.b (Water_flag).w ; does level have water?
beq.s Level_LoadPal ; if not, branch
move.w #$8014,(a6) ; H-INT enabled
moveq #0,d0
move.w (Current_ZoneAndAct).w,d0
if ~~useFullWaterTables
subi.w #hidden_palace_zone_act_1,d0
endif
ror.b #1,d0
lsr.w #6,d0
andi.w #$FFFE,d0
lea (WaterHeight).l,a1 ; load water height array
move.w (a1,d0.w),d0
move.w d0,(Water_Level_1).w ; set water heights
move.w d0,(Water_Level_2).w
move.w d0,(Water_Level_3).w
clr.b (Water_routine).w ; clear water routine counter
clr.b (Water_fullscreen_flag).w ; clear water movement
move.b #1,(Water_on).w ; enable water
; loc_407C:
Level_LoadPal:
moveq #PalID_BGND,d0
bsr.w PalLoad_Now ; load Sonic's palette line
tst.b (Water_flag).w ; does level have water?
beq.s Level_GetBgm ; if not, branch
moveq #PalID_HPZ_U,d0 ; palette number $15
cmpi.b #hidden_palace_zone,(Current_Zone).w
beq.s Level_WaterPal ; branch if level is HPZ
moveq #PalID_CPZ_U,d0 ; palette number $16
cmpi.b #chemical_plant_zone,(Current_Zone).w
beq.s Level_WaterPal ; branch if level is CPZ
moveq #PalID_ARZ_U,d0 ; palette number $17
; loc_409E:
Level_WaterPal:
bsr.w PalLoad_Water_Now ; load underwater palette (with d0)
tst.b (Last_star_pole_hit).w ; is it the start of the level?
beq.s Level_GetBgm ; if yes, branch
move.b (Saved_Water_move).w,(Water_fullscreen_flag).w
; loc_40AE:
Level_GetBgm:
tst.w (Demo_mode_flag).w
bmi.s +
moveq #0,d0
move.b (Current_Zone).w,d0
lea_ MusicList,a1
tst.w (Two_player_mode).w
beq.s Level_PlayBgm
lea_ MusicList2,a1
; loc_40C8:
Level_PlayBgm:
move.b (a1,d0.w),d0 ; load from music playlist
move.w d0,(Level_Music).w ; store level music
bsr.w PlayMusic ; play level music
move.b #ObjID_TitleCard,(TitleCard+id).w ; load Obj34 (level title card) at $FFFFB080
; loc_40DA:
Level_TtlCard:
move.b #VintID_TitleCard,(Vint_routine).w
bsr.w WaitForVint
jsr (RunObjects).l
jsr (BuildSprites).l
bsr.w RunPLC_RAM
move.w (TitleCard_ZoneName+x_pos).w,d0
cmp.w (TitleCard_ZoneName+titlecard_x_target).w,d0 ; has title card sequence finished?
bne.s Level_TtlCard ; if not, branch
tst.l (Plc_Buffer).w ; are there any items in the pattern load cue?
bne.s Level_TtlCard ; if yes, branch
move.b #VintID_TitleCard,(Vint_routine).w
bsr.w WaitForVint
jsr (Hud_Base).l
+
moveq #PalID_BGND,d0
bsr.w PalLoad_ForFade ; load Sonic's palette line
bsr.w LevelSizeLoad
jsrto (DeformBgLayer).l, JmpTo_DeformBgLayer
clr.w (Vscroll_Factor_FG).w
move.w #-$E0,(Vscroll_Factor_P2_FG).w
clearRAM Horiz_Scroll_Buf,Horiz_Scroll_Buf_End
bsr.w LoadZoneTiles
jsrto (loadZoneBlockMaps).l, JmpTo_loadZoneBlockMaps
jsr (loc_402D4).l
jsrto (DrawInitialBG).l, JmpTo_DrawInitialBG
jsr (FloorLog_Unk).l
bsr.w LoadCollisionIndexes
bsr.w WaterEffects
bsr.w InitPlayers
move.w #0,(Ctrl_1_Logical).w
move.w #0,(Ctrl_2_Logical).w
move.w #0,(Ctrl_1).w
move.w #0,(Ctrl_2).w
move.b #1,(Control_Locked).w
move.b #1,(Control_Locked_P2).w
move.b #0,(Level_started_flag).w
; Level_ChkWater:
tst.b (Water_flag).w ; does level have water?
beq.s + ; if not, branch
move.b #ObjID_WaterSurface,(WaterSurface1+id).w ; load Obj04 (water surface) at $FFFFB380
move.w #$60,(WaterSurface1+x_pos).w ; set horizontal offset
move.b #ObjID_WaterSurface,(WaterSurface2+id).w ; load Obj04 (water surface) at $FFFFB3C0
move.w #$120,(WaterSurface2+x_pos).w ; set different horizontal offset
+
cmpi.b #chemical_plant_zone,(Current_Zone).w ; check if zone == CPZ
bne.s + ; branch if not
move.b #ObjID_CPZPylon,(CPZPylon+id).w ; load Obj7C (CPZ pylon) at $FFFFB340
+
cmpi.b #oil_ocean_zone,(Current_Zone).w ; check if zone == OOZ
bne.s Level_ClrHUD ; branch if not
move.b #ObjID_Oil,(Oil+id).w ; load Obj07 (OOZ oil) at $FFFFB380
; Level_LoadObj: misnomer now
Level_ClrHUD:
moveq #0,d0
tst.b (Last_star_pole_hit).w ; are you starting from a lamppost?
bne.s Level_FromCheckpoint ; if yes, branch
move.w d0,(Ring_count).w ; clear rings
move.l d0,(Timer).w ; clear time
move.b d0,(Extra_life_flags).w ; clear extra lives counter
move.w d0,(Ring_count_2P).w ; ditto for player 2
move.l d0,(Timer_2P).w
move.b d0,(Extra_life_flags_2P).w
; loc_41E4:
Level_FromCheckpoint:
move.b d0,(Time_Over_flag).w
move.b d0,(Time_Over_flag_2P).w
move.b d0,(SlotMachine_Routine).w
move.w d0,(SlotMachineInUse).w
move.w d0,(Debug_placement_mode).w
move.w d0,(Level_Inactive_flag).w
move.b d0,(Teleport_timer).w
move.b d0,(Teleport_flag).w
move.w d0,(Rings_Collected).w
move.w d0,(Rings_Collected_2P).w
move.w d0,(Monitors_Broken).w
move.w d0,(Monitors_Broken_2P).w
move.w d0,(Loser_Time_Left).w
bsr.w OscillateNumInit
move.b #1,(Update_HUD_score).w
move.b #1,(Update_HUD_rings).w
move.b #1,(Update_HUD_timer).w
move.b #1,(Update_HUD_timer_2P).w
jsr (ObjectsManager).l
jsr (RingsManager).l
jsr (SpecialCNZBumpers).l
jsr (RunObjects).l
jsr (BuildSprites).l
jsrto (AniArt_Load).l, JmpTo_AniArt_Load
bsr.w SetLevelEndType
move.w #0,(Demo_button_index).w
move.w #0,(Demo_button_index_2P).w
lea (DemoScriptPointers).l,a1
moveq #0,d0
move.b (Current_Zone).w,d0 ; load zone value
lsl.w #2,d0
movea.l (a1,d0.w),a1
tst.w (Demo_mode_flag).w
bpl.s +
lea (EndingDemoScriptPointers).l,a1
move.w (Ending_demo_number).w,d0
subq.w #1,d0
lsl.w #2,d0
movea.l (a1,d0.w),a1
+
move.b 1(a1),(Demo_press_counter).w
tst.b (Current_Zone).w ; emerald_hill_zone
bne.s +
lea (Demo_EHZ_Tails).l,a1
move.b 1(a1),(Demo_press_counter_2P).w
+
move.w #$668,(Demo_Time_left).w
tst.w (Demo_mode_flag).w
bpl.s +
move.w #$21C,(Demo_Time_left).w
cmpi.w #4,(Ending_demo_number).w
bne.s +
move.w #$1FE,(Demo_Time_left).w
+
tst.b (Water_flag).w
beq.s ++
moveq #PalID_HPZ_U,d0
cmpi.b #hidden_palace_zone,(Current_Zone).w
beq.s +
moveq #PalID_CPZ_U,d0
cmpi.b #chemical_plant_zone,(Current_Zone).w
beq.s +
moveq #PalID_ARZ_U,d0
+
bsr.w PalLoad_Water_ForFade
+
move.w #-1,(TitleCard_ZoneName+titlecard_leaveflag).w
move.b #$E,(TitleCard_Left+routine).w ; make the left part move offscreen
move.w #$A,(TitleCard_Left+titlecard_location).w
- move.b #VintID_TitleCard,(Vint_routine).w
bsr.w WaitForVint
jsr (RunObjects).l
jsr (BuildSprites).l
bsr.w RunPLC_RAM
tst.b (TitleCard_Background+id).w
bne.s - ; loop while the title card background is still loaded
lea (TitleCard).w,a1
move.b #$16,TitleCard_ZoneName-TitleCard+routine(a1)
move.w #$2D,TitleCard_ZoneName-TitleCard+anim_frame_duration(a1)
move.b #$16,TitleCard_Zone-TitleCard+routine(a1)
move.w #$2D,TitleCard_Zone-TitleCard+anim_frame_duration(a1)
tst.b TitleCard_ActNumber-TitleCard+id(a1)
beq.s + ; branch if the act number has been unloaded
move.b #$16,TitleCard_ActNumber-TitleCard+routine(a1)
move.w #$2D,TitleCard_ActNumber-TitleCard+anim_frame_duration(a1)
+ move.b #0,(Control_Locked).w
move.b #0,(Control_Locked_P2).w
move.b #1,(Level_started_flag).w
; Level_StartGame: loc_435A:
bclr #GameModeFlag_TitleCard,(Game_Mode).w ; clear $80 from the game mode
; ---------------------------------------------------------------------------
; Main level loop (when all title card and loading sequences are finished)
; ---------------------------------------------------------------------------
; loc_4360:
Level_MainLoop:
bsr.w PauseGame
move.b #VintID_Level,(Vint_routine).w
bsr.w WaitForVint
addq.w #1,(Timer_frames).w ; add 1 to level timer
bsr.w MoveSonicInDemo
bsr.w WaterEffects
jsr (RunObjects).l
tst.w (Level_Inactive_flag).w
bne.w Level
jsrto (DeformBgLayer).l, JmpTo_DeformBgLayer
bsr.w UpdateWaterSurface
jsr (RingsManager).l
cmpi.b #casino_night_zone,(Current_Zone).w ; is it CNZ?
bne.s + ; if not, branch past jsr
jsr (SpecialCNZBumpers).l
+
jsrto (AniArt_Load).l, JmpTo_AniArt_Load
bsr.w PalCycle_Load
bsr.w RunPLC_RAM
bsr.w OscillateNumDo
bsr.w ChangeRingFrame
bsr.w CheckLoadSignpostArt
jsr (BuildSprites).l
jsr (ObjectsManager).l
cmpi.b #GameModeID_Demo,(Game_Mode).w ; check if in demo mode
beq.s +
cmpi.b #GameModeID_Level,(Game_Mode).w ; check if in normal play mode
beq.w Level_MainLoop
rts
; ---------------------------------------------------------------------------
+
tst.w (Level_Inactive_flag).w
bne.s +
tst.w (Demo_Time_left).w
beq.s +
cmpi.b #GameModeID_Demo,(Game_Mode).w
beq.w Level_MainLoop
move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen
rts
; ---------------------------------------------------------------------------
+
cmpi.b #GameModeID_Demo,(Game_Mode).w
bne.s +
move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen
+
move.w #1*60,(Demo_Time_left).w ; 1 second
move.w #$3F,(Palette_fade_range).w
clr.w (PalChangeSpeed).w
-
move.b #VintID_Level,(Vint_routine).w
bsr.w WaitForVint
bsr.w MoveSonicInDemo
jsr (RunObjects).l
jsr (BuildSprites).l
jsr (ObjectsManager).l
subq.w #1,(PalChangeSpeed).w
bpl.s +
move.w #2,(PalChangeSpeed).w
bsr.w Pal_FadeToBlack.UpdateAllColours
+
tst.w (Demo_Time_left).w
bne.s -
rts
; ---------------------------------------------------------------------------
; Subroutine to set the player mode, which is forced to Sonic and Tails in
; the demo mode and in 2P mode
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_4450:
Level_SetPlayerMode:
cmpi.b #GameModeID_TitleCard|GameModeID_Demo,(Game_Mode).w ; pre-level demo mode?
beq.s + ; if yes, branch
tst.w (Two_player_mode).w ; 2P mode?
bne.s + ; if yes, branch
move.w (Player_option).w,(Player_mode).w ; use the option chosen in the Options screen
rts
; ---------------------------------------------------------------------------
+ move.w #0,(Player_mode).w ; force Sonic and Tails
rts
; End of function Level_SetPlayerMode
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_446E:
InitPlayers:
move.w (Player_mode).w,d0
bne.s InitPlayers_Alone ; branch if this isn't a Sonic and Tails game
move.b #ObjID_Sonic,(MainCharacter+id).w ; load Obj01 Sonic object at $FFFFB000
move.b #ObjID_SpindashDust,(Sonic_Dust+id).w ; load Obj08 Sonic's spindash dust/splash object at $FFFFD100
cmpi.b #wing_fortress_zone,(Current_Zone).w
beq.s + ; skip loading Tails if this is WFZ
cmpi.b #death_egg_zone,(Current_Zone).w
beq.s + ; skip loading Tails if this is DEZ
cmpi.b #sky_chase_zone,(Current_Zone).w
beq.s + ; skip loading Tails if this is SCZ
move.b #ObjID_Tails,(Sidekick+id).w ; load Obj02 Tails object at $FFFFB040
move.w (MainCharacter+x_pos).w,(Sidekick+x_pos).w
move.w (MainCharacter+y_pos).w,(Sidekick+y_pos).w
subi.w #$20,(Sidekick+x_pos).w
addi_.w #4,(Sidekick+y_pos).w
move.b #ObjID_SpindashDust,(Tails_Dust+id).w ; load Obj08 Tails' spindash dust/splash object at $FFFFD140
+
rts
; ===========================================================================
; loc_44BE:
InitPlayers_Alone: ; either Sonic or Tails but not both
subq.w #1,d0
bne.s InitPlayers_TailsAlone ; branch if this is a Tails alone game
move.b #ObjID_Sonic,(MainCharacter+id).w ; load Obj01 Sonic object at $FFFFB000
move.b #ObjID_SpindashDust,(Sonic_Dust+id).w ; load Obj08 Sonic's spindash dust/splash object at $FFFFD100
rts
; ===========================================================================
; loc_44D0:
InitPlayers_TailsAlone:
move.b #ObjID_Tails,(MainCharacter+id).w ; load Obj02 Tails object at $FFFFB000
move.b #ObjID_SpindashDust,(Tails_Dust+id).w ; load Obj08 Tails' spindash dust/splash object at $FFFFD100
addi_.w #4,(MainCharacter+y_pos).w
rts
; End of function InitPlayers
; ---------------------------------------------------------------------------
; Subroutine to move the water or oil surface sprites to where the screen is at
; (the closest match I could find to this subroutine in Sonic 1 is Obj1B_Action)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_44E4:
UpdateWaterSurface:
tst.b (Water_flag).w
beq.s ++ ; rts
move.w (Camera_X_pos).w,d1
btst #0,(Timer_frames+1).w
beq.s +
addi.w #$20,d1
+ ; match obj x-position to screen position
move.w d1,d0
addi.w #$60,d0
move.w d0,(WaterSurface1+x_pos).w
addi.w #$120,d1
move.w d1,(WaterSurface2+x_pos).w
+
rts
; End of function UpdateWaterSurface
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; ---------------------------------------------------------------------------
; Subroutine to do special water effects
; ---------------------------------------------------------------------------
; sub_450E: ; LZWaterEffects:
WaterEffects:
tst.b (Water_flag).w ; does level have water?
beq.s NonWaterEffects ; if not, branch
tst.b (Deform_lock).w
bne.s MoveWater
cmpi.b #6,(MainCharacter+routine).w ; is player dead?
bhs.s MoveWater ; if yes, branch
bsr.w DynamicWater
; loc_4526: ; LZMoveWater:
MoveWater:
clr.b (Water_fullscreen_flag).w
moveq #0,d0
cmpi.b #aquatic_ruin_zone,(Current_Zone).w ; is level ARZ?
beq.s + ; if yes, branch
move.b (Oscillating_Data).w,d0
lsr.w #1,d0
+
add.w (Water_Level_2).w,d0
move.w d0,(Water_Level_1).w
; calculate distance between water surface and top of screen
move.w (Water_Level_1).w,d0
sub.w (Camera_Y_pos).w,d0
bhs.s +
tst.w d0
bpl.s +
move.b #$DF,(Hint_counter_reserve+1).w ; H-INT every 224th scanline
move.b #1,(Water_fullscreen_flag).w
+
cmpi.w #$DF,d0
blo.s +
move.w #$DF,d0
+
move.b d0,(Hint_counter_reserve+1).w ; H-INT every d0 scanlines
; loc_456A:
NonWaterEffects:
cmpi.b #oil_ocean_zone,(Current_Zone).w ; is the level OOZ?
bne.s + ; if not, branch
bsr.w OilSlides ; call oil slide routine
+
cmpi.b #wing_fortress_zone,(Current_Zone).w ; is the level WFZ?
bne.s + ; if not, branch
bsr.w WindTunnel ; call wind and block break routine
+
rts
; End of function WaterEffects
; ===========================================================================
if useFullWaterTables
WaterHeight: zoneOrderedTable 2,2
zoneTableEntry.w $600, $600 ; EHZ
zoneTableEntry.w $600, $600 ; Zone 1
zoneTableEntry.w $600, $600 ; WZ
zoneTableEntry.w $600, $600 ; Zone 3
zoneTableEntry.w $600, $600 ; MTZ
zoneTableEntry.w $600, $600 ; MTZ
zoneTableEntry.w $600, $600 ; WFZ
zoneTableEntry.w $600, $600 ; HTZ
zoneTableEntry.w $600, $600 ; HPZ
zoneTableEntry.w $600, $600 ; Zone 9
zoneTableEntry.w $600, $600 ; OOZ
zoneTableEntry.w $600, $600 ; MCZ
zoneTableEntry.w $600, $600 ; CNZ
zoneTableEntry.w $600, $710 ; CPZ
zoneTableEntry.w $600, $600 ; DEZ
zoneTableEntry.w $410, $510 ; ARZ
zoneTableEntry.w $600, $600 ; SCZ
zoneTableEnd
else
; word_4584:
WaterHeight:
dc.w $600, $600 ; HPZ
dc.w $600, $600 ; Zone 9
dc.w $600, $600 ; OOZ
dc.w $600, $600 ; MCZ
dc.w $600, $600 ; CNZ
dc.w $600, $710 ; CPZ
dc.w $600, $600 ; DEZ
dc.w $410, $510 ; ARZ
endif
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_45A4: ; LZDynamicWater:
DynamicWater:
moveq #0,d0
move.w (Current_ZoneAndAct).w,d0
if ~~useFullWaterTables
subi.w #hidden_palace_zone_act_1,d0
endif
ror.b #1,d0
lsr.w #6,d0
andi.w #$FFFE,d0
move.w Dynamic_water_routine_table(pc,d0.w),d0
jsr Dynamic_water_routine_table(pc,d0.w)
moveq #0,d1
move.b (Water_on).w,d1
move.w (Water_Level_3).w,d0
sub.w (Water_Level_2).w,d0
beq.s ++ ; rts
bcc.s +
neg.w d1
+
add.w d1,(Water_Level_2).w
+
rts
; End of function DynamicWater
; ===========================================================================
if useFullWaterTables
Dynamic_water_routine_table: zoneOrderedOffsetTable 2,2
zoneOffsetTableEntry.w DynamicWaterNull ; EHZ 1
zoneOffsetTableEntry.w DynamicWaterNull ; EHZ 2
zoneOffsetTableEntry.w DynamicWaterNull ; Zone 1
zoneOffsetTableEntry.w DynamicWaterNull ; Zone 1
zoneOffsetTableEntry.w DynamicWaterNull ; WZ 1
zoneOffsetTableEntry.w DynamicWaterNull ; WZ 2
zoneOffsetTableEntry.w DynamicWaterNull ; Zone 3
zoneOffsetTableEntry.w DynamicWaterNull ; Zone 3
zoneOffsetTableEntry.w DynamicWaterNull ; MTZ 1
zoneOffsetTableEntry.w DynamicWaterNull ; MTZ 2
zoneOffsetTableEntry.w DynamicWaterNull ; MTZ 3
zoneOffsetTableEntry.w DynamicWaterNull ; MTZ 4
zoneOffsetTableEntry.w DynamicWaterNull ; WFZ 1
zoneOffsetTableEntry.w DynamicWaterNull ; WFZ 2
zoneOffsetTableEntry.w DynamicWaterNull ; HTZ 1
zoneOffsetTableEntry.w DynamicWaterNull ; HTZ 2
zoneOffsetTableEntry.w DynamicWaterNull ; HPZ 1
zoneOffsetTableEntry.w DynamicWaterNull ; HPZ 2
zoneOffsetTableEntry.w DynamicWaterNull ; Zone 9
zoneOffsetTableEntry.w DynamicWaterNull ; Zone 9
zoneOffsetTableEntry.w DynamicWaterNull ; OOZ 1
zoneOffsetTableEntry.w DynamicWaterNull ; OOZ 2
zoneOffsetTableEntry.w DynamicWaterNull ; MCZ 1
zoneOffsetTableEntry.w DynamicWaterNull ; MCZ 2
zoneOffsetTableEntry.w DynamicWaterNull ; CNZ 1
zoneOffsetTableEntry.w DynamicWaterNull ; CNZ 2
zoneOffsetTableEntry.w DynamicWaterNull ; CPZ 1
zoneOffsetTableEntry.w DynamicWaterCPZ2 ; CPZ 2
zoneOffsetTableEntry.w DynamicWaterNull ; DEZ 1
zoneOffsetTableEntry.w DynamicWaterNull ; DEZ 2
zoneOffsetTableEntry.w DynamicWaterNull ; ARZ 1
zoneOffsetTableEntry.w DynamicWaterNull ; ARZ 2
zoneOffsetTableEntry.w DynamicWaterNull ; SCZ 1
zoneOffsetTableEntry.w DynamicWaterNull ; SCZ 2
zoneTableEnd
else
; off_45D8:
Dynamic_water_routine_table: offsetTable
offsetTableEntry.w DynamicWaterNull ; HPZ 1
offsetTableEntry.w DynamicWaterNull ; HPZ 2
offsetTableEntry.w DynamicWaterNull ; Zone 9
offsetTableEntry.w DynamicWaterNull ; Zone 9
offsetTableEntry.w DynamicWaterNull ; OOZ 1
offsetTableEntry.w DynamicWaterNull ; OOZ 2
offsetTableEntry.w DynamicWaterNull ; MCZ 1
offsetTableEntry.w DynamicWaterNull ; MCZ 2
offsetTableEntry.w DynamicWaterNull ; CNZ 1
offsetTableEntry.w DynamicWaterNull ; CNZ 2
offsetTableEntry.w DynamicWaterNull ; CPZ 1
offsetTableEntry.w DynamicWaterCPZ2 ; CPZ 2
offsetTableEntry.w DynamicWaterNull ; DEZ 1
offsetTableEntry.w DynamicWaterNull ; DEZ 2
offsetTableEntry.w DynamicWaterNull ; ARZ 1
offsetTableEntry.w DynamicWaterNull ; ARZ 2
endif
; ===========================================================================
; return_45F8:
DynamicWaterNull:
rts
; ===========================================================================
; loc_45FA:
DynamicWaterCPZ2:
cmpi.w #$1DE0,(Camera_X_pos).w
blo.s + ; rts
move.w #$510,(Water_Level_3).w
+ rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Equates:
windtunnel_min_x_pos = 0
windtunnel_max_x_pos = 4
windtunnel_min_y_pos = 2
windtunnel_max_y_pos = 6
; sub_460A:
WindTunnel:
tst.w (Debug_placement_mode).w
bne.w WindTunnel_End ; don't interact with wind tunnels while in debug mode
lea (WindTunnelsCoordinates).l,a2
moveq #(WindTunnelsCoordinates_End-WindTunnelsCoordinates)/8-1,d1
lea (MainCharacter).w,a1 ; a1=character
- ; check for current wind tunnel if the main character is inside it
move.w x_pos(a1),d0
cmp.w windtunnel_min_x_pos(a2),d0
blo.w WindTunnel_Leave ; branch, if main character is too far left
cmp.w windtunnel_max_x_pos(a2),d0
bhs.w WindTunnel_Leave ; branch, if main character is too far right
move.w y_pos(a1),d2
cmp.w windtunnel_min_y_pos(a2),d2
blo.w WindTunnel_Leave ; branch, if main character is too far up
cmp.w windtunnel_max_y_pos(a2),d2
bhs.s WindTunnel_Leave ; branch, if main character is too far down
tst.b (WindTunnel_holding_flag).w
bne.w WindTunnel_End
cmpi.b #4,routine(a1) ; is the main character hurt, dying, etc. ?
bhs.s WindTunnel_LeaveHurt ; if yes, branch
move.b #1,(WindTunnel_flag).w ; affects character animation and bubble movement
subi_.w #4,x_pos(a1) ; move main character to the left
move.w #-$400,x_vel(a1)
move.w #0,y_vel(a1)
move.b #AniIDSonAni_Float2,anim(a1)
bset #1,status(a1) ; set "in-air" bit
btst #button_up,(Ctrl_1_Held).w ; is Up being pressed?
beq.s + ; if not, branch
subq.w #1,y_pos(a1) ; move up
+
btst #button_down,(Ctrl_1_Held).w ; is Down being pressed?
beq.s + ; if not, branch
addq.w #1,y_pos(a1) ; move down
+
rts
; ===========================================================================
; loc_4690:
WindTunnel_Leave:
addq.w #8,a2
dbf d1,- ; check next tunnel
; when all wind tunnels have been checked
tst.b (WindTunnel_flag).w
beq.s WindTunnel_End
move.b #AniIDSonAni_Walk,anim(a1)
; loc_46A2:
WindTunnel_LeaveHurt: ; the main character is hurt or dying, leave the tunnel and don't check the other
clr.b (WindTunnel_flag).w
; return_46A6:
WindTunnel_End:
rts
; End of function WindTunnel
; ===========================================================================
; word_46A8:
WindTunnelsCoordinates:
dc.w $1510,$400,$1AF0,$580
dc.w $20F0,$618,$2500,$680
WindTunnelsCoordinates_End:
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_46B8:
OilSlides:
lea (MainCharacter).w,a1 ; a1=character
move.b (Ctrl_1_Held_Logical).w,d2
bsr.s +
lea (Sidekick).w,a1 ; a1=character
move.b (Ctrl_2_Held_Logical).w,d2
+
btst #1,status(a1)
bne.s +
move.w y_pos(a1),d0
add.w d0,d0
andi.w #$F00,d0
move.w x_pos(a1),d1
lsr.w #7,d1
andi.w #$7F,d1
add.w d1,d0
lea (Level_Layout).w,a2
move.b (a2,d0.w),d0
lea OilSlides_Chunks_End(pc),a2
moveq #OilSlides_Chunks_End-OilSlides_Chunks-1,d1
- cmp.b -(a2),d0
dbeq d1,-
beq.s loc_4712
+
if status_sec_isSliding = 7
tst.b status_secondary(a1)
bpl.s + ; rts
else
btst #status_sec_isSliding,status_secondary(a1)
beq.s + ; rts
endif
move.w #5,move_lock(a1)
andi.b #(~status_sec_isSliding_mask)&$FF,status_secondary(a1)
+ rts
; ===========================================================================
loc_4712:
lea (OilSlides_Speeds).l,a2
move.b (a2,d1.w),d0
beq.s loc_476E
move.b inertia(a1),d1
tst.b d0
bpl.s +
cmp.b d0,d1
ble.s ++
subi.w #$40,inertia(a1)
bra.s ++
; ===========================================================================
+
cmp.b d0,d1
bge.s +
addi.w #$40,inertia(a1)
+
bclr #0,status(a1)
tst.b d1
bpl.s +
bset #0,status(a1)
+
move.b #AniIDSonAni_Slide,anim(a1)
ori.b #status_sec_isSliding_mask,status_secondary(a1)
move.b (Vint_runcount+3).w,d0
andi.b #$1F,d0
bne.s + ; rts
move.w #SndID_OilSlide,d0
jsr (PlaySound).l
+
rts
; ===========================================================================
loc_476E:
move.w #4,d1
move.w inertia(a1),d0
btst #button_left,d2
beq.s +
move.b #AniIDSonAni_Walk,anim(a1)
bset #0,status(a1)
sub.w d1,d0
tst.w d0
bpl.s +
sub.w d1,d0
+
btst #button_right,d2
beq.s +
move.b #AniIDSonAni_Walk,anim(a1)
bclr #0,status(a1)
add.w d1,d0
tst.w d0
bmi.s +
add.w d1,d0
+
move.w #4,d1
tst.w d0
beq.s +++
bmi.s ++
sub.w d1,d0
bhi.s +
move.w #0,d0
move.b #AniIDSonAni_Wait,anim(a1)
+ bra.s ++
; ===========================================================================
+
add.w d1,d0
bhi.s +
move.w #0,d0
move.b #AniIDSonAni_Wait,anim(a1)
+
move.w d0,inertia(a1)
ori.b #status_sec_isSliding_mask,status_secondary(a1)
rts
; End of function OilSlides
; ===========================================================================
OilSlides_Speeds:
dc.b -8, -8, -8, 8, 8, 0, 0, 0, -8, -8, 0, 8, 8, 8, 0, 8
dc.b 8, 8, 0, -8, 0, 0, -8, 8, -8, -8, -8, 8, 8, 8, -8, -8 ; 16
; These are the IDs of the chunks where Sonic and Tails will slide
OilSlides_Chunks:
dc.b $2F,$30,$31,$33,$35,$38,$3A,$3C,$63,$64,$83,$90,$91,$93,$A1,$A3
dc.b $BD,$C7,$C8,$CE,$D7,$D8,$E6,$EB,$EC,$ED,$F1,$F2,$F3,$F4,$FA,$FD ; 16
OilSlides_Chunks_End:
even
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_481E:
MoveSonicInDemo:
tst.w (Demo_mode_flag).w ; is demo mode on?
bne.w MoveDemo_On ; if yes, branch
rts
; ---------------------------------------------------------------------------
; demo recording routine
; (unused/dead code, but obviously used during development)
; ---------------------------------------------------------------------------
; MoveDemo_Record: loc_4828:
; calculate output location of recorded player 1 demo?
lea (DemoScriptPointers).l,a1
moveq #0,d0
move.b (Current_Zone).w,d0
lsl.w #2,d0
movea.l (a1,d0.w),a1
move.w (Demo_button_index).w,d0
adda.w d0,a1
move.b (Ctrl_1_Held).w,d0 ; load input of player 1
cmp.b (a1),d0 ; is same button held?
bne.s + ; if not, branch
addq.b #1,1(a1) ; increment press length counter
cmpi.b #$FF,1(a1) ; is button held too long?
beq.s + ; if yes, branch
bra.s MoveDemo_Record_P2 ; go to player 2
; ===========================================================================
+
move.b d0,2(a1) ; store last button press
move.b #0,3(a1) ; reset hold length counter
addq.w #2,(Demo_button_index).w ; advance to next button press
andi.w #$3FF,(Demo_button_index).w ; wrap at max button press changes 1024
; loc_486A:
MoveDemo_Record_P2:
cmpi.b #emerald_hill_zone,(Current_Zone).w
bne.s ++ ; rts
lea ($FEC000).l,a1 ; output location of recorded player 2 demo? (unknown)
move.w (Demo_button_index_2P).w,d0
adda.w d0,a1
move.b (Ctrl_2_Held).w,d0 ; load input of player 2
cmp.b (a1),d0 ; is same button held?
bne.s + ; if not, branch
addq.b #1,1(a1) ; increment press length counter
cmpi.b #$FF,1(a1) ; is button held too long?
beq.s + ; if yes, branch
bra.s ++ ; if not, return
; ===========================================================================
+
move.b d0,2(a1) ; store last button press
move.b #0,3(a1) ; reset hold length counter
addq.w #2,(Demo_button_index_2P).w ; advance to next button press
andi.w #$3FF,(Demo_button_index_2P).w ; wrap at max button press changes 1024
+ rts
; end of inactive recording code
; ===========================================================================
; continue with MoveSonicInDemo:
; loc_48AA:
MoveDemo_On:
move.b (Ctrl_1_Press).w,d0
or.b (Ctrl_2_Press).w,d0
andi.b #button_start_mask,d0
beq.s +
tst.w (Demo_mode_flag).w
bmi.s +
move.b #GameModeID_TitleScreen,(Game_Mode).w ; => TitleScreen
+
lea (DemoScriptPointers).l,a1 ; load pointer to input data
moveq #0,d0
move.b (Current_Zone).w,d0
cmpi.b #GameModeID_SpecialStage,(Game_Mode).w ; special stage mode?
bne.s MoveDemo_On_P1 ; if yes, branch
moveq #6,d0
; loc_48DA:
MoveDemo_On_P1:
lsl.w #2,d0
movea.l (a1,d0.w),a1
move.w (Demo_button_index).w,d0
adda.w d0,a1 ; a1 now points to the current button press data
move.b (a1),d0 ; load button press
lea (Ctrl_1_Held).w,a0
move.b d0,d1
moveq #0,d2 ; this was modified from (a0) to #0 in Rev01 of Sonic 1 to nullify the following line
eor.b d2,d0 ; does nothing now (used to let you hold a button to prevent Sonic from jumping in demos)
move.b d1,(a0)+ ; save button press data from demo to Ctrl_1_Held
and.b d1,d0 ; does nothing now
move.b d0,(a0)+ ; save the same thing to Ctrl_1_Press
subq.b #1,(Demo_press_counter).w ; decrement counter until next press
bcc.s MoveDemo_On_P2 ; if it isn't 0 yet, branch
move.b 3(a1),(Demo_press_counter).w ; reset counter to length of next press
addq.w #2,(Demo_button_index).w ; advance to next button press
; loc_4908:
MoveDemo_On_P2:
if emerald_hill_zone_act_1<$100 ; will it fit within a byte?
cmpi.b #emerald_hill_zone_act_1,(Current_Zone).w
else
cmpi.w #emerald_hill_zone_act_1,(Current_ZoneAndAct).w ; avoid a range overflow error
endif
bne.s MoveDemo_On_SkipP2 ; if it's not the EHZ demo, branch to skip player 2
lea (Demo_EHZ_Tails).l,a1
; same as the corresponding remainder of MoveDemo_On_P1, but for player 2
move.w (Demo_button_index_2P).w,d0
adda.w d0,a1
move.b (a1),d0
lea (Ctrl_2_Held).w,a0
move.b d0,d1
moveq #0,d2
eor.b d2,d0
move.b d1,(a0)+
and.b d1,d0
move.b d0,(a0)+
subq.b #1,(Demo_press_counter_2P).w
bcc.s + ; rts
move.b 3(a1),(Demo_press_counter_2P).w
addq.w #2,(Demo_button_index_2P).w
+
rts
; ===========================================================================
; loc_4940:
MoveDemo_On_SkipP2:
move.w #0,(Ctrl_2).w
rts
; End of function MoveSonicInDemo
; ===========================================================================
; ---------------------------------------------------------------------------
; DEMO SCRIPT POINTERS
; Contains an array of pointers to the script controlling the players actions
; to use for each level.
; ---------------------------------------------------------------------------
; off_4948:
DemoScriptPointers: zoneOrderedTable 4,1
zoneTableEntry.l Demo_EHZ ; $00
zoneTableEntry.l Demo_EHZ ; $01
zoneTableEntry.l Demo_EHZ ; $02
zoneTableEntry.l Demo_EHZ ; $03
zoneTableEntry.l Demo_EHZ ; $04
zoneTableEntry.l Demo_EHZ ; $05
zoneTableEntry.l Demo_EHZ ; $06
zoneTableEntry.l Demo_EHZ ; $07
zoneTableEntry.l Demo_EHZ ; $08
zoneTableEntry.l Demo_EHZ ; $09
zoneTableEntry.l Demo_EHZ ; $0A
zoneTableEntry.l Demo_EHZ ; $0B
zoneTableEntry.l Demo_CNZ ; $0C
zoneTableEntry.l Demo_CPZ ; $0D
zoneTableEntry.l Demo_EHZ ; $0E
zoneTableEntry.l Demo_ARZ ; $0F
zoneTableEntry.l Demo_EHZ ; $10
zoneTableEnd
; ---------------------------------------------------------------------------
; dword_498C:
EndingDemoScriptPointers:
; these values are invalid addresses, but they were used for the ending
; demos, which aren't present in Sonic 2
dc.l $8B0837
dc.l $42085C ; 1
dc.l $6A085F ; 2
dc.l $2F082C ; 3
dc.l $210803 ; 4
dc.l $28300808 ; 5
dc.l $2E0815 ; 6
dc.l $F0846 ; 7
dc.l $1A08FF ; 8
dc.l $8CA0000 ; 9
dc.l 0 ; 10
dc.l 0 ; 11
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_49BC:
LoadCollisionIndexes:
moveq #0,d0
move.b (Current_Zone).w,d0
lsl.w #2,d0
move.l #Primary_Collision,(Collision_addr).w
move.w d0,-(sp)
movea.l Off_ColP(pc,d0.w),a0
lea (Primary_Collision).w,a1
bsr.w KosDec
move.w (sp)+,d0
movea.l Off_ColS(pc,d0.w),a0
lea (Secondary_Collision).w,a1
bra.w KosDec
; End of function LoadCollisionIndexes
; ===========================================================================
; ---------------------------------------------------------------------------
; Pointers to primary collision indexes
; Contains an array of pointers to the primary collision index data for each
; level. 1 pointer for each level, pointing the primary collision index.
; ---------------------------------------------------------------------------
Off_ColP: zoneOrderedTable 4,1
zoneTableEntry.l ColP_EHZHTZ
zoneTableEntry.l ColP_Invalid ; 1
zoneTableEntry.l ColP_MTZ ; 2
zoneTableEntry.l ColP_Invalid ; 3
zoneTableEntry.l ColP_MTZ ; 4
zoneTableEntry.l ColP_MTZ ; 5
zoneTableEntry.l ColP_WFZSCZ ; 6
zoneTableEntry.l ColP_EHZHTZ ; 7
zoneTableEntry.l ColP_HPZ ; 8
zoneTableEntry.l ColP_Invalid ; 9
zoneTableEntry.l ColP_OOZ ; 10
zoneTableEntry.l ColP_MCZ ; 11
zoneTableEntry.l ColP_CNZ ; 12
zoneTableEntry.l ColP_CPZDEZ ; 13
zoneTableEntry.l ColP_CPZDEZ ; 14
zoneTableEntry.l ColP_ARZ ; 15
zoneTableEntry.l ColP_WFZSCZ ; 16
zoneTableEnd
; ---------------------------------------------------------------------------
; Pointers to secondary collision indexes
; Contains an array of pointers to the secondary collision index data for
; each level. 1 pointer for each level, pointing the secondary collision
; index.
; ---------------------------------------------------------------------------
Off_ColS: zoneOrderedTable 4,1
zoneTableEntry.l ColS_EHZHTZ
zoneTableEntry.l ColP_Invalid ; 1
zoneTableEntry.l ColP_MTZ ; 2
zoneTableEntry.l ColP_Invalid ; 3
zoneTableEntry.l ColP_MTZ ; 4
zoneTableEntry.l ColP_MTZ ; 5
zoneTableEntry.l ColS_WFZSCZ ; 6
zoneTableEntry.l ColS_EHZHTZ ; 7
zoneTableEntry.l ColS_HPZ ; 8
zoneTableEntry.l ColP_Invalid ; 9
zoneTableEntry.l ColP_OOZ ; 10
zoneTableEntry.l ColP_MCZ ; 11
zoneTableEntry.l ColS_CNZ ; 12
zoneTableEntry.l ColS_CPZDEZ ; 13
zoneTableEntry.l ColS_CPZDEZ ; 14
zoneTableEntry.l ColS_ARZ ; 15
zoneTableEntry.l ColS_WFZSCZ ; 16
zoneTableEnd
; ---------------------------------------------------------------------------
; Oscillating number subroutine
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_4A70:
OscillateNumInit:
lea (Oscillating_Numbers).w,a1
lea (Osc_Data).l,a2
moveq #bytesToWcnt(Osc_Data_End-Osc_Data),d1
; loc_4A7C:
Osc_Loop:
move.w (a2)+,(a1)+
dbf d1,Osc_Loop
rts
; End of function OscillateNumInit
; ===========================================================================
; word_4A84:
Osc_Data:
dc.w %0000000001111101 ; oscillation direction bitfield
dc.w $80, 0 ; baseline values
dc.w $80, 0
dc.w $80, 0
dc.w $80, 0
dc.w $80, 0
dc.w $80, 0
dc.w $80, 0
dc.w $80, 0
dc.w $80, 0
dc.w $3848, $EE
dc.w $2080, $B4
dc.w $3080,$10E
dc.w $5080,$1C2
dc.w $7080,$276
dc.w $80, 0
dc.w $4000, $FE
Osc_Data_End:
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_4AC6:
OscillateNumDo:
tst.w (Two_player_mode).w
bne.s +
cmpi.b #6,(MainCharacter+routine).w
bhs.s OscillateNumDo_Return
+
lea (Oscillating_Numbers).w,a1
lea (Osc_Data2).l,a2
move.w (a1)+,d3
moveq #bytesToLcnt(Osc_Data2_End-Osc_Data2),d1
- move.w (a2)+,d2
move.w (a2)+,d4
btst d1,d3
bne.s +
move.w 2(a1),d0
add.w d2,d0
move.w d0,2(a1)
_add.w d0,0(a1)
_cmp.b 0(a1),d4
bhi.s ++
bset d1,d3
bra.s ++
; ===========================================================================
+
move.w 2(a1),d0
sub.w d2,d0
move.w d0,2(a1)
_add.w d0,0(a1)
_cmp.b 0(a1),d4
bls.s +
bclr d1,d3
+
addq.w #4,a1
dbf d1,-
move.w d3,(Oscillation_Control).w
; return_4B22:
OscillateNumDo_Return:
rts
; End of function OscillateNumDo
; ===========================================================================
; word_4B24:
Osc_Data2:
dc.w 2, $10
dc.w 2, $18
dc.w 2, $20
dc.w 2, $30
dc.w 4, $20
dc.w 8, 8
dc.w 8, $40
dc.w 4, $40
dc.w 2, $38
dc.w 2, $38
dc.w 2, $20
dc.w 3, $30
dc.w 5, $50
dc.w 7, $70
dc.w 2, $40
dc.w 2, $40
Osc_Data2_End:
; ---------------------------------------------------------------------------
; Subroutine to change global object animation variables (like rings)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_4B64:
ChangeRingFrame:
subq.b #1,(Logspike_anim_counter).w
bpl.s +
move.b #$B,(Logspike_anim_counter).w
subq.b #1,(Logspike_anim_frame).w ; animate unused log spikes
andi.b #7,(Logspike_anim_frame).w
+
subq.b #1,(Rings_anim_counter).w
bpl.s +
move.b #7,(Rings_anim_counter).w
addq.b #1,(Rings_anim_frame).w ; animate rings in the level (obj25)
andi.b #3,(Rings_anim_frame).w
+
subq.b #1,(Unknown_anim_counter).w
bpl.s +
move.b #7,(Unknown_anim_counter).w
addq.b #1,(Unknown_anim_frame).w ; animate nothing (deleted special stage object is my best guess)
cmpi.b #6,(Unknown_anim_frame).w
blo.s +
move.b #0,(Unknown_anim_frame).w
+
tst.b (Ring_spill_anim_counter).w
beq.s + ; rts
moveq #0,d0
move.b (Ring_spill_anim_counter).w,d0
add.w (Ring_spill_anim_accum).w,d0
move.w d0,(Ring_spill_anim_accum).w
rol.w #7,d0
andi.w #3,d0
move.b d0,(Ring_spill_anim_frame).w ; animate scattered rings (obj37)
subq.b #1,(Ring_spill_anim_counter).w
+
rts
; End of function ChangeRingFrame
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
nosignpost macro actid
cmpi.w #actid,(Current_ZoneAndAct).w
beq.ATTRIBUTE + ; rts
endm
; sub_4BD2:
SetLevelEndType:
move.w #0,(Level_Has_Signpost).w ; set level type to non-signpost
tst.w (Two_player_mode).w ; is it two-player competitive mode?
bne.s LevelEnd_SetSignpost ; if yes, branch
nosignpost.w emerald_hill_zone_act_2
nosignpost.w metropolis_zone_act_3
nosignpost.w wing_fortress_zone_act_1
nosignpost.w hill_top_zone_act_2
nosignpost.w oil_ocean_zone_act_2
nosignpost.s mystic_cave_zone_act_2
nosignpost.s casino_night_zone_act_2
nosignpost.s chemical_plant_zone_act_2
nosignpost.s death_egg_zone_act_1
nosignpost.s aquatic_ruin_zone_act_2
nosignpost.s sky_chase_zone_act_1
; loc_4C40:
LevelEnd_SetSignpost:
move.w #1,(Level_Has_Signpost).w ; set level type to signpost
+ rts
; End of function SetLevelEndType
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_4C48:
CheckLoadSignpostArt:
tst.w (Level_Has_Signpost).w
beq.s + ; rts
tst.w (Debug_placement_mode).w
bne.s + ; rts
move.w (Camera_X_pos).w,d0
move.w (Camera_Max_X_pos).w,d1
subi.w #$100,d1
cmp.w d1,d0
blt.s SignpostUpdateTailsBounds
tst.b (Update_HUD_timer).w
beq.s SignpostUpdateTailsBounds
cmp.w (Camera_Min_X_pos).w,d1
beq.s SignpostUpdateTailsBounds
move.w d1,(Camera_Min_X_pos).w ; prevent camera from scrolling back to the left
tst.w (Two_player_mode).w
bne.s + ; rts
moveq #PLCID_Signpost,d0 ; <== PLC_1F
bra.w LoadPLC2 ; load signpost art
; ---------------------------------------------------------------------------
; loc_4C80:
SignpostUpdateTailsBounds:
tst.w (Two_player_mode).w
beq.s + ; rts
move.w (Camera_X_pos_P2).w,d0
move.w (Tails_Max_X_pos).w,d1
subi.w #$100,d1
cmp.w d1,d0
blt.s + ; rts
tst.b (Update_HUD_timer_2P).w
beq.s + ; rts
cmp.w (Tails_Min_X_pos).w,d1
beq.s + ; rts
move.w d1,(Tails_Min_X_pos).w ; prevent Tails from going past new left boundary
+ rts
; End of function CheckLoadSignpostArt
; ===========================================================================
; macro to simplify editing the demo scripts
demoinput macro buttons,duration
btns_mask := 0
idx := 0
rept strlen("buttons")
btn := substr("buttons",idx,1)
switch btn
case "U"
btns_mask := btns_mask|button_up_mask
case "D"
btns_mask := btns_mask|button_down_mask
case "L"
btns_mask := btns_mask|button_left_mask
case "R"
btns_mask := btns_mask|button_right_mask
case "A"
btns_mask := btns_mask|button_A_mask
case "B"
btns_mask := btns_mask|button_B_mask
case "C"
btns_mask := btns_mask|button_C_mask
case "S"
btns_mask := btns_mask|button_start_mask
endcase
idx := idx+1
endm
dc.b btns_mask,duration-1
endm
; ---------------------------------------------------------------------------
; EHZ Demo Script (Sonic)
; ---------------------------------------------------------------------------
; byte_4CA8: Demo_Def:
Demo_EHZ:
demoinput , $4C
demoinput R, $43
demoinput RC, 9
demoinput R, $3F
demoinput RC, 6
demoinput R, $B0
demoinput RC, $A
demoinput R, $46
demoinput , $1E
demoinput L, $F
demoinput , 5
demoinput L, 5
demoinput , 9
demoinput L, $3F
demoinput , 5
demoinput R, $67
demoinput , $62
demoinput R, $12
demoinput , $22
demoinput D, 8
demoinput DC, 7
demoinput D, $E
demoinput , $3C
demoinput R, $A
demoinput , $1E
demoinput D, 7
demoinput DC, 7
demoinput D, 2
demoinput , $F
demoinput R, $100
demoinput R, $2F
demoinput , $23
demoinput C, 8
demoinput RC, $10
demoinput R, 3
demoinput , $30
demoinput RC, $24
demoinput R, $BE
demoinput , $C
demoinput L, $14
demoinput , $17
demoinput D, 3
demoinput DC, 7
demoinput D, 3
demoinput , $64
demoinput S, 1
demoinput A, 1
demoinput , 1
; ---------------------------------------------------------------------------
; EHZ Demo Script (Tails)
; ---------------------------------------------------------------------------
; byte_4D08:
Demo_EHZ_Tails:
demoinput , $3C
demoinput R, $10
demoinput UR, $44
demoinput URC, $7
demoinput UR, $7
demoinput R, $CA
demoinput , $12
demoinput R, $2
demoinput RC, $9
demoinput R, $53
demoinput , $12
demoinput R, $B
demoinput RC, $F
demoinput R, $24
demoinput , $B
demoinput C, $5
demoinput , $E
demoinput R, $56
demoinput , $1F
demoinput R, $5B
demoinput , $11
demoinput R, $100
demoinput R, $C1
demoinput , $21
demoinput L, $E
demoinput , $E
demoinput C, $5
demoinput RC, $10
demoinput C, $6
demoinput , $D
demoinput L, $6
demoinput , $5F
demoinput R, $74
demoinput , $19
demoinput L, $45
demoinput , $9
demoinput D, $31
demoinput , $9
demoinput R, $E
demoinput , $24
demoinput R, $28
demoinput , $5
demoinput R, $1
demoinput , $1
demoinput , $1
demoinput , $1
demoinput , $1
demoinput , $1
; ---------------------------------------------------------------------------
; CNZ Demo Script
; ---------------------------------------------------------------------------
Demo_CNZ:
demoinput , $49
demoinput R, $11
demoinput UR, 1
demoinput R, 2
demoinput UR, 7
demoinput R, $61
demoinput RC, 6
demoinput C, 2
demoinput , 9
demoinput L, 3
demoinput DL, 4
demoinput L, 2
demoinput , $1A
demoinput R, $12
demoinput RC, $1A
demoinput C, 5
demoinput RC, $24
demoinput R, $1B
demoinput , 8
demoinput L, $11
demoinput , $F
demoinput R, $78
demoinput RC, $17
demoinput C, 1
demoinput , $10
demoinput L, $12
demoinput , 8
demoinput R, $53
demoinput , $70
demoinput R, $75
demoinput , $38
demoinput R, $17
demoinput , 5
demoinput L, $27
demoinput , $D
demoinput L, $13
demoinput , $6A
demoinput C, $11
demoinput RC, 3
demoinput DRC, 6
demoinput DR, $15
demoinput R, 6
demoinput , 6
demoinput L, $D
demoinput , $49
demoinput L, $A
demoinput , $1F
demoinput R, 7
demoinput , $30
demoinput L, 2
demoinput , $100
demoinput , $50
demoinput R, 1
demoinput RC, $C
demoinput R, $2B
demoinput , $5F
; ---------------------------------------------------------------------------
; CPZ Demo Script
; ---------------------------------------------------------------------------
Demo_CPZ:
demoinput , $47
demoinput R, $1C
demoinput RC, 8
demoinput R, $A
demoinput , $1C
demoinput R, $E
demoinput RC, $29
demoinput R, $100
demoinput R, $E8
demoinput DR, 5
demoinput D, 2
demoinput L, $34
demoinput DL, $68
demoinput L, 1
demoinput , $16
demoinput C, 1
demoinput LC, 8
demoinput L, $F
demoinput , $18
demoinput R, 2
demoinput DR, 2
demoinput R, $D
demoinput , $20
demoinput RC, 7
demoinput R, $B
demoinput , $1C
demoinput L, $E
demoinput , $1D
demoinput L, 7
demoinput , $100
demoinput , $E0
demoinput R, $F
demoinput , $1D
demoinput L, 3
demoinput , $26
demoinput R, 7
demoinput , 7
demoinput C, 5
demoinput , $29
demoinput L, $12
demoinput , $18
demoinput R, $1A
demoinput , $11
demoinput L, $2E
demoinput , $14
demoinput S, 1
demoinput A, 1
demoinput , 1
; ---------------------------------------------------------------------------
; ARZ Demo Script
; ---------------------------------------------------------------------------
Demo_ARZ:
demoinput , $43
demoinput R, $4B
demoinput RC, 9
demoinput R, $50
demoinput RC, $C
demoinput R, 6
demoinput , $1B
demoinput R, $61
demoinput RC, $15
demoinput R, $55
demoinput , $41
demoinput R, 5
demoinput UR, 1
demoinput R, $5C
demoinput , $47
demoinput R, $3C
demoinput RC, 9
demoinput R, $28
demoinput , $B
demoinput R, $93
demoinput RC, $33
demoinput R, $23
demoinput , $23
demoinput R, $4D
demoinput , $1F
demoinput L, 2
demoinput UL, 3
demoinput L, 1
demoinput , $B
demoinput L, $D
demoinput , $11
demoinput R, 6
demoinput , $62
demoinput R, 4
demoinput RC, 6
demoinput R, $17
demoinput , $1C
demoinput R, $57
demoinput RC, $B
demoinput R, $17
demoinput , $16
demoinput R, $D
demoinput , $2C
demoinput C, 2
demoinput RC, $1B
demoinput R, $83
demoinput , $C
demoinput S, 1
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_4E98:
LoadZoneTiles:
moveq #0,d0
move.b (Current_Zone).w,d0
add.w d0,d0
add.w d0,d0
move.w d0,d1
add.w d0,d0
add.w d1,d0
lea (LevelArtPointers).l,a2
lea (a2,d0.w),a2
move.l (a2)+,d0
andi.l #$FFFFFF,d0 ; 8x8 tile pointer
movea.l d0,a0
lea (Chunk_Table).l,a1
bsr.w KosDec
move.w a1,d3
cmpi.b #hill_top_zone,(Current_Zone).w
bne.s +
lea (ArtKos_HTZ).l,a0
lea (Chunk_Table+tiles_to_bytes(ArtTile_ArtKos_NumTiles_HTZ_Main)).l,a1
bsr.w KosDec ; patch for HTZ
move.w #tiles_to_bytes(ArtTile_ArtKos_NumTiles_HTZ),d3
+
cmpi.b #wing_fortress_zone,(Current_Zone).w
bne.s +
lea (ArtKos_WFZ).l,a0
lea (Chunk_Table+tiles_to_bytes(ArtTile_ArtKos_NumTiles_WFZ_Main)).l,a1
bsr.w KosDec ; patch for WFZ
move.w #tiles_to_bytes(ArtTile_ArtKos_NumTiles_WFZ),d3
+
cmpi.b #death_egg_zone,(Current_Zone).w
bne.s +
move.w #tiles_to_bytes(ArtTile_ArtKos_NumTiles_DEZ),d3
+
move.w d3,d7
andi.w #$FFF,d3
lsr.w #1,d3
rol.w #4,d7
andi.w #$F,d7
- move.w d7,d2
lsl.w #7,d2
lsl.w #5,d2
move.l #$FFFFFF,d1
move.w d2,d1
jsr (QueueDMATransfer).l
move.w d7,-(sp)
move.b #VintID_TitleCard,(Vint_routine).w
bsr.w WaitForVint
bsr.w RunPLC_RAM
move.w (sp)+,d7
move.w #$800,d3
dbf d7,-
rts
; End of function LoadZoneTiles
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo_loadZoneBlockMaps
jmp (loadZoneBlockMaps).l
JmpTo_DeformBgLayer
jmp (DeformBgLayer).l
JmpTo_AniArt_Load
jmp (AniArt_Load).l
JmpTo_DrawInitialBG
jmp (DrawInitialBG).l
align 4
endif
; ===========================================================================
; loc_4F64:
SpecialStage:
cmpi.b #7,(Current_Special_Stage).w
blo.s +
move.b #0,(Current_Special_Stage).w
+
move.w #SndID_SpecStageEntry,d0 ; play that funky special stage entry sound
bsr.w PlaySound
move.b #MusID_FadeOut,d0 ; fade out the music
bsr.w PlayMusic
bsr.w Pal_FadeToWhite
tst.w (Two_player_mode).w
beq.s +
move.w #0,(Two_player_mode).w
st.b (SS_2p_Flag).w ; set to -1
bra.s ++
; ===========================================================================
+
sf.b (SS_2p_Flag).w ; set to 0
; (!)
+
move #$2700,sr ; Mask all interrupts
lea (VDP_control_port).l,a6
move.w #$8B03,(a6) ; EXT-INT disabled, V scroll by screen, H scroll by line
move.w #$8004,(a6) ; H-INT disabled
move.w #$8ADF,(Hint_counter_reserve).w ; H-INT every 224th scanline
move.w #$8200|(VRAM_SS_Plane_A_Name_Table1/$400),(a6) ; PNT A base: $C000
move.w #$8400|(VRAM_SS_Plane_B_Name_Table/$2000),(a6) ; PNT B base: $A000
move.w #$8C08,(a6) ; H res 32 cells, no interlace, S/H enabled
move.w #$9003,(a6) ; Scroll table size: 128x32
move.w #$8700,(a6) ; Background palette/color: 0/0
move.w #$8D00|(VRAM_SS_Horiz_Scroll_Table/$400),(a6) ; H scroll table base: $FC00
move.w #$8500|(VRAM_SS_Sprite_Attribute_Table/$200),(a6) ; Sprite attribute table base: $F800
move.w (VDP_Reg1_val).w,d0
andi.b #$BF,d0
move.w d0,(VDP_control_port).l
; /------------------------------------------------------------------------\
; | We're gonna zero-fill a bunch of VRAM regions. This was done by macro, |
; | so there's gonna be a lot of wasted cycles. |
; \------------------------------------------------------------------------/
dmaFillVRAM 0,VRAM_SS_Plane_A_Name_Table2,VRAM_SS_Plane_Table_Size ; clear Plane A pattern name table 1
dmaFillVRAM 0,VRAM_SS_Plane_A_Name_Table1,VRAM_SS_Plane_Table_Size ; clear Plane A pattern name table 2
dmaFillVRAM 0,VRAM_SS_Plane_B_Name_Table,VRAM_SS_Plane_Table_Size ; clear Plane B pattern name table
dmaFillVRAM 0,VRAM_SS_Horiz_Scroll_Table,VRAM_SS_Horiz_Scroll_Table_Size ; clear Horizontal scroll table
clr.l (Vscroll_Factor).w
clr.l (unk_F61A).w
clr.b (SpecialStage_Started).w
; /------------------------------------------------------------------------\
; | Now we clear out some regions in main RAM where we want to store some |
; | of our data structures. |
; \------------------------------------------------------------------------/
; Bug: These '+4's shouldn't be here; clearRAM accidentally clears an additional 4 bytes
clearRAM SS_Sprite_Table,SS_Sprite_Table_End+4
clearRAM SS_Horiz_Scroll_Buf_1,SS_Horiz_Scroll_Buf_1_End+4
clearRAM SS_Misc_Variables,SS_Misc_Variables_End+4
clearRAM SS_Sprite_Table_Input,SS_Sprite_Table_Input_End
clearRAM SS_Object_RAM,SS_Object_RAM_End
move #$2300,sr
lea (VDP_control_port).l,a6
move.w #$8F02,(a6) ; VRAM pointer increment: $0002
bsr.w ssInitTableBuffers
bsr.w ssLdComprsdData
move.w #0,(SpecialStage_CurrentSegment).w
moveq #PLCID_SpecialStage,d0
bsr.w RunPLC_ROM
clr.b (Level_started_flag).w
move.l #0,(Camera_X_pos).w ; probably means something else in this context
move.l #0,(Camera_Y_pos).w
move.l #0,(Camera_X_pos_copy).w
move.l #0,(Camera_Y_pos_copy).w
cmpi.w #1,(Player_mode).w ; is this a Tails alone game?
bgt.s + ; if yes, branch
move.b #ObjID_SonicSS,(MainCharacter+id).w ; load Obj09 (special stage Sonic)
tst.w (Player_mode).w ; is this a Sonic and Tails game?
bne.s ++ ; if not, branch
+ move.b #ObjID_TailsSS,(Sidekick+id).w ; load Obj10 (special stage Tails)
+ move.b #ObjID_SSHUD,(SpecialStageHUD+id).w ; load Obj5E (special stage HUD)
move.b #ObjID_StartBanner,(SpecialStageStartBanner+id).w ; load Obj5F (special stage banner)
move.b #ObjID_SSNumberOfRings,(SpecialStageNumberOfRings+id).w ; load Obj87 (special stage ring count)
move.w #$80,(SS_Offset_X).w
move.w #$36,(SS_Offset_Y).w
bsr.w SSPlaneB_Background
bsr.w SSDecompressPlayerArt
bsr.w SSInitPalAndData
move.l #$C0000,(SS_New_Speed_Factor).w
clr.w (Ctrl_1_Logical).w
clr.w (Ctrl_2_Logical).w
- move.b #VintID_S2SS,(Vint_routine).w
bsr.w WaitForVint
move.b (SSTrack_drawing_index).w,d0
bne.s -
bsr.w SSTrack_Draw
- move.b #VintID_S2SS,(Vint_routine).w
bsr.w WaitForVint
bsr.w SSTrack_Draw
bsr.w SSLoadCurrentPerspective
bsr.w SSObjectsManager
move.b (SSTrack_duration_timer).w,d0
subq.w #1,d0
bne.s -
jsr (Obj5A_CreateRingsToGoText).l
bsr.w SS_ScrollBG
jsr (RunObjects).l
jsr (BuildSprites).l
bsr.w RunPLC_RAM
move.b #VintID_CtrlDMA,(Vint_routine).w
bsr.w WaitForVint
move.w #MusID_SpecStage,d0
bsr.w PlayMusic
move.w (VDP_Reg1_val).w,d0
ori.b #$40,d0
move.w d0,(VDP_control_port).l
bsr.w Pal_FadeFromWhite
- bsr.w PauseGame
move.w (Ctrl_1).w,(Ctrl_1_Logical).w
move.w (Ctrl_2).w,(Ctrl_2_Logical).w
cmpi.b #GameModeID_SpecialStage,(Game_Mode).w ; special stage mode?
bne.w SpecialStage_Unpause ; if not, branch
move.b #VintID_S2SS,(Vint_routine).w
bsr.w WaitForVint
bsr.w SSTrack_Draw
bsr.w SSSetGeometryOffsets
bsr.w SSLoadCurrentPerspective
bsr.w SSObjectsManager
bsr.w SS_ScrollBG
jsr (RunObjects).l
jsr (BuildSprites).l
bsr.w RunPLC_RAM
tst.b (SpecialStage_Started).w
beq.s -
moveq #PLCID_SpecStageBombs,d0
bsr.w LoadPLC
- bsr.w PauseGame
cmpi.b #GameModeID_SpecialStage,(Game_Mode).w ; special stage mode?
bne.w SpecialStage_Unpause ; if not, branch
move.b #VintID_S2SS,(Vint_routine).w
bsr.w WaitForVint
bsr.w SSTrack_Draw
bsr.w SSSetGeometryOffsets
bsr.w SSLoadCurrentPerspective
bsr.w SSObjectsManager
bsr.w SS_ScrollBG
bsr.w PalCycle_SS
tst.b (SS_Pause_Only_flag).w
beq.s +
move.w (Ctrl_1).w,d0
andi.w #(button_start_mask<<8)|button_start_mask,d0
move.w d0,(Ctrl_1_Logical).w
move.w (Ctrl_2).w,d0
andi.w #(button_start_mask<<8)|button_start_mask,d0
move.w d0,(Ctrl_2_Logical).w
bra.s ++
; ===========================================================================
+
move.w (Ctrl_1).w,(Ctrl_1_Logical).w
move.w (Ctrl_2).w,(Ctrl_2_Logical).w
+
jsr (RunObjects).l
tst.b (SS_Check_Rings_flag).w
bne.s +
jsr (BuildSprites).l
bsr.w RunPLC_RAM
bra.s -
; ===========================================================================
+
andi.b #7,(Emerald_count).w
tst.b (SS_2p_Flag).w
beq.s +
lea (SS2p_RingBuffer).w,a0
move.w (a0)+,d0
add.w (a0)+,d0
add.w (a0)+,d0
add.w (a0)+,d0
add.w (a0)+,d0
add.w (a0)+,d0
bra.s ++
; ===========================================================================
+
move.w (Ring_count).w,d0
add.w (Ring_count_2P).w,d0
+
cmp.w (SS_Perfect_rings_left).w,d0
bne.s +
st.b (Perfect_rings_flag).w
+
bsr.w Pal_FadeToWhite
tst.w (Two_player_mode_copy).w
bne.w loc_540C
move #$2700,sr
lea (VDP_control_port).l,a6
move.w #$8200|(VRAM_Menu_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000
move.w #$8400|(VRAM_Menu_Plane_B_Name_Table/$2000),(a6) ; PNT B base: $E000
move.w #$9001,(a6) ; Scroll table size: 64x32
move.w #$8C81,(a6) ; H res 40 cells, no interlace, S/H disabled
bsr.w ClearScreen
jsrto (Hud_Base).l, JmpTo_Hud_Base
clr.w (VDP_Command_Buffer).w
move.l #VDP_Command_Buffer,(VDP_Command_Buffer_Slot).w
move #$2300,sr
moveq #PalID_Result,d0
bsr.w PalLoad_Now
moveq #PLCID_Std1,d0
bsr.w LoadPLC2
move.l #vdpComm(tiles_to_bytes(ArtTile_VRAM_Start+2),VRAM,WRITE),d0
lea SpecialStage_ResultsLetters(pc),a0
jsrto (LoadTitleCardSS).l, JmpTo_LoadTitleCardSS
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_SpecialStageResults),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_SpecialStageResults).l,a0
bsr.w NemDec
move.w (Player_mode).w,d0
beq.s ++
subq.w #1,d0
beq.s +
clr.w (Ring_count).w
bra.s ++
; ===========================================================================
+
clr.w (Ring_count_2P).w
+
move.w (Ring_count).w,(Bonus_Countdown_1).w
move.w (Ring_count_2P).w,(Bonus_Countdown_2).w
clr.w (Total_Bonus_Countdown).w
tst.b (Got_Emerald).w
beq.s +
move.w #1000,(Total_Bonus_Countdown).w
+
move.b #1,(Update_HUD_score).w
move.b #1,(Update_Bonus_score).w
move.w #MusID_EndLevel,d0
jsr (PlaySound).l
clearRAM SS_Sprite_Table_Input,SS_Sprite_Table_Input_End
clearRAM SS_Object_RAM,SS_Object_RAM_End
move.b #ObjID_SSResults,(SpecialStageResults+id).w ; load Obj6F (special stage results) at $FFFFB800
-
move.b #VintID_Level,(Vint_routine).w
bsr.w WaitForVint
jsr (RunObjects).l
jsr (BuildSprites).l
bsr.w RunPLC_RAM
tst.w (Level_Inactive_flag).w
beq.s -
tst.l (Plc_Buffer).w
bne.s -
move.w #SndID_SpecStageEntry,d0
bsr.w PlaySound
bsr.w Pal_FadeToWhite
tst.w (Two_player_mode_copy).w
bne.s loc_540C
move.b #GameModeID_Level,(Game_Mode).w ; => Level (Zone play mode)
rts
; ===========================================================================
loc_540C:
move.w #VsRSID_SS,(Results_Screen_2P).w
move.b #GameModeID_2PResults,(Game_Mode).w ; => TwoPlayerResults
rts
; ===========================================================================
; loc_541A:
SpecialStage_Unpause:
move.b #MusID_Unpause,(Music_to_play).w
move.b #VintID_Level,(Vint_routine).w
bra.w WaitForVint
; ===========================================================================
; ---------------------------------------------------------------------------
; Animated color of the twinkling stars in the special stage background
; ---------------------------------------------------------------------------
; loc_542A: Pal_UNK8:
Pal_SpecialStageStars: dc.w $EEE, $CCC, $AAA, $888, $888, $AAA, $CCC, $EEE
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_543A
PalCycle_SS:
move.b (Vint_runcount+3).w,d0
andi.b #3,d0
bne.s +
move.b (SS_Star_color_1).w,d0
addi_.b #1,(SS_Star_color_1).w
andi.w #7,d0
add.w d0,d0
move.w Pal_SpecialStageStars(pc,d0.w),(Normal_palette+$1C).w
move.b (SS_Star_color_2).w,d0
addi_.b #1,(SS_Star_color_2).w
andi.w #7,d0
add.w d0,d0
move.w Pal_SpecialStageStars(pc,d0.w),(Normal_palette+$1E).w
+
cmpi.b #6,(Current_Special_Stage).w
bne.s +
cmpi.b #3,(Current_Special_Act).w
beq.w SSCheckpoint_rainbow
/
tst.b (SS_Checkpoint_Rainbow_flag).w
beq.s + ; rts
move.b (Vint_runcount+3).w,d0
andi.b #7,d0
bne.s + ; rts
move.b (SS_Rainbow_palette).w,d0
addi_.b #1,(SS_Rainbow_palette).w
andi.b #3,d0
add.w d0,d0
move.w d0,d1
add.w d0,d0
add.w d1,d0
move.w word_54C4(pc,d0.w),(Normal_palette_line4+$16).w
move.w word_54C6(pc,d0.w),(Normal_palette_line4+$18).w
move.w word_54C8(pc,d0.w),(Normal_palette_line4+$1A).w
+
rts
; ===========================================================================
; special stage rainbow blinking sprite palettes... (chaos emerald colors?)
;word_54BC:
dc.w $0EE, $0C0, $0EE, $0C0
word_54C4: dc.w $0EE
word_54C6: dc.w $0CC
word_54C8: dc.w $088, $0E0, $0C0, $080, $EE0, $CC0, $880, $E0E, $C0C, $808
; ===========================================================================
;loc_54DC
SSCheckpoint_rainbow:
tst.b (SS_Pause_Only_flag).w
beq.s -
moveq #0,d0
move.b (Vint_runcount+3).w,d0
andi.b #1,d0
bne.w -
move.w (Ring_count).w,d2
add.w (Ring_count_2P).w,d2
cmp.w (SS_Ring_Requirement).w,d2
blt.w -
lea (Normal_palette+2).w,a0
movea.l a0,a1
move.w (a0)+,d0
moveq #$B,d1
- move.w (a0)+,(a1)+
dbf d1,-
move.w d0,(a1)
rts
; End of function PalCycle_SS
;|||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_5514
SSLoadCurrentPerspective:
cmpi.b #4,(SSTrack_drawing_index).w
bne.s + ; rts
movea.l #SSRAM_MiscKoz_SpecialPerspective,a0
moveq #0,d0
move.b (SSTrack_mapping_frame).w,d0
add.w d0,d0
adda.w (a0,d0.w),a0
move.l a0,(SS_CurrentPerspective).w
+ rts
; End of function SSLoadCurrentPerspective
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_5534
SSObjectsManager:
cmpi.b #4,(SSTrack_drawing_index).w
bne.w return_55DC
moveq #0,d0
move.b (SpecialStage_CurrentSegment).w,d0
cmp.b (SpecialStage_LastSegment2).w,d0
beq.w return_55DC
move.b d0,(SpecialStage_LastSegment2).w
movea.l (SS_CurrentLevelLayout).w,a1
move.b (a1,d0.w),d3
andi.w #$7F,d3
lea (Ani_SSTrack_Len).l,a0
move.b (a0,d3.w),d3
add.w d3,d3
add.w d3,d3
movea.l (SS_CurrentLevelObjectLocations).w,a0
-
bsr.w SSSingleObjLoad
bne.s return_55DC
moveq #0,d0
move.b (a0)+,d0
bmi.s ++
move.b d0,d1
andi.b #$40,d1
bne.s +
addq.w #1,(SS_Perfect_rings_left).w
move.b #ObjID_SSRing,id(a1)
add.w d0,d0
add.w d0,d0
add.w d3,d0
move.w d0,objoff_30(a1)
move.b (a0)+,angle(a1)
bra.s -
; ===========================================================================
+
andi.w #$3F,d0
move.b #ObjID_SSBomb,id(a1)
add.w d0,d0
add.w d0,d0
add.w d3,d0
move.w d0,objoff_30(a1)
move.b (a0)+,angle(a1)
bra.s -
; ===========================================================================
+
move.l a0,(SS_CurrentLevelObjectLocations).w
addq.b #1,d0
beq.s return_55DC
addq.b #1,d0
beq.s ++
addq.b #1,d0
beq.s +
st.b (SS_NoCheckpoint_flag).w
sf.b (SS_NoCheckpointMsg_flag).w
bra.s ++
; ===========================================================================
+
tst.b (SS_2p_Flag).w
bne.s +
move.b #ObjID_SSEmerald,id(a1)
rts
; ===========================================================================
+
move.b #ObjID_SSMessage,id(a1)
return_55DC:
rts
; End of function SSObjectsManager
; ===========================================================================
SSTrackPNTCommands:
dc.l vdpComm(VRAM_SS_Plane_A_Name_Table2 + 0 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE)
dc.l vdpComm(VRAM_SS_Plane_A_Name_Table2 + 1 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE)
dc.l vdpComm(VRAM_SS_Plane_A_Name_Table2 + 2 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE)
dc.l vdpComm(VRAM_SS_Plane_A_Name_Table2 + 3 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE)
dc.l vdpComm(VRAM_SS_Plane_A_Name_Table1 + 0 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE)
dc.l vdpComm(VRAM_SS_Plane_A_Name_Table1 + 1 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE)
dc.l vdpComm(VRAM_SS_Plane_A_Name_Table1 + 2 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE)
dc.l vdpComm(VRAM_SS_Plane_A_Name_Table1 + 3 * (PNT_Buffer_End-PNT_Buffer),VRAM,WRITE)
Ani_SSTrack_Len:
dc.b SSTrackAni_TurnThenRise_End - SSTrackAni_TurnThenRise ; 0
dc.b SSTrackAni_TurnThenDrop_End - SSTrackAni_TurnThenDrop ; 1
dc.b SSTrackAni_TurnThenStraight_End - SSTrackAni_TurnThenStraight ; 2
dc.b SSTrackAni_Straight_End - SSTrackAni_Straight ; 3
dc.b SSTrackAni_StraightThenTurn_End - SSTrackAni_StraightThenTurn ; 4
dc.b 0 ; 5
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_5604
SSTrack_Draw:
moveq #0,d0
move.b (SSTrack_drawing_index).w,d0 ; Get drawing position
cmpi.b #4,d0 ; Is it time to draw a new frame?
bge.w SSTrackSetOrientation ; Branch if not
add.w d0,d0 ; Multiply by 4
add.w d0,d0
bne.w SSTrack_BeginDraw ; Branch if we don't need to start a new segment
move.l (SSTrack_last_mappings).w,(SSTrack_last_mappings_copy).w ; Save last mappings
move.b (SSTrack_mapping_frame).w,(SSTrack_last_mapping_frame).w ; Save last frame
moveq #0,d1
moveq #0,d2
moveq #0,d3
moveq #0,d4
move.b (SpecialStage_CurrentSegment).w,d1 ; Get current segment ID
move.b (SSTrack_anim_frame).w,d2 ; Get current frame
movea.l (SS_CurrentLevelLayout).w,a1 ; Pointer to level layout
move.b (a1,d1.w),d3 ; Get segment geometry type
andi.b #$7F,d3 ; Strip flip flag
move.b d3,(SSTrack_anim).w ; Set this as new animation
move.w d3,d1 ; Copy to d1
add.w d3,d3 ; Turn it into an index
lea (Ani_SpecialStageTrack).l,a1 ; Animation table
adda.w (a1,d3.w),a1 ; Add offset so a1 points to animation data
adda.w d2,a1 ; Offset into current animation frame
moveq #0,d4
move.b (a1),d4 ; d4 = animation frame to draw
move.b d4,(SSTrack_mapping_frame).w ; Save to RAM
lsl.w #2,d4
lea (Map_SpecialStageTrack).l,a1 ; Mappings table
movea.l (a1,d4.w),a0 ; a0 = pointer to mappings for current track frame
movea.l a0,a1 ; Copy to a1
moveq #0,d2
move.b (a0)+,d2 ; Skip the first 2 bytes
move.b (a0)+,d2 ; Why not 'addq.l #2,a0'?
move.b (a0)+,d2 ; Get byte
lsl.w #8,d2 ; Shift it up to be the high byte of a word
move.b (a0)+,d2 ; Read another byte; why not 'move.w (a0)+,d2'?
addq.w #4,d2 ; Add 4
adda.w d2,a1 ; Use as offset from start of file
movea.l a1,a2 ; Save to a2
moveq #0,d2
move.b (a1)+,d2 ; Skip the first 2 bytes
move.b (a1)+,d2 ; Why not 'addq.l #2,a1'?
move.b (a1)+,d2 ; Get byte
lsl.w #8,d2 ; Shift it up to be the high byte of a word
move.b (a1)+,d2 ; Read another byte; why not 'move.w (a1)+,d2'?
addq.w #4,d2 ; Add 4
adda.w d2,a2 ; Use as offset from previous offset
move.b (a2)+,d2 ; Ignore the first 3 bytes
move.b (a2)+,d2 ; Why not 'addq.l #3,a2'?
move.b (a2)+,d2
move.b (a2)+,d2 ; Get byte (unused)
move.l a0,(SSTrack_mappings_bitflags).w ; Save pointer to bit flags mappings
move.l a0,(SSTrack_last_mappings).w ; ... twice
move.l a1,(SSTrack_mappings_uncompressed).w ; Save pointer to uncompressed mappings
move.l a2,(SSTrack_mappings_RLE).w ; Save pointer to RLE mappings
lea_ Ani_SSTrack_Len,a4 ; Pointer to animation lengths
move.b (a4,d1.w),d2 ; Get length of current animation
move.b (SSTrack_anim_frame).w,(SSTrack_last_anim_frame).w ; Save old frame
addi_.b #1,(SSTrack_anim_frame).w ; Increment current frame
cmp.b (SSTrack_anim_frame).w,d2 ; Compare with animation length
bne.s SSTrack_BeginDraw ; If not equal, branch
move.b #0,(SSTrack_anim_frame).w ; Reset to start
move.b (SpecialStage_CurrentSegment).w,(SpecialStage_LastSegment).w ; Save old segment
addi_.b #1,(SpecialStage_CurrentSegment).w ; Increment current segment
;loc_56D2
SSTrack_BeginDraw:
tst.b (SS_Alternate_PNT).w ; Are we using the alternate PNT?
beq.s + ; Branch if not
addi.w #$10,d0 ; Change where we will be drawing
+
lea_ SSTrackPNTCommands,a3 ; Table of VRAM commands
movea.l (a3,d0.w),a3 ; Get command to set destination in VRAM for current frame
move.l a3,(VDP_control_port).l ; Send it to VDP
lea (VDP_data_port).l,a6
bsr.w SSTrackSetOrientation ; Set oriantation flags
movea.l (SSTrack_mappings_bitflags).w,a0 ; Get pointer to bit flags mappings
movea.l (SSTrack_mappings_uncompressed).w,a1 ; Get pointer to uncompressed mappings
movea.l (SSTrack_mappings_RLE).w,a2 ; Get pointer to RLE mappings
lea (SSDrawRegBuffer).w,a3 ; Pointer to register buffer from last draw
movem.w (a3)+,d2-d7 ; Restore registers from previous call (or set them to zero)
lea (SSPNT_UncLUT).l,a3 ; Pattern name list for drawing routines
lea (SSPNT_RLELUT).l,a4 ; RLE-encoded pattern name list for drawing routines
movea.w #-8,a5 ; Initialize loop counter: draws 7 lines
moveq #0,d0
tst.b (SSTrack_Orientation).w ; Is the current segment flipped?
bne.w SSTrackDrawLineFlipLoop ; Branch if yes
;loc_5722
SSTrackDrawLineLoop:
adda_.w #1,a5 ; Increment loop counter
cmpa.w #0,a5 ; Have all 7 lines been drawn?
beq.w SSTrackDraw_return ; If yes, return
;loc_572E
SSTrackDrawLoop_Inner:
moveq #0,d1
subq.w #1,d7 ; Subtract 1 from bit counter
bpl.s + ; Branch if we still have bits we can use
move.b (a0)+,d6 ; Get a new byte from bit flags
moveq #7,d7 ; We now have 8 fresh new bits
+
add.b d6,d6 ; Do we have to use RLE compression?
bcc.s SSTrackDrawRLE ; Branch if yes
subq.b #1,d5 ; Subtract 1 from bit counter
bpl.s + ; Branch if we still have bits we can use
move.b (a1)+,d4 ; Get a new byte from uncompressed mappings pointer
moveq #7,d5 ; We now have 8 fresh new bits
+
add.b d4,d4 ; Do we need a 10-bit index?
bcc.s + ; Branch if not
moveq #$A,d0 ; d0 = 10 bits
sub.b d5,d0 ; d0 = 10 - d5
subq.b #3,d0 ; d0 = 7 - d5; why not shorten it to 'moveq #7,d0 \n sub.b d5,d0'?
add.w d0,d0 ; Convert into table index
move.w SSTrackDrawUnc_Read10LUT(pc,d0.w),d0
jmp SSTrackDrawUnc_Read10LUT(pc,d0.w)
; ===========================================================================
;off_5758
SSTrackDrawUnc_Read10LUT: offsetTable
offsetTableEntry.w SSTrackDrawUnc_Read10_Got7 ; 0
offsetTableEntry.w SSTrackDrawUnc_Read10_Got6 ; 1
offsetTableEntry.w SSTrackDrawUnc_Read10_Got5 ; 2
offsetTableEntry.w SSTrackDrawUnc_Read10_Got4 ; 3
offsetTableEntry.w SSTrackDrawUnc_Read10_Got3 ; 4
offsetTableEntry.w SSTrackDrawUnc_Read10_Got2 ; 5
offsetTableEntry.w SSTrackDrawUnc_Read10_Got1 ; 6
offsetTableEntry.w SSTrackDrawUnc_Read10_Got0 ; 7
; ===========================================================================
+
moveq #6,d0 ; d0 = 6
sub.b d5,d0 ; d0 = 6 - d5
addq.b #1,d0 ; d0 = 7 - d5; why not shorten it to 'moveq #7,d0 \n sub.b d5,d0'?
add.w d0,d0 ; Convert into table index
move.w SSTrackDrawUnc_Read6LUT(pc,d0.w),d0
jmp SSTrackDrawUnc_Read6LUT(pc,d0.w)
; ===========================================================================
;off_5778
SSTrackDrawUnc_Read6LUT: offsetTable
offsetTableEntry.w SSTrackDrawUnc_Read6_Got7 ; 0
offsetTableEntry.w SSTrackDrawUnc_Read6_Got6 ; 1
offsetTableEntry.w SSTrackDrawUnc_Read6_Got5 ; 2
offsetTableEntry.w SSTrackDrawUnc_Read6_Got4 ; 3
offsetTableEntry.w SSTrackDrawUnc_Read6_Got3 ; 4
offsetTableEntry.w SSTrackDrawUnc_Read6_Got2 ; 5
offsetTableEntry.w SSTrackDrawUnc_Read6_Got1 ; 6
offsetTableEntry.w SSTrackDrawUnc_Read6_Got0 ; 7
; ===========================================================================
SSTrackDrawRLE:
subq.b #1,d3 ; Subtract 1 from bit counter
bpl.s ++ ; Branch if we still have bits we can use
move.b (a2)+,d2 ; Get a new byte from RLE mappings pointer
cmpi.b #-1,d2 ; Is d2 equal to -1?
bne.s + ; Branch if not
moveq #0,d3 ; Set bit counter to zero
bra.w SSTrackDrawLineLoop
; ===========================================================================
+
moveq #7,d3 ; We now have 8 fresh new bits
+
add.b d2,d2 ; Do we need a 7-bit index?
bcc.s + ; Branch if not
moveq #7,d0 ; d0 = 7
sub.b d3,d0 ; d0 = 10 - d3
add.b d0,d0 ; Convert into table index
move.w SSTrackDrawRLE_Read7LUT(pc,d0.w),d0
jmp SSTrackDrawRLE_Read7LUT(pc,d0.w)
; ===========================================================================
;off_57AE
SSTrackDrawRLE_Read7LUT: offsetTable
offsetTableEntry.w SSTrackDrawRLE_Read7_Got7 ; 0
offsetTableEntry.w SSTrackDrawRLE_Read7_Got6 ; 1
offsetTableEntry.w SSTrackDrawRLE_Read7_Got5 ; 2
offsetTableEntry.w SSTrackDrawRLE_Read7_Got4 ; 3
offsetTableEntry.w SSTrackDrawRLE_Read7_Got3 ; 4
offsetTableEntry.w SSTrackDrawRLE_Read7_Got2 ; 5
offsetTableEntry.w SSTrackDrawRLE_Read7_Got1 ; 6
offsetTableEntry.w SSTrackDrawRLE_Read7_Got0 ; 7
; ===========================================================================
+
moveq #6,d0 ; d0 = 6
sub.b d3,d0 ; d0 = 6 - d3
addq.b #1,d0 ; d0 = 7 - d3; why not shorten it to 'moveq #7,d0 \n sub.b d3,d0'?
add.b d0,d0 ; Convert into table index
move.w SSTrackDrawRLE_Read6LUT(pc,d0.w),d0
jmp SSTrackDrawRLE_Read6LUT(pc,d0.w)
; ===========================================================================
;off_57CE
SSTrackDrawRLE_Read6LUT: offsetTable
offsetTableEntry.w SSTrackDrawRLE_Read6_Got7 ; 0
offsetTableEntry.w SSTrackDrawRLE_Read6_Got6 ; 1
offsetTableEntry.w SSTrackDrawRLE_Read6_Got5 ; 2
offsetTableEntry.w SSTrackDrawRLE_Read6_Got4 ; 3
offsetTableEntry.w SSTrackDrawRLE_Read6_Got3 ; 4
offsetTableEntry.w SSTrackDrawRLE_Read6_Got2 ; 5
offsetTableEntry.w SSTrackDrawRLE_Read6_Got1 ; 6
offsetTableEntry.w SSTrackDrawRLE_Read6_Got0 ; 7
; ===========================================================================
;loc_57DE
SSTrackDrawUnc_Read10_Got0:
; Reads 10 bits from uncompressed mappings, 0 bits in bit buffer
moveq #0,d0
move.b (a1)+,d0
lsl.w #2,d0
move.b (a1)+,d4
rol.b #2,d4
move.b d4,d1
andi.b #3,d1
or.b d1,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #6,d5
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5806
SSTrackDrawUnc_Read10_Got1:
; Reads 10 bits from uncompressed mappings, 1 bit in bit buffer
move.b d4,d0
lsl.w #2,d0
andi.w #$200,d0
move.b (a1)+,d1
lsl.w #1,d1
or.w d1,d0
move.b (a1)+,d4
rol.b #1,d4
move.b d4,d1
andi.b #1,d1
or.b d1,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #7,d5
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5836
SSTrackDrawUnc_Read10_Got2:
; Reads 10 bits from uncompressed mappings, 2 bits in bit buffer
move.b d4,d0
lsl.w #2,d0
andi.w #$300,d0
move.b (a1)+,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #0,d5 ; Bit buffer now empty
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5856
SSTrackDrawUnc_Read10_Got3:
; Reads 10 bits from uncompressed mappings, 3 bits in bit buffer
move.b d4,d0
lsl.w #2,d0
andi.w #$380,d0
move.b (a1)+,d4
ror.b #1,d4
move.b d4,d1
andi.b #$7F,d1
or.b d1,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #1,d5 ; Bit buffer now has 1 bit
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5880
SSTrackDrawUnc_Read10_Got4:
; Reads 10 bits from uncompressed mappings, 4 bits in bit buffer
move.b d4,d0
lsl.w #2,d0
andi.w #$3C0,d0
move.b (a1)+,d4
ror.b #2,d4
move.b d4,d1
andi.b #$3F,d1
or.b d1,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #2,d5 ; Bit buffer now has 2 bits
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_58AA
SSTrackDrawUnc_Read10_Got5:
; Reads 10 bits from uncompressed mappings, 5 bits in bit buffer
move.b d4,d0
lsl.w #2,d0
andi.w #$3E0,d0
move.b (a1)+,d4
ror.b #3,d4
move.b d4,d1
andi.b #$1F,d1
or.b d1,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #3,d5 ; Bit buffer now has 3 bits
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_58D4
SSTrackDrawUnc_Read10_Got6:
; Reads 10 bits from uncompressed mappings, 6 bits in bit buffer
move.b d4,d0
lsl.w #2,d0
andi.w #$3F0,d0
move.b (a1)+,d4
ror.b #4,d4
move.b d4,d1
andi.b #$F,d1
or.b d1,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #4,d5 ; Bit buffer now has 4 bits
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_58FE
SSTrackDrawUnc_Read10_Got7:
; Reads 10 bits from uncompressed mappings, 7 bits in bit buffer
move.b d4,d0
lsl.w #2,d0
andi.w #$3F8,d0
move.b (a1)+,d4
rol.b #3,d4
move.b d4,d1
andi.b #7,d1
or.b d1,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #5,d5 ; Bit buffer now has 5 bits
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5928
SSTrackDrawUnc_Read6_Got0:
; Reads 6 bits from uncompressed mappings, 0 bits in bit buffer
move.b (a1)+,d4
ror.b #2,d4
move.b d4,d0
andi.w #$3F,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #2,d5 ; Bit buffer now has 2 bits
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5944
SSTrackDrawUnc_Read6_Got1:
; Reads 6 bits from uncompressed mappings, 1 bit in bit buffer
move.b d4,d0
lsr.b #2,d0
andi.w #$20,d0
move.b (a1)+,d4
ror.b #3,d4
move.b d4,d1
andi.b #$1F,d1
or.b d1,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #3,d5 ; Bit buffer now has 3 bits
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_596A
SSTrackDrawUnc_Read6_Got2:
; Reads 6 bits from uncompressed mappings, 2 bits in bit buffer
move.b d4,d0
lsr.b #2,d0
andi.w #$30,d0
move.b (a1)+,d4
ror.b #4,d4
move.b d4,d1
andi.b #$F,d1
or.b d1,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #4,d5 ; Bit buffer now has 4 bits
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5990
SSTrackDrawUnc_Read6_Got3:
; Reads 6 bits from uncompressed mappings, 3 bits in bit buffer
move.b d4,d0
lsr.b #2,d0
andi.w #$38,d0
move.b (a1)+,d4
rol.b #3,d4
move.b d4,d1
andi.b #7,d1
or.b d1,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #5,d5 ; Bit buffer now has 5 bits
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_59B6
SSTrackDrawUnc_Read6_Got4:
; Reads 6 bits from uncompressed mappings, 4 bits in bit buffer
move.b d4,d0
lsr.b #2,d0
andi.w #$3C,d0
move.b (a1)+,d4
rol.b #2,d4
move.b d4,d1
andi.b #3,d1
or.b d1,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #6,d5 ; Bit buffer now has 6 bits
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_59DC
SSTrackDrawUnc_Read6_Got5:
; Reads 6 bits from uncompressed mappings, 5 bits in bit buffer
move.b d4,d0
lsr.b #2,d0
andi.w #$3E,d0
move.b (a1)+,d4
rol.b #1,d4
move.b d4,d1
andi.b #1,d1
or.b d1,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #7,d5 ; Bit buffer now has 7 bits
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5A02
SSTrackDrawUnc_Read6_Got6:
; Reads 6 bits from uncompressed mappings, 6 bits in bit buffer
lsr.b #2,d4
andi.w #$3F,d4
add.w d4,d4
move.w (a3,d4.w),d4
ori.w #palette_line_3,d4
move.w d4,(a6)
moveq #0,d5 ; Bit buffer now empty
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5A1A
SSTrackDrawUnc_Read6_Got7:
; Reads 6 bits from uncompressed mappings, 7 bits in bit buffer
ror.b #2,d4
move.b d4,d0
andi.w #$3F,d0
add.w d0,d0
move.w (a3,d0.w),d0
ori.w #palette_line_3,d0
move.w d0,(a6)
moveq #1,d5 ; Bit buffer now has 1 bit
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5A34
SSTrackDrawRLE_Read7_Got0:
; Reads 7 bits from RLE-compressed mappings, 0 bits in bit buffer
move.b (a2)+,d2
ror.b #1,d2
move.b d2,d0
andi.w #$7F,d0
moveq #1,d3 ; Bit buffer now has 1 bit
cmpi.b #$7F,d0
beq.w SSTrackDrawLineLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5A66
SSTrackDrawRLE_Read7_Got1:
; Reads 7 bits from RLE-compressed mappings, 1 bit in bit buffer
move.b d2,d1
lsr.b #1,d1
andi.b #$40,d1
move.b (a2)+,d2
ror.b #2,d2
move.b d2,d0
andi.w #$3F,d0
or.b d1,d0
moveq #2,d3 ; Bit buffer now has 2 bits
cmpi.b #$7F,d0
beq.w SSTrackDrawLineLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5AA2
SSTrackDrawRLE_Read7_Got2:
; Reads 7 bits from RLE-compressed mappings, 2 bits in bit buffer
move.b d2,d1
lsr.b #1,d1
andi.b #$60,d1
move.b (a2)+,d2
ror.b #3,d2
move.b d2,d0
andi.w #$1F,d0
or.b d1,d0
moveq #3,d3 ; Bit buffer now has 3 bits
cmpi.b #$7F,d0
beq.w SSTrackDrawLineLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5ADE
SSTrackDrawRLE_Read7_Got3:
; Reads 7 bits from RLE-compressed mappings, 3 bits in bit buffer
move.b d2,d1
lsr.b #1,d1
andi.b #$70,d1
move.b (a2)+,d2
ror.b #4,d2
move.b d2,d0
andi.w #$F,d0
or.b d1,d0
moveq #4,d3 ; Bit buffer now has 4 bits
cmpi.b #$7F,d0
beq.w SSTrackDrawLineLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5B1A
SSTrackDrawRLE_Read7_Got4:
; Reads 7 bits from RLE-compressed mappings, 4 bits in bit buffer
move.b d2,d1
lsr.b #1,d1
andi.b #$78,d1
move.b (a2)+,d2
rol.b #3,d2
move.b d2,d0
andi.w #7,d0
or.b d1,d0
moveq #5,d3 ; Bit buffer now has 5 bits
cmpi.b #$7F,d0
beq.w SSTrackDrawLineLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5B56
SSTrackDrawRLE_Read7_Got5:
; Reads 7 bits from RLE-compressed mappings, 5 bits in bit buffer
move.b d2,d1
lsr.b #1,d1
andi.b #$7C,d1
move.b (a2)+,d2
rol.b #2,d2
move.b d2,d0
andi.w #3,d0
or.b d1,d0
moveq #6,d3 ; Bit buffer now has 6 bits
cmpi.b #$7F,d0
beq.w SSTrackDrawLineLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5B92
SSTrackDrawRLE_Read7_Got6:
; Reads 7 bits from RLE-compressed mappings, 6 bits in bit buffer
move.b d2,d1
lsr.b #1,d1
andi.b #$7E,d1
move.b (a2)+,d2
rol.b #1,d2
move.b d2,d0
andi.w #1,d0
or.b d1,d0
moveq #7,d3 ; Bit buffer now has 7 bits
cmpi.b #$7F,d0
beq.w SSTrackDrawLineLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5BCE
SSTrackDrawRLE_Read7_Got7:
; Reads 7 bits from RLE-compressed mappings, 7 bits in bit buffer
lsr.b #1,d2
andi.w #$7F,d2
moveq #0,d3 ; Bit buffer now empty
cmpi.b #$7F,d2
beq.w SSTrackDrawLineLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d2
add.w d2,d2
add.w d2,d2
move.w (a4,d2.w),d1
move.w 2(a4,d2.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5BFC
SSTrackDrawRLE_Read6_Got0:
; Reads 6 bits from RLE-compressed mappings, 0 bits in bit buffer
move.b (a2)+,d2
ror.b #2,d2
move.b d2,d0
andi.w #$3F,d0
add.w d0,d0
add.w d0,d0
moveq #2,d3 ; Bit buffer now has 2 bits
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5C22
SSTrackDrawRLE_Read6_Got1:
; Reads 6 bits from RLE-compressed mappings, 1 bit in bit buffer
move.b d2,d0
lsr.b #2,d0
andi.w #$20,d0
move.b (a2)+,d2
ror.b #3,d2
move.b d2,d1
andi.b #$1F,d1
or.b d1,d0
moveq #3,d3 ; Bit buffer now has 3 bits
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5C52
SSTrackDrawRLE_Read6_Got2:
; Reads 6 bits from RLE-compressed mappings, 2 bits in bit buffer
move.b d2,d0
lsr.b #2,d0
andi.w #$30,d0
move.b (a2)+,d2
ror.b #4,d2
move.b d2,d1
andi.b #$F,d1
or.b d1,d0
add.w d0,d0
add.w d0,d0
moveq #4,d3 ; Bit buffer now has 4 bits
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5C82
SSTrackDrawRLE_Read6_Got3:
; Reads 6 bits from RLE-compressed mappings, 3 bits in bit buffer
move.b d2,d0
lsr.b #2,d0
andi.w #$38,d0
move.b (a2)+,d2
rol.b #3,d2
move.b d2,d1
andi.b #7,d1
or.b d1,d0
add.w d0,d0
add.w d0,d0
moveq #5,d3 ; Bit buffer now has 5 bits
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5CB2
SSTrackDrawRLE_Read6_Got4:
; Reads 6 bits from RLE-compressed mappings, 4 bits in bit buffer
move.b d2,d0
lsr.b #2,d0
andi.w #$3C,d0
move.b (a2)+,d2
rol.b #2,d2
move.b d2,d1
andi.b #3,d1
or.b d1,d0
add.w d0,d0
add.w d0,d0
moveq #6,d3 ; Bit buffer now has 6 bits
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5CE2
SSTrackDrawRLE_Read6_Got5:
; Reads 6 bits from RLE-compressed mappings, 5 bits in bit buffer
move.b d2,d0
lsr.b #2,d0
andi.w #$3E,d0
move.b (a2)+,d2
rol.b #1,d2
move.b d2,d1
andi.b #1,d1
or.b d1,d0
add.w d0,d0
add.w d0,d0
moveq #7,d3 ; Bit buffer now has 7 bits
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5D12
SSTrackDrawRLE_Read6_Got6:
; Reads 6 bits from RLE-compressed mappings, 6 bits in bit buffer
lsr.b #2,d2
andi.w #$3F,d2
add.w d2,d2
add.w d2,d2
moveq #0,d3 ; Bit buffer now empty
move.w (a4,d2.w),d1
move.w 2(a4,d2.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5D34
SSTrackDrawRLE_Read6_Got7:
; Reads 6 bits from RLE-compressed mappings, 7 bits in bit buffer
ror.b #2,d2
move.b d2,d0
andi.w #$3F,d0
add.w d0,d0
add.w d0,d0
moveq #1,d3 ; Bit buffer now has 1 bit
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,(a6)
dbf d0,-
bra.w SSTrackDrawLoop_Inner
; ===========================================================================
;loc_5D58
SSTrackDraw_return:
cmpi.b #3,(SSTrack_drawing_index).w ; Have we drawed a full frame?
beq.s + ; Branch if yes
move.l a0,(SSTrack_mappings_bitflags).w ; Save pointer
move.l a1,(SSTrack_mappings_uncompressed).w ; Save pointer
move.l a2,(SSTrack_mappings_RLE).w ; Save pointer
lea (SSDrawRegBuffer_End).w,a3 ; Pointer to end of registry buffer
movem.w d2-d7,-(a3) ; Save the bit buffers and bit counters
rts
; ===========================================================================
+
lea (SSDrawRegBuffer).w,a2 ; Pointer to registry buffer
moveq #0,d0
rept 6
move.w d0,(a2)+ ; Clear bit buffers and bit counters
endm
rts
; ===========================================================================
;loc_5D8A
SSTrackDrawLineFlipLoop:
adda_.w #1,a5 ; Increment loop counter
cmpa.w #0,a5 ; Have all 8 lines been drawn?
beq.w SSTrackDraw_return ; If yes, return
lea (PNT_Buffer).w,a6 ; Destination buffer
swap d0 ; High word starts at 0
addi.w #$100,d0 ; Adding $100 means seek to end of current line/start of next line
andi.w #$F00,d0 ; Keep to confines
adda.w d0,a6 ; Seek to end of current line
swap d0 ; Leaves the low word of d0 free for use
;loc_5DA8
SSTrackDrawFlipLoop_Inner:
moveq #0,d1
subq.w #1,d7 ; Subtract 1 from bit counter
bpl.s + ; Branch if we still have bits we can use
move.b (a0)+,d6 ; Get a new byte from bit flags
moveq #7,d7 ; We now have 8 fresh new bits
+
add.b d6,d6 ; Do we have to use RLE compression?
bcc.s SSTrackDrawFlipRLE ; Branch if yes
subq.b #1,d5 ; Subtract 1 from bit counter
bpl.s + ; Branch if we still have bits we can use
move.b (a1)+,d4 ; Get a new byte from uncompressed mappings pointer
moveq #7,d5 ; We now have 8 fresh new bits
+
add.b d4,d4 ; Do we need a 10-bit index?
bcc.s + ; Branch if not
move.w #$A,d0 ; d0 = 10 bits
sub.b d5,d0 ; d0 = 10 - d5
subq.b #3,d0 ; d0 = 7 - d5; why not shorten it to 'moveq #7,d0 \n sub.b d5,d0'?
add.w d0,d0 ; Convert into table index
move.w SSTrackDrawFlipUnc_Read10LUT(pc,d0.w),d0
jmp SSTrackDrawFlipUnc_Read10LUT(pc,d0.w)
; ===========================================================================
;off_5DD4
SSTrackDrawFlipUnc_Read10LUT: offsetTable
offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got7 ; 0
offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got6 ; 1
offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got5 ; 2
offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got4 ; 3
offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got3 ; 4
offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got2 ; 5
offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got1 ; 6
offsetTableEntry.w SSTrackDrawFlipUnc_Read10_Got0 ; 7
; ===========================================================================
+
move.w #6,d0 ; d0 = 6
sub.b d5,d0 ; d0 = 6 - d5
addq.b #1,d0 ; d0 = 7 - d5; why not shorten it to 'moveq #7,d0 \n sub.b d5,d0'?
add.w d0,d0 ; Convert into table index
move.w SSTrackDrawFlipUnc_Read6LUT(pc,d0.w),d0
jmp SSTrackDrawFlipUnc_Read6LUT(pc,d0.w)
; ===========================================================================
;off_5DF6
SSTrackDrawFlipUnc_Read6LUT: offsetTable
offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got7 ; 0
offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got6 ; 1
offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got5 ; 2
offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got4 ; 3
offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got3 ; 4
offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got2 ; 5
offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got1 ; 6
offsetTableEntry.w SSTrackDrawFlipUnc_Read6_Got0 ; 7
; ===========================================================================
;loc_5E06
SSTrackDrawFlipRLE:
subq.b #1,d3 ; Subtract 1 from bit counter
bpl.s ++ ; Branch if we still have bits we can use
move.b (a2)+,d2 ; Get a new byte from RLE mappings pointer
cmpi.b #-1,d2 ; Is d2 equal to -1?
bne.s + ; Branch if not
moveq #0,d3 ; Set bit counter to zero
bra.w SSTrackDrawLineFlipLoop
; ===========================================================================
+
moveq #7,d3 ; We now have 8 fresh new bits
+
add.b d2,d2 ; Do we need a 7-bit index?
bcc.s + ; Branch if not
move.w #7,d0 ; d0 = 7
sub.b d3,d0 ; d0 = 10 - d3
add.b d0,d0 ; Convert into table index
move.w SSTrackDrawFlipRLE_Read7LUT(pc,d0.w),d0
jmp SSTrackDrawFlipRLE_Read7LUT(pc,d0.w)
; ===========================================================================
;off_5E2E
SSTrackDrawFlipRLE_Read7LUT: offsetTable
offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got7 ; 0
offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got6 ; 1
offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got5 ; 2
offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got4 ; 3
offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got3 ; 4
offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got2 ; 5
offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got1 ; 6
offsetTableEntry.w SSTrackDrawFlipRLE_Read7_Got0 ; 7
; ===========================================================================
+
move.w #6,d0 ; d0 = 6
sub.b d3,d0 ; d0 = 6 - d3
addq.b #1,d0 ; d0 = 7 - d3; why not shorten it to 'moveq #7,d0 \n sub.b d3,d0'?
add.b d0,d0 ; Convert into table index
move.w SSTrackDrawFlipRLE_Read6LUT(pc,d0.w),d0
jmp SSTrackDrawFlipRLE_Read6LUT(pc,d0.w)
; ===========================================================================
;off_5E50
SSTrackDrawFlipRLE_Read6LUT: offsetTable
offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got7 ; 0
offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got6 ; 1
offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got5 ; 2
offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got4 ; 3
offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got3 ; 4
offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got2 ; 5
offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got1 ; 6
offsetTableEntry.w SSTrackDrawFlipRLE_Read6_Got0 ; 7
; ===========================================================================
;loc_5E60
SSTrackDrawFlipUnc_Read10_Got0:
; Reads 10 bits from uncompressed mappings, 0 bits in bit buffer
move.w #0,d0
move.b (a1)+,d0
lsl.w #2,d0
move.b (a1)+,d4
rol.b #2,d4
move.b d4,d1
andi.b #3,d1
or.b d1,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #6,d5 ; Bit buffer now has 6 bits
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_5E8A
SSTrackDrawFlipUnc_Read10_Got1:
; Reads 10 bits from uncompressed mappings, 1 bit in bit buffer
move.b d4,d0
lsl.w #2,d0
andi.w #$200,d0
move.b (a1)+,d1
lsl.w #1,d1
or.w d1,d0
move.b (a1)+,d4
rol.b #1,d4
move.b d4,d1
andi.b #1,d1
or.b d1,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #7,d5 ; Bit buffer now has 7 bits
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_5EBA
SSTrackDrawFlipUnc_Read10_Got2:
; Reads 10 bits from uncompressed mappings, 2 bits in bit buffer
move.b d4,d0
lsl.w #2,d0
andi.w #$300,d0
move.b (a1)+,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #0,d5 ; Bit buffer now empty
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_5EDA
SSTrackDrawFlipUnc_Read10_Got3:
; Reads 10 bits from uncompressed mappings, 3 bits in bit buffer
move.b d4,d0
lsl.w #2,d0
andi.w #$380,d0
move.b (a1)+,d4
ror.b #1,d4
move.b d4,d1
andi.b #$7F,d1
or.b d1,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #1,d5 ; Bit buffer now has 1 bit
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_5F04
SSTrackDrawFlipUnc_Read10_Got4:
; Reads 10 bits from uncompressed mappings, 4 bits in bit buffer
move.b d4,d0
lsl.w #2,d0
andi.w #$3C0,d0
move.b (a1)+,d4
ror.b #2,d4
move.b d4,d1
andi.b #$3F,d1
or.b d1,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #2,d5 ; Bit buffer now has 2 bits
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_5F2E
SSTrackDrawFlipUnc_Read10_Got5:
; Reads 10 bits from uncompressed mappings, 5 bits in bit buffer
move.b d4,d0
lsl.w #2,d0
andi.w #$3E0,d0
move.b (a1)+,d4
ror.b #3,d4
move.b d4,d1
andi.b #$1F,d1
or.b d1,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #3,d5 ; Bit buffer now has 3 bits
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_5F58
SSTrackDrawFlipUnc_Read10_Got6:
; Reads 10 bits from uncompressed mappings, 6 bits in bit buffer
move.b d4,d0
lsl.w #2,d0
andi.w #$3F0,d0
move.b (a1)+,d4
ror.b #4,d4
move.b d4,d1
andi.b #$F,d1
or.b d1,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #4,d5 ; Bit buffer now has 4 bits
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_5F82
SSTrackDrawFlipUnc_Read10_Got7:
; Reads 10 bits from uncompressed mappings, 7 bits in bit buffer
move.b d4,d0
lsl.w #2,d0
andi.w #$3F8,d0
move.b (a1)+,d4
rol.b #3,d4
move.b d4,d1
andi.b #7,d1
or.b d1,d0
addi.w #(SSPNT_UncLUT_Part2-SSPNT_UncLUT)/2,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #5,d5 ; Bit buffer now has 5 bits
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_5FAC
SSTrackDrawFlipUnc_Read6_Got0:
; Reads 6 bits from uncompressed mappings, 0 bits in bit buffer
move.b (a1)+,d4
ror.b #2,d4
move.b d4,d0
andi.w #$3F,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #2,d5 ; Bit buffer now has 2 bits
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_5FC8
SSTrackDrawFlipUnc_Read6_Got1:
; Reads 6 bits from uncompressed mappings, 1 bit in bit buffer
move.b d4,d0
lsr.b #2,d0
andi.w #$20,d0
move.b (a1)+,d4
ror.b #3,d4
move.b d4,d1
andi.b #$1F,d1
or.b d1,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #3,d5 ; Bit buffer now has 3 bits
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_5FEE
SSTrackDrawFlipUnc_Read6_Got2:
; Reads 6 bits from uncompressed mappings, 2 bits in bit buffer
move.b d4,d0
lsr.b #2,d0
andi.w #$30,d0
move.b (a1)+,d4
ror.b #4,d4
move.b d4,d1
andi.b #$F,d1
or.b d1,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #4,d5 ; Bit buffer now has 4 bits
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_6014
SSTrackDrawFlipUnc_Read6_Got3:
; Reads 6 bits from uncompressed mappings, 3 bits in bit buffer
move.b d4,d0
lsr.b #2,d0
andi.w #$38,d0
move.b (a1)+,d4
rol.b #3,d4
move.b d4,d1
andi.b #7,d1
or.b d1,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #5,d5 ; Bit buffer now has 5 bits
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_603A
SSTrackDrawFlipUnc_Read6_Got4:
; Reads 6 bits from uncompressed mappings, 4 bits in bit buffer
move.b d4,d0
lsr.b #2,d0
andi.w #$3C,d0
move.b (a1)+,d4
rol.b #2,d4
move.b d4,d1
andi.b #3,d1
or.b d1,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #6,d5 ; Bit buffer now has 6 bits
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_6060
SSTrackDrawFlipUnc_Read6_Got5:
; Reads 6 bits from uncompressed mappings, 5 bits in bit buffer
move.b d4,d0
lsr.b #2,d0
andi.w #$3E,d0
move.b (a1)+,d4
rol.b #1,d4
move.b d4,d1
andi.b #1,d1
or.b d1,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #7,d5 ; Bit buffer now has 7 bits
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_6086
SSTrackDrawFlipUnc_Read6_Got6:
; Reads 6 bits from uncompressed mappings, 6 bits in bit buffer
lsr.b #2,d4
andi.w #$3F,d4
add.w d4,d4
move.w (a3,d4.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #0,d5 ; Bit buffer now empty
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_609E
SSTrackDrawFlipUnc_Read6_Got7:
; Reads 6 bits from uncompressed mappings, 7 bits in bit buffer
ror.b #2,d4
move.b d4,d0
andi.w #$3F,d0
add.w d0,d0
move.w (a3,d0.w),d0
eori.w #flip_x|palette_line_3,d0
move.w d0,-(a6)
moveq #1,d5 ; Bit buffer now has 1 bit
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_60B8
SSTrackDrawFlipRLE_Read7_Got0:
; Reads 7 bits from RLE-compressed mappings, 0 bits in bit buffer
move.b (a2)+,d2
ror.b #1,d2
move.b d2,d0
andi.w #$7F,d0
moveq #1,d3 ; Bit buffer now has 1 bit
cmpi.b #$7F,d0
beq.w SSTrackDrawLineFlipLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_60EA
SSTrackDrawFlipRLE_Read7_Got1:
; Reads 7 bits from RLE-compressed mappings, 1 bit in bit buffer
move.b d2,d1
lsr.b #1,d1
andi.b #$40,d1
move.b (a2)+,d2
ror.b #2,d2
move.b d2,d0
andi.w #$3F,d0
or.b d1,d0
moveq #2,d3 ; Bit buffer now has 2 bits
cmpi.b #$7F,d0
beq.w SSTrackDrawLineFlipLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_6126
SSTrackDrawFlipRLE_Read7_Got2:
; Reads 7 bits from RLE-compressed mappings, 2 bits in bit buffer
move.b d2,d1
lsr.b #1,d1
andi.b #$60,d1
move.b (a2)+,d2
ror.b #3,d2
move.b d2,d0
andi.w #$1F,d0
or.b d1,d0
moveq #3,d3 ; Bit buffer now has 3 bits
cmpi.b #$7F,d0
beq.w SSTrackDrawLineFlipLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_6162
SSTrackDrawFlipRLE_Read7_Got3:
; Reads 7 bits from RLE-compressed mappings, 3 bits in bit buffer
move.b d2,d1
lsr.b #1,d1
andi.b #$70,d1
move.b (a2)+,d2
ror.b #4,d2
move.b d2,d0
andi.w #$F,d0
or.b d1,d0
moveq #4,d3 ; Bit buffer now has 4 bits
cmpi.b #$7F,d0
beq.w SSTrackDrawLineFlipLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_619E
SSTrackDrawFlipRLE_Read7_Got4:
; Reads 7 bits from RLE-compressed mappings, 4 bits in bit buffer
move.b d2,d1
lsr.b #1,d1
andi.b #$78,d1
move.b (a2)+,d2
rol.b #3,d2
move.b d2,d0
andi.w #7,d0
or.b d1,d0
moveq #5,d3 ; Bit buffer now has 5 bits
cmpi.b #$7F,d0
beq.w SSTrackDrawLineFlipLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_61DA
SSTrackDrawFlipRLE_Read7_Got5:
; Reads 7 bits from RLE-compressed mappings, 5 bits in bit buffer
move.b d2,d1
lsr.b #1,d1
andi.b #$7C,d1
move.b (a2)+,d2
rol.b #2,d2
move.b d2,d0
andi.w #3,d0
or.b d1,d0
moveq #6,d3 ; Bit buffer now has 6 bits
cmpi.b #$7F,d0
beq.w SSTrackDrawLineFlipLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_6216
SSTrackDrawFlipRLE_Read7_Got6:
; Reads 7 bits from RLE-compressed mappings, 6 bits in bit buffer
move.b d2,d1
lsr.b #1,d1
andi.b #$7E,d1
move.b (a2)+,d2
rol.b #1,d2
move.b d2,d0
andi.w #1,d0
or.b d1,d0
moveq #7,d3 ; Bit buffer now has 7 bits
cmpi.b #$7F,d0
beq.w SSTrackDrawLineFlipLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d0
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_6252
SSTrackDrawFlipRLE_Read7_Got7:
; Reads 7 bits from RLE-compressed mappings, 7 bits in bit buffer
lsr.b #1,d2
andi.w #$7F,d2
moveq #0,d3 ; Bit buffer now empty
cmpi.b #$7F,d2
beq.w SSTrackDrawLineFlipLoop
addi.w #(SSPNT_RLELUT_Part2-SSPNT_RLELUT)/4,d2
add.w d2,d2
add.w d2,d2
move.w (a4,d2.w),d1
move.w 2(a4,d2.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_6280
SSTrackDrawFlipRLE_Read6_Got0:
; Reads 6 bits from RLE-compressed mappings, 0 bits in bit buffer
move.b (a2)+,d2
ror.b #2,d2
move.b d2,d0
andi.w #$3F,d0
add.w d0,d0
add.w d0,d0
moveq #2,d3 ; Bit buffer now has 2 bits
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_62A6
SSTrackDrawFlipRLE_Read6_Got1:
; Reads 6 bits from RLE-compressed mappings, 1 bit in bit buffer
move.b d2,d0
lsr.b #2,d0
andi.w #$20,d0
move.b (a2)+,d2
ror.b #3,d2
move.b d2,d1
andi.b #$1F,d1
or.b d1,d0
moveq #3,d3 ; Bit buffer now has 3 bits
add.w d0,d0
add.w d0,d0
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_62D6
SSTrackDrawFlipRLE_Read6_Got2:
; Reads 6 bits from RLE-compressed mappings, 2 bits in bit buffer
move.b d2,d0
lsr.b #2,d0
andi.w #$30,d0
move.b (a2)+,d2
ror.b #4,d2
move.b d2,d1
andi.b #$F,d1
or.b d1,d0
add.w d0,d0
add.w d0,d0
moveq #4,d3 ; Bit buffer now has 4 bits
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_6306
SSTrackDrawFlipRLE_Read6_Got3:
; Reads 6 bits from RLE-compressed mappings, 3 bits in bit buffer
move.b d2,d0
lsr.b #2,d0
andi.w #$38,d0
move.b (a2)+,d2
rol.b #3,d2
move.b d2,d1
andi.b #7,d1
or.b d1,d0
add.w d0,d0
add.w d0,d0
moveq #5,d3 ; Bit buffer now has 5 bits
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_6336
SSTrackDrawFlipRLE_Read6_Got4:
; Reads 6 bits from RLE-compressed mappings, 4 bits in bit buffer
move.b d2,d0
lsr.b #2,d0
andi.w #$3C,d0
move.b (a2)+,d2
rol.b #2,d2
move.b d2,d1
andi.b #3,d1
or.b d1,d0
add.w d0,d0
add.w d0,d0
moveq #6,d3 ; Bit buffer now has 6 bits
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_6366
SSTrackDrawFlipRLE_Read6_Got5:
; Reads 6 bits from RLE-compressed mappings, 5 bits in bit buffer
move.b d2,d0
lsr.b #2,d0
andi.w #$3E,d0
move.b (a2)+,d2
rol.b #1,d2
move.b d2,d1
andi.b #1,d1
or.b d1,d0
add.w d0,d0
add.w d0,d0
moveq #7,d3 ; Bit buffer now has 7 bits
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_6396
SSTrackDrawFlipRLE_Read6_Got6:
; Reads 6 bits from RLE-compressed mappings, 6 bits in bit buffer
lsr.b #2,d2
andi.w #$3F,d2
add.w d2,d2
add.w d2,d2
moveq #0,d3 ; Bit buffer now empty
move.w (a4,d2.w),d1
move.w 2(a4,d2.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
;loc_63B8
SSTrackDrawFlipRLE_Read6_Got7:
; Reads 6 bits from RLE-compressed mappings, 7 bits in bit buffer
ror.b #2,d2
move.b d2,d0
andi.w #$3F,d0
add.w d0,d0
add.w d0,d0
moveq #1,d3 ; Bit buffer now has 1 bit
move.w (a4,d0.w),d1
move.w 2(a4,d0.w),d0
ori.w #palette_line_3|high_priority,d1
- move.w d1,-(a6)
dbf d0,-
bra.w SSTrackDrawFlipLoop_Inner
; ===========================================================================
; frames of animation of the special stage track
; this chooses how objects curve along the track as well as which track frame to draw
; off_63DC:
Ani_SpecialStageTrack: offsetTable
offsetTableEntry.w SSTrackAni_TurnThenRise ; 0
offsetTableEntry.w SSTrackAni_TurnThenDrop ; 1
offsetTableEntry.w SSTrackAni_TurnThenStraight ; 2
offsetTableEntry.w SSTrackAni_Straight ; 3
offsetTableEntry.w SSTrackAni_StraightThenTurn ; 4
; byte_63E6:
SSTrackAni_TurnThenRise:
dc.b $26,$27,$28,$29,$2A,$2B,$26 ; turning
dc.b 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, $A, $B, $C, $D, $E, $F,$10 ; rise
SSTrackAni_TurnThenRise_End:
; byte_63FE:
SSTrackAni_TurnThenDrop:
dc.b $26,$27,$28,$29,$2A,$2B,$26 ; turning
dc.b $15,$16,$17,$18,$19,$1A,$1B,$1C,$1D,$1E,$1F,$20,$21,$22,$23,$24,$25 ; drop
SSTrackAni_TurnThenDrop_End:
; byte_6416:
SSTrackAni_TurnThenStraight:
dc.b $26,$27,$28,$29,$2A,$2B,$26 ; turning
dc.b $2C,$2D,$2E,$2F,$30 ; exit turn
SSTrackAni_TurnThenStraight_End:
; byte_6422:
SSTrackAni_Straight:
dc.b $11,$12,$13,$14,$11,$12,$13,$14 ; straight
dc.b $11,$12,$13,$14,$11,$12,$13,$14 ; straight
SSTrackAni_Straight_End:
; byte_6432:
SSTrackAni_StraightThenTurn:
dc.b $11,$12,$13,$14 ; straight
dc.b $31,$32,$33,$34,$35,$36,$37 ; enter turn
SSTrackAni_StraightThenTurn_End:
even
; ===========================================================================
; pointers to the mappings for each frame of the special stage track
; indexed into by the numbers used in the above animations
;
; Format of each mappings file:
; File is divided in 3 segments, with the same structure:
; Segment structure:
; 4-byte unsigned length of segment (not counting the 4 bytes used for length);
; the first 2 bytes of each length is ignored, and only the last 2 bytes are
; actually used.
; Rest of the segment is mappings data, as follows:
; 1st segment:
; Mappings data is a bitstream indicating whether to draw a single tile at
; a time using the uncompressed mappings (see 2nd segment) or a sequence of
; tiles using the RLE mappings (see 3rd segment).
; 2nd segment:
; Mappings data is a bitstream: the first bit in each cycle determines how
; many bits from the stream are to be used as an index to the uncompressed
; pattern name list SSPNT_UncLUT: if the first bit is set, 10 bits form an
; index into SSPNT_UncLUT_Part2, otherwise 6 bits are used as an index into
; SSPNT_UncLUT.
; These tiles are drawn in palette line 3.
; 3nd segment:
; Mappings data is a bitstream: the first bit in each cycle determines how
; many bits from the stream are to be used as an index to the RLE-compressed
; pattern name list SSPNT_RLELUT: if the first bit is set, 7 bits form an
; index into SSPNT_RLELUT_Part2, otherwise 6 bits are used as an index into
; SSPNT_RLELUT.
; These tiles are drawn in palette line 3, with the high priority bit set.
; off_643E:
Map_SpecialStageTrack:
dc.l MapSpec_Rise1 ; 0
dc.l MapSpec_Rise2 ; 1
dc.l MapSpec_Rise3 ; 2
dc.l MapSpec_Rise4 ; 3
dc.l MapSpec_Rise5 ; 4
dc.l MapSpec_Rise6 ; 5
dc.l MapSpec_Rise7 ; 6
dc.l MapSpec_Rise8 ; 7
dc.l MapSpec_Rise9 ; 8
dc.l MapSpec_Rise10 ; 9
dc.l MapSpec_Rise11 ; $A
dc.l MapSpec_Rise12 ; $B
dc.l MapSpec_Rise13 ; $C
dc.l MapSpec_Rise14 ; $D ; This may flip the special stage's horizontal orientation
dc.l MapSpec_Rise15 ; $E
dc.l MapSpec_Rise16 ; $F
dc.l MapSpec_Rise17 ; $10
dc.l MapSpec_Straight1 ; $11
dc.l MapSpec_Straight2 ; $12 ; This may flip the special stage's horizontal orientation
dc.l MapSpec_Straight3 ; $13
dc.l MapSpec_Straight4 ; $14
dc.l MapSpec_Drop1 ; $15
dc.l MapSpec_Drop2 ; $16
dc.l MapSpec_Drop3 ; $17
dc.l MapSpec_Drop4 ; $18
dc.l MapSpec_Drop5 ; $19
dc.l MapSpec_Drop6 ; $1A ; This may flip the special stage's horizontal orientation
dc.l MapSpec_Drop7 ; $1B
dc.l MapSpec_Drop8 ; $1C
dc.l MapSpec_Drop9 ; $1D
dc.l MapSpec_Drop10 ; $1E
dc.l MapSpec_Drop11 ; $1F
dc.l MapSpec_Drop12 ; $20
dc.l MapSpec_Drop13 ; $21
dc.l MapSpec_Drop14 ; $22
dc.l MapSpec_Drop15 ; $23
dc.l MapSpec_Drop16 ; $24
dc.l MapSpec_Drop17 ; $25
dc.l MapSpec_Turning1 ; $26
dc.l MapSpec_Turning2 ; $27
dc.l MapSpec_Turning3 ; $28
dc.l MapSpec_Turning4 ; $29
dc.l MapSpec_Turning5 ; $2A
dc.l MapSpec_Turning6 ; $2B
dc.l MapSpec_Unturn1 ; $2C
dc.l MapSpec_Unturn2 ; $2D
dc.l MapSpec_Unturn3 ; $2E
dc.l MapSpec_Unturn4 ; $2F
dc.l MapSpec_Unturn5 ; $30
dc.l MapSpec_Turn1 ; $31
dc.l MapSpec_Turn2 ; $32
dc.l MapSpec_Turn3 ; $33
dc.l MapSpec_Turn4 ; $34
dc.l MapSpec_Turn5 ; $35
dc.l MapSpec_Turn6 ; $36
dc.l MapSpec_Turn7 ; $37
; These are pattern names. They get sent to either the pattern name table
; buffer or one region of one of the plane A name tables in the special stage.
; They are indexed by the second segment of the mappings in Map_SpecialStageTrack, above.
;word_651E
SSPNT_UncLUT:
dc.w make_block_tile($0001,0,0,0,1), make_block_tile($0007,0,0,0,1), make_block_tile($002C,0,0,0,1), make_block_tile($000B,0,0,0,1) ; $00
dc.w make_block_tile($0024,0,0,0,1), make_block_tile($0024,1,0,0,1), make_block_tile($0039,0,0,0,1), make_block_tile($002B,1,0,0,1) ; $04
dc.w make_block_tile($005D,0,0,0,1), make_block_tile($005D,1,0,0,1), make_block_tile($002B,0,0,0,1), make_block_tile($004A,0,0,0,1) ; $08
dc.w make_block_tile($0049,0,0,0,1), make_block_tile($0037,0,0,0,1), make_block_tile($0049,1,0,0,1), make_block_tile($0045,0,0,0,1) ; $0C
dc.w make_block_tile($0045,1,0,0,1), make_block_tile($003A,1,0,0,1), make_block_tile($0048,0,0,0,1), make_block_tile($0050,1,0,0,1) ; $10
dc.w make_block_tile($0036,0,0,0,1), make_block_tile($0037,1,0,0,1), make_block_tile($003A,0,0,0,1), make_block_tile($0050,0,0,0,1) ; $14
dc.w make_block_tile($0042,1,0,0,1), make_block_tile($0042,0,0,0,1), make_block_tile($0015,1,0,0,1), make_block_tile($001D,0,0,0,1) ; $18
dc.w make_block_tile($004B,0,0,0,1), make_block_tile($0017,1,0,0,1), make_block_tile($0048,1,0,0,1), make_block_tile($0036,1,0,0,1) ; $1C
dc.w make_block_tile($0038,0,0,0,1), make_block_tile($004B,1,0,0,1), make_block_tile($0015,0,0,0,1), make_block_tile($0021,0,0,0,1) ; $20
dc.w make_block_tile($0017,0,0,0,1), make_block_tile($0033,0,0,0,1), make_block_tile($001A,0,0,0,1), make_block_tile($002A,0,0,0,1) ; $24
dc.w make_block_tile($005E,0,0,0,1), make_block_tile($0028,0,0,0,1), make_block_tile($0030,0,0,0,1), make_block_tile($0021,1,0,0,1) ; $28
dc.w make_block_tile($0038,1,0,0,1), make_block_tile($001A,1,0,0,1), make_block_tile($0025,0,0,0,1), make_block_tile($005E,1,0,0,1) ; $2C
dc.w make_block_tile($0025,1,0,0,1), make_block_tile($0033,1,0,0,1), make_block_tile($0003,0,0,0,1), make_block_tile($0014,1,0,0,1) ; $30
dc.w make_block_tile($0014,0,0,0,1), make_block_tile($0004,0,0,0,1), make_block_tile($004E,0,0,0,1), make_block_tile($0003,1,0,0,1) ; $34
dc.w make_block_tile($000C,0,0,0,1), make_block_tile($002A,1,0,0,1), make_block_tile($0002,0,0,0,1), make_block_tile($0051,0,0,0,1) ; $38
dc.w make_block_tile($0040,0,0,0,1), make_block_tile($003D,0,0,0,1), make_block_tile($0019,0,0,0,1), make_block_tile($0052,0,0,0,1) ; $3C
;word_659E
SSPNT_UncLUT_Part2:
dc.w make_block_tile($0009,0,0,0,1), make_block_tile($005A,0,0,0,1), make_block_tile($0030,1,0,0,1), make_block_tile($004E,1,0,0,1) ; $40
dc.w make_block_tile($0052,1,0,0,1), make_block_tile($0051,1,0,0,1), make_block_tile($0009,1,0,0,1), make_block_tile($0040,1,0,0,1) ; $44
dc.w make_block_tile($002F,0,0,0,1), make_block_tile($005A,1,0,0,1), make_block_tile($0018,1,0,0,1), make_block_tile($0034,0,0,0,1) ; $48
dc.w make_block_tile($0019,1,0,0,1), make_block_tile($002F,1,0,0,1), make_block_tile($003D,1,0,0,1), make_block_tile($003E,0,0,0,1) ; $4C
dc.w make_block_tile($0018,0,0,0,1), make_block_tile($000C,1,0,0,1), make_block_tile($0012,0,0,0,1), make_block_tile($0004,1,0,0,1) ; $50
dc.w make_block_tile($0026,0,0,0,1), make_block_tile($0034,1,0,0,1), make_block_tile($0005,1,0,0,1), make_block_tile($003B,0,0,0,1) ; $54
dc.w make_block_tile($003E,1,0,0,1), make_block_tile($003B,1,0,0,1), make_block_tile($0000,0,0,0,1), make_block_tile($0002,1,0,0,1) ; $58
dc.w make_block_tile($0005,0,0,0,1), make_block_tile($000D,0,0,0,1), make_block_tile($0055,0,0,0,1), make_block_tile($00AF,0,0,0,1) ; $5C
dc.w make_block_tile($001C,0,0,0,1), make_block_tile($001B,0,0,0,1), make_block_tile($000D,1,0,0,1), make_block_tile($0016,0,0,0,1) ; $60
dc.w make_block_tile($0012,1,0,0,1), make_block_tile($001F,0,0,0,1), make_block_tile($0032,1,0,0,1), make_block_tile($0013,0,0,0,1) ; $64
dc.w make_block_tile($0092,0,0,0,1), make_block_tile($0026,1,0,0,1), make_block_tile($0010,0,0,0,1), make_block_tile($004D,0,0,0,1) ; $68
dc.w make_block_tile($0047,0,0,0,1), make_block_tile($0092,1,0,0,1), make_block_tile($0000,1,0,0,1), make_block_tile($0062,0,0,0,1) ; $6C
dc.w make_block_tile($0066,0,0,0,1), make_block_tile($0090,0,0,0,1), make_block_tile($0008,0,0,0,1), make_block_tile($007C,1,0,0,1) ; $70
dc.w make_block_tile($0067,1,0,0,1), make_block_tile($00F7,1,0,0,1), make_block_tile($000E,0,0,0,1), make_block_tile($0060,0,0,0,1) ; $74
dc.w make_block_tile($0032,0,0,0,1), make_block_tile($0094,0,0,0,1), make_block_tile($001C,1,0,0,1), make_block_tile($0105,1,0,0,1) ; $78
dc.w make_block_tile($00B0,1,0,0,1), make_block_tile($0059,0,0,0,1), make_block_tile($000F,0,0,0,1), make_block_tile($0067,0,0,0,1) ; $7C
dc.w make_block_tile($0068,0,0,0,1), make_block_tile($0094,1,0,0,1), make_block_tile($007C,0,0,0,1), make_block_tile($00B0,0,0,0,1) ; $80
dc.w make_block_tile($00B1,0,0,0,1), make_block_tile($0006,0,0,0,1), make_block_tile($0041,1,0,0,1), make_block_tile($0087,0,0,0,1) ; $84
dc.w make_block_tile($0093,0,0,0,1), make_block_tile($00CC,0,0,0,1), make_block_tile($001F,1,0,0,1), make_block_tile($0068,1,0,0,1) ; $88
dc.w make_block_tile($0041,0,0,0,1), make_block_tile($008F,0,0,0,1), make_block_tile($0090,1,0,0,1), make_block_tile($00C2,0,0,0,1) ; $8C
dc.w make_block_tile($0013,1,0,0,1), make_block_tile($00C2,1,0,0,1), make_block_tile($005C,0,0,0,1), make_block_tile($0064,0,0,0,1) ; $90
dc.w make_block_tile($00D8,0,0,0,1), make_block_tile($001B,1,0,0,1), make_block_tile($00CC,1,0,0,1), make_block_tile($0011,1,0,0,1) ; $94
dc.w make_block_tile($0055,1,0,0,1), make_block_tile($00E2,1,0,0,1), make_block_tile($00F3,1,0,0,1), make_block_tile($0044,0,0,0,1) ; $98
dc.w make_block_tile($00D8,1,0,0,1), make_block_tile($0085,0,0,0,1), make_block_tile($00A1,0,0,0,1), make_block_tile($00C1,0,0,0,1) ; $9C
dc.w make_block_tile($0119,0,0,0,1), make_block_tile($0089,1,0,0,1), make_block_tile($000A,1,0,0,1), make_block_tile($0022,1,0,0,1) ; $A0
dc.w make_block_tile($003F,0,0,0,1), make_block_tile($005B,0,0,0,1), make_block_tile($007F,0,0,0,1), make_block_tile($0086,1,0,0,1) ; $A4
dc.w make_block_tile($0008,1,0,0,1), make_block_tile($0080,0,0,0,1), make_block_tile($0066,1,0,0,1), make_block_tile($00E0,1,0,0,1) ; $A8
dc.w make_block_tile($00C1,1,0,0,1), make_block_tile($0020,0,0,0,1), make_block_tile($0022,0,0,0,1), make_block_tile($0054,0,0,0,1) ; $AC
dc.w make_block_tile($00D2,0,0,0,1), make_block_tile($0059,1,0,0,1), make_block_tile($00B1,1,0,0,1), make_block_tile($0060,1,0,0,1) ; $B0
dc.w make_block_tile($0119,1,0,0,1), make_block_tile($00A4,1,0,0,1), make_block_tile($008F,1,0,0,1), make_block_tile($000A,0,0,0,1) ; $B4
dc.w make_block_tile($0061,0,0,0,1), make_block_tile($0075,0,0,0,1), make_block_tile($0095,0,0,0,1), make_block_tile($00B6,0,0,0,1) ; $B8
dc.w make_block_tile($00E0,0,0,0,1), make_block_tile($0010,1,0,0,1), make_block_tile($0098,1,0,0,1), make_block_tile($005B,1,0,0,1) ; $BC
dc.w make_block_tile($00D2,1,0,0,1), make_block_tile($0016,1,0,0,1), make_block_tile($0053,0,0,0,1), make_block_tile($0091,0,0,0,1) ; $C0
dc.w make_block_tile($0096,0,0,0,1), make_block_tile($00A4,0,0,0,1), make_block_tile($00DD,0,0,0,1), make_block_tile($00E6,0,0,0,1) ; $C4
dc.w make_block_tile($007A,1,0,0,1), make_block_tile($004D,1,0,0,1), make_block_tile($00E6,1,0,0,1), make_block_tile($0011,0,0,0,1) ; $C8
dc.w make_block_tile($0057,0,0,0,1), make_block_tile($007A,0,0,0,1), make_block_tile($0086,0,0,0,1), make_block_tile($009E,0,0,0,1) ; $CC
dc.w make_block_tile($00DA,0,0,0,1), make_block_tile($0058,0,0,0,1), make_block_tile($00DC,0,0,0,1), make_block_tile($00E3,0,0,0,1) ; $D0
dc.w make_block_tile($0063,1,0,0,1), make_block_tile($003C,0,0,0,1), make_block_tile($0056,0,0,0,1), make_block_tile($0069,0,0,0,1) ; $D4
dc.w make_block_tile($007E,0,0,0,1), make_block_tile($00AE,0,0,0,1), make_block_tile($00B5,0,0,0,1), make_block_tile($00B8,0,0,0,1) ; $D8
dc.w make_block_tile($00CD,0,0,0,1), make_block_tile($00FB,0,0,0,1), make_block_tile($00FF,0,0,0,1), make_block_tile($005C,1,0,0,1) ; $DC
dc.w make_block_tile($00CD,1,0,0,1), make_block_tile($0074,1,0,0,1), make_block_tile($00EA,1,0,0,1), make_block_tile($00FF,1,0,0,1) ; $E0
dc.w make_block_tile($00B5,1,0,0,1), make_block_tile($0043,0,0,0,1), make_block_tile($006C,0,0,0,1), make_block_tile($0074,0,0,0,1) ; $E4
dc.w make_block_tile($0077,0,0,0,1), make_block_tile($0089,0,0,0,1), make_block_tile($0097,0,0,0,1), make_block_tile($009F,0,0,0,1) ; $E8
dc.w make_block_tile($00A0,0,0,0,1), make_block_tile($0113,0,0,0,1), make_block_tile($011B,0,0,0,1), make_block_tile($0078,1,0,0,1) ; $EC
dc.w make_block_tile($000F,1,0,0,1), make_block_tile($00E1,1,0,0,1), make_block_tile($00FB,1,0,0,1), make_block_tile($0128,1,0,0,1) ; $F0
dc.w make_block_tile($0063,0,0,0,1), make_block_tile($0084,0,0,0,1), make_block_tile($008D,0,0,0,1), make_block_tile($00CB,0,0,0,1) ; $F4
dc.w make_block_tile($00D7,0,0,0,1), make_block_tile($00E9,0,0,0,1), make_block_tile($0128,0,0,0,1), make_block_tile($0138,0,0,0,1) ; $F8
dc.w make_block_tile($00AE,1,0,0,1), make_block_tile($00EC,1,0,0,1), make_block_tile($0031,0,0,0,1), make_block_tile($004C,0,0,0,1) ; $FC
dc.w make_block_tile($00E2,0,0,0,1), make_block_tile($00EA,0,0,0,1), make_block_tile($0064,1,0,0,1), make_block_tile($0029,0,0,0,1) ; $100
dc.w make_block_tile($002D,0,0,0,1), make_block_tile($006D,0,0,0,1), make_block_tile($0078,0,0,0,1), make_block_tile($0088,0,0,0,1) ; $104
dc.w make_block_tile($00B4,0,0,0,1), make_block_tile($00BE,0,0,0,1), make_block_tile($00CF,0,0,0,1), make_block_tile($00E1,0,0,0,1) ; $108
dc.w make_block_tile($00E4,0,0,0,1), make_block_tile($0054,1,0,0,1), make_block_tile($00D6,1,0,0,1), make_block_tile($00D7,1,0,0,1) ; $10C
dc.w make_block_tile($0061,1,0,0,1), make_block_tile($012B,1,0,0,1), make_block_tile($0047,1,0,0,1), make_block_tile($0035,0,0,0,1) ; $110
dc.w make_block_tile($006A,0,0,0,1), make_block_tile($0072,0,0,0,1), make_block_tile($0073,0,0,0,1), make_block_tile($0098,0,0,0,1) ; $114
dc.w make_block_tile($00D5,0,0,0,1), make_block_tile($00D6,0,0,0,1), make_block_tile($0116,0,0,0,1), make_block_tile($011E,0,0,0,1) ; $118
dc.w make_block_tile($0126,0,0,0,1), make_block_tile($0127,0,0,0,1), make_block_tile($012F,0,0,0,1), make_block_tile($015D,0,0,0,1) ; $11C
dc.w make_block_tile($0069,1,0,0,1), make_block_tile($0088,1,0,0,1), make_block_tile($0075,1,0,0,1), make_block_tile($0097,1,0,0,1) ; $120
dc.w make_block_tile($00B4,1,0,0,1), make_block_tile($00D1,1,0,0,1), make_block_tile($00D4,1,0,0,1), make_block_tile($00D5,1,0,0,1) ; $124
dc.w make_block_tile($00CB,1,0,0,1), make_block_tile($00E4,1,0,0,1), make_block_tile($0091,1,0,0,1), make_block_tile($0062,1,0,0,1) ; $128
dc.w make_block_tile($0006,1,0,0,1), make_block_tile($00B8,1,0,0,1), make_block_tile($0065,0,0,0,1), make_block_tile($006E,0,0,0,1) ; $12C
dc.w make_block_tile($0071,0,0,0,1), make_block_tile($007D,0,0,0,1), make_block_tile($00D1,0,0,0,1), make_block_tile($00E7,0,0,0,1) ; $130
dc.w make_block_tile($00F9,0,0,0,1), make_block_tile($0108,0,0,0,1), make_block_tile($012E,0,0,0,1), make_block_tile($014B,0,0,0,1) ; $134
dc.w make_block_tile($0081,1,0,0,1), make_block_tile($0085,1,0,0,1), make_block_tile($0077,1,0,0,1), make_block_tile($007E,1,0,0,1) ; $138
dc.w make_block_tile($0095,1,0,0,1), make_block_tile($00DF,1,0,0,1), make_block_tile($0087,1,0,0,1), make_block_tile($006C,1,0,0,1) ; $13C
dc.w make_block_tile($00F5,1,0,0,1), make_block_tile($0108,1,0,0,1), make_block_tile($0079,1,0,0,1), make_block_tile($006D,1,0,0,1) ; $140
dc.w make_block_tile($012A,1,0,0,1), make_block_tile($00AA,1,0,0,1), make_block_tile($001E,0,0,0,1), make_block_tile($0027,0,0,0,1) ; $144
dc.w make_block_tile($0046,0,0,0,1), make_block_tile($005F,0,0,0,1), make_block_tile($0070,0,0,0,1), make_block_tile($0079,0,0,0,1) ; $148
dc.w make_block_tile($009A,0,0,0,1), make_block_tile($00AA,0,0,0,1), make_block_tile($00C3,0,0,0,1), make_block_tile($00D3,0,0,0,1) ; $14C
dc.w make_block_tile($00D4,0,0,0,1), make_block_tile($00DE,0,0,0,1), make_block_tile($00DF,0,0,0,1), make_block_tile($00F8,0,0,0,1) ; $150
dc.w make_block_tile($0100,0,0,0,1), make_block_tile($0101,0,0,0,1), make_block_tile($012B,0,0,0,1), make_block_tile($0133,0,0,0,1) ; $154
dc.w make_block_tile($0136,0,0,0,1), make_block_tile($0143,0,0,0,1), make_block_tile($0151,0,0,0,1), make_block_tile($002E,1,0,0,1) ; $158
dc.w make_block_tile($009E,1,0,0,1), make_block_tile($0099,1,0,0,1), make_block_tile($00D3,1,0,0,1), make_block_tile($00DD,1,0,0,1) ; $15C
dc.w make_block_tile($00DE,1,0,0,1), make_block_tile($00E9,1,0,0,1), make_block_tile($00EF,1,0,0,1), make_block_tile($00F0,1,0,0,1) ; $160
dc.w make_block_tile($00F8,1,0,0,1), make_block_tile($0127,1,0,0,1), make_block_tile($00BE,1,0,0,1), make_block_tile($0096,1,0,0,1) ; $164
dc.w make_block_tile($004F,0,0,0,1), make_block_tile($006F,0,0,0,1), make_block_tile($0081,0,0,0,1), make_block_tile($008B,0,0,0,1) ; $168
dc.w make_block_tile($008E,0,0,0,1), make_block_tile($009C,0,0,0,1), make_block_tile($00A3,0,0,0,1), make_block_tile($00B3,0,0,0,1) ; $16C
dc.w make_block_tile($00C0,0,0,0,1), make_block_tile($00CE,0,0,0,1), make_block_tile($00F0,0,0,0,1), make_block_tile($00F1,0,0,0,1) ; $170
dc.w make_block_tile($00F5,0,0,0,1), make_block_tile($00F7,0,0,0,1), make_block_tile($0102,0,0,0,1), make_block_tile($0104,0,0,0,1) ; $174
dc.w make_block_tile($0105,0,0,0,1), make_block_tile($0109,0,0,0,1), make_block_tile($010C,0,0,0,1), make_block_tile($0114,0,0,0,1) ; $178
dc.w make_block_tile($0118,0,0,0,1), make_block_tile($0120,0,0,0,1), make_block_tile($0124,0,0,0,1), make_block_tile($0125,0,0,0,1) ; $17C
dc.w make_block_tile($012A,0,0,0,1), make_block_tile($0130,0,0,0,1), make_block_tile($0132,0,0,0,1), make_block_tile($0137,0,0,0,1) ; $180
dc.w make_block_tile($0159,0,0,0,1), make_block_tile($0165,0,0,0,1), make_block_tile($003F,1,0,0,1), make_block_tile($006B,1,0,0,1) ; $184
dc.w make_block_tile($0080,1,0,0,1), make_block_tile($0053,1,0,0,1), make_block_tile($00C6,1,0,0,1), make_block_tile($00CF,1,0,0,1) ; $188
dc.w make_block_tile($00D9,1,0,0,1), make_block_tile($00DC,1,0,0,1), make_block_tile($0056,1,0,0,1), make_block_tile($00B6,1,0,0,1) ; $18C
dc.w make_block_tile($00F9,1,0,0,1), make_block_tile($0102,1,0,0,1), make_block_tile($0104,1,0,0,1), make_block_tile($0115,1,0,0,1) ; $190
dc.w make_block_tile($006A,1,0,0,1), make_block_tile($0113,1,0,0,1), make_block_tile($0072,1,0,0,1), make_block_tile($0035,1,0,0,1) ; $194
dc.w make_block_tile($0138,1,0,0,1), make_block_tile($015D,1,0,0,1), make_block_tile($0143,1,0,0,1), make_block_tile($0023,0,0,0,1) ; $198
dc.w make_block_tile($0076,0,0,0,1), make_block_tile($007B,0,0,0,1), make_block_tile($008A,0,0,0,1), make_block_tile($009D,0,0,0,1) ; $19C
dc.w make_block_tile($00A6,0,0,0,1), make_block_tile($00A8,0,0,0,1), make_block_tile($00AC,0,0,0,1), make_block_tile($00B2,0,0,0,1) ; $1A0
dc.w make_block_tile($00B7,0,0,0,1), make_block_tile($00BB,0,0,0,1), make_block_tile($00BC,0,0,0,1), make_block_tile($00BD,0,0,0,1) ; $1A4
dc.w make_block_tile($00C6,0,0,0,1), make_block_tile($00E5,0,0,0,1), make_block_tile($00E8,0,0,0,1), make_block_tile($00EE,0,0,0,1) ; $1A8
dc.w make_block_tile($00F4,0,0,0,1), make_block_tile($010A,0,0,0,1), make_block_tile($010D,0,0,0,1), make_block_tile($0111,0,0,0,1) ; $1AC
dc.w make_block_tile($0115,0,0,0,1), make_block_tile($011A,0,0,0,1), make_block_tile($011F,0,0,0,1), make_block_tile($0122,0,0,0,1) ; $1B0
dc.w make_block_tile($0123,0,0,0,1), make_block_tile($0139,0,0,0,1), make_block_tile($013A,0,0,0,1), make_block_tile($013C,0,0,0,1) ; $1B4
dc.w make_block_tile($0142,0,0,0,1), make_block_tile($0144,0,0,0,1), make_block_tile($0147,0,0,0,1), make_block_tile($0148,0,0,0,1) ; $1B8
dc.w make_block_tile($015E,0,0,0,1), make_block_tile($015F,0,0,0,1), make_block_tile($0163,0,0,0,1), make_block_tile($0168,0,0,0,1) ; $1BC
dc.w make_block_tile($016A,0,0,0,1), make_block_tile($016C,0,0,0,1), make_block_tile($0170,0,0,0,1), make_block_tile($00E5,1,0,0,1) ; $1C0
dc.w make_block_tile($00CE,1,0,0,1), make_block_tile($00EE,1,0,0,1), make_block_tile($00F1,1,0,0,1), make_block_tile($0084,1,0,0,1) ; $1C4
dc.w make_block_tile($00FD,1,0,0,1), make_block_tile($0100,1,0,0,1), make_block_tile($00B9,1,0,0,1), make_block_tile($0117,1,0,0,1) ; $1C8
dc.w make_block_tile($0071,1,0,0,1), make_block_tile($0109,1,0,0,1), make_block_tile($010D,1,0,0,1), make_block_tile($0065,1,0,0,1) ; $1CC
dc.w make_block_tile($0125,1,0,0,1), make_block_tile($0122,1,0,0,1), make_block_tile($0031,1,0,0,1), make_block_tile($003C,1,0,0,1) ; $1D0
dc.w make_block_tile($010F,1,0,0,1), make_block_tile($00C5,1,0,0,1), make_block_tile($0133,1,0,0,1), make_block_tile($0137,1,0,0,1) ; $1D4
dc.w make_block_tile($011F,1,0,0,1), make_block_tile($002E,0,0,0,1), make_block_tile($006B,0,0,0,1), make_block_tile($0082,0,0,0,1) ; $1D8
dc.w make_block_tile($0083,0,0,0,1), make_block_tile($008C,0,0,0,1), make_block_tile($0099,0,0,0,1), make_block_tile($009B,0,0,0,1) ; $1DC
dc.w make_block_tile($00A2,0,0,0,1), make_block_tile($00A5,0,0,0,1), make_block_tile($00A7,0,0,0,1), make_block_tile($00A9,0,0,0,1) ; $1E0
dc.w make_block_tile($00AB,0,0,0,1), make_block_tile($00AD,0,0,0,1), make_block_tile($00B9,0,0,0,1), make_block_tile($00BA,0,0,0,1) ; $1E4
dc.w make_block_tile($00BF,0,0,0,1), make_block_tile($00C4,0,0,0,1), make_block_tile($00C5,0,0,0,1), make_block_tile($00C7,0,0,0,1) ; $1E8
dc.w make_block_tile($00C8,0,0,0,1), make_block_tile($00C9,0,0,0,1), make_block_tile($00CA,0,0,0,1), make_block_tile($00D0,0,0,0,1) ; $1EC
dc.w make_block_tile($00D9,0,0,0,1), make_block_tile($00DB,0,0,0,1), make_block_tile($00EB,0,0,0,1), make_block_tile($00EC,0,0,0,1) ; $1F0
dc.w make_block_tile($00ED,0,0,0,1), make_block_tile($00EF,0,0,0,1), make_block_tile($00F2,0,0,0,1), make_block_tile($00F3,0,0,0,1) ; $1F4
dc.w make_block_tile($00F6,0,0,0,1), make_block_tile($00FA,0,0,0,1), make_block_tile($00FC,0,0,0,1), make_block_tile($00FD,0,0,0,1) ; $1F8
dc.w make_block_tile($00FE,0,0,0,1), make_block_tile($0103,0,0,0,1), make_block_tile($0106,0,0,0,1), make_block_tile($0107,0,0,0,1) ; $2FC
dc.w make_block_tile($010B,0,0,0,1), make_block_tile($010E,0,0,0,1), make_block_tile($010F,0,0,0,1), make_block_tile($0110,0,0,0,1) ; $200
dc.w make_block_tile($0112,0,0,0,1), make_block_tile($0117,0,0,0,1), make_block_tile($011C,0,0,0,1), make_block_tile($011D,0,0,0,1) ; $204
dc.w make_block_tile($0121,0,0,0,1), make_block_tile($0129,0,0,0,1), make_block_tile($012C,0,0,0,1), make_block_tile($012D,0,0,0,1) ; $208
dc.w make_block_tile($0131,0,0,0,1), make_block_tile($0134,0,0,0,1), make_block_tile($0135,0,0,0,1), make_block_tile($013B,0,0,0,1) ; $20C
dc.w make_block_tile($013D,0,0,0,1), make_block_tile($013E,0,0,0,1), make_block_tile($013F,0,0,0,1), make_block_tile($0140,0,0,0,1) ; $210
dc.w make_block_tile($0141,0,0,0,1), make_block_tile($0145,0,0,0,1), make_block_tile($0146,0,0,0,1), make_block_tile($0149,0,0,0,1) ; $214
dc.w make_block_tile($014A,0,0,0,1), make_block_tile($014C,0,0,0,1), make_block_tile($014D,0,0,0,1), make_block_tile($014E,0,0,0,1) ; $218
dc.w make_block_tile($014F,0,0,0,1), make_block_tile($0150,0,0,0,1), make_block_tile($0152,0,0,0,1), make_block_tile($0153,0,0,0,1) ; $21C
dc.w make_block_tile($0154,0,0,0,1), make_block_tile($0155,0,0,0,1), make_block_tile($0156,0,0,0,1), make_block_tile($0157,0,0,0,1) ; $220
dc.w make_block_tile($0158,0,0,0,1), make_block_tile($015A,0,0,0,1), make_block_tile($015B,0,0,0,1), make_block_tile($015C,0,0,0,1) ; $224
dc.w make_block_tile($0160,0,0,0,1), make_block_tile($0161,0,0,0,1), make_block_tile($0162,0,0,0,1), make_block_tile($0164,0,0,0,1) ; $228
dc.w make_block_tile($0166,0,0,0,1), make_block_tile($0167,0,0,0,1), make_block_tile($0169,0,0,0,1), make_block_tile($016B,0,0,0,1) ; $22C
dc.w make_block_tile($016D,0,0,0,1), make_block_tile($016E,0,0,0,1), make_block_tile($016F,0,0,0,1), make_block_tile($0171,0,0,0,1) ; $230
dc.w make_block_tile($0172,0,0,0,1), make_block_tile($0173,0,0,0,1), make_block_tile($006E,1,0,0,1), make_block_tile($007D,1,0,0,1) ; $234
dc.w make_block_tile($00C3,1,0,0,1), make_block_tile($00DB,1,0,0,1), make_block_tile($00E7,1,0,0,1), make_block_tile($00E8,1,0,0,1) ; $238
dc.w make_block_tile($00EB,1,0,0,1), make_block_tile($00ED,1,0,0,1), make_block_tile($00F2,1,0,0,1), make_block_tile($00F6,1,0,0,1) ; $23C
dc.w make_block_tile($00FA,1,0,0,1), make_block_tile($00FC,1,0,0,1), make_block_tile($00FE,1,0,0,1), make_block_tile($002D,1,0,0,1) ; $240
dc.w make_block_tile($0103,1,0,0,1), make_block_tile($0106,1,0,0,1), make_block_tile($0107,1,0,0,1), make_block_tile($010B,1,0,0,1) ; $244
dc.w make_block_tile($0073,1,0,0,1), make_block_tile($009A,1,0,0,1), make_block_tile($0129,1,0,0,1), make_block_tile($012C,1,0,0,1) ; $248
dc.w make_block_tile($012D,1,0,0,1), make_block_tile($0111,1,0,0,1), make_block_tile($013C,1,0,0,1), make_block_tile($0120,1,0,0,1) ; $24C
dc.w make_block_tile($0146,1,0,0,1), make_block_tile($00A9,1,0,0,1), make_block_tile($009C,1,0,0,1), make_block_tile($0116,1,0,0,1) ; $250
dc.w make_block_tile($014F,1,0,0,1), make_block_tile($014C,1,0,0,1), make_block_tile($006F,1,0,0,1), make_block_tile($0158,1,0,0,1) ; $254
dc.w make_block_tile($0156,1,0,0,1), make_block_tile($0159,1,0,0,1), make_block_tile($015A,1,0,0,1), make_block_tile($0161,1,0,0,1) ; $258
dc.w make_block_tile($007B,1,0,0,1), make_block_tile($0166,1,0,0,1), make_block_tile($011C,1,0,0,1), make_block_tile($0118,1,0,0,1) ; $25C
dc.w make_block_tile($00A0,1,0,0,1), make_block_tile($00A3,1,0,0,1), make_block_tile($0167,1,0,0,1), make_block_tile($00A1,1,0,0,1) ; $260
; These are run-length encoded pattern names. They get sent to either the
; pattern name table buffer or one region of one of the plane A name tables
; in the special stage.
; They are indexed by the third segment of the mappings in Map_SpecialStageTrack, above.
; Format: PNT,count
;word_69E6
SSPNT_RLELUT:
dc.w make_block_tile($0007,0,0,0,0),$0001, make_block_tile($0001,0,0,0,0),$0001 ; $00
dc.w make_block_tile($004A,0,0,0,0),$0001, make_block_tile($0039,0,0,0,0),$0003 ; $02
dc.w make_block_tile($0001,0,0,0,0),$0005, make_block_tile($0028,0,0,0,0),$0007 ; $04
dc.w make_block_tile($002C,0,0,0,0),$0001, make_block_tile($0001,0,0,0,0),$0002 ; $06
dc.w make_block_tile($0028,0,0,0,0),$0005, make_block_tile($0039,0,0,0,0),$0001 ; $08
dc.w make_block_tile($0028,0,0,0,0),$0009, make_block_tile($0001,0,0,0,0),$0004 ; $0A
dc.w make_block_tile($0028,0,0,0,0),$0006, make_block_tile($0028,0,0,0,0),$0003 ; $0C
dc.w make_block_tile($004A,0,0,0,0),$0002, make_block_tile($0001,0,0,0,0),$0003 ; $0E
dc.w make_block_tile($0028,0,0,0,0),$0004, make_block_tile($0039,0,0,0,0),$0002 ; $10
dc.w make_block_tile($0039,0,0,0,0),$0004, make_block_tile($0001,0,0,0,0),$0006 ; $12
dc.w make_block_tile($0007,0,0,0,0),$0002, make_block_tile($002C,0,0,0,0),$0002 ; $14
dc.w make_block_tile($0028,0,0,0,0),$0001, make_block_tile($001D,0,0,0,0),$0001 ; $16
dc.w make_block_tile($0028,0,0,0,0),$0008, make_block_tile($0028,0,0,0,0),$0002 ; $18
dc.w make_block_tile($0007,0,0,0,0),$0003, make_block_tile($0001,0,0,0,0),$0007 ; $1A
dc.w make_block_tile($0028,0,0,0,0),$000B, make_block_tile($0039,0,0,0,0),$0005 ; $1C
dc.w make_block_tile($001D,0,0,0,0),$0003, make_block_tile($001D,0,0,0,0),$0004 ; $1E
dc.w make_block_tile($001D,0,0,0,0),$0002, make_block_tile($001D,0,0,0,0),$0005 ; $20
dc.w make_block_tile($0028,0,0,0,0),$000D, make_block_tile($000B,0,0,0,0),$0001 ; $22
dc.w make_block_tile($0028,0,0,0,0),$000A, make_block_tile($0039,0,0,0,0),$0006 ; $24
dc.w make_block_tile($0039,0,0,0,0),$0007, make_block_tile($002C,0,0,0,0),$0003 ; $26
dc.w make_block_tile($001D,0,0,0,0),$0009, make_block_tile($004A,0,0,0,0),$0003 ; $28
dc.w make_block_tile($001D,0,0,0,0),$0007, make_block_tile($0028,0,0,0,0),$000F ; $2A
dc.w make_block_tile($001D,0,0,0,0),$000B, make_block_tile($001D,0,0,0,0),$0011 ; $2C
dc.w make_block_tile($001D,0,0,0,0),$000D, make_block_tile($001D,0,0,0,0),$0008 ; $2E
dc.w make_block_tile($0028,0,0,0,0),$0011, make_block_tile($001D,0,0,0,0),$0006 ; $30
dc.w make_block_tile($000B,0,0,0,0),$0002, make_block_tile($001D,0,0,0,0),$0015 ; $32
dc.w make_block_tile($0028,0,0,0,0),$000C, make_block_tile($001D,0,0,0,0),$000A ; $34
dc.w make_block_tile($0028,0,0,0,0),$000E, make_block_tile($0001,0,0,0,0),$0008 ; $36
dc.w make_block_tile($001D,0,0,0,0),$000F, make_block_tile($0028,0,0,0,0),$0010 ; $38
dc.w make_block_tile($0007,0,0,0,0),$0006, make_block_tile($001D,0,0,0,0),$0013 ; $3A
dc.w make_block_tile($004A,0,0,0,0),$0004, make_block_tile($001D,0,0,0,0),$0017 ; $3C
dc.w make_block_tile($0007,0,0,0,0),$0004, make_block_tile($000B,0,0,0,0),$0003 ; $3E
;word_6AE6
SSPNT_RLELUT_Part2:
dc.w make_block_tile($001D,0,0,0,0),$001B, make_block_tile($004A,0,0,0,0),$0006 ; $40
dc.w make_block_tile($001D,0,0,0,0),$001D, make_block_tile($004A,0,0,0,0),$0005 ; $42
dc.w make_block_tile($0001,0,0,0,0),$0009, make_block_tile($0007,0,0,0,0),$0005 ; $44
dc.w make_block_tile($001D,0,0,0,0),$001E, make_block_tile($001D,0,0,0,0),$0019 ; $46
dc.w make_block_tile($0001,0,0,0,0),$0011, make_block_tile($001D,0,0,0,0),$000C ; $48
dc.w make_block_tile($001D,0,0,0,0),$007F, make_block_tile($002C,0,0,0,0),$0004 ; $4A
dc.w make_block_tile($001D,0,0,0,0),$000E, make_block_tile($001D,0,0,0,0),$001C ; $4C
dc.w make_block_tile($004A,0,0,0,0),$000A, make_block_tile($001D,0,0,0,0),$001A ; $4E
dc.w make_block_tile($004A,0,0,0,0),$0007, make_block_tile($001D,0,0,0,0),$0018 ; $50
dc.w make_block_tile($000B,0,0,0,0),$0004, make_block_tile($001D,0,0,0,0),$0012 ; $52
dc.w make_block_tile($001D,0,0,0,0),$0010, make_block_tile($0001,0,0,0,0),$000F ; $54
dc.w make_block_tile($000B,0,0,0,0),$0005, make_block_tile($0001,0,0,0,0),$000D ; $56
dc.w make_block_tile($0001,0,0,0,0),$0013, make_block_tile($004A,0,0,0,0),$0009 ; $58
dc.w make_block_tile($004A,0,0,0,0),$000B, make_block_tile($004A,0,0,0,0),$000C ; $5A
dc.w make_block_tile($002C,0,0,0,0),$0005, make_block_tile($001D,0,0,0,0),$0014 ; $5C
dc.w make_block_tile($000B,0,0,0,0),$0007, make_block_tile($001D,0,0,0,0),$0016 ; $5E
dc.w make_block_tile($0001,0,0,0,0),$000C, make_block_tile($0001,0,0,0,0),$000E ; $60
dc.w make_block_tile($004A,0,0,0,0),$0008, make_block_tile($001D,0,0,0,0),$005F ; $62
dc.w make_block_tile($0001,0,0,0,0),$000A, make_block_tile($000B,0,0,0,0),$0006 ; $64
dc.w make_block_tile($000B,0,0,0,0),$0008, make_block_tile($000B,0,0,0,0),$000A ; $66
dc.w make_block_tile($0039,0,0,0,0),$0008, make_block_tile($000B,0,0,0,0),$0009 ; $68
dc.w make_block_tile($002C,0,0,0,0),$0006, make_block_tile($0001,0,0,0,0),$0010 ; $6A
dc.w make_block_tile($000B,0,0,0,0),$000C, make_block_tile($0001,0,0,0,0),$000B ; $6C
dc.w make_block_tile($0001,0,0,0,0),$0012, make_block_tile($0007,0,0,0,0),$0007 ; $6E
dc.w make_block_tile($001D,0,0,0,0),$001F, make_block_tile($0028,0,0,0,0),$0012 ; $70
dc.w make_block_tile($000B,0,0,0,0),$000B, make_block_tile($002C,0,0,0,0),$0007 ; $72
dc.w make_block_tile($002C,0,0,0,0),$000B, make_block_tile($001D,0,0,0,0),$0023 ; $74
dc.w make_block_tile($0001,0,0,0,0),$0015, make_block_tile($002C,0,0,0,0),$0008 ; $76
dc.w make_block_tile($001D,0,0,0,0),$002E, make_block_tile($001D,0,0,0,0),$003F ; $78
dc.w make_block_tile($0001,0,0,0,0),$0014, make_block_tile($000B,0,0,0,0),$000D ; $7A
dc.w make_block_tile($002C,0,0,0,0),$0009, make_block_tile($002C,0,0,0,0),$000A ; $7C
dc.w make_block_tile($001D,0,0,0,0),$0025, make_block_tile($001D,0,0,0,0),$0055 ; $7E
dc.w make_block_tile($001D,0,0,0,0),$0071, make_block_tile($001D,0,0,0,0),$007C ; $80
dc.w make_block_tile($004A,0,0,0,0),$000D, make_block_tile($002C,0,0,0,0),$000C ; $82
dc.w make_block_tile($002C,0,0,0,0),$000F, make_block_tile($002C,0,0,0,0),$0010 ; $84
;unknown
;byte_6BFE:
dc.b $FF,$FB,$FF,$FB,$FF,$FA,$FF,$FA; 528
dc.b $FF,$FA,$FF,$FA ; 544
; ===========================================================================
; (!)
;loc_6C0A
SSTrackSetOrientation:
move.b (SS_Alternate_HorizScroll_Buf).w,(SS_Last_Alternate_HorizScroll_Buf).w
moveq #0,d1
movea.l (SSTrack_mappings_bitflags).w,a0 ; Get frame mappings pointer
cmpa.l #MapSpec_Straight2,a0 ; Is the track rising or one of the first straight frame?
blt.s + ; Branch if yes
cmpa.l #MapSpec_Straight3,a0 ; Is it straight path frame 3 or higher?
bge.s + ; Branch if yes
; We only get here for straight frame 2
movea.l (SS_CurrentLevelLayout).w,a5 ; Get current level layout
move.b (SpecialStage_CurrentSegment).w,d1 ; Get current segment
move.b (a5,d1.w),d1 ; Get segment geometry
bpl.s +++ ; Branch if not flipped
-
st.b (SSTrack_Orientation).w ; Mark as being flipped
move.b (SSTrack_drawing_index).w,d0 ; Get drawing position
cmp.b (SS_player_anim_frame_timer).w,d0 ; Is it lower than the player's frame?
blt.w return_6C9A ; Return if yes
st.b (SS_Alternate_HorizScroll_Buf).w ; Use the alternate horizontal scroll buffer
rts
; ===========================================================================
+
cmpa.l #MapSpec_Rise14,a0 ; Is the track one of the first 13 rising frames?
blt.s + ; Branch if yes
cmpa.l #MapSpec_Rise15,a0 ; Is it rising frame 15 or higher?
bge.s + ; Branch if yes
; We only get here for straight frame 14
movea.l (SS_CurrentLevelLayout).w,a5 ; Get current level layout
move.b (SpecialStage_CurrentSegment).w,d1 ; Get current segment
move.b (a5,d1.w),d1 ; Get segment geometry
bpl.s ++ ; Branch if not flipped
bra.s -
; ===========================================================================
+
cmpa.l #MapSpec_Drop6,a0 ; Is the track before drop frame 6?
blt.s return_6C9A ; Return is yes
cmpa.l #MapSpec_Drop7,a0 ; Is it drop frame 7 or higher?
bge.s return_6C9A ; Return if yes
; We only get here for straight frame 6
movea.l (SS_CurrentLevelLayout).w,a5 ; Get current level layout
move.b (SpecialStage_CurrentSegment).w,d1 ; Get current segment
move.b (a5,d1.w),d1 ; Get segment geometry
bmi.s - ; Branch if flipped
+
sf.b (SSTrack_Orientation).w ; Mark as being unflipped
move.b (SSTrack_drawing_index).w,d0 ; Get drawing position
cmp.b (SS_player_anim_frame_timer).w,d0 ; Is it lower than the player's frame?
blt.s return_6C9A ; Return if yes
sf.b (SS_Alternate_HorizScroll_Buf).w ; Don't use the alternate horizontal scroll buffer
return_6C9A:
rts
; End of function SSTrack_Draw
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Initialize the PNT and H scroll table buffers.
ssInitTableBuffers:
lea (SS_Horiz_Scroll_Buf_1).w,a1
lea (SS_Horiz_Scroll_Buf_2).w,a2
moveq #0,d0 ; Scroll of 0 for PNTA and PNTB on lines 0 and 1 (normal) or lines 6 and 7 (flipped)
moveq #0,d1 ; Scroll of 0 for PNTB on lines 2 and 3 (normal) or lines 4 and 5 (flipped)
moveq #0,d2 ; Scroll of 0 for PNTB on lines 4 and 5 (normal) or lines 2 and 3 (flipped)
moveq #0,d3 ; Scroll of 0 for PNTB on lines 6 and 7 (normal) or lines 0 and 1 (flipped)
move.w #-$100,d1 ; Scroll of 3 screens for PNTA on lines 2 and 3 (normal) or lines 4 and 5 (flipped)
move.w #-$200,d2 ; Scroll of 2 screens for PNTA on lines 4 and 5 (normal) or lines 2 and 3 (flipped)
move.w #-$300,d3 ; Scroll of 1 screen for PNTA on lines 6 and 7 (normal) or lines 0 and 1 (flipped)
swap d1
swap d2
swap d3
moveq #$1F,d4
- move.l d0,(a1)+
move.l d0,(a1)+
move.l d1,(a1)+
move.l d1,(a1)+
move.l d2,(a1)+
move.l d2,(a1)+
move.l d3,(a1)+
move.l d3,(a1)+
move.l d3,(a2)+
move.l d3,(a2)+
move.l d2,(a2)+
move.l d2,(a2)+
move.l d1,(a2)+
move.l d1,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
dbf d4,-
rts
; End of function ssInitTableBuffers
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Load compressed special stage data into RAM, or VRAM for the art.
ssLdComprsdData:
lea (ArtKos_Special).l,a0
lea (Chunk_Table).l,a1
bsr.w KosDec
move.l #vdpComm(tiles_to_bytes(ArtTile_VRAM_Start),VRAM,WRITE),(VDP_control_port).l
lea (VDP_data_port).l,a1
movea.l #Chunk_Table,a0
move.w (a0)+,d0
subq.w #1,d0
- rept 7
move.l (a0),(a1)
endm
move.l (a0)+,(a1)
dbf d0,-
lea (MiscKoz_SpecialPerspective).l,a0
lea (SSRAM_MiscKoz_SpecialPerspective).l,a1
bsr.w KosDec
lea (MiscKoz_SpecialLevelLayout).l,a0
lea (SSRAM_MiscNem_SpecialLevelLayout).w,a4
bsr.w NemDecToRAM
lea (MiscKoz_SpecialObjectLocations).l,a0
lea (SSRAM_MiscKoz_SpecialObjectLocations).w,a1
bsr.w KosDec
rts
; End of function ssLdComprsdData
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_6D52
SSPlaneB_Background:
move #$2700,sr
movea.l #Chunk_Table,a1
lea (MapEng_SpecialBackBottom).l,a0
move.w #make_art_tile(ArtTile_ArtNem_SpecialBack,0,0),d0
bsr.w EniDec
movea.l #Chunk_Table+$400,a1
lea (MapEng_SpecialBack).l,a0
move.w #make_art_tile(ArtTile_ArtNem_SpecialBack,0,0),d0
bsr.w EniDec
lea (Chunk_Table).l,a1
move.l #vdpComm(VRAM_SS_Plane_B_Name_Table + $0000,VRAM,WRITE),d0
moveq #$1F,d1
moveq #$1F,d2
jsrto (PlaneMapToVRAM_H80_SpecialStage).l, PlaneMapToVRAM_H80_SpecialStage
lea (Chunk_Table).l,a1
move.l #vdpComm(VRAM_SS_Plane_B_Name_Table + $0040,VRAM,WRITE),d0
moveq #$1F,d1
moveq #$1F,d2
jsrto (PlaneMapToVRAM_H80_SpecialStage).l, PlaneMapToVRAM_H80_SpecialStage
lea (Chunk_Table).l,a1
move.l #vdpComm(VRAM_SS_Plane_B_Name_Table + $0080,VRAM,WRITE),d0
moveq #$1F,d1
moveq #$1F,d2
jsrto (PlaneMapToVRAM_H80_SpecialStage).l, PlaneMapToVRAM_H80_SpecialStage
lea (Chunk_Table).l,a1
move.l #vdpComm(VRAM_SS_Plane_B_Name_Table + $00C0,VRAM,WRITE),d0
moveq #$1F,d1
moveq #$1F,d2
jsrto (PlaneMapToVRAM_H80_SpecialStage).l, PlaneMapToVRAM_H80_SpecialStage
move #$2300,sr
rts
; End of function SSPlaneB_Background
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_6DD4
SSDecompressPlayerArt:
lea (ArtNem_SpecialSonicAndTails).l,a0
lea (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF).l,a4
bra.w NemDecToRAM
; End of function SSDecompressPlayerArt
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_6DE4
SS_ScrollBG:
bsr.w SSPlaneB_SetHorizOffset
bsr.w SSTrack_SetVscroll
rts
; End of function SS_ScrollBG
; ===========================================================================
; special stage background vertical and horizontal scroll offsets
off_6DEE: offsetTable
offsetTableEntry.w byte_6E04 ; 0
offsetTableEntry.w byte_6E09 ; 1
offsetTableEntry.w byte_6E0E ; 2
offsetTableEntry.w byte_6E13 ; 3
offsetTableEntry.w byte_6E18 ; 4
offsetTableEntry.w byte_6E1D ; 5
offsetTableEntry.w byte_6E22 ; 6
offsetTableEntry.w byte_6E27 ; 7
offsetTableEntry.w byte_6E2C ; 8
offsetTableEntry.w byte_6E31 ; 9
offsetTableEntry.w byte_6E36 ; $A
byte_6E04: dc.b 2, 2, 2, 2, 2
byte_6E09: dc.b 4, 4, 5, 4, 5
byte_6E0E: dc.b $B, $B, $B, $B, $C
byte_6E13: dc.b 0, 0, 1, 0, 0
byte_6E18: dc.b 1, 1, 1, 1, 1
byte_6E1D: dc.b 9, 9, 8, 9, 9
byte_6E22: dc.b 9, 9, 9, 9, $A
byte_6E27: dc.b 7, 7, 6, 7, 7
byte_6E2C: dc.b 0, 1, 1, 1, 0
byte_6E31: dc.b 4, 3, 3, 3, 4
byte_6E36: dc.b 0, 0,$FF, 0, 0
even
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_6E3C
SSPlaneB_SetHorizOffset:
moveq #0,d7
moveq #0,d6
moveq #0,d0
move.b (SSTrack_last_anim_frame).w,d2 ; Get last track animation frame
move.b (SSTrack_anim).w,d0 ; Get current track animation
add.w d0,d0 ; Convert it to an index
move.w off_6E54(pc,d0.w),d0
jmp off_6E54(pc,d0.w)
; ===========================================================================
off_6E54: offsetTable
offsetTableEntry.w + ; 0 ; Turn, then rise
offsetTableEntry.w + ; 1 ; Turn, then drop
offsetTableEntry.w + ; 2 ; Turn, then straight
offsetTableEntry.w ++ ; 3 ; rts ; Straight
offsetTableEntry.w ++ ; 4 ; rts ; Straight, then turn
; ===========================================================================
+
moveq #0,d1
cmpi.b #1,d2 ; Was the last frame the first in this segment?
blt.s ++ ; Branch if yes
moveq #2,d1
cmpi.b #2,d2 ; Was the last frame frame 1?
blt.s ++ ; Branch if yes
moveq #4,d1
cmpi.b #$A,d2 ; Was the last frame less than $A?
blt.s ++ ; Branch if yes
moveq #2,d1
cmpi.b #$B,d2 ; Was the last frame $A?
blt.s ++ ; Branch if yes
moveq #0,d1
cmpi.b #$C,d2 ; Was the last frame $B?
blt.s ++ ; Branch if yes
+
rts
; ===========================================================================
+
moveq #0,d0
moveq #0,d2
move.b (SSTrack_drawing_index).w,d0 ; Get drawing position
lea_ off_6DEE,a0 ; a0 = pointer to background scroll data
adda.w (a0,d1.w),a0 ; a0 = pointer to background scroll data for current animation frame
move.b (a0,d0.w),d2 ; Get background offset for current frame duration
tst.b (SS_Last_Alternate_HorizScroll_Buf).w ; Was the alternate horizontal scroll buffer used last time?
bne.s + ; Branch if yes
tst.b (SS_Alternate_HorizScroll_Buf).w ; Is the alternate horizontal scroll buffer being used now?
beq.s +++ ; Branch if not
bra.s ++
; ===========================================================================
+
tst.b (SS_Alternate_HorizScroll_Buf).w ; Is the alternate horizontal scroll buffer still being used?
bne.s ++ ; Branch if yes
lea (SS_Horiz_Scroll_Buf_1 + 2).w,a1 ; Load horizontal scroll buffer for PNT B
bra.s +++
; ===========================================================================
+
lea (SS_Horiz_Scroll_Buf_2 + 2).w,a1 ; Load alternate horizontal scroll buffer for PNT B
neg.w d2 ; Change the sign of the background offset
bra.s ++
; ===========================================================================
+
lea (SS_Horiz_Scroll_Buf_1 + 2).w,a1 ; Load horizontal scroll buffer for PNT B
tst.b (SS_Alternate_HorizScroll_Buf).w ; Is the alternate horizontal scroll buffer being used now?
beq.s + ; Branch if not
lea (SS_Horiz_Scroll_Buf_2 + 2).w,a1 ; Load alternate horizontal scroll buffer for PNT B
neg.w d2 ; Change the sign of the background offset
+
move.w #$FF,d0 ; 256 lines
- sub.w d2,(a1)+ ; Change current line's offset
adda_.l #2,a1 ; Skip PNTA entry
dbf d0,-
rts
; End of function SSPlaneB_SetHorizOffset
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_6EE0
SSTrack_SetVscroll:
move.w (Vscroll_Factor_BG).w,(SSTrack_LastVScroll).w ; Save last vertical scroll value
moveq #0,d7 ; Set flag to decrease vertical scroll
moveq #0,d0
moveq #0,d2
move.b (SSTrack_last_anim_frame).w,d2 ; Get last track animation frame
move.b (SSTrack_anim).w,d0 ; Get current track animation
add.w d0,d0 ; Convert it to index
move.w off_6EFE(pc,d0.w),d0
jmp off_6EFE(pc,d0.w)
; ===========================================================================
off_6EFE: offsetTable
offsetTableEntry.w loc_6F0A ; 0 ; Turn, then rise
offsetTableEntry.w loc_6F2A ; 1 ; Turn, then drop
offsetTableEntry.w + ; 2 ; rts ; Turn, then straight
offsetTableEntry.w loc_6F4C ; 3 ; Straight
offsetTableEntry.w + ; 4 ; rts ; Straight, then turn
; ===========================================================================
+
rts
; ===========================================================================
loc_6F0A:
move.b +(pc,d2.w),d1 ; Get current frame's vertical scroll offset
bpl.s SSTrack_ApplyVscroll ; Branch if positive
rts
; ===========================================================================
; Special stage vertical scroll index for 'turn, then rise' animation
+
dc.b -1
dc.b -1 ; 1
dc.b -1 ; 2
dc.b -1 ; 3
dc.b -1 ; 4
dc.b -1 ; 5
dc.b -1 ; 6
dc.b -1 ; 7
dc.b -1 ; 8
dc.b -1 ; 9
dc.b 8 ; 10
dc.b 8 ; 11
dc.b 2 ; 12
dc.b 4 ; 13
dc.b 4 ; 14
dc.b 4 ; 15
dc.b 4 ; 16
dc.b 4 ; 17
dc.b 4 ; 18
dc.b $A ; 19
dc.b $C ; 20
dc.b $E ; 21
dc.b $12 ; 22
dc.b $10 ; 23
; ===========================================================================
loc_6F2A:
st d7 ; Set flag to increase vertical scroll
move.b +(pc,d2.w),d1 ; Get current frame's vertical scroll offset
bpl.s SSTrack_ApplyVscroll ; Branch if positive
rts
; ===========================================================================
; Special stage vertical scroll index for 'turn, then drop' animation
+
dc.b -1
dc.b -1 ; 1
dc.b -1 ; 2
dc.b -1 ; 3
dc.b -1 ; 4
dc.b -1 ; 5
dc.b -1 ; 6
dc.b -1 ; 7
dc.b -1 ; 8
dc.b -1 ; 9
dc.b -1 ; 10
dc.b $10 ; 11
dc.b $12 ; 12
dc.b $E ; 13
dc.b $C ; 14
dc.b $A ; 15
dc.b 4 ; 16
dc.b 4 ; 17
dc.b 4 ; 18
dc.b 4 ; 19
dc.b 4 ; 20
dc.b 4 ; 21
dc.b 2 ; 22
dc.b 0 ; 23
; ===========================================================================
loc_6F4C:
tst.b (SS_Pause_Only_flag).w ; Is the game paused?
bne.s + ; rts ; Return if yes
move.b ++(pc,d2.w),d1 ; Get current frame's vertical scroll offset
bpl.s SSTrack_ApplyVscroll ; Branch if positive
+
rts
; ===========================================================================
; Special stage vertical scroll index for 'straight' animation -- bobbing up and down
+
rept 4
dc.b 6
dc.b 6
dc.b $14
dc.b $14
endm
; ===========================================================================
;loc_6F6A
SSTrack_ApplyVscroll:
moveq #0,d0
moveq #0,d2
move.b (SSTrack_drawing_index).w,d0 ; Get drawing position
lea_ off_6DEE,a0 ; a0 = pointer to background scroll data
adda.w (a0,d1.w),a0 ; a0 = pointer to background scroll data for current animation frame
move.b (a0,d0.w),d2 ; Get background offset for current frame duration
tst.b d7 ; Are we supposed to increase the vertical scroll?
bpl.s + ; Branch if not
add.w d2,(Vscroll_Factor_BG).w ; Increase vertical scroll
rts
; ===========================================================================
+
sub.w d2,(Vscroll_Factor_BG).w ; Decrease vertical scroll
rts
; End of function SSTrack_SetVscroll
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_6F8E:
SSSingleObjLoad:
lea (SS_Dynamic_Object_RAM).w,a1
move.w #(SS_Dynamic_Object_RAM_End-SS_Dynamic_Object_RAM)/object_size-1,d5
- tst.b id(a1)
beq.s + ; rts
lea next_object(a1),a1 ; a1=object
dbf d5,-
+
rts
; End of function sub_6F8E
; ===========================================================================
;loc_6FA4:
SSSingleObjLoad2:
movea.l a0,a1
move.w #SS_Dynamic_Object_RAM_End,d5
sub.w a0,d5
if object_size=$40
lsr.w #6,d5
else
divu.w #object_size,d5
endif
subq.w #1,d5
bcs.s + ; rts
- tst.b id(a1)
beq.s + ; rts
lea next_object(a1),a1
dbf d5,-
+ rts
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 5E - HUD from Special Stage
; ----------------------------------------------------------------------------
; Sprite_6FC0:
Obj5E:
move.b routine(a0),d0
bne.w JmpTo_DisplaySprite
move.l #Obj5E_MapUnc_7070,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_SpecialHUD,0,0),art_tile(a0)
move.b #4,render_flags(a0)
move.b #0,priority(a0)
move.b #1,routine(a0)
bset #6,render_flags(a0)
moveq #0,d1
tst.b (SS_2p_Flag).w
beq.s +
addq.w #6,d1
tst.b (Graphics_Flags).w
bpl.s ++
addq.w #1,d1
bra.s ++
; ---------------------------------------------------------------------------
+ move.w (Player_mode).w,d1
andi.w #3,d1
tst.b (Graphics_Flags).w
bpl.s +
addq.w #3,d1 ; set special stage tails name to "TAILS" instead of MILES
+
add.w d1,d1
moveq #0,d2
moveq #0,d3
lea (SSHUDLayout).l,a1
lea sub2_x_pos(a0),a2
adda.w (a1,d1.w),a1
move.b (a1)+,d3
move.b d3,mainspr_childsprites(a0)
subq.w #1,d3
moveq #0,d0
move.b (a1)+,d0
- move.w d0,(a2,d2.w)
move.b (a1)+,sub2_mapframe-sub2_x_pos(a2,d2.w) ; sub2_mapframe
addq.w #next_subspr,d2
dbf d3,-
rts
; ===========================================================================
; off_7042:
SSHUDLayout: offsetTable
offsetTableEntry.w SSHUD_SonicMilesTotal ; 0
offsetTableEntry.w SSHUD_Sonic ; 1
offsetTableEntry.w SSHUD_Miles ; 2
offsetTableEntry.w SSHUD_SonicTailsTotal ; 3
offsetTableEntry.w SSHUD_Sonic_2 ; 4
offsetTableEntry.w SSHUD_Tails ; 5
offsetTableEntry.w SSHUD_SonicMiles ; 6
offsetTableEntry.w SSHUD_SonicTails ; 7
; byte_7052:
SSHUD_SonicMilesTotal:
dc.b 3 ; Sprite count
dc.b $80 ; X-pos
dc.b 0, 1, 3 ; Sprite 1 frame, Sprite 2 frame, etc
; byte_7057:
SSHUD_Sonic:
dc.b 1
dc.b $D4
dc.b 0
; byte_705A:
SSHUD_Miles:
dc.b 1
dc.b $38
dc.b 1
; byte_705D:
SSHUD_SonicTailsTotal:
dc.b 3
dc.b $80
dc.b 0, 2, 3
; byte_7062:
SSHUD_Sonic_2:
dc.b 1
dc.b $D4
dc.b 0
; byte_7065:
SSHUD_Tails:
dc.b 1
dc.b $38
dc.b 2
; 2 player
; byte_7068:
SSHUD_SonicMiles:
dc.b 2
dc.b $80
dc.b 0, 1
; byte_706C:
SSHUD_SonicTails:
dc.b 2
dc.b $80
dc.b 0, 2
; -----------------------------------------------------------------------------------
; sprite mappings
; -----------------------------------------------------------------------------------
Obj5E_MapUnc_7070: BINCLUDE "mappings/sprite/obj5E.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 5F - Start banner/"Ending controller" from Special Stage
; ----------------------------------------------------------------------------
; Sprite_70F0:
Obj5F:
moveq #0,d0
move.b routine(a0),d0
move.w Obj5F_Index(pc,d0.w),d1
jmp Obj5F_Index(pc,d1.w)
; ===========================================================================
; off_70FE:
Obj5F_Index: offsetTable
offsetTableEntry.w Obj5F_Init ; 0
offsetTableEntry.w Obj5F_Main ; 2
offsetTableEntry.w loc_71B4 ; 4
offsetTableEntry.w loc_710A ; 6
offsetTableEntry.w return_723E ; 8
offsetTableEntry.w loc_7218 ; $A
; ===========================================================================
loc_710A:
moveq #0,d0
move.b angle(a0),d0
bsr.w CalcSine
muls.w objoff_14(a0),d0
muls.w objoff_14(a0),d1
asr.w #8,d0
asr.w #8,d1
add.w d1,x_pos(a0)
add.w d0,y_pos(a0)
cmpi.w #0,x_pos(a0)
blt.w JmpTo_DeleteObject
cmpi.w #$100,x_pos(a0)
bgt.w JmpTo_DeleteObject
cmpi.w #0,y_pos(a0)
blt.w JmpTo_DeleteObject
if removeJmpTos
JmpTo_DisplaySprite
endif
jmpto (DisplaySprite).l, JmpTo_DisplaySprite
; ===========================================================================
; loc_714A:
Obj5F_Init:
tst.b (SS_2p_Flag).w
beq.s +
move.w #8,d0
jsrto (Obj5A_PrintPhrase).l, JmpTo_Obj5A_PrintPhrase
+ move.w #$80,x_pos(a0)
move.w #-$40,y_pos(a0)
move.w #$100,y_vel(a0)
move.l #Obj5F_MapUnc_7240,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_SpecialStart,0,0),art_tile(a0)
move.b #4,render_flags(a0)
move.b #1,priority(a0)
move.b #2,routine(a0)
; loc_718A:
Obj5F_Main:
jsrto (ObjectMove).l, JmpTo_ObjectMove
cmpi.w #$48,y_pos(a0)
blt.w JmpTo_DisplaySprite
move.w #0,y_vel(a0)
move.w #$48,y_pos(a0)
move.b #4,routine(a0)
move.b #$F,objoff_2A(a0)
jmpto (DisplaySprite).l, JmpTo_DisplaySprite
; ===========================================================================
loc_71B4:
subi_.b #1,objoff_2A(a0)
if ~~removeJmpTos
bne.w JmpTo_DisplaySprite
else
bne.s JmpTo_DisplaySprite
endif
moveq #6,d6
; WARNING: the build script needs editing if you rename this label
word_728C_user: lea (Obj5F_MapUnc_7240+$4C).l,a2 ; word_728C
moveq #2,d3
move.w #8,objoff_14(a0)
move.b #6,routine(a0)
- bsr.w SSSingleObjLoad
bne.s +
moveq #0,d0
move.w #bytesToLcnt(object_size),d1
- move.l (a0,d0.w),(a1,d0.w)
addq.w #4,d0
dbf d1,-
if object_size&3
move.w (a0,d0.w),(a1,d0.w)
endif
move.b d3,mapping_frame(a1)
addq.w #1,d3
move.w #-$28,d2
move.w 8(a2),d1
bsr.w CalcAngle
move.b d0,angle(a1)
lea $A(a2),a2
+ dbf d6,--
move.b #$A,routine(a0)
move.w #$1E,objoff_2A(a0)
rts
; ===========================================================================
loc_7218:
subi_.w #1,objoff_2A(a0)
bpl.s +++ ; rts
tst.b (SS_2p_Flag).w
beq.s +
move.w #$A,d0
jsrto (Obj5A_PrintPhrase).l, JmpTo_Obj5A_PrintPhrase
bra.s ++
; ===========================================================================
+ jsrto (Obj5A_CreateRingReqMessage).l, JmpTo_Obj5A_CreateRingReqMessage
+ st.b (SpecialStage_Started).w
jmpto (DeleteObject).l, JmpTo_DeleteObject
; ===========================================================================
+ rts
; ===========================================================================
if removeJmpTos
JmpTo_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
return_723E:
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
; WARNING: the build script needs editing if you rename this label
; or if you change the meaning of frame 2 in these mappings
Obj5F_MapUnc_7240: BINCLUDE "mappings/sprite/obj5F_a.bin"
; -----------------------------------------------------------------------------------
; sprite mappings
; -----------------------------------------------------------------------------------
Obj5F_MapUnc_72D2: BINCLUDE "mappings/sprite/obj5F_b.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 87 - Number of rings in Special Stage
; ----------------------------------------------------------------------------
; Sprite_7356:
Obj87:
moveq #0,d0
move.b objoff_A(a0),d0
move.w Obj87_Index(pc,d0.w),d1
jmp Obj87_Index(pc,d1.w)
; ===========================================================================
; off_7364:
Obj87_Index: offsetTable
offsetTableEntry.w Obj87_Init ; 0
offsetTableEntry.w loc_7480 ; 2
offsetTableEntry.w loc_753E ; 4
offsetTableEntry.w loc_75DE ; 6
; ===========================================================================
; loc_736C:
Obj87_Init:
move.b #2,objoff_A(a0) ; => loc_7480
move.l #Obj5F_MapUnc_72D2,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_SpecialHUD,2,0),art_tile(a0)
move.b #4,render_flags(a0)
bset #6,render_flags(a0)
move.b #2,mainspr_childsprites(a0)
move.w #$20,d0
moveq #0,d1
lea sub2_x_pos(a0),a1
move.w #$48,(a1) ; sub2_x_pos
move.w d0,sub2_y_pos-sub2_x_pos(a1) ; sub2_y_pos
move.w d1,mainspr_height-sub2_x_pos(a1) ; mainspr_height and sub2_mapframe
move.w #$E0,sub3_x_pos-sub2_x_pos(a1) ; sub3_x_pos
move.w d0,sub3_y_pos-sub2_x_pos(a1) ; sub3_y_pos
move.w d1,mapping_frame-sub2_x_pos(a1) ; mapping_frame and sub3_mapframe
move.w d0,sub4_y_pos-sub2_x_pos(a1) ; sub4_y_pos
move.w d0,sub5_y_pos-sub2_x_pos(a1) ; sub5_y_pos
move.w d0,sub6_y_pos-sub2_x_pos(a1) ; sub6_y_pos
move.w d0,sub7_y_pos-sub2_x_pos(a1) ; sub7_y_pos
tst.b (SS_2p_Flag).w
bne.s +++
cmpi.w #0,(Player_mode).w
beq.s +
subi_.b #1,mainspr_childsprites(a0)
move.w #$94,(a1) ; sub2_x_pos
rts
; ===========================================================================
+
bsr.w SSSingleObjLoad
bne.s + ; rts
move.b #ObjID_SSNumberOfRings,id(a1) ; load obj87
move.b #4,objoff_A(a1) ; => loc_753E
move.l #Obj5F_MapUnc_72D2,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_SpecialHUD,2,0),art_tile(a1)
move.b #4,render_flags(a1)
bset #6,render_flags(a1)
move.b #1,mainspr_childsprites(a1)
lea sub2_x_pos(a1),a2
move.w #$80,(a2) ; sub2_x_pos
move.w d0,sub2_y_pos-sub2_x_pos(a2) ; sub2_y_pos
move.w d1,mainspr_height-sub2_x_pos(a2) ; mainspr_height and sub2_mapframe
move.w d0,sub3_y_pos-sub2_x_pos(a2) ; sub3_y_pos
move.w d0,sub4_y_pos-sub2_x_pos(a2) ; sub4_y_pos
/ rts
; ===========================================================================
+
bsr.w SSSingleObjLoad
bne.s - ; rts
move.b #ObjID_SSNumberOfRings,id(a1) ; load obj87
move.b #6,objoff_A(a1) ; => loc_75DE
move.l #Obj5F_MapUnc_72D2,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_SpecialHUD,2,0),art_tile(a1)
move.b #4,render_flags(a1)
bset #6,render_flags(a1)
move.b #0,mainspr_childsprites(a1)
lea sub2_x_pos(a1),a2
move.w #$2C,d0
move.w #$A,d1
move.w d0,sub2_y_pos-sub2_x_pos(a2) ; sub2_y_pos
move.w d1,mainspr_height-sub2_x_pos(a2) ; mainspr_height and sub2_mapframe
move.w d0,sub3_y_pos-sub2_x_pos(a2) ; sub3_y_pos
move.w d1,mapping_frame-sub2_x_pos(a2) ; mapping_frame and sub3_mapframe
move.w d0,sub4_y_pos-sub2_x_pos(a2) ; sub4_y_pos
move.w d1,sub4_mapframe-1-sub2_x_pos(a2) ; something and sub4_mapframe
rts
; ===========================================================================
loc_7480:
moveq #0,d0
moveq #0,d3
moveq #0,d5
lea sub2_x_pos(a0),a1
movea.l a1,a2
addq.w #5,a2 ; a2 = sub2_mapframe(a0)
cmpi.w #2,(Player_mode).w
beq.s loc_74EA
move.b (MainCharacter+ss_rings_hundreds).w,d0
beq.s +
addq.w #1,d3
move.b d0,(a2)
lea next_subspr(a2),a2
+ move.b (MainCharacter+ss_rings_tens).w,d0
tst.b d3
bne.s +
tst.b d0
beq.s ++
+ addq.w #1,d3
move.b d0,(a2)
lea next_subspr(a2),a2
+ addq.w #1,d3
move.b (MainCharacter+ss_rings_units).w,(a2)
lea next_subspr(a2),a2
move.w d3,d4
subq.w #1,d4
move.w #$48,d1
tst.w (Player_mode).w
beq.s +
addi.w #$54,d1
/ move.w d1,(a1,d5.w)
addi_.w #8,d1
addq.w #next_subspr,d5
dbf d4,-
cmpi.w #1,(Player_mode).w
beq.s loc_7536
loc_74EA:
moveq #0,d0
moveq #0,d4
move.b (Sidekick+ss_rings_hundreds).w,d0
beq.s +
addq.w #1,d4
move.b d0,(a2)
lea next_subspr(a2),a2
+ move.b (Sidekick+ss_rings_tens).w,d0
tst.b d4
bne.s +
tst.b d0
beq.s ++
+
addq.w #1,d4
move.b d0,(a2)
lea next_subspr(a2),a2
+ move.b (Sidekick+ss_rings_units).w,(a2)
addq.w #1,d4
add.w d4,d3
subq.w #1,d4
move.w #$E0,d1
tst.w (Player_mode).w
beq.s +
subi.w #$44,d1
/ move.w d1,(a1,d5.w)
addi_.w #8,d1
addq.w #6,d5
dbf d4,-
loc_7536:
move.b d3,mainspr_childsprites(a0)
jmpto (DisplaySprite).l, JmpTo_DisplaySprite
; ===========================================================================
loc_753E:
moveq #0,d0
moveq #0,d1
moveq #0,d2
moveq #1,d3
move.b (MainCharacter+ss_rings_units).w,d0
add.b (Sidekick+ss_rings_units).w,d0
move.b (MainCharacter+ss_rings_tens).w,d1
add.b (Sidekick+ss_rings_tens).w,d1
move.b (MainCharacter+ss_rings_hundreds).w,d2
add.b (Sidekick+ss_rings_hundreds).w,d2
cmpi.b #10,d0
blo.s +
addq.w #1,d1
subi.b #10,d0
+
tst.b d1
beq.s ++
cmpi.b #10,d1
blo.s +
addi_.b #1,d2
subi.b #10,d1
+
addq.w #1,d3
tst.b d2
beq.s ++
addq.w #1,d3
bra.s ++
; ===========================================================================
+
tst.b d2
beq.s +
addq.w #2,d3
+
lea sub2_x_pos(a0),a1
move.b d3,mainspr_childsprites(a0)
cmpi.b #2,d3
blt.s +
beq.s ++
move.w #$78,(a1) ; sub2_x_pos
move.b d2,sub2_mapframe-sub2_x_pos(a1) ; sub2_mapframe
move.w #$80,sub3_x_pos-sub2_x_pos(a1) ; sub3_x_pos
move.b d1,sub3_mapframe-sub2_x_pos(a1) ; sub3_mapframe
move.w #$88,sub4_x_pos-sub2_x_pos(a1) ; sub4_x_pos
move.b d0,sub4_mapframe-sub2_x_pos(a1) ; sub4_mapframe
jmpto (DisplaySprite).l, JmpTo_DisplaySprite
; ===========================================================================
+
move.w #$80,(a1) ; sub2_x_pos
move.b d0,sub2_mapframe-sub2_x_pos(a1) ; sub2_mapframe
jmpto (DisplaySprite).l, JmpTo_DisplaySprite
; ===========================================================================
+
move.w #$7C,(a1) ; sub2_x_pos
move.b d1,sub2_mapframe-sub2_x_pos(a1) ; sub2_mapframe
move.w #$84,sub3_x_pos-sub2_x_pos(a1) ; sub3_x_pos
move.b d0,sub3_mapframe-sub2_x_pos(a1) ; sub3_mapframe
jmpto (DisplaySprite).l, JmpTo_DisplaySprite
; ===========================================================================
loc_75DE:
move.b (SS_2P_BCD_Score).w,d0
bne.s +
rts
; ===========================================================================
+
lea sub2_x_pos(a0),a1
moveq #0,d2
move.b d0,d1
andi.b #$F0,d0
beq.s +
addq.w #1,d2
move.w #$20,(a1) ; sub2_x_pos
lea next_subspr(a1),a1
subi.b #$10,d0
beq.s +
addq.w #1,d2
move.w #$30,(a1) ; sub3_x_pos
lea next_subspr(a1),a1
subi.b #$10,d0
beq.s +
addq.w #1,d2
move.w #$40,(a1) ; sub4_x_pos
bra.s ++
; ===========================================================================
+
andi.b #$F,d1
beq.s +
addq.w #1,d2
move.w #$B8,(a1) ; sub?_x_pos
lea next_subspr(a1),a1
subi_.b #1,d1
beq.s +
addq.w #1,d2
move.w #$C8,(a1) ; sub?_x_pos
lea next_subspr(a1),a1
subi_.b #1,d1
beq.s +
addq.w #1,d2
move.w #$D8,(a1) ; sub?_x_pos
+
move.b d2,mainspr_childsprites(a0)
jmpto (DisplaySprite).l, JmpTo_DisplaySprite
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_7650
SSSetGeometryOffsets:
move.b (SSTrack_drawing_index).w,d0 ; Get drawing position
cmp.b (SS_player_anim_frame_timer).w,d0 ; Compare to player frame duration
beq.s + ; If both are equal, branch
rts
; ===========================================================================
+
moveq #0,d0
move.b (SSTrack_mapping_frame).w,d0 ; Get current track mapping frame
add.w d0,d0 ; Convert to index
lea SSCurveOffsets(pc,d0.w),a2 ; Load current curve offsets into a2
move.b (a2)+,d0 ; Get x offset
tst.b (SSTrack_Orientation).w ; Is track flipped?
beq.s + ; Branch if not
neg.b d0 ; Change sign of offset
+
ext.w d0 ; Extend to word
addi.w #$80,d0 ; Add 128 (why?)
move.w d0,(SS_Offset_X).w ; Set X geometry offset
move.b (a2),d0 ; Get y offset
ext.w d0 ; Extend to word
addi.w #$36,d0 ; Add $36 (why?)
move.w d0,(SS_Offset_Y).w ; Set Y geometry offset
rts
; End of function SSSetGeometryOffsets
; ===========================================================================
; Position offsets to sort-of rotate the plane sonic/tails are in
; when the special stage track is curving, so they follow it better.
; Each word seems to be (x_offset, y_offset)
; See also Ani_SpecialStageTrack.
SSCurveOffsets: ; word_768A:
dc.b $13, 0, $13, 0, $13, 0, $13, 0 ; $00
dc.b 9, -$A, 0,-$1C, 0,-$1C, 0,-$20 ; $04
dc.b 0,-$24, 0,-$2A, 0,-$10, 0, 6 ; $08
dc.b 0, $E, 0, $10, 0, $12, 0, $12 ; $0C
dc.b 9, $12 ; $10; upward curve
dc.b 0, 0, 0, 0, 0, 0, 0, 0 ; $11; straight
dc.b $13, 0, $13, 0, $13, 0, $13, 0 ; $15
dc.b $B, $C, 0, $C, 0, $12, 0, $A ; $19
dc.b 0, 8, 0, 2, 0, $10, 0,-$20 ; $1D
dc.b 0,-$1F, 0,-$1E, 0,-$1B, 0,-$18 ; $21
dc.b 0, -$E ; $25; downward curve
dc.b $13, 0, $13, 0, $13, 0, $13, 0 ; $26
dc.b $13, 0, $13, 0 ; $2B; turning
dc.b $13, 0, $13, 0, $13, 0, $13, 0 ; $2C
dc.b $B, 0 ; $30; exit turn
dc.b 0, 0, 0, 0, 0, 0, 0, 0 ; $31
dc.b 0, 0, 0, 0, 3, 0 ; $35; straight
; ===========================================================================
; Subroutine to advance to the next act and get an encoded version
; of the ring requirements.
; Output:
; d0, d1: Binary coded decimal version of ring requirements (maximum of 299 rings)
; d2: Number of digits in the ring requirements - 1 (minimum 2 digits)
;loc_76FA
SSStartNewAct:
moveq #0,d1
moveq #1,d2
move.w (Current_Special_StageAndAct).w,d0
move.b d0,d1
lsr.w #8,d0
add.w d0,d0
add.w d0,d0
add.w d1,d0
tst.w (Player_mode).w
bne.s +
move.b SpecialStage_RingReq_Team(pc,d0.w),d1
bra.s ++
; ===========================================================================
+
move.b SpecialStage_RingReq_Alone(pc,d0.w),d1
+
move.w d1,(SS_Ring_Requirement).w
moveq #0,d0
cmpi.w #100,d1
blt.s +
addq.w #1,d2
; The following code does a more complete binary coded decimal conversion:
if 1==0
- addi.w #$100,d0
subi.w #100,d1
cmpi.w #100,d1
bgt.s -
else
; This code (the original) is limited to 299 rings:
subi.w #100,d1
move.w #$100,d0
cmpi.w #100,d1
blt.s +
subi.w #100,d1
addi.w #$100,d0
endif
+
divu.w #10,d1
lsl.w #4,d1
or.b d1,d0
swap d1
or.b d1,d0
move.w d0,d1
addi_.w #1,(Current_Special_StageAndAct).w
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; Ring requirement values for Sonic and Tails games
;
; This array stores the number of rings you need to get to complete each round
; of each special stage, while playing with both sonic and tails. 4 bytes per
; stage, corresponding to the four possible parts of the level. Last part is unused.
; ----------------------------------------------------------------------------
; Misc_7756:
SpecialStage_RingReq_Team:
dc.b 40, 80,140,120 ; 4
dc.b 50,100,140,150 ; 8
dc.b 60,110,160,170 ; 12
dc.b 40,100,150,160 ; 16
dc.b 55,110,200,200 ; 20
dc.b 80,140,220,220 ; 24
dc.b 100,190,210,210 ; 28
; ----------------------------------------------------------------------------
; Ring requirement values for Sonic or Tails alone games
;
; This array stores the number of rings you need to get to complete each round
; of each special stage, while playing with either sonic or tails. 4 bytes per
; stage, corresponding to the four possible parts of the level. Last part is unused.
; ----------------------------------------------------------------------------
; Misc_7772:
SpecialStage_RingReq_Alone:
dc.b 30, 70,130,110 ; 4
dc.b 50,100,140,140 ; 8
dc.b 50,110,160,160 ; 12
dc.b 40,110,150,150 ; 16
dc.b 50, 90,160,160 ; 20
dc.b 80,140,210,210 ; 24
dc.b 100,150,190,190 ; 28
; special stage palette table
; word_778E:
SpecialStage_Palettes:
dc.w PalID_SS1
dc.w PalID_SS2
dc.w PalID_SS3
dc.w PalID_SS4
dc.w PalID_SS5
dc.w PalID_SS6
dc.w PalID_SS7
dc.w PalID_SS1_2p
dc.w PalID_SS2_2p
dc.w PalID_SS3_2p
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_77A2
SSInitPalAndData:
clr.b (Current_Special_Act).w
move.b #-1,(SpecialStage_LastSegment2).w
move.w #0,(Ring_count).w
move.w #0,(Ring_count_2P).w
move.b #0,(Perfect_rings_flag).w
move.b #0,(Got_Emerald).w
move.b #4,(SS_Star_color_2).w
lea (SS2p_RingBuffer).w,a2
moveq #0,d0
move.w d0,(a2)+
move.w d0,(a2)+
move.w d0,(a2)+
move.w d0,(a2)+
move.w d0,(a2)+
move.w d0,(a2)+
moveq #PalID_SS,d0
bsr.w PalLoad_ForFade
lea_ SpecialStage_Palettes,a1
moveq #0,d0
move.b (Current_Special_Stage).w,d0
add.w d0,d0
move.w d0,d1
tst.b (SS_2p_Flag).w
beq.s +
cmpi.b #4,d0
blo.s +
addi_.w #6,d0
+
move.w (a1,d0.w),d0
bsr.w PalLoad_ForFade
lea (SSRAM_MiscKoz_SpecialObjectLocations).w,a0
adda.w (a0,d1.w),a0
move.l a0,(SS_CurrentLevelObjectLocations).w
lea (SSRAM_MiscNem_SpecialLevelLayout).w,a0
adda.w (a0,d1.w),a0
move.l a0,(SS_CurrentLevelLayout).w
rts
; End of function SSInitPalAndData
; ===========================================================================
; temporarily remap characters to title card letter format
; Characters are encoded as Aa, Bb, Cc, etc. through a macro
charset 'A',0 ; can't have an embedded 0 in a string
charset 'B',"\4\8\xC\4\x10\x14\x18\x1C\x1E\x22\x26\x2A\4\4\x30\x34\x38\x3C\x40\x44\x48\x4C\x52\x56\4"
charset 'a',"\4\4\4\4\4\4\4\4\2\4\4\4\6\4\4\4\4\4\4\4\4\4\6\4\4"
charset '.',"\x5A"
; letter lookup string
llookup := "ABCDEFGHIJKLMNOPQRSTUVWXYZ ."
; macro for defining title card letters in conjunction with the remapped character set
titleLetters macro letters
; ". ZYXWVUTSRQPONMLKJIHGFEDCBA"
used := %0110000000000110000000010000 ; set to initial state
c := 0
rept strlen(letters)
t := substr(letters,c,1)
if ~~(used&1<<strstr(llookup,t)) ; has the letter been used already?
used := used|1<<strstr(llookup,t) ; if not, mark it as used
dc.b t ; output letter code
if t=="."
dc.b 2 ; output character size
else
dc.b lowstring(t) ; output letter size
endif
endif
c := c+1
endm
dc.w $FFFF ; output string terminator
endm
;word_7822:
SpecialStage_ResultsLetters:
titleLetters "ACDGHILMPRSTUW."
charset ; revert character set
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo_DisplaySprite
jmp (DisplaySprite).l
JmpTo_LoadTitleCardSS
jmp (LoadTitleCardSS).l
JmpTo_DeleteObject
jmp (DeleteObject).l
JmpTo_Obj5A_CreateRingReqMessage
jmp (Obj5A_CreateRingReqMessage).l
JmpTo_Obj5A_PrintPhrase
jmp (Obj5A_PrintPhrase).l
; sub_7862:
JmpTo_ObjectMove
jmp (ObjectMove).l
JmpTo_Hud_Base
jmp (Hud_Base).l
align 4
endif
; ----------------------------------------------------------------------------
; Continue Screen
; ----------------------------------------------------------------------------
; loc_7870:
ContinueScreen:
bsr.w Pal_FadeToBlack
move #$2700,sr
move.w (VDP_Reg1_val).w,d0
andi.b #$BF,d0
move.w d0,(VDP_control_port).l
lea (VDP_control_port).l,a6
move.w #$8004,(a6) ; H-INT disabled
move.w #$8700,(a6) ; Background palette/color: 0/0
bsr.w ClearScreen
clearRAM ContScr_Object_RAM,ContScr_Object_RAM_End
bsr.w ContinueScreen_LoadLetters
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_ContinueTails),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_ContinueTails).l,a0
bsr.w NemDec
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_MiniContinue),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_MiniSonic).l,a0
cmpi.w #2,(Player_mode).w
bne.s +
lea (ArtNem_MiniTails).l,a0
+
bsr.w NemDec
moveq #$A,d1
jsr (ContScrCounter).l
moveq #PalID_SS1,d0
bsr.w PalLoad_ForFade
move.w #0,(Target_palette).w
move.b #MusID_Continue,d0
bsr.w PlayMusic
move.w #$293,(Demo_Time_left).w ; 11 seconds minus 1 frame
clr.b (Level_started_flag).w
clr.l (Camera_X_pos_copy).w
move.l #$1000000,(Camera_Y_pos_copy).w
move.b #ObjID_ContinueChars,(MainCharacter+id).w ; load ObjDB (sonic on continue screen)
move.b #ObjID_ContinueChars,(Sidekick+id).w ; load ObjDB (tails on continue screen)
move.b #6,(Sidekick+routine).w ; => ObjDB_Tails_Init
move.b #ObjID_ContinueText,(ContinueText+id).w ; load ObjDA (continue screen text)
move.b #ObjID_ContinueIcons,(ContinueIcons+id).w ; load ObjDA (continue icons)
move.b #4,(ContinueIcons+routine).w ; => loc_7AD0
jsr (RunObjects).l
jsr (BuildSprites).l
move.b #VintID_Menu,(Vint_routine).w
bsr.w WaitForVint
move.w (VDP_Reg1_val).w,d0
ori.b #$40,d0
move.w d0,(VDP_control_port).l
bsr.w Pal_FadeFromBlack
-
move.b #VintID_Menu,(Vint_routine).w
bsr.w WaitForVint
cmpi.b #4,(MainCharacter+routine).w
bhs.s +
move #$2700,sr
move.w (Demo_Time_left).w,d1
divu.w #60,d1
andi.l #$F,d1
jsr (ContScrCounter).l
move #$2300,sr
+
jsr (RunObjects).l
jsr (BuildSprites).l
cmpi.w #$180,(Sidekick+x_pos).w
bhs.s +
cmpi.b #4,(MainCharacter+routine).w
bhs.s -
tst.w (Demo_Time_left).w
bne.w -
move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen
rts
; ---------------------------------------------------------------------------
+
move.b #GameModeID_Level,(Game_Mode).w ; => Level (Zone play mode)
move.b #3,(Life_count).w
move.b #3,(Life_count_2P).w
moveq #0,d0
move.w d0,(Ring_count).w
move.l d0,(Timer).w
move.l d0,(Score).w
move.b d0,(Last_star_pole_hit).w
move.w d0,(Ring_count_2P).w
move.l d0,(Timer_2P).w
move.l d0,(Score_2P).w
move.b d0,(Last_star_pole_hit_2P).w
move.l #5000,(Next_Extra_life_score).w
move.l #5000,(Next_Extra_life_score_2P).w
subq.b #1,(Continue_count).w
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_7A04:
ContinueScreen_LoadLetters:
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_TitleCard),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_TitleCard).l,a0
bsr.w NemDec
lea (Level_Layout).w,a4
lea (ArtNem_TitleCard2).l,a0
bsr.w NemDecToRAM
lea (ContinueScreen_AdditionalLetters).l,a0
move.l #vdpComm(tiles_to_bytes(ArtTile_ContinueScreen_Additional),VRAM,WRITE),(VDP_control_port).l
lea (Level_Layout).w,a1
lea (VDP_data_port).l,a6
-
moveq #0,d0
move.b (a0)+,d0
bmi.s + ; rts
lsl.w #5,d0
lea (a1,d0.w),a2
moveq #0,d1
move.b (a0)+,d1
lsl.w #3,d1
subq.w #1,d1
- move.l (a2)+,(a6)
dbf d1,-
bra.s --
; ---------------------------------------------------------------------------
+ rts
; End of function ContinueScreen_LoadLetters
; ===========================================================================
; temporarily remap characters to title card letter format
; Characters are encoded as Aa, Bb, Cc, etc. through a macro
charset 'A',0 ; can't have an embedded 0 in a string
charset 'B',"\4\8\xC\4\x10\x14\x18\x1C\x1E\x22\x26\x2A\4\4\x30\x34\x38\x3C\x40\x44\x48\x4C\x52\x56\4"
charset 'a',"\4\4\4\4\4\4\4\4\2\4\4\4\6\4\4\4\4\4\4\4\4\4\6\4\4"
charset '.',"\x5A"
; Defines which letters load for the continue screen
; Each letter occurs only once, and the letters ENOZ (i.e. ZONE) aren't loaded here
; However, this is hidden by the titleLetters macro, and normal titles can be used
; (the macro is defined near SpecialStage_ResultsLetters, which uses it before here)
; word_7A5E:
ContinueScreen_AdditionalLetters:
titleLetters "CONTINUE"
charset ; revert character set
; ===========================================================================
; ----------------------------------------------------------------------------
; Object DA - Continue text
; ----------------------------------------------------------------------------
; loc_7A68:
ObjDA: ; (screen-space obj)
moveq #0,d0
move.b routine(a0),d0
move.w ObjDA_Index(pc,d0.w),d1
jmp ObjDA_Index(pc,d1.w)
; ===========================================================================
; Obj_DA_subtbl:
ObjDA_Index: offsetTable
offsetTableEntry.w ObjDA_Init ; 0
offsetTableEntry.w JmpTo2_DisplaySprite ; 2
offsetTableEntry.w loc_7AD0 ; 4
offsetTableEntry.w loc_7B46 ; 6
; ===========================================================================
; loc_7A7E:
ObjDA_Init:
addq.b #2,routine(a0)
move.l #ObjDA_MapUnc_7CB6,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_ContinueText,0,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo_Adjust2PArtPointer
move.b #0,render_flags(a0)
move.b #$3C,width_pixels(a0)
move.w #$120,x_pixel(a0)
move.w #$C0,y_pixel(a0)
JmpTo2_DisplaySprite
jmp (DisplaySprite).l
; ===========================================================================
; word_7AB2:
ObjDA_XPositions:
dc.w $116, $12A, $102, $13E, $EE, $152, $DA, $166
dc.w $C6, $17A, $B2, $18E, $9E, $1A2, $8A; 8
; ===========================================================================
loc_7AD0:
movea.l a0,a1
lea_ ObjDA_XPositions,a2
moveq #0,d1
move.b (Continue_count).w,d1
subq.b #2,d1
bcc.s +
jmp (DeleteObject).l
; ===========================================================================
+
moveq #1,d3
cmpi.b #$E,d1
blo.s +
moveq #0,d3
moveq #$E,d1
+
move.b d1,d2
andi.b #1,d2
- _move.b #ObjID_ContinueIcons,id(a1) ; load objDA
move.w (a2)+,x_pixel(a1)
tst.b d2
beq.s +
subi.w #$A,x_pixel(a1)
+
move.w #$D0,y_pixel(a1)
move.b #4,mapping_frame(a1)
move.b #6,routine(a1)
move.l #ObjDA_MapUnc_7CB6,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_ContinueText_2,0,1),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo_Adjust2PArtPointer2
move.b #0,render_flags(a1)
lea next_object(a1),a1 ; load obj addr
dbf d1,-
lea -next_object(a1),a1 ; load obj addr
move.b d3,subtype(a1)
loc_7B46:
tst.b subtype(a0)
beq.s +
cmpi.b #4,(MainCharacter+routine).w
blo.s +
move.b (Vint_runcount+3).w,d0
andi.b #1,d0
bne.s +
tst.w (MainCharacter+x_vel).w
bne.s JmpTo2_DeleteObject
rts
; ===========================================================================
+
move.b (Vint_runcount+3).w,d0
andi.b #$F,d0
bne.s JmpTo3_DisplaySprite
bchg #0,mapping_frame(a0)
JmpTo3_DisplaySprite
jmp (DisplaySprite).l
; ===========================================================================
JmpTo2_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
; ----------------------------------------------------------------------------
; Object DB - Sonic lying down or Tails nagging (on the continue screen)
; ----------------------------------------------------------------------------
; Sprite_7B82:
ObjDB:
; a0=character
moveq #0,d0
move.b routine(a0),d0
move.w ObjDB_Index(pc,d0.w),d1
jsr ObjDB_Index(pc,d1.w)
jmp (DisplaySprite).l
; ===========================================================================
; off_7B96: ObjDB_States:
ObjDB_Index: offsetTable
offsetTableEntry.w ObjDB_Sonic_Init ; 0
offsetTableEntry.w ObjDB_Sonic_Wait ; 2
offsetTableEntry.w ObjDB_Sonic_Run ; 4
offsetTableEntry.w ObjDB_Tails_Init ; 6
offsetTableEntry.w ObjDB_Tails_Wait ; 8
offsetTableEntry.w ObjDB_Tails_Run ; $A
; ===========================================================================
; loc_7BA2:
ObjDB_Sonic_Init:
addq.b #2,routine(a0) ; => ObjDB_Sonic_Wait
move.w #$9C,x_pos(a0)
move.w #$19C,y_pos(a0)
move.l #Mapunc_Sonic,mappings(a0)
move.w #make_art_tile(ArtTile_ArtUnc_Sonic,0,0),art_tile(a0)
move.b #4,render_flags(a0)
move.b #2,priority(a0)
move.b #$20,anim(a0)
; loc_7BD2:
ObjDB_Sonic_Wait:
tst.b (Ctrl_1_Press).w ; is start pressed?
bmi.s ObjDB_Sonic_StartRunning ; if yes, branch
jsr (Sonic_Animate).l
jmp (LoadSonicDynPLC).l
; ---------------------------------------------------------------------------
; loc_7BE4:
ObjDB_Sonic_StartRunning:
addq.b #2,routine(a0) ; => ObjDB_Sonic_Run
move.b #$21,anim(a0)
clr.w inertia(a0)
move.b #SndID_SpindashRev,d0 ; super peel-out sound
bsr.w PlaySound
; loc_7BFA:
ObjDB_Sonic_Run:
cmpi.w #$800,inertia(a0)
bne.s +
move.w #$1000,x_vel(a0)
bra.s ++
; ---------------------------------------------------------------------------
+
addi.w #$20,inertia(a0)
+
jsr (ObjectMove).l
jsr (Sonic_Animate).l
jmp (LoadSonicDynPLC).l
; ===========================================================================
; loc_7C22:
ObjDB_Tails_Init:
addq.b #2,routine(a0) ; => ObjDB_Tails_Wait
move.w #$B8,x_pos(a0)
move.w #$1A0,y_pos(a0)
move.l #ObjDA_MapUnc_7CB6,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_ContinueTails,0,0),art_tile(a0)
move.b #4,render_flags(a0)
move.b #2,priority(a0)
move.b #0,anim(a0)
; loc_7C52:
ObjDB_Tails_Wait:
tst.b (Ctrl_1_Press).w ; is start pressed?
bmi.s ObjDB_Tails_StartRunning ; if yes, branch
lea (Ani_objDB).l,a1
jmp (AnimateSprite).l
; ---------------------------------------------------------------------------
; loc_7C64:
ObjDB_Tails_StartRunning:
addq.b #2,routine(a0) ; => ObjDB_Tails_Run
move.l #MapUnc_Tails,mappings(a0)
move.w #make_art_tile(ArtTile_ArtUnc_Tails,0,0),art_tile(a0)
move.b #0,anim(a0)
clr.w inertia(a0)
move.b #SndID_SpindashRev,d0 ; super peel-out sound
bsr.w PlaySound
; loc_7C88:
ObjDB_Tails_Run:
cmpi.w #$720,inertia(a0)
bne.s +
move.w #$1000,x_vel(a0)
bra.s ++
; ---------------------------------------------------------------------------
+
addi.w #$18,inertia(a0)
+
jsr (ObjectMove).l
jsr (Tails_Animate).l
jmp (LoadTailsDynPLC).l
; ===========================================================================
; animation script for continue screen Tails nagging
; off_7CB0
Ani_objDB: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 9, 2, 3,$FF
even
; -------------------------------------------------------------------------------
; Sprite mappings for text, countdown, stars, and Tails on the continue screen
; Art starts at $A000 in VRAM
; -------------------------------------------------------------------------------
ObjDA_MapUnc_7CB6: BINCLUDE "mappings/sprite/objDA.bin"
if ~~removeJmpTos
JmpTo_Adjust2PArtPointer2
jmp (Adjust2PArtPointer2).l
JmpTo_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; loc_7D50:
TwoPlayerResults:
bsr.w Pal_FadeToBlack
move #$2700,sr
move.w (VDP_Reg1_val).w,d0
andi.b #$BF,d0
move.w d0,(VDP_control_port).l
bsr.w ClearScreen
lea (VDP_control_port).l,a6
move.w #$8004,(a6) ; H-INT disabled
move.w #$8200|(VRAM_Menu_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000
move.w #$8400|(VRAM_Menu_Plane_B_Name_Table/$2000),(a6) ; PNT B base: $E000
move.w #$8200|(VRAM_Menu_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000
move.w #$8700,(a6) ; Background palette/color: 0/0
move.w #$8C81,(a6) ; H res 40 cells, no interlace, S/H disabled
move.w #$9001,(a6) ; Scroll table size: 64x32
clearRAM Sprite_Table_Input,Sprite_Table_Input_End
clearRAM VSRslts_Object_RAM,VSRslts_Object_RAM_End
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_FontStuff),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_FontStuff).l,a0
bsr.w NemDec
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_1P2PWins),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_1P2PWins).l,a0
bsr.w NemDec
lea (Chunk_Table).l,a1
lea (MapEng_MenuBack).l,a0
move.w #make_art_tile(ArtTile_VRAM_Start,3,0),d0
bsr.w EniDec
lea (Chunk_Table).l,a1
move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0
moveq #$27,d1
moveq #$1B,d2
jsrto (PlaneMapToVRAM_H40).l, PlaneMapToVRAM_H40
move.w (Results_Screen_2P).w,d0
add.w d0,d0
add.w d0,d0
add.w d0,d0
lea TwoPlayerResultsPointers(pc),a2
movea.l (a2,d0.w),a0
movea.l 4(a2,d0.w),a2
lea (Chunk_Table).l,a1
move.w #make_art_tile(ArtTile_VRAM_Start,0,0),d0
bsr.w EniDec
jsr (a2) ; dynamic call! to Setup2PResults_Act, Setup2PResults_Zone, Setup2PResults_Game, Setup2PResults_SpecialAct, or Setup2PResults_SpecialZone, assuming the pointers in TwoPlayerResultsPointers have not been changed
lea (Chunk_Table).l,a1
move.l #vdpComm(tiles_to_bytes(ArtTile_TwoPlayerResults),VRAM,WRITE),d0
moveq #$27,d1
moveq #$1B,d2
jsrto (PlaneMapToVRAM_H40).l, PlaneMapToVRAM_H40
clr.w (VDP_Command_Buffer).w
move.l #VDP_Command_Buffer,(VDP_Command_Buffer_Slot).w
clr.b (Level_started_flag).w
clr.w (Anim_Counters).w
lea (Anim_SonicMilesBG).l,a2
jsrto (Dynamic_Normal).l, JmpTo_Dynamic_Normal
moveq #PLCID_Std1,d0
bsr.w LoadPLC2
moveq #PalID_Menu,d0
bsr.w PalLoad_ForFade
moveq #0,d0
move.b #MusID_2PResult,d0
cmp.w (Level_Music).w,d0
beq.s +
move.w d0,(Level_Music).w
bsr.w PlayMusic
+
move.w #$707,(Demo_Time_left).w
clr.w (Two_player_mode).w
clr.l (Camera_X_pos).w
clr.l (Camera_Y_pos).w
clr.l (Vscroll_Factor).w
clr.l (Vscroll_Factor_P2).w
clr.l (Vscroll_Factor_P2_HInt).w
move.b #ObjID_HUD,(VSResults_HUD+id).w
move.b #VintID_Menu,(Vint_routine).w
bsr.w WaitForVint
move.w (VDP_Reg1_val).w,d0
ori.b #$40,d0
move.w d0,(VDP_control_port).l
bsr.w Pal_FadeFromBlack
- move.b #VintID_Menu,(Vint_routine).w
bsr.w WaitForVint
lea (Anim_SonicMilesBG).l,a2
jsrto (Dynamic_Normal).l, JmpTo_Dynamic_Normal
jsr (RunObjects).l
jsr (BuildSprites).l
bsr.w RunPLC_RAM
tst.l (Plc_Buffer).w
bne.s -
move.b (Ctrl_1_Press).w,d0
or.b (Ctrl_2_Press).w,d0
andi.b #button_start_mask,d0
beq.s - ; stay on that screen until either player presses start
move.w (Results_Screen_2P).w,d0 ; were we at the act results screen? (VsRSID_Act)
bne.w TwoPlayerResultsDone_Zone ; if not, branch
tst.b (Current_Act).w ; did we just finish act 1?
bne.s + ; if not, branch
addq.b #1,(Current_Act).w ; go to the next act
move.b #1,(Current_Act_2P).w
move.b #GameModeID_Level,(Game_Mode).w ; => Level (Zone play mode)
move.b #0,(Last_star_pole_hit).w
move.b #0,(Last_star_pole_hit_2P).w
moveq #1,d0
move.w d0,(Two_player_mode).w
move.w d0,(Two_player_mode_copy).w
moveq #0,d0
move.l d0,(Score).w
move.l d0,(Score_2P).w
move.l #5000,(Next_Extra_life_score).w
move.l #5000,(Next_Extra_life_score_2P).w
rts
; ===========================================================================
+ ; Displays results for the zone
move.b #2,(Current_Act_2P).w
bsr.w sub_84A4
lea (SS_Total_Won).w,a4
clr.w (a4)
bsr.s sub_7F9A
bsr.s sub_7F9A
move.b (a4),d1
sub.b 1(a4),d1
beq.s + ; if there's a tie, branch
move.w #VsRSID_Zone,(Results_Screen_2P).w
move.b #GameModeID_2PResults,(Game_Mode).w ; => TwoPlayerResults
rts
; ===========================================================================
+ ; There's a tie, play a special stage
move.b (Current_Zone_2P).w,d0
addq.b #1,d0
move.b d0,(Current_Special_Stage).w
move.w #VsRSID_SS,(Results_Screen_2P).w
move.b #1,(SpecialStage_flag_2P).w
move.b #GameModeID_SpecialStage,(Game_Mode).w ; => SpecialStage
moveq #1,d0
move.w d0,(Two_player_mode).w
move.w d0,(Two_player_mode_copy).w
move.b #0,(Last_star_pole_hit).w
move.b #0,(Last_star_pole_hit_2P).w
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_7F9A:
moveq #0,d1
move.b (a5),d1
sub.b 1(a5),d1
beq.s ++
bcs.s +
addq.b #1,(a4)
bra.s ++
; ===========================================================================
+
addq.b #1,1(a4)
+
addq.w #2,a5
rts
; End of function sub_7F9A
; ===========================================================================
; loc_7FB2:
TwoPlayerResultsDone_Zone:
subq.w #1,d0 ; were we at the zone results screen? (VsRSID_Zone)
bne.s TwoPlayerResultsDone_Game ; if not, branch
; loc_7FB6:
TwoPlayerResultsDone_ZoneOrSpecialStages:
lea (Results_Data_2P).w,a4
moveq #0,d0
moveq #0,d1
rept 3
move.w (a4)+,d0
add.l d0,d1
move.w (a4)+,d0
add.l d0,d1
addq.w #2,a4
endm
move.w (a4)+,d0
add.l d0,d1
move.w (a4)+,d0
add.l d0,d1
swap d1
tst.w d1 ; have all levels been completed?
bne.s + ; if not, branch
move.w #VsRSID_Game,(Results_Screen_2P).w
move.b #GameModeID_2PResults,(Game_Mode).w ; => TwoPlayerResults
rts
; ===========================================================================
+
tst.w (Game_Over_2P).w
beq.s + ; if there's a Game Over, clear the results
lea (Results_Data_2P).w,a1
moveq #bytesToWcnt(Results_Data_2P_End-Results_Data_2P),d0
- move.w #-1,(a1)+
dbf d0,-
move.b #3,(Life_count).w
move.b #3,(Life_count_2P).w
+
move.b #GameModeID_2PLevelSelect,(Game_Mode).w ; => LevelSelectMenu2P
rts
; ===========================================================================
; loc_8020:
TwoPlayerResultsDone_Game:
subq.w #1,d0 ; were we at the game results screen? (VsRSID_Game)
bne.s TwoPlayerResultsDone_SpecialStage ; if not, branch
move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen
rts
; ===========================================================================
; loc_802C:
TwoPlayerResultsDone_SpecialStage:
subq.w #1,d0 ; were we at the special stage results screen? (VsRSID_SS)
bne.w TwoPlayerResultsDone_SpecialStages ; if not, branch
cmpi.b #3,(Current_Zone_2P).w ; do we come from the special stage "zone"?
beq.s + ; if yes, branch
move.w #VsRSID_Zone,(Results_Screen_2P).w ; show zone results after tiebreaker special stage
move.b #GameModeID_2PResults,(Game_Mode).w ; => TwoPlayerResults
rts
; ===========================================================================
+
tst.b (Current_Act_2P).w
beq.s +
cmpi.b #2,(Current_Act_2P).w
beq.s loc_80AC
bsr.w sub_84A4
lea (SS_Total_Won).w,a4
clr.w (a4)
bsr.s sub_8094
bsr.s sub_8094
move.b (a4),d1
sub.b 1(a4),d1
bne.s loc_80AC
+
addq.b #1,(Current_Act_2P).w
addq.b #1,(Current_Special_Stage).w
move.w #VsRSID_SS,(Results_Screen_2P).w
move.b #1,(SpecialStage_flag_2P).w
move.b #GameModeID_SpecialStage,(Game_Mode).w ; => SpecialStage
move.w #1,(Two_player_mode).w
move.w #0,(Level_Music).w
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_8094:
moveq #0,d1
move.b (a5),d1
sub.b 1(a5),d1
beq.s ++
bcs.s +
addq.b #1,(a4)
bra.s ++
; ===========================================================================
+
addq.b #1,1(a4)
+
addq.w #2,a5
rts
; End of function sub_8094
; ===========================================================================
loc_80AC:
move.w #VsRSID_SSZone,(Results_Screen_2P).w
move.b #GameModeID_2PResults,(Game_Mode).w ; => TwoPlayerResults
rts
; ===========================================================================
; loc_80BA: BranchTo_loc_7FB6:
TwoPlayerResultsDone_SpecialStages:
; we were at the special stages results screen (VsRSID_SSZone)
bra.w TwoPlayerResultsDone_ZoneOrSpecialStages
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 21 - Score/Rings/Time display (in 2P results)
; ----------------------------------------------------------------------------
; Sprite_80BE:
Obj21: ; (screen-space obj)
moveq #0,d0
move.b routine(a0),d0
move.w Obj21_Index(pc,d0.w),d1
jmp Obj21_Index(pc,d1.w)
; ===========================================================================
; JmpTbl_80CC: Obj21_States:
Obj21_Index: offsetTable
offsetTableEntry.w Obj21_Init ; 0
offsetTableEntry.w Obj21_Main ; 2
; ---------------------------------------------------------------------------
; word_80D0:
Obj21_PositionTable:
; x, y
dc.w $F0, $148
dc.w $F0, $130
dc.w $E0, $148
dc.w $F0, $148
dc.w $F0, $148
; ===========================================================================
; loc_80E4:
Obj21_Init:
addq.b #2,routine(a0) ; => Obj21_Main
move.w (Results_Screen_2P).w,d0
add.w d0,d0
add.w d0,d0
move.l Obj21_PositionTable(pc,d0.w),x_pixel(a0) ; and y_pixel(a0)
move.l #Obj21_MapUnc_8146,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_1P2PWins,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo2_Adjust2PArtPointer
move.b #0,render_flags(a0)
move.b #0,priority(a0)
moveq #2,d1
move.b (SS_Total_Won).w,d0 ; d0 = SS_Total_Won_1P
sub.b (SS_Total_Won+1).w,d0 ; - SS_Total_Won_2P
beq.s ++
bcs.s +
moveq #0,d1
bra.s ++
; ---------------------------------------------------------------------------
+
moveq #1,d1
+
move.b d1,mapping_frame(a0)
; loc_812C:
Obj21_Main:
andi.w #tile_mask,art_tile(a0)
btst #3,(Vint_runcount+3).w
beq.s JmpTo4_DisplaySprite
ori.w #palette_line_1,art_tile(a0)
JmpTo4_DisplaySprite
jmp (DisplaySprite).l
; ===========================================================================
; --------------------------------------------------------------------------
; sprite mappings
; --------------------------------------------------------------------------
Obj21_MapUnc_8146: BINCLUDE "mappings/sprite/obj21.bin"
; ===========================================================================
; loc_819A:
Setup2PResults_Act:
move.w #$1F2,d2
moveq #0,d0
bsr.w sub_8672
move.w #$216,d2
moveq #0,d1
move.b (Current_Act_2P).w,d1
addq.b #1,d1
bsr.w sub_86B0
move.w #$33E,d2
move.l (Score).w,d1
bsr.w sub_86F6
move.w #$352,d2
move.l (Score_2P).w,d1
bsr.w sub_86F6
move.w #$3DA,d2
moveq #0,d0
move.w (Timer_minute_word).w,d1
bsr.w sub_86B0
move.w #$3E0,d2
moveq #0,d1
move.b (Timer_second).w,d1
bsr.w sub_86B0
move.w #$3E6,d2
moveq #0,d1
move.b (Timer_frame).w,d1
mulu.w #$1B0,d1
lsr.l #8,d1
bsr.w sub_86B0
move.w #$3EE,d2
moveq #0,d0
move.w (Timer_minute_word_2P).w,d1
bsr.w sub_86B0
move.w #$3F4,d2
moveq #0,d1
move.b (Timer_second_2P).w,d1
bsr.w sub_86B0
move.w #$3FA,d2
moveq #0,d1
move.b (Timer_centisecond_2P).w,d1
mulu.w #$1B0,d1
lsr.l #8,d1
bsr.w sub_86B0
move.w #$486,d2
moveq #0,d0
move.w (Ring_count).w,d1
bsr.w sub_86B0
move.w #$49A,d2
move.w (Ring_count_2P).w,d1
bsr.w sub_86B0
move.w #$526,d2
moveq #0,d0
move.w (Rings_Collected).w,d1
bsr.w sub_86B0
move.w #$53A,d2
move.w (Rings_Collected_2P).w,d1
bsr.w sub_86B0
move.w #$5C6,d2
moveq #0,d0
move.w (Monitors_Broken).w,d1
bsr.w sub_86B0
move.w #$5DA,d2
move.w (Monitors_Broken_2P).w,d1
bsr.w sub_86B0
bsr.w sub_8476
move.w #$364,d2
move.w #$6000,d0
move.l (Score).w,d1
sub.l (Score_2P).w,d1
bsr.w sub_8652
move.w #$404,d2
move.l (Timer_2P).w,d1
sub.l (Timer).w,d1
bsr.w sub_8652
move.w #$4A4,d2
moveq #0,d1
move.w (Ring_count).w,d1
sub.w (Ring_count_2P).w,d1
bsr.w sub_8652
move.w #$544,d2
moveq #0,d1
move.w (Rings_Collected).w,d1
sub.w (Rings_Collected_2P).w,d1
bsr.w sub_8652
move.w #$5E4,d2
moveq #0,d1
move.w (Monitors_Broken).w,d1
sub.w (Monitors_Broken_2P).w,d1
bsr.w sub_8652
move.w #$706,d2
moveq #0,d0
moveq #0,d1
move.b (a4),d1
bsr.w sub_86B0
move.w #$70E,d2
moveq #0,d1
move.b 1(a4),d1
bsr.w sub_86B0
move.w (a4),(SS_Total_Won).w
rts
; ===========================================================================
; loc_82FA:
Setup2PResults_Zone:
move.w #$242,d2
moveq #0,d0
bsr.w sub_8672
bsr.w sub_84A4
lea (SS_Total_Won).w,a4
clr.w (a4)
move.w #$398,d6
bsr.w sub_854A
move.w #$488,d6
bsr.w sub_854A
move.w #$618,d6
bsr.w sub_854A
rts
; ===========================================================================
; loc_8328:
Setup2PResults_Game:
lea (Results_Data_2P).w,a5
lea (SS_Total_Won).w,a4
clr.w (a4)
move.w #$208,d6
bsr.w sub_84C4
move.w #$258,d6
bsr.w sub_84C4
move.w #$2A8,d6
bsr.w sub_84C4
move.w #$348,d6
bsr.w sub_84C4
move.w #$398,d6
bsr.w sub_84C4
move.w #$3E8,d6
bsr.w sub_84C4
move.w #$488,d6
bsr.w sub_84C4
move.w #$4D8,d6
bsr.w sub_84C4
move.w #$528,d6
bsr.w sub_84C4
move.w #$5C8,d6
bsr.w sub_84C4
move.w #$618,d6
bsr.w sub_84C4
move.w #$668,d6
bsr.w sub_84C4
move.w #$70A,d2
moveq #0,d0
moveq #0,d1
move.b (a4),d1
bsr.w sub_86B0
move.w #$710,d2
moveq #0,d1
move.b 1(a4),d1
bsr.w sub_86B0
rts
; ===========================================================================
; loc_83B0:
Setup2PResults_SpecialAct:
move.w #$266,d2
moveq #0,d1
move.b (Current_Act_2P).w,d1
addq.b #1,d1
bsr.w sub_86B0
move.w #$4D6,d2
moveq #0,d0
move.w (SS2p_RingBuffer).w,d1 ; P1 SS act 1 rings
bsr.w sub_86B0
move.w #$4E6,d2
move.w (SS2p_RingBuffer+2).w,d1 ; P2 SS act 1 rings
bsr.w sub_86B0
move.w #$576,d2
moveq #0,d0
move.w (SS2p_RingBuffer+4).w,d1 ; P1 SS act 2 rings
bsr.w sub_86B0
move.w #$586,d2
move.w (SS2p_RingBuffer+6).w,d1 ; P2 SS act 2 rings
bsr.w sub_86B0
move.w #$616,d2
moveq #0,d0
move.w (SS2p_RingBuffer+8).w,d1 ; P1 SS act 3 rings
bsr.w sub_86B0
move.w #$626,d2
move.w (SS2p_RingBuffer+$A).w,d1 ; P2 SS act 3 rings
bsr.w sub_86B0
bsr.w sub_8476
move.w #$6000,d0
move.w #$4F0,d2
moveq #0,d1
move.w (SS2p_RingBuffer).w,d1 ; P1 SS act 1 rings
sub.w (SS2p_RingBuffer+2).w,d1 ; P2 SS act 1 rings
bsr.w sub_8652
move.w #$590,d2
moveq #0,d1
move.w (SS2p_RingBuffer+4).w,d1 ; P1 SS act 2 rings
sub.w (SS2p_RingBuffer+6).w,d1 ; P2 SS act 2 rings
bsr.w sub_8652
move.w #$630,d2
moveq #0,d1
move.w (SS2p_RingBuffer+8).w,d1 ; P1 SS act 3 rings
sub.w (SS2p_RingBuffer+$A).w,d1 ; P2 SS act 3 rings
bsr.w sub_8652
move.w (a4),(SS_Total_Won).w
rts
; ===========================================================================
; loc_8452:
Setup2PResults_SpecialZone:
bsr.w sub_84A4
lea (SS_Total_Won).w,a4
clr.w (a4)
move.w #$4D4,d6
bsr.w sub_85CE
move.w #$574,d6
bsr.w sub_85CE
move.w #$614,d6
bsr.w sub_85CE
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_8476:
lea (EHZ_Results_2P).w,a4
move.b (Current_Zone_2P).w,d0
beq.s +
lea (MCZ_Results_2P).w,a4
subq.b #1,d0
beq.s +
lea (CNZ_Results_2P).w,a4
subq.b #1,d0
beq.s +
lea (SS_Results_2P).w,a4
+
moveq #0,d0
move.b (Current_Act_2P).w,d0
add.w d0,d0
lea (a4,d0.w),a4
clr.w (a4)
rts
; End of function sub_8476
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_84A4:
lea (EHZ_Results_2P).w,a5
move.b (Current_Zone_2P).w,d0
beq.s + ; rts
lea (MCZ_Results_2P).w,a5
subq.b #1,d0
beq.s + ; rts
lea (CNZ_Results_2P).w,a5
subq.b #1,d0
beq.s + ; rts
lea (SS_Results_2P).w,a5
+
rts
; End of function sub_84A4
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_84C4:
move.w (a5),d0
bmi.s +
move.w d6,d2
moveq #0,d0
moveq #0,d1
move.b (a5),d1
bsr.w sub_86B0
addq.w #8,d6
move.w d6,d2
moveq #0,d1
move.b 1(a5),d1
bsr.w sub_86B0
addi.w #$12,d6
move.w d6,d2
move.w #$6000,d0
moveq #0,d1
move.b (a5),d1
sub.b 1(a5),d1
bsr.w sub_8652
addq.w #2,a5
rts
; ===========================================================================
+
addq.w #4,d6
not.w d0
bne.s +
lea (Text2P_NoGame).l,a1
move.w d6,d2
bsr.w loc_8698
addi.w #$16,d6
move.w d6,d2
lea (Text2P_Blank).l,a1
bsr.w loc_8698
addq.w #2,a5
rts
; ===========================================================================
+
moveq #0,d0
lea (Text2P_GameOver).l,a1
move.w d6,d2
bsr.w loc_8698
addi.w #$16,d6
move.w d6,d2
move.w #$6000,d0
moveq #0,d1
move.b (a5),d1
sub.b 1(a5),d1
bsr.w sub_8652
addq.w #2,a5
rts
; End of function sub_84C4
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_854A:
move.w (a5),d0
bmi.s loc_8582
move.w d6,d2
moveq #0,d0
moveq #0,d1
move.b (a5),d1
bsr.w sub_86B0
addq.w #8,d6
move.w d6,d2
moveq #0,d1
move.b 1(a5),d1
bsr.w sub_86B0
addi.w #$C,d6
move.w d6,d2
move.w #$6000,d0
moveq #0,d1
move.b (a5),d1
sub.b 1(a5),d1
bsr.w sub_8652
addq.w #2,a5
rts
; ===========================================================================
loc_8582:
not.w d0
bne.s loc_85A6
lea (Text2P_NoGame).l,a1
move.w d6,d2
bsr.w loc_8698
addi.w #$14,d6
move.w d6,d2
lea (Text2P_Blank).l,a1
bsr.w loc_8698
addq.w #2,a5
rts
; ===========================================================================
loc_85A6:
moveq #0,d0
lea (Text2P_GameOver).l,a1
move.w d6,d2
bsr.w loc_8698
addi.w #$14,d6
move.w d6,d2
move.w #$6000,d0
moveq #0,d1
move.b (a5),d1
sub.b 1(a5),d1
bsr.w sub_8652
addq.w #2,a5
rts
; End of function sub_854A
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_85CE:
move.w (a5),d0
bmi.s +
move.w d6,d2
moveq #0,d0
moveq #0,d1
move.b (a5),d1
bsr.w sub_86B0
addi.w #$C,d6
move.w d6,d2
moveq #0,d1
move.b 1(a5),d1
bsr.w sub_86B0
addi.w #$10,d6
move.w d6,d2
move.w #$6000,d0
moveq #0,d1
move.b (a5),d1
sub.b 1(a5),d1
bsr.w sub_8652
addq.w #2,a5
rts
; ===========================================================================
+
not.w d0
bne.s loc_862C
lea (Text2P_NoGame).l,a1
move.w d6,d2
addq.w #4,d2
bsr.w loc_8698
addi.w #$14,d6
move.w d6,d2
lea (Text2P_Blank).l,a1
bsr.s loc_8698
addq.w #2,a5
rts
; ===========================================================================
loc_862C:
moveq #0,d0
lea (Text2P_GameOver).l,a1
move.w d6,d2
bsr.s loc_8698
addi.w #$14,d6
move.w d6,d2
move.w #$6000,d0
moveq #0,d1
move.b (a5),d1
sub.b 1(a5),d1
bsr.w sub_8652
addq.w #2,a5
rts
; End of function sub_85CE
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_8652:
lea (Text2P_Tied).l,a1
beq.s ++
bcs.s +
lea (Text2P_1P).l,a1
addq.b #1,(a4)
bra.s ++
; ===========================================================================
+
lea (Text2P_2P).l,a1
addq.b #1,1(a4)
+
bra.s loc_8698
; End of function sub_8652
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_8672:
lea (Text2P_EmeraldHill).l,a1
move.b (Current_Zone_2P).w,d1
beq.s loc_8698
lea (Text2P_MysticCave).l,a1
subq.b #1,d1
beq.s loc_8698
lea (Text2P_CasinoNight).l,a1
subq.b #1,d1
beq.s loc_8698
lea (Text2P_SpecialStage).l,a1
loc_8698:
lea (Chunk_Table).l,a2
lea (a2,d2.w),a2
moveq #0,d1
move.b (a1)+,d1
- move.b (a1)+,d0
move.w d0,(a2)+
dbf d1,-
rts
; End of function sub_8672
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_86B0:
lea (Chunk_Table).l,a2
lea (a2,d2.w),a2
lea (word_86F0).l,a3
moveq #0,d2
moveq #2,d5
- moveq #0,d3
move.w (a3)+,d4
- sub.w d4,d1
bcs.s +
addq.w #1,d3
bra.s -
; ---------------------------------------------------------------------------
+
add.w d4,d1
tst.w d5
beq.s ++
tst.w d3
beq.s +
moveq #1,d2
+
tst.w d2
beq.s ++
+
addi.b #$10,d3
move.b d3,d0
move.w d0,(a2)
+
addq.w #2,a2
dbf d5,--
rts
; End of function sub_86B0
; ===========================================================================
word_86F0:
dc.w 100
dc.w 10 ; 1
dc.w 1 ; 2
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_86F6:
lea (Chunk_Table).l,a2
lea (a2,d2.w),a2
lea (dword_8732).l,a3
moveq #0,d2
moveq #5,d5
- moveq #0,d3
move.l (a3)+,d4
- sub.l d4,d1
bcs.s +
addq.w #1,d3
bra.s -
; ===========================================================================
+
add.l d4,d1
tst.w d3
beq.s +
moveq #1,d2
+
tst.w d2
beq.s +
addi.b #$10,d3
move.b d3,d0
move.w d0,(a2)
+
addq.w #2,a2
dbf d5,--
rts
; End of function sub_86F6
; ===========================================================================
dword_8732:
dc.l 100000
dc.l 10000
dc.l 1000
dc.l 100
dc.l 10
dc.l 1
; set the character set for menu text
charset '@',"\27\30\31\32\33\34\35\36\37\38\39\40\41\42\43\44\45\46\47\48\49\50\51\52\53\54\55"
charset '0',"\16\17\18\19\20\21\22\23\24\25"
charset '*',$1A
charset ':',$1C
charset '.',$1D
charset ' ',0
; Menu text
menutxt macro text
dc.b strlen(text)-1
dc.b text
endm
Text2P_EmeraldHill: menutxt "EMERALD HILL" ; byte_874A:
rev02even
Text2P_MysticCave: menutxt " MYSTIC CAVE" ; byte_8757:
rev02even
Text2P_CasinoNight: menutxt "CASINO NIGHT" ; byte_8764:
rev02even
Text2P_SpecialStage: menutxt "SPECIAL STAGE" ; byte_8771:
rev02even
Text2P_Special: menutxt " SPECIAL " ; byte_877F:
rev02even
Text2P_Zone: menutxt "ZONE " ; byte_878C:
rev02even
Text2P_Stage: menutxt "STAGE" ; byte_8792:
rev02even
Text2P_GameOver: menutxt "GAME OVER" ; byte_8798:
rev02even
Text2P_TimeOver: menutxt "TIME OVER"
rev02even
Text2P_NoGame: menutxt "NO GAME" ; byte_87AC:
rev02even
Text2P_Tied: menutxt "TIED" ; byte_87B4:
rev02even
Text2P_1P: menutxt " 1P" ; byte_87B9:
rev02even
Text2P_2P: menutxt " 2P" ; byte_87BD:
rev02even
Text2P_Blank: menutxt " " ; byte_87C1:
rev02even
charset ; reset character set
; ------------------------------------------------------------------------
; MENU ANIMATION SCRIPT
; ------------------------------------------------------------------------
;word_87C6:
Anim_SonicMilesBG: zoneanimstart
; Sonic/Miles animated background
zoneanimdecl -1, ArtUnc_MenuBack, 1, 6, $A
dc.b 0,$C7
dc.b $A, 5
dc.b $14, 5
dc.b $1E,$C7
dc.b $14, 5
dc.b $A, 5
even
zoneanimend
; off_87DC:
TwoPlayerResultsPointers:
VsResultsScreen_Act: dc.l Map_2PActResults, Setup2PResults_Act
VsResultsScreen_Zone: dc.l Map_2PZoneResults, Setup2PResults_Zone
VsResultsScreen_Game: dc.l Map_2PGameResults, Setup2PResults_Game
VsResultsScreen_SS: dc.l Map_2PSpecialStageActResults, Setup2PResults_SpecialAct
VsResultsScreen_SSZone: dc.l Map_2PSpecialStageZoneResults, Setup2PResults_SpecialZone
; 2P single act results screen (enigma compressed)
; byte_8804:
Map_2PActResults: BINCLUDE "mappings/misc/2P Act Results.bin"
; 2P zone results screen (enigma compressed)
; byte_88CE:
Map_2PZoneResults: BINCLUDE "mappings/misc/2P Zone Results.bin"
; 2P game results screen (after all 4 zones) (enigma compressed)
; byte_8960:
Map_2PGameResults: BINCLUDE "mappings/misc/2P Game Results.bin"
; 2P special stage act results screen (enigma compressed)
; byte_8AA4:
Map_2PSpecialStageActResults: BINCLUDE "mappings/misc/2P Special Stage Act Results.bin"
; 2P special stage zone results screen (enigma compressed)
; byte_8B30:
Map_2PSpecialStageZoneResults: BINCLUDE "mappings/misc/2P Special Stage Zone Results.bin"
even
if ~~removeJmpTos
JmpTo2_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo_Dynamic_Normal
jmp (Dynamic_Normal).l
align 4
endif
; ===========================================================================
; loc_8BD4:
MenuScreen:
bsr.w Pal_FadeToBlack
move #$2700,sr
move.w (VDP_Reg1_val).w,d0
andi.b #$BF,d0
move.w d0,(VDP_control_port).l
bsr.w ClearScreen
lea (VDP_control_port).l,a6
move.w #$8004,(a6) ; H-INT disabled
move.w #$8200|(VRAM_Menu_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000
move.w #$8400|(VRAM_Menu_Plane_B_Name_Table/$2000),(a6) ; PNT B base: $E000
move.w #$8200|(VRAM_Menu_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000
move.w #$8700,(a6) ; Background palette/color: 0/0
move.w #$8C81,(a6) ; H res 40 cells, no interlace, S/H disabled
move.w #$9001,(a6) ; Scroll table size: 64x32
clearRAM Sprite_Table_Input,Sprite_Table_Input_End
clearRAM Menus_Object_RAM,Menus_Object_RAM_End
; load background + graphics of font/LevSelPics
clr.w (VDP_Command_Buffer).w
move.l #VDP_Command_Buffer,(VDP_Command_Buffer_Slot).w
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_FontStuff),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_FontStuff).l,a0
bsr.w NemDec
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_MenuBox),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_MenuBox).l,a0
bsr.w NemDec
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_LevelSelectPics),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_LevelSelectPics).l,a0
bsr.w NemDec
lea (Chunk_Table).l,a1
lea (MapEng_MenuBack).l,a0
move.w #make_art_tile(ArtTile_VRAM_Start,3,0),d0
bsr.w EniDec
lea (Chunk_Table).l,a1
move.l #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE),d0
moveq #$27,d1
moveq #$1B,d2
jsrto (PlaneMapToVRAM_H40).l, JmpTo_PlaneMapToVRAM_H40 ; fullscreen background
cmpi.b #GameModeID_OptionsMenu,(Game_Mode).w ; options menu?
beq.w MenuScreen_Options ; if yes, branch
cmpi.b #GameModeID_LevelSelect,(Game_Mode).w ; level select menu?
beq.w MenuScreen_LevelSelect ; if yes, branch
;MenuScreen_LevSel2P:
lea (Chunk_Table).l,a1
lea (MapEng_LevSel2P).l,a0
move.w #make_art_tile(ArtTile_ArtNem_MenuBox,0,0),d0
bsr.w EniDec
lea (Chunk_Table+$198).l,a1
lea (MapEng_LevSel2P).l,a0
move.w #make_art_tile(ArtTile_ArtNem_MenuBox,1,0),d0
bsr.w EniDec
lea (Chunk_Table+$330).l,a1
lea (MapEng_LevSelIcon).l,a0
move.w #make_art_tile(ArtTile_ArtNem_LevelSelectPics,0,0),d0
bsr.w EniDec
lea (Chunk_Table+$498).l,a2
moveq #$F,d1
- move.w #$207B,(a2)+
dbf d1,-
bsr.w Update2PLevSelSelection
addq.b #1,(Current_Zone_2P).w
andi.b #3,(Current_Zone_2P).w
bsr.w ClearOld2PLevSelSelection
addq.b #1,(Current_Zone_2P).w
andi.b #3,(Current_Zone_2P).w
bsr.w ClearOld2PLevSelSelection
addq.b #1,(Current_Zone_2P).w
andi.b #3,(Current_Zone_2P).w
bsr.w ClearOld2PLevSelSelection
addq.b #1,(Current_Zone_2P).w
andi.b #3,(Current_Zone_2P).w
clr.w (Player_mode).w
clr.b (Current_Act_2P).w
clr.w (Results_Screen_2P).w ; VsRSID_Act
clr.b (Level_started_flag).w
clr.w (Anim_Counters).w
clr.w (Game_Over_2P).w
lea (Anim_SonicMilesBG).l,a2
jsrto (Dynamic_Normal).l, JmpTo2_Dynamic_Normal
moveq #PalID_Menu,d0
bsr.w PalLoad_ForFade
lea (Normal_palette_line3).w,a1
lea (Target_palette_line3).w,a2
moveq #bytesToLcnt($20),d1
- move.l (a1),(a2)+
clr.l (a1)+
dbf d1,-
move.b #MusID_Options,d0
jsrto (PlayMusic).l, JmpTo_PlayMusic
move.w #$707,(Demo_Time_left).w
clr.w (Two_player_mode).w
clr.l (Camera_X_pos).w
clr.l (Camera_Y_pos).w
move.b #VintID_Menu,(Vint_routine).w
bsr.w WaitForVint
move.w (VDP_Reg1_val).w,d0
ori.b #$40,d0
move.w d0,(VDP_control_port).l
bsr.w Pal_FadeFromBlack
;loc_8DA8:
LevelSelect2P_Main:
move.b #VintID_Menu,(Vint_routine).w
bsr.w WaitForVint
move #$2700,sr
bsr.w ClearOld2PLevSelSelection
bsr.w LevelSelect2P_Controls
bsr.w Update2PLevSelSelection
move #$2300,sr
lea (Anim_SonicMilesBG).l,a2
jsrto (Dynamic_Normal).l, JmpTo2_Dynamic_Normal
move.b (Ctrl_1_Press).w,d0
or.b (Ctrl_2_Press).w,d0
andi.b #button_start_mask,d0
bne.s LevelSelect2P_PressStart
bra.w LevelSelect2P_Main
; ===========================================================================
;loc_8DE2:
LevelSelect2P_PressStart:
bsr.w Chk2PZoneCompletion
bmi.s loc_8DF4
move.w #SndID_Error,d0
jsrto (PlaySound).l, JmpTo_PlaySound
bra.w LevelSelect2P_Main
; ===========================================================================
loc_8DF4:
moveq #0,d0
move.b (Current_Zone_2P).w,d0
add.w d0,d0
move.w LevelSelect2P_LevelOrder(pc,d0.w),d0
bmi.s loc_8E3A
move.w d0,(Current_ZoneAndAct).w
move.w #1,(Two_player_mode).w
move.b #GameModeID_Level,(Game_Mode).w ; => Level (Zone play mode)
move.b #0,(Last_star_pole_hit).w
move.b #0,(Last_star_pole_hit_2P).w
moveq #0,d0
move.l d0,(Score).w
move.l d0,(Score_2P).w
move.l #5000,(Next_Extra_life_score).w
move.l #5000,(Next_Extra_life_score_2P).w
rts
; ===========================================================================
loc_8E3A:
move.b #4,(Current_Special_Stage).w
move.b #GameModeID_SpecialStage,(Game_Mode).w ; => SpecialStage
moveq #1,d0
move.w d0,(Two_player_mode).w
move.w d0,(Two_player_mode_copy).w
rts
; ===========================================================================
; word_8E52:
LevelSelect2P_LevelOrder:
dc.w emerald_hill_zone_act_1
dc.w mystic_cave_zone_act_1
dc.w casino_night_zone_act_1
dc.w $FFFF
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_8E5A:
LevelSelect2P_Controls:
move.b (Ctrl_1_Press).w,d0
or.b (Ctrl_2_Press).w,d0
move.b d0,d1
andi.b #button_up_mask|button_down_mask,d0
beq.s +
bchg #1,(Current_Zone_2P).w
+
andi.b #button_left_mask|button_right_mask,d1
beq.s + ; rts
bchg #0,(Current_Zone_2P).w
+
rts
; End of function LevelSelect2P_Controls
; ---------------------------------------------------------------------------
; Subroutine to update the 2P level select selection graphically
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_8E7E:
Update2PLevSelSelection:
moveq #0,d0
move.b (Current_Zone_2P).w,d0
lsl.w #4,d0 ; 16 bytes per entry
lea (LevSel2PIconData).l,a3
lea (a3,d0.w),a3
move.w #$6000,d0 ; highlight text
lea (Chunk_Table+$48).l,a2
movea.l (a3)+,a1
bsr.w MenuScreenTextToRAM
lea (Chunk_Table+$94).l,a2
movea.l (a3)+,a1
bsr.w MenuScreenTextToRAM
lea (Chunk_Table+$D8).l,a2
movea.l 4(a3),a1
bsr.w Chk2PZoneCompletion ; has the zone been completed?
bmi.s + ; if not, branch
lea (Chunk_Table+$468).l,a1 ; display large X instead of icon
+
moveq #2,d1
- move.l (a1)+,(a2)+
move.l (a1)+,(a2)+
lea $1A(a2),a2
dbf d1,-
lea (Chunk_Table).l,a1
move.l (a3)+,d0
moveq #$10,d1
moveq #$B,d2
jsrto (PlaneMapToVRAM_H40).l, JmpTo_PlaneMapToVRAM_H40
lea (Pal_LevelIcons).l,a1
moveq #0,d0
move.b (a3),d0
lsl.w #5,d0
lea (a1,d0.w),a1
lea (Normal_palette_line3).w,a2
moveq #bytesToLcnt(palette_line_size),d1
- move.l (a1)+,(a2)+
dbf d1,-
rts
; End of function Update2PLevSelSelection
; ---------------------------------------------------------------------------
; Subroutine to check if a 2P zone has been completed
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_8EFE:
Chk2PZoneCompletion:
moveq #0,d0
move.b (Current_Zone_2P).w,d0
; multiply d0 by 6
move.w d0,d1
add.w d0,d0
add.w d1,d0
add.w d0,d0
lea (Results_Data_2P).w,a5
lea (a5,d0.w),a5
move.w (a5),d0
add.w 2(a5),d0
rts
; End of function Chk2PZoneCompletion
; ---------------------------------------------------------------------------
; Subroutine to clear the old 2P level select selection
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_8F1C:
ClearOld2PLevSelSelection:
moveq #0,d0
move.b (Current_Zone_2P).w,d0
lsl.w #4,d0
lea (LevSel2PIconData).l,a3
lea (a3,d0.w),a3
moveq #0,d0
lea (Chunk_Table+$1E0).l,a2
movea.l (a3)+,a1
bsr.w MenuScreenTextToRAM
lea (Chunk_Table+$22C).l,a2
movea.l (a3)+,a1
bsr.w MenuScreenTextToRAM
lea (Chunk_Table+$270).l,a2
lea (Chunk_Table+$498).l,a1
bsr.w Chk2PZoneCompletion
bmi.s +
lea (Chunk_Table+$468).l,a1
+
moveq #2,d1
- move.l (a1)+,(a2)+
move.l (a1)+,(a2)+
lea $1A(a2),a2
dbf d1,-
lea (Chunk_Table+$198).l,a1
move.l (a3)+,d0
moveq #$10,d1
moveq #$B,d2
jmpto (PlaneMapToVRAM_H40).l, JmpTo_PlaneMapToVRAM_H40
; End of function ClearOld2PLevSelSelection
; ===========================================================================
; off_8F7E:
LevSel2PIconData:
; macro to declare icon data for a 2P level select icon
iconData macro txtlabel,txtlabel2,vramAddr,iconPal,iconAddr
dc.l txtlabel, txtlabel2 ; text locations
dc.l vdpComm(vramAddr,VRAM,WRITE) ; VRAM location to place data
dc.l iconPal<<24|iconAddr ; icon palette and plane data location
endm
iconData Text2P_EmeraldHill,Text2P_Zone,VRAM_Plane_A_Name_Table+planeLocH40(2,2),0,$FF0330
iconData Text2P_MysticCave,Text2P_Zone,VRAM_Plane_A_Name_Table+planeLocH40(22,2),5,$FF03A8
iconData Text2P_CasinoNight,Text2P_Zone,VRAM_Plane_A_Name_Table+planeLocH40(2,15),6,$FF03C0
iconData Text2P_Special,Text2P_Stage,VRAM_Plane_A_Name_Table+planeLocH40(22,15),$C,$FF0450
; ---------------------------------------------------------------------------
; Common menu screen subroutine for transferring text to RAM
; ARGUMENTS:
; d0 = starting art tile
; a1 = data source
; a2 = destination
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_8FBE:
MenuScreenTextToRAM:
moveq #0,d1
move.b (a1)+,d1
- move.b (a1)+,d0
move.w d0,(a2)+
dbf d1,-
rts
; End of function MenuScreenTextToRAM
; ===========================================================================
; loc_8FCC:
MenuScreen_Options:
lea (Chunk_Table).l,a1
lea (MapEng_Options).l,a0
move.w #make_art_tile(ArtTile_ArtNem_MenuBox,0,0),d0
bsr.w EniDec
lea (Chunk_Table+$160).l,a1
lea (MapEng_Options).l,a0
move.w #make_art_tile(ArtTile_ArtNem_MenuBox,1,0),d0
bsr.w EniDec
clr.b (Options_menu_box).w
bsr.w OptionScreen_DrawSelected
addq.b #1,(Options_menu_box).w
bsr.w OptionScreen_DrawUnselected
addq.b #1,(Options_menu_box).w
bsr.w OptionScreen_DrawUnselected
clr.b (Options_menu_box).w
clr.b (Level_started_flag).w
clr.w (Anim_Counters).w
lea (Anim_SonicMilesBG).l,a2
jsrto (Dynamic_Normal).l, JmpTo2_Dynamic_Normal
moveq #PalID_Menu,d0
bsr.w PalLoad_ForFade
move.b #MusID_Options,d0
jsrto (PlayMusic).l, JmpTo_PlayMusic
clr.w (Two_player_mode).w
clr.l (Camera_X_pos).w
clr.l (Camera_Y_pos).w
clr.w (Correct_cheat_entries).w
clr.w (Correct_cheat_entries_2).w
move.b #VintID_Menu,(Vint_routine).w
bsr.w WaitForVint
move.w (VDP_Reg1_val).w,d0
ori.b #$40,d0
move.w d0,(VDP_control_port).l
bsr.w Pal_FadeFromBlack
; loc_9060:
OptionScreen_Main:
move.b #VintID_Menu,(Vint_routine).w
bsr.w WaitForVint
move #$2700,sr
bsr.w OptionScreen_DrawUnselected
bsr.w OptionScreen_Controls
bsr.w OptionScreen_DrawSelected
move #$2300,sr
lea (Anim_SonicMilesBG).l,a2
jsrto (Dynamic_Normal).l, JmpTo2_Dynamic_Normal
move.b (Ctrl_1_Press).w,d0
or.b (Ctrl_2_Press).w,d0
andi.b #button_start_mask,d0
bne.s OptionScreen_Select
bra.w OptionScreen_Main
; ===========================================================================
; loc_909A:
OptionScreen_Select:
move.b (Options_menu_box).w,d0
bne.s OptionScreen_Select_Not1P
; Start a single player game
moveq #0,d0
move.w d0,(Two_player_mode).w
move.w d0,(Two_player_mode_copy).w
move.w d0,(Current_ZoneAndAct).w ; emerald_hill_zone_act_1
move.b #GameModeID_Level,(Game_Mode).w ; => Level (Zone play mode)
rts
; ===========================================================================
; loc_90B6:
OptionScreen_Select_Not1P:
subq.b #1,d0
bne.s OptionScreen_Select_Other
; Start a 2P VS game
moveq #1,d0
move.w d0,(Two_player_mode).w
move.w d0,(Two_player_mode_copy).w
move.b #GameModeID_2PLevelSelect,(Game_Mode).w ; => LevelSelectMenu2P
move.b #0,(Current_Zone_2P).w
move.w #0,(Player_mode).w
rts
; ===========================================================================
; loc_90D8:
OptionScreen_Select_Other:
; When pressing START on the sound test option, return to the SEGA screen
move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_90E0:
OptionScreen_Controls:
moveq #0,d2
move.b (Options_menu_box).w,d2
move.b (Ctrl_1_Press).w,d0
or.b (Ctrl_2_Press).w,d0
btst #button_up,d0
beq.s +
subq.b #1,d2
bcc.s +
move.b #2,d2
+
btst #button_down,d0
beq.s +
addq.b #1,d2
cmpi.b #3,d2
blo.s +
moveq #0,d2
+
move.b d2,(Options_menu_box).w
lsl.w #2,d2
move.b OptionScreen_Choices(pc,d2.w),d3 ; number of choices for the option
movea.l OptionScreen_Choices(pc,d2.w),a1 ; location where the choice is stored (in RAM)
move.w (a1),d2
btst #button_left,d0
beq.s +
subq.b #1,d2
bcc.s +
move.b d3,d2
+
btst #button_right,d0
beq.s +
addq.b #1,d2
cmp.b d3,d2
bls.s +
moveq #0,d2
+
btst #button_A,d0
beq.s +
addi.b #$10,d2
cmp.b d3,d2
bls.s +
moveq #0,d2
+
move.w d2,(a1)
cmpi.b #2,(Options_menu_box).w
bne.s + ; rts
andi.w #button_B_mask|button_C_mask,d0
beq.s + ; rts
move.w (Sound_test_sound).w,d0
addi.w #$80,d0
jsrto (PlayMusic).l, JmpTo_PlayMusic
lea (level_select_cheat).l,a0
lea (continues_cheat).l,a2
lea (Level_select_flag).w,a1
moveq #0,d2 ; flag to tell the routine to enable the continues cheat
bsr.w CheckCheats
+
rts
; End of function OptionScreen_Controls
; ===========================================================================
; word_917A:
OptionScreen_Choices:
dc.l (3-1)<<24|(Player_option&$FFFFFF)
dc.l (2-1)<<24|(Two_player_items&$FFFFFF)
dc.l ($80-1)<<24|(Sound_test_sound&$FFFFFF)
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_9186
OptionScreen_DrawSelected:
bsr.w OptionScreen_SelectTextPtr
moveq #0,d1
move.b (Options_menu_box).w,d1
lsl.w #3,d1
lea (OptScrBoxData).l,a3
lea (a3,d1.w),a3
move.w #palette_line_3,d0
lea (Chunk_Table+$30).l,a2
movea.l (a3)+,a1
bsr.w MenuScreenTextToRAM
lea (Chunk_Table+$B6).l,a2
moveq #0,d1
cmpi.b #2,(Options_menu_box).w
beq.s +
move.b (Options_menu_box).w,d1
lsl.w #2,d1
lea OptionScreen_Choices(pc),a1
movea.l (a1,d1.w),a1
move.w (a1),d1
lsl.w #2,d1
+
movea.l (a4,d1.w),a1
bsr.w MenuScreenTextToRAM
cmpi.b #2,(Options_menu_box).w
bne.s +
lea (Chunk_Table+$C2).l,a2
bsr.w OptionScreen_HexDumpSoundTest
+
lea (Chunk_Table).l,a1
move.l (a3)+,d0
moveq #$15,d1
moveq #7,d2
jmpto (PlaneMapToVRAM_H40).l, JmpTo_PlaneMapToVRAM_H40
; ===========================================================================
;loc_91F8
OptionScreen_DrawUnselected:
bsr.w OptionScreen_SelectTextPtr
moveq #0,d1
move.b (Options_menu_box).w,d1
lsl.w #3,d1
lea (OptScrBoxData).l,a3
lea (a3,d1.w),a3
moveq #palette_line_0,d0
lea (Chunk_Table+$190).l,a2
movea.l (a3)+,a1
bsr.w MenuScreenTextToRAM
lea (Chunk_Table+$216).l,a2
moveq #0,d1
cmpi.b #2,(Options_menu_box).w
beq.s +
move.b (Options_menu_box).w,d1
lsl.w #2,d1
lea OptionScreen_Choices(pc),a1
movea.l (a1,d1.w),a1
move.w (a1),d1
lsl.w #2,d1
+
movea.l (a4,d1.w),a1
bsr.w MenuScreenTextToRAM
cmpi.b #2,(Options_menu_box).w
bne.s +
lea (Chunk_Table+$222).l,a2
bsr.w OptionScreen_HexDumpSoundTest
+
lea (Chunk_Table+$160).l,a1
move.l (a3)+,d0
moveq #$15,d1
moveq #7,d2
jmpto (PlaneMapToVRAM_H40).l, JmpTo_PlaneMapToVRAM_H40
; ===========================================================================
;loc_9268
OptionScreen_SelectTextPtr:
lea (off_92D2).l,a4
tst.b (Graphics_Flags).w
bpl.s +
lea (off_92DE).l,a4
+
tst.b (Options_menu_box).w
beq.s +
lea (off_92EA).l,a4
+
cmpi.b #2,(Options_menu_box).w
bne.s + ; rts
lea (off_92F2).l,a4
+
rts
; ===========================================================================
;loc_9296
OptionScreen_HexDumpSoundTest:
move.w (Sound_test_sound).w,d1
move.b d1,d2
lsr.b #4,d1
bsr.s +
move.b d2,d1
+
andi.w #$F,d1
cmpi.b #$A,d1
blo.s +
addi.b #4,d1
+
addi.b #$10,d1
move.b d1,d0
move.w d0,(a2)+
rts
; ===========================================================================
; off_92BA:
OptScrBoxData:
; macro to declare the data for an options screen box
boxData macro txtlabel,vramAddr
dc.l txtlabel, vdpComm(vramAddr,VRAM,WRITE)
endm
boxData TextOptScr_PlayerSelect,VRAM_Plane_A_Name_Table+planeLocH40(9,3)
boxData TextOptScr_VsModeItems,VRAM_Plane_A_Name_Table+planeLocH40(9,11)
boxData TextOptScr_SoundTest,VRAM_Plane_A_Name_Table+planeLocH40(9,19)
off_92D2:
dc.l TextOptScr_SonicAndMiles
dc.l TextOptScr_SonicAlone
dc.l TextOptScr_MilesAlone
off_92DE:
dc.l TextOptScr_SonicAndTails
dc.l TextOptScr_SonicAlone
dc.l TextOptScr_TailsAlone
off_92EA:
dc.l TextOptScr_AllKindsItems
dc.l TextOptScr_TeleportOnly
off_92F2:
dc.l TextOptScr_0
; ===========================================================================
; loc_92F6:
MenuScreen_LevelSelect:
; Load foreground (sans zone icon)
lea (Chunk_Table).l,a1
lea (MapEng_LevSel).l,a0 ; 2 bytes per 8x8 tile, compressed
move.w #make_art_tile(ArtTile_VRAM_Start,0,0),d0
bsr.w EniDec
lea (Chunk_Table).l,a1
move.l #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE),d0
moveq #$27,d1
moveq #$1B,d2 ; 40x28 = whole screen
jsrto (PlaneMapToVRAM_H40).l, JmpTo_PlaneMapToVRAM_H40 ; display patterns
; Draw sound test number
moveq #palette_line_0,d3
bsr.w LevelSelect_DrawSoundNumber
; Load zone icon
lea (Chunk_Table+$8C0).l,a1
lea (MapEng_LevSelIcon).l,a0
move.w #make_art_tile(ArtTile_ArtNem_LevelSelectPics,0,0),d0
bsr.w EniDec
bsr.w LevelSelect_DrawIcon
clr.w (Player_mode).w
clr.w (Results_Screen_2P).w ; VsRSID_Act
clr.b (Level_started_flag).w
clr.w (Anim_Counters).w
; Animate background (loaded back in MenuScreen)
lea (Anim_SonicMilesBG).l,a2
jsrto (Dynamic_Normal).l, JmpTo2_Dynamic_Normal ; background
moveq #PalID_Menu,d0
bsr.w PalLoad_ForFade
lea (Normal_palette_line3).w,a1
lea (Target_palette_line3).w,a2
moveq #bytesToLcnt(palette_line_size),d1
- move.l (a1),(a2)+
clr.l (a1)+
dbf d1,-
move.b #MusID_Options,d0
jsrto (PlayMusic).l, JmpTo_PlayMusic
move.w #$707,(Demo_Time_left).w
clr.w (Two_player_mode).w
clr.l (Camera_X_pos).w
clr.l (Camera_Y_pos).w
clr.w (Correct_cheat_entries).w
clr.w (Correct_cheat_entries_2).w
move.b #VintID_Menu,(Vint_routine).w
bsr.w WaitForVint
move.w (VDP_Reg1_val).w,d0
ori.b #$40,d0
move.w d0,(VDP_control_port).l
bsr.w Pal_FadeFromBlack
;loc_93AC:
LevelSelect_Main: ; routine running during level select
move.b #VintID_Menu,(Vint_routine).w
bsr.w WaitForVint
move #$2700,sr
moveq #palette_line_0-palette_line_0,d3 ; palette line << 13
bsr.w LevelSelect_MarkFields ; unmark fields
bsr.w LevSelControls ; possible change selected fields
move.w #palette_line_3-palette_line_0,d3 ; palette line << 13
bsr.w LevelSelect_MarkFields ; mark fields
bsr.w LevelSelect_DrawIcon
move #$2300,sr
lea (Anim_SonicMilesBG).l,a2
jsrto (Dynamic_Normal).l, JmpTo2_Dynamic_Normal
move.b (Ctrl_1_Press).w,d0
or.b (Ctrl_2_Press).w,d0
andi.b #button_start_mask,d0 ; start pressed?
bne.s LevelSelect_PressStart ; yes
bra.w LevelSelect_Main ; no
; ===========================================================================
;loc_93F0:
LevelSelect_PressStart:
move.w (Level_select_zone).w,d0
add.w d0,d0
move.w LevelSelect_Order(pc,d0.w),d0
bmi.w LevelSelect_Return ; sound test
cmpi.w #$4000,d0
bne.s LevelSelect_StartZone
;LevelSelect_SpecialStage:
move.b #GameModeID_SpecialStage,(Game_Mode).w ; => SpecialStage
clr.w (Current_ZoneAndAct).w
move.b #3,(Life_count).w
move.b #3,(Life_count_2P).w
moveq #0,d0
move.w d0,(Ring_count).w
move.l d0,(Timer).w
move.l d0,(Score).w
move.w d0,(Ring_count_2P).w
move.l d0,(Timer_2P).w
move.l d0,(Score_2P).w
move.l #5000,(Next_Extra_life_score).w
move.l #5000,(Next_Extra_life_score_2P).w
move.w (Player_option).w,(Player_mode).w
rts
; ===========================================================================
;loc_944C:
LevelSelect_Return:
move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen
rts
; ===========================================================================
; -----------------------------------------------------------------------------
; Level Select Level Order
; One entry per item in the level select menu. Just set the value for the item
; you want to link to the level/act number of the level you want to load when
; the player selects that item.
; -----------------------------------------------------------------------------
;Misc_9454:
LevelSelect_Order:
dc.w emerald_hill_zone_act_1
dc.w emerald_hill_zone_act_2 ; 1
dc.w chemical_plant_zone_act_1 ; 2
dc.w chemical_plant_zone_act_2 ; 3
dc.w aquatic_ruin_zone_act_1 ; 4
dc.w aquatic_ruin_zone_act_2 ; 5
dc.w casino_night_zone_act_1 ; 6
dc.w casino_night_zone_act_2 ; 7
dc.w hill_top_zone_act_1 ; 8
dc.w hill_top_zone_act_2 ; 9
dc.w mystic_cave_zone_act_1 ; 10
dc.w mystic_cave_zone_act_2 ; 11
dc.w oil_ocean_zone_act_1 ; 12
dc.w oil_ocean_zone_act_2 ; 13
dc.w metropolis_zone_act_1 ; 14
dc.w metropolis_zone_act_2 ; 15
dc.w metropolis_zone_act_3 ; 16
dc.w sky_chase_zone_act_1 ; 17
dc.w wing_fortress_zone_act_1 ; 18
dc.w death_egg_zone_act_1 ; 19
dc.w $4000 ; 20 - special stage
dc.w $FFFF ; 21 - sound test
; ===========================================================================
;loc_9480:
LevelSelect_StartZone:
andi.w #$3FFF,d0
move.w d0,(Current_ZoneAndAct).w
move.b #GameModeID_Level,(Game_Mode).w ; => Level (Zone play mode)
move.b #3,(Life_count).w
move.b #3,(Life_count_2P).w
moveq #0,d0
move.w d0,(Ring_count).w
move.l d0,(Timer).w
move.l d0,(Score).w
move.w d0,(Ring_count_2P).w
move.l d0,(Timer_2P).w
move.l d0,(Score_2P).w
move.b d0,(Continue_count).w
move.l #5000,(Next_Extra_life_score).w
move.l #5000,(Next_Extra_life_score_2P).w
move.b #MusID_FadeOut,d0
jsrto (PlaySound).l, JmpTo_PlaySound
moveq #0,d0
move.w d0,(Two_player_mode_copy).w
move.w d0,(Two_player_mode).w
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Change what you're selecting in the level select
; ---------------------------------------------------------------------------
; loc_94DC:
LevSelControls:
move.b (Ctrl_1_Press).w,d1
andi.b #button_up_mask|button_down_mask,d1
bne.s + ; up/down pressed
subq.w #1,(LevSel_HoldTimer).w
bpl.s LevSelControls_CheckLR
+
move.w #$B,(LevSel_HoldTimer).w
move.b (Ctrl_1_Held).w,d1
andi.b #button_up_mask|button_down_mask,d1
beq.s LevSelControls_CheckLR ; up/down not pressed, check for left & right
move.w (Level_select_zone).w,d0
btst #button_up,d1
beq.s +
subq.w #1,d0 ; decrease by 1
bcc.s + ; >= 0?
moveq #$15,d0 ; set to $15
+
btst #button_down,d1
beq.s +
addq.w #1,d0 ; yes, add 1
cmpi.w #$16,d0
blo.s + ; smaller than $16?
moveq #0,d0 ; if not, set to 0
+
move.w d0,(Level_select_zone).w
rts
; ===========================================================================
; loc_9522:
LevSelControls_CheckLR:
cmpi.w #$15,(Level_select_zone).w ; are we in the sound test?
bne.s LevSelControls_SwitchSide ; no
move.w (Sound_test_sound).w,d0
move.b (Ctrl_1_Press).w,d1
btst #button_left,d1
beq.s +
subq.b #1,d0
bcc.s +
moveq #$7F,d0
+
btst #button_right,d1
beq.s +
addq.b #1,d0
cmpi.w #$80,d0
blo.s +
moveq #0,d0
+
btst #button_A,d1
beq.s +
addi.b #$10,d0
andi.b #$7F,d0
+
move.w d0,(Sound_test_sound).w
andi.w #button_B_mask|button_C_mask,d1
beq.s + ; rts
move.w (Sound_test_sound).w,d0
addi.w #$80,d0
jsrto (PlayMusic).l, JmpTo_PlayMusic
lea (debug_cheat).l,a0
lea (super_sonic_cheat).l,a2
lea (Debug_options_flag).w,a1
moveq #1,d2 ; flag to tell the routine to enable the Super Sonic cheat
bsr.w CheckCheats
+
rts
; ===========================================================================
; loc_958A:
LevSelControls_SwitchSide: ; not in soundtest, not up/down pressed
move.b (Ctrl_1_Press).w,d1
andi.b #button_left_mask|button_right_mask,d1
beq.s + ; no direction key pressed
move.w (Level_select_zone).w,d0 ; left or right pressed
move.b LevelSelect_SwitchTable(pc,d0.w),d0 ; set selected zone according to table
move.w d0,(Level_select_zone).w
+
rts
; ===========================================================================
;byte_95A2:
LevelSelect_SwitchTable:
dc.b $E
dc.b $F ; 1
dc.b $11 ; 2
dc.b $11 ; 3
dc.b $12 ; 4
dc.b $12 ; 5
dc.b $13 ; 6
dc.b $13 ; 7
dc.b $14 ; 8
dc.b $14 ; 9
dc.b $15 ; 10
dc.b $15 ; 11
dc.b $C ; 12
dc.b $D ; 13
dc.b 0 ; 14
dc.b 1 ; 15
dc.b 1 ; 16
dc.b 2 ; 17
dc.b 4 ; 18
dc.b 6 ; 19
dc.b 8 ; 20
dc.b $A ; 21
even
; ===========================================================================
;loc_95B8:
LevelSelect_MarkFields:
lea (Chunk_Table).l,a4
lea (LevSel_MarkTable).l,a5
lea (VDP_data_port).l,a6
moveq #0,d0
move.w (Level_select_zone).w,d0
lsl.w #2,d0
lea (a5,d0.w),a3
moveq #0,d0
move.b (a3),d0
mulu.w #$50,d0
moveq #0,d1
move.b 1(a3),d1
add.w d1,d0
lea (a4,d0.w),a1
moveq #0,d1
move.b (a3),d1
lsl.w #7,d1
add.b 1(a3),d1
addi.w #VRAM_Plane_A_Name_Table,d1
lsl.l #2,d1
lsr.w #2,d1
ori.w #vdpComm($0000,VRAM,WRITE)>>16,d1
swap d1
move.l d1,4(a6)
moveq #$D,d2
- move.w (a1)+,d0
add.w d3,d0
move.w d0,(a6)
dbf d2,-
addq.w #2,a3
moveq #0,d0
move.b (a3),d0
beq.s +
mulu.w #$50,d0
moveq #0,d1
move.b 1(a3),d1
add.w d1,d0
lea (a4,d0.w),a1
moveq #0,d1
move.b (a3),d1
lsl.w #7,d1
add.b 1(a3),d1
addi.w #VRAM_Plane_A_Name_Table,d1
lsl.l #2,d1
lsr.w #2,d1
ori.w #vdpComm($0000,VRAM,WRITE)>>16,d1
swap d1
move.l d1,4(a6)
move.w (a1)+,d0
add.w d3,d0
move.w d0,(a6)
+
cmpi.w #$15,(Level_select_zone).w
bne.s + ; rts
bsr.w LevelSelect_DrawSoundNumber
+
rts
; ===========================================================================
;loc_965A:
LevelSelect_DrawSoundNumber:
move.l #vdpComm(VRAM_Plane_A_Name_Table+planeLocH40(34,18),VRAM,WRITE),(VDP_control_port).l
move.w (Sound_test_sound).w,d0
move.b d0,d2
lsr.b #4,d0
bsr.s +
move.b d2,d0
+
andi.w #$F,d0
cmpi.b #$A,d0
blo.s +
addi.b #4,d0
+
addi.b #$10,d0
add.w d3,d0
move.w d0,(a6)
rts
; ===========================================================================
;loc_9688:
LevelSelect_DrawIcon:
move.w (Level_select_zone).w,d0
lea (LevSel_IconTable).l,a3
lea (a3,d0.w),a3
lea (Chunk_Table+$8C0).l,a1
moveq #0,d0
move.b (a3),d0
lsl.w #3,d0
move.w d0,d1
add.w d0,d0
add.w d1,d0
lea (a1,d0.w),a1
move.l #vdpComm(VRAM_Plane_A_Name_Table+planeLocH40(27,22),VRAM,WRITE),d0
moveq #3,d1
moveq #2,d2
jsrto (PlaneMapToVRAM_H40).l, JmpTo_PlaneMapToVRAM_H40
lea (Pal_LevelIcons).l,a1
moveq #0,d0
move.b (a3),d0
lsl.w #5,d0
lea (a1,d0.w),a1
lea (Normal_palette_line3).w,a2
moveq #bytesToLcnt(palette_line_size),d1
- move.l (a1)+,(a2)+
dbf d1,-
rts
; ===========================================================================
;byte_96D8
LevSel_IconTable:
dc.b 0,0 ;0 EHZ
dc.b 7,7 ;2 CPZ
dc.b 8,8 ;4 ARZ
dc.b 6,6 ;6 CNZ
dc.b 2,2 ;8 HTZ
dc.b 5,5 ;$A MCZ
dc.b 4,4 ;$C OOZ
dc.b 1,1,1 ;$E MTZ
dc.b 9 ;$11 SCZ
dc.b $A ;$12 WFZ
dc.b $B ;$13 DEZ
dc.b $C ;$14 Special Stage
dc.b $E ;$15 Sound Test
even
;byte_96EE:
LevSel_MarkTable: ; 4 bytes per level select entry
; line primary, 2*column ($E fields), line secondary, 2*column secondary (1 field)
dc.b 3, 6, 3,$24 ;0
dc.b 3, 6, 4,$24
dc.b 6, 6, 6,$24
dc.b 6, 6, 7,$24
dc.b 9, 6, 9,$24 ;4
dc.b 9, 6, $A,$24
dc.b $C, 6, $C,$24
dc.b $C, 6, $D,$24
dc.b $F, 6, $F,$24 ;8
dc.b $F, 6,$10,$24
dc.b $12, 6,$12,$24
dc.b $12, 6,$13,$24
dc.b $15, 6,$15,$24 ;$C
dc.b $15, 6,$16,$24
; --- second column ---
dc.b 3,$2C, 3,$48
dc.b 3,$2C, 4,$48
dc.b 3,$2C, 5,$48 ;$10
dc.b 6,$2C, 0, 0
dc.b 9,$2C, 0, 0
dc.b $C,$2C, 0, 0
dc.b $F,$2C, 0, 0 ;$14
dc.b $12,$2C,$12,$48
; ===========================================================================
; loc_9746:
CheckCheats: ; This is called from 2 places: the options screen and the level select screen
move.w (Correct_cheat_entries).w,d0 ; Get the number of correct sound IDs entered so far
adda.w d0,a0 ; Skip to the next entry
move.w (Sound_test_sound).w,d0 ; Get the current sound test sound
cmp.b (a0),d0 ; Compare it to the cheat
bne.s + ; If they're different, branch
addq.w #1,(Correct_cheat_entries).w ; Add 1 to the number of correct entries
tst.b 1(a0) ; Is the next entry 0?
bne.s ++ ; If not, branch
move.w #$101,(a1) ; Enable the cheat
move.b #SndID_Ring,d0 ; Play the ring sound
jsrto (PlaySound).l, JmpTo_PlaySound
+
move.w #0,(Correct_cheat_entries).w ; Clear the number of correct entries
+
move.w (Correct_cheat_entries_2).w,d0 ; Do the same procedure with the other cheat
adda.w d0,a2
move.w (Sound_test_sound).w,d0
cmp.b (a2),d0
bne.s ++
addq.w #1,(Correct_cheat_entries_2).w
tst.b 1(a2)
bne.s +++ ; rts
tst.w d2 ; Test this to determine which cheat to enable
bne.s + ; If not 0, branch
move.b #$F,(Continue_count).w ; Give 15 continues
; The next line causes the bug where the OOZ music plays until reset.
; Remove "&$7F" to fix the bug.
move.b #SndID_ContinueJingle&$7F,d0 ; Play the continue jingle
jsrto (PlayMusic).l, JmpTo_PlayMusic
bra.s ++
; ===========================================================================
+
move.w #7,(Got_Emerald).w ; Give 7 emeralds to the player
move.b #MusID_Emerald,d0 ; Play the emerald jingle
jsrto (PlayMusic).l, JmpTo_PlayMusic
+
move.w #0,(Correct_cheat_entries_2).w ; Clear the number of correct entries
+
rts
; ===========================================================================
level_select_cheat: dc.b $19, $65, 9, $17, 0 ; 17th September 1965, Yuji Naka's birthdate
rev02even
; byte_97B7
continues_cheat: dc.b 1, 1, 2, 4, 0 ; 24th November, Sonic 2's release date in the EU and US: "Sonic 2sday"
rev02even
debug_cheat: dc.b 1, 9, 9, 2, 1, 1, 2, 4, 0 ; 24th November 1992, Sonic 2's release date in the EU and US: "Sonic 2sday"
rev02even
; byte_97C5
super_sonic_cheat: dc.b 4, 1, 2, 6, 0 ; Book of Genesis, 41:26
rev02even
; set the character set for menu text
charset '@',"\27\30\31\32\33\34\35\36\37\38\39\40\41\42\43\44\45\46\47\48\49\50\51\52\53\54\55"
charset '0',"\16\17\18\19\20\21\22\23\24\25"
charset '*',$1A
charset ':',$1C
charset '.',$1D
charset ' ',0
; options screen menu text
TextOptScr_PlayerSelect: menutxt "* PLAYER SELECT *" ; byte_97CA:
TextOptScr_SonicAndMiles: menutxt "SONIC AND MILES" ; byte_97DC:
TextOptScr_SonicAndTails: menutxt "SONIC AND TAILS" ; byte_97EC:
TextOptScr_SonicAlone: menutxt "SONIC ALONE " ; byte_97FC:
TextOptScr_MilesAlone: menutxt "MILES ALONE " ; byte_980C:
TextOptScr_TailsAlone: menutxt "TAILS ALONE " ; byte_981C:
TextOptScr_VsModeItems: menutxt "* VS MODE ITEMS *" ; byte_982C:
TextOptScr_AllKindsItems: menutxt "ALL KINDS ITEMS" ; byte_983E:
TextOptScr_TeleportOnly: menutxt "TELEPORT ONLY " ; byte_984E:
TextOptScr_SoundTest: menutxt "* SOUND TEST *" ; byte_985E:
TextOptScr_0: menutxt " 00 " ; byte_9870:
charset ; reset character set
; level select picture palettes
; byte_9880:
Pal_LevelIcons: BINCLUDE "art/palettes/Level Select Icons.bin"
; 2-player level select screen mappings (Enigma compressed)
; byte_9A60:
MapEng_LevSel2P: BINCLUDE "mappings/misc/Level Select 2P.bin"
; options screen mappings (Enigma compressed)
; byte_9AB2:
MapEng_Options: BINCLUDE "mappings/misc/Options Screen.bin"
; level select screen mappings (Enigma compressed)
; byte_9ADE:
MapEng_LevSel: BINCLUDE "mappings/misc/Level Select.bin"
; 1P and 2P level select icon mappings (Enigma compressed)
; byte_9C32:
MapEng_LevSelIcon: BINCLUDE "mappings/misc/Level Select Icons.bin"
if ~~removeJmpTos
JmpTo_PlaySound
jmp (PlaySound).l
JmpTo_PlayMusic
jmp (PlayMusic).l
; loc_9C70: JmpTo_PlaneMapToVRAM
JmpTo_PlaneMapToVRAM_H40
jmp (PlaneMapToVRAM_H40).l
JmpTo2_Dynamic_Normal
jmp (Dynamic_Normal).l
align 4
endif
; ===========================================================================
; loc_9C7C:
EndingSequence:
clearRAM EndSeq_Object_RAM,EndSeq_Object_RAM_End
clearRAM Misc_Variables,Misc_Variables_End
clearRAM Camera_RAM,Camera_RAM_End
move #$2700,sr
move.w (VDP_Reg1_val).w,d0
andi.b #$BF,d0
move.w d0,(VDP_control_port).l
stopZ80
dmaFillVRAM 0,VRAM_Plane_A_Name_Table,VRAM_Plane_Table_Size ; clear Plane A pattern name table
clr.l (Vscroll_Factor).w
clr.l (unk_F61A).w
startZ80
lea (VDP_control_port).l,a6
move.w #$8B03,(a6) ; EXT-INT disabled, V scroll by screen, H scroll by line
move.w #$8200|(VRAM_EndSeq_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000
move.w #$8400|(VRAM_EndSeq_Plane_B_Name_Table1/$2000),(a6) ; PNT B base: $E000
move.w #$8500|(VRAM_Sprite_Attribute_Table/$200),(a6) ; Sprite attribute table base: $F800
move.w #$9001,(a6) ; Scroll table size: 64x32
move.w #$8004,(a6) ; H-INT disabled
move.w #$8720,(a6) ; Background palette/color: 2/0
move.w #$8ADF,(Hint_counter_reserve).w ; H-INT every 224th scanline
move.w (Hint_counter_reserve).w,(a6)
clr.b (Super_Sonic_flag).w
cmpi.b #7,(Emerald_count).w
bne.s +
cmpi.w #2,(Player_mode).w
beq.s +
st (Super_Sonic_flag).w
move.b #-1,(Super_Sonic_palette).w
move.b #$F,(Palette_timer).w
move.w #$30,(Palette_frame).w
+
moveq #0,d0
cmpi.w #2,(Player_mode).w
beq.s +
tst.b (Super_Sonic_flag).w
bne.s ++
bra.w +++
; ===========================================================================
+
addq.w #2,d0
+
addq.w #2,d0
+
move.w d0,(Ending_Routine).w
bsr.w EndingSequence_LoadCharacterArt
bsr.w EndingSequence_LoadFlickyArt
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_EndingFinalTornado),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_EndingFinalTornado).l,a0
jsrto (NemDec).l, JmpTo_NemDec
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_EndingPics),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_EndingPics).l,a0
jsrto (NemDec).l, JmpTo_NemDec
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_EndingMiniTornado),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_EndingMiniTornado).l,a0
jsrto (NemDec).l, JmpTo_NemDec
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Tornado),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_Tornado).l,a0
jsrto (NemDec).l, JmpTo_NemDec
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Clouds),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_Clouds).l,a0
jsrto (NemDec).l, JmpTo_NemDec
move.w #death_egg_zone_act_1,(Current_ZoneAndAct).w
move #$2300,sr
moveq #MusID_Ending,d0
jsrto (PlayMusic).l, JmpTo2_PlayMusic
move.l #$EEE0EEE,d1
lea (Normal_palette).w,a1
moveq #bytesToLcnt(palette_line_size*4),d0
- move.l d1,(a1)+
dbf d0,-
lea (Pal_AC7E).l,a1
lea (Target_palette).w,a2
moveq #bytesToLcnt(palette_line_size*4),d0
- move.l (a1)+,(a2)+
dbf d0,-
clr.b (Screen_Shaking_Flag).w
moveq #0,d0
move.w d0,(Debug_placement_mode).w
move.w d0,(Level_Inactive_flag).w
move.w d0,(Timer_frames).w
move.w d0,(Camera_X_pos).w
move.w d0,(Camera_Y_pos).w
move.w d0,(Camera_X_pos_copy).w
move.w d0,(Camera_Y_pos_copy).w
move.w d0,(Camera_BG_X_pos).w
move.w #$C8,(Camera_BG_Y_pos).w
move.l d0,(Vscroll_Factor).w
move.b d0,(Horiz_block_crossed_flag_BG).w
move.b d0,(Verti_block_crossed_flag_BG).w
move.w d0,(Ending_VInt_Subrout).w
move.w d0,(Credits_Trigger).w
; Bug: The '+4' shouldn't be here; clearRAM accidentally clears an additional 4 bytes
clearRAM Horiz_Scroll_Buf,Horiz_Scroll_Buf_End+4
move.w #$7FFF,(PalCycle_Timer).w
lea (CutScene).w,a1
move.b #ObjID_CutScene,id(a1) ; load objCA (end of game cutscene) at $FFFFB100
move.b #6,routine(a1)
move.w #$60,objoff_3C(a1)
move.w #1,objoff_30(a1)
cmpi.w #4,(Ending_Routine).w
bne.s +
move.w #$10,objoff_2E(a1)
move.w #$100,objoff_3C(a1)
+
move.b #VintID_Ending,(Vint_routine).w
bsr.w WaitForVint
move.w (VDP_Reg1_val).w,d0
ori.b #$40,d0
move.w d0,(VDP_control_port).l
-
move.b #VintID_Ending,(Vint_routine).w
bsr.w WaitForVint
addq.w #1,(Timer_frames).w
jsr (RandomNumber).l
jsr (RunObjects).l
jsr (BuildSprites).l
tst.b (Ending_PalCycle_flag).w
beq.s +
jsrto (PalCycle_Load).l, JmpTo_PalCycle_Load
+
bsr.w EndgameCredits
tst.w (Level_Inactive_flag).w
beq.w -
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_9EF4
EndgameCredits:
tst.b (Credits_Trigger).w
beq.w +++ ; rts
bsr.w Pal_FadeToBlack
lea (VDP_control_port).l,a6
move.w #$8004,(a6) ; H-INT disabled
move.w #$8200|(VRAM_EndSeq_Plane_A_Name_Table/$400),(a6) ; PNT A base: $C000
move.w #$8400|(VRAM_EndSeq_Plane_B_Name_Table1/$2000),(a6) ; PNT B base: $E000
move.w #$9001,(a6) ; Scroll table size: 64x32
move.w #$9200,(a6) ; Disable window
move.w #$8B03,(a6) ; EXT-INT disabled, V scroll by screen, H scroll by line
move.w #$8700,(a6) ; Background palette/color: 0/0
clr.b (Water_fullscreen_flag).w
move.w #$8C81,(a6) ; H res 40 cells, no interlace, S/H disabled
jsrto (ClearScreen).l, JmpTo_ClearScreen
clearRAM Sprite_Table_Input,Sprite_Table_Input_End
clearRAM EndSeq_Object_RAM,EndSeq_Object_RAM_End
clearRAM Misc_Variables,Misc_Variables_End
clearRAM Camera_RAM,Camera_RAM_End
clr.b (Screen_Shaking_Flag).w
moveq #0,d0
move.w d0,(Level_Inactive_flag).w
move.w d0,(Timer_frames).w
move.w d0,(Camera_X_pos).w
move.w d0,(Camera_Y_pos).w
move.w d0,(Camera_X_pos_copy).w
move.w d0,(Camera_Y_pos_copy).w
move.w d0,(Camera_BG_X_pos).w
move.w d0,(Camera_BG_Y_pos).w
move.l d0,(Vscroll_Factor).w
move.b d0,(Horiz_block_crossed_flag_BG).w
move.b d0,(Verti_block_crossed_flag_BG).w
move.w d0,(Ending_VInt_Subrout).w
move.w d0,(Credits_Trigger).w
; Bug: The '+4' shouldn't be here; clearRAM accidentally clears an additional 4 bytes
clearRAM Horiz_Scroll_Buf,Horiz_Scroll_Buf_End+4
moveq #MusID_Credits,d0
jsrto (PlaySound).l, JmpTo2_PlaySound
clr.w (Target_palette).w
move.w #$EEE,(Target_palette+$C).w
move.w #$EE,(Target_palette_line2+$C).w
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_CreditText_CredScr),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_CreditText).l,a0
jsrto (NemDec).l, JmpTo_NemDec
clr.w (CreditsScreenIndex).w
-
jsrto (ClearScreen).l, JmpTo_ClearScreen
bsr.w ShowCreditsScreen
bsr.w Pal_FadeFromBlack
; Here's how to calculate new duration values for the below instructions.
; Each slide of the credits is displayed for $18E frames at 60 FPS, or $144 frames at 50 FPS.
; We also need to take into account how many frames the fade-in/fade-out take: which is $16 each.
; Also, there are 21 slides to display.
; That said, by doing '($18E+$16+$16)*21', we get the total number of frames it takes until
; the credits reach the Sonic 2 splash (which is technically not an actual slide in the credits).
; Dividing this by 60 will give us how many seconds it takes. The result being 154.7.
; Doing the same for 50 FPS, by dividing the result of '($144+$16+$16)*21' by 50, will give us 154.56.
; Now that we have the time it should take for the credits to end, we can adjust the calculation to account
; for any slides we may have added. For example, if you added a slide, bringing the total to 22,
; performing '((154.7*60)/22)-($16+$16)' will give you the new value to put in the 'move.w' instruction below.
move.w #$18E,d0
btst #6,(Graphics_Flags).w
beq.s +
move.w #$144,d0
/ move.b #VintID_Ending,(Vint_routine).w
bsr.w WaitForVint
dbf d0,-
bsr.w Pal_FadeToBlack
lea (off_B2CA).l,a1
addq.w #1,(CreditsScreenIndex).w
move.w (CreditsScreenIndex).w,d0
lsl.w #2,d0
move.l (a1,d0.w),d0
bpl.s --
bsr.w Pal_FadeToBlack
jsrto (ClearScreen).l, JmpTo_ClearScreen
move.l #vdpComm($0000,VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_EndingTitle).l,a0
jsrto (NemDec).l, JmpTo_NemDec
lea (MapEng_EndGameLogo).l,a0
lea (Chunk_Table).l,a1
move.w #0,d0
jsrto (EniDec).l, JmpTo_EniDec
lea (Chunk_Table).l,a1
move.l #vdpComm(VRAM_Plane_A_Name_Table+planeLocH40(12,11),VRAM,WRITE),d0
moveq #$F,d1
moveq #5,d2
jsrto (PlaneMapToVRAM_H40).l, JmpTo2_PlaneMapToVRAM_H40
clr.w (CreditsScreenIndex).w
bsr.w EndgameLogoFlash
move.w #$3B,d0
- move.b #VintID_Ending,(Vint_routine).w
bsr.w WaitForVint
dbf d0,-
move.w #$257,d6
- move.b #VintID_Ending,(Vint_routine).w
bsr.w WaitForVint
addq.w #1,(CreditsScreenIndex).w
bsr.w EndgameLogoFlash
cmpi.w #$5E,(CreditsScreenIndex).w
blo.s -
move.b (Ctrl_1_Press).w,d1
andi.b #button_B_mask|button_C_mask|button_A_mask|button_start_mask,d1
bne.s +
dbf d6,-
+
st (Level_Inactive_flag).w
move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen
/
rts
; End of function sub_9EF4
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_A0C0
EndgameLogoFlash:
lea (Normal_palette+2).w,a2
move.w (CreditsScreenIndex).w,d0
cmpi.w #$24,d0
bhs.s -
btst #0,d0
bne.s -
lsr.w #1,d0
move.b byte_A0EC(pc,d0.w),d0
mulu.w #$18,d0
lea pal_A0FE(pc,d0.w),a1
moveq #5,d0
- move.l (a1)+,(a2)+
dbf d0,-
rts
; End of function EndgameLogoFlash
; ===========================================================================
byte_A0EC:
dc.b 0
dc.b 1 ; 1
dc.b 2 ; 2
dc.b 3 ; 3
dc.b 4 ; 4
dc.b 3 ; 5
dc.b 2 ; 6
dc.b 1 ; 7
dc.b 0 ; 8
dc.b 5 ; 9
dc.b 6 ; 10
dc.b 7 ; 11
dc.b 8 ; 12
dc.b 7 ; 13
dc.b 6 ; 14
dc.b 5 ; 15
dc.b 0 ; 16
dc.b 0 ; 17
; palette cycle for the end-of-game logo
pal_A0FE: BINCLUDE "art/palettes/Ending Cycle.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object CA - Cut scene at end of game
; ----------------------------------------------------------------------------
; Sprite_A1D6:
ObjCA:
addq.w #1,objoff_32(a0)
cmpi.w #4,(Ending_Routine).w
beq.s +
cmpi.w #2,(Ending_Routine).w
bne.s +
st (Super_Sonic_flag).w
move.w #$100,(Ring_count).w
move.b #-1,(Super_Sonic_palette).w
+
moveq #0,d0
move.b routine(a0),d0
move.w ObjCA_Index(pc,d0.w),d1
jmp ObjCA_Index(pc,d1.w)
; ===========================================================================
; off_A208:
ObjCA_Index: offsetTable
offsetTableEntry.w ObjCA_Init ; 0
offsetTableEntry.w loc_A240 ; 2
offsetTableEntry.w loc_A24E ; 4
offsetTableEntry.w loc_A240 ; 6
offsetTableEntry.w loc_A256 ; 8
offsetTableEntry.w loc_A30A ; $A
offsetTableEntry.w loc_A34C ; $C
offsetTableEntry.w loc_A38E ; $E
; ===========================================================================
; loc_A218:
ObjCA_Init:
moveq #4,d0
move.w #$180,d1
btst #6,(Graphics_Flags).w
beq.s sub_A22A
move.w #$100,d1
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_A22A:
lea (EndSeqPaletteChanger).w,a1
move.b #ObjID_TtlScrPalChanger,id(a1) ; load objC9 (palette change handler) at $FFFFB0C0
move.b d0,subtype(a1)
addq.b #2,routine(a0)
move.w d1,objoff_3C(a0)
rts
; End of function sub_A22A
; ===========================================================================
loc_A240:
subq.w #1,objoff_3C(a0)
bmi.s +
rts
; ===========================================================================
+
addq.b #2,routine(a0)
rts
; ===========================================================================
loc_A24E:
moveq #6,d0
move.w #$80,d1
bra.s sub_A22A
; ===========================================================================
loc_A256:
move.w objoff_2E(a0),d0
cmpi.w #$10,d0
bhs.s +
addq.w #4,objoff_2E(a0)
clr.b routine(a0)
move.l a0,-(sp)
movea.l off_A29C(pc,d0.w),a0
lea (Chunk_Table).l,a1
move.w #make_art_tile(ArtTile_ArtNem_EndingPics,0,0),d0
jsrto (EniDec).l, JmpTo_EniDec
move #$2700,sr
lea (Chunk_Table).l,a1
move.l #vdpComm(VRAM_Plane_A_Name_Table + planeLocH40(14,8),VRAM,WRITE),d0
moveq #$B,d1
moveq #8,d2
jsrto (PlaneMapToVRAM_H40).l, JmpTo2_PlaneMapToVRAM_H40
move #$2300,sr
movea.l (sp)+,a0 ; load 0bj address
rts
; ===========================================================================
off_A29C:
dc.l MapEng_Ending1
dc.l MapEng_Ending2
dc.l MapEng_Ending3
dc.l MapEng_Ending4
; ===========================================================================
+
move.w #2,(Ending_VInt_Subrout).w
st (Control_Locked).w
st (Ending_PalCycle_flag).w
lea (MainCharacter).w,a1 ; a1=character
move.w (Ending_Routine).w,d0
move.w ObjCA_State5_States(pc,d0.w),d0
jsr ObjCA_State5_States(pc,d0.w)
move.w #$80,d1
bsr.w sub_A22A
move.w #$40,objoff_3C(a0)
rts
; ===========================================================================
ObjCA_State5_States: offsetTable
offsetTableEntry.w loc_A2E0 ; 0
offsetTableEntry.w loc_A2EE ; 2
offsetTableEntry.w loc_A2F2 ; 4
; ===========================================================================
loc_A2E0:
moveq #8,d0
-
move.b #ObjID_Sonic,id(a1) ; load Sonic object
move.b #$81,obj_control(a1)
rts
; ===========================================================================
loc_A2EE:
moveq #$C,d0
bra.s -
; ===========================================================================
loc_A2F2:
moveq #$E,d0
move.b #ObjID_Tails,id(a1) ; load Tails object
move.b #$81,obj_control(a1)
move.b #ObjID_TailsTails,(Tails_Tails_Cutscene+id).w ; load Obj05 (Tails' tails) at $FFFFB080
move.w a1,(Tails_Tails_Cutscene+parent).w
rts
; ===========================================================================
loc_A30A:
subq.w #1,objoff_3C(a0)
bpl.s +
moveq #$A,d0
move.w #$80,d1
bsr.w sub_A22A
move.w #$C0,objoff_3C(a0)
+
lea (MainCharacter).w,a1 ; a1=character
move.b #AniIDSonAni_Float2,anim(a1)
move.w #$A0,x_pos(a1)
move.w #$50,y_pos(a1)
cmpi.w #2,(Ending_Routine).w
bne.s + ; rts
move.b #AniIDSonAni_Walk,anim(a1)
move.w #$1000,inertia(a1)
+
rts
; ===========================================================================
loc_A34C:
subq.w #1,objoff_3C(a0)
bmi.s +
moveq #0,d4
moveq #0,d5
move.w #0,(Camera_X_pos_diff).w
move.w #$100,(Camera_Y_pos_diff).w
bra.w SwScrl_DEZ
; ===========================================================================
+
addq.b #2,routine(a0)
move.w #$100,objoff_3C(a0)
cmpi.w #4,(Ending_Routine).w
bne.s return_A38C
move.w #$880,objoff_3C(a0)
btst #6,(Graphics_Flags).w
beq.s return_A38C
move.w #$660,objoff_3C(a0)
return_A38C:
rts
; ===========================================================================
loc_A38E:
btst #6,(Graphics_Flags).w
beq.s +
cmpi.w #$E40,objoff_32(a0)
beq.s loc_A3BE
bra.w ++
; ===========================================================================
+
cmpi.w #$1140,objoff_32(a0)
beq.s loc_A3BE
+
subq.w #1,objoff_3C(a0)
bne.s +
lea (word_AD62).l,a2
jsrto (LoadChildObject).l, JmpTo_LoadChildObject
+
bra.w loc_AB9C
; ===========================================================================
loc_A3BE:
addq.b #2,routine(a0)
st (Credits_Trigger).w
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; Object CC - Trigger for rescue plane and birds from ending sequence
; ----------------------------------------------------------------------------
; Sprite_A3C8:
ObjCC:
jsrto (ObjB2_Animate_Pilot).l, JmpTo_ObjB2_Animate_Pilot
moveq #0,d0
move.b routine(a0),d0
move.w ObjCC_Index(pc,d0.w),d1
jmp ObjCC_Index(pc,d1.w)
; ===========================================================================
; loc_A3DA:
ObjCC_Index: offsetTable
offsetTableEntry.w ObjCC_Init ; 0
offsetTableEntry.w ObjCC_Main ; 2
; ===========================================================================
; loc_A3DE:
ObjCC_Init:
lea (ObjB2_SubObjData).l,a1
jsrto (LoadSubObject_Part3).l, JmpTo_LoadSubObject_Part3
cmpi.w #2,(Player_mode).w
bne.s +
move.b #4,mapping_frame(a0)
move.b #1,anim(a0)
+
move.w #-$10,x_pos(a0)
move.w #$C0,y_pos(a0)
move.w #$100,x_vel(a0)
move.w #-$80,y_vel(a0)
move.b #$14,objoff_35(a0)
move.b #3,priority(a0)
move.w #4,(Ending_VInt_Subrout).w
move.l a0,-(sp)
lea (MapEng_EndingTailsPlane).l,a0
cmpi.w #4,(Ending_Routine).w
bne.s +
lea (MapEng_EndingSonicPlane).l,a0
+
lea (Chunk_Table).l,a1
move.w #make_art_tile(ArtTile_ArtNem_EndingFinalTornado,0,1),d0
jsrto (EniDec).l, JmpTo_EniDec
movea.l (sp)+,a0 ; load 0bj address
move.w #$C00,(Normal_palette_line3).w
jmpto (DisplaySprite).l, JmpTo5_DisplaySprite
; ===========================================================================
; loc_A456:
ObjCC_Main:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w ObjCC_State2_States(pc,d0.w),d1
jsr ObjCC_State2_States(pc,d1.w)
jmpto (DisplaySprite).l, JmpTo5_DisplaySprite
; ===========================================================================
ObjCC_State2_States: offsetTable
offsetTableEntry.w loc_A474 ; 0
offsetTableEntry.w loc_A4B6 ; 2
offsetTableEntry.w loc_A5A6 ; 4
offsetTableEntry.w loc_A6C6 ; 6
offsetTableEntry.w loc_A7DE ; 8
offsetTableEntry.w loc_A83E ; $A
; ===========================================================================
loc_A474:
cmpi.w #$A0,x_pos(a0)
beq.s +
jsrto (ObjectMove).l, JmpTo2_ObjectMove
-
lea (Ani_objB2_a).l,a1
jmpto (AnimateSprite).l, JmpTo_AnimateSprite
; ===========================================================================
+
addq.b #2,routine_secondary(a0)
move.w #$480,objoff_3C(a0)
btst #6,(Graphics_Flags).w
beq.s +
move.w #$3D0,objoff_3C(a0)
+
move.w #$40,objoff_32(a0)
st (CutScene+objoff_34).w
clr.w x_vel(a0)
clr.w y_vel(a0)
bra.s -
; ===========================================================================
loc_A4B6:
bsr.w sub_ABBA
bsr.w sub_A524
subq.w #1,objoff_3C(a0)
bmi.s +
bra.s -
; ===========================================================================
+
addq.b #2,routine_secondary(a0)
move.w #2,objoff_3C(a0)
clr.w objoff_32(a0)
clr.b mapping_frame(a0)
cmpi.w #2,(Ending_Routine).w
beq.s +
move.b #7,mapping_frame(a0)
cmpi.w #4,(Ending_Routine).w
bne.s +
move.b #$18,mapping_frame(a0)
+
clr.b anim(a0)
clr.b anim_frame(a0)
clr.b anim_frame_duration(a0)
move.l #ObjCF_MapUnc_ADA2,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0)
jsr (Adjust2PArtPointer).l
subi.w #$14,x_pos(a0)
addi.w #$14,y_pos(a0)
bra.w sub_A58C
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_A524:
lea (MainCharacter).w,a1 ; a1=character
move.w (Ending_Routine).w,d0
move.w off_A534(pc,d0.w),d0
jmp off_A534(pc,d0.w)
; End of function sub_A524
; ===========================================================================
off_A534: offsetTable
offsetTableEntry.w loc_A53A ; 0
offsetTableEntry.w loc_A55C ; 2
offsetTableEntry.w loc_A582 ; 4
; ===========================================================================
loc_A53A:
move.w y_pos(a0),d0
subi.w #$1C,d0
-
move.w d0,y_pos(a1)
move.w x_pos(a0),x_pos(a1)
move.l #$1000505,mapping_frame(a1)
move.w #$100,anim_frame_duration(a1)
rts
; ===========================================================================
loc_A55C:
tst.w objoff_32(a0)
beq.s +
subq.w #1,objoff_32(a0)
addi.l #$8000,x_pos(a1)
addq.w #1,y_pos(a1)
rts
; ===========================================================================
+
move.w #$C0,x_pos(a1)
move.w #$90,y_pos(a1)
rts
; ===========================================================================
loc_A582:
move.w y_pos(a0),d0
subi.w #$18,d0
bra.s -
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_A58C:
tst.b (Super_Sonic_flag).w
bne.w return_A38C
loc_A594:
lea (MainCharacter).w,a1 ; a1=character
move.w #$200,x_pos(a1)
move.w #0,y_pos(a1)
rts
; End of function sub_A58C
; ===========================================================================
loc_A5A6:
bsr.s sub_A58C
subq.w #1,objoff_3C(a0)
bpl.s + ; rts
move.w #2,objoff_3C(a0)
move.w objoff_32(a0),d0
cmpi.w #$1C,d0
bhs.s ++
addq.w #1,objoff_32(a0)
move.w (Ending_Routine).w,d1
move.w off_A5FC(pc,d1.w),d1
lea off_A5FC(pc,d1.w),a1
move.b (a1,d0.w),mapping_frame(a0)
add.w d0,d0
add.w d0,d0
move.l word_A656(pc,d0.w),d1
move.w d1,y_pos(a0)
swap d1
move.w d1,x_pos(a0)
+
rts
; ===========================================================================
+
addq.b #2,routine_secondary(a0)
move.w #$60,objoff_3C(a0)
clr.b objoff_31(a0)
clr.w objoff_32(a0)
rts
; ===========================================================================
off_A5FC: offsetTable
offsetTableEntry.w byte_A602 ; 0
offsetTableEntry.w byte_A61E ; 2
offsetTableEntry.w byte_A63A ; 4
byte_A602:
dc.b 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, $A, $A
dc.b $A, $B, $B, $B, $B, $B, $B, $B, $B, $B, $B, $B; 16
byte_A61E:
dc.b 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3
dc.b 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4; 16
byte_A63A:
dc.b $18,$18,$18,$18,$19,$19,$19,$19,$19,$19,$19, 9, 9, 9, $A, $A
dc.b $A, $B, $B, $B, $B, $B, $B, $B, $B, $B, $B, $B; 16
word_A656:
dc.w $A0, $70, $B0, $70, $B6, $71, $BC, $72
dc.w $C4, $74, $C8, $75, $CA, $76, $CC, $77; 8
dc.w $CE, $78, $D0, $79, $D2, $7A, $D4, $7B; 16
dc.w $D6, $7C, $D9, $7E, $DC, $81, $DE, $84; 24
dc.w $E1, $87, $E4, $8B, $E7, $8F, $EC, $94; 32
dc.w $F0, $99, $F5, $9D, $F9, $A4, $100, $AC; 40
dc.w $108, $B8, $112, $C4, $11F, $D3, $12C, $FA; 48
; ===========================================================================
loc_A6C6:
subq.w #1,objoff_3C(a0)
bmi.s loc_A720
tst.b (Super_Sonic_flag).w
beq.s + ; rts
subq.b #1,objoff_31(a0)
bpl.s + ; rts
addq.b #3,objoff_31(a0)
move.w objoff_32(a0),d0
addq.w #4,objoff_32(a0)
cmpi.w #$78,d0
bhs.s + ; rts
cmpi.w #$C,d0
blo.s ++
bsr.w loc_A594
move.l word_A766(pc,d0.w),d1
move.w d1,y_pos(a0)
swap d1
move.w d1,x_pos(a0)
lsr.w #2,d0
move.b byte_A748(pc,d0.w),mapping_frame(a0)
+
rts
; ===========================================================================
+
move.l word_A766(pc,d0.w),d0
lea (MainCharacter).w,a1 ; a1=character
move.w d0,y_pos(a1)
swap d0
move.w d0,x_pos(a1)
rts
; ===========================================================================
loc_A720:
addq.b #2,routine_secondary(a0)
clr.w objoff_3C(a0)
clr.w objoff_32(a0)
lea (word_AD6E).l,a2
jsrto (LoadChildObject).l, JmpTo_LoadChildObject
tst.b (Super_Sonic_flag).w
bne.w return_A38C
lea (word_AD6A).l,a2
jmpto (LoadChildObject).l, JmpTo_LoadChildObject
; ===========================================================================
byte_A748:
dc.b $12,$12,$12,$12,$12,$12,$12,$13,$13,$13,$13,$13,$13,$14,$14,$14
dc.b $14,$15,$15,$15,$16,$16,$16,$16,$16,$16,$16,$16,$16, 0; 16
word_A766:
dc.w $C0, $90 ; 1
dc.w $B0, $91 ; 3
dc.w $A8, $92 ; 5
dc.w $9B, $96 ; 7
dc.w $99, $98 ; 9
dc.w $98, $99 ; 11
dc.w $99, $9A ; 13
dc.w $9B, $9C ; 15
dc.w $9F, $9E ; 17
dc.w $A4, $A0 ; 19
dc.w $AC, $A2 ; 21
dc.w $B7, $A5 ; 23
dc.w $C4, $A8 ; 25
dc.w $D3, $AB ; 27
dc.w $DE, $AE ; 29
dc.w $E8, $B0 ; 31
dc.w $EF, $B2 ; 33
dc.w $F4, $B5 ; 35
dc.w $F9, $B8 ; 37
dc.w $FC, $BB ; 39
dc.w $FE, $BE ; 41
dc.w $FF, $C0 ; 43
dc.w $100, $C2 ; 45
dc.w $101, $C5 ; 47
dc.w $102, $C8 ; 49
dc.w $102, $CC ; 51
dc.w $101, $D1 ; 53
dc.w $FD, $D7 ; 55
dc.w $F9, $DE ; 57
dc.w $F9,$118 ; 59
; ===========================================================================
loc_A7DE:
bsr.w loc_A594
subq.w #1,objoff_3C(a0)
bpl.s + ; rts
move.w #2,objoff_3C(a0)
move.w objoff_32(a0),d0
cmpi.w #$1C,d0
bhs.s ++
addq.w #4,objoff_32(a0)
lea word_A822(pc,d0.w),a1
move.w (a1)+,d0
add.w d0,(Horiz_Scroll_Buf).w
move.w (a1)+,d0
add.w d0,(Vscroll_Factor_FG).w
+
rts
; ===========================================================================
+
addq.b #2,routine_secondary(a0)
bset #3,status(a0)
clr.b objoff_31(a0)
clr.w objoff_32(a0)
rts
; ===========================================================================
word_A822:
dc.w -$3A
dc.w $88 ; 1
dc.w -$C ; 2
dc.w $22 ; 3
dc.w -8 ; 4
dc.w $10 ; 5
dc.w -4 ; 6
dc.w 8 ; 7
dc.w -2 ; 8
dc.w 4 ; 9
dc.w -1 ; 10
dc.w 2 ; 11
dc.w -1 ; 12
dc.w 2 ; 13
; ===========================================================================
loc_A83E:
tst.b (Super_Sonic_flag).w
beq.w return_A38C
move.b #$17,mapping_frame(a0)
subq.b #1,objoff_31(a0)
bpl.s + ; rts
addq.b #3,objoff_31(a0)
move.w objoff_32(a0),d0
cmpi.w #$20,d0
bhs.s + ; rts
addq.w #4,objoff_32(a0)
move.l word_A874(pc,d0.w),d1
move.w d1,y_pos(a0)
swap d1
move.w d1,x_pos(a0)
+
rts
; ===========================================================================
word_A874:
dc.w $60,$88 ; 1
dc.w $50,$68 ; 3
dc.w $44,$46 ; 5
dc.w $3C,$36 ; 7
dc.w $36,$2A ; 9
dc.w $33,$24 ; 11
dc.w $31,$20 ; 13
dc.w $30,$1E ; 15
; ===========================================================================
; ----------------------------------------------------------------------------
; Object CE - Sonic and Tails jumping off the plane from ending sequence
; ----------------------------------------------------------------------------
; Sprite_A894:
ObjCE:
moveq #0,d0
move.b routine(a0),d0
move.w ObjCE_Index(pc,d0.w),d1
jmp ObjCE_Index(pc,d1.w)
; ===========================================================================
; off_A8A2:
ObjCE_Index: offsetTable
offsetTableEntry.w ObjCE_Init ; 0
offsetTableEntry.w loc_A902 ; 2
offsetTableEntry.w loc_A936 ; 4
offsetTableEntry.w BranchTo_JmpTo5_DisplaySprite ; 6
; ===========================================================================
; loc_A8AA:
ObjCE_Init:
lea (ObjB3_SubObjData).l,a1
jsrto (LoadSubObject_Part3).l, JmpTo_LoadSubObject_Part3
move.l #ObjCF_MapUnc_ADA2,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,1),art_tile(a0)
move.b #1,priority(a0)
jsr (Adjust2PArtPointer).l
move.b #$C,mapping_frame(a0)
cmpi.w #4,(Ending_Routine).w
bne.s +
move.b #$F,mapping_frame(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,1,1),art_tile(a0)
+
move.w #$E8,d0
move.w d0,x_pos(a0)
move.w d0,objoff_30(a0)
move.w #$118,d0
move.w d0,y_pos(a0)
move.w d0,objoff_32(a0)
rts
; ===========================================================================
loc_A902:
movea.w objoff_2C(a0),a1 ; a1=object
btst #3,status(a1)
bne.s +
loc_A90E:
move.w objoff_30(a0),d0
add.w (Horiz_Scroll_Buf).w,d0
move.w d0,x_pos(a0)
move.w objoff_32(a0),d0
sub.w (Vscroll_Factor_FG).w,d0
move.w d0,y_pos(a0)
BranchTo_JmpTo5_DisplaySprite
jmpto (DisplaySprite).l, JmpTo5_DisplaySprite
; ===========================================================================
+
addq.b #2,routine(a0)
clr.w objoff_3C(a0)
jmpto (DisplaySprite).l, JmpTo5_DisplaySprite
; ===========================================================================
loc_A936:
subq.w #1,objoff_3C(a0)
bpl.s BranchTo2_JmpTo5_DisplaySprite
move.w #4,objoff_3C(a0)
move.w objoff_34(a0),d0
cmpi.w #4,d0
bhs.s ++
addq.w #2,objoff_34(a0)
lea byte_A980(pc,d0.w),a1
cmpi.w #2,(Ending_Routine).w
bne.s +
lea byte_A984(pc,d0.w),a1
+
move.b (a1)+,d0
ext.w d0
add.w d0,x_pos(a0)
move.b (a1)+,d0
ext.w d0
add.w d0,y_pos(a0)
addq.b #1,mapping_frame(a0)
BranchTo2_JmpTo5_DisplaySprite
jmpto (DisplaySprite).l, JmpTo5_DisplaySprite
; ===========================================================================
+
addq.b #2,routine(a0)
jmpto (DisplaySprite).l, JmpTo5_DisplaySprite
; ===========================================================================
byte_A980:
dc.b -8, 0
dc.b -$44,-$38 ; 2
byte_A984:
dc.b -8, 0
dc.b -$50,-$40 ; 2
; ===========================================================================
; ----------------------------------------------------------------------------
; Object CF - "Plane's helixes" from ending sequence
; ----------------------------------------------------------------------------
; Sprite_A988:
ObjCF:
moveq #0,d0
move.b routine(a0),d0
move.w ObjCF_Index(pc,d0.w),d1
jmp ObjCF_Index(pc,d1.w)
; ===========================================================================
; off_A996:
ObjCF_Index: offsetTable
offsetTableEntry.w ObjCF_Init ; 0
offsetTableEntry.w ObjCF_Animate ; 2
; ===========================================================================
; loc_A99A:
ObjCF_Init:
lea (ObjB3_SubObjData).l,a1
jsrto (LoadSubObject_Part3).l, JmpTo_LoadSubObject_Part3
move.l #ObjCF_MapUnc_ADA2,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,1),art_tile(a0)
move.b #3,priority(a0)
jsr (Adjust2PArtPointer).l
move.b #5,mapping_frame(a0)
move.b #2,anim(a0)
move.w #$10F,d0
move.w d0,x_pos(a0)
move.w d0,objoff_30(a0)
move.w #$15E,d0
move.w d0,y_pos(a0)
move.w d0,objoff_32(a0)
rts
; ===========================================================================
; loc_A9E4:
ObjCF_Animate:
lea (Ani_objCF).l,a1
jsrto (AnimateSprite).l, JmpTo_AnimateSprite
bra.w loc_A90E
; ===========================================================================
; ----------------------------------------------------------------------------
; Object CB - Background clouds from ending sequence
; ----------------------------------------------------------------------------
; Sprite_A9F2:
ObjCB:
moveq #0,d0
move.b routine(a0),d0
move.w ObjCB_Index(pc,d0.w),d1
jmp ObjCB_Index(pc,d1.w)
; ===========================================================================
; off_AA00:
ObjCB_Index: offsetTable
offsetTableEntry.w ObjCB_Init ; 0
offsetTableEntry.w loc_AA76 ; 2
offsetTableEntry.w loc_AA8A ; 4
; ===========================================================================
; loc_AA06:
ObjCB_Init:
lea (ObjB3_SubObjData).l,a1
jsrto (LoadSubObject_Part3).l, JmpTo_LoadSubObject_Part3
move.w art_tile(a0),d0
andi.w #$1FFF,d0
ori.w #palette_mask,d0
move.w d0,art_tile(a0)
move.b #$30,width_pixels(a0)
move.l (RNG_seed).w,d0
ror.l #1,d0
move.l d0,(RNG_seed).w
move.w d0,d1
andi.w #3,d0
move.b ObjCB_Frames(pc,d0.w),mapping_frame(a0)
add.w d0,d0
move.w ObjCB_YSpeeds(pc,d0.w),y_vel(a0)
tst.b (CutScene+$34).w
beq.s +
andi.w #$FF,d1
move.w d1,y_pos(a0)
move.w #$150,x_pos(a0)
rts
; ===========================================================================
+
andi.w #$1FF,d1
move.w d1,x_pos(a0)
move.w #$100,y_pos(a0)
rts
; ===========================================================================
; byte_AA6A:
ObjCB_Frames:
dc.b 0
dc.b 1 ; 1
dc.b 2 ; 2
dc.b 0 ; 3
; word_AA6E:
ObjCB_YSpeeds:
dc.w -$300
dc.w -$200 ; 1
dc.w -$100 ; 2
dc.w -$300 ; 3
; ===========================================================================
loc_AA76:
tst.b (CutScene+objoff_34).w
beq.s loc_AA8A
addq.b #2,routine(a0)
move.w y_vel(a0),x_vel(a0)
clr.w y_vel(a0)
loc_AA8A:
jsrto (ObjectMove).l, JmpTo2_ObjectMove
tst.b (CutScene+objoff_34).w
beq.s +
cmpi.w #-$20,x_pos(a0)
blt.w JmpTo3_DeleteObject
jmpto (DisplaySprite).l, JmpTo5_DisplaySprite
; ===========================================================================
+
tst.w y_pos(a0)
bmi.w JmpTo3_DeleteObject
jmpto (DisplaySprite).l, JmpTo5_DisplaySprite
; ===========================================================================
; ----------------------------------------------------------------------------
; Object CD - Birds from ending sequence
; ----------------------------------------------------------------------------
endingbird_delay = objoff_3C ; delay before doing the next action
; Sprite_AAAE:
ObjCD:
moveq #0,d0
move.b routine(a0),d0
move.w ObjCD_Index(pc,d0.w),d1
jmp ObjCD_Index(pc,d1.w)
; ===========================================================================
; off_AABC:
ObjCD_Index: offsetTable
offsetTableEntry.w ObjCD_Init ; 0
offsetTableEntry.w ObjCD_Main ; 2
; ===========================================================================
; loc_AAC0:
ObjCD_Init:
lea (Obj28_SubObjData).l,a1
jsrto (LoadSubObject_Part3).l, JmpTo_LoadSubObject_Part3
move.l (RNG_seed).w,d0
ror.l #3,d0
move.l d0,(RNG_seed).w
move.l d0,d1
andi.w #$7F,d0
move.w #-$A0,d2
add.w d0,d2
move.w d2,x_pos(a0)
ror.l #3,d1
andi.w #$FF,d1
moveq #8,d2
add.w d1,d2
move.w d2,y_pos(a0)
move.w #$100,x_vel(a0)
moveq #$20,d0
cmpi.w #$20,d1
blo.s +
neg.w d0
+
move.w d0,y_vel(a0)
move.w #$C0,endingbird_delay(a0)
rts
; ===========================================================================
; loc_AB0E:
ObjCD_Main:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w ObjCD_Main_States(pc,d0.w),d1
jsr ObjCD_Main_States(pc,d1.w)
jsrto (ObjectMove).l, JmpTo2_ObjectMove
lea (Ani_objCD).l,a1
jsrto (AnimateSprite).l, JmpTo_AnimateSprite
jmpto (DisplaySprite).l, JmpTo5_DisplaySprite
; ===========================================================================
ObjCD_Main_States: offsetTable
offsetTableEntry.w loc_AB34 ; 0
offsetTableEntry.w loc_AB5C ; 2
offsetTableEntry.w loc_AB8E ; 4
; ===========================================================================
loc_AB34:
subq.w #1,endingbird_delay(a0)
bpl.s + ; rts
addq.b #2,routine_secondary(a0)
move.w y_vel(a0),objoff_2E(a0)
clr.w x_vel(a0)
move.w y_pos(a0),objoff_32(a0)
move.w #$80,y_vel(a0)
move.w #$180,endingbird_delay(a0)
+
rts
; ===========================================================================
loc_AB5C:
subq.w #1,endingbird_delay(a0)
bmi.s ++
move.w y_pos(a0),d0
moveq #-4,d1
cmp.w objoff_32(a0),d0
bhs.s +
neg.w d1
+
add.w d1,y_vel(a0)
rts
; ===========================================================================
+
addq.b #2,routine_secondary(a0)
move.w #-$100,x_vel(a0)
move.w objoff_2E(a0),y_vel(a0)
move.w #$C0,endingbird_delay(a0)
rts
; ===========================================================================
loc_AB8E:
subq.w #1,endingbird_delay(a0)
bmi.s +
rts
; ===========================================================================
+
addq.w #4,sp
if removeJmpTos
JmpTo3_DeleteObject
endif
jmpto (DeleteObject).l, JmpTo3_DeleteObject
; ===========================================================================
loc_AB9C:
subq.w #1,objoff_30(a0)
bpl.s + ; rts
move.l (RNG_seed).w,d0
andi.w #$1F,d0
move.w d0,objoff_30(a0)
lea (word_AD5E).l,a2
jsrto (LoadChildObject).l, JmpTo_LoadChildObject
+
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_ABBA:
subq.w #1,objoff_30(a0)
bpl.s + ; rts
tst.b objoff_35(a0)
beq.s + ; rts
subq.b #1,objoff_35(a0)
move.l (RNG_seed).w,d0
andi.w #$F,d0
move.w d0,objoff_30(a0)
lea (word_AD66).l,a2
jsrto (LoadChildObject).l, JmpTo_LoadChildObject
+ rts
; End of function sub_ABBA
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_ABE2:
EndingSequence_LoadCharacterArt:
move.w (Ending_Routine).w,d0
move.w EndingSequence_LoadCharacterArt_Characters(pc,d0.w),d0
jmp EndingSequence_LoadCharacterArt_Characters(pc,d0.w)
; End of function EndingSequence_LoadCharacterArt
; ===========================================================================
EndingSequence_LoadCharacterArt_Characters: offsetTable
offsetTableEntry.w EndingSequence_LoadCharacterArt_Sonic ; 0
offsetTableEntry.w EndingSequence_LoadCharacterArt_SuperSonic ; 2
offsetTableEntry.w EndingSequence_LoadCharacterArt_Tails ; 4
; ===========================================================================
; loc_ABF4:
EndingSequence_LoadCharacterArt_Sonic:
move.l #vdpComm(tiles_to_bytes(ArtTile_EndingCharacter),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_EndingSonic).l,a0
jmpto (NemDec).l, JmpTo_NemDec
; ===========================================================================
; loc_AC08:
EndingSequence_LoadCharacterArt_SuperSonic:
move.l #vdpComm(tiles_to_bytes(ArtTile_EndingCharacter),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_EndingSuperSonic).l,a0
jmpto (NemDec).l, JmpTo_NemDec
; ===========================================================================
; loc_AC1C:
EndingSequence_LoadCharacterArt_Tails:
move.l #vdpComm(tiles_to_bytes(ArtTile_EndingCharacter),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_EndingTails).l,a0
jmpto (NemDec).l, JmpTo_NemDec
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_AC30:
EndingSequence_LoadFlickyArt:
move.w (Ending_Routine).w,d0
move.w EndingSequence_LoadFlickyArt_Flickies(pc,d0.w),d0
jmp EndingSequence_LoadFlickyArt_Flickies(pc,d0.w)
; End of function EndingSequence_LoadFlickyArt
; ===========================================================================
EndingSequence_LoadFlickyArt_Flickies: offsetTable
offsetTableEntry.w EndingSequence_LoadFlickyArt_Bird ; 0
offsetTableEntry.w EndingSequence_LoadFlickyArt_Eagle ; 2
offsetTableEntry.w EndingSequence_LoadFlickyArt_Chicken ; 4
; ===========================================================================
; loc_AC42:
EndingSequence_LoadFlickyArt_Bird:
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Animal_2),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_Bird).l,a0
jmpto (NemDec).l, JmpTo_NemDec
; ===========================================================================
; loc_AC56:
EndingSequence_LoadFlickyArt_Eagle:
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Animal_2),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_Eagle).l,a0
jmpto (NemDec).l, JmpTo_NemDec
; ===========================================================================
; loc_AC6A:
EndingSequence_LoadFlickyArt_Chicken:
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_Animal_2),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_Chicken).l,a0
jmpto (NemDec).l, JmpTo_NemDec
; ===========================================================================
Pal_AC7E: BINCLUDE "art/palettes/Ending Sonic.bin"
Pal_AC9E: BINCLUDE "art/palettes/Ending Sonic Far.bin"
Pal_ACDE: BINCLUDE "art/palettes/Ending Background.bin"
Pal_AD1E: BINCLUDE "art/palettes/Ending Photos.bin"
Pal_AD3E: BINCLUDE "art/palettes/Ending Super Sonic.bin"
word_AD5E:
dc.w objoff_3E
dc.b ObjID_EndingSeqClouds
dc.b $00
word_AD62:
dc.w objoff_3E
dc.b ObjID_EndingSeqTrigger
dc.b $00
word_AD66:
dc.w objoff_3E
dc.b ObjID_EndingSeqBird
dc.b $00
word_AD6A:
dc.w objoff_3E
dc.b ObjID_EndingSeqSonic
dc.b $00
word_AD6E:
dc.w objoff_3E
dc.b ObjID_TornadoHelixes
dc.b $00
; off_AD72:
Obj28_SubObjData:
subObjData Obj28_MapUnc_11E1C,make_art_tile(ArtTile_ArtNem_Animal_2,0,0),4,2,8,0
; animation script
; byte_AD7C
Ani_objCD: offsetTable
offsetTableEntry.w byte_AD7E ; 0
byte_AD7E: dc.b 5, 0, 1,$FF
; animation script
; off_AD82
Ani_objCF: offsetTable
offsetTableEntry.w byte_AD88 ; 0
offsetTableEntry.w byte_AD8E ; 1
offsetTableEntry.w byte_AD9E ; 2
byte_AD88: dc.b 3, 0, 0, 1,$FA, 0
byte_AD8E: dc.b 3, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4,$FA, 0
byte_AD9E: dc.b 1, 5, 6,$FF
even
; -----------------------------------------------------------------------------
; sprite mappings
; -----------------------------------------------------------------------------
ObjCF_MapUnc_ADA2: BINCLUDE "mappings/sprite/objCF.bin"
; --------------------------------------------------------------------------------------
; Enigma compressed art mappings
; "Sonic the Hedgehog 2" mappings ; MapEng_B23A:
MapEng_EndGameLogo: BINCLUDE "mappings/misc/Sonic 2 end of game logo.bin"
even
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_B262
ShowCreditsScreen:
lea off_B2CA(pc),a1
move.w (CreditsScreenIndex).w,d0
lsl.w #2,d0
move.l (a1,d0.w),d0
movea.l d0,a1
loc_B272:
move #$2700,sr
lea (VDP_data_port).l,a6
-
move.l (a1)+,d0
bmi.s ++
movea.l d0,a2
move.w (a1)+,d0
bsr.s sub_B29E
move.l d0,4(a6)
move.b (a2)+,d0
lsl.w #8,d0
-
move.b (a2)+,d0
bmi.s +
move.w d0,(a6)
bra.s -
; ===========================================================================
+ bra.s --
; ===========================================================================
+
move #$2300,sr
rts
; End of function ShowCreditsScreen
; ---------------------------------------------------------------------------
; Subroutine to convert a VRAM address into a 32-bit VRAM write command word
; Input:
; d0 VRAM address (word)
; Output:
; d0 32-bit VDP command word for a VRAM write to specified address.
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_B29E:
andi.l #$FFFF,d0
lsl.l #2,d0
lsr.w #2,d0
ori.w #vdpComm($0000,VRAM,WRITE)>>16,d0
swap d0
rts
; End of function sub_B29E
; ===========================================================================
; macro for declaring pointer/position structures for intro/credit text
vram_pnt := VRAM_Plane_A_Name_Table
creditsPtrs macro addr,pos
if "addr"<>""
dc.l addr
dc.w vram_pnt + pos
shift
shift
creditsPtrs ALLARGS
else
dc.w -1
endif
endm
textLoc function col,line,(($80 * line) + (2 * col))
; intro text pointers (one intro screen)
vram_pnt := VRAM_TtlScr_Plane_A_Name_Table
off_B2B0: creditsPtrs byte_BD1A,textLoc($0F,$09), byte_BCEE,textLoc($11,$0C), \
byte_BCF6,textLoc($03,$0F), byte_BCE9,textLoc($12,$12)
; credits screen pointer table
off_B2CA:
dc.l off_B322, off_B336, off_B34A, off_B358 ; 3
dc.l off_B366, off_B374, off_B388, off_B3A8 ; 7
dc.l off_B3C2, off_B3DC, off_B3F0, off_B41C ; 11
dc.l off_B436, off_B450, off_B45E, off_B490 ; 15
dc.l off_B4B0, off_B4C4, off_B4F0, off_B51C ; 19
dc.l off_B548, -1 ; 21
; credits text pointers for each screen of credits
vram_pnt := VRAM_Plane_A_Name_Table
off_B322: creditsPtrs byte_BC46,textLoc($0E,$0B), byte_BC51,textLoc($18,$0B), byte_BC55,textLoc($02,$0F)
off_B336: creditsPtrs byte_B55C,textLoc($03,$0B), byte_B56F,textLoc($16,$0B), byte_B581,textLoc($06,$0F)
off_B34A: creditsPtrs byte_B56F,textLoc($0C,$0B), byte_B59F,textLoc($07,$0F)
off_B358: creditsPtrs byte_B5BC,textLoc($0C,$0B), byte_B5CD,textLoc($06,$0F)
off_B366: creditsPtrs byte_B5EB,textLoc($05,$0B), byte_B60C,textLoc($07,$0F)
off_B374: creditsPtrs byte_B628,textLoc($08,$0A), byte_B642,textLoc($04,$0E), byte_B665,textLoc($0A,$10)
off_B388: creditsPtrs byte_B67B,textLoc($04,$08), byte_B69C,textLoc($11,$0A), byte_B6A4,textLoc($09,$0C), byte_B6BC,textLoc($04,$10), byte_B6DE,textLoc($08,$12)
off_B3A8: creditsPtrs byte_B6F8,textLoc($0B,$09), byte_B70B,textLoc($09,$0B), byte_B723,textLoc($0A,$0F), byte_B738,textLoc($03,$11)
off_B3C2: creditsPtrs byte_B75C,textLoc($04,$09), byte_B642,textLoc($04,$0D), byte_B77E,textLoc($07,$0F), byte_B799,textLoc($07,$11)
off_B3DC: creditsPtrs byte_B7B5,textLoc($08,$0A), byte_B75C,textLoc($04,$0C), byte_B799,textLoc($07,$10)
off_B3F0: creditsPtrs byte_B7F2,textLoc($09,$06), byte_B6BC,textLoc($04,$0A), byte_B80B,textLoc($0A,$0C), byte_B821,textLoc($09,$0E), byte_B839,textLoc($07,$10), byte_B855,textLoc($0B,$12), byte_B869,textLoc($0B,$14)
off_B41C: creditsPtrs byte_B7B5,textLoc($09,$09), byte_B87D,textLoc($0A,$0B), byte_B893,textLoc($0B,$0F), byte_B8A8,textLoc($07,$11)
off_B436: creditsPtrs byte_B8C5,textLoc($06,$09), byte_B8E2,textLoc($05,$0D), byte_B902,textLoc($03,$0F), byte_B90F,textLoc($04,$11)
off_B450: creditsPtrs byte_B932,textLoc($04,$0B), byte_B954,textLoc($05,$0F)
off_B45E: creditsPtrs byte_B974,textLoc($04,$05), byte_B995,textLoc($0F,$09), byte_B9A1,textLoc($0F,$0B), byte_B9AD,textLoc($0F,$0D), byte_B9B8,textLoc($10,$0F), byte_B9C1,textLoc($11,$11), byte_B9C8,textLoc($11,$13), byte_B9D0,textLoc($0F,$15)
off_B490: creditsPtrs byte_B9DB,textLoc($03,$08), byte_BA00,textLoc($08,$0C), byte_BA1B,textLoc($06,$0E), byte_BA3A,textLoc($09,$10), byte_BA52,textLoc($0A,$12)
off_B4B0: creditsPtrs byte_BA69,textLoc($09,$0A), byte_BA81,textLoc($05,$0E), byte_B7CE,textLoc($03,$10)
off_B4C4: creditsPtrs byte_B55C,textLoc($0B,$06), byte_BAA2,textLoc($0A,$08), byte_BAB8,textLoc($03,$0C), byte_BADC,textLoc($07,$0E), byte_BAF7,textLoc($05,$10), byte_BB16,textLoc($07,$12), byte_BB32,textLoc($02,$14)
off_B4F0: creditsPtrs byte_BB58,textLoc($06,$06), byte_BB75,textLoc($12,$08), byte_BB7B,textLoc($06,$0C), byte_BC9F,textLoc($05,$0E), byte_BBD8,textLoc($08,$10), byte_BBF2,textLoc($08,$12), byte_BC0C,textLoc($09,$14)
off_B51C: creditsPtrs byte_BB58,textLoc($06,$06), byte_BB75,textLoc($12,$08), byte_BB98,textLoc($03,$0C), byte_BBBC,textLoc($07,$0E), byte_BCBE,textLoc($07,$10), byte_BCD9,textLoc($0D,$12), byte_BC25,textLoc($04,$14)
off_B548: creditsPtrs byte_BC7B,textLoc($0B,$09), byte_BC8F,textLoc($12,$0D), byte_BC95,textLoc($10,$11)
; temporarily remap characters to credit text format
; let's encode 2-wide characters like Aa, Bb, Cc, etc. and hide it with a macro
charset '@',"\x3B\2\4\6\8\xA\xC\xE\x10\x12\x13\x15\x17\x19\x1B\x1D\x1F\x21\x23\x25\x27\x29\x2B\x2D\x2F\x31\x33"
charset 'a',"\3\5\7\9\xB\xD\xF\x11\x12\x14\x16\x18\x1A\x1C\x1E\x20\x22\x24\x26\x28\x2A\x2C\x2E\x30\x32\x34"
charset '!',"\x3D\x39\x3F\x36"
charset '\H',"\x39\x37\x38"
charset '9',"\x3E\x40\x41"
charset '1',"\x3C\x35"
charset '.',"\x3A"
charset ' ',0
; macro for defining credit text in conjunction with the remapped character set
vram_src := ArtTile_ArtNem_CreditText_CredScr
creditText macro pal,ss
if ((vram_src & $FF) <> $0) && ((vram_src & $FF) <> $1)
fatal "The low byte of vram_src was $\{vram_src & $FF}, but it must be $00 or $01."
endif
c := 0
dc.b (make_art_tile(vram_src,pal,0) & $FF00) >> 8
rept strlen(ss)
t := substr(ss,c,1)
dc.b t
l := lowstring(t)
if t="I"
elseif l<>t
dc.b l
elseif t="1"
dc.b "!"
elseif t="2"
dc.b "$"
elseif t="9"
dc.b "#"
endif
c := c+1
endm
dc.b -1
rev02even
endm
; credits text data (palette index followed by a string)
vram_src := ArtTile_ArtNem_CreditText_CredScr
byte_B55C: creditText 1,"EXECUTIVE"
byte_B56F: creditText 1,"PRODUCER"
byte_B581: creditText 0,"HAYAO NAKAYAMA"
byte_B59F: creditText 0,"SHINOBU TOYODA"
byte_B5BC: creditText 1,"DIRECTOR"
byte_B5CD: creditText 0,"MASAHARU YOSHII"
byte_B5EB: creditText 1,"CHIEF PROGRAMMER"
byte_B60C: creditText 0,"YUJI NAKA (YU2)"
byte_B628: creditText 1,"GAME PLANNER"
byte_B642: creditText 0,"HIROKAZU YASUHARA"
byte_B665: creditText 0,"(CAROL YAS)"
byte_B67B: creditText 1,"CHARACTER DESIGN"
byte_B69C: creditText 1,"AND"
byte_B6A4: creditText 1,"CHIEF ARTIST"
byte_B6BC: creditText 0,"YASUSHI YAMAGUCHI"
byte_B6DE: creditText 0,"(JUDY TOTOYA)"
byte_B6F8: creditText 1,"ASSISTANT"
byte_B70B: creditText 1,"PROGRAMMERS"
byte_B723: creditText 0,"BILL WILLIS"
byte_B738: creditText 0,"MASANOBU YAMAMOTO"
byte_B75C: creditText 1,"OBJECT PLACEMENT"
byte_B77E: creditText 0,"TAKAHIRO ANTO"
byte_B799: creditText 0,"YUTAKA SUGANO"
byte_B7B5: creditText 1,"SPECIALSTAGE"
byte_B7CE: creditText 0,"CAROL ANN HANSHAW"
byte_B7F2: creditText 1,"ZONE ARTISTS"
byte_B80B: creditText 0,"CRAIG STITT"
byte_B821: creditText 0,"BRENDA ROSS"
byte_B839: creditText 0,"JINA ISHIWATARI"
byte_B855: creditText 0,"TOM PAYNE"
byte_B869: creditText 0,"PHENIX RIE"
byte_B87D: creditText 1,"ART AND CG"
byte_B893: creditText 0,"TIM SKELLY"
byte_B8A8: creditText 0,"PETER MORAWIEC"
byte_B8C5: creditText 1,"MUSIC COMPOSER"
byte_B8E2: creditText 0,"MASATO NAKAMURA"
byte_B902: creditText 0,"( @1992"
byte_B90F: creditText 0,"DREAMS COME TRUE)"
byte_B932: creditText 1,"SOUND PROGRAMMER"
byte_B954: creditText 0,"TOMOYUKI SHIMADA"
byte_B974: creditText 1,"SOUND ASSISTANTS"
byte_B995: creditText 0,"MACKY"
byte_B9A1: creditText 0,"JIMITA"
byte_B9AD: creditText 0,"MILPO"
byte_B9B8: creditText 0,"IPPO"
byte_B9C1: creditText 0,"S.O"
byte_B9C8: creditText 0,"OYZ"
byte_B9D0: creditText 0,"N.GEE"
byte_B9DB: creditText 1,"PROJECT ASSISTANTS"
byte_BA00: creditText 0,"SYUICHI KATAGI"
byte_BA1B: creditText 0,"TAKAHIRO HAMANO"
byte_BA3A: creditText 0,"YOSHIKI OOKA"
byte_BA52: creditText 0,"STEVE WOITA"
byte_BA69: creditText 1,"GAME MANUAL"
byte_BA81: creditText 0,"YOUICHI TAKAHASHI"
byte_BAA2: creditText 1,"SUPPORTERS"
byte_BAB8: creditText 0,"DAIZABUROU SAKURAI"
byte_BADC: creditText 0,"HISASHI SUZUKI"
if gameRevision=0
byte_BAF7: creditText 0,"TOHMAS KALINSKE" ; typo
else
byte_BAF7: creditText 0,"THOMAS KALINSKE"
endif
byte_BB16: creditText 0,"FUJIO MINEGISHI"
byte_BB32: creditText 0,"TAKAHARU UTSUNOMIYA"
byte_BB58: creditText 1,"SPECIAL THANKS"
byte_BB75: creditText 1,"TO"
byte_BB7B: creditText 0,"CINDY CLAVERAN"
byte_BB98: creditText 0,"DEBORAH MCCRACKEN"
byte_BBBC: creditText 0,"TATSUO YAMADA"
byte_BBD8: creditText 0,"DAISUKE SAITO"
byte_BBF2: creditText 0,"KUNITAKE AOKI"
byte_BC0C: creditText 0,"TSUNEKO AOKI"
byte_BC25: creditText 0,"MASAAKI KAWAMURA"
byte_BC46: creditText 0,"SONIC"
byte_BC51: creditText 1,"2"
byte_BC55: creditText 0,"CAST OF CHARACTERS"
byte_BC7B: creditText 0,"PRESENTED"
byte_BC8F: creditText 0,"BY"
byte_BC95: creditText 0,"SEGA"
byte_BC9F: creditText 0,"FRANCE TANTIADO"
byte_BCBE: creditText 0,"RICK MACARAEG"
byte_BCD9: creditText 0,"LOCKY P"
charset ; have to revert character set before changing again
; temporarily remap characters to intro text format
charset '@',"\x3A\1\3\5\7\9\xB\xD\xF\x11\x12\x14\x16\x18\x1A\x1C\x1E\x20\x22\x24\x26\x28\x2A\x2C\x2E\x30\x32"
charset 'a',"\2\4\6\8\xA\xC\xE\x10\x11\x13\x15\x17\x19\x1B\x1D\x1F\x21\x23\x25\x27\x29\x2B\x2D\x2F\x31\x33"
charset '!',"\x3C\x38\x3E\x35"
charset '\H',"\x38\x36\x37"
charset '9',"\x3D\x3F\x40"
charset '1',"\x3B\x34"
charset '.',"\x39"
charset ' ',0
; intro text
vram_src := ArtTile_ArtNem_CreditText
byte_BCE9: creditText 0,"IN"
byte_BCEE: creditText 0,"AND"
byte_BCF6: creditText 0,"MILES 'TAILS' PROWER"
byte_BD1A: creditText 0,"SONIC"
charset ; revert character set
even
; -------------------------------------------------------------------------------
; Nemesis compressed art
; 64 blocks
; Standard font used in credits
; -------------------------------------------------------------------------------
; ArtNem_BD26:
ArtNem_CreditText: BINCLUDE "art/nemesis/Credit Text.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo5_DisplaySprite
jmp (DisplaySprite).l
JmpTo3_DeleteObject
jmp (DeleteObject).l
JmpTo2_PlaySound
jmp (PlaySound).l
JmpTo_ObjB2_Animate_Pilot
jmp (ObjB2_Animate_Pilot).l
JmpTo_AnimateSprite
jmp (AnimateSprite).l
JmpTo_NemDec
jmp (NemDec).l
JmpTo_EniDec
jmp (EniDec).l
JmpTo_ClearScreen
jmp (ClearScreen).l
JmpTo2_PlayMusic
jmp (PlayMusic).l
JmpTo_LoadChildObject
jmp (LoadChildObject).l
; JmpTo2_PlaneMapToVRAM_H40
JmpTo2_PlaneMapToVRAM_H40
jmp (PlaneMapToVRAM_H40).l
JmpTo2_ObjectMove
jmp (ObjectMove).l
JmpTo_PalCycle_Load
jmp (PalCycle_Load).l
JmpTo_LoadSubObject_Part3
jmp (LoadSubObject_Part3).l
align 4
endif
; ---------------------------------------------------------------------------
; Subroutine to load level boundaries and start locations
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_BFBC:
LevelSizeLoad:
clr.w (Scroll_flags).w
clr.w (Scroll_flags_BG).w
clr.w (Scroll_flags_BG2).w
clr.w (Scroll_flags_BG3).w
clr.w (Scroll_flags_P2).w
clr.w (Scroll_flags_BG_P2).w
clr.w (Scroll_flags_BG2_P2).w
clr.w (Scroll_flags_BG3_P2).w
clr.w (Scroll_flags_copy).w
clr.w (Scroll_flags_BG_copy).w
clr.w (Scroll_flags_BG2_copy).w
clr.w (Scroll_flags_BG3_copy).w
clr.w (Scroll_flags_copy_P2).w
clr.w (Scroll_flags_BG_copy_P2).w
clr.w (Scroll_flags_BG2_copy_P2).w
clr.w (Scroll_flags_BG3_copy_P2).w
clr.b (Deform_lock).w
clr.b (Screen_Shaking_Flag_HTZ).w
clr.b (Screen_Shaking_Flag).w
clr.b (Scroll_lock).w
clr.b (Scroll_lock_P2).w
moveq #0,d0
move.b d0,(Dynamic_Resize_Routine).w ; load level boundaries
if gameRevision=2
move.w d0,(WFZ_LevEvent_Subrout).w
move.w d0,(WFZ_BG_Y_Speed).w
move.w d0,(Camera_BG_X_offset).w
move.w d0,(Camera_BG_Y_offset).w
endif
move.w (Current_ZoneAndAct).w,d0
ror.b #1,d0
lsr.w #4,d0
lea LevelSize(pc,d0.w),a0
move.l (a0)+,d0
move.l d0,(Camera_Min_X_pos).w
move.l d0,(unk_EEC0).w ; unused besides this one write...
move.l d0,(Tails_Min_X_pos).w
move.l (a0)+,d0
move.l d0,(Camera_Min_Y_pos).w
; Warning: unk_EEC4 is only a word long, this line also writes to Camera_Max_Y_pos
; If you remove this instruction, the camera will scroll up until it kills Sonic
move.l d0,(unk_EEC4).w ; unused besides this one write...
move.l d0,(Tails_Min_Y_pos).w
move.w #$1010,(Horiz_block_crossed_flag).w
move.w #(224/2)-16,(Camera_Y_pos_bias).w
move.w #(224/2)-16,(Camera_Y_pos_bias_P2).w
bra.w +
; ===========================================================================
; ----------------------------------------------------------------------------
; LEVEL SIZE ARRAY
; This array defines the screen boundaries for each act in the game.
; ----------------------------------------------------------------------------
; xstart xend ystart yend ; ZID ; Zone
LevelSize: zoneOrderedTable 2,8 ; WrdArr_LvlSize
zoneTableEntry.w $0, $29A0, $0, $320 ; EHZ act 1
zoneTableEntry.w $0, $2940, $0, $420 ; EHZ act 2
zoneTableEntry.w $0, $3FFF, $0, $720 ; $01
zoneTableEntry.w $0, $3FFF, $0, $720
zoneTableEntry.w $0, $3FFF, $0, $720 ; $02
zoneTableEntry.w $0, $3FFF, $0, $720
zoneTableEntry.w $0, $3FFF, $0, $720 ; $03
zoneTableEntry.w $0, $3FFF, $0, $720
zoneTableEntry.w $0, $2280, -$100, $800 ; MTZ act 1
zoneTableEntry.w $0, $1E80, -$100, $800 ; MTZ act 2
zoneTableEntry.w $0, $2A80, -$100, $800 ; MTZ act 3
zoneTableEntry.w $0, $3FFF, -$100, $800
zoneTableEntry.w $0, $3FFF, $0, $720 ; WFZ
zoneTableEntry.w $0, $3FFF, $0, $720
zoneTableEntry.w $0, $2800, $0, $720 ; HTZ act 1
zoneTableEntry.w $0, $3280, $0, $720 ; HTZ act 2
zoneTableEntry.w $0, $3FFF, $0, $720 ; $08
zoneTableEntry.w $0, $3FFF, $0, $720
zoneTableEntry.w $0, $3FFF, $0, $720 ; $09
zoneTableEntry.w $0, $3FFF, $0, $720
zoneTableEntry.w $0, $2F80, $0, $680 ; OOZ act 1
zoneTableEntry.w $0, $2D00, $0, $680 ; OOZ act 2
zoneTableEntry.w $0, $2380, $3C0, $720 ; MCZ act 1
zoneTableEntry.w $0, $3FFF, $60, $720 ; MCZ act 2
zoneTableEntry.w $0, $27A0, $0, $720 ; CNZ act 1
zoneTableEntry.w $0, $2A80, $0, $720 ; CNZ act 2
zoneTableEntry.w $0, $2780, $0, $720 ; CPZ act 1
zoneTableEntry.w $0, $2A80, $0, $720 ; CPZ act 2
zoneTableEntry.w $0, $1000, $C8, $C8 ; DEZ
zoneTableEntry.w $0, $1000, $C8, $C8
zoneTableEntry.w $0, $28C0, $200, $600 ; ARZ act 1
zoneTableEntry.w $0, $3FFF, $180, $710 ; ARZ act 2
zoneTableEntry.w $0, $3FFF, $0, $000 ; SCZ
zoneTableEntry.w $0, $3FFF, $0, $720
zoneTableEnd
; ===========================================================================
+
tst.b (Last_star_pole_hit).w ; was a star pole hit yet?
beq.s + ; if not, branch
jsr (Obj79_LoadData).l ; load the previously saved data
move.w (MainCharacter+x_pos).w,d1
move.w (MainCharacter+y_pos).w,d0
bra.s ++
; ===========================================================================
+ ; Put the character at the start location for the level
move.w (Current_ZoneAndAct).w,d0
ror.b #1,d0
lsr.w #5,d0
lea StartLocations(pc,d0.w),a1
moveq #0,d1
move.w (a1)+,d1
move.w d1,(MainCharacter+x_pos).w
moveq #0,d0
move.w (a1),d0
move.w d0,(MainCharacter+y_pos).w
+
subi.w #$A0,d1
bcc.s +
moveq #0,d1
+
move.w (Camera_Max_X_pos).w,d2
cmp.w d2,d1
blo.s +
move.w d2,d1
+
move.w d1,(Camera_X_pos).w
move.w d1,(Camera_X_pos_P2).w
subi.w #$60,d0
bcc.s +
moveq #0,d0
+
cmp.w (Camera_Max_Y_pos_now).w,d0
blt.s +
move.w (Camera_Max_Y_pos_now).w,d0
+
move.w d0,(Camera_Y_pos).w
move.w d0,(Camera_Y_pos_P2).w
bsr.w InitCameraValues
rts
; End of function LevelSizeLoad
; ===========================================================================
; --------------------------------------------------------------------------------------
; CHARACTER START LOCATION ARRAY
; 2 entries per act, corresponding to the X and Y locations that you want the player to
; appear at when the level starts.
; --------------------------------------------------------------------------------------
StartLocations: zoneOrderedTable 2,4 ; WrdArr_StartLoc
zoneTableBinEntry 2, "startpos/EHZ_1.bin" ; $00
zoneTableBinEntry 2, "startpos/EHZ_2.bin"
zoneTableEntry.w $60, $28F ; $01
zoneTableEntry.w $60, $2AF
zoneTableEntry.w $60, $1AC ; $02
zoneTableEntry.w $60, $1AC
zoneTableEntry.w $60, $28F ; $03
zoneTableEntry.w $60, $2AF
zoneTableBinEntry 2, "startpos/MTZ_1.bin" ; $04
zoneTableBinEntry 2, "startpos/MTZ_2.bin"
zoneTableBinEntry 2, "startpos/MTZ_3.bin" ; $05
zoneTableEntry.w $60, $2AF
zoneTableBinEntry 2, "startpos/WFZ.bin" ; $06
zoneTableEntry.w $1E0, $4CC
zoneTableBinEntry 2, "startpos/HTZ_1.bin" ; $07
zoneTableBinEntry 2, "startpos/HTZ_2.bin"
zoneTableEntry.w $230, $1AC ; $08
zoneTableEntry.w $230, $1AC
zoneTableEntry.w $60, $28F ; $09
zoneTableEntry.w $60, $2AF
zoneTableBinEntry 2, "startpos/OOZ_1.bin" ; $0A
zoneTableBinEntry 2, "startpos/OOZ_2.bin"
zoneTableBinEntry 2, "startpos/MCZ_1.bin" ; $0B
zoneTableBinEntry 2, "startpos/MCZ_2.bin"
zoneTableBinEntry 2, "startpos/CNZ_1.bin" ; $0C
zoneTableBinEntry 2, "startpos/CNZ_2.bin"
zoneTableBinEntry 2, "startpos/CPZ_1.bin" ; $0D
zoneTableBinEntry 2, "startpos/CPZ_2.bin"
zoneTableBinEntry 2, "startpos/DEZ.bin" ; $0E
zoneTableEntry.w $60, $12D
zoneTableBinEntry 2, "startpos/ARZ_1.bin" ; $0F
zoneTableBinEntry 2, "startpos/ARZ_2.bin"
zoneTableBinEntry 2, "startpos/SCZ.bin" ; $10
zoneTableEntry.w $140, $70
zoneTableEnd
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_C258:
InitCameraValues:
tst.b (Last_star_pole_hit).w ; was a star pole hit yet?
bne.s + ; if yes, branch
move.w d0,(Camera_BG_Y_pos).w
move.w d0,(Camera_BG2_Y_pos).w
move.w d1,(Camera_BG_X_pos).w
move.w d1,(Camera_BG2_X_pos).w
move.w d1,(Camera_BG3_X_pos).w
move.w d0,(Camera_BG_Y_pos_P2).w
move.w d0,(Camera_BG2_Y_pos_P2).w
move.w d1,(Camera_BG_X_pos_P2).w
move.w d1,(Camera_BG2_X_pos_P2).w
move.w d1,(Camera_BG3_X_pos_P2).w
+
moveq #0,d2
move.b (Current_Zone).w,d2
add.w d2,d2
move.w InitCam_Index(pc,d2.w),d2
jmp InitCam_Index(pc,d2.w)
; End of function InitCameraValues
; ===========================================================================
; off_C296:
InitCam_Index: zoneOrderedOffsetTable 2,1
zoneOffsetTableEntry.w InitCam_EHZ
zoneOffsetTableEntry.w InitCam_Null0 ; 1
zoneOffsetTableEntry.w InitCam_WZ ; 2
zoneOffsetTableEntry.w InitCam_Null0 ; 3
zoneOffsetTableEntry.w InitCam_Std ; 4 MTZ
zoneOffsetTableEntry.w InitCam_Std ; 5 MTZ3
zoneOffsetTableEntry.w InitCam_Null1 ; 6
zoneOffsetTableEntry.w InitCam_HTZ ; 7
zoneOffsetTableEntry.w InitCam_HPZ ; 8
zoneOffsetTableEntry.w InitCam_Null2 ; 9
zoneOffsetTableEntry.w InitCam_OOZ ; 10
zoneOffsetTableEntry.w InitCam_MCZ ; 11
zoneOffsetTableEntry.w InitCam_CNZ ; 12
zoneOffsetTableEntry.w InitCam_CPZ ; 13
zoneOffsetTableEntry.w InitCam_Null3 ; 14
zoneOffsetTableEntry.w InitCam_ARZ ; 15
zoneOffsetTableEntry.w InitCam_SCZ ; 16
zoneTableEnd
; ===========================================================================
;loc_C2B8:
InitCam_EHZ:
clr.l (Camera_BG_X_pos).w
clr.l (Camera_BG_Y_pos).w
clr.l (Camera_BG2_Y_pos).w
clr.l (Camera_BG3_Y_pos).w
lea (TempArray_LayerDef).w,a2
clr.l (a2)+
clr.l (a2)+
clr.l (a2)+
clr.l (Camera_BG_X_pos_P2).w
clr.l (Camera_BG_Y_pos_P2).w
clr.l (Camera_BG2_Y_pos_P2).w
clr.l (Camera_BG3_Y_pos_P2).w
rts
; ===========================================================================
; wtf:
InitCam_Null0:
if gameRevision=0
rts
endif
; ===========================================================================
; Wood_Zone_BG:
InitCam_WZ:
if gameRevision=0
asr.w #2,d0
addi.w #$400,d0
move.w d0,(Camera_BG_Y_pos).w
asr.w #3,d1
move.w d1,(Camera_BG_X_pos).w
rts
endif
; ===========================================================================
;loc_C2E4:
InitCam_Std:
asr.w #2,d0
move.w d0,(Camera_BG_Y_pos).w
asr.w #3,d1
move.w d1,(Camera_BG_X_pos).w
rts
; ===========================================================================
;return_C2F2:
InitCam_Null1:
rts
; ===========================================================================
;loc_C2F4:
InitCam_HTZ:
clr.l (Camera_BG_X_pos).w
clr.l (Camera_BG_Y_pos).w
clr.l (Camera_BG2_Y_pos).w
clr.l (Camera_BG3_Y_pos).w
lea (TempArray_LayerDef).w,a2
clr.l (a2)+
clr.l (a2)+
clr.l (a2)+
clr.l (Camera_BG_X_pos_P2).w
clr.l (Camera_BG_Y_pos_P2).w
clr.l (Camera_BG2_Y_pos_P2).w
clr.l (Camera_BG3_Y_pos_P2).w
rts
; ===========================================================================
; Hidden_Palace_Zone_BG:
InitCam_HPZ:
if gameRevision=0
asr.w #1,d0
move.w d0,(Camera_BG_Y_pos).w
clr.l (Camera_BG_X_pos).w
rts
endif
; ===========================================================================
; Unknown_Zone_BG:
InitCam_CCZ:
if gameRevision=0
asl.l #4,d0
move.l d0,d2
asl.l #1,d0
add.l d2,d0
asr.l #8,d0
addq.w #1,d0
move.w d0,(Camera_BG_Y_pos).w
clr.l (Camera_BG_X_pos).w
rts
endif
; ===========================================================================
;return_C320:
InitCam_Null2:
rts
; ===========================================================================
;loc_C322:
InitCam_OOZ:
lsr.w #3,d0
addi.w #$50,d0
move.w d0,(Camera_BG_Y_pos).w
clr.l (Camera_BG_X_pos).w
rts
; ===========================================================================
;loc_C332:
InitCam_MCZ:
clr.l (Camera_BG_X_pos).w
clr.l (Camera_BG_X_pos_P2).w
tst.b (Current_Act).w
bne.s +
divu.w #3,d0
subi.w #$140,d0
move.w d0,(Camera_BG_Y_pos).w
move.w d0,(Camera_BG_Y_pos_P2).w
rts
; ===========================================================================
+
divu.w #6,d0
subi.w #$10,d0
move.w d0,(Camera_BG_Y_pos).w
move.w d0,(Camera_BG_Y_pos_P2).w
rts
; ===========================================================================
;loc_C364:
InitCam_CNZ:
clr.l (Camera_BG_X_pos).w
clr.l (Camera_BG_Y_pos).w
clr.l (Camera_BG_Y_pos_P2).w
rts
; ===========================================================================
;loc_C372:
InitCam_CPZ:
lsr.w #2,d0
move.w d0,(Camera_BG_Y_pos).w
move.w d0,(Camera_BG_Y_pos_P2).w
lsr.w #1,d1
move.w d1,(Camera_BG2_X_pos).w
lsr.w #2,d1
move.w d1,(Camera_BG_X_pos).w
rts
; ===========================================================================
;return_C38A:
InitCam_Null3:
rts
; ===========================================================================
;loc_C38C:
InitCam_ARZ:
tst.b (Current_Act).w
beq.s +
subi.w #$E0,d0
lsr.w #1,d0
move.w d0,(Camera_BG_Y_pos).w
bra.s loc_C3A6
; ===========================================================================
+
subi.w #$180,d0
move.w d0,(Camera_BG_Y_pos).w
loc_C3A6:
muls.w #$119,d1
asr.l #8,d1
move.w d1,(Camera_BG_X_pos).w
move.w d1,(Camera_ARZ_BG_X_pos).w
clr.w (Camera_BG_X_pos+2).w
clr.w (Camera_ARZ_BG_X_pos+2).w
clr.l (Camera_BG2_Y_pos).w
clr.l (Camera_BG3_Y_pos).w
rts
; ===========================================================================
;loc_C3C6:
InitCam_SCZ:
clr.l (Camera_BG_X_pos).w
clr.l (Camera_BG_Y_pos).w
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_C3D0:
DeformBgLayer:
tst.b (Deform_lock).w
beq.s +
rts
; ---------------------------------------------------------------------------
+
clr.w (Scroll_flags).w
clr.w (Scroll_flags_BG).w
clr.w (Scroll_flags_BG2).w
clr.w (Scroll_flags_BG3).w
clr.w (Scroll_flags_P2).w
clr.w (Scroll_flags_BG_P2).w
clr.w (Scroll_flags_BG2_P2).w
clr.w (Scroll_flags_BG3_P2).w
clr.w (Camera_X_pos_diff).w
clr.w (Camera_Y_pos_diff).w
clr.w (Camera_X_pos_diff_P2).w
clr.w (Camera_Y_pos_diff_P2).w
cmpi.b #sky_chase_zone,(Current_Zone).w
bne.w +
tst.w (Debug_placement_mode).w
beq.w loc_C4D0 ; skip normal scrolling for SCZ
+
tst.b (Scroll_lock).w
bne.s DeformBgLayerAfterScrollVert
lea (MainCharacter).w,a0 ; a0=character
lea (Camera_X_pos).w,a1
lea (Camera_Min_X_pos).w,a2
lea (Scroll_flags).w,a3
lea (Camera_X_pos_diff).w,a4
lea (Horiz_scroll_delay_val).w,a5
lea (Sonic_Pos_Record_Buf).w,a6
cmpi.w #2,(Player_mode).w
bne.s +
lea (Horiz_scroll_delay_val_P2).w,a5
lea (Tails_Pos_Record_Buf).w,a6
+
bsr.w ScrollHoriz
lea (Horiz_block_crossed_flag).w,a2
bsr.w SetHorizScrollFlags
lea (Camera_Y_pos).w,a1
lea (Camera_Min_X_pos).w,a2
lea (Camera_Y_pos_diff).w,a4
move.w (Camera_Y_pos_bias).w,d3
cmpi.w #2,(Player_mode).w
bne.s +
move.w (Camera_Y_pos_bias_P2).w,d3
+
bsr.w ScrollVerti
lea (Verti_block_crossed_flag).w,a2
bsr.w SetVertiScrollFlags
DeformBgLayerAfterScrollVert:
tst.w (Two_player_mode).w
beq.s loc_C4D0
tst.b (Scroll_lock_P2).w
bne.s loc_C4D0
lea (Sidekick).w,a0 ; a0=character
lea (Camera_X_pos_P2).w,a1
lea (Tails_Min_X_pos).w,a2
lea (Scroll_flags_P2).w,a3
lea (Camera_X_pos_diff_P2).w,a4
lea (Horiz_scroll_delay_val_P2).w,a5
lea (Tails_Pos_Record_Buf).w,a6
bsr.w ScrollHoriz
lea (Horiz_block_crossed_flag_P2).w,a2
bsr.w SetHorizScrollFlags
lea (Camera_Y_pos_P2).w,a1
lea (Tails_Min_X_pos).w,a2
lea (Camera_Y_pos_diff_P2).w,a4
move.w (Camera_Y_pos_bias_P2).w,d3
bsr.w ScrollVerti
lea (Verti_block_crossed_flag_P2).w,a2
bsr.w SetVertiScrollFlags
loc_C4D0:
bsr.w RunDynamicLevelEvents
move.w (Camera_Y_pos).w,(Vscroll_Factor_FG).w
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
move.l (Camera_X_pos).w,(Camera_X_pos_copy).w
move.l (Camera_Y_pos).w,(Camera_Y_pos_copy).w
moveq #0,d0
move.b (Current_Zone).w,d0
add.w d0,d0
move.w SwScrl_Index(pc,d0.w),d0
jmp SwScrl_Index(pc,d0.w)
; End of function DeformBgLayer
; ===========================================================================
; ---------------------------------------------------------------------------
; JUMP TABLE FOR SOFTWARE SCROLL MANAGERS
;
; "Software scrolling" is my term for what Nemesis (and by extension, the rest
; of the world) calls "rasterized layer deformation".* Software scroll managers
; are needed to achieve certain special camera effects - namely, locking the
; screen for a boss fight and defining the limits of said screen lock, or in
; the case of Sky Chase Zone ($10), moving the camera at a fixed rate through
; a predefined course.
; They are also used for things like controlling the parallax scrolling and
; water ripple effects in EHZ, and moving the clouds in HTZ and the stars in DEZ.
; ---------------------------------------------------------------------------
SwScrl_Index: zoneOrderedOffsetTable 2,1 ; JmpTbl_SwScrlMgr
zoneOffsetTableEntry.w SwScrl_EHZ ; $00
zoneOffsetTableEntry.w SwScrl_Minimal ; $01
zoneOffsetTableEntry.w SwScrl_Lev2 ; $02
zoneOffsetTableEntry.w SwScrl_Minimal ; $03
zoneOffsetTableEntry.w SwScrl_MTZ ; $04
zoneOffsetTableEntry.w SwScrl_MTZ ; $05
zoneOffsetTableEntry.w SwScrl_WFZ ; $06
zoneOffsetTableEntry.w SwScrl_HTZ ; $07
zoneOffsetTableEntry.w SwScrl_HPZ ; $08
zoneOffsetTableEntry.w SwScrl_Minimal ; $09
zoneOffsetTableEntry.w SwScrl_OOZ ; $0A
zoneOffsetTableEntry.w SwScrl_MCZ ; $0B
zoneOffsetTableEntry.w SwScrl_CNZ ; $0C
zoneOffsetTableEntry.w SwScrl_CPZ ; $0D
zoneOffsetTableEntry.w SwScrl_DEZ ; $0E
zoneOffsetTableEntry.w SwScrl_ARZ ; $0F
zoneOffsetTableEntry.w SwScrl_SCZ ; $10
zoneTableEnd
; ===========================================================================
; loc_C51E:
SwScrl_Title:
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
addq.w #1,(Camera_X_pos).w
move.w (Camera_X_pos).w,d2
neg.w d2
asr.w #2,d2
lea (Horiz_Scroll_Buf).w,a1
moveq #0,d0
move.w #bytesToLcnt($280),d1
- move.l d0,(a1)+
dbf d1,-
move.w d2,d0
move.w #bytesToLcnt($80),d1
- move.l d0,(a1)+
dbf d1,-
move.w d0,d3
move.b (Vint_runcount+3).w,d1
andi.w #7,d1
bne.s +
subq.w #1,(TempArray_LayerDef).w
+
move.w (TempArray_LayerDef).w,d1
andi.w #$1F,d1
lea SwScrl_RippleData(pc),a2
lea (a2,d1.w),a2
move.w #bytesToLcnt($40),d1
- move.b (a2)+,d0
ext.w d0
add.w d3,d0
move.l d0,(a1)+
dbf d1,-
rts
; ===========================================================================
; loc_C57E:
SwScrl_EHZ:
tst.w (Two_player_mode).w
bne.w SwScrl_EHZ_2P
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
lea (Horiz_Scroll_Buf).w,a1
move.w (Camera_X_pos).w,d0
neg.w d0
move.w d0,d2
swap d0
move.w #0,d0
move.w #bytesToLcnt($58),d1
- move.l d0,(a1)+
dbf d1,-
move.w d2,d0
asr.w #6,d0
move.w #bytesToLcnt($E8),d1
- move.l d0,(a1)+
dbf d1,-
move.w d0,d3
move.b (Vint_runcount+3).w,d1
andi.w #7,d1
bne.s +
subq.w #1,(TempArray_LayerDef).w
+
move.w (TempArray_LayerDef).w,d1
andi.w #$1F,d1
lea (SwScrl_RippleData).l,a2
lea (a2,d1.w),a2
move.w #bytesToLcnt($54),d1
- move.b (a2)+,d0
ext.w d0
add.w d3,d0
move.l d0,(a1)+
dbf d1,-
move.w #0,d0
move.w #bytesToLcnt($2C),d1
- move.l d0,(a1)+
dbf d1,-
move.w d2,d0
asr.w #4,d0
move.w #bytesToLcnt($40),d1
- move.l d0,(a1)+
dbf d1,-
move.w d2,d0
asr.w #4,d0
move.w d0,d1
asr.w #1,d1
add.w d1,d0
move.w #bytesToLcnt($40),d1
- move.l d0,(a1)+
dbf d1,-
move.l d0,d4
swap d4
move.w d2,d0
asr.w #1,d0
move.w d2,d1
asr.w #3,d1
sub.w d1,d0
ext.l d0
asl.l #8,d0
divs.w #$30,d0
ext.l d0
asl.l #8,d0
moveq #0,d3
move.w d2,d3
asr.w #3,d3
move.w #bytesToLcnt($3C),d1 ; $3C bytes
- move.w d4,(a1)+
move.w d3,(a1)+
swap d3
add.l d0,d3
swap d3
dbf d1,-
move.w #($48)/8-1,d1 ; $48 bytes
- move.w d4,(a1)+
move.w d3,(a1)+
move.w d4,(a1)+
move.w d3,(a1)+
swap d3
add.l d0,d3
add.l d0,d3
swap d3
dbf d1,-
move.w #($B4)/12-1,d1 ; $B4 bytes
- move.w d4,(a1)+
move.w d3,(a1)+
move.w d4,(a1)+
move.w d3,(a1)+
move.w d4,(a1)+
move.w d3,(a1)+
swap d3
add.l d0,d3
add.l d0,d3
add.l d0,d3
swap d3
dbf d1,-
; note there is a bug here. the bottom 8 pixels haven't had their hscroll values set. only the EHZ scrolling code has this bug.
rts
; ===========================================================================
; horizontal offsets for the water rippling effect
; byte_C682:
SwScrl_RippleData:
dc.b 1, 2, 1, 3, 1, 2, 2, 1, 2, 3, 1, 2, 1, 2, 0, 0; 16
dc.b 2, 0, 3, 2, 2, 3, 2, 2, 1, 3, 0, 0, 1, 0, 1, 3; 32
dc.b 1, 2, 1, 3, 1, 2, 2, 1, 2, 3, 1, 2, 1, 2, 0, 0; 48
dc.b 2, 0, 3, 2, 2, 3, 2, 2, 1, 3, 0, 0, 1, 0, 1, 3; 64
dc.b 1, 2 ; 66
; ===========================================================================
; loc_C6C4:
SwScrl_EHZ_2P:
move.b (Vint_runcount+3).w,d1
andi.w #7,d1
bne.s +
subq.w #1,(TempArray_LayerDef).w
+
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
andi.l #$FFFEFFFE,(Vscroll_Factor).w
lea (Horiz_Scroll_Buf).w,a1
move.w (Camera_X_pos).w,d0
move.w #bytesToLcnt($2C),d1
bsr.s sub_C71A
moveq #0,d0
move.w d0,(Vscroll_Factor_P2_BG).w
subi.w #$E0,(Vscroll_Factor_P2_BG).w
move.w (Camera_Y_pos_P2).w,(Vscroll_Factor_P2_FG).w
subi.w #$E0,(Vscroll_Factor_P2_FG).w
andi.l #$FFFEFFFE,(Vscroll_Factor_P2).w
lea (Horiz_Scroll_Buf+$1B0).w,a1
move.w (Camera_X_pos_P2).w,d0
move.w #bytesToLcnt($3C),d1
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_C71A:
neg.w d0
move.w d0,d2
swap d0
move.w #0,d0
- move.l d0,(a1)+
dbf d1,-
move.w d2,d0
asr.w #6,d0
move.w #bytesToLcnt($74),d1
- move.l d0,(a1)+
dbf d1,-
move.w d0,d3
move.w (TempArray_LayerDef).w,d1
andi.w #$1F,d1
lea_ SwScrl_RippleData,a2
lea (a2,d1.w),a2
move.w #bytesToLcnt($2C),d1
- move.b (a2)+,d0
ext.w d0
add.w d3,d0
move.l d0,(a1)+
dbf d1,-
move.w #0,d0
move.w #bytesToLcnt($14),d1
- move.l d0,(a1)+
dbf d1,-
move.w d2,d0
asr.w #4,d0
move.w #bytesToLcnt($20),d1
- move.l d0,(a1)+
dbf d1,-
move.w d2,d0
asr.w #4,d0
move.w d0,d1
asr.w #1,d1
add.w d1,d0
move.w #bytesToLcnt($20),d1
- move.l d0,(a1)+
dbf d1,-
move.w d2,d0
asr.w #1,d0
move.w d2,d1
asr.w #3,d1
sub.w d1,d0
ext.l d0
asl.l #8,d0
divs.w #$30,d0
ext.l d0
asl.l #8,d0
moveq #0,d3
move.w d2,d3
asr.w #3,d3
move.w #bytesToLcnt($A0),d1
- move.w d2,(a1)+
move.w d3,(a1)+
swap d3
add.l d0,d3
swap d3
dbf d1,-
rts
; End of function sub_C71A
; ===========================================================================
; unused...
; loc_C7BA:
SwScrl_Lev2:
if gameRevision<2
move.w (Camera_X_pos_diff).w,d4
ext.l d4
asl.l #5,d4
move.w (Camera_Y_pos_diff).w,d5
ext.l d5
asl.l #6,d5
bsr.w SetHorizVertiScrollFlagsBG
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
lea (Horiz_Scroll_Buf).w,a1
move.w #bytesToLcnt($380),d1
move.w (Camera_X_pos).w,d0
neg.w d0
swap d0
move.w (Camera_BG_X_pos).w,d0
neg.w d0
- move.l d0,(a1)+
dbf d1,-
endif
rts
; ===========================================================================
; loc_C7F2:
SwScrl_MTZ:
move.w (Camera_X_pos_diff).w,d4
ext.l d4
asl.l #5,d4
move.w (Camera_Y_pos_diff).w,d5
ext.l d5
asl.l #6,d5
bsr.w SetHorizVertiScrollFlagsBG
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
lea (Horiz_Scroll_Buf).w,a1
move.w #bytesToLcnt($380),d1
move.w (Camera_X_pos).w,d0
neg.w d0
swap d0
move.w (Camera_BG_X_pos).w,d0
neg.w d0
- move.l d0,(a1)+
dbf d1,-
rts
; ===========================================================================
; loc_C82A:
SwScrl_WFZ:
move.w (Camera_BG_X_pos_diff).w,d4
ext.l d4
asl.l #8,d4
moveq #2,d6
bsr.w SetHorizScrollFlagsBG
move.w (Camera_BG_Y_pos_diff).w,d5
ext.l d5
lsl.l #8,d5
moveq #6,d6
bsr.w SetVertiScrollFlagsBG
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
move.l (Camera_BG_X_pos).w,d0
; This can be removed if the getaway ship's entry uses d0 instead.
move.l d0,d1
lea (TempArray_LayerDef).w,a2
move.l d0,(a2)+ ; Static parts of BG (generally no clouds in them)
move.l d1,(a2)+ ; Eggman's getaway ship
; Note: this is bugged: this tallies only the cloud speeds. It works fine
; if you are standing still, but makes the clouds move faster when going
; right and slower when going left. This is exactly the opposite of what
; should happen.
addi.l #$8000,(a2)+ ; Larger clouds
addi.l #$4000,(a2)+ ; Medium clouds
addi.l #$2000,(a2)+ ; Small clouds
lea (SwScrl_WFZ_Transition_Array).l,a3
cmpi.w #$2700,(Camera_X_pos).w
bhs.s .got_array
lea (SwScrl_WFZ_Normal_Array).l,a3
.got_array:
lea (TempArray_LayerDef).w,a2
lea (Horiz_Scroll_Buf).w,a1
move.w (Camera_BG_Y_pos).w,d1
andi.w #$7FF,d1
moveq #0,d0
moveq #0,d3
; Find the first visible scrolling section
.seg_loop:
move.b (a3)+,d0 ; Number of lines in this segment
addq.w #1,a3 ; Skip index
sub.w d0,d1 ; Does this segment have any visible lines?
bcc.s .seg_loop ; Branch if not
neg.w d1 ; d1 = number of lines to draw in this segment
move.w #bytesToLcnt($380),d2 ; Number of rows in hscroll buffer
move.w (Camera_X_pos).w,d0
neg.w d0
swap d0
move.b -1(a3),d3 ; Fetch TempArray_LayerDef index
move.w (a2,d3.w),d0 ; Fetch scroll value for this row...
neg.w d0 ; ... and flip sign for VDP
.row_loop:
move.l d0,(a1)+
subq.w #1,d1 ; Has the current segment finished?
bne.s .next_row ; Branch if not
move.b (a3)+,d1 ; Fetch a new line count
move.b (a3)+,d3 ; Fetch TempArray_LayerDef index
move.w (a2,d3.w),d0 ; Fetch scroll value for this row...
neg.w d0 ; ... and flip sign for VDP
.next_row:
dbf d2,.row_loop
rts
; ===========================================================================
; WFZ BG scrolling data
; Each pair of bytes corresponds to one scrolling segment of the BG, and
; the bytes have the following meaning:
; number of lines, index into TempArray_LayerDef
; byte_C8CA
SwScrl_WFZ_Transition_Array:
dc.b $C0, 0,$C0, 0,$80, 0,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C
dc.b $30,$10,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C,$30,$10,$20, 8; 16
dc.b $30, $C,$30,$10,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C,$30,$10; 32
dc.b $80, 4,$80, 4,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C,$30,$10; 48
dc.b $20, 8,$30, $C,$30,$10,$C0, 0,$C0, 0,$80, 0; 64
;byte_C916
SwScrl_WFZ_Normal_Array:
dc.b $C0, 0,$C0, 0,$80, 0,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C
dc.b $30,$10,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C,$30,$10,$20, 8; 16
dc.b $30, $C,$30,$10,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C,$30,$10; 32
dc.b $20, 8,$30, $C,$30,$10,$20, 8,$30, $C,$30,$10,$20, 8,$30, $C; 48
dc.b $30,$10,$20, 8,$30, $C,$30,$10,$C0, 0,$C0, 0,$80, 0; 64
; Note: this array is missing $80 lines compared to the transition array.
; This causes the lower clouds to read data from the start of SwScrl_HTZ.
; These are the missing entries:
if 1==0
dc.b $20, 8,$30, $C,$30,$10
endif
; ===========================================================================
; loc_C964:
SwScrl_HTZ:
tst.w (Two_player_mode).w
bne.w SwScrl_HTZ_2P ; never used in normal gameplay
tst.b (Screen_Shaking_Flag_HTZ).w
bne.w HTZ_Screen_Shake
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
lea (Horiz_Scroll_Buf).w,a1
move.w (Camera_X_pos).w,d0
neg.w d0
move.w d0,d2
swap d0
move.w d2,d0
asr.w #3,d0
move.w #bytesToLcnt($200),d1
- move.l d0,(a1)+
dbf d1,-
move.l d0,d4
move.w (TempArray_LayerDef+$22).w,d0
addq.w #4,(TempArray_LayerDef+$22).w
sub.w d0,d2
move.w d2,d0
move.w d0,d1
asr.w #1,d0
asr.w #4,d1
sub.w d1,d0
ext.l d0
asl.l #8,d0
divs.w #$70,d0
ext.l d0
asl.l #8,d0
lea (TempArray_LayerDef).w,a2
moveq #0,d3
move.w d1,d3
swap d3
add.l d0,d3
swap d3
move.w d3,(a2)+
swap d3
add.l d0,d3
swap d3
move.w d3,(a2)+
swap d3
add.l d0,d3
swap d3
move.w d3,(a2)+
move.w d3,(a2)+
swap d3
add.l d0,d3
add.l d0,d3
swap d3
moveq #3,d1
- move.w d3,(a2)+
move.w d3,(a2)+
move.w d3,(a2)+
swap d3
add.l d0,d3
add.l d0,d3
add.l d0,d3
swap d3
dbf d1,-
add.l d0,d0
add.l d0,d0
move.w d3,d4
move.l d4,(a1)+
move.l d4,(a1)+
move.l d4,(a1)+
swap d3
add.l d0,d3
swap d3
move.w d3,d4
move.l d4,(a1)+
move.l d4,(a1)+
move.l d4,(a1)+
move.l d4,(a1)+
move.l d4,(a1)+
swap d3
add.l d0,d3
swap d3
move.w d3,d4
move.w #6,d1
- move.l d4,(a1)+
dbf d1,-
swap d3
add.l d0,d3
add.l d0,d3
swap d3
move.w d3,d4
move.w #7,d1
- move.l d4,(a1)+
dbf d1,-
swap d3
add.l d0,d3
add.l d0,d3
swap d3
move.w d3,d4
move.w #9,d1
- move.l d4,(a1)+
dbf d1,-
swap d3
add.l d0,d3
add.l d0,d3
add.l d0,d3
swap d3
move.w d3,d4
move.w #$E,d1
- move.l d4,(a1)+
dbf d1,-
swap d3
add.l d0,d3
add.l d0,d3
add.l d0,d3
swap d3
move.w #2,d2
- move.w d3,d4
move.w #$F,d1
- move.l d4,(a1)+
dbf d1,-
swap d3
add.l d0,d3
add.l d0,d3
add.l d0,d3
add.l d0,d3
swap d3
dbf d2,--
rts
; ===========================================================================
;loc_CA92:
HTZ_Screen_Shake:
move.w (Camera_BG_X_pos_diff).w,d4
ext.l d4
lsl.l #8,d4
moveq #2,d6
bsr.w SetHorizScrollFlagsBG
move.w (Camera_BG_Y_pos_diff).w,d5
ext.l d5
lsl.l #8,d5
moveq #0,d6
bsr.w SetVertiScrollFlagsBG
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
move.w (Camera_Y_pos).w,(Vscroll_Factor_FG).w
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
moveq #0,d2
tst.b (Screen_Shaking_Flag).w
beq.s +
move.w (Timer_frames).w,d0
andi.w #$3F,d0
lea_ SwScrl_RippleData,a1
lea (a1,d0.w),a1
moveq #0,d0
move.b (a1)+,d0
add.w d0,(Vscroll_Factor_FG).w
add.w d0,(Vscroll_Factor_BG).w
add.w d0,(Camera_Y_pos_copy).w
move.b (a1)+,d2
add.w d2,(Camera_X_pos_copy).w
+
lea (Horiz_Scroll_Buf).w,a1
move.w #bytesToLcnt($380),d1
move.w (Camera_X_pos).w,d0
add.w d2,d0
neg.w d0
swap d0
move.w (Camera_BG_X_pos).w,d0
add.w d2,d0
neg.w d0
- move.l d0,(a1)+
dbf d1,-
rts
; ===========================================================================
; loc_CB10:
SwScrl_HTZ_2P:
move.w (Camera_X_pos_diff).w,d4
ext.l d4
asl.l #6,d4
move.w (Camera_Y_pos_diff).w,d5
ext.l d5
asl.l #2,d5
moveq #0,d5
bsr.w SetHorizVertiScrollFlagsBG
move.b #0,(Scroll_flags_BG).w
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
andi.l #$FFFEFFFE,(Vscroll_Factor).w
lea (Horiz_Scroll_Buf).w,a1
move.w #bytesToLcnt($1C0),d1
move.w (Camera_X_pos).w,d0
neg.w d0
swap d0
move.w (Camera_BG_X_pos).w,d0
neg.w d0
- move.l d0,(a1)+
dbf d1,-
move.w (Camera_X_pos_diff_P2).w,d4
ext.l d4
asl.l #6,d4
add.l d4,(Camera_BG_X_pos_P2).w
moveq #0,d0
move.w d0,(Vscroll_Factor_P2_BG).w
subi.w #$E0,(Vscroll_Factor_P2_BG).w
move.w (Camera_Y_pos_P2).w,(Vscroll_Factor_P2_FG).w
subi.w #$E0,(Vscroll_Factor_P2_FG).w
andi.l #$FFFEFFFE,(Vscroll_Factor_P2).w
lea (Horiz_Scroll_Buf+$1B0).w,a1
move.w #bytesToLcnt($1D0),d1
move.w (Camera_X_pos_P2).w,d0
neg.w d0
swap d0
move.w (Camera_BG_X_pos_P2).w,d0
neg.w d0
- move.l d0,(a1)+
dbf d1,-
rts
; ===========================================================================
; unused...
; loc_CBA0:
SwScrl_HPZ:
move.w (Camera_X_pos_diff).w,d4
ext.l d4
asl.l #6,d4
moveq #2,d6
bsr.w SetHorizScrollFlagsBG
move.w (Camera_Y_pos_diff).w,d5
ext.l d5
asl.l #7,d5
moveq #6,d6
bsr.w SetVertiScrollFlagsBG
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
lea (TempArray_LayerDef).w,a1
move.w (Camera_X_pos).w,d2
neg.w d2
move.w d2,d0
asr.w #1,d0
move.w #7,d1
- move.w d0,(a1)+
dbf d1,-
move.w d2,d0
asr.w #3,d0
sub.w d2,d0
ext.l d0
asl.l #3,d0
divs.w #8,d0
ext.l d0
asl.l #4,d0
asl.l #8,d0
moveq #0,d3
move.w d2,d3
asr.w #1,d3
lea (TempArray_LayerDef+$60).w,a2
swap d3
add.l d0,d3
swap d3
move.w d3,(a1)+
move.w d3,(a1)+
move.w d3,(a1)+
move.w d3,-(a2)
move.w d3,-(a2)
move.w d3,-(a2)
swap d3
add.l d0,d3
swap d3
move.w d3,(a1)+
move.w d3,(a1)+
move.w d3,-(a2)
move.w d3,-(a2)
swap d3
add.l d0,d3
swap d3
move.w d3,(a1)+
move.w d3,-(a2)
swap d3
add.l d0,d3
swap d3
move.w d3,(a1)+
move.w d3,-(a2)
move.w (Camera_BG_X_pos).w,d0
neg.w d0
move.w #$19,d1
- move.w d0,(a1)+
dbf d1,-
adda.w #$E,a1
move.w d2,d0
asr.w #1,d0
move.w #$17,d1
- move.w d0,(a1)+
dbf d1,-
lea (TempArray_LayerDef).w,a2
move.w (Camera_BG_Y_pos).w,d0
move.w d0,d2
andi.w #$3F0,d0
lsr.w #3,d0
lea (a2,d0.w),a2
bra.w SwScrl_HPZ_Continued
; ===========================================================================
; loc_CC66:
SwScrl_OOZ:
move.w (Camera_X_pos_diff).w,d0
ext.l d0
asl.l #5,d0
add.l d0,(Camera_BG_X_pos).w
move.w (Camera_Y_pos_diff).w,d0
ext.l d0
asl.l #5,d0
move.l (Camera_BG_Y_pos).w,d3
add.l d3,d0
moveq #4,d6
bsr.w SetVertiScrollFlagsBG2
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
lea (Horiz_Scroll_Buf+$380).w,a1
move.w (Camera_X_pos).w,d0
neg.w d0
swap d0
move.w (Camera_BG_X_pos).w,d7
neg.w d7
move.w (Camera_BG_Y_pos).w,d1
subi.w #$50,d1
bcc.s +
moveq #0,d1
+
subi.w #$B0,d1
bcs.s +
moveq #0,d1
+
move.w #$DF,d6
add.w d6,d1
move.w d7,d0
bsr.s OOZ_BGScroll_Lines
bsr.s OOZ_BGScroll_MediumClouds
bsr.s OOZ_BGScroll_SlowClouds
bsr.s OOZ_BGScroll_FastClouds
move.w d7,d0
asr.w #4,d0
moveq #6,d1
bsr.s OOZ_BGScroll_Lines
move.b (Vint_runcount+3).w,d1
andi.w #7,d1
bne.s +
subq.w #1,(TempArray_LayerDef).w
+
move.w (TempArray_LayerDef).w,d1
andi.w #$1F,d1
lea SwScrl_RippleData(pc),a2
lea (a2,d1.w),a2
moveq #$20,d1
- move.b (a2)+,d0
ext.w d0
move.l d0,-(a1)
subq.w #1,d6
bmi.s + ; rts
dbf d1,-
bsr.s OOZ_BGScroll_MediumClouds
bsr.s OOZ_BGScroll_SlowClouds
bsr.s OOZ_BGScroll_FastClouds
bsr.s OOZ_BGScroll_SlowClouds
bsr.s OOZ_BGScroll_MediumClouds
move.w d7,d0
moveq #$47,d1
bsr.s OOZ_BGScroll_Lines
+ rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_CD0A
OOZ_BGScroll_FastClouds:
move.w d7,d0
asr.w #2,d0
bra.s +
; End of function OOZ_BGScroll_FastClouds
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_CD10
OOZ_BGScroll_MediumClouds:
move.w d7,d0
asr.w #3,d0
bra.s +
; End of function OOZ_BGScroll_MediumClouds
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_CD16
OOZ_BGScroll_SlowClouds:
move.w d7,d0
asr.w #4,d0
+
moveq #7,d1
; End of function OOZ_BGScroll_SlowClouds
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Scrolls min(d6,d1+1) lines by an (constant) amount specified in d0
;sub_CD1C
OOZ_BGScroll_Lines:
move.l d0,-(a1)
subq.w #1,d6
bmi.s +
dbf d1,OOZ_BGScroll_Lines
rts
; ===========================================================================
+
addq.l #4,sp
rts
; End of function OOZ_BGScroll_Lines
; ===========================================================================
; loc_CD2C:
SwScrl_MCZ:
tst.w (Two_player_mode).w
bne.w SwScrl_MCZ_2P
move.w (Camera_Y_pos).w,d0
move.l (Camera_BG_Y_pos).w,d3
tst.b (Current_Act).w
bne.s +
divu.w #3,d0
subi.w #$140,d0
bra.s ++
; ===========================================================================
+
divu.w #6,d0
subi.w #$10,d0
+
swap d0
moveq #6,d6
bsr.w SetVertiScrollFlagsBG2
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
moveq #0,d2
tst.b (Screen_Shaking_Flag).w
beq.s +
move.w (Timer_frames).w,d0
andi.w #$3F,d0
lea_ SwScrl_RippleData,a1
lea (a1,d0.w),a1
moveq #0,d0
move.b (a1)+,d0
add.w d0,(Vscroll_Factor_FG).w
add.w d0,(Vscroll_Factor_BG).w
add.w d0,(Camera_Y_pos_copy).w
move.b (a1)+,d2
add.w d2,(Camera_X_pos_copy).w
+
lea (TempArray_LayerDef).w,a2
lea $1E(a2),a3
move.w (Camera_X_pos).w,d0
ext.l d0
asl.l #4,d0
divs.w #$A,d0
ext.l d0
asl.l #4,d0
asl.l #8,d0
move.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,$E(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,$C(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,$A(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,8(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,6(a2)
move.w d1,$10(a2)
move.w d1,$1C(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,4(a2)
move.w d1,$12(a2)
move.w d1,$1A(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,2(a2)
move.w d1,$14(a2)
move.w d1,$18(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,(a2)
move.w d1,$16(a2)
lea (SwScrl_MCZ_RowHeights).l,a3
lea (TempArray_LayerDef).w,a2
lea (Horiz_Scroll_Buf).w,a1
move.w (Camera_BG_Y_pos).w,d1
moveq #0,d0
- move.b (a3)+,d0
addq.w #2,a2
sub.w d0,d1
bcc.s -
neg.w d1
subq.w #2,a2
move.w #bytesToLcnt($380),d2
move.w (Camera_X_pos).w,d0
neg.w d0
swap d0
move.w (a2)+,d0
neg.w d0
- move.l d0,(a1)+
subq.w #1,d1
bne.s +
move.b (a3)+,d1
move.w (a2)+,d0
neg.w d0
+ dbf d2,-
rts
; ===========================================================================
; byte_CE6C:
SwScrl_MCZ_RowHeights:
dc.b $25
dc.b $17 ; 1
dc.b $12 ; 2
dc.b 7 ; 3
dc.b 7 ; 4
dc.b 2 ; 5
dc.b 2 ; 6
dc.b $30 ; 7
dc.b $D ; 8
dc.b $13 ; 9
dc.b $20 ; 10
dc.b $40 ; 11
dc.b $20 ; 12
dc.b $13 ; 13
dc.b $D ; 14
dc.b $30 ; 15
dc.b 2 ; 16
dc.b 2 ; 17
dc.b 7 ; 18
dc.b 7 ; 19
dc.b $20 ; 20
dc.b $12 ; 21
dc.b $17 ; 22
dc.b $25 ; 23
even
; ===========================================================================
; loc_CE84:
SwScrl_MCZ_2P:
moveq #0,d0
move.w (Camera_Y_pos).w,d0
tst.b (Current_Act).w
bne.s +
divu.w #3,d0
subi.w #$140,d0
bra.s ++
; ===========================================================================
+
divu.w #6,d0
subi.w #$10,d0
+
move.w d0,(Camera_BG_Y_pos).w
move.w d0,(Vscroll_Factor_BG).w
andi.l #$FFFEFFFE,(Vscroll_Factor).w
lea (TempArray_LayerDef).w,a2
lea $1E(a2),a3
move.w (Camera_X_pos).w,d0
ext.l d0
asl.l #4,d0
divs.w #$A,d0
ext.l d0
asl.l #4,d0
asl.l #8,d0
move.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,$E(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,$C(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,$A(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,8(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,6(a2)
move.w d1,$10(a2)
move.w d1,$1C(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,4(a2)
move.w d1,$12(a2)
move.w d1,$1A(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,2(a2)
move.w d1,$14(a2)
move.w d1,$18(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,(a2)
move.w d1,$16(a2)
lea (SwScrl_MCZ2P_RowHeights).l,a3
lea (TempArray_LayerDef).w,a2
lea (Horiz_Scroll_Buf).w,a1
move.w (Camera_BG_Y_pos).w,d1
lsr.w #1,d1
moveq #0,d0
- move.b (a3)+,d0
addq.w #2,a2
sub.w d0,d1
bcc.s -
neg.w d1
subq.w #2,a2
move.w #bytesToLcnt($1C0),d2
move.w (Camera_X_pos).w,d0
neg.w d0
swap d0
move.w (a2)+,d0
neg.w d0
- move.l d0,(a1)+
subq.w #1,d1
bne.s +
move.b (a3)+,d1
move.w (a2)+,d0
neg.w d0
+ dbf d2,-
bra.s +
; ===========================================================================
; byte_CF90:
SwScrl_MCZ2P_RowHeights:
dc.b $13
dc.b $B
dc.b 9 ; 1
dc.b 4 ; 2
dc.b 3 ; 3
dc.b 1 ; 4
dc.b 1 ; 5
dc.b $18 ; 6
dc.b 6 ; 7
dc.b $A ; 8
dc.b $10 ; 9
dc.b $20 ; 10
dc.b $10 ; 11
dc.b $A ; 12
dc.b 6 ; 13
dc.b $18 ; 14
dc.b 1 ; 15
dc.b 1 ; 16
dc.b 3 ; 17
dc.b 4 ; 18
dc.b $10 ; 19
dc.b 9 ; 20
dc.b $B ; 21
dc.b $13 ; 22
even
; ===========================================================================
+
moveq #0,d0
move.w (Camera_Y_pos_P2).w,d0
tst.b (Current_Act).w
bne.s +
divu.w #3,d0
subi.w #$140,d0
bra.s ++
; ===========================================================================
+
divu.w #6,d0
subi.w #$10,d0
+
move.w d0,(Camera_BG_Y_pos_P2).w
move.w d0,(Vscroll_Factor_P2_BG).w
subi.w #$E0,(Vscroll_Factor_P2_BG).w
move.w (Camera_Y_pos_P2).w,(Vscroll_Factor_P2_FG).w
subi.w #$E0,(Vscroll_Factor_P2_FG).w
andi.l #$FFFEFFFE,(Vscroll_Factor_P2).w
lea (TempArray_LayerDef).w,a2
lea $1E(a2),a3
move.w (Camera_X_pos_P2).w,d0
ext.l d0
asl.l #4,d0
divs.w #$A,d0
ext.l d0
asl.l #4,d0
asl.l #8,d0
move.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,$E(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,$C(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,$A(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,8(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,6(a2)
move.w d1,$10(a2)
move.w d1,$1C(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,4(a2)
move.w d1,$12(a2)
move.w d1,$1A(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,2(a2)
move.w d1,$14(a2)
move.w d1,$18(a2)
swap d1
add.l d0,d1
swap d1
move.w d1,(a3)+
move.w d1,(a2)
move.w d1,$16(a2)
lea_ SwScrl_MCZ2P_RowHeights+1,a3
lea (TempArray_LayerDef).w,a2
lea (Horiz_Scroll_Buf+$1B0).w,a1
move.w (Camera_BG_Y_pos_P2).w,d1
lsr.w #1,d1
moveq #$17,d0
bra.s +
; ===========================================================================
-
move.b (a3)+,d0
+
addq.w #2,a2
sub.w d0,d1
bcc.s -
neg.w d1
subq.w #2,a2
move.w #bytesToLcnt($1D0),d2
move.w (Camera_X_pos_P2).w,d0
neg.w d0
swap d0
move.w (a2)+,d0
neg.w d0
- move.l d0,(a1)+
subq.w #1,d1
bne.s +
move.b (a3)+,d1
move.w (a2)+,d0
neg.w d0
+ dbf d2,-
rts
; ===========================================================================
; loc_D0C6:
SwScrl_CNZ:
tst.w (Two_player_mode).w
bne.w SwScrl_CNZ_2P
move.w (Camera_Y_pos).w,d0
lsr.w #6,d0
move.w d0,(Camera_BG_Y_pos).w
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
move.w (Camera_X_pos).w,d2
bsr.w sub_D160
lea (SwScrl_CNZ_RowHeights).l,a3
lea (TempArray_LayerDef).w,a2
lea (Horiz_Scroll_Buf).w,a1
move.w (Camera_BG_Y_pos).w,d1
moveq #0,d0
- move.b (a3)+,d0
addq.w #2,a2
sub.w d0,d1
bcc.s -
neg.w d1
subq.w #2,a2
move.w #bytesToLcnt($380),d2
move.w (Camera_X_pos).w,d0
neg.w d0
swap d0
move.w (a2)+,d0
neg.w d0
- move.l d0,(a1)+
subq.w #1,d1
bne.s +
- move.w (a2)+,d0
neg.w d0
move.b (a3)+,d1
beq.s ++
+ dbf d2,--
rts
; ===========================================================================
+
move.w #bytesToLcnt($40),d1
move.w d0,d3
move.b (Vint_runcount+3).w,d0
lsr.w #3,d0
neg.w d0
andi.w #$1F,d0
lea_ SwScrl_RippleData,a4
lea (a4,d0.w),a4
- move.b (a4)+,d0
ext.w d0
add.w d3,d0
move.l d0,(a1)+
dbf d1,-
subi.w #$10,d2
bra.s --
; ===========================================================================
; byte_D156:
SwScrl_CNZ_RowHeights:
dc.b $10
dc.b $10 ; 1
dc.b $10 ; 2
dc.b $10 ; 3
dc.b $10 ; 4
dc.b $10 ; 5
dc.b $10 ; 6
dc.b $10 ; 7
dc.b 0 ; 8
dc.b -$10 ; 9
even
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_D160:
lea (TempArray_LayerDef).w,a1
move.w d2,d0
asr.w #3,d0
sub.w d2,d0
ext.l d0
asl.l #5,d0
asl.l #8,d0
moveq #0,d3
move.w d2,d3
move.w #6,d1
- move.w d3,(a1)+
swap d3
add.l d0,d3
swap d3
dbf d1,-
move.w d2,d0
asr.w #3,d0
move.w d0,4(a1)
asr.w #1,d0
move.w d0,(a1)+
move.w d0,(a1)+
rts
; End of function sub_D160
; ===========================================================================
; loc_D194:
SwScrl_CNZ_2P:
move.w (Camera_Y_pos).w,d0
lsr.w #6,d0
move.w d0,(Camera_BG_Y_pos).w
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
andi.l #$FFFEFFFE,(Vscroll_Factor).w
move.w (Camera_X_pos).w,d2
bsr.w sub_D160
lea (Horiz_Scroll_Buf).w,a1
move.w (Camera_BG_Y_pos).w,d1
moveq #0,d0
move.w (Camera_X_pos).w,d0
move.w #$6F,d2
lea (SwScrl_CNZ2P_RowHeights+2).l,a3
bsr.s sub_D216
move.w (Camera_Y_pos_P2).w,d0
lsr.w #6,d0
move.w d0,(Camera_BG_Y_pos_P2).w
move.w d0,(Vscroll_Factor_P2_BG).w
subi.w #$E0,(Vscroll_Factor_P2_BG).w
move.w (Camera_Y_pos_P2).w,(Vscroll_Factor_P2_FG).w
subi.w #$E0,(Vscroll_Factor_P2_FG).w
andi.l #$FFFEFFFE,(Vscroll_Factor_P2).w
move.w (Camera_X_pos_P2).w,d2
bsr.w sub_D160
lea (Horiz_Scroll_Buf+$1B0).w,a1
move.w (Camera_BG_Y_pos_P2).w,d1
moveq #0,d0
move.w (Camera_X_pos_P2).w,d0
move.w #bytesToLcnt($1D0),d2
lea (SwScrl_CNZ2P_RowHeights+1).l,a3
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_D216:
lsr.w #1,d1
lea (TempArray_LayerDef).w,a2
moveq #0,d3
- move.b (a3)+,d3
addq.w #2,a2
sub.w d3,d1
bcc.s -
neg.w d1
subq.w #2,a2
neg.w d0
swap d0
move.w (a2)+,d0
neg.w d0
- move.l d0,(a1)+
subq.w #1,d1
bne.s +
- move.w (a2)+,d0
neg.w d0
move.b (a3)+,d1
beq.s ++
+
dbf d2,--
rts
; ===========================================================================
+
move.w #bytesToLcnt($20),d1
move.w d0,d3
move.b (Vint_runcount+3).w,d0
lsr.w #3,d0
neg.w d0
andi.w #$1F,d0
lea_ SwScrl_RippleData,a4
lea (a4,d0.w),a4
- move.b (a4)+,d0
ext.w d0
add.w d3,d0
move.l d0,(a1)+
dbf d1,-
subq.w #8,d2
bra.s --
; End of function sub_D216
; ===========================================================================
; byte_D270:
SwScrl_CNZ2P_RowHeights:
dc.b 4
dc.b 4 ; 1
dc.b 8 ; 2
dc.b 8 ; 3
dc.b 8 ; 4
dc.b 8 ; 5
dc.b 8 ; 6
dc.b 8 ; 7
dc.b 8 ; 8
dc.b 8 ; 9
dc.b 0 ; 10
dc.b $78 ; 11
even
; ===========================================================================
; loc_D27C:
SwScrl_CPZ:
move.w (Camera_X_pos_diff).w,d4
ext.l d4
asl.l #5,d4
move.w (Camera_Y_pos_diff).w,d5
ext.l d5
asl.l #6,d5
bsr.w SetHorizVertiScrollFlagsBG
move.w (Camera_X_pos_diff).w,d4
ext.l d4
asl.l #7,d4
moveq #4,d6
bsr.w SetHorizScrollFlagsBG2
move.w (Camera_BG_Y_pos).w,d0
move.w d0,(Camera_BG2_Y_pos).w
move.w d0,(Vscroll_Factor_BG).w
move.b (Scroll_flags_BG).w,d0
or.b (Scroll_flags_BG2).w,d0
move.b d0,(Scroll_flags_BG3).w
clr.b (Scroll_flags_BG).w
clr.b (Scroll_flags_BG2).w
move.b (Vint_runcount+3).w,d1
andi.w #7,d1
bne.s +
subq.w #1,(TempArray_LayerDef).w
+
lea (CPZ_CameraSections+1).l,a0
move.w (Camera_BG_Y_pos).w,d0
move.w d0,d2
andi.w #$3F0,d0
lsr.w #4,d0
lea (a0,d0.w),a0
move.w d0,d4
lea (Horiz_Scroll_Buf).w,a1
move.w #$E,d1
move.w (Camera_X_pos).w,d0
neg.w d0
swap d0
andi.w #$F,d2
move.w (Camera_BG_X_pos).w,d0
cmpi.b #$12,d4
beq.s loc_D34A
blo.s +
move.w (Camera_BG2_X_pos).w,d0
+
neg.w d0
add.w d2,d2
jmp ++(pc,d2.w)
; ===========================================================================
- move.w (Camera_BG_X_pos).w,d0
cmpi.b #$12,d4
beq.s +++
blo.s +
move.w (Camera_BG2_X_pos).w,d0
+
neg.w d0
+ rept 16
move.l d0,(a1)+
endm
addq.b #1,d4
dbf d1,-
rts
; ===========================================================================
loc_D34A:
move.w #bytesToLcnt($40),d0
sub.w d2,d0
move.w d0,d2
bra.s ++
; ===========================================================================
+
move.w #$F,d2
+
move.w (Camera_BG_X_pos).w,d3
neg.w d3
move.w (TempArray_LayerDef).w,d0
andi.w #$1F,d0
lea_ SwScrl_RippleData,a2
lea (a2,d0.w),a2
- move.b (a2)+,d0
ext.w d0
add.w d3,d0
move.l d0,(a1)+
dbf d2,-
addq.b #1,d4
dbf d1,--
rts
; ===========================================================================
; loc_D382:
SwScrl_DEZ:
move.w (Camera_X_pos_diff).w,d4
ext.l d4
asl.l #8,d4
move.w (Camera_Y_pos_diff).w,d5
ext.l d5
asl.l #8,d5
bsr.w SetHorizVertiScrollFlagsBG
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
move.w (Camera_X_pos).w,d4
lea (TempArray_LayerDef).w,a2
move.w d4,(a2)+
addq.w #3,(a2)+ ; these random-seeming numbers control how fast each row of stars scrolls by
addq.w #2,(a2)+
addq.w #4,(a2)+
addq.w #1,(a2)+
addq.w #2,(a2)+
addq.w #4,(a2)+
addq.w #3,(a2)+
addq.w #4,(a2)+
addq.w #2,(a2)+
addq.w #6,(a2)+
addq.w #3,(a2)+
addq.w #4,(a2)+
addq.w #1,(a2)+
addq.w #2,(a2)+
addq.w #4,(a2)+
addq.w #3,(a2)+
addq.w #2,(a2)+
addq.w #3,(a2)+
addq.w #4,(a2)+
addq.w #1,(a2)+
addq.w #3,(a2)+
addq.w #4,(a2)+
addq.w #2,(a2)+
addq.w #1,(a2)
move.w (a2)+,d0 ; this is to make one row go at half speed (1 pixel every other frame)
moveq #0,d1
move.w d0,d1
lsr.w #1,d0
move.w d0,(a2)+
addq.w #3,(a2)+ ; more star speeds...
addq.w #2,(a2)+
addq.w #4,(a2)+
swap d1
move.l d1,d0
lsr.l #3,d1
sub.l d1,d0
swap d0
move.w d0,4(a2)
swap d0
sub.l d1,d0
swap d0
move.w d0,2(a2)
swap d0
sub.l d1,d0
swap d0
move.w d0,(a2)+
addq.w #4,a2
addq.w #1,(a2)+
move.w d4,(a2)+
move.w d4,(a2)+
move.w d4,(a2)+
lea (SwScrl_DEZ_RowHeights).l,a3
lea (TempArray_LayerDef).w,a2
lea (Horiz_Scroll_Buf).w,a1
move.w (Camera_BG_Y_pos).w,d1
moveq #0,d0
- move.b (a3)+,d0
addq.w #2,a2
sub.w d0,d1
bcc.s -
neg.w d1
subq.w #2,a2
move.w #bytesToLcnt($380),d2
move.w (Camera_X_pos).w,d0
neg.w d0
swap d0
move.w (a2)+,d0
neg.w d0
- move.l d0,(a1)+
subq.w #1,d1
bne.s +
move.b (a3)+,d1
move.w (a2)+,d0
neg.w d0
+ dbf d2,-
moveq #0,d2
tst.b (Screen_Shaking_Flag).w
beq.s ++ ; rts
subq.w #1,(DEZ_Shake_Timer).w
bpl.s +
clr.b (Screen_Shaking_Flag).w
+
move.w (Timer_frames).w,d0
andi.w #$3F,d0
lea_ SwScrl_RippleData,a1
lea (a1,d0.w),a1
moveq #0,d0
move.b (a1)+,d0
add.w d0,(Vscroll_Factor_FG).w
add.w d0,(Vscroll_Factor_BG).w
add.w d0,(Camera_Y_pos_copy).w
move.b (a1)+,d2
add.w d2,(Camera_X_pos_copy).w
+
rts
; ===========================================================================
; byte_D48A:
SwScrl_DEZ_RowHeights:
dc.b $80
dc.b 8 ; 1
dc.b 8 ; 2
dc.b 8 ; 3
dc.b 8 ; 4
dc.b 8 ; 5
dc.b 8 ; 6
dc.b 8 ; 7
dc.b 8 ; 8
dc.b 8 ; 9
dc.b 8 ; 10
dc.b 8 ; 11
dc.b 8 ; 12
dc.b 8 ; 13
dc.b 8 ; 14
dc.b 8 ; 15
dc.b 8 ; 16
dc.b 8 ; 17
dc.b 8 ; 18
dc.b 8 ; 19
dc.b 8 ; 20
dc.b 8 ; 21
dc.b 8 ; 22
dc.b 8 ; 23
dc.b 8 ; 24
dc.b 8 ; 25
dc.b 8 ; 26
dc.b 8 ; 27
dc.b 8 ; 28
dc.b 3 ; 29
dc.b 5 ; 30
dc.b 8 ; 31
dc.b $10 ; 32
dc.b $80 ; 33
dc.b $80 ; 34
dc.b $80 ; 35
even
; ===========================================================================
; loc_D4AE:
SwScrl_ARZ:
move.w (Camera_X_pos_diff).w,d4
ext.l d4
muls.w #$119,d4
moveq #2,d6
bsr.w SetHorizScrollFlagsBG_ARZ
move.w (Camera_Y_pos_diff).w,d5
ext.l d5
asl.l #7,d5
tst.b (Current_Act).w
bne.s +
asl.l #1,d5
+
moveq #6,d6
bsr.w SetVertiScrollFlagsBG
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
moveq #0,d2
tst.b (Screen_Shaking_Flag).w
beq.s .screenNotShaking
move.w (Timer_frames).w,d0
andi.w #$3F,d0
lea_ SwScrl_RippleData,a1
lea (a1,d0.w),a1
moveq #0,d0
; Shake camera Y-pos (note that BG scrolling is not affected by this, causing it to distort)
move.b (a1)+,d0
add.w d0,(Vscroll_Factor_FG).w
add.w d0,(Vscroll_Factor_BG).w
add.w d0,(Camera_Y_pos_copy).w
; Shake camera X-pos
move.b (a1)+,d2
add.w d2,(Camera_X_pos_copy).w
.screenNotShaking:
lea (TempArray_LayerDef).w,a2 ; Starts at BG scroll row 1
lea 6(a2),a3 ; Starts at BG scroll row 4
; Set up the speed of each row (there are 16 rows in total)
move.w (Camera_X_pos).w,d0
ext.l d0
asl.l #4,d0
divs.w #$A,d0
ext.l d0
asl.l #4,d0
asl.l #8,d0
move.l d0,d1
; Set row 4's speed
swap d1
move.w d1,(a3)+ ; Top row of background moves 10 ($A) times slower than foreground
swap d1
add.l d1,d1
add.l d0,d1
; Set rows 5-10's speed
rept 6
swap d1
move.w d1,(a3)+ ; Next row moves 3 times faster than top row, then next row is 4 times faster, then 5, etc.
swap d1
add.l d0,d1
endm
; Set row 11's speed
swap d1
move.w d1,(a3)+
; These instructions reveal that ARZ had slightly different scrolling,
; at one point:
; Above the background's mountains is a row of leaves, which is actually
; composed of three separately-scrolling rows. According to this code,
; the first and third rows were meant to scroll at a different speed to the
; second. Possibly due to how bad it looks, the speed values are overwritten
; a few instructions later, so all three move at the same speed.
; This code seems to pre-date the Simon Wai build, which uses the final's
; scrolling.
move.w d1,(a2) ; Set row 1's speed
move.w d1,4(a2) ; Set row 3's speed
move.w (Camera_BG_X_pos).w,d0
move.w d0,2(a2) ; Set row 2's speed
move.w d0,$16(a2) ; Set row 12's speed
_move.w d0,0(a2) ; Overwrite row 1's speed (now same as row 2's)
move.w d0,4(a2) ; Overwrite row 3's speed (now same as row 2's)
move.w d0,$18(a2) ; Set row 13's speed
move.w d0,$1A(a2) ; Set row 14's speed
move.w d0,$1C(a2) ; Set row 15's speed
move.w d0,$1E(a2) ; Set row 16's speed
lea (SwScrl_ARZ_RowHeights).l,a3
lea (TempArray_LayerDef).w,a2
lea (Horiz_Scroll_Buf).w,a1
move.w (Camera_BG_Y_pos).w,d1
moveq #0,d0
; Find which row of background is visible at the top of the screen
.findTopRowLoop:
move.b (a3)+,d0 ; Get row height
addq.w #2,a2 ; Next row speed (note: is off by 2. This is fixed below)
sub.w d0,d1
bcc.s .findTopRowLoop ; If current row is above the screen, loop and do next row
neg.w d1 ; d1 now contains how many pixels of the row is currently on-screen
subq.w #2,a2 ; Get correct row speed
move.w #bytesToLcnt($380),d2 ; Actual size of Horiz_Scroll_Buf
move.w (Camera_X_pos).w,d0
neg.w d0
swap d0 ; Store FG X-pos in upper 16-bits...
move.w (a2)+,d0 ; ...and BG X-pos in lower 16 bits, as Horiz_Scroll_Buf expects it
neg.w d0
- move.l d0,(a1)+ ; Write 1 FG Horizontal Scroll value, and 1 BG Horizontal Scroll value
subq.w #1,d1 ; Loop until row at top of screen is done
bne.s +
move.b (a3)+,d1 ; Once that row is done, go to next row...
move.w (a2)+,d0 ; ...and use next speed
neg.w d0
+ dbf d2,- ; Loop until Horiz_Scroll_Buf is full
rts
; ===========================================================================
; byte_D5CE:
SwScrl_ARZ_RowHeights:
dc.b $B0
dc.b $70 ; 1
dc.b $30 ; 2
dc.b $60 ; 3
dc.b $15 ; 4
dc.b $C ; 5
dc.b $E ; 6
dc.b 6 ; 7
dc.b $C ; 8
dc.b $1F ; 9
dc.b $30 ; 10
dc.b $C0 ; 11
dc.b $F0 ; 12
dc.b $F0 ; 13
dc.b $F0 ; 14
dc.b $F0 ; 15
even
; ===========================================================================
; loc_D5DE:
SwScrl_SCZ:
tst.w (Debug_placement_mode).w
bne.w SwScrl_Minimal
lea (Camera_X_pos).w,a1
lea (Scroll_flags).w,a3
lea (Camera_X_pos_diff).w,a4
move.w (Tornado_Velocity_X).w,d0
move.w (a1),d4
add.w (a1),d0
move.w d0,d1
sub.w (a1),d1
asl.w #8,d1
move.w d0,(a1)
move.w d1,(a4)
lea (Horiz_block_crossed_flag).w,a2
bsr.w SetHorizScrollFlags
lea (Camera_Y_pos).w,a1
lea (Camera_Y_pos_diff).w,a4
move.w (Tornado_Velocity_Y).w,d0
move.w (a1),d4
add.w (a1),d0
move.w d0,d1
sub.w (a1),d1
asl.w #8,d1
move.w d0,(a1)
move.w d1,(a4)
lea (Verti_block_crossed_flag).w,a2
bsr.w SetVertiScrollFlags
move.w (Camera_X_pos_diff).w,d4
beq.s +
move.w #$100,d4
+
ext.l d4
asl.l #7,d4
moveq #0,d5
bsr.w SetHorizVertiScrollFlagsBG
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
lea (Horiz_Scroll_Buf).w,a1
move.w #bytesToLcnt($380),d1
move.w (Camera_X_pos).w,d0
neg.w d0
swap d0
move.w (Camera_BG_X_pos).w,d0
neg.w d0
- move.l d0,(a1)+
dbf d1,-
rts
; ===========================================================================
; loc_D666:
SwScrl_Minimal:
move.w (Camera_X_pos_diff).w,d4
ext.l d4
asl.l #5,d4
move.w (Camera_Y_pos_diff).w,d5
ext.l d5
asl.l #6,d5
bsr.w SetHorizVertiScrollFlagsBG
move.w (Camera_BG_Y_pos).w,(Vscroll_Factor_BG).w
lea (Horiz_Scroll_Buf).w,a1
move.w #bytesToLcnt($380),d1
move.w (Camera_X_pos).w,d0
neg.w d0
swap d0
move.w (Camera_BG_X_pos).w,d0
neg.w d0
- move.l d0,(a1)+
dbf d1,-
rts
; ===========================================================================
; unused...
; loc_D69E:
SwScrl_HPZ_Continued:
lea (Horiz_Scroll_Buf).w,a1
move.w #$E,d1
move.w (Camera_X_pos).w,d0
neg.w d0
swap d0
andi.w #$F,d2
add.w d2,d2
move.w (a2)+,d0
jmp +(pc,d2.w)
; ===========================================================================
- move.w (a2)+,d0
+ rept 16
move.l d0,(a1)+
endm
dbf d1,-
rts
; ---------------------------------------------------------------------------
; Subroutine to set horizontal scroll flags
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_D6E2:
SetHorizScrollFlags:
move.w (a1),d0 ; get camera X pos
andi.w #$10,d0
move.b (a2),d1
eor.b d1,d0 ; has the camera crossed a 16-pixel boundary?
bne.s ++ ; if not, branch
eori.b #$10,(a2)
move.w (a1),d0 ; get camera X pos
sub.w d4,d0 ; subtract previous camera X pos
bpl.s + ; branch if the camera has moved forward
bset #2,(a3) ; set moving back in level bit
rts
; ===========================================================================
+
bset #3,(a3) ; set moving forward in level bit
+
rts
; End of function SetHorizScrollFlags
; ---------------------------------------------------------------------------
; Subroutine to scroll the camera horizontally
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_D704:
ScrollHoriz:
move.w (a1),d4 ; get camera X pos
tst.b (Teleport_flag).w
bne.s .return ; if a teleport is in progress, return
move.w (a5),d1 ; should scrolling be delayed?
beq.s .scrollNotDelayed ; if not, branch
subi.w #$100,d1 ; reduce delay value
move.w d1,(a5)
moveq #0,d1
move.b (a5),d1 ; get delay value
lsl.b #2,d1 ; multiply by 4, the size of a position buffer entry
addq.b #4,d1
move.w 2(a5),d0 ; get current position buffer index
sub.b d1,d0
move.w (a6,d0.w),d0 ; get Sonic's position a certain number of frames ago
andi.w #$3FFF,d0
bra.s .checkIfShouldScroll ; use that value for scrolling
; ===========================================================================
; loc_D72E:
.scrollNotDelayed:
move.w x_pos(a0),d0
; loc_D732:
.checkIfShouldScroll:
sub.w (a1),d0
subi.w #(320/2)-16,d0 ; is the player less than 144 pixels from the screen edge?
blt.s .scrollLeft ; if he is, scroll left
subi.w #16,d0 ; is the player more than 159 pixels from the screen edge?
bge.s .scrollRight ; if he is, scroll right
clr.w (a4) ; otherwise, don't scroll
; return_D742:
.return:
rts
; ===========================================================================
; loc_D744:
.scrollLeft:
cmpi.w #-16,d0
bgt.s .maxNotReached
move.w #-16,d0 ; limit scrolling to 16 pixels per frame
; loc_D74E:
.maxNotReached:
add.w (a1),d0 ; get new camera position
cmp.w (a2),d0 ; is it greater than the minimum position?
bgt.s .doScroll ; if it is, branch
move.w (a2),d0 ; prevent camera from going any further back
bra.s .doScroll
; ===========================================================================
; loc_D758:
.scrollRight:
cmpi.w #16,d0
blo.s .maxNotReached2
move.w #16,d0
; loc_D762:
.maxNotReached2:
add.w (a1),d0 ; get new camera position
cmp.w Camera_Max_X_pos-Camera_Min_X_pos(a2),d0 ; is it less than the max position?
blt.s .doScroll ; if it is, branch
move.w Camera_Max_X_pos-Camera_Min_X_pos(a2),d0 ; prevent camera from going any further forward
; loc_D76E:
.doScroll:
move.w d0,d1
sub.w (a1),d1 ; subtract old camera position
asl.w #8,d1 ; shift up by a byte
move.w d0,(a1) ; set new camera position
move.w d1,(a4) ; set difference between old and new positions
rts
; End of function ScrollHoriz
; ---------------------------------------------------------------------------
; Subroutine to scroll the camera vertically
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; The upper 16 bits of Camera_Y_pos is the actual Y-pos, the lower ones seem
; unused, yet this code goes to a strange extent to manage them.
;sub_D77A:
ScrollVerti:
moveq #0,d1
move.w y_pos(a0),d0
sub.w (a1),d0 ; subtract camera Y pos
cmpi.w #-$100,(Camera_Min_Y_pos).w ; does the level wrap vertically?
bne.s .noWrap ; if not, branch
andi.w #$7FF,d0
; loc_D78E:
.noWrap:
btst #2,status(a0) ; is the player rolling?
beq.s .notRolling ; if not, branch
subq.w #5,d0 ; subtract difference between standing and rolling heights
; loc_D798:
.notRolling:
btst #1,status(a0) ; is the player in the air?
beq.s .checkBoundaryCrossed_onGround ; if not, branch
;.checkBoundaryCrossed_inAir:
; If Sonic's in the air, he has $20 pixels above and below him to move without disturbing the camera.
; The camera movement is also only capped at $10 pixels.
addi.w #$20,d0
sub.w d3,d0
bcs.s .doScroll_fast ; If Sonic is above the boundary, scroll to catch up to him
subi.w #$40,d0
bcc.s .doScroll_fast ; If Sonic is below the boundary, scroll to catch up to him
tst.b (Camera_Max_Y_Pos_Changing).w ; is the max Y pos changing?
bne.s .scrollUpOrDown_maxYPosChanging ; if it is, branch
bra.s .doNotScroll
; ===========================================================================
; loc_D7B6:
.checkBoundaryCrossed_onGround:
; On the ground, the camera follows Sonic very strictly.
sub.w d3,d0 ; subtract camera bias
bne.s .decideScrollType ; If Sonic has moved, scroll to catch up to him
tst.b (Camera_Max_Y_Pos_Changing).w ; is the max Y pos changing?
bne.s .scrollUpOrDown_maxYPosChanging ; if it is, branch
; loc_D7C0:
.doNotScroll:
clr.w (a4) ; clear Y position difference (Camera_Y_pos_bias)
rts
; ===========================================================================
; loc_D7C4:
.decideScrollType:
cmpi.w #(224/2)-16,d3 ; is the camera bias normal?
bne.s .doScroll_slow ; if not, branch
mvabs.w inertia(a0),d1 ; get player ground velocity, force it to be positive
cmpi.w #$800,d1 ; is the player travelling very fast?
bhs.s .doScroll_fast ; if he is, branch
;.doScroll_medium:
move.w #6<<8,d1 ; If player is going too fast, cap camera movement to 6 pixels per frame
cmpi.w #6,d0 ; is player going down too fast?
bgt.s .scrollDown_max ; if so, move camera at capped speed
cmpi.w #-6,d0 ; is player going up too fast?
blt.s .scrollUp_max ; if so, move camera at capped speed
bra.s .scrollUpOrDown ; otherwise, move camera at player's speed
; ===========================================================================
; loc_D7EA:
.doScroll_slow:
move.w #2<<8,d1 ; If player is going too fast, cap camera movement to 2 pixels per frame
cmpi.w #2,d0 ; is player going down too fast?
bgt.s .scrollDown_max ; if so, move camera at capped speed
cmpi.w #-2,d0 ; is player going up too fast?
blt.s .scrollUp_max ; if so, move camera at capped speed
bra.s .scrollUpOrDown ; otherwise, move camera at player's speed
; ===========================================================================
; loc_D7FC:
.doScroll_fast:
; related code appears in ScrollBG
; S3K uses 24 instead of 16
move.w #16<<8,d1 ; If player is going too fast, cap camera movement to $10 pixels per frame
cmpi.w #16,d0 ; is player going down too fast?
bgt.s .scrollDown_max ; if so, move camera at capped speed
cmpi.w #-16,d0 ; is player going up too fast?
blt.s .scrollUp_max ; if so, move camera at capped speed
bra.s .scrollUpOrDown ; otherwise, move camera at player's speed
; ===========================================================================
; loc_D80E:
.scrollUpOrDown_maxYPosChanging:
moveq #0,d0 ; Distance for camera to move = 0
move.b d0,(Camera_Max_Y_Pos_Changing).w ; clear camera max Y pos changing flag
; loc_D814:
.scrollUpOrDown:
moveq #0,d1
move.w d0,d1 ; get position difference
add.w (a1),d1 ; add old camera Y position
tst.w d0 ; is the camera to scroll down?
bpl.w .scrollDown ; if it is, branch
bra.w .scrollUp
; ===========================================================================
; loc_D824:
.scrollUp_max:
neg.w d1 ; make the value negative (since we're going backwards)
ext.l d1
asl.l #8,d1 ; move this into the upper word, so it lines up with the actual y_pos value in Camera_Y_pos
add.l (a1),d1 ; add the two, getting the new Camera_Y_pos value
swap d1 ; actual Y-coordinate is now the low word
; loc_D82E:
.scrollUp:
cmp.w Camera_Min_Y_pos-Camera_Min_X_pos(a2),d1 ; is the new position less than the minimum Y pos?
bgt.s .doScroll ; if not, branch
cmpi.w #-$100,d1
bgt.s .minYPosReached
andi.w #$7FF,d1
andi.w #$7FF,(a1)
bra.s .doScroll
; ===========================================================================
; loc_D844:
.minYPosReached:
move.w Camera_Min_Y_pos-Camera_Min_X_pos(a2),d1 ; prevent camera from going any further up
bra.s .doScroll
; ===========================================================================
; loc_D84A:
.scrollDown_max:
ext.l d1
asl.l #8,d1 ; move this into the upper word, so it lines up with the actual y_pos value in Camera_Y_pos
add.l (a1),d1 ; add the two, getting the new Camera_Y_pos value
swap d1 ; actual Y-coordinate is now the low word
; loc_D852:
.scrollDown:
cmp.w Camera_Max_Y_pos_now-Camera_Min_X_pos(a2),d1 ; is the new position greater than the maximum Y pos?
blt.s .doScroll ; if not, branch
subi.w #$800,d1
bcs.s .maxYPosReached
subi.w #$800,(a1)
bra.s .doScroll
; ===========================================================================
; loc_D864:
.maxYPosReached:
move.w Camera_Max_Y_pos_now-Camera_Min_X_pos(a2),d1 ; prevent camera from going any further down
; loc_D868:
.doScroll:
move.w (a1),d4 ; get old pos (used by SetVertiScrollFlags)
swap d1 ; actual Y-coordinate is now the high word, as Camera_Y_pos expects it
move.l d1,d3
sub.l (a1),d3
ror.l #8,d3
move.w d3,(a4) ; set difference between old and new positions
move.l d1,(a1) ; set new camera Y pos
rts
; End of function ScrollVerti
; ---------------------------------------------------------------------------
; Subroutine to set vertical scroll flags
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
SetVertiScrollFlags:
move.w (a1),d0 ; get camera Y pos
andi.w #$10,d0
move.b (a2),d1
eor.b d1,d0 ; has the camera crossed a 16-pixel boundary?
bne.s ++ ; if not, branch
eori.b #$10,(a2)
move.w (a1),d0 ; get camera Y pos
sub.w d4,d0 ; subtract old camera Y pos
bpl.s + ; branch if the camera has scrolled down
bset #0,(a3) ; set moving up in level bit
rts
; ===========================================================================
+
bset #1,(a3) ; set moving down in level bit
+
rts
; End of function SetVertiScrollFlags
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; d4 is horizontal, d5 vertical, derived from $FFFFEEB0 & $FFFFEEB2 respectively
;sub_D89A: ;Hztl_Vrtc_Bg_Deformation:
SetHorizVertiScrollFlagsBG: ; used by lev2, MTZ, HTZ, CPZ, DEZ, SCZ, Minimal
move.l (Camera_BG_X_pos).w,d2
move.l d2,d0
add.l d4,d0 ; add x-shift for this frame
move.l d0,(Camera_BG_X_pos).w
move.l d0,d1
swap d1
andi.w #$10,d1
move.b (Horiz_block_crossed_flag_BG).w,d3
eor.b d3,d1
bne.s ++
eori.b #$10,(Horiz_block_crossed_flag_BG).w
sub.l d2,d0
bpl.s +
bset #2,(Scroll_flags_BG).w
bra.s ++
; ===========================================================================
+
bset #3,(Scroll_flags_BG).w
+
move.l (Camera_BG_Y_pos).w,d3
move.l d3,d0
add.l d5,d0 ; add y-shift for this frame
move.l d0,(Camera_BG_Y_pos).w
move.l d0,d1
swap d1
andi.w #$10,d1
move.b (Verti_block_crossed_flag_BG).w,d2
eor.b d2,d1
bne.s ++ ; rts
eori.b #$10,(Verti_block_crossed_flag_BG).w
sub.l d3,d0
bpl.s +
bset #0,(Scroll_flags_BG).w
rts
; ===========================================================================
+
bset #1,(Scroll_flags_BG).w
+
rts
; End of function SetHorizVertiScrollFlagsBG
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_D904: ;Horizontal_Bg_Deformation:
SetHorizScrollFlagsBG: ; used by WFZ, HTZ, HPZ
move.l (Camera_BG_X_pos).w,d2
move.l d2,d0
add.l d4,d0 ; add x-shift for this frame
move.l d0,(Camera_BG_X_pos).w
move.l d0,d1
swap d1
andi.w #$10,d1
move.b (Horiz_block_crossed_flag_BG).w,d3
eor.b d3,d1
bne.s ++ ; rts
eori.b #$10,(Horiz_block_crossed_flag_BG).w
sub.l d2,d0
bpl.s +
bset d6,(Scroll_flags_BG).w
bra.s ++ ; rts
; ===========================================================================
+
addq.b #1,d6
bset d6,(Scroll_flags_BG).w
+
rts
; End of function SetHorizScrollFlagsBG
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_D938: ;Vertical_Bg_Deformation1:
SetVertiScrollFlagsBG: ; used by WFZ, HTZ, HPZ, ARZ
move.l (Camera_BG_Y_pos).w,d3
move.l d3,d0
add.l d5,d0 ; add y-shift for this frame
;loc_D940: ;Vertical_Bg_Deformation2:
SetVertiScrollFlagsBG2:
move.l d0,(Camera_BG_Y_pos).w
move.l d0,d1
swap d1
andi.w #$10,d1
move.b (Verti_block_crossed_flag_BG).w,d2
eor.b d2,d1
bne.s ++ ; rts
eori.b #$10,(Verti_block_crossed_flag_BG).w
sub.l d3,d0
bpl.s +
bset d6,(Scroll_flags_BG).w ; everytime Verti_block_crossed_flag_BG changes from $10 to $00
rts
; ===========================================================================
+
addq.b #1,d6
bset d6,(Scroll_flags_BG).w ; everytime Verti_block_crossed_flag_BG changes from $00 to $10
+
rts
; End of function SetVertiScrollFlagsBG
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_D96C: ;ARZ_Bg_Deformation:
SetHorizScrollFlagsBG_ARZ: ; only used by ARZ
move.l (Camera_ARZ_BG_X_pos).w,d0
add.l d4,d0
move.l d0,(Camera_ARZ_BG_X_pos).w
lea (Camera_BG_X_pos).w,a1
move.w (a1),d2
move.w (Camera_ARZ_BG_X_pos).w,d0
sub.w d2,d0
bcs.s +
bhi.s ++
rts
; ===========================================================================
+
cmpi.w #-$10,d0
bgt.s ++
move.w #-$10,d0
bra.s ++
; ===========================================================================
+
cmpi.w #$10,d0
blo.s +
move.w #$10,d0
+
add.w (a1),d0
move.w d0,(a1)
move.w d0,d1
andi.w #$10,d1
move.b (Horiz_block_crossed_flag_BG).w,d3
eor.b d3,d1
bne.s ++ ; rts
eori.b #$10,(Horiz_block_crossed_flag_BG).w
sub.w d2,d0
bpl.s +
bset d6,(Scroll_flags_BG).w
bra.s ++ ; rts
; ===========================================================================
+
addq.b #1,d6
bset d6,(Scroll_flags_BG).w
+
rts
; End of function SetHorizScrollFlagsBG_ARZ
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_D9C8: ;CPZ_Bg_Deformation:
SetHorizScrollFlagsBG2: ; only used by CPZ
move.l (Camera_BG2_X_pos).w,d2
move.l d2,d0
add.l d4,d0
move.l d0,(Camera_BG2_X_pos).w
move.l d0,d1
swap d1
andi.w #$10,d1
move.b (Horiz_block_crossed_flag_BG2).w,d3
eor.b d3,d1
bne.s ++ ; rts
eori.b #$10,(Horiz_block_crossed_flag_BG2).w
sub.l d2,d0
bpl.s +
bset d6,(Scroll_flags_BG2).w
bra.s ++ ; rts
; ===========================================================================
+
addq.b #1,d6
bset d6,(Scroll_flags_BG2).w
+
rts
; End of function SetHorizScrollFlagsBG2
; ===========================================================================
; some apparently unused code
;SetHorizScrollFlagsBG3:
move.l (Camera_BG3_X_pos).w,d2
move.l d2,d0
add.l d4,d0
move.l d0,(Camera_BG3_X_pos).w
move.l d0,d1
swap d1
andi.w #$10,d1
move.b (Horiz_block_crossed_flag_BG3).w,d3
eor.b d3,d1
bne.s ++ ; rts
eori.b #$10,(Horiz_block_crossed_flag_BG3).w
sub.l d2,d0
bpl.s +
bset d6,(Scroll_flags_BG3).w
bra.s ++ ; rts
; ===========================================================================
+
addq.b #1,d6
bset d6,(Scroll_flags_BG3).w
+
rts
; ===========================================================================
; Unused - dead code leftover from S1:
lea (VDP_control_port).l,a5
lea (VDP_data_port).l,a6
lea (Scroll_flags_BG).w,a2
lea (Camera_BG_X_pos).w,a3
lea (Level_Layout+$80).w,a4
move.w #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE)>>16,d2
bsr.w Draw_BG1
lea (Scroll_flags_BG2).w,a2
lea (Camera_BG2_X_pos).w,a3
bra.w Draw_BG2
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to display correct tiles as you move
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_DA5C:
LoadTilesAsYouMove:
lea (VDP_control_port).l,a5
lea (VDP_data_port).l,a6
lea (Scroll_flags_BG_copy).w,a2
lea (Camera_BG_copy).w,a3
lea (Level_Layout+$80).w,a4 ; first background line
move.w #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE)>>16,d2
bsr.w Draw_BG1
lea (Scroll_flags_BG2_copy).w,a2 ; referred to in CPZ deformation routine, but cleared right after
lea (Camera_BG2_copy).w,a3
bsr.w Draw_BG2 ; Essentially unused, though
lea (Scroll_flags_BG3_copy).w,a2
lea (Camera_BG3_copy).w,a3
bsr.w Draw_BG3 ; used in CPZ deformation routine
tst.w (Two_player_mode).w
beq.s +
lea (Scroll_flags_copy_P2).w,a2
lea (Camera_P2_copy).w,a3 ; second player camera
lea (Level_Layout).w,a4
move.w #vdpComm(VRAM_Plane_A_Name_Table_2P,VRAM,WRITE)>>16,d2
bsr.w Draw_FG_P2
+
lea (Scroll_flags_copy).w,a2
lea (Camera_RAM_copy).w,a3
lea (Level_Layout).w,a4
move.w #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE)>>16,d2
tst.b (Screen_redraw_flag).w
; comment out this line to disable blast processing
beq.s Draw_FG
move.b #0,(Screen_redraw_flag).w
moveq #-$10,d4
moveq #$F,d6
; loc_DACE:
Draw_All:
movem.l d4-d6,-(sp) ; This whole routine basically redraws the whole
moveq #-$10,d5 ; area instead of merely a line of tiles
move.w d4,d1
bsr.w CalcBlockVRAMPos
move.w d1,d4
moveq #-$10,d5
bsr.w DrawBlockRow1 ; draw the current row
movem.l (sp)+,d4-d6
addi.w #$10,d4 ; move onto the next row
dbf d6,Draw_All ; repeat for all rows
move.b #0,(Scroll_flags_copy).w
rts
; ===========================================================================
; loc_DAF6:
Draw_FG:
tst.b (a2) ; is any scroll flag set?
beq.s return_DB5A ; if not, branch
bclr #0,(a2) ; has the level scrolled up?
beq.s + ; if not, branch
moveq #-$10,d4
moveq #-$10,d5
bsr.w CalcBlockVRAMPos
moveq #-$10,d4
moveq #-$10,d5
bsr.w DrawBlockRow1 ; redraw upper row
+
bclr #1,(a2) ; has the level scrolled down?
beq.s + ; if not, branch
move.w #224,d4
moveq #-$10,d5
bsr.w CalcBlockVRAMPos
move.w #224,d4
moveq #-$10,d5
bsr.w DrawBlockRow1 ; redraw bottom row
+
bclr #2,(a2) ; has the level scrolled to the left?
beq.s + ; if not, branch
moveq #-$10,d4
moveq #-$10,d5
bsr.w CalcBlockVRAMPos
moveq #-$10,d4
moveq #-$10,d5
bsr.w DrawBlockCol1 ; redraw left-most column
+
bclr #3,(a2) ; has the level scrolled to the right?
beq.s return_DB5A ; if not, return
moveq #-$10,d4
move.w #320,d5
bsr.w CalcBlockVRAMPos
moveq #-$10,d4
move.w #320,d5
bsr.w DrawBlockCol1 ; redraw right-most column
return_DB5A:
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_DB5C:
Draw_FG_P2:
tst.b (a2)
beq.s return_DBC0
bclr #0,(a2)
beq.s +
moveq #-$10,d4
moveq #-$10,d5
bsr.w CalcBlockVRAMPosB
moveq #-$10,d4
moveq #-$10,d5
bsr.w DrawBlockRow1
+
bclr #1,(a2)
beq.s +
move.w #$E0,d4
moveq #-$10,d5
bsr.w CalcBlockVRAMPosB
move.w #$E0,d4
moveq #-$10,d5
bsr.w DrawBlockRow1
+
bclr #2,(a2)
beq.s +
moveq #-$10,d4
moveq #-$10,d5
bsr.w CalcBlockVRAMPosB
moveq #-$10,d4
moveq #-$10,d5
bsr.w DrawBlockCol1
+
bclr #3,(a2)
beq.s return_DBC0
moveq #-$10,d4
move.w #320,d5
bsr.w CalcBlockVRAMPosB
moveq #-$10,d4
move.w #320,d5
bsr.w DrawBlockCol1
return_DBC0:
rts
; End of function Draw_FG_P2
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_DBC2:
Draw_BG1:
tst.b (a2)
beq.w return_DC90
bclr #0,(a2)
beq.s +
moveq #-$10,d4
moveq #-$10,d5
bsr.w CalcBlockVRAMPos
moveq #-$10,d4
moveq #-$10,d5
bsr.w DrawBlockRow1
+
bclr #1,(a2)
beq.s +
move.w #$E0,d4
moveq #-$10,d5
bsr.w CalcBlockVRAMPos
move.w #$E0,d4
moveq #-$10,d5
bsr.w DrawBlockRow1
+
bclr #2,(a2)
beq.s +
moveq #-$10,d4
moveq #-$10,d5
bsr.w CalcBlockVRAMPos
moveq #-$10,d4
moveq #-$10,d5
bsr.w DrawBlockCol1
+
bclr #3,(a2)
beq.s +
moveq #-$10,d4
move.w #320,d5
bsr.w CalcBlockVRAMPos
moveq #-$10,d4
move.w #320,d5
bsr.w DrawBlockCol1
+
bclr #4,(a2)
beq.s +
moveq #-$10,d4
moveq #0,d5
bsr.w CalcBlockVRAMPos2
moveq #-$10,d4
moveq #0,d5
moveq #$1F,d6
bsr.w DrawBlockRow2
+
bclr #5,(a2)
beq.s +
move.w #$E0,d4
moveq #0,d5
bsr.w CalcBlockVRAMPos2
move.w #$E0,d4
moveq #0,d5
moveq #$1F,d6
bsr.w DrawBlockRow2
+
bclr #6,(a2)
beq.s +
moveq #-$10,d4
moveq #-$10,d5
bsr.w CalcBlockVRAMPos
moveq #-$10,d4
moveq #-$10,d5
moveq #$1F,d6
bsr.w DrawBlockRow
+
bclr #7,(a2)
beq.s return_DC90
move.w #$E0,d4
moveq #-$10,d5
bsr.w CalcBlockVRAMPos
move.w #$E0,d4
moveq #-$10,d5
moveq #$1F,d6
bsr.w DrawBlockRow
return_DC90:
rts
; End of function Draw_BG1
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_DC92:
Draw_BG2:
tst.b (a2)
beq.w ++ ; rts
bclr #0,(a2)
beq.s +
move.w #$70,d4
moveq #-$10,d5
bsr.w CalcBlockVRAMPos
move.w #$70,d4
moveq #-$10,d5
moveq #2,d6
bsr.w DrawBlockCol2
+
bclr #1,(a2)
beq.s + ; rts
move.w #$70,d4
move.w #320,d5
bsr.w CalcBlockVRAMPos
move.w #$70,d4
move.w #320,d5
moveq #2,d6
bsr.w DrawBlockCol2
+
rts
; End of function Draw_BG2
; ===========================================================================
; Scrap Brain Zone 1 block positioning array -- S1 left-over
; Each entry is an index into BGCameraLookup; used to decide the camera to use
; for given block for reloading BG. A entry of 0 means assume X = 0 for section,
; but otherwise loads camera Y for selected camera.
;byte_DCD6
SBZ_CameraSections:
dc.b 0
dc.b 0 ; 1
dc.b 0 ; 2
dc.b 0 ; 3
dc.b 0 ; 4
dc.b 6 ; 5
dc.b 6 ; 6
dc.b 6 ; 7
dc.b 6 ; 8
dc.b 6 ; 9
dc.b 6 ; 10
dc.b 6 ; 11
dc.b 6 ; 12
dc.b 6 ; 13
dc.b 6 ; 14
dc.b 4 ; 15
dc.b 4 ; 16
dc.b 4 ; 17
dc.b 4 ; 18
dc.b 4 ; 19
dc.b 4 ; 20
dc.b 4 ; 21
dc.b 2 ; 22
dc.b 2 ; 23
dc.b 2 ; 24
dc.b 2 ; 25
dc.b 2 ; 26
dc.b 2 ; 27
dc.b 2 ; 28
dc.b 2 ; 29
dc.b 2 ; 30
dc.b 2 ; 31
dc.b 2 ; 32
even
; ===========================================================================
; Scrap Brain Zone 1 drawing code -- S1 left-over
; Compare with CPZ drawing code
; begin unused routine
moveq #-$10,d4
bclr #0,(a2)
bne.s +
bclr #1,(a2)
beq.s +++
move.w #$E0,d4
+
lea_ SBZ_CameraSections+1,a0
move.w (Camera_BG_Y_pos).w,d0
add.w d4,d0
andi.w #$1F0,d0
lsr.w #4,d0
move.b (a0,d0.w),d0
lea (BGCameraLookup).l,a3
movea.w (a3,d0.w),a3 ; Camera, either BG, BG2 or BG3 depending on Y
beq.s +
moveq #-$10,d5
movem.l d4-d5,-(sp)
bsr.w CalcBlockVRAMPos
movem.l (sp)+,d4-d5
bsr.w DrawBlockRow1
bra.s ++
; ===========================================================================
+
moveq #0,d5
movem.l d4-d5,-(sp)
bsr.w CalcBlockVRAMPos2
movem.l (sp)+,d4-d5
moveq #$1F,d6
bsr.w DrawBlockRow2
+
tst.b (a2)
bne.s +
rts
; ===========================================================================
+
moveq #-$10,d4
moveq #-$10,d5
move.b (a2),d0
andi.b #-$58,d0
beq.s +
lsr.b #1,d0
move.b d0,(a2)
move.w #320,d5
+
lea_ SBZ_CameraSections,a0
move.w (Camera_BG_Y_pos).w,d0
andi.w #$1F0,d0
lsr.w #4,d0
lea (a0,d0.w),a0
bra.w loc_DE86
; end unused routine
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_DD82:
Draw_BG3:
tst.b (a2)
beq.w ++ ; rts
cmpi.b #chemical_plant_zone,(Current_Zone).w
beq.w Draw_BG3_CPZ
; S1 left-over: GHZ used this
bclr #0,(a2)
beq.s +
move.w #$40,d4
moveq #-$10,d5
bsr.w CalcBlockVRAMPos
move.w #$40,d4
moveq #-$10,d5
moveq #2,d6
bsr.w DrawBlockCol2
+
bclr #1,(a2)
beq.s + ; rts
move.w #$40,d4
move.w #320,d5
bsr.w CalcBlockVRAMPos
move.w #$40,d4
move.w #320,d5
moveq #2,d6
bsr.w DrawBlockCol2
+
rts
; ===========================================================================
; Chemical Plant Zone 1 block positioning array
; Each entry is an index into BGCameraLookup; used to decide the camera to use
; for given block for reloading BG. A entry of 0 means assume X = 0 for section,
; but otherwise loads camera Y for selected camera.
;byte_DDD0
CPZ_CameraSections:
dc.b 2
dc.b 2 ; 1
dc.b 2 ; 2
dc.b 2 ; 3
dc.b 2 ; 4
dc.b 2 ; 5
dc.b 2 ; 6
dc.b 2 ; 7
dc.b 2 ; 8
dc.b 2 ; 9
dc.b 2 ; 10
dc.b 2 ; 11
dc.b 2 ; 12
dc.b 2 ; 13
dc.b 2 ; 14
dc.b 2 ; 15
dc.b 2 ; 16
dc.b 2 ; 17
dc.b 2 ; 18
dc.b 2 ; 19
dc.b 4 ; 20
dc.b 4 ; 21
dc.b 4 ; 22
dc.b 4 ; 23
dc.b 4 ; 24
dc.b 4 ; 25
dc.b 4 ; 26
dc.b 4 ; 27
dc.b 4 ; 28
dc.b 4 ; 29
dc.b 4 ; 30
dc.b 4 ; 31
dc.b 4 ; 32
dc.b 4 ; 33
dc.b 4 ; 34
dc.b 4 ; 35
dc.b 4 ; 36
dc.b 4 ; 37
dc.b 4 ; 38
dc.b 4 ; 39
dc.b 4 ; 40
dc.b 4 ; 41
dc.b 4 ; 42
dc.b 4 ; 43
dc.b 4 ; 44
dc.b 4 ; 45
dc.b 4 ; 46
dc.b 4 ; 47
dc.b 4 ; 48
dc.b 4 ; 49
dc.b 4 ; 50
dc.b 4 ; 51
dc.b 4 ; 52
dc.b 4 ; 53
dc.b 4 ; 54
dc.b 4 ; 55
dc.b 4 ; 56
dc.b 4 ; 57
dc.b 4 ; 58
dc.b 4 ; 59
dc.b 4 ; 60
dc.b 4 ; 61
dc.b 4 ; 62
dc.b 4 ; 63
dc.b 4 ; 64
even
; ===========================================================================
; loc_DE12:
Draw_BG3_CPZ:
moveq #-$10,d4 ; bit0 = top row
bclr #0,(a2)
bne.s +
bclr #1,(a2)
beq.s ++
move.w #$E0,d4 ; bit1 = bottom row
+
lea_ CPZ_CameraSections+1,a0
move.w (Camera_BG_Y_pos).w,d0
add.w d4,d0
andi.w #$3F0,d0
lsr.w #4,d0
move.b (a0,d0.w),d0
movea.w BGCameraLookup(pc,d0.w),a3 ; Camera, either BG, BG2 or BG3 depending on Y
moveq #-$10,d5
movem.l d4-d5,-(sp)
bsr.w CalcBlockVRAMPos
movem.l (sp)+,d4-d5
bsr.w DrawBlockRow1
+
tst.b (a2)
bne.s +
rts
; ===========================================================================
+
moveq #-$10,d4
moveq #-$10,d5
move.b (a2),d0
andi.b #-$58,d0
beq.s +
lsr.b #1,d0
move.b d0,(a2)
move.w #320,d5
+
lea_ CPZ_CameraSections,a0
move.w (Camera_BG_Y_pos).w,d0
andi.w #$7F0,d0
lsr.w #4,d0
lea (a0,d0.w),a0
bra.w loc_DE86
; ===========================================================================
;word_DE7E
BGCameraLookup:
dc.w Camera_BG_copy ; BG Camera
dc.w Camera_BG_copy ; BG Camera
dc.w Camera_BG2_copy ; BG2 Camera
dc.w Camera_BG3_copy ; BG3 Camera
; ===========================================================================
loc_DE86:
tst.w (Two_player_mode).w
bne.s ++
moveq #$F,d6
move.l #vdpCommDelta($0080),d7
- moveq #0,d0
move.b (a0)+,d0
btst d0,(a2)
beq.s +
movea.w BGCameraLookup(pc,d0.w),a3 ; Camera, either BG, BG2 or BG3 depending on Y
movem.l d4-d5/a0,-(sp)
movem.l d4-d5,-(sp)
bsr.w GetBlockPtr
movem.l (sp)+,d4-d5
bsr.w CalcBlockVRAMPos
bsr.w ProcessAndWriteBlock2
movem.l (sp)+,d4-d5/a0
+
addi.w #$10,d4
dbf d6,-
clr.b (a2)
rts
; ===========================================================================
+
moveq #$F,d6
move.l #vdpCommDelta($0080),d7
- moveq #0,d0
move.b (a0)+,d0
btst d0,(a2)
beq.s +
movea.w BGCameraLookup(pc,d0.w),a3 ; Camera, either BG, BG2 or BG3 depending on Y
movem.l d4-d5/a0,-(sp)
movem.l d4-d5,-(sp)
bsr.w GetBlockPtr
movem.l (sp)+,d4-d5
bsr.w CalcBlockVRAMPos
bsr.w ProcessAndWriteBlock2_2P
movem.l (sp)+,d4-d5/a0
+
addi.w #$10,d4
dbf d6,-
clr.b (a2)
rts
; End of function Draw_BG3
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_DF04:
DrawBlockCol1:
moveq #$F,d6
DrawBlockCol2:
add.w (a3),d5 ; add camera X pos
add.w 4(a3),d4 ; add camera Y pos
move.l #vdpCommDelta($0080),d7 ; store VDP command for line increment
move.l d0,d1 ; copy byte-swapped VDP command for later access
bsr.w GetBlockAddr
tst.w (Two_player_mode).w
bne.s ++
- move.w (a0),d3 ; get ID of the 16x16 block
andi.w #$3FF,d3
lsl.w #3,d3 ; multiply by 8, the size in bytes of a 16x16
lea (Block_Table).w,a1
adda.w d3,a1 ; a1 = address of the current 16x16 in the block table
move.l d1,d0
bsr.w ProcessAndWriteBlock2
adda.w #$10,a0 ; move onto the 16x16 vertically below this one
addi.w #$100,d1 ; draw on alternate 8x8 lines
andi.w #$FFF,d1
addi.w #$10,d4 ; add 16 to Y offset
move.w d4,d0
andi.w #$70,d0 ; have we reached a new 128x128?
bne.s + ; if not, branch
bsr.w GetBlockAddr ; otherwise, renew the block address
+ dbf d6,- ; repeat 16 times
rts
; ===========================================================================
/ move.w (a0),d3
andi.w #$3FF,d3
lsl.w #3,d3
lea (Block_Table).w,a1
adda.w d3,a1
move.l d1,d0
bsr.w ProcessAndWriteBlock2_2P
adda.w #$10,a0
addi.w #$80,d1
andi.w #$FFF,d1
addi.w #$10,d4
move.w d4,d0
andi.w #$70,d0
bne.s +
bsr.w GetBlockAddr
+ dbf d6,-
rts
; End of function DrawBlockCol1
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_DF8A: DrawTiles_Vertical:
DrawBlockRow:
add.w (a3),d5
add.w 4(a3),d4
bra.s DrawBlockRow3
; End of function DrawBlockRow
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_DF92: DrawTiles_Vertical1:
DrawBlockRow1:
moveq #$15,d6
add.w (a3),d5 ; add X pos
; loc_DF96: DrawTiles_Vertical2:
DrawBlockRow2:
add.w 4(a3),d4 ; add Y pos
; loc_DF9A: DrawTiles_Vertical3:
DrawBlockRow3:
tst.w (Two_player_mode).w
bne.s DrawBlockRow_2P
move.l a2,-(sp)
move.w d6,-(sp)
lea (Block_cache).w,a2
move.l d0,d1
or.w d2,d1
swap d1 ; make VRAM write command
move.l d1,-(sp)
move.l d1,(a5) ; set up a VRAM write at that address
swap d1
bsr.w GetBlockAddr
- move.w (a0),d3 ; get ID of the 16x16 block
andi.w #$3FF,d3
lsl.w #3,d3 ; multiply by 8, the size in bytes of a 16x16
lea (Block_Table).w,a1
adda.w d3,a1 ; a1 = address of current 16x16 in the block table
bsr.w ProcessAndWriteBlock
addq.w #2,a0 ; move onto next 16x16
addq.b #4,d1 ; increment VRAM write address
bpl.s +
andi.b #$7F,d1 ; restrict to a single 8x8 line
swap d1
move.l d1,(a5) ; set up a VRAM write at a new address
swap d1
+
addi.w #$10,d5 ; add 16 to X offset
move.w d5,d0
andi.w #$70,d0 ; have we reached a new 128x128?
bne.s + ; if not, branch
bsr.w GetBlockAddr ; otherwise, renew the block address
+
dbf d6,- ; repeat 22 times
move.l (sp)+,d1
addi.l #vdpCommDelta($0080),d1 ; move onto next line
lea (Block_cache).w,a2
move.l d1,(a5) ; write to this VRAM address
swap d1
move.w (sp)+,d6
- move.l (a2)+,(a6) ; write stored 8x8s
addq.b #4,d1 ; increment VRAM write address
bmi.s +
ori.b #$80,d1 ; force to bottom 8x8 line
swap d1
move.l d1,(a5) ; set up a VRAM write at a new address
swap d1
+
dbf d6,- ; repeat 22 times
movea.l (sp)+,a2
rts
; ===========================================================================
; loc_E018:
DrawBlockRow_2P:
move.l d0,d1
or.w d2,d1
swap d1
move.l d1,(a5)
swap d1
tst.b d1
bmi.s +++
bsr.w GetBlockAddr
- move.w (a0),d3
andi.w #$3FF,d3
lsl.w #3,d3
lea (Block_Table).w,a1
adda.w d3,a1
bsr.w ProcessAndWriteBlock_2P
addq.w #2,a0
addq.b #4,d1
bpl.s +
andi.b #$7F,d1
swap d1
move.l d1,(a5)
swap d1
+
addi.w #$10,d5
move.w d5,d0
andi.w #$70,d0
bne.s +
bsr.w GetBlockAddr
+ dbf d6,-
rts
; ===========================================================================
+
bsr.w GetBlockAddr
- move.w (a0),d3
andi.w #$3FF,d3
lsl.w #3,d3
lea (Block_Table).w,a1
adda.w d3,a1
bsr.w ProcessAndWriteBlock_2P
addq.w #2,a0
addq.b #4,d1
bmi.s +
ori.b #$80,d1
swap d1
move.l d1,(a5)
swap d1
+
addi.w #$10,d5
move.w d5,d0
andi.w #$70,d0
bne.s +
bsr.w GetBlockAddr
+ dbf d6,-
rts
; End of function DrawBlockRow1
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_E09E:
GetBlockAddr:
movem.l d4-d5,-(sp)
move.w d4,d3 ; d3 = camera Y pos + offset
add.w d3,d3
andi.w #$F00,d3 ; limit to units of $100 ($100 = $80 * 2, $80 = height of a 128x128)
lsr.w #3,d5 ; divide by 8
move.w d5,d0
lsr.w #4,d0 ; divide by 16 (overall division of 128)
andi.w #$7F,d0
add.w d3,d0 ; get offset of current 128x128 in the level layout table
moveq #-1,d3
clr.w d3 ; d3 = $FFFF0000
move.b (a4,d0.w),d3 ; get tile ID of the current 128x128 tile
lsl.w #7,d3 ; multiply by 128, the size in bytes of a 128x128 in RAM
andi.w #$70,d4 ; round down to nearest 16-pixel boundary
andi.w #$E,d5 ; force this to be a multiple of 16
add.w d4,d3 ; add vertical offset of current 16x16
add.w d5,d3 ; add horizontal offset of current 16x16
movea.l d3,a0 ; store address, in the metablock table, of the current 16x16
movem.l (sp)+,d4-d5
rts
; End of function GetBlockAddr
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_E0D4:
ProcessAndWriteBlock:
btst #3,(a0) ; is this 16x16 to be Y-flipped?
bne.s ProcessAndWriteBlock_FlipY ; if it is, branch
btst #2,(a0) ; is this 16x16 to be X-flipped?
bne.s ProcessAndWriteBlock_FlipX ; if it is, branch
move.l (a1)+,(a6) ; write top two 8x8s to VRAM
move.l (a1)+,(a2)+ ; store bottom two 8x8s for later writing
rts
; ===========================================================================
ProcessAndWriteBlock_FlipX:
move.l (a1)+,d3
eori.l #(flip_x<<16)|flip_x,d3 ; toggle X-flip flag of the 8x8s
swap d3 ; swap the position of the 8x8s
move.l d3,(a6) ; write top two 8x8s to VRAM
move.l (a1)+,d3
eori.l #(flip_x<<16)|flip_x,d3
swap d3
move.l d3,(a2)+ ; store bottom two 8x8s for later writing
rts
; ===========================================================================
ProcessAndWriteBlock_FlipY:
btst #2,(a0) ; is this 16x16 to be X-flipped as well?
bne.s ProcessAndWriteBlock_FlipXY ; if it is, branch
move.l (a1)+,d0
move.l (a1)+,d3
eori.l #(flip_y<<16)|flip_y,d3 ; toggle Y-flip flag of the 8x8s
move.l d3,(a6) ; write bottom two 8x8s to VRAM
eori.l #(flip_y<<16)|flip_y,d0
move.l d0,(a2)+ ; store top two 8x8s for later writing
rts
; ===========================================================================
ProcessAndWriteBlock_FlipXY:
move.l (a1)+,d0
move.l (a1)+,d3
eori.l #((flip_x|flip_y)<<16)|flip_x|flip_y,d3 ; toggle X and Y-flip flags of the 8x8s
swap d3
move.l d3,(a6) ; write bottom two 8x8s to VRAM
eori.l #((flip_x|flip_y)<<16)|flip_x|flip_y,d0
swap d0
move.l d0,(a2)+ ; store top two 8x8s for later writing
rts
; End of function ProcessAndWriteBlock
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_E136:
ProcessAndWriteBlock_2P:
btst #3,(a0)
bne.s loc_E154
btst #2,(a0)
bne.s loc_E146
move.l (a1)+,(a6)
rts
; ===========================================================================
loc_E146:
move.l (a1)+,d3
eori.l #(flip_x<<16)|flip_x,d3
swap d3
move.l d3,(a6)
rts
; ===========================================================================
loc_E154:
btst #2,(a0)
bne.s loc_E166
move.l (a1)+,d3
eori.l #(flip_y<<16)|flip_y,d3
move.l d3,(a6)
rts
; ===========================================================================
loc_E166:
move.l (a1)+,d3
eori.l #((flip_x|flip_y)<<16)|flip_x|flip_y,d3
swap d3
move.l d3,(a6)
rts
; End of function ProcessAndWriteBlock_2P
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_E174:
ProcessAndWriteBlock2:
or.w d2,d0
swap d0 ; make VRAM write command
btst #3,(a0) ; is the 16x16 to be Y-flipped?
bne.s ProcessAndWriteBlock2_FlipY ; if it is, branch
btst #2,(a0) ; is the 16x16 to be X-flipped?
bne.s ProcessAndWriteBlock2_FlipX ; if it is, branch
move.l d0,(a5) ; write to this VRAM address
move.l (a1)+,(a6) ; write top two 8x8s
add.l d7,d0 ; move onto next line
move.l d0,(a5)
move.l (a1)+,(a6) ; write bottom two 8x8s
rts
; ===========================================================================
ProcessAndWriteBlock2_FlipX:
move.l d0,(a5)
move.l (a1)+,d3
eori.l #(flip_x<<16)|flip_x,d3 ; toggle X-flip flag of the 8x8s
swap d3 ; swap the position of the 8x8s
move.l d3,(a6) ; write top two 8x8s
add.l d7,d0 ; move onto next line
move.l d0,(a5)
move.l (a1)+,d3
eori.l #(flip_x<<16)|flip_x,d3
swap d3
move.l d3,(a6) ; write bottom two 8x8s
rts
; ===========================================================================
ProcessAndWriteBlock2_FlipY:
btst #2,(a0) ; is the 16x16 to be X-flipped as well?
bne.s ProcessAndWriteBlock2_FlipXY ; if it is, branch
move.l d5,-(sp)
move.l d0,(a5)
move.l (a1)+,d5
move.l (a1)+,d3
eori.l #(flip_y<<16)|flip_y,d3 ; toggle Y-flip flag of 8x8s
move.l d3,(a6) ; write bottom two 8x8s
add.l d7,d0 ; move onto next line
move.l d0,(a5)
eori.l #(flip_y<<16)|flip_y,d5
move.l d5,(a6) ; write top two 8x8s
move.l (sp)+,d5
rts
; ===========================================================================
ProcessAndWriteBlock2_FlipXY:
move.l d5,-(sp)
move.l d0,(a5)
move.l (a1)+,d5
move.l (a1)+,d3
eori.l #((flip_x|flip_y)<<16)|flip_x|flip_y,d3 ; toggle X and Y-flip flags of 8x8s
swap d3 ; swap the position of the 8x8s
move.l d3,(a6) ; write bottom two 8x8s
add.l d7,d0
move.l d0,(a5)
eori.l #((flip_x|flip_y)<<16)|flip_x|flip_y,d5
swap d5
move.l d5,(a6) ; write top two 8x8s
move.l (sp)+,d5
rts
; End of function ProcessAndWriteBlock2
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_E1FA:
ProcessAndWriteBlock2_2P:
or.w d2,d0
swap d0
btst #3,(a0)
bne.s loc_E220
btst #2,(a0)
bne.s loc_E210
move.l d0,(a5)
move.l (a1)+,(a6)
rts
; ===========================================================================
loc_E210:
move.l d0,(a5)
move.l (a1)+,d3
eori.l #(flip_x<<16)|flip_x,d3
swap d3
move.l d3,(a6)
rts
; ===========================================================================
loc_E220:
btst #2,(a0)
bne.s loc_E234
move.l d0,(a5)
move.l (a1)+,d3
eori.l #(flip_y<<16)|flip_y,d3
move.l d3,(a6)
rts
; ===========================================================================
loc_E234:
move.l d0,(a5)
move.l (a1)+,d3
eori.l #((flip_x|flip_y)<<16)|flip_x|flip_y,d3
swap d3
move.l d3,(a6)
rts
; End of function ProcessAndWriteBlock2_2P
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_E244
GetBlockPtr:
add.w (a3),d5
add.w 4(a3),d4
lea (Block_Table).w,a1
move.w d4,d3 ; d3 = camera Y pos + offset
add.w d3,d3
andi.w #$F00,d3 ; limit to units of $100 ($100 = $80 * 2, $80 = height of a 128x128)
lsr.w #3,d5 ; divide by 8
move.w d5,d0
lsr.w #4,d0 ; divide by 16 (overall division of 128)
andi.w #$7F,d0
add.w d3,d0 ; get offset of current 128x128 in the level layout table
moveq #-1,d3
clr.w d3 ; d3 = $FFFF0000
move.b (a4,d0.w),d3 ; get tile ID of the current 128x128 tile
lsl.w #7,d3 ; multiply by 128, the size in bytes of a 128x128 in RAM
andi.w #$70,d4 ; round down to nearest 16-pixel boundary
andi.w #$E,d5 ; force this to be a multiple of 16
add.w d4,d3 ; add vertical offset of current 16x16
add.w d5,d3 ; add horizontal offset of current 16x16
movea.l d3,a0 ; store address, in the metablock table, of the current 16x16
move.w (a0),d3
andi.w #$3FF,d3
lsl.w #3,d3
adda.w d3,a1
rts
; End of function GetBlockPtr
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_E286: Calc_VRAM_Pos:
CalcBlockVRAMPos:
add.w (a3),d5 ; add X pos
CalcBlockVRAMPos2:
tst.w (Two_player_mode).w
bne.s CalcBlockVRAMPos_2P
add.w 4(a3),d4 ; add Y pos
andi.w #$F0,d4 ; round down to the nearest 16-pixel boundary
andi.w #$1F0,d5 ; round down to the nearest 16-pixel boundary
lsl.w #4,d4 ; make it into units of $100 - the height in plane A of a 16x16
lsr.w #2,d5 ; make it into units of 4 - the width in plane A of a 16x16
add.w d5,d4 ; combine the two to get final address
; access a VDP address in plane name table A ($C000) or B ($E000) if d2 has bit 13 unset or set
moveq #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE)&$FFFF,d0
swap d0
move.w d4,d0 ; make word-swapped VDP command
rts
; ===========================================================================
; loc_E2A8:
CalcBlockVRAMPos_2P:
add.w 4(a3),d4
loc_E2AC:
andi.w #$1F0,d4
andi.w #$1F0,d5
lsl.w #3,d4
lsr.w #2,d5
add.w d5,d4
; access a VDP address in plane name table A ($C000) or B ($E000) if d2 has bit 13 unset or set
moveq #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE)&$FFFF,d0
swap d0
move.w d4,d0
rts
; End of function CalcBlockVRAMPos
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;loc_E2C2:
CalcBlockVRAMPosB:
tst.w (Two_player_mode).w
bne.s +
add.w 4(a3),d4
add.w (a3),d5
andi.w #$F0,d4
andi.w #$1F0,d5
lsl.w #4,d4
lsr.w #2,d5
add.w d5,d4
; access a VDP address in 2p plane name table A ($A000) or B ($8000) if d2 has bit 13 unset or set
moveq #vdpComm(VRAM_Plane_A_Name_Table_2P,VRAM,WRITE)&$FFFF,d0
swap d0
move.w d4,d0
rts
; ===========================================================================
; interestingly, this subroutine was in the Sonic 1 ROM, unused
+
add.w 4(a3),d4
add.w (a3),d5
andi.w #$1F0,d4
andi.w #$1F0,d5
lsl.w #3,d4
lsr.w #2,d5
add.w d5,d4
; access a VDP address in 2p plane name table A ($A000) or B ($8000) if d2 has bit 13 unset or set
moveq #vdpComm(VRAM_Plane_A_Name_Table_2P,VRAM,WRITE)&$FFFF,d0
swap d0
move.w d4,d0
rts
; End of function CalcBlockVRAMPosB
; ===========================================================================
; Loads the background in its initial state into VRAM (plane B).
; Especially important for levels that never re-load the background dynamically
;loc_E300:
DrawInitialBG:
lea (VDP_control_port).l,a5
lea (VDP_data_port).l,a6
lea (Camera_BG_X_pos).w,a3
lea (Level_Layout+$80).w,a4 ; background
move.w #vdpComm(VRAM_Plane_B_Name_Table,VRAM,WRITE)>>16,d2
moveq #0,d4
cmpi.b #casino_night_zone,(Current_Zone).w
beq.w ++
tst.w (Two_player_mode).w
beq.w +
cmpi.b #mystic_cave_zone,(Current_Zone).w
beq.w loc_E396
+
moveq #-$10,d4
+
moveq #$F,d6
- movem.l d4-d6,-(sp)
moveq #0,d5
move.w d4,d1
bsr.w CalcBlockVRAMPos
move.w d1,d4
moveq #0,d5
moveq #$1F,d6
move #$2700,sr
bsr.w DrawBlockRow
move #$2300,sr
movem.l (sp)+,d4-d6
addi.w #$10,d4
dbf d6,-
rts
; ===========================================================================
; dead code
moveq #-$10,d4
moveq #$F,d6
- movem.l d4-d6,-(sp)
moveq #0,d5
move.w d4,d1
bsr.w CalcBlockVRAMPosB
move.w d1,d4
moveq #0,d5
moveq #$1F,d6
move #$2700,sr
bsr.w DrawBlockRow
move #$2300,sr
movem.l (sp)+,d4-d6
addi.w #$10,d4
dbf d6,-
rts
; ===========================================================================
loc_E396:
moveq #0,d4
moveq #$1F,d6
- movem.l d4-d6,-(sp)
moveq #0,d5
move.w d4,d1
bsr.w loc_E2AC
move.w d1,d4
moveq #0,d5
moveq #$1F,d6
move #$2700,sr
bsr.w DrawBlockRow3
move #$2300,sr
movem.l (sp)+,d4-d6
addi.w #$10,d4
dbf d6,-
rts
; ===========================================================================
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; loadZoneBlockMaps
; Loads block and bigblock mappings for the current Zone.
loadZoneBlockMaps:
moveq #0,d0
move.b (Current_Zone).w,d0
add.w d0,d0
add.w d0,d0
move.w d0,d1
add.w d0,d0
add.w d1,d0
lea (LevelArtPointers).l,a2
lea (a2,d0.w),a2
move.l a2,-(sp)
addq.w #4,a2
move.l (a2)+,d0
andi.l #$FFFFFF,d0 ; pointer to block mappings
movea.l d0,a0
lea (Block_Table).w,a1
jsrto (KosDec).l, JmpTo_KosDec ; load block maps
cmpi.b #hill_top_zone,(Current_Zone).w
bne.s +
lea (Block_Table+$980).w,a1
lea (BM16_HTZ).l,a0
jsrto (KosDec).l, JmpTo_KosDec ; patch for Hill Top Zone block map
+
tst.w (Two_player_mode).w
beq.s +
; In 2P mode, adjust the block table to halve the pattern index on each block
lea (Block_Table).w,a1
move.w #bytesToWcnt(Block_Table_End-Block_Table),d2
- move.w (a1),d0 ; read an entry
move.w d0,d1
andi.w #$F800,d0 ; filter for upper five bits
andi.w #$7FF,d1 ; filter for lower eleven bits (patternIndex)
lsr.w #1,d1 ; halve the pattern index
or.w d1,d0 ; put the parts back together
move.w d0,(a1)+ ; change the entry with the adjusted value
dbf d2,-
+
move.l (a2)+,d0
andi.l #$FFFFFF,d0 ; pointer to chunk mappings
movea.l d0,a0
lea (Chunk_Table).l,a1
jsrto (KosDec).l, JmpTo_KosDec
bsr.w loadLevelLayout
movea.l (sp)+,a2 ; zone specific pointer in LevelArtPointers
addq.w #4,a2
moveq #0,d0
move.b (a2),d0 ; PLC2 ID
beq.s +
jsrto (LoadPLC).l, JmpTo_LoadPLC
+
addq.w #4,a2
moveq #0,d0
move.b (a2),d0 ; palette ID
jsrto (PalLoad_Now).l, JmpTo_PalLoad_Now
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
loadLevelLayout:
moveq #0,d0
move.w (Current_ZoneAndAct).w,d0
ror.b #1,d0
lsr.w #6,d0
lea (Off_Level).l,a0
move.w (a0,d0.w),d0
lea (a0,d0.l),a0
lea (Level_Layout).w,a1
jmpto (KosDec).l, JmpTo_KosDec
; End of function loadLevelLayout
; ===========================================================================
lea (Level_Layout).w,a3
move.w #bytesToLcnt(Level_Layout_End-Level_Layout),d1
moveq #0,d0
- move.l d0,(a3)+
dbf d1,-
lea (Level_Layout).w,a3
moveq #0,d1
bsr.w sub_E4A2
lea (Level_Layout+$80).w,a3
moveq #2,d1
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_E4A2:
moveq #0,d0
move.w (Current_ZoneAndAct).w,d0
ror.b #1,d0
lsr.w #5,d0
add.w d1,d0
lea (Off_Level).l,a1
move.w (a1,d0.w),d0
lea (a1,d0.l),a1
moveq #0,d1
move.w d1,d2
move.b (a1)+,d1
move.b (a1)+,d2
move.l d1,d5
addq.l #1,d5
moveq #0,d3
move.w #$80,d3
divu.w d5,d3
subq.w #1,d3
- movea.l a3,a0
move.w d3,d4
- move.l a1,-(sp)
move.w d1,d0
- move.b (a1)+,(a0)+
dbf d0,-
movea.l (sp)+,a1
dbf d4,--
lea (a1,d5.w),a1
lea $100(a3),a3
dbf d2,---
rts
; End of function sub_E4A2
; ===========================================================================
lea ($FE0000).l,a1
lea ($FE0080).l,a2
lea (Chunk_Table).l,a3
move.w #$3F,d1
- bsr.w sub_E59C
bsr.w sub_E59C
dbf d1,-
lea ($FE0000).l,a1
lea ($FF0000).l,a2
move.w #$3F,d1
- move.w #0,(a2)+
dbf d1,-
move.w #$3FBF,d1
- move.w (a1)+,(a2)+
dbf d1,-
rts
; ===========================================================================
lea ($FE0000).l,a1
lea (Chunk_Table).l,a3
moveq #$1F,d0
- move.l (a1)+,(a3)+
dbf d0,-
moveq #0,d7
lea ($FE0000).l,a1
move.w #$FF,d5
loc_E55A:
lea (Chunk_Table).l,a3
move.w d7,d6
- movem.l a1-a3,-(sp)
move.w #$3F,d0
- cmpm.w (a1)+,(a3)+
bne.s +
dbf d0,-
movem.l (sp)+,a1-a3
adda.w #$80,a1
dbf d5,loc_E55A
bra.s ++
; ===========================================================================
+ movem.l (sp)+,a1-a3
adda.w #$80,a3
dbf d6,--
moveq #$1F,d0
- move.l (a1)+,(a3)+
dbf d0,-
addq.l #1,d7
dbf d5,loc_E55A
/
bra.s - ; infinite loop
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_E59C:
moveq #7,d0
- move.l (a3)+,(a1)+
move.l (a3)+,(a1)+
move.l (a3)+,(a1)+
move.l (a3)+,(a1)+
move.l (a3)+,(a2)+
move.l (a3)+,(a2)+
move.l (a3)+,(a2)+
move.l (a3)+,(a2)+
dbf d0,-
adda.w #$80,a1
adda.w #$80,a2
rts
; End of function sub_E59C
; ===========================================================================
if gameRevision=0
nop
endif
if ~~removeJmpTos
; JmpTo_PalLoad2
JmpTo_PalLoad_Now
jmp (PalLoad_Now).l
JmpTo_LoadPLC
jmp (LoadPLC).l
JmpTo_KosDec
jmp (KosDec).l
align 4
endif
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; screen resizing, earthquakage, etc
; sub_E5D0:
RunDynamicLevelEvents:
moveq #0,d0
move.b (Current_Zone).w,d0
add.w d0,d0
move.w DynamicLevelEventIndex(pc,d0.w),d0
jsr DynamicLevelEventIndex(pc,d0.w)
moveq #2,d1
move.w (Camera_Max_Y_pos).w,d0
sub.w (Camera_Max_Y_pos_now).w,d0
beq.s ++ ; rts
bcc.s +++
neg.w d1
move.w (Camera_Y_pos).w,d0
cmp.w (Camera_Max_Y_pos).w,d0
bls.s +
move.w d0,(Camera_Max_Y_pos_now).w
andi.w #$FFFE,(Camera_Max_Y_pos_now).w
+
add.w d1,(Camera_Max_Y_pos_now).w
move.b #1,(Camera_Max_Y_Pos_Changing).w
+
rts
; ===========================================================================
+
move.w (Camera_Y_pos).w,d0
addi_.w #8,d0
cmp.w (Camera_Max_Y_pos_now).w,d0
blo.s +
btst #1,(MainCharacter+status).w
beq.s +
add.w d1,d1
add.w d1,d1
+
add.w d1,(Camera_Max_Y_pos_now).w
move.b #1,(Camera_Max_Y_Pos_Changing).w
rts
; End of function RunDynamicLevelEvents
; ===========================================================================
; off_E636:
DynamicLevelEventIndex: zoneOrderedOffsetTable 2,1
zoneOffsetTableEntry.w LevEvents_EHZ ; 0 ; EHZ
zoneOffsetTableEntry.w LevEvents_001 ; 1 ; LEV1
zoneOffsetTableEntry.w LevEvents_002 ; 2 ; LEV2
zoneOffsetTableEntry.w LevEvents_003 ; 3 ; LEV3
zoneOffsetTableEntry.w LevEvents_MTZ ; 4 ; MTZ
zoneOffsetTableEntry.w LevEvents_MTZ3 ; 5 ; MTZ3
zoneOffsetTableEntry.w LevEvents_WFZ ; 6 ; WFZ
zoneOffsetTableEntry.w LevEvents_HTZ ; 7 ; HTZ
zoneOffsetTableEntry.w LevEvents_HPZ ; 8 ; HPZ
zoneOffsetTableEntry.w LevEvents_009 ; 9 ; LEV9
zoneOffsetTableEntry.w LevEvents_OOZ ; $A ; OOZ
zoneOffsetTableEntry.w LevEvents_MCZ ; $B ; MCZ
zoneOffsetTableEntry.w LevEvents_CNZ ; $C ; CNZ
zoneOffsetTableEntry.w LevEvents_CPZ ; $D ; CPZ
zoneOffsetTableEntry.w LevEvents_DEZ ; $E ; DEZ
zoneOffsetTableEntry.w LevEvents_ARZ ; $F ; ARZ
zoneOffsetTableEntry.w LevEvents_SCZ ; $10 ; SCZ
zoneTableEnd
; ===========================================================================
; loc_E658:
LevEvents_EHZ:
tst.b (Current_Act).w
bne.s LevEvents_EHZ2
rts
; ---------------------------------------------------------------------------
LevEvents_EHZ2:
moveq #0,d0
move.b (Dynamic_Resize_Routine).w,d0
move.w LevEvents_EHZ2_Index(pc,d0.w),d0
jmp LevEvents_EHZ2_Index(pc,d0.w)
; ===========================================================================
; off_E66E:
LevEvents_EHZ2_Index: offsetTable
offsetTableEntry.w LevEvents_EHZ2_Routine1 ; 0
offsetTableEntry.w LevEvents_EHZ2_Routine2 ; 2
offsetTableEntry.w LevEvents_EHZ2_Routine3 ; 4
offsetTableEntry.w LevEvents_EHZ2_Routine4 ; 6
; ===========================================================================
; loc_E676:
LevEvents_EHZ2_Routine1:
tst.w (Two_player_mode).w
bne.s ++
cmpi.w #$2780,(Camera_X_pos).w
blo.s + ; rts
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
move.w #$390,(Camera_Max_Y_pos).w
move.w #$390,(Tails_Max_Y_pos).w
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_EHZ2_Routine2
+
rts
; ---------------------------------------------------------------------------
+
move.w #$2920,(Camera_Max_X_pos).w
move.w #$2920,(Tails_Max_X_pos).w
rts
; ===========================================================================
; loc_E6B0:
LevEvents_EHZ2_Routine2:
cmpi.w #$28F0,(Camera_X_pos).w
blo.s + ; rts
move.w #$28F0,(Camera_Min_X_pos).w
move.w #$2940,(Camera_Max_X_pos).w
move.w #$28F0,(Tails_Min_X_pos).w
move.w #$2940,(Tails_Max_X_pos).w
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_EHZ2_Routine3
move.w #MusID_FadeOut,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
clr.b (ScreenShift).w
move.b #2,(Current_Boss_ID).w
moveq #PLCID_EhzBoss,d0
jsrto (LoadPLC).l, JmpTo2_LoadPLC
+
rts
; ===========================================================================
; loc_E6EE:
LevEvents_EHZ2_Routine3:
cmpi.w #$388,(Camera_Y_pos).w
blo.s +
move.w #$388,(Camera_Min_Y_pos).w
move.w #$388,(Tails_Min_Y_pos).w
+
addq.b #1,(ScreenShift).w
cmpi.b #$5A,(ScreenShift).w
blo.s ++
jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad
bne.s +
move.b #ObjID_EHZBoss,id(a1) ; load obj56 (EHZ boss)
move.b #$81,subtype(a1)
move.w #$29D0,x_pos(a1)
move.w #$426,y_pos(a1)
+
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_EHZ2_Routine4
move.w #MusID_Boss,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
+
rts
; ===========================================================================
; loc_E738:
LevEvents_EHZ2_Routine4:
tst.b (Boss_defeated_flag).w
beq.s +
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
+
rts
; ===========================================================================
; return_E752:
LevEvents_001:
rts
; ===========================================================================
; return_E754:
LevEvents_002:
rts
; ===========================================================================
; return_E756:
LevEvents_003:
rts
; ===========================================================================
; return_E758:
LevEvents_MTZ:
rts
; ===========================================================================
; loc_E75A:
LevEvents_MTZ3:
moveq #0,d0
move.b (Dynamic_Resize_Routine).w,d0
move.w LevEvents_MTZ3_Index(pc,d0.w),d0
jmp LevEvents_MTZ3_Index(pc,d0.w)
; ===========================================================================
; off_E768:
LevEvents_MTZ3_Index: offsetTable
offsetTableEntry.w LevEvents_MTZ3_Routine1 ; 0
offsetTableEntry.w LevEvents_MTZ3_Routine2 ; 2
offsetTableEntry.w LevEvents_MTZ3_Routine3 ; 4
offsetTableEntry.w LevEvents_MTZ3_Routine4 ; 6
offsetTableEntry.w LevEvents_MTZ3_Routine5 ; 8
; ===========================================================================
; loc_E772:
LevEvents_MTZ3_Routine1:
cmpi.w #$2530,(Camera_X_pos).w
blo.s +
move.w #$500,(Camera_Max_Y_pos_now).w
move.w #$450,(Camera_Max_Y_pos).w
move.w #$450,(Tails_Max_Y_pos).w
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_MTZ3_Routine2
+
rts
; ===========================================================================
; loc_E792:
LevEvents_MTZ3_Routine2:
cmpi.w #$2980,(Camera_X_pos).w
blo.s +
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
move.w #$400,(Camera_Max_Y_pos).w
move.w #$400,(Tails_Max_Y_pos).w
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_MTZ3_Routine3
+
rts
; ===========================================================================
; loc_E7B8:
LevEvents_MTZ3_Routine3:
cmpi.w #$2A80,(Camera_X_pos).w
blo.s +
move.w #$2AB0,(Camera_Min_X_pos).w
move.w #$2AB0,(Camera_Max_X_pos).w
move.w #$2AB0,(Tails_Min_X_pos).w
move.w #$2AB0,(Tails_Max_X_pos).w
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_MTZ3_Routine4
move.w #MusID_FadeOut,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
clr.b (ScreenShift).w
move.b #7,(Current_Boss_ID).w
moveq #PLCID_MtzBoss,d0
jsrto (LoadPLC).l, JmpTo2_LoadPLC
+
rts
; ===========================================================================
; loc_E7F6:
LevEvents_MTZ3_Routine4:
cmpi.w #$400,(Camera_Y_pos).w
blo.s +
move.w #$400,(Camera_Min_Y_pos).w
move.w #$400,(Tails_Min_Y_pos).w
+
addq.b #1,(ScreenShift).w
cmpi.b #$5A,(ScreenShift).w
blo.s ++
jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad
bne.s +
move.b #ObjID_MTZBoss,id(a1) ; load obj54 (MTZ boss)
+
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_MTZ3_Routine5
move.w #MusID_Boss,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
+
rts
; ===========================================================================
; loc_E82E:
LevEvents_MTZ3_Routine5:
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
rts
; ===========================================================================
; loc_E842:
LevEvents_WFZ:
moveq #0,d0
move.b (Dynamic_Resize_Routine).w,d0
move.w LevEvents_WFZ_Index(pc,d0.w),d0
jsr LevEvents_WFZ_Index(pc,d0.w)
move.w (WFZ_LevEvent_Subrout).w,d0
move.w LevEvents_WFZ_Index2(pc,d0.w),d0
jmp LevEvents_WFZ_Index2(pc,d0.w)
; ===========================================================================
; off_E85C:
LevEvents_WFZ_Index2: offsetTable
offsetTableEntry.w LevEvents_WFZ_Routine5 ; 0
offsetTableEntry.w LevEvents_WFZ_Routine6 ; 2
offsetTableEntry.w LevEvents_WFZ_RoutineNull ; 4
; ===========================================================================
; off_E862:
LevEvents_WFZ_Index: offsetTable
offsetTableEntry.w LevEvents_WFZ_Routine1 ; 0
offsetTableEntry.w LevEvents_WFZ_Routine2 ; 2
offsetTableEntry.w LevEvents_WFZ_Routine3 ; 4
offsetTableEntry.w LevEvents_WFZ_Routine4 ; 6
; ===========================================================================
; loc_E86A:
LevEvents_WFZ_Routine1:
move.l (Camera_X_pos).w,(Camera_BG_X_pos).w
move.l (Camera_Y_pos).w,(Camera_BG_Y_pos).w
moveq #0,d0
move.w d0,(Camera_BG_X_pos_diff).w
move.w d0,(Camera_BG_Y_pos_diff).w
move.w d0,(Camera_BG_X_offset).w
move.w d0,(Camera_BG_Y_offset).w
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_WFZ_Routine2
rts
; ===========================================================================
; loc_E88E:
LevEvents_WFZ_Routine2:
cmpi.w #$2BC0,(Camera_X_pos).w
blo.s +
cmpi.w #$580,(Camera_Y_pos).w
blo.s +
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_WFZ_Routine3
move.w #0,(WFZ_BG_Y_Speed).w
+
move.w (Camera_X_pos_diff).w,(Camera_BG_X_pos_diff).w
move.w (Camera_Y_pos_diff).w,(Camera_BG_Y_pos_diff).w
move.w (Camera_X_pos).w,d0
move.w (Camera_Y_pos).w,d1
bra.w ScrollBG
; ===========================================================================
; loc_E8C0:
LevEvents_WFZ_Routine3:
cmpi.w #$800,(Camera_BG_X_offset).w
beq.s +
addq.w #2,(Camera_BG_X_offset).w
+
cmpi.w #$600,(Camera_BG_X_offset).w
blt.s LevEvents_WFZ_Routine3_Part2
move.w (WFZ_BG_Y_Speed).w,d0
moveq #4,d1
cmpi.w #$840,d0
bhs.s +
add.w d1,d0
move.w d0,(WFZ_BG_Y_Speed).w
+
lsr.w #8,d0
add.w d0,(Camera_BG_Y_offset).w
; loc_E8EC:
LevEvents_WFZ_Routine3_Part2:
move.w (Camera_X_pos_diff).w,(Camera_BG_X_pos_diff).w
move.w (Camera_Y_pos_diff).w,(Camera_BG_Y_pos_diff).w
move.w (Camera_X_pos).w,d0
move.w (Camera_Y_pos).w,d1
bra.w ScrollBG
; ===========================================================================
; loc_E904:
LevEvents_WFZ_Routine4:
cmpi.w #-$2C0,(Camera_BG_X_offset).w
beq.s ++
subi_.w #2,(Camera_BG_X_offset).w
cmpi.w #$1B81,(Camera_BG_Y_offset).w
beq.s ++
move.w (WFZ_BG_Y_Speed).w,d0
beq.s +
moveq #4,d1
neg.w d1
add.w d1,d0
move.w d0,(WFZ_BG_Y_Speed).w
lsr.w #8,d0
+
addq.w #1,d0
add.w d0,(Camera_BG_Y_offset).w
+
move.w (Camera_X_pos_diff).w,(Camera_BG_X_pos_diff).w
move.w (Camera_Y_pos_diff).w,(Camera_BG_Y_pos_diff).w
move.w (Camera_X_pos).w,d0
move.w (Camera_Y_pos).w,d1
bra.w ScrollBG
; ===========================================================================
; loc_E94A:
LevEvents_WFZ_Routine5:
cmpi.w #$2880,(Camera_X_pos).w
blo.s + ; rts
cmpi.w #$400,(Camera_Y_pos).w
blo.s + ; rts
addq.w #2,(WFZ_LevEvent_Subrout).w ; => LevEvents_WFZ_Routine6
moveq #PLCID_WfzBoss,d0
jsrto (LoadPLC).l, JmpTo2_LoadPLC
move.w #$2880,(Camera_Min_X_pos).w
+
rts
; ===========================================================================
; loc_E96C:
LevEvents_WFZ_Routine6:
cmpi.w #$500,(Camera_Y_pos).w
blo.s + ; rts
addq.w #2,(WFZ_LevEvent_Subrout).w ; => LevEvents_WFZ_RoutineNull
st (Control_Locked).w
moveq #PLCID_Tornado,d0
jsrto (LoadPLC).l, JmpTo2_LoadPLC
+
rts
; ===========================================================================
; return_E984:
LevEvents_WFZ_RoutineNull:
rts
; ===========================================================================
; loc_E986:
LevEvents_HTZ:
tst.b (Current_Act).w
bne.w LevEvents_HTZ2
moveq #0,d0
move.b (Dynamic_Resize_Routine).w,d0
move.w LevEvents_HTZ_Index(pc,d0.w),d0
jmp LevEvents_HTZ_Index(pc,d0.w)
; ===========================================================================
; off_E99C:
LevEvents_HTZ_Index: offsetTable
offsetTableEntry.w LevEvents_HTZ_Routine1 ; 0 left of earthquake
offsetTableEntry.w LevEvents_HTZ_Routine2 ; 2 earthquake
offsetTableEntry.w LevEvents_HTZ_Routine3 ; 4 right of earthquake
; ===========================================================================
; loc_E9A2:
LevEvents_HTZ_Routine1:
cmpi.w #$400,(Camera_Y_pos).w
blo.s LevEvents_HTZ_Routine1_Part2
cmpi.w #$1800,(Camera_X_pos).w
blo.s LevEvents_HTZ_Routine1_Part2
move.b #1,(Screen_Shaking_Flag_HTZ).w
move.l (Camera_X_pos).w,(Camera_BG_X_pos).w
move.l (Camera_Y_pos).w,(Camera_BG_Y_pos).w
moveq #0,d0
move.w d0,(Camera_BG_X_pos_diff).w
move.w d0,(Camera_BG_Y_pos_diff).w
move.w d0,(Camera_BG_X_offset).w
move.w #320,(Camera_BG_Y_offset).w
subi.w #$100,(Camera_BG_Y_pos).w
move.w #0,(HTZ_Terrain_Delay).w
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ_Routine2
-
rts
; ===========================================================================
LevEvents_HTZ_Routine1_Part2:
tst.b (Screen_Shaking_Flag_HTZ).w
beq.s - ; rts
move.w #$200,d0
moveq #0,d1
move.w d1,(Camera_BG_X_pos_diff).w
move.w d1,(Camera_BG_Y_pos_diff).w
bsr.w ScrollBG
or.w d0,d1
bne.s - ; rts
move.b #0,(Screen_Shaking_Flag_HTZ).w
rts
; ===========================================================================
; loc_EA0E:
LevEvents_HTZ_Routine2:
cmpi.w #$1978,(Camera_X_pos).w
blo.w LevEvents_HTZ_Routine2_Continue
cmpi.w #$1E00,(Camera_X_pos).w
blo.s .keep_shaking
move.b #0,(Screen_Shaking_Flag).w
bra.s LevEvents_HTZ_Routine2_Continue
; ---------------------------------------------------------------------------
.keep_shaking:
tst.b (HTZ_Terrain_Direction).w
bne.s .sinking
cmpi.w #320,(Camera_BG_Y_offset).w
beq.s .flip_delay
move.w (Timer_frames).w,d0
move.w d0,d1
andi.w #3,d0
bne.s LevEvents_HTZ_Routine2_Continue
addq.w #1,(Camera_BG_Y_offset).w
andi.w #$3F,d1
bne.s LevEvents_HTZ_Routine2_Continue
move.w #SndID_Rumbling2,d0 ; rumbling sound
jsr (PlaySound).l
bra.s LevEvents_HTZ_Routine2_Continue
; ---------------------------------------------------------------------------
.sinking:
cmpi.w #224,(Camera_BG_Y_offset).w
beq.s .flip_delay
move.w (Timer_frames).w,d0
move.w d0,d1
andi.w #3,d0
bne.s LevEvents_HTZ_Routine2_Continue
subq.w #1,(Camera_BG_Y_offset).w
andi.w #$3F,d1
bne.s LevEvents_HTZ_Routine2_Continue
move.w #SndID_Rumbling2,d0
jsr (PlaySound).l
bra.s LevEvents_HTZ_Routine2_Continue
; ---------------------------------------------------------------------------
.flip_delay:
move.b #0,(Screen_Shaking_Flag).w
subq.w #1,(HTZ_Terrain_Delay).w
bpl.s LevEvents_HTZ_Routine2_Continue
move.w #$78,(HTZ_Terrain_Delay).w
eori.b #1,(HTZ_Terrain_Direction).w
move.b #1,(Screen_Shaking_Flag).w
; loc_EAA0:
LevEvents_HTZ_Routine2_Continue:
cmpi.w #$1800,(Camera_X_pos).w
blo.s .exit_left
cmpi.w #$1F00,(Camera_X_pos).w
bhs.s .exit_right
move.w (Camera_X_pos_diff).w,(Camera_BG_X_pos_diff).w
move.w (Camera_Y_pos_diff).w,(Camera_BG_Y_pos_diff).w
move.w (Camera_X_pos).w,d0
move.w (Camera_Y_pos).w,d1
bra.w ScrollBG
; ---------------------------------------------------------------------------
.exit_left:
move.l #$4000000,(Camera_BG_X_pos).w
moveq #0,d0
move.l d0,(Camera_BG_Y_pos).w
move.l d0,(Camera_BG_X_offset).w
move.b d0,(HTZ_Terrain_Direction).w
subq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ_Routine1
move.w #MusID_StopSFX,d0
jsr (PlaySound).l
rts
; ---------------------------------------------------------------------------
.exit_right:
move.l #$4000000,(Camera_BG_X_pos).w
moveq #0,d0
move.l d0,(Camera_BG_Y_pos).w
move.l d0,(Camera_BG_X_offset).w
move.b d0,(HTZ_Terrain_Direction).w
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ_Routine3
move.w #MusID_StopSFX,d0
jsr (PlaySound).l
rts
; ===========================================================================
; loc_EB14:
LevEvents_HTZ_Routine3:
cmpi.w #$1F00,(Camera_X_pos).w
bhs.s LevEvents_HTZ_Routine3_Part2
move.b #1,(Screen_Shaking_Flag_HTZ).w
move.l (Camera_X_pos).w,(Camera_BG_X_pos).w
move.l (Camera_Y_pos).w,(Camera_BG_Y_pos).w
moveq #0,d0
move.w d0,(Camera_BG_X_pos_diff).w
move.w d0,(Camera_BG_Y_pos_diff).w
move.w d0,(Camera_BG_X_offset).w
move.w #320,(Camera_BG_Y_offset).w
subi.w #$100,(Camera_BG_Y_pos).w
move.w #0,(HTZ_Terrain_Delay).w
subq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ_Routine2
-
rts
; ---------------------------------------------------------------------------
; loc_EB54:
LevEvents_HTZ_Routine3_Part2:
tst.b (Screen_Shaking_Flag_HTZ).w
beq.s - ; rts
move.w #$200,d0
moveq #0,d1
move.w d1,(Camera_BG_X_pos_diff).w
move.w d1,(Camera_BG_Y_pos_diff).w
bsr.w ScrollBG
or.w d0,d1
bne.s - ; rts
move.b #0,(Screen_Shaking_Flag_HTZ).w
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Computes how much the background layer has been scrolled in X and Y and
; stores result to Camera_BG_X_pos_diff and Camera_BG_Y_pos_diff.
; Caps maximum scroll speed to 16 pixels per frame in either direction.
; This is used to decide how much of the BG needs to be reloaded.
;
; Used for rising lava/terrain in HTZ, and for WFZ->DEZ transition in WFZ.
;
; Input:
; d0 Target X position of background
; d1 Target Y position of background
;sub_EB78
ScrollBG:
sub.w (Camera_BG_X_pos).w,d0
sub.w (Camera_BG_X_offset).w,d0
bpl.s .going_right
cmpi.w #-16,d0
bgt.s .skip_x_cap
move.w #-16,d0
.skip_x_cap:
bra.s .move_x
; ===========================================================================
.going_right:
cmpi.w #16,d0
blo.s .move_x
move.w #16,d0
.move_x:
move.b d0,(Camera_BG_X_pos_diff).w
sub.w (Camera_BG_Y_pos).w,d1
sub.w (Camera_BG_Y_offset).w,d1
bpl.s .going_down
cmpi.w #-16,d1
bgt.s .skip_y_cap
move.w #-16,d1
.skip_y_cap:
bra.s .move_y
; ===========================================================================
.going_down:
cmpi.w #16,d1
blo.s .move_y
move.w #16,d1
.move_y:
move.b d1,(Camera_BG_Y_pos_diff).w
rts
; End of function ScrollBG
; ===========================================================================
; unused/dead code
; This code is probably meant for testing the background scrolling code
; used by HTZ and WFZ. It would allows the BG position to be shifted up
; and down by the second controller.
btst #button_up,(Ctrl_2_Held).w
beq.s +
tst.w (Camera_BG_Y_offset).w
beq.s +
subq.w #1,(Camera_BG_Y_offset).w
+
btst #button_down,(Ctrl_2_Held).w
beq.s +
cmpi.w #$700,(Camera_BG_Y_offset).w
beq.s +
addq.w #1,(Camera_BG_Y_offset).w
+
rts
; ===========================================================================
; sub_EBEA:
LevEvents_HTZ2:
bsr.w LevEvents_HTZ2_Prepare
moveq #0,d0
move.b (Dynamic_Resize_Routine).w,d0
move.w LevEvents_HTZ2_Index(pc,d0.w),d0
jmp LevEvents_HTZ2_Index(pc,d0.w)
; ===========================================================================
; off_EBFC:
LevEvents_HTZ2_Index: offsetTable
offsetTableEntry.w LevEvents_HTZ2_Routine1 ; 0 earthquake left
offsetTableEntry.w LevEvents_HTZ2_Routine2 ; 2 earthquake (top)
offsetTableEntry.w LevEvents_HTZ2_Routine3 ; 4 earthquake right (top)
offsetTableEntry.w LevEvents_HTZ2_Routine4 ; 6 earthquake (bottom)
offsetTableEntry.w LevEvents_HTZ2_Routine5 ; 8 earthquake right (bottom)
offsetTableEntry.w LevEvents_HTZ2_Routine6 ; $A boss area cutoff
offsetTableEntry.w LevEvents_HTZ2_Routine7 ; $C boss area camera shift
offsetTableEntry.w LevEvents_HTZ2_Routine8 ; $E boss begin
offsetTableEntry.w LevEvents_HTZ2_Routine9 ; $10 boss end / extend camera
; ===========================================================================
; loc_EC0E:
LevEvents_HTZ2_Routine1:
cmpi.w #$14C0,(Camera_X_pos).w
blo.s LevEvents_HTZ2_Routine1_Part2
move.b #1,(Screen_Shaking_Flag_HTZ).w
move.l (Camera_X_pos).w,(Camera_BG_X_pos).w
move.l (Camera_Y_pos).w,(Camera_BG_Y_pos).w
moveq #0,d0
move.w d0,(Camera_BG_X_pos_diff).w
move.w d0,(Camera_BG_Y_pos_diff).w
move.w d0,(Camera_BG_X_offset).w
move.w #$2C0,(Camera_BG_Y_offset).w
subi.w #$100,(Camera_BG_Y_pos).w
move.w #0,(HTZ_Terrain_Delay).w
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine2
cmpi.w #$380,(Camera_Y_pos).w
blo.s + ; rts
move.w #-$680,(Camera_BG_X_offset).w
addi.w #$480,(Camera_BG_X_pos).w
move.w #$300,(Camera_BG_Y_offset).w
addq.b #6,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine5
/
rts
; ---------------------------------------------------------------------------
LevEvents_HTZ2_Routine1_Part2:
tst.b (Screen_Shaking_Flag_HTZ).w
beq.s - ; rts
move.w #$200,d0
moveq #0,d1
move.w d1,(Camera_BG_X_pos_diff).w
move.w d1,(Camera_BG_Y_pos_diff).w
bsr.w ScrollBG
or.w d0,d1
bne.s - ; rts
move.b #0,(Screen_Shaking_Flag_HTZ).w
rts
; ===========================================================================
; loc_EC90:
LevEvents_HTZ2_Routine2:
cmpi.w #$1678,(Camera_X_pos).w
blo.w LevEvents_HTZ2_Routine2_Continue
cmpi.w #$1A00,(Camera_X_pos).w
blo.s .keep_shaking
move.b #0,(Screen_Shaking_Flag).w
bra.s LevEvents_HTZ2_Routine2_Continue
; ---------------------------------------------------------------------------
.keep_shaking:
tst.b (HTZ_Terrain_Direction).w
bne.s .sinking
cmpi.w #$2C0,(Camera_BG_Y_offset).w
beq.s .flip_delay
move.w (Timer_frames).w,d0
move.w d0,d1
andi.w #3,d0
bne.s LevEvents_HTZ2_Routine2_Continue
addq.w #1,(Camera_BG_Y_offset).w
andi.w #$3F,d1
bne.s LevEvents_HTZ2_Routine2_Continue
move.w #SndID_Rumbling2,d0
jsr (PlaySound).l
bra.s LevEvents_HTZ2_Routine2_Continue
; ---------------------------------------------------------------------------
.sinking:
cmpi.w #0,(Camera_BG_Y_offset).w
beq.s .flip_delay
move.w (Timer_frames).w,d0
move.w d0,d1
andi.w #3,d0
bne.s LevEvents_HTZ2_Routine2_Continue
subq.w #1,(Camera_BG_Y_offset).w
andi.w #$3F,d1
bne.s LevEvents_HTZ2_Routine2_Continue
move.w #SndID_Rumbling2,d0
jsr (PlaySound).l
bra.s LevEvents_HTZ2_Routine2_Continue
; ---------------------------------------------------------------------------
.flip_delay:
move.b #0,(Screen_Shaking_Flag).w
subq.w #1,(HTZ_Terrain_Delay).w
bpl.s LevEvents_HTZ2_Routine2_Continue
move.w #$78,(HTZ_Terrain_Delay).w
eori.b #1,(HTZ_Terrain_Direction).w
move.b #1,(Screen_Shaking_Flag).w
; loc_ED22:
LevEvents_HTZ2_Routine2_Continue:
cmpi.w #$14C0,(Camera_X_pos).w
blo.s .exit_left
cmpi.w #$1B00,(Camera_X_pos).w
bhs.s .exit_right
move.w (Camera_X_pos_diff).w,(Camera_BG_X_pos_diff).w
move.w (Camera_Y_pos_diff).w,(Camera_BG_Y_pos_diff).w
move.w (Camera_X_pos).w,d0
move.w (Camera_Y_pos).w,d1
bra.w ScrollBG
; ---------------------------------------------------------------------------
.exit_left:
move.l #$4000000,(Camera_BG_X_pos).w
moveq #0,d0
move.l d0,(Camera_BG_Y_pos).w
move.l d0,(Camera_BG_X_offset).w
move.b d0,(HTZ_Terrain_Direction).w
subq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine1
move.w #MusID_StopSFX,d0
jsr (PlaySound).l
rts
; ---------------------------------------------------------------------------
.exit_right:
move.l #$4000000,(Camera_BG_X_pos).w
moveq #0,d0
move.l d0,(Camera_BG_Y_pos).w
move.l d0,(Camera_BG_X_offset).w
move.b d0,(HTZ_Terrain_Direction).w
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine3
move.w #MusID_StopSFX,d0
jsr (PlaySound).l
rts
; ===========================================================================
; loc_ED96:
LevEvents_HTZ2_Routine3:
cmpi.w #$1B00,(Camera_X_pos).w
bhs.s LevEvents_HTZ2_Routine3_Part2
move.b #1,(Screen_Shaking_Flag_HTZ).w
move.l (Camera_X_pos).w,(Camera_BG_X_pos).w
move.l (Camera_Y_pos).w,(Camera_BG_Y_pos).w
moveq #0,d0
move.w d0,(Camera_BG_X_pos_diff).w
move.w d0,(Camera_BG_Y_pos_diff).w
move.w d0,(Camera_BG_X_offset).w
move.w #$2C0,(Camera_BG_Y_offset).w
subi.w #$100,(Camera_BG_Y_pos).w
move.w #0,(HTZ_Terrain_Delay).w
subq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine2
-
rts
; ===========================================================================
LevEvents_HTZ2_Routine3_Part2:
tst.b (Screen_Shaking_Flag_HTZ).w
beq.s - ; rts
move.w #$200,d0
moveq #0,d1
move.w d1,(Camera_BG_X_pos_diff).w
move.w d1,(Camera_BG_Y_pos_diff).w
bsr.w ScrollBG
or.w d0,d1
bne.s - ; rts
move.b #0,(Screen_Shaking_Flag_HTZ).w
rts
; ===========================================================================
; loc_EDFA:
LevEvents_HTZ2_Routine4:
cmpi.w #$15F0,(Camera_X_pos).w
blo.w LevEvents_HTZ2_Routine4_Continue
cmpi.w #$1AC0,(Camera_X_pos).w
bhs.s LevEvents_HTZ2_Routine4_Continue
tst.b (HTZ_Terrain_Direction).w
bne.s .sinking
cmpi.w #$300,(Camera_BG_Y_offset).w
beq.s .flip_delay
move.w (Timer_frames).w,d0
move.w d0,d1
andi.w #3,d0
bne.s LevEvents_HTZ2_Routine4_Continue
addq.w #1,(Camera_BG_Y_offset).w
andi.w #$3F,d1
bne.s LevEvents_HTZ2_Routine4_Continue
move.w #SndID_Rumbling2,d0
jsr (PlaySound).l
bra.s LevEvents_HTZ2_Routine4_Continue
; ===========================================================================
.sinking:
cmpi.w #0,(Camera_BG_Y_offset).w
beq.s .flip_delay
move.w (Timer_frames).w,d0
move.w d0,d1
andi.w #3,d0
bne.s LevEvents_HTZ2_Routine4_Continue
subq.w #1,(Camera_BG_Y_offset).w
andi.w #$3F,d1
bne.s LevEvents_HTZ2_Routine4_Continue
move.w #SndID_Rumbling2,d0
jsr (PlaySound).l
bra.s LevEvents_HTZ2_Routine4_Continue
; ===========================================================================
.flip_delay:
move.b #0,(Screen_Shaking_Flag).w
subq.w #1,(HTZ_Terrain_Delay).w
bpl.s LevEvents_HTZ2_Routine4_Continue
move.w #$78,(HTZ_Terrain_Delay).w
eori.b #1,(HTZ_Terrain_Direction).w
move.b #1,(Screen_Shaking_Flag).w
LevEvents_HTZ2_Routine4_Continue:
cmpi.w #$14C0,(Camera_X_pos).w
blo.s .exit_left
cmpi.w #$1B00,(Camera_X_pos).w
bhs.s .exit_right
move.w (Camera_X_pos_diff).w,(Camera_BG_X_pos_diff).w
move.w (Camera_Y_pos_diff).w,(Camera_BG_Y_pos_diff).w
move.w (Camera_X_pos).w,d0
move.w (Camera_Y_pos).w,d1
bra.w ScrollBG
; ===========================================================================
.exit_left:
move.l #$4000000,(Camera_BG_X_pos).w
moveq #0,d0
move.l d0,(Camera_BG_Y_pos).w
move.l d0,(Camera_BG_X_offset).w
move.b d0,(HTZ_Terrain_Direction).w
subq.b #6,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine1
move.w #MusID_StopSFX,d0
jsr (PlaySound).l
rts
; ===========================================================================
.exit_right:
move.l #$4000000,(Camera_BG_X_pos).w
moveq #0,d0
move.l d0,(Camera_BG_Y_pos).w
move.l d0,(Camera_BG_X_offset).w
move.b d0,(HTZ_Terrain_Direction).w
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine5
move.w #MusID_StopSFX,d0
jsr (PlaySound).l
rts
; ===========================================================================
; loc_EEF8:
LevEvents_HTZ2_Routine5:
cmpi.w #$1B00,(Camera_X_pos).w
bhs.s LevEvents_HTZ2_Routine5_Part2
move.b #1,(Screen_Shaking_Flag_HTZ).w
move.l (Camera_X_pos).w,(Camera_BG_X_pos).w
move.l (Camera_Y_pos).w,(Camera_BG_Y_pos).w
moveq #0,d0
move.w d0,(Camera_BG_X_pos_diff).w
move.w d0,(Camera_BG_Y_pos_diff).w
move.w #-$680,(Camera_BG_X_offset).w
addi.w #$480,(Camera_BG_X_pos).w
move.w #$300,(Camera_BG_Y_offset).w
subi.w #$100,(Camera_BG_Y_pos).w
move.w #0,(HTZ_Terrain_Delay).w
subq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine4
-
rts
; ===========================================================================
LevEvents_HTZ2_Routine5_Part2:
tst.b (Screen_Shaking_Flag_HTZ).w
beq.s - ; rts
move.w #$200,d0
moveq #0,d1
move.w d1,(Camera_BG_X_pos_diff).w
move.w d1,(Camera_BG_Y_pos_diff).w
bsr.w ScrollBG
or.w d0,d1
bne.s - ; rts
move.b #0,(Screen_Shaking_Flag_HTZ).w
rts
; ===========================================================================
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_EF66:
LevEvents_HTZ2_Prepare:
cmpi.w #$2B00,(Camera_X_pos).w
blo.s + ; rts
cmpi.b #$A,(Dynamic_Resize_Routine).w
bge.s + ; rts
move.b #$A,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine6
move.b #0,(Screen_Shaking_Flag_HTZ).w
+
rts
; End of function LevEvents_HTZ2_Prepare
; ===========================================================================
; loc_EF84:
LevEvents_HTZ2_Routine6:
cmpi.w #$2C50,(Camera_X_pos).w
blo.s + ; rts
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
move.w #$480,(Camera_Max_Y_pos).w
move.w #$480,(Tails_Max_Y_pos).w
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine7
+
rts
; ===========================================================================
; loc_EFAA:
LevEvents_HTZ2_Routine7:
cmpi.w #$2EDF,(Camera_X_pos).w
blo.s + ; rts
move.w #$2EE0,(Camera_Min_X_pos).w
move.w #$2F5E,(Camera_Max_X_pos).w
move.w #$2EE0,(Tails_Min_X_pos).w
move.w #$2F5E,(Tails_Max_X_pos).w
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine8
move.w #MusID_FadeOut,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
clr.b (ScreenShift).w
move.b #3,(Current_Boss_ID).w
moveq #PLCID_HtzBoss,d0
jmpto (LoadPLC).l, JmpTo2_LoadPLC
; ===========================================================================
+
rts
; ===========================================================================
; loc_EFE8:
LevEvents_HTZ2_Routine8:
cmpi.w #$478,(Camera_Y_pos).w
blo.s +
move.w #$478,(Camera_Min_Y_pos).w
move.w #$478,(Tails_Min_Y_pos).w
+
addq.b #1,(ScreenShift).w
cmpi.b #$5A,(ScreenShift).w
blo.s ++ ; rts
jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad
bne.s +
move.b #ObjID_HTZBoss,id(a1) ; load obj52 (HTZ boss)
+
addq.b #2,(Dynamic_Resize_Routine).w ; => LevEvents_HTZ2_Routine9
move.w #MusID_Boss,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
+
rts
; ===========================================================================
; loc_F020:
LevEvents_HTZ2_Routine9:
tst.b (Boss_defeated_flag).w
beq.s ++ ; rts
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
cmpi.w #$30E0,(Camera_X_pos).w
blo.s ++ ; rts
cmpi.w #$428,(Camera_Min_Y_pos).w
blo.s +
subq.w #2,(Camera_Min_Y_pos).w
+
cmpi.w #$430,(Camera_Max_Y_pos).w
blo.s +
subq.w #2,(Camera_Max_Y_pos).w
+
rts
; ===========================================================================
; return_F05A:
LevEvents_HPZ:
rts
; ===========================================================================
; return_F05C:
LevEvents_009:
rts
; ===========================================================================
; loc_F05E:
LevEvents_OOZ:
tst.b (Current_Act).w
bne.s LevEvents_OOZ2
rts
; ---------------------------------------------------------------------------
; loc_F066:
LevEvents_OOZ2:
moveq #0,d0
move.b (Dynamic_Resize_Routine).w,d0
move.w LevEvents_OOZ2_Index(pc,d0.w),d0
jmp LevEvents_OOZ2_Index(pc,d0.w)
; ===========================================================================
; off_F074:
LevEvents_OOZ2_Index: offsetTable
offsetTableEntry.w LevEvents_OOZ2_Routine1 ; 0
offsetTableEntry.w LevEvents_OOZ2_Routine2 ; 2
offsetTableEntry.w LevEvents_OOZ2_Routine3 ; 4
offsetTableEntry.w LevEvents_OOZ2_Routine4 ; 6
; ===========================================================================
; loc_F07C:
LevEvents_OOZ2_Routine1:
cmpi.w #$2668,(Camera_X_pos).w
blo.s + ; rts
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
move.w #$2D8,(Oil+y_pos).w
move.w #$1E0,(Camera_Max_Y_pos).w
move.w #$1E0,(Tails_Max_Y_pos).w
addq.b #2,(Dynamic_Resize_Routine).w
+
rts
; ===========================================================================
; loc_F0A8:
LevEvents_OOZ2_Routine2:
cmpi.w #$2880,(Camera_X_pos).w
blo.s + ; rts
move.w #$2880,(Camera_Min_X_pos).w
move.w #$28C0,(Camera_Max_X_pos).w
move.w #$2880,(Tails_Min_X_pos).w
move.w #$28C0,(Tails_Max_X_pos).w
addq.b #2,(Dynamic_Resize_Routine).w
move.w #MusID_FadeOut,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
clr.b (ScreenShift).w
move.b #8,(Current_Boss_ID).w
moveq #PLCID_OozBoss,d0
jsrto (LoadPLC).l, JmpTo2_LoadPLC
moveq #PalID_OOZ_B,d0
jsrto (PalLoad_Now).l, JmpTo2_PalLoad_Now
+
rts
; ===========================================================================
; loc_F0EC:
LevEvents_OOZ2_Routine3:
cmpi.w #$1D8,(Camera_Y_pos).w
blo.s +
move.w #$1D8,(Camera_Min_Y_pos).w
move.w #$1D8,(Tails_Min_Y_pos).w
+
addq.b #1,(ScreenShift).w
cmpi.b #$5A,(ScreenShift).w
blo.s ++ ; rts
jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad
bne.s +
move.b #ObjID_OOZBoss,id(a1) ; load obj55 (OOZ boss)
+
addq.b #2,(Dynamic_Resize_Routine).w
move.w #MusID_Boss,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
+
rts
; ===========================================================================
; loc_F124:
LevEvents_OOZ2_Routine4:
tst.b (Boss_defeated_flag).w
beq.s + ; rts
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
+
rts
; ===========================================================================
; loc_F13E:
LevEvents_MCZ:
tst.b (Current_Act).w
bne.s LevEvents_MCZ2
rts
; ---------------------------------------------------------------------------
; loc_F146:
LevEvents_MCZ2:
moveq #0,d0
move.b (Dynamic_Resize_Routine).w,d0
move.w LevEvents_MCZ2_Index(pc,d0.w),d0
jmp LevEvents_MCZ2_Index(pc,d0.w)
; ===========================================================================
; off_F154:
LevEvents_MCZ2_Index: offsetTable
offsetTableEntry.w LevEvents_MCZ2_Routine1 ; 0
offsetTableEntry.w LevEvents_MCZ2_Routine2 ; 2
offsetTableEntry.w LevEvents_MCZ2_Routine3 ; 4
offsetTableEntry.w LevEvents_MCZ2_Routine4 ; 6
; ===========================================================================
; loc_F15C:
LevEvents_MCZ2_Routine1:
tst.w (Two_player_mode).w
bne.s ++
cmpi.w #$2080,(Camera_X_pos).w
blo.s + ; rts
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
move.w #$5D0,(Camera_Max_Y_pos).w
move.w #$5D0,(Tails_Max_Y_pos).w
addq.b #2,(Dynamic_Resize_Routine).w
+
rts
; ---------------------------------------------------------------------------
+
move.w #$2100,(Camera_Max_X_pos).w
move.w #$2100,(Tails_Max_X_pos).w
rts
; ===========================================================================
; loc_F196:
LevEvents_MCZ2_Routine2:
cmpi.w #$20F0,(Camera_X_pos).w
blo.s + ; rts
move.w #$20F0,(Camera_Max_X_pos).w
move.w #$20F0,(Camera_Min_X_pos).w
move.w #$20F0,(Tails_Max_X_pos).w
move.w #$20F0,(Tails_Min_X_pos).w
addq.b #2,(Dynamic_Resize_Routine).w
move.w #MusID_FadeOut,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
clr.b (ScreenShift).w
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtUnc_FallingRocks),VRAM,WRITE),(VDP_control_port).l
lea (VDP_data_port).l,a6
lea (ArtUnc_FallingRocks).l,a2
moveq #7,d0
- rept 8
move.l (a2)+,(a6)
endm
dbf d0,-
move.b #5,(Current_Boss_ID).w
moveq #PLCID_MczBoss,d0
jsrto (LoadPLC).l, JmpTo2_LoadPLC
moveq #PalID_MCZ_B,d0
jsrto (PalLoad_Now).l, JmpTo2_PalLoad_Now
+
rts
; ===========================================================================
; loc_F206:
LevEvents_MCZ2_Routine3:
cmpi.w #$5C8,(Camera_Y_pos).w
blo.s +
move.w #$5C8,(Camera_Min_Y_pos).w
move.w #$5C8,(Tails_Min_Y_pos).w
+
addq.b #1,(ScreenShift).w
cmpi.b #$5A,(ScreenShift).w
blo.s ++ ; rts
jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad
bne.s +
move.b #ObjID_MCZBoss,id(a1) ; load obj57 (MCZ boss)
+
addq.b #2,(Dynamic_Resize_Routine).w
move.w #MusID_Boss,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
+
rts
; ===========================================================================
; loc_F23E:
LevEvents_MCZ2_Routine4:
tst.b (Screen_Shaking_Flag).w
beq.s +
move.w (Timer_frames).w,d0
andi.w #$1F,d0
bne.s +
move.w #SndID_Rumbling2,d0
jsrto (PlaySound).l, JmpTo3_PlaySound
+
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
rts
; ===========================================================================
; loc_F26A:
LevEvents_CNZ:
jsr (SlotMachine).l
tst.b (Current_Act).w
bne.s LevEvents_CNZ2
rts ; no events for act 1
; ===========================================================================
; loc_F278:
LevEvents_CNZ2:
moveq #0,d0
move.b (Dynamic_Resize_Routine).w,d0
move.w LevEvents_CNZ2_Index(pc,d0.w),d0
jmp LevEvents_CNZ2_Index(pc,d0.w)
; ===========================================================================
; off_F286:
LevEvents_CNZ2_Index: offsetTable
offsetTableEntry.w LevEvents_CNZ2_Routine1 ; 0
offsetTableEntry.w LevEvents_CNZ2_Routine2 ; 2
offsetTableEntry.w LevEvents_CNZ2_Routine3 ; 4
offsetTableEntry.w LevEvents_CNZ2_Routine4 ; 6
; ===========================================================================
; loc_F28E:
LevEvents_CNZ2_Routine1:
tst.w (Two_player_mode).w
bne.s ++
cmpi.w #$27C0,(Camera_X_pos).w
blo.s + ; rts
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
move.w #$62E,(Camera_Max_Y_pos).w
move.w #$62E,(Tails_Max_Y_pos).w
move.b #$F9,(Level_Layout+$C54).w
addq.b #2,(Dynamic_Resize_Routine).w
+
rts
; ===========================================================================
+
move.w #$26A0,(Camera_Max_X_pos).w
move.w #$26A0,(Tails_Max_X_pos).w
rts
; ===========================================================================
; loc_F2CE:
LevEvents_CNZ2_Routine2:
cmpi.w #$2890,(Camera_X_pos).w
blo.s + ; rts
move.b #$F9,(Level_Layout+$C50).w
move.w #$2860,(Camera_Min_X_pos).w
move.w #$28E0,(Camera_Max_X_pos).w
move.w #$2860,(Tails_Min_X_pos).w
move.w #$28E0,(Tails_Max_X_pos).w
addq.b #2,(Dynamic_Resize_Routine).w
move.w #MusID_FadeOut,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
clr.b (ScreenShift).w
move.b #6,(Current_Boss_ID).w
moveq #PLCID_CnzBoss,d0
jsrto (LoadPLC).l, JmpTo2_LoadPLC
moveq #PalID_CNZ_B,d0
jsrto (PalLoad_Now).l, JmpTo2_PalLoad_Now
+
rts
; ===========================================================================
; loc_F318:
LevEvents_CNZ2_Routine3:
cmpi.w #$4E0,(Camera_Y_pos).w
blo.s +
move.w #$4E0,(Camera_Min_Y_pos).w
move.w #$4E0,(Tails_Min_Y_pos).w
+
addq.b #1,(ScreenShift).w
cmpi.b #$5A,(ScreenShift).w
blo.s ++ ; rts
jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad
bne.s +
move.b #ObjID_CNZBoss,id(a1) ; load obj51
+
addq.b #2,(Dynamic_Resize_Routine).w
move.w #MusID_Boss,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
+
rts
; ===========================================================================
; loc_F350:
LevEvents_CNZ2_Routine4:
cmpi.w #$2A00,(Camera_X_pos).w
blo.s + ; rts
move.w #$5D0,(Camera_Max_Y_pos).w
move.w #$5D0,(Tails_Max_Y_pos).w
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
+
rts
; ===========================================================================
; loc_F378:
LevEvents_CPZ:
tst.b (Current_Act).w
bne.s LevEvents_CPZ2
rts
; ===========================================================================
; loc_F380:
LevEvents_CPZ2:
moveq #0,d0
move.b (Dynamic_Resize_Routine).w,d0
move.w LevEvents_CPZ2_Index(pc,d0.w),d0
jmp LevEvents_CPZ2_Index(pc,d0.w)
; ===========================================================================
; off_F38E:
LevEvents_CPZ2_Index: offsetTable
offsetTableEntry.w LevEvents_CPZ2_Routine1 ; 0
offsetTableEntry.w LevEvents_CPZ2_Routine2 ; 2
offsetTableEntry.w LevEvents_CPZ2_Routine3 ; 4
offsetTableEntry.w LevEvents_CPZ2_Routine4 ; 6
; ===========================================================================
; loc_F396:
LevEvents_CPZ2_Routine1:
cmpi.w #$2680,(Camera_X_pos).w
blo.s + ; rts
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
move.w #$450,(Camera_Max_Y_pos).w
move.w #$450,(Tails_Max_Y_pos).w
addq.b #2,(Dynamic_Resize_Routine).w
+
rts
; ===========================================================================
; loc_F3BC:
LevEvents_CPZ2_Routine2:
cmpi.w #$2A20,(Camera_X_pos).w
blo.s + ; rts
move.w #$2A20,(Camera_Min_X_pos).w
move.w #$2A20,(Camera_Max_X_pos).w
move.w #$2A20,(Tails_Min_X_pos).w
move.w #$2A20,(Tails_Max_X_pos).w
addq.b #2,(Dynamic_Resize_Routine).w
move.w #MusID_FadeOut,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
clr.b (ScreenShift).w
move.b #1,(Current_Boss_ID).w
moveq #PLCID_CpzBoss,d0
jmpto (LoadPLC).l, JmpTo2_LoadPLC
; ===========================================================================
+
rts
; ===========================================================================
; loc_F3FA:
LevEvents_CPZ2_Routine3:
cmpi.w #$448,(Camera_Y_pos).w
blo.s +
move.w #$448,(Camera_Min_Y_pos).w
move.w #$448,(Tails_Min_Y_pos).w
+
addq.b #1,(ScreenShift).w
cmpi.b #$5A,(ScreenShift).w
blo.s ++
jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad
bne.s +
move.b #ObjID_CPZBoss,id(a1) ; load obj5D
+
addq.b #2,(Dynamic_Resize_Routine).w
move.w #MusID_Boss,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
+
rts
; ===========================================================================
; loc_F432:
LevEvents_CPZ2_Routine4:
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
rts
; ===========================================================================
; loc_F446:
LevEvents_DEZ:
moveq #0,d0
move.b (Dynamic_Resize_Routine).w,d0
move.w LevEvents_DEZ_Index(pc,d0.w),d0
jmp LevEvents_DEZ_Index(pc,d0.w)
; ===========================================================================
; off_F454:
LevEvents_DEZ_Index: offsetTable
offsetTableEntry.w LevEvents_DEZ_Routine1 ; 0
offsetTableEntry.w LevEvents_DEZ_Routine2 ; 2
offsetTableEntry.w LevEvents_DEZ_Routine3 ; 4
offsetTableEntry.w LevEvents_DEZ_Routine4 ; 6
offsetTableEntry.w LevEvents_DEZ_Routine5 ; 8
; ===========================================================================
; loc_F45E:
LevEvents_DEZ_Routine1:
move.w #320,d0
cmp.w (Camera_X_pos).w,d0
bhi.s + ; rts
addq.b #2,(Dynamic_Resize_Routine).w
jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad
bne.s + ; rts
move.b #ObjID_MechaSonic,id(a1) ; load objAF (silver sonic)
move.b #$48,subtype(a1)
move.w #$348,x_pos(a1)
move.w #$A0,y_pos(a1)
moveq #PLCID_FieryExplosion,d0
jmpto (LoadPLC).l, JmpTo2_LoadPLC
; ===========================================================================
+
rts
; ===========================================================================
; return_F490:
LevEvents_DEZ_Routine2:
rts
; ===========================================================================
; loc_F492:
LevEvents_DEZ_Routine3:
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
cmpi.w #$300,(Camera_X_pos).w
blo.s + ; rts
addq.b #2,(Dynamic_Resize_Routine).w
moveq #PLCID_DezBoss,d0
jmpto (LoadPLC).l, JmpTo2_LoadPLC
; ===========================================================================
+
rts
; ===========================================================================
; loc_F4AC:
LevEvents_DEZ_Routine4:
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w #$680,d0
cmp.w (Camera_X_pos).w,d0
bhi.s + ; rts
addq.b #2,(Dynamic_Resize_Routine).w
move.w d0,(Camera_Min_X_pos).w
addi.w #$C0,d0
move.w d0,(Camera_Max_X_pos).w
+
rts
; ===========================================================================
; return_F4CE:
LevEvents_DEZ_Routine5:
rts
; ===========================================================================
; loc_F4D0:
LevEvents_ARZ:
tst.b (Current_Act).w
bne.s LevEvents_ARZ2
rts
; ===========================================================================
; loc_F4D8:
LevEvents_ARZ2:
moveq #0,d0
move.b (Dynamic_Resize_Routine).w,d0
move.w LevEvents_ARZ2_Index(pc,d0.w),d0
jmp LevEvents_ARZ2_Index(pc,d0.w)
; ===========================================================================
; off_F4E6:
LevEvents_ARZ2_Index: offsetTable
offsetTableEntry.w LevEvents_ARZ2_Routine1 ; 0
offsetTableEntry.w LevEvents_ARZ2_Routine2 ; 2
offsetTableEntry.w LevEvents_ARZ2_Routine3 ; 4
offsetTableEntry.w LevEvents_ARZ2_Routine4 ; 6
; ===========================================================================
; loc_F4EE:
LevEvents_ARZ2_Routine1:
cmpi.w #$2810,(Camera_X_pos).w
blo.s + ; rts
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
move.w #$400,(Camera_Max_Y_pos).w
move.w #$400,(Tails_Max_Y_pos).w
addq.b #2,(Dynamic_Resize_Routine).w
move.b #4,(Current_Boss_ID).w
moveq #PLCID_ArzBoss,d0
jsrto (LoadPLC).l, JmpTo2_LoadPLC
+
rts
; ===========================================================================
; loc_F520:
LevEvents_ARZ2_Routine2:
cmpi.w #$2A40,(Camera_X_pos).w
blo.s + ; rts
move.w #$2A40,(Camera_Max_X_pos).w
move.w #$2A40,(Camera_Min_X_pos).w
move.w #$2A40,(Tails_Max_X_pos).w
move.w #$2A40,(Tails_Min_X_pos).w
addq.b #2,(Dynamic_Resize_Routine).w
move.w #MusID_FadeOut,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
clr.b (ScreenShift).w
jsrto (SingleObjLoad).l, JmpTo_SingleObjLoad
bne.s + ; rts
move.b #ObjID_ARZBoss,id(a1) ; load obj89
+
rts
; ===========================================================================
; loc_F55C:
LevEvents_ARZ2_Routine3:
cmpi.w #$3F8,(Camera_Y_pos).w
blo.s +
move.w #$3F8,(Camera_Min_Y_pos).w
move.w #$3F8,(Tails_Min_Y_pos).w
+
addq.b #1,(ScreenShift).w
cmpi.b #$5A,(ScreenShift).w
blo.s + ; rts
addq.b #2,(Dynamic_Resize_Routine).w
move.w #MusID_Boss,d0
jsrto (PlayMusic).l, JmpTo3_PlayMusic
+
rts
; ===========================================================================
; loc_F58A:
LevEvents_ARZ2_Routine4:
move.w (Camera_X_pos).w,(Camera_Min_X_pos).w
move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w
move.w (Camera_X_pos).w,(Tails_Min_X_pos).w
rts
; ===========================================================================
; loc_F59E:
LevEvents_SCZ:
tst.b (Current_Act).w
bne.w LevEvents_SCZ2
moveq #0,d0
move.b (Dynamic_Resize_Routine).w,d0
move.w LevEvents_SCZ_Index(pc,d0.w),d0
jmp LevEvents_SCZ_Index(pc,d0.w)
; ===========================================================================
; off_F5B4:
LevEvents_SCZ_Index: offsetTable
offsetTableEntry.w LevEvents_SCZ_Routine1 ; 0
offsetTableEntry.w LevEvents_SCZ_Routine2 ; 2
offsetTableEntry.w LevEvents_SCZ_Routine3 ; 4
offsetTableEntry.w LevEvents_SCZ_Routine4 ; 6
offsetTableEntry.w LevEvents_SCZ_RoutineNull ; 8
; ===========================================================================
; loc_F5BE:
LevEvents_SCZ_Routine1:
move.w #1,(Tornado_Velocity_X).w
move.w #0,(Tornado_Velocity_Y).w
addq.b #2,(Dynamic_Resize_Routine).w
rts
; ===========================================================================
; loc_F5D0:
LevEvents_SCZ_Routine2:
cmpi.w #$1180,(Camera_X_pos).w
blo.s +
move.w #-1,(Tornado_Velocity_X).w
move.w #1,(Tornado_Velocity_Y).w
move.w #$500,(Camera_Max_Y_pos).w
addq.b #2,(Dynamic_Resize_Routine).w
+
rts
; ===========================================================================
; loc_F5F0:
LevEvents_SCZ_Routine3:
cmpi.w #$500,(Camera_Y_pos).w
blo.s +
move.w #1,(Tornado_Velocity_X).w
move.w #0,(Tornado_Velocity_Y).w
addq.b #2,(Dynamic_Resize_Routine).w
+
rts
; ===========================================================================
; loc_F60A:
LevEvents_SCZ_Routine4:
cmpi.w #$1400,(Camera_X_pos).w
blo.s LevEvents_SCZ_RoutineNull
move.w #0,(Tornado_Velocity_X).w
move.w #0,(Tornado_Velocity_Y).w
addq.b #2,(Dynamic_Resize_Routine).w
; return_F622:
LevEvents_SCZ_RoutineNull:
rts
; ===========================================================================
; return_F624:
LevEvents_SCZ2:
rts
; ===========================================================================
; loc_F626:
PlayLevelMusic:
move.w (Level_Music).w,d0
jmpto (PlayMusic).l, JmpTo3_PlayMusic
; ===========================================================================
; loc_F62E:
LoadPLC_AnimalExplosion:
moveq #0,d0
move.b (Current_Zone).w,d0
lea (Animal_PLCTable).l,a2
move.b (a2,d0.w),d0
jsrto (LoadPLC).l, JmpTo2_LoadPLC
moveq #PLCID_Explosion,d0
jsrto (LoadPLC).l, JmpTo2_LoadPLC
rts
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo3_PlaySound
jmp (PlaySound).l
; JmpTo2_PalLoad2
JmpTo2_PalLoad_Now
jmp (PalLoad_Now).l
JmpTo2_LoadPLC
jmp (LoadPLC).l
JmpTo3_PlayMusic
jmp (PlayMusic).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 11 - Bridge in Emerald Hill Zone and Hidden Palace Zone
; ----------------------------------------------------------------------------
; OST Variables:
Obj11_child1 = objoff_30 ; pointer to first set of bridge segments
Obj11_child2 = objoff_34 ; pointer to second set of bridge segments, if applicable
; Sprite_F66C:
Obj11:
btst #6,render_flags(a0) ; is this a child sprite object?
bne.w + ; if yes, branch
moveq #0,d0
move.b routine(a0),d0
move.w Obj11_Index(pc,d0.w),d1
jmp Obj11_Index(pc,d1.w)
; ===========================================================================
+ ; child sprite objects only need to be drawn
move.w #$180,d0
bra.w DisplaySprite3
; ===========================================================================
; off_F68C:
Obj11_Index: offsetTable
offsetTableEntry.w Obj11_Init ; 0
offsetTableEntry.w Obj11_EHZ ; 2
offsetTableEntry.w Obj11_Display ; 4
offsetTableEntry.w Obj11_HPZ ; 6
; ===========================================================================
; loc_F694: Obj11_Main:
Obj11_Init:
addq.b #2,routine(a0)
move.l #Obj11_MapUnc_FC70,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_EHZ_Bridge,2,0),art_tile(a0)
move.b #3,priority(a0)
cmpi.b #hidden_palace_zone,(Current_Zone).w ; is this an HPZ bridge?
bne.s + ; if not, branch
addq.b #4,routine(a0)
move.l #Obj11_MapUnc_FC28,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_HPZ_Bridge,3,0),art_tile(a0)
+
bsr.w Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$80,width_pixels(a0)
move.w y_pos(a0),d2
move.w d2,objoff_3C(a0)
move.w x_pos(a0),d3
lea subtype(a0),a2 ; copy bridge subtype to a2
moveq #0,d1
move.b (a2),d1 ; d1 = subtype
move.w d1,d0
lsr.w #1,d0
lsl.w #4,d0 ; (d0 div 2) * 16
sub.w d0,d3 ; x position of left half
swap d1 ; store subtype in high word for later
move.w #8,d1
bsr.s Obj11_MakeBdgSegment
move.w sub6_x_pos(a1),d0
subq.w #8,d0
move.w d0,x_pos(a1) ; center of first subsprite object
move.l a1,Obj11_child1(a0) ; pointer to first subsprite object
swap d1 ; retrieve subtype
subq.w #8,d1
bls.s + ; branch, if subtype <= 8 (bridge has no more than 8 logs)
; else, create a second subsprite object for the rest of the bridge
move.w d1,d4
bsr.s Obj11_MakeBdgSegment
move.l a1,Obj11_child2(a0) ; pointer to second subsprite object
move.w d4,d0
add.w d0,d0
add.w d4,d0 ; d0*3
move.w sub2_x_pos(a1,d0.w),d0
subq.w #8,d0
move.w d0,x_pos(a1) ; center of second subsprite object
+
bra.s Obj11_EHZ
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_F728:
Obj11_MakeBdgSegment:
jsrto (SingleObjLoad2).l, JmpTo_SingleObjLoad2
bne.s + ; rts
_move.b id(a0),id(a1) ; load obj11
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
move.b render_flags(a0),render_flags(a1)
bset #6,render_flags(a1)
move.b #$40,mainspr_width(a1)
move.b d1,mainspr_childsprites(a1)
subq.b #1,d1
lea sub2_x_pos(a1),a2 ; starting address for subsprite data
- move.w d3,(a2)+ ; sub?_x_pos
move.w d2,(a2)+ ; sub?_y_pos
move.w #0,(a2)+ ; sub?_mapframe
addi.w #$10,d3 ; width of a log, x_pos for next log
dbf d1,- ; repeat for d1 logs
+
rts
; End of function Obj11_MakeBdgSegment
; ===========================================================================
; loc_F77A: Obj11_Action:
Obj11_EHZ:
move.b status(a0),d0
andi.b #standing_mask,d0
bne.s +
tst.b objoff_3E(a0)
beq.s loc_F7BC
subq.b #4,objoff_3E(a0)
bra.s loc_F7B8
+
andi.b #p2_standing,d0
beq.s ++
move.b objoff_3F(a0),d0
sub.b objoff_3B(a0),d0
beq.s ++
bcc.s +
addq.b #1,objoff_3F(a0)
bra.s ++
; ---------------------------------------------------------------------------
+
subq.b #1,objoff_3F(a0)
+
cmpi.b #$40,objoff_3E(a0)
beq.s loc_F7B8
addq.b #4,objoff_3E(a0)
loc_F7B8:
bsr.w Obj11_Depress
loc_F7BC:
moveq #0,d1
move.b subtype(a0),d1
lsl.w #3,d1
move.w d1,d2
addq.w #8,d1
add.w d2,d2
moveq #8,d3
move.w x_pos(a0),d4
bsr.w sub_F872
; loc_F7D4:
Obj11_Unload:
; this is essentially MarkObjGone, except we need to delete our subsprite objects as well
tst.w (Two_player_mode).w ; is it two player mode?
beq.s + ; if not, branch
rts
; ---------------------------------------------------------------------------
+
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.s +
rts
; ---------------------------------------------------------------------------
+ ; delete first subsprite object
movea.l Obj11_child1(a0),a1 ; a1=object
bsr.w DeleteObject2
cmpi.b #8,subtype(a0)
bls.s + ; if bridge has more than 8 logs, delete second subsprite object
movea.l Obj11_child2(a0),a1 ; a1=object
bsr.w DeleteObject2
+
bra.w DeleteObject
; ===========================================================================
; loc_F80C: BranchTo_DisplaySprite:
Obj11_Display:
bra.w DisplaySprite
; ===========================================================================
; loc_F810: Obj11_Action_HPZ:
Obj11_HPZ:
move.b status(a0),d0
andi.b #standing_mask,d0
bne.s +
tst.b objoff_3E(a0)
beq.s loc_F852
subq.b #4,objoff_3E(a0)
bra.s loc_F84E
; ===========================================================================
+
andi.b #p2_standing,d0
beq.s ++
move.b objoff_3F(a0),d0
sub.b objoff_3B(a0),d0
beq.s ++
bcc.s +
addq.b #1,objoff_3F(a0)
bra.s ++
; ===========================================================================
+
subq.b #1,objoff_3F(a0)
+
cmpi.b #$40,objoff_3E(a0)
beq.s loc_F84E
addq.b #4,objoff_3E(a0)
loc_F84E:
bsr.w Obj11_Depress
loc_F852:
moveq #0,d1
move.b subtype(a0),d1
lsl.w #3,d1
move.w d1,d2
addq.w #8,d1
add.w d2,d2
moveq #8,d3
move.w x_pos(a0),d4
bsr.w sub_F872
bsr.w sub_F912
bra.w Obj11_Unload
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_F872:
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
moveq #$3B,d5
movem.l d1-d4,-(sp)
bsr.s +
movem.l (sp)+,d1-d4
lea (MainCharacter).w,a1 ; a1=character
subq.b #1,d6
moveq #$3F,d5
+
btst d6,status(a0)
beq.s loc_F8F0
btst #1,status(a1)
bne.s +
moveq #0,d0
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.s +
cmp.w d2,d0
blo.s ++
+
bclr #3,status(a1)
bclr d6,status(a0)
moveq #0,d4
rts
; ===========================================================================
+
lsr.w #4,d0
move.b d0,(a0,d5.w)
movea.l Obj11_child1(a0),a2
cmpi.w #8,d0
blo.s +
movea.l Obj11_child2(a0),a2 ; a2=object
subi_.w #8,d0
+
add.w d0,d0
move.w d0,d1
add.w d0,d0
add.w d1,d0
move.w sub2_y_pos(a2,d0.w),d0
subq.w #8,d0
moveq #0,d1
move.b y_radius(a1),d1
sub.w d1,d0
move.w d0,y_pos(a1)
moveq #0,d4
rts
; ===========================================================================
loc_F8F0:
move.w d1,-(sp)
jsrto (PlatformObject11_cont).l, JmpTo_PlatformObject11_cont
move.w (sp)+,d1
btst d6,status(a0)
beq.s + ; rts
moveq #0,d0
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
lsr.w #4,d0
move.b d0,(a0,d5.w)
+
rts
; End of function sub_F872
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_F912:
moveq #0,d0
tst.w (MainCharacter+x_vel).w
bne.s +
move.b (Vint_runcount+3).w,d0
andi.w #$1C,d0
lsr.w #1,d0
+
moveq #0,d2
move.b byte_F950+1(pc,d0.w),d2
swap d2
move.b byte_F950(pc,d0.w),d2
moveq #0,d0
tst.w (Sidekick+x_vel).w
bne.s +
move.b (Vint_runcount+3).w,d0
andi.w #$1C,d0
lsr.w #1,d0
+
moveq #0,d6
move.b byte_F950+1(pc,d0.w),d6
swap d6
move.b byte_F950(pc,d0.w),d6
bra.s +
; ===========================================================================
byte_F950:
dc.b 1, 2
dc.b 1, 2 ; 2
dc.b 1, 2 ; 4
dc.b 1, 2 ; 6
dc.b 0, 1 ; 8
dc.b 0, 0 ; 10
dc.b 0, 0 ; 12
dc.b 0, 1 ; 14
; ===========================================================================
+
moveq #-2,d3
moveq #-2,d4
move.b status(a0),d0
andi.b #p1_standing,d0
beq.s +
move.b objoff_3F(a0),d3
+
move.b status(a0),d0
andi.b #p2_standing,d0
beq.s +
move.b objoff_3B(a0),d4
+
movea.l Obj11_child1(a0),a1
lea sub9_mapframe+next_subspr(a1),a2
lea sub2_mapframe(a1),a1
moveq #0,d1
move.b subtype(a0),d1
subq.b #1,d1
moveq #0,d5
- moveq #0,d0
subq.w #1,d3
cmp.b d3,d5
bne.s +
move.w d2,d0
+
addq.w #2,d3
cmp.b d3,d5
bne.s +
move.w d2,d0
+
subq.w #1,d3
subq.w #1,d4
cmp.b d4,d5
bne.s +
move.w d6,d0
+
addq.w #2,d4
cmp.b d4,d5
bne.s +
move.w d6,d0
+
subq.w #1,d4
cmp.b d3,d5
bne.s +
swap d2
move.w d2,d0
swap d2
+
cmp.b d4,d5
bne.s +
swap d6
move.w d6,d0
swap d6
+
move.b d0,(a1)
addq.w #1,d5
addq.w #6,a1
cmpa.w a2,a1
bne.s +
movea.l Obj11_child2(a0),a1 ; a1=object
lea sub2_mapframe(a1),a1
+ dbf d1,-
rts
; End of function sub_F912
; ===========================================================================
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; subroutine to make the bridge push down where Sonic or Tails walks over
; loc_F9E8:
Obj11_Depress:
move.b objoff_3E(a0),d0
jsrto (CalcSine).l, JmpTo_CalcSine
move.w d0,d4
lea (byte_FB28).l,a4
moveq #0,d0
move.b subtype(a0),d0
lsl.w #4,d0
moveq #0,d3
move.b objoff_3F(a0),d3
move.w d3,d2
add.w d0,d3
moveq #0,d5
lea (Obj11_DepressionOffsets-$80).l,a5
move.b (a5,d3.w),d5
andi.w #$F,d3
lsl.w #4,d3
lea (a4,d3.w),a3
movea.l Obj11_child1(a0),a1
lea sub9_y_pos+next_subspr(a1),a2
lea sub2_y_pos(a1),a1
- moveq #0,d0
move.b (a3)+,d0
addq.w #1,d0
mulu.w d5,d0
mulu.w d4,d0
swap d0
add.w objoff_3C(a0),d0
move.w d0,(a1)
addq.w #6,a1
cmpa.w a2,a1
bne.s +
movea.l Obj11_child2(a0),a1 ; a1=object
lea sub2_y_pos(a1),a1
+ dbf d2,-
moveq #0,d0
move.b subtype(a0),d0
moveq #0,d3
move.b objoff_3F(a0),d3
addq.b #1,d3
sub.b d0,d3
neg.b d3
bmi.s ++ ; rts
move.w d3,d2
lsl.w #4,d3
lea (a4,d3.w),a3
adda.w d2,a3
subq.w #1,d2
bcs.s ++ ; rts
- moveq #0,d0
move.b -(a3),d0
addq.w #1,d0
mulu.w d5,d0
mulu.w d4,d0
swap d0
add.w objoff_3C(a0),d0
move.w d0,(a1)
addq.w #6,a1
cmpa.w a2,a1
bne.s +
movea.l Obj11_child2(a0),a1 ; a1=object
lea sub2_y_pos(a1),a1
+ dbf d2,-
+
rts
; ===========================================================================
; seems to be bridge piece vertical position offset data
Obj11_DepressionOffsets: ; byte_FA98:
dc.b 2, 4, 6, 8, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0; 16
dc.b 2, 4, 6, 8, $A, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0; 32
dc.b 2, 4, 6, 8, $A, $A, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0; 48
dc.b 2, 4, 6, 8, $A, $C, $A, 8, 6, 4, 2, 0, 0, 0, 0, 0; 64
dc.b 2, 4, 6, 8, $A, $C, $C, $A, 8, 6, 4, 2, 0, 0, 0, 0; 80
dc.b 2, 4, 6, 8, $A, $C, $E, $C, $A, 8, 6, 4, 2, 0, 0, 0; 96
dc.b 2, 4, 6, 8, $A, $C, $E, $E, $C, $A, 8, 6, 4, 2, 0, 0; 112
dc.b 2, 4, 6, 8, $A, $C, $E,$10, $E, $C, $A, 8, 6, 4, 2, 0; 128
dc.b 2, 4, 6, 8, $A, $C, $E,$10,$10, $E, $C, $A, 8, 6, 4, 2; 144
; something else important for bridge depression to work (phase? bridge size adjustment?)
byte_FB28:
dc.b $FF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 16
dc.b $B5,$FF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 32
dc.b $7E,$DB,$FF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 48
dc.b $61,$B5,$EC,$FF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 64
dc.b $4A,$93,$CD,$F3,$FF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 80
dc.b $3E,$7E,$B0,$DB,$F6,$FF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 96
dc.b $38,$6D,$9D,$C5,$E4,$F8,$FF, 0, 0, 0, 0, 0, 0, 0, 0, 0; 112
dc.b $31,$61,$8E,$B5,$D4,$EC,$FB,$FF, 0, 0, 0, 0, 0, 0, 0, 0; 128
dc.b $2B,$56,$7E,$A2,$C1,$DB,$EE,$FB,$FF, 0, 0, 0, 0, 0, 0, 0; 144
dc.b $25,$4A,$73,$93,$B0,$CD,$E1,$F3,$FC,$FF, 0, 0, 0, 0, 0, 0; 160
dc.b $1F,$44,$67,$88,$A7,$BD,$D4,$E7,$F4,$FD,$FF, 0, 0, 0, 0, 0; 176
dc.b $1F,$3E,$5C,$7E,$98,$B0,$C9,$DB,$EA,$F6,$FD,$FF, 0, 0, 0, 0; 192
dc.b $19,$38,$56,$73,$8E,$A7,$BD,$D1,$E1,$EE,$F8,$FE,$FF, 0, 0, 0; 208
dc.b $19,$38,$50,$6D,$83,$9D,$B0,$C5,$D8,$E4,$F1,$F8,$FE,$FF, 0, 0; 224
dc.b $19,$31,$4A,$67,$7E,$93,$A7,$BD,$CD,$DB,$E7,$F3,$F9,$FE,$FF, 0; 240
dc.b $19,$31,$4A,$61,$78,$8E,$A2,$B5,$C5,$D4,$E1,$EC,$F4,$FB,$FE,$FF; 256
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj11_MapUnc_FC28: BINCLUDE "mappings/sprite/obj11_a.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj11_MapUnc_FC70: BINCLUDE "mappings/sprite/obj11_b.bin"
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
if ~~removeJmpTos
; sub_FC88:
JmpTo_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo_PlatformObject11_cont
jmp (PlatformObject11_cont).l
; sub_FC94:
JmpTo_CalcSine
jmp (CalcSine).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 15 - Swinging platform from Aquatic Ruin Zone
; ----------------------------------------------------------------------------
; Sprite_FC9C:
Obj15:
btst #6,render_flags(a0)
bne.w +
moveq #0,d0
move.b routine(a0),d0
move.w Obj15_Index(pc,d0.w),d1
jmp Obj15_Index(pc,d1.w)
; ---------------------------------------------------------------------------
+
move.w #$200,d0
bra.w DisplaySprite3
; ===========================================================================
; off_FCBC: Obj15_States:
Obj15_Index: offsetTable
offsetTableEntry.w Obj15_Init ; 0
offsetTableEntry.w Obj15_State2 ; 2
offsetTableEntry.w Obj15_Display ; 4
offsetTableEntry.w Obj15_State4 ; 6
offsetTableEntry.w Obj15_State5 ; 8
offsetTableEntry.w Obj15_State6 ; $A
offsetTableEntry.w Obj15_State7 ; $C
; ===========================================================================
; loc_FCCA:
Obj15_Init:
addq.b #2,routine(a0)
move.l #Obj15_MapUnc_101E8,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_OOZSwingPlat,2,0),art_tile(a0)
move.b #4,render_flags(a0)
move.b #3,priority(a0)
move.b #$20,width_pixels(a0)
move.b #$10,y_radius(a0)
move.w y_pos(a0),objoff_38(a0)
move.w x_pos(a0),objoff_3A(a0)
cmpi.b #mystic_cave_zone,(Current_Zone).w
bne.s +
move.l #Obj15_Obj7A_MapUnc_10256,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0)
move.b #$18,width_pixels(a0)
move.b #8,y_radius(a0)
+
cmpi.b #aquatic_ruin_zone,(Current_Zone).w
bne.s +
move.l #Obj15_Obj83_MapUnc_1021E,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0)
move.b #$20,width_pixels(a0)
move.b #8,y_radius(a0)
+
bsr.w Adjust2PArtPointer
moveq #0,d1
move.b subtype(a0),d1
bpl.s +
addq.b #4,routine(a0)
+
move.b d1,d4
andi.b #$70,d4
andi.w #$F,d1
move.w x_pos(a0),d2
move.w y_pos(a0),d3
jsrto (SingleObjLoad2).l, JmpTo2_SingleObjLoad2
bne.w +++
_move.b id(a0),id(a1) ; load obj15
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
move.b #4,render_flags(a1)
cmpi.b #$20,d4
bne.s +
move.b #4,routine(a1)
move.b #4,priority(a1)
move.b #$10,width_pixels(a1)
move.b #$50,y_radius(a1)
bset #4,render_flags(a1)
move.b #3,mapping_frame(a1)
move.w d2,x_pos(a1)
addi.w #$40,d3
move.w d3,y_pos(a1)
addi.w #$48,d3
move.w d3,y_pos(a0)
bra.s ++
; ===========================================================================
+
bset #6,render_flags(a1)
move.b #$48,mainspr_width(a1)
move.b d1,mainspr_childsprites(a1)
subq.b #1,d1
lea sub2_x_pos(a1),a2
- move.w d2,(a2)+ ; sub?_x_pos
move.w d3,(a2)+ ; sub?_y_pos
move.w #1,(a2)+ ; sub2_mapframe
addi.w #$10,d3
dbf d1,-
move.b #2,sub2_mapframe(a1)
move.w sub6_x_pos(a1),x_pos(a1)
move.w sub6_y_pos(a1),y_pos(a1)
move.w d2,sub6_x_pos(a1)
move.w d3,sub6_y_pos(a1)
move.b #1,mainspr_mapframe(a1)
addi_.w #8,d3
move.w d3,y_pos(a0)
move.b #$50,mainspr_height(a1)
bset #4,render_flags(a1)
+
move.l a1,objoff_30(a0)
+
move.w #$8000,angle(a0)
move.w #0,objoff_3E(a0)
move.b subtype(a0),d1
andi.w #$70,d1
move.b d1,subtype(a0)
cmpi.b #$40,d1
bne.s Obj15_State2
move.l #Obj15_MapUnc_102DE,mappings(a0)
move.b #$A7,collision_flags(a0)
; loc_FE50:
Obj15_State2:
move.w x_pos(a0),-(sp)
bsr.w sub_FE70
moveq #0,d1
move.b width_pixels(a0),d1
moveq #0,d3
move.b y_radius(a0),d3
addq.b #1,d3
move.w (sp)+,d4
jsrto (PlatformObject2).l, JmpTo_PlatformObject2
bra.w loc_1000C
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_FE70:
moveq #0,d0
moveq #0,d1
move.b (Oscillating_Data+$18).w,d0
move.b subtype(a0),d1
beq.s loc_FEC2
cmpi.b #$10,d1
bne.s ++
cmpi.b #$3F,d0
beq.s +
bhs.s loc_FEC2
moveq #$40,d0
bra.s loc_FEC2
; ===========================================================================
/
move.w #SndID_PlatformKnock,d0
jsr (PlaySoundLocal).l
moveq #$40,d0
bra.s loc_FEC2
; ===========================================================================
+
cmpi.b #$20,d1
beq.w +++ ; rts
cmpi.b #$30,d1
bne.s +
cmpi.b #$41,d0
beq.s -
blo.s loc_FEC2
moveq #$40,d0
bra.s loc_FEC2
; ===========================================================================
+
cmpi.b #$40,d1
bne.s loc_FEC2
bsr.w loc_FF6E
loc_FEC2:
move.b objoff_2E(a0),d1
cmp.b d0,d1
beq.w ++ ; rts
move.b d0,objoff_2E(a0)
move.w #$80,d1
btst #0,status(a0)
beq.s +
neg.w d0
add.w d1,d0
+
jsrto (CalcSine).l, JmpTo2_CalcSine
move.w objoff_38(a0),d2
move.w objoff_3A(a0),d3
moveq #0,d6
movea.l objoff_30(a0),a1
move.b mainspr_childsprites(a1),d6
subq.w #1,d6
bcs.s + ; rts
swap d0
swap d1
asr.l #4,d0
asr.l #4,d1
moveq #0,d4
moveq #0,d5
lea sub2_x_pos(a1),a2
- movem.l d4-d5,-(sp)
swap d4
swap d5
add.w d2,d4
add.w d3,d5
move.w d5,(a2)+ ; sub?_x_pos
move.w d4,(a2)+ ; sub?_y_pos
movem.l (sp)+,d4-d5
add.l d0,d4
add.l d1,d5
addq.w #next_subspr-4,a2
dbf d6,-
movem.l d4-d5,-(sp)
swap d4
swap d5
add.w d2,d4
add.w d3,d5
move.w sub6_x_pos(a1),d2
move.w sub6_y_pos(a1),d3
move.w d5,sub6_x_pos(a1)
move.w d4,sub6_y_pos(a1)
move.w d2,x_pos(a1)
move.w d3,y_pos(a1)
movem.l (sp)+,d4-d5
asr.l #1,d0
asr.l #1,d1
add.l d0,d4
add.l d1,d5
swap d4
swap d5
add.w objoff_38(a0),d4
add.w objoff_3A(a0),d5
move.w d4,y_pos(a0)
move.w d5,x_pos(a0)
+
rts
; End of function sub_FE70
; ===========================================================================
loc_FF6E:
tst.w objoff_36(a0)
beq.s +
subq.w #1,objoff_36(a0)
bra.w loc_10006
; ===========================================================================
+
tst.b objoff_34(a0)
bne.s +
move.w (MainCharacter+x_pos).w,d0
sub.w objoff_3A(a0),d0
addi.w #$20,d0
cmpi.w #$40,d0
bhs.s loc_10006
tst.w (Debug_placement_mode).w
bne.w loc_10006
move.b #1,objoff_34(a0)
+
tst.b objoff_3D(a0)
beq.s +
move.w objoff_3E(a0),d0
addi_.w #8,d0
move.w d0,objoff_3E(a0)
add.w d0,angle(a0)
cmpi.w #$200,d0
bne.s loc_10006
move.w #0,objoff_3E(a0)
move.w #$8000,angle(a0)
move.b #0,objoff_3D(a0)
move.w #$3C,objoff_36(a0)
bra.s loc_10006
; ===========================================================================
+
move.w objoff_3E(a0),d0
subi_.w #8,d0
move.w d0,objoff_3E(a0)
add.w d0,angle(a0)
cmpi.w #$FE00,d0
bne.s loc_10006
move.w #0,objoff_3E(a0)
move.w #$4000,angle(a0)
move.b #1,objoff_3D(a0)
; loc_10000:
move.w #$3C,objoff_36(a0)
loc_10006:
move.b angle(a0),d0
rts
; ===========================================================================
loc_1000C:
tst.w (Two_player_mode).w
beq.s +
bra.w DisplaySprite
; ===========================================================================
+
move.w objoff_3A(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w +
bra.w DisplaySprite
; ===========================================================================
+
movea.l objoff_30(a0),a1
bsr.w DeleteObject2
bra.w DeleteObject
; ===========================================================================
Obj15_Display: ;;
bra.w DisplaySprite
; ===========================================================================
; loc_1003E:
Obj15_State4:
move.w x_pos(a0),-(sp)
bsr.w sub_FE70
moveq #0,d1
move.b width_pixels(a0),d1
moveq #0,d3
move.b y_radius(a0),d3
addq.b #1,d3
move.w (sp)+,d4
jsrto (PlatformObject2).l, JmpTo_PlatformObject2
move.b status(a0),d0
andi.b #standing_mask,d0
beq.w BranchTo_loc_1000C
tst.b (Oscillating_Data+$18).w
bne.w BranchTo_loc_1000C
jsrto (SingleObjLoad2).l, JmpTo2_SingleObjLoad2
bne.s loc_100E4
moveq #0,d0
move.w #bytesToLcnt(object_size),d1
- move.l (a0,d0.w),(a1,d0.w)
addq.w #4,d0
dbf d1,-
if object_size&3
move.w (a0,d0.w),(a1,d0.w)
endif
move.b #$A,routine(a1)
cmpi.b #aquatic_ruin_zone,(Current_Zone).w
bne.s +
addq.b #2,routine(a1)
+
move.w #$200,x_vel(a1)
btst #0,status(a0)
beq.s +
neg.w x_vel(a1)
+
bset #1,status(a1)
move.w a0,d0
subi.w #Object_RAM,d0
if object_size=$40
lsr.w #6,d0
else
divu.w #object_size,d0
endif
andi.w #$7F,d0
move.w a1,d1
subi.w #Object_RAM,d1
if object_size=$40
lsr.w #6,d1
else
divu.w #object_size,d1
endif
andi.w #$7F,d1
lea (MainCharacter).w,a1 ; a1=character
cmp.b interact(a1),d0
bne.s +
move.b d1,interact(a1)
+
lea (Sidekick).w,a1 ; a1=character
cmp.b interact(a1),d0
bne.s loc_100E4
move.b d1,interact(a1)
loc_100E4:
move.b #3,mapping_frame(a0)
addq.b #2,routine(a0)
andi.b #$E7,status(a0)
BranchTo_loc_1000C
bra.w loc_1000C
; ===========================================================================
; loc_100F8:
Obj15_State5:
bsr.w sub_FE70
bra.w loc_1000C
; ===========================================================================
; loc_10100:
Obj15_State6:
move.w x_pos(a0),-(sp)
btst #1,status(a0)
beq.s +
bsr.w ObjectMove
addi.w #$18,y_vel(a0)
cmpi.w #$720,y_pos(a0)
blo.s ++
move.w #$720,y_pos(a0)
bclr #1,status(a0)
move.w #0,x_vel(a0)
move.w #0,y_vel(a0)
move.w y_pos(a0),objoff_38(a0)
bra.s ++
; ===========================================================================
+
moveq #0,d0
move.b (Oscillating_Data+$14).w,d0
lsr.w #1,d0
add.w objoff_38(a0),d0
move.w d0,y_pos(a0)
+
moveq #0,d1
move.b width_pixels(a0),d1
moveq #0,d3
move.b y_radius(a0),d3
addq.b #1,d3
move.w (sp)+,d4
jsrto (PlatformObject2).l, JmpTo_PlatformObject2
bra.w MarkObjGone
; ===========================================================================
; loc_10166:
Obj15_State7:
move.w x_pos(a0),-(sp)
bsr.w ObjectMove
btst #1,status(a0)
beq.s +
addi.w #$18,y_vel(a0)
move.w (Water_Level_2).w,d0
cmp.w y_pos(a0),d0
bhi.s ++
move.w d0,y_pos(a0)
move.w d0,objoff_38(a0)
bclr #1,status(a0)
move.w #$100,x_vel(a0)
move.w #0,y_vel(a0)
bra.s ++
; ===========================================================================
+
moveq #0,d0
move.b (Oscillating_Data+$14).w,d0
lsr.w #1,d0
add.w objoff_38(a0),d0
move.w d0,y_pos(a0)
tst.w x_vel(a0)
beq.s +
moveq #0,d3
move.b width_pixels(a0),d3
jsrto (ObjCheckRightWallDist).l, JmpTo_ObjCheckRightWallDist
tst.w d1
bpl.s +
add.w d1,x_pos(a0)
move.w #0,x_vel(a0)
+
moveq #0,d1
move.b width_pixels(a0),d1
moveq #0,d3
move.b y_radius(a0),d3
addq.b #1,d3
move.w (sp)+,d4
jsrto (PlatformObject2).l, JmpTo_PlatformObject2
bra.w MarkObjGone
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj15_MapUnc_101E8: BINCLUDE "mappings/sprite/obj15_a.bin"
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj15_Obj83_MapUnc_1021E: BINCLUDE "mappings/sprite/obj83.bin"
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj15_Obj7A_MapUnc_10256: offsetTable
offsetTableEntry.w word_1025E
offsetTableEntry.w word_10270
offsetTableEntry.w word_1027A
offsetTableEntry.w word_1028C
word_1025E: dc.w 2
dc.w $F809, $6060, $6030, $FFE8
dc.w $F809, $6860, $6830, 0
word_10270: dc.w 1
dc.w $F805, $6066, $6033, $FFF8
word_1027A: dc.w 2
dc.w $E805, $406A, $4035, $FFF4
dc.w $F80B, $406E, $4037, $FFF4
word_1028C: dc.w $A
dc.w $A805, $406A, $4035, $FFF4
dc.w $B80B, $406E, $4037, $FFF4
dc.w $C805, $6066, $6033, $FFF8
dc.w $D805, $6066, $6033, $FFF8
dc.w $E805, $6066, $6033, $FFF8
dc.w $F805, $6066, $6033, $FFF8
dc.w $805, $6066, $6033, $FFF8
dc.w $1805, $6066, $6033, $FFF8
dc.w $2805, $6066, $6033, $FFF8
dc.w $3805, $6066, $6033, $FFF8
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj15_MapUnc_102DE: offsetTable
offsetTableEntry.w word_102E4
offsetTableEntry.w word_10270
offsetTableEntry.w word_1027A
word_102E4: dc.w 2
dc.w $F80D, $6058, $602C, $FFE0
dc.w $F80D, $6858, $682C, 0
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo_PlatformObject2
jmp (PlatformObject2).l
JmpTo2_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo2_CalcSine
jmp (CalcSine).l
JmpTo_ObjCheckRightWallDist
jmp (ObjCheckRightWallDist).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 17 - GHZ rotating log helix spikes (from Sonic 1, unused)
; the programming of this was modified somewhat between Sonic 1 and Sonic 2
; ----------------------------------------------------------------------------
; Sprite_10310:
Obj17:
moveq #0,d0
move.b routine(a0),d0
move.w Obj17_Index(pc,d0.w),d1
jmp Obj17_Index(pc,d1.w)
; ===========================================================================
; off_1031E:
Obj17_Index: offsetTable
offsetTableEntry.w Obj17_Init ; 0
offsetTableEntry.w Obj17_Main ; 2
offsetTableEntry.w Obj17_Display ; 4
; ===========================================================================
; loc_10324: Obj17_Main:
Obj17_Init:
addq.b #2,routine(a0)
move.l #Obj17_MapUnc_10452,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_GHZ_Spiked_Log,2,0),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #3,priority(a0)
move.b #8,width_pixels(a0)
move.w y_pos(a0),d2
move.w x_pos(a0),d3
_move.b id(a0),d4
lea subtype(a0),a2 ; move helix length to a2
moveq #0,d1
move.b (a2),d1 ; move a2 to d1
move.b #0,(a2)+
move.w d1,d0
lsr.w #1,d0
lsl.w #4,d0
sub.w d0,d3
subq.b #2,d1
bcs.s Obj17_Main
moveq #0,d6
; loc_10372:
Obj17_MakeHelix:
bsr.w SingleObjLoad2
bne.s Obj17_Main
addq.b #1,subtype(a0)
move.w a1,d5
subi.w #Object_RAM,d5
if object_size=$40
lsr.w #6,d5
else
divu.w #object_size,d5
endif
andi.w #$7F,d5
move.b d5,(a2)+
move.b #4,routine(a1)
_move.b d4,id(a1) ; load obj17
move.w d2,y_pos(a1)
move.w d3,x_pos(a1)
move.l mappings(a0),mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_GHZ_Spiked_Log,2,0),art_tile(a1)
bsr.w Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #3,priority(a1)
move.b #8,width_pixels(a1)
move.b d6,objoff_3E(a1)
addq.b #1,d6
andi.b #7,d6
addi.w #$10,d3
cmp.w x_pos(a0),d3
bne.s +
move.b d6,objoff_3E(a0)
addq.b #1,d6
andi.b #7,d6
addi.w #$10,d3
addq.b #1,subtype(a0)
+ dbf d1,Obj17_MakeHelix ; repeat d1 times (helix length)
; loc_103E8: Obj17_Action:
Obj17_Main:
bsr.w Obj17_RotateSpike
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w Obj17_DelAll
bra.w DisplaySprite
; ===========================================================================
; loc_10404:
Obj17_DelAll:
moveq #0,d2
lea subtype(a0),a2 ; move helix length to a2
move.b (a2)+,d2 ; move a2 to d2
subq.b #2,d2
bcs.s BranchTo2_DeleteObject
; loc_10410:
Obj17_DelLoop:
moveq #0,d0
move.b (a2)+,d0
if object_size=$40
lsl.w #6,d0
else
mulu.w #object_size,d0
endif
addi.l #Object_RAM,d0
movea.l d0,a1 ; a1=object
bsr.w DeleteObject2 ; delete object
dbf d2,Obj17_DelLoop ; repeat d2 times (helix length)
; loc_10426:
BranchTo2_DeleteObject
bra.w DeleteObject
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_1042A:
Obj17_RotateSpike:
move.b (Logspike_anim_frame).w,d0
move.b #0,collision_flags(a0) ; make object harmless
add.b objoff_3E(a0),d0
andi.b #7,d0
move.b d0,mapping_frame(a0) ; change current frame
bne.s + ; rts
move.b #%10000100,collision_flags(a0) ; make object harmful
+
rts
; End of function Obj17_RotateSpike
; ===========================================================================
; loc_1044A:
Obj17_Display:
bsr.w Obj17_RotateSpike
bra.w DisplaySprite
; ===========================================================================
; -----------------------------------------------------------------------------
; sprite mappings - helix of spikes on a pole (GHZ) (unused)
; -----------------------------------------------------------------------------
Obj17_MapUnc_10452: BINCLUDE "mappings/sprite/obj17.bin"
; ===========================================================================
if gameRevision<2
nop
endif
; ----------------------------------------------------------------------------
; Object 18 - Stationary floating platform from ARZ, EHZ and HTZ
; ----------------------------------------------------------------------------
; Sprite_104AC:
Obj18:
moveq #0,d0
move.b routine(a0),d0
move.w Obj18_Index(pc,d0.w),d1
jmp Obj18_Index(pc,d1.w)
; ===========================================================================
; off_104BA:
Obj18_Index: offsetTable
offsetTableEntry.w Obj18_Init ; 0
offsetTableEntry.w loc_1056A ; 2
offsetTableEntry.w BranchTo3_DeleteObject ; 4
offsetTableEntry.w loc_105A8 ; 6
offsetTableEntry.w loc_105D4 ; 8
; ===========================================================================
;word_104C4:
Obj18_InitData:
; width_pixels
; frame
dc.b $20, 0
dc.b $20, 1
dc.b $20, 2
dc.b $40, 3
dc.b $30, 4
; ===========================================================================
; loc_104CE:
Obj18_Init:
addq.b #2,routine(a0)
moveq #0,d0
move.b subtype(a0),d0
lsr.w #3,d0
andi.w #$E,d0
lea Obj18_InitData(pc,d0.w),a2
move.b (a2)+,width_pixels(a0)
move.b (a2)+,mapping_frame(a0)
move.l #Obj18_MapUnc_107F6,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,2,0),art_tile(a0)
cmpi.b #aquatic_ruin_zone,(Current_Zone).w
bne.s +
move.l #Obj18_MapUnc_1084E,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,2,0),art_tile(a0)
+
bsr.w Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #4,priority(a0)
move.w y_pos(a0),objoff_2C(a0)
move.w y_pos(a0),objoff_34(a0)
move.w x_pos(a0),objoff_32(a0)
move.w #$80,angle(a0)
tst.b subtype(a0)
bpl.s ++
addq.b #6,routine(a0)
andi.b #$F,subtype(a0)
move.b #$30,y_radius(a0)
cmpi.b #aquatic_ruin_zone,(Current_Zone).w
bne.s +
move.b #$28,y_radius(a0)
+
bset #4,render_flags(a0)
bra.w loc_105D4
; ===========================================================================
+
andi.b #$F,subtype(a0)
loc_1056A:
move.b status(a0),d0
andi.b #standing_mask,d0
bne.s +
tst.b objoff_38(a0)
beq.s ++
subq.b #4,objoff_38(a0)
bra.s ++
; ===========================================================================
+
cmpi.b #$40,objoff_38(a0)
beq.s +
addq.b #4,objoff_38(a0)
+
move.w x_pos(a0),-(sp)
bsr.w sub_10638
bsr.w sub_1061E
moveq #0,d1
move.b width_pixels(a0),d1
moveq #8,d3
move.w (sp)+,d4
jsrto (PlatformObject).l, JmpTo_PlatformObject
bra.s loc_105B0
; ===========================================================================
loc_105A8:
bsr.w sub_10638
bsr.w sub_1061E
loc_105B0:
tst.w (Two_player_mode).w
beq.s +
bra.w DisplaySprite
; ===========================================================================
+
move.w objoff_32(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.s BranchTo3_DeleteObject
bra.w DisplaySprite
; ===========================================================================
BranchTo3_DeleteObject
bra.w DeleteObject
; ===========================================================================
loc_105D4:
move.b status(a0),d0
andi.b #standing_mask,d0
bne.s +
tst.b objoff_38(a0)
beq.s ++
subq.b #4,objoff_38(a0)
bra.s ++
; ===========================================================================
+
cmpi.b #$40,objoff_38(a0)
beq.s +
addq.b #4,objoff_38(a0)
+
move.w x_pos(a0),-(sp)
bsr.w sub_10638
bsr.w sub_1061E
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
move.w (sp)+,d4
jsrto (SolidObject).l, JmpTo_SolidObject
bra.s loc_105B0
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_1061E:
move.b objoff_38(a0),d0
jsrto (CalcSine).l, JmpTo3_CalcSine
move.w #$400,d1
muls.w d1,d0
swap d0
add.w objoff_2C(a0),d0
move.w d0,y_pos(a0)
rts
; End of function sub_1061E
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_10638:
moveq #0,d0
move.b subtype(a0),d0
andi.w #$F,d0
add.w d0,d0
move.w Obj18_Behaviours(pc,d0.w),d1
jmp Obj18_Behaviours(pc,d1.w)
; End of function sub_10638
; ===========================================================================
; off_1064C:
Obj18_Behaviours: offsetTable
offsetTableEntry.w return_10668 ; 0
offsetTableEntry.w loc_1067A ; 1
offsetTableEntry.w loc_106C0 ; 2
offsetTableEntry.w loc_106D8 ; 3
offsetTableEntry.w loc_10702 ; 4
offsetTableEntry.w loc_1066A ; 5
offsetTableEntry.w loc_106B0 ; 6
offsetTableEntry.w loc_10778 ; 7
offsetTableEntry.w loc_107A4 ; 8
offsetTableEntry.w return_10668 ; 9
offsetTableEntry.w loc_107BC ; $A
offsetTableEntry.w loc_107D6 ; $B
offsetTableEntry.w loc_106A2 ; $C
offsetTableEntry.w loc_10692 ; $D
; ===========================================================================
return_10668:
rts
; ===========================================================================
loc_1066A:
move.w objoff_32(a0),d0
move.b angle(a0),d1
neg.b d1
addi.b #$40,d1
bra.s loc_10686
; ===========================================================================
loc_1067A:
move.w objoff_32(a0),d0
move.b angle(a0),d1
subi.b #$40,d1
loc_10686:
ext.w d1
add.w d1,d0
move.w d0,x_pos(a0)
bra.w loc_107EE
; ===========================================================================
loc_10692:
move.w objoff_34(a0),d0
move.b (Oscillating_Data+$C).w,d1
neg.b d1
addi.b #$30,d1
bra.s loc_106CC
; ===========================================================================
loc_106A2:
move.w objoff_34(a0),d0
move.b (Oscillating_Data+$C).w,d1
subi.b #$30,d1
bra.s loc_106CC
; ===========================================================================
loc_106B0:
move.w objoff_34(a0),d0
move.b angle(a0),d1
neg.b d1
addi.b #$40,d1
bra.s loc_106CC
; ===========================================================================
loc_106C0:
move.w objoff_34(a0),d0
move.b angle(a0),d1
subi.b #$40,d1
loc_106CC:
ext.w d1
add.w d1,d0
move.w d0,objoff_2C(a0)
bra.w loc_107EE
; ===========================================================================
loc_106D8:
tst.w objoff_3A(a0)
bne.s loc_106F0
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s + ; rts
move.w #$1E,objoff_3A(a0)
/
rts
; ===========================================================================
loc_106F0:
subq.w #1,objoff_3A(a0)
bne.s - ; rts
move.w #$20,objoff_3A(a0)
addq.b #1,subtype(a0)
rts
; ===========================================================================
loc_10702:
tst.w objoff_3A(a0)
beq.s loc_10730
subq.w #1,objoff_3A(a0)
bne.s loc_10730
bclr #p1_standing_bit,status(a0)
beq.s +
lea (MainCharacter).w,a1 ; a1=character
bsr.s sub_1075E
+
bclr #p2_standing_bit,status(a0)
beq.s +
lea (Sidekick).w,a1 ; a1=character
bsr.s sub_1075E
+
move.b #6,routine(a0)
loc_10730:
move.l objoff_2C(a0),d3
move.w y_vel(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d3
move.l d3,objoff_2C(a0)
addi.w #$38,y_vel(a0)
move.w (Camera_Max_Y_pos_now).w,d0
addi.w #$120,d0
cmp.w objoff_2C(a0),d0
bhs.s + ; rts
move.b #4,routine(a0)
+
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_1075E:
bset #1,status(a1)
bclr #3,status(a1)
move.b #2,routine(a1)
move.w y_vel(a0),y_vel(a1)
rts
; End of function sub_1075E
; ===========================================================================
loc_10778:
tst.w objoff_3A(a0)
bne.s loc_10798
lea (ButtonVine_Trigger).w,a2
moveq #0,d0
move.b subtype(a0),d0
lsr.w #4,d0
tst.b (a2,d0.w)
beq.s + ; rts
move.w #$3C,objoff_3A(a0)
/
rts
; ===========================================================================
loc_10798:
subq.w #1,objoff_3A(a0)
bne.s - ; rts
addq.b #1,subtype(a0)
rts
; ===========================================================================
loc_107A4:
subq.w #2,objoff_2C(a0)
move.w objoff_34(a0),d0
subi.w #$200,d0
cmp.w objoff_2C(a0),d0
bne.s + ; rts
clr.b subtype(a0)
+
rts
; ===========================================================================
loc_107BC:
move.w objoff_34(a0),d0
move.b angle(a0),d1
subi.b #$40,d1
ext.w d1
asr.w #1,d1
add.w d1,d0
move.w d0,objoff_2C(a0)
bra.w loc_107EE
; ===========================================================================
loc_107D6:
move.w objoff_34(a0),d0
move.b angle(a0),d1
neg.b d1
addi.b #$40,d1
ext.w d1
asr.w #1,d1
add.w d1,d0
move.w d0,objoff_2C(a0)
loc_107EE:
move.b (Oscillating_Data+$18).w,angle(a0)
rts
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj18_MapUnc_107F6: BINCLUDE "mappings/sprite/obj18_a.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj18_MapUnc_1084E: BINCLUDE "mappings/sprite/obj18_b.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo3_CalcSine
jmp (CalcSine).l
JmpTo_PlatformObject
jmp (PlatformObject).l
JmpTo_SolidObject
jmp (SolidObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 1A - Collapsing platform from HPZ (and GHZ)
; also supports OOZ, but never made use of
;
; Unlike Object 1F, this supports sloped platforms and subtype-dependant
; mappings. Both are used by GHZ, the latter to allow different shading
; on right-facing ledges.
; ----------------------------------------------------------------------------
; Sprite_108BC:
Obj1A:
moveq #0,d0
move.b routine(a0),d0
move.w Obj1A_Index(pc,d0.w),d1
jmp Obj1A_Index(pc,d1.w)
; ===========================================================================
; off_108CA:
Obj1A_Index: offsetTable
offsetTableEntry.w Obj1A_Init ; 0
offsetTableEntry.w Obj1A_Main ; 2
offsetTableEntry.w Obj1A_Fragment ; 4
; ===========================================================================
collapsing_platform_delay_pointer = objoff_34
collapsing_platform_delay_counter = objoff_38
collapsing_platform_stood_on_flag = objoff_3A
collapsing_platform_slope_pointer = objoff_3C
; loc_108D0:
Obj1A_Init:
addq.b #2,routine(a0)
move.l #Obj1A_MapUnc_10C6C,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,2,0),art_tile(a0)
bsr.w Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #4,priority(a0)
move.b #7,collapsing_platform_delay_counter(a0)
move.b subtype(a0),mapping_frame(a0)
move.l #Obj1A_DelayData,collapsing_platform_delay_pointer(a0)
cmpi.b #hidden_palace_zone,(Current_Zone).w
bne.s +
move.l #Obj1A_MapUnc_1101C,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_HPZPlatform,2,0),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #$30,width_pixels(a0)
move.l #Obj1A_HPZ_SlopeData,collapsing_platform_slope_pointer(a0)
move.l #Obj1A_HPZ_DelayData,collapsing_platform_delay_pointer(a0)
bra.s Obj1A_Main
; ===========================================================================
+
cmpi.b #oil_ocean_zone,(Current_Zone).w
bne.s +
move.l #Obj1F_MapUnc_110C6,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_OOZPlatform,3,0),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #$40,width_pixels(a0)
move.l #Obj1A_OOZ_SlopeData,collapsing_platform_slope_pointer(a0)
bra.s Obj1A_Main
; ===========================================================================
+
move.l #Obj1A_GHZ_SlopeData,collapsing_platform_slope_pointer(a0)
move.b #$34,width_pixels(a0)
move.b #$38,y_radius(a0)
bset #4,render_flags(a0)
; loc_1097C:
Obj1A_Main:
tst.b collapsing_platform_stood_on_flag(a0)
beq.s +
tst.b collapsing_platform_delay_counter(a0)
beq.w Obj1A_CreateFragments ; time up; collapse
subq.b #1,collapsing_platform_delay_counter(a0)
+
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s sub_1099E
move.b #1,collapsing_platform_stood_on_flag(a0)
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_1099E:
moveq #0,d1
move.b width_pixels(a0),d1
movea.l collapsing_platform_slope_pointer(a0),a2 ; a2=object
move.w x_pos(a0),d4
jsrto (SlopedPlatform).l, JmpTo_SlopedPlatform
bra.w MarkObjGone
; End of function sub_1099E
; ===========================================================================
; loc_109B4:
Obj1A_Fragment:
tst.b collapsing_platform_delay_counter(a0)
beq.s Obj1A_FragmentFall ; time up; collapse
tst.b collapsing_platform_stood_on_flag(a0)
bne.s +
subq.b #1,collapsing_platform_delay_counter(a0)
bra.w DisplaySprite
; ===========================================================================
+
bsr.w sub_1099E
subq.b #1,collapsing_platform_delay_counter(a0)
bne.s +
lea (MainCharacter).w,a1 ; a1=character
bsr.s sub_109DC
lea (Sidekick).w,a1 ; a1=character
sub_109DC:
btst #3,status(a1)
beq.s +
bclr #3,status(a1)
bclr #5,status(a1)
move.b #AniIDSonAni_Run,next_anim(a1)
+
rts
; End of function sub_109DC
; ===========================================================================
; loc_109F8:
Obj1A_FragmentFall:
bsr.w ObjectMoveAndFall
tst.b render_flags(a0)
bpl.w DeleteObject
bra.w DisplaySprite
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 1F - Collapsing platform from ARZ, MCZ and OOZ (and MZ, SLZ and SBZ)
; ----------------------------------------------------------------------------
; Sprite_10A08:
Obj1F:
moveq #0,d0
move.b routine(a0),d0
move.w Obj1F_Index(pc,d0.w),d1
jmp Obj1F_Index(pc,d1.w)
; ===========================================================================
; off_10A16:
Obj1F_Index: offsetTable
offsetTableEntry.w Obj1F_Init ; 0
offsetTableEntry.w Obj1F_Main ; 2
offsetTableEntry.w Obj1F_Fragment ; 4
; ===========================================================================
; loc_10A1C:
Obj1F_Init:
addq.b #2,routine(a0)
move.l #Obj1F_MapUnc_10F0C,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_MZ_Platform,2,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #4,priority(a0)
move.b #7,collapsing_platform_delay_counter(a0)
move.b #$44,width_pixels(a0)
lea (Obj1F_DelayData_EvenSubtype).l,a4
btst #0,subtype(a0)
beq.s +
lea (Obj1F_DelayData_OddSubtype).l,a4
+
move.l a4,collapsing_platform_delay_pointer(a0)
cmpi.b #oil_ocean_zone,(Current_Zone).w
bne.s +
move.l #Obj1F_MapUnc_110C6,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_OOZPlatform,3,0),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #$40,width_pixels(a0)
move.l #Obj1F_OOZ_DelayData,collapsing_platform_delay_pointer(a0)
+
cmpi.b #mystic_cave_zone,(Current_Zone).w
bne.s +
move.l #Obj1F_MapUnc_11106,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_MCZCollapsePlat,3,0),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #$20,width_pixels(a0)
move.l #Obj1F_MCZ_DelayData,collapsing_platform_delay_pointer(a0)
+
cmpi.b #aquatic_ruin_zone,(Current_Zone).w
bne.s Obj1F_Main
move.l #Obj1F_MapUnc_1115E,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,2,0),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #$20,width_pixels(a0)
move.l #Obj1F_ARZ_DelayData,collapsing_platform_delay_pointer(a0)
; loc_10AD6:
Obj1F_Main:
tst.b collapsing_platform_stood_on_flag(a0)
beq.s +
tst.b collapsing_platform_delay_counter(a0)
beq.w Obj1F_CreateFragments ; time up; collapse
subq.b #1,collapsing_platform_delay_counter(a0)
+
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s sub_10AF8
move.b #1,collapsing_platform_stood_on_flag(a0)
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_10AF8:
moveq #0,d1
move.b width_pixels(a0),d1
move.w #$10,d3
move.w x_pos(a0),d4
jsrto (PlatformObject).l, JmpTo2_PlatformObject
bra.w MarkObjGone
; End of function sub_10AF8
; ===========================================================================
; loc_10B0E:
Obj1F_Fragment:
tst.b collapsing_platform_delay_counter(a0)
beq.s Obj1F_FragmentFall ; time up; collapse
tst.b collapsing_platform_stood_on_flag(a0)
bne.s +
subq.b #1,collapsing_platform_delay_counter(a0)
bra.w DisplaySprite
; ===========================================================================
+
bsr.w sub_10AF8
subq.b #1,collapsing_platform_delay_counter(a0)
bne.s + ; rts
lea (MainCharacter).w,a1 ; a1=character
bsr.s sub_10B36
lea (Sidekick).w,a1 ; a1=character
sub_10B36:
btst #3,status(a1)
beq.s + ; rts
bclr #3,status(a1)
bclr #5,status(a1)
move.b #AniIDSonAni_Run,next_anim(a1)
+
rts
; End of function sub_10B36
; ===========================================================================
; loc_10B52:
Obj1F_FragmentFall:
bsr.w ObjectMoveAndFall
tst.b render_flags(a0)
bpl.w DeleteObject
bra.w DisplaySprite
; ===========================================================================
; loc_10B62:
Obj1F_CreateFragments:
addq.b #1,mapping_frame(a0)
bra.s +
; ===========================================================================
; loc_10B68:
Obj1A_CreateFragments:
addq.b #2,mapping_frame(a0)
+
movea.l collapsing_platform_delay_pointer(a0),a4
moveq #0,d0
move.b mapping_frame(a0),d0
add.w d0,d0
movea.l mappings(a0),a3
adda.w (a3,d0.w),a3
move.w (a3)+,d1
subq.w #1,d1
bset #5,render_flags(a0)
_move.b id(a0),d4
move.b render_flags(a0),d5
movea.l a0,a1
bra.s +
; ===========================================================================
- bsr.w SingleObjLoad
bne.s +++
addq.w #8,a3
+
move.b #4,routine(a1)
_move.b d4,id(a1) ; load obj1F
move.l a3,mappings(a1)
move.b d5,render_flags(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w art_tile(a0),art_tile(a1)
move.b priority(a0),priority(a1)
move.b width_pixels(a0),width_pixels(a1)
move.b y_radius(a0),y_radius(a1)
move.b (a4)+,collapsing_platform_delay_counter(a1)
cmpa.l a0,a1
bhs.s +
bsr.w DisplaySprite2
+ dbf d1,-
+
bsr.w DisplaySprite
move.w #SndID_Smash,d0
jmp (PlaySound).l
; ===========================================================================
; Delay data for obj1A in all but HPZ:
;byte_10BF2:
Obj1A_DelayData:
dc.b $1C,$18,$14,$10,$1A,$16,$12, $E, $A, 6,$18,$14,$10, $C, 8, 4
dc.b $16,$12, $E, $A, 6, 2,$14,$10, $C; 16
rev02even
; Delay data for obj1A in HPZ:
;byte_10C0B:
Obj1A_HPZ_DelayData:
dc.b $18,$1C,$20,$1E,$1A,$16, 6, $E,$14,$12, $A, 2
rev02even
; Delay data for obj1F even subtypes in all levels without more specific data:
;byte_10C17:
Obj1F_DelayData_EvenSubtype:
dc.b $1E,$16, $E, 6,$1A,$12, $A, 2
rev02even
; Delay data for obj1F odd subtypes in all levels without more specific data:
;byte_10C1F:
Obj1F_DelayData_OddSubtype:
dc.b $16,$1E,$1A,$12, 6, $E, $A, 2
rev02even
; Delay data for obj1F in OOZ:
;byte_10C27:
Obj1F_OOZ_DelayData:
dc.b $1A,$12, $A, 2,$16, $E, 6
rev02even
; Delay data for obj1F in MCZ:
;byte_10C2E:
Obj1F_MCZ_DelayData:
dc.b $1A,$16,$12, $E, $A, 2
rev02even
; Delay data for obj1F in ARZ:
;byte_10C34:
Obj1F_ARZ_DelayData:
dc.b $16,$1A,$18,$12, 6, $E, $A, 2
rev02even
; S1 remnant: Height data for GHZ collapsing platform (unused):
;byte_10C3C:
Obj1A_GHZ_SlopeData:
dc.b $20,$20,$20,$20,$20,$20,$20,$20,$21,$21,$22,$22,$23,$23,$24,$24
dc.b $25,$25,$26,$26,$27,$27,$28,$28,$29,$29,$2A,$2A,$2B,$2B,$2C,$2C; 16
dc.b $2D,$2D,$2E,$2E,$2F,$2F,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30; 32
even
; -------------------------------------------------------------------------------
; unused sprite mappings (GHZ)
; -------------------------------------------------------------------------------
Obj1A_MapUnc_10C6C: BINCLUDE "mappings/sprite/obj1A_a.bin"
; ----------------------------------------------------------------------------
; unused sprite mappings (MZ, SLZ, SBZ)
; ----------------------------------------------------------------------------
Obj1F_MapUnc_10F0C: BINCLUDE "mappings/sprite/obj1F_a.bin"
; Slope data for platforms.
;byte_10FDC:
Obj1A_OOZ_SlopeData:
dc.b $10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10
;byte_10FEC:
Obj1A_HPZ_SlopeData
dc.b $10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10
dc.b $10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10
dc.b $10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10
; ----------------------------------------------------------------------------
; sprite mappings (HPZ)
; ----------------------------------------------------------------------------
Obj1A_MapUnc_1101C: BINCLUDE "mappings/sprite/obj1A_b.bin"
; ----------------------------------------------------------------------------
; sprite mappings (OOZ)
; ----------------------------------------------------------------------------
Obj1F_MapUnc_110C6: BINCLUDE "mappings/sprite/obj1F_b.bin"
; -------------------------------------------------------------------------------
; sprite mappings (MCZ)
; -------------------------------------------------------------------------------
Obj1F_MapUnc_11106: BINCLUDE "mappings/sprite/obj1F_c.bin"
; -------------------------------------------------------------------------------
; sprite mappings (ARZ)
; -------------------------------------------------------------------------------
Obj1F_MapUnc_1115E: BINCLUDE "mappings/sprite/obj1F_d.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo_SlopedPlatform
jmp (SlopedPlatform).l
JmpTo2_PlatformObject
jmp (PlatformObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 1C - Bridge stake in Emerald Hill Zone and Hill Top Zone, falling oil in Oil Ocean Zone
; ----------------------------------------------------------------------------
; Sprite_111D4:
Obj1C:
moveq #0,d0
move.b routine(a0),d0
move.w Obj1C_Index(pc,d0.w),d1
jmp Obj1C_Index(pc,d1.w)
; ===========================================================================
; off_111E2:
Obj1C_Index: offsetTable
offsetTableEntry.w Obj1C_Init ; 0
offsetTableEntry.w BranchTo_MarkObjGone ; 2
; ===========================================================================
objsubdecl macro frame, mapaddr,artaddr,width,priority
dc.l frame<<24|mapaddr
dc.w artaddr
dc.b width, priority
endm
; dword_111E6:
Obj1C_InitData:
objsubdecl 0, Obj1C_MapUnc_11552, make_art_tile(ArtTile_ArtNem_BoltEnd_Rope,2,0), 4, 6
objsubdecl 1, Obj1C_MapUnc_11552, make_art_tile(ArtTile_ArtNem_BoltEnd_Rope,2,0), 4, 6
objsubdecl 1, Obj11_MapUnc_FC70, make_art_tile(ArtTile_ArtNem_EHZ_Bridge,2,0), 4, 1
objsubdecl 2, Obj1C_MapUnc_11552, make_art_tile(ArtTile_ArtNem_BoltEnd_Rope,1,0), $10, 6
objsubdecl 3, Obj16_MapUnc_21F14, make_art_tile(ArtTile_ArtNem_HtzZipline,2,0), 8, 4
objsubdecl 4, Obj16_MapUnc_21F14, make_art_tile(ArtTile_ArtNem_HtzZipline,2,0), 8, 4
objsubdecl 1, Obj16_MapUnc_21F14, make_art_tile(ArtTile_ArtNem_HtzZipline,2,0), $20, 1
objsubdecl 0, Obj1C_MapUnc_113D6, make_art_tile(ArtTile_ArtKos_LevelArt,2,0), 8, 1
objsubdecl 1, Obj1C_MapUnc_113D6, make_art_tile(ArtTile_ArtKos_LevelArt,2,0), 8, 1
objsubdecl 0, Obj1C_MapUnc_113EE, make_art_tile(ArtTile_ArtUnc_Waterfall3,2,0), 4, 4
objsubdecl 0, Obj1C_MapUnc_11406, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 4, 4
objsubdecl 1, Obj1C_MapUnc_11406, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 4, 4
objsubdecl 2, Obj1C_MapUnc_11406, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 4, 4
objsubdecl 3, Obj1C_MapUnc_11406, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 4, 4
objsubdecl 4, Obj1C_MapUnc_11406, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 4, 4
objsubdecl 5, Obj1C_MapUnc_11406, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 4, 4
objsubdecl 0, Obj1C_MapUnc_114AE, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), $18, 4
objsubdecl 1, Obj1C_MapUnc_114AE, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), $18, 4
objsubdecl 2, Obj1C_MapUnc_114AE, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 8, 4
objsubdecl 3, Obj1C_MapUnc_114AE, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 8, 4
objsubdecl 4, Obj1C_MapUnc_114AE, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0), 8, 4
; byte_1128E:
Obj1C_Radii:
dc.b 0
dc.b 0 ; 1
dc.b 0 ; 2
dc.b 0 ; 3
dc.b 0 ; 4
dc.b 0 ; 5
dc.b 0 ; 6
dc.b 0 ; 7
dc.b 0 ; 8
dc.b 0 ; 9
dc.b 0 ; 10
dc.b 0 ; 11
dc.b 0 ; 12
dc.b $30 ; 13
dc.b $40 ; 14
dc.b $60 ; 15
dc.b 0 ; 16
dc.b 0 ; 17
dc.b $30 ; 18
dc.b $40 ; 19
dc.b $50 ; 20
dc.b 0 ; 21
; ===========================================================================
; loc_112A4:
Obj1C_Init:
addq.b #2,routine(a0)
moveq #0,d0
move.b subtype(a0),d0
move.w d0,d1
lsl.w #3,d0
lea Obj1C_InitData(pc),a1
lea (a1,d0.w),a1
move.b (a1),mapping_frame(a0)
move.l (a1)+,mappings(a0)
move.w (a1)+,art_tile(a0)
bsr.w Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b (a1)+,width_pixels(a0)
move.b (a1)+,priority(a0)
lea Obj1C_Radii(pc),a1
move.b (a1,d1.w),d1
beq.s BranchTo_MarkObjGone ; if the radius is zero, branch
move.b d1,y_radius(a0)
bset #4,render_flags(a0)
BranchTo_MarkObjGone
bra.w MarkObjGone
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 71 - Bridge stake and pulsing orb from Hidden Palace Zone
; ----------------------------------------------------------------------------
; Sprite_112F0:
Obj71:
moveq #0,d0
move.b routine(a0),d0
move.w Obj71_Index(pc,d0.w),d1
jmp Obj71_Index(pc,d1.w)
; ===========================================================================
; off_112FE:
Obj71_Index: offsetTable
offsetTableEntry.w Obj71_Init ; 0
offsetTableEntry.w Obj71_Main ; 2
; ---------------------------------------------------------------------------
; dword_11302:
Obj71_InitData:
objsubdecl 3, Obj11_MapUnc_FC28, make_art_tile(ArtTile_ArtNem_HPZ_Bridge,3,0), 4, 1 ; Hidden Palace bridge
objsubdecl 0, Obj71_MapUnc_11396, make_art_tile(ArtTile_ArtNem_HPZOrb,3,1), $10, 1 ; Hidden Palace pulsing orb
objsubdecl 0, Obj71_MapUnc_11576, make_art_tile(ArtTile_ArtNem_MtzLavaBubble,2,0), $10, 1 ; MTZ lava bubble
; ===========================================================================
; loc_1131A:
Obj71_Init:
addq.b #2,routine(a0)
move.b subtype(a0),d0
andi.w #$F,d0
lsl.w #3,d0
lea Obj71_InitData(pc),a1
lea (a1,d0.w),a1
move.b (a1),mapping_frame(a0)
move.l (a1)+,mappings(a0)
move.w (a1)+,art_tile(a0)
bsr.w Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b (a1)+,width_pixels(a0)
move.b (a1)+,priority(a0)
move.b subtype(a0),d0
andi.w #$F0,d0
lsr.b #4,d0
move.b d0,anim(a0)
; loc_1135C:
Obj71_Main:
lea (Ani_obj71).l,a1
bsr.w AnimateSprite
bra.w MarkObjGone
; ===========================================================================
; off_1136A:
Ani_obj71: offsetTable
offsetTableEntry.w byte_11372 ; 0
offsetTableEntry.w byte_1137A ; 1
offsetTableEntry.w byte_11389 ; 2
offsetTableEntry.w byte_11392 ; 3
byte_11372: dc.b 8, 3, 3, 4, 5, 5, 4,$FF
rev02even
byte_1137A: dc.b 5, 0, 0, 0, 1, 2, 3, 3, 2, 1, 2, 3, 3, 1,$FF
rev02even
byte_11389: dc.b $B, 0, 1, 2, 3, 4, 5,$FD, 3
rev02even
byte_11392: dc.b $7F, 6,$FD, 2
even
; --------------------------------------------------------------------------------
; sprite mappings
; --------------------------------------------------------------------------------
Obj71_MapUnc_11396: BINCLUDE "mappings/sprite/obj71_a.bin"
; ----------------------------------------------------------------------------------------
; Unknown sprite mappings
; ----------------------------------------------------------------------------------------
Obj1C_MapUnc_113D6: BINCLUDE "mappings/sprite/obj1C_a.bin"
; --------------------------------------------------------------------------------
; Unknown sprite mappings
; --------------------------------------------------------------------------------
Obj1C_MapUnc_113EE: BINCLUDE "mappings/sprite/obj1C_b.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj1C_MapUnc_11406: BINCLUDE "mappings/sprite/obj1C_c.bin"
; --------------------------------------------------------------------------------
; sprite mappings
; --------------------------------------------------------------------------------
Obj1C_MapUnc_114AE: BINCLUDE "mappings/sprite/obj1C_d.bin"
; --------------------------------------------------------------------------------
; sprite mappings
; --------------------------------------------------------------------------------
Obj1C_MapUnc_11552: BINCLUDE "mappings/sprite/obj1C_e.bin"
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj71_MapUnc_11576: BINCLUDE "mappings/sprite/obj71_b.bin"
; ===========================================================================
if gameRevision<2
nop
endif
; ----------------------------------------------------------------------------
; Object 2A - Stomper from MCZ
; ----------------------------------------------------------------------------
; Sprite_115C4:
Obj2A:
moveq #0,d0
move.b routine(a0),d0
move.w Obj2A_Index(pc,d0.w),d1
jmp Obj2A_Index(pc,d1.w)
; ===========================================================================
; off_115D2:
Obj2A_Index: offsetTable
offsetTableEntry.w Obj2A_Init ; 0
offsetTableEntry.w Obj2A_Main ; 2
; ===========================================================================
; loc_115D6:
Obj2A_Init:
addq.b #2,routine(a0)
move.l #Obj2A_MapUnc_11666,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,2,0),art_tile(a0)
bsr.w Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #4,priority(a0)
move.w y_pos(a0),objoff_32(a0)
move.b #$50,y_radius(a0)
bset #4,render_flags(a0)
; loc_11610:
Obj2A_Main:
tst.b routine_secondary(a0)
bne.s +
addq.w #1,objoff_30(a0)
cmpi.w #$60,objoff_30(a0)
bne.s ++
move.b #2,routine_secondary(a0)
bra.s ++
; ===========================================================================
+
subq.w #8,objoff_30(a0)
bhi.s +
move.w #0,objoff_30(a0)
move.b #0,routine_secondary(a0)
+
move.w objoff_32(a0),d0
sub.w objoff_30(a0),d0
move.w d0,y_pos(a0)
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
move.w #$40,d2
move.w d2,d3
addq.w #1,d3
move.w x_pos(a0),d4
jsrto (SolidObject).l, JmpTo2_SolidObject
bra.w MarkObjGone
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj2A_MapUnc_11666: BINCLUDE "mappings/sprite/obj2A.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 2D - One way barrier from CPZ and DEZ
; ----------------------------------------------------------------------------
; Sprite_1169A:
Obj2D:
moveq #0,d0
move.b routine(a0),d0
move.w Obj2D_Index(pc,d0.w),d1
jmp Obj2D_Index(pc,d1.w)
; ===========================================================================
; off_116A8:
Obj2D_Index: offsetTable
offsetTableEntry.w Obj2D_Init ; 0
offsetTableEntry.w Obj2D_Main ; 2
; ===========================================================================
; loc_116AC:
Obj2D_Init:
addq.b #2,routine(a0)
move.l #Obj2D_MapUnc_11822,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_HtzValveBarrier,1,0),art_tile(a0)
move.b #8,width_pixels(a0)
cmpi.b #metropolis_zone,(Current_Zone).w
beq.s +
cmpi.b #metropolis_zone_2,(Current_Zone).w
bne.s ++
+
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,3,0),art_tile(a0)
move.b #$C,width_pixels(a0)
+
cmpi.b #chemical_plant_zone,(Current_Zone).w
bne.s +
move.w #make_art_tile(ArtTile_ArtNem_ConstructionStripes_2,1,0),art_tile(a0)
move.b #8,width_pixels(a0)
+
cmpi.b #death_egg_zone,(Current_Zone).w
bne.s +
move.w #make_art_tile(ArtTile_ArtNem_ConstructionStripes_1,1,0),art_tile(a0)
move.b #8,width_pixels(a0)
+
cmpi.b #aquatic_ruin_zone,(Current_Zone).w
bne.s +
move.w #make_art_tile(ArtTile_ArtNem_ARZBarrierThing,1,0),art_tile(a0)
move.b #8,width_pixels(a0)
+
bsr.w Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #4,priority(a0)
move.w y_pos(a0),objoff_32(a0)
move.b subtype(a0),mapping_frame(a0)
move.w x_pos(a0),d2
move.w d2,d3
subi.w #$200,d2
addi.w #$18,d3
btst #0,status(a0)
beq.s +
subi.w #-$1E8,d2
addi.w #$1E8,d3
+
move.w d2,objoff_38(a0)
move.w d3,objoff_3A(a0)
; loc_1175E:
Obj2D_Main:
btst #0,status(a0)
bne.s +
move.w objoff_38(a0),d2
move.w x_pos(a0),d3
tst.b routine_secondary(a0) ; check if barrier is moving up
beq.s ++
move.w objoff_3A(a0),d3
bra.s ++
; ===========================================================================
+
move.w x_pos(a0),d2
move.w objoff_3A(a0),d3
tst.b routine_secondary(a0) ; check if barrier is moving up
beq.s +
move.w objoff_38(a0),d2
+
move.w objoff_32(a0),d4
move.w d4,d5
subi.w #$20,d4
addi.w #$20,d5
move.b #0,routine_secondary(a0) ; set barrier to move down, check if characters are in area
lea (MainCharacter).w,a1 ; a1=character
bsr.s Obj2D_CheckCharacter
lea (Sidekick).w,a1 ; a1=character
bsr.s Obj2D_CheckCharacter
tst.b routine_secondary(a0) ; check if barrier is moving up
beq.s +
cmpi.w #$40,objoff_30(a0) ; check if barrier is high enough
beq.s +++
addq.w #8,objoff_30(a0) ; move barrier up
bra.s ++
; ===========================================================================
+
tst.w objoff_30(a0) ; check if barrier is not in original position
beq.s ++
subq.w #8,objoff_30(a0) ; move barrier down
+
move.w objoff_32(a0),d0 ; set the barrier y position
sub.w objoff_30(a0),d0
move.w d0,y_pos(a0)
+
moveq #0,d1 ; perform solid object collision
move.b width_pixels(a0),d1
addi.w #$B,d1
move.w #$20,d2
move.w d2,d3
addq.w #1,d3
move.w x_pos(a0),d4
jsrto (SolidObject).l, JmpTo2_SolidObject
bra.w MarkObjGone ; delete object if off screen
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_117F4
Obj2D_CheckCharacter:
; rect ltrb (d2, d4, d3, d5)
move.w x_pos(a1),d0
cmp.w d2,d0
blt.w return_11820
cmp.w d3,d0
bhs.w return_11820
move.w y_pos(a1),d0
cmp.w d4,d0
blo.w return_11820
cmp.w d5,d0
bhs.w return_11820
tst.b obj_control(a1)
bmi.s return_11820
move.b #2,routine_secondary(a0) ; set barrier to move up
return_11820:
rts
; End of function Obj2D_CheckCharacter
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj2D_MapUnc_11822: BINCLUDE "mappings/sprite/obj2D.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo2_SolidObject
jmp (SolidObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 28 - Animal and the 100 points from a badnik
; ----------------------------------------------------------------------------
animal_ground_routine_base = objoff_30
animal_ground_x_vel = objoff_32
animal_ground_y_vel = objoff_34
; Sprite_1188C:
Obj28:
moveq #0,d0
move.b routine(a0),d0
move.w Obj28_Index(pc,d0.w),d1
jmp Obj28_Index(pc,d1.w)
; ===========================================================================
; off_1189A:
Obj28_Index: offsetTable
offsetTableEntry.w Obj28_Init ; 0
offsetTableEntry.w Obj28_Main ; 2
offsetTableEntry.w Obj28_Walk ; 4
offsetTableEntry.w Obj28_Fly ; 6
offsetTableEntry.w Obj28_Walk ; 8
offsetTableEntry.w Obj28_Walk ; $A
offsetTableEntry.w Obj28_Walk ; $C
offsetTableEntry.w Obj28_Fly ; $E
offsetTableEntry.w Obj28_Walk ; $10
offsetTableEntry.w Obj28_Fly ; $12
offsetTableEntry.w Obj28_Walk ; $14
offsetTableEntry.w Obj28_Walk ; $16
offsetTableEntry.w Obj28_Walk ; $18
offsetTableEntry.w Obj28_Walk ; $1A
offsetTableEntry.w Obj28_Prison ; $1C
; These are the S1 ending actions:
offsetTableEntry.w Obj28_FlickyWait ; $1E
offsetTableEntry.w Obj28_FlickyWait ; $20
offsetTableEntry.w Obj28_FlickyJump ; $22
offsetTableEntry.w Obj28_RabbitWait ; $24
offsetTableEntry.w Obj28_LandJump ; $26
offsetTableEntry.w Obj28_SingleBounce ; $28
offsetTableEntry.w Obj28_LandJump ; $2A
offsetTableEntry.w Obj28_SingleBounce ; $2C
offsetTableEntry.w Obj28_LandJump ; $2E
offsetTableEntry.w Obj28_FlyBounce ; $30
offsetTableEntry.w Obj28_DoubleBounce ; $32
; byte_118CE:
Obj28_ZoneAnimals: zoneOrderedTable 1,2
zoneAnimals macro first,second
zoneTableEntry.b (Obj28_Properties_first - Obj28_Properties) / 8
zoneTableEntry.b (Obj28_Properties_second - Obj28_Properties) / 8
endm
; This table declares what animals will appear in the zone.
; When an enemy is destroyed, a random animal is chosen from the 2 selected animals.
; Note: you must also load the corresponding art in the PLCs.
zoneAnimals.b Squirrel, Bird ; EHZ
zoneAnimals.b Squirrel, Bird ; Zone 1
zoneAnimals.b Squirrel, Bird ; WZ
zoneAnimals.b Squirrel, Bird ; Zone 3
zoneAnimals.b Beaver, Eagle ; MTZ
zoneAnimals.b Beaver, Eagle ; MTZ
zoneAnimals.b Beaver, Eagle ; WFZ
zoneAnimals.b Beaver, Eagle ; HTZ
zoneAnimals.b Mouse, Seal ; HPZ
zoneAnimals.b Mouse, Seal ; Zone 9
zoneAnimals.b Penguin, Seal ; OOZ
zoneAnimals.b Mouse, Chicken ; MCZ
zoneAnimals.b Bear, Bird ; CNZ
zoneAnimals.b Rabbit, Eagle ; CPZ
zoneAnimals.b Pig, Chicken ; DEZ
zoneAnimals.b Penguin, Bird ; ARZ
zoneAnimals.b Turtle, Chicken ; SCZ
zoneTableEnd
; word_118F0:
Obj28_Properties:
obj28decl macro xvel,yvel,mappings,{INTLABEL}
Obj28_Properties___LABEL__: label *
dc.w xvel
dc.w yvel
dc.l mappings
endm
; This table declares the speed and mappings of each animal.
Rabbit: obj28decl -$200,-$400,Obj28_MapUnc_11EAC
Chicken: obj28decl -$200,-$300,Obj28_MapUnc_11E1C
Penguin: obj28decl -$180,-$300,Obj28_MapUnc_11EAC
Seal: obj28decl -$140,-$180,Obj28_MapUnc_11E88
Pig: obj28decl -$1C0,-$300,Obj28_MapUnc_11E64
Bird: obj28decl -$300,-$400,Obj28_MapUnc_11E1C
Squirrel: obj28decl -$280,-$380,Obj28_MapUnc_11E40
Eagle: obj28decl -$280,-$300,Obj28_MapUnc_11E1C
Mouse: obj28decl -$200,-$380,Obj28_MapUnc_11E40
Beaver: obj28decl -$2C0,-$300,Obj28_MapUnc_11E40
Turtle: obj28decl -$140,-$200,Obj28_MapUnc_11E40
Bear: obj28decl -$200,-$300,Obj28_MapUnc_11E40
; The following tables tell the properties of animals based on their subtype.
; word_11950:
Obj28_Speeds:
dc.w -$440, -$400
dc.w -$440, -$400 ; 2
dc.w -$440, -$400 ; 4
dc.w -$300, -$400 ; 6
dc.w -$300, -$400 ; 8
dc.w -$180, -$300 ; 10
dc.w -$180, -$300 ; 12
dc.w -$140, -$180 ; 14
dc.w -$1C0, -$300 ; 16
dc.w -$200, -$300 ; 18
dc.w -$280, -$380 ; 20
; off_1197C:
Obj28_Mappings:
dc.l Obj28_MapUnc_11E1C
dc.l Obj28_MapUnc_11E1C ; 1
dc.l Obj28_MapUnc_11E1C ; 2
dc.l Obj28_MapUnc_11EAC ; 3
dc.l Obj28_MapUnc_11EAC ; 4
dc.l Obj28_MapUnc_11EAC ; 5
dc.l Obj28_MapUnc_11EAC ; 6
dc.l Obj28_MapUnc_11E88 ; 7
dc.l Obj28_MapUnc_11E64 ; 8
dc.l Obj28_MapUnc_11E1C ; 9
dc.l Obj28_MapUnc_11E40 ; 10
; word_119A8:
Obj28_ArtLocations:
dc.w ArtTile_ArtNem_S1EndFlicky ; 0 Flicky
dc.w ArtTile_ArtNem_S1EndFlicky ; 1 Flicky
dc.w ArtTile_ArtNem_S1EndFlicky ; 2 Flicky
dc.w ArtTile_ArtNem_S1EndRabbit ; 3 Rabbit
dc.w ArtTile_ArtNem_S1EndRabbit ; 4 Rabbit
dc.w ArtTile_ArtNem_S1EndPenguin ; 5 Penguin
dc.w ArtTile_ArtNem_S1EndPenguin ; 6 Penguin
dc.w ArtTile_ArtNem_S1EndSeal ; 7 Seal
dc.w ArtTile_ArtNem_S1EndPig ; 8 Pig
dc.w ArtTile_ArtNem_S1EndChicken ; 9 Chicken
dc.w ArtTile_ArtNem_S1EndSquirrel ; 10 Squirrel
; ===========================================================================
; loc_119BE:
Obj28_Init:
tst.b subtype(a0)
beq.w Obj28_InitRandom
moveq #0,d0
move.b subtype(a0),d0
add.w d0,d0
move.b d0,routine(a0)
subi.w #$14,d0
move.w Obj28_ArtLocations(pc,d0.w),art_tile(a0)
add.w d0,d0
move.l Obj28_Mappings(pc,d0.w),mappings(a0)
lea Obj28_Speeds(pc),a1
move.w (a1,d0.w),animal_ground_x_vel(a0)
move.w (a1,d0.w),x_vel(a0)
move.w 2(a1,d0.w),animal_ground_y_vel(a0)
move.w 2(a1,d0.w),y_vel(a0)
bsr.w Adjust2PArtPointer
move.b #$C,y_radius(a0)
move.b #4,render_flags(a0)
bset #0,render_flags(a0)
move.b #6,priority(a0)
move.b #8,width_pixels(a0)
move.b #7,anim_frame_duration(a0)
bra.w DisplaySprite
; ===========================================================================
; loc_11A2C:
Obj28_InitRandom:
addq.b #2,routine(a0)
jsrto (RandomNumber).l, JmpTo_RandomNumber
move.w #make_art_tile(ArtTile_ArtNem_Animal_1,0,0),art_tile(a0)
andi.w #1,d0
beq.s +
move.w #make_art_tile(ArtTile_ArtNem_Animal_2,0,0),art_tile(a0)
+
moveq #0,d1
move.b (Current_Zone).w,d1
add.w d1,d1
add.w d0,d1
lea Obj28_ZoneAnimals(pc),a1
move.b (a1,d1.w),d0
move.b d0,animal_ground_routine_base(a0)
lsl.w #3,d0
lea Obj28_Properties(pc),a1
adda.w d0,a1
move.w (a1)+,animal_ground_x_vel(a0)
move.w (a1)+,animal_ground_y_vel(a0)
move.l (a1)+,mappings(a0)
bsr.w Adjust2PArtPointer
move.b #$C,y_radius(a0)
move.b #4,render_flags(a0)
bset #0,render_flags(a0)
move.b #6,priority(a0)
move.b #8,width_pixels(a0)
move.b #7,anim_frame_duration(a0)
move.b #2,mapping_frame(a0)
move.w #-$400,y_vel(a0)
tst.b objoff_38(a0)
bne.s ++
bsr.w SingleObjLoad
bne.s +
_move.b #ObjID_Points,id(a1) ; load obj29
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w objoff_3E(a0),d0
lsr.w #1,d0
move.b d0,mapping_frame(a1)
+ bra.w DisplaySprite
; ===========================================================================
+
move.b #$1C,routine(a0)
clr.w x_vel(a0)
bra.w DisplaySprite
; ===========================================================================
;loc_11ADE
Obj28_Main:
tst.b render_flags(a0)
bpl.w DeleteObject
bsr.w ObjectMoveAndFall
tst.w y_vel(a0)
bmi.s +
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.s +
add.w d1,y_pos(a0)
move.w animal_ground_x_vel(a0),x_vel(a0)
move.w animal_ground_y_vel(a0),y_vel(a0)
move.b #1,mapping_frame(a0)
move.b animal_ground_routine_base(a0),d0
add.b d0,d0
addq.b #4,d0
move.b d0,routine(a0)
tst.b objoff_38(a0)
beq.s +
btst #4,(Vint_runcount+3).w
beq.s +
neg.w x_vel(a0)
bchg #0,render_flags(a0)
+ bra.w DisplaySprite
; ===========================================================================
;loc_11B38
Obj28_Walk:
bsr.w ObjectMoveAndFall
move.b #1,mapping_frame(a0)
tst.w y_vel(a0)
bmi.s +
move.b #0,mapping_frame(a0)
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.s +
add.w d1,y_pos(a0)
move.w animal_ground_y_vel(a0),y_vel(a0)
+
tst.b subtype(a0)
bne.s Obj28_ChkDel
tst.b render_flags(a0)
bpl.w DeleteObject
bra.w DisplaySprite
; ===========================================================================
;loc_11B74
Obj28_Fly:
bsr.w ObjectMove
addi.w #$18,y_vel(a0)
tst.w y_vel(a0)
bmi.s +
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.s +
add.w d1,y_pos(a0)
move.w animal_ground_y_vel(a0),y_vel(a0)
tst.b subtype(a0)
beq.s +
cmpi.b #$A,subtype(a0)
beq.s +
neg.w x_vel(a0)
bchg #0,render_flags(a0)
+
subq.b #1,anim_frame_duration(a0)
bpl.s +
move.b #1,anim_frame_duration(a0)
addq.b #1,mapping_frame(a0)
andi.b #1,mapping_frame(a0)
+
tst.b subtype(a0)
bne.s Obj28_ChkDel
tst.b render_flags(a0)
bpl.w DeleteObject
bra.w DisplaySprite
; ===========================================================================
;loc_11BD8
Obj28_ChkDel:
move.w x_pos(a0),d0
sub.w (MainCharacter+x_pos).w,d0
bcs.s +
subi.w #$180,d0
bpl.s +
tst.b render_flags(a0)
bpl.w DeleteObject
+
bra.w DisplaySprite
; ===========================================================================
;loc_11BF4
Obj28_Prison:
tst.b render_flags(a0)
bpl.w DeleteObject
subq.w #1,objoff_36(a0)
bne.w +
move.b #2,routine(a0)
move.b #1,priority(a0)
+
bra.w DisplaySprite
; ===========================================================================
;loc_11C14
Obj28_FlickyWait:
bsr.w ChkAnimalInRange
bcc.s +
move.w animal_ground_x_vel(a0),x_vel(a0)
move.w animal_ground_y_vel(a0),y_vel(a0)
move.b #$E,routine(a0)
bra.w Obj28_Fly
; ===========================================================================
+
bra.w Obj28_ChkDel
; ===========================================================================
;loc_11C34
Obj28_FlickyJump:
bsr.w ChkAnimalInRange
bpl.s +
clr.w x_vel(a0)
clr.w animal_ground_x_vel(a0)
bsr.w ObjectMove
addi.w #$18,y_vel(a0)
bsr.w AnimalJump
bsr.w AnimalFaceSonic
subq.b #1,anim_frame_duration(a0)
bpl.s +
move.b #1,anim_frame_duration(a0)
addq.b #1,mapping_frame(a0)
andi.b #1,mapping_frame(a0)
+
bra.w Obj28_ChkDel
; ===========================================================================
;loc_11C6E
Obj28_RabbitWait:
bsr.w ChkAnimalInRange
bpl.s ++
move.w animal_ground_x_vel(a0),x_vel(a0)
move.w animal_ground_y_vel(a0),y_vel(a0)
move.b #4,routine(a0)
bra.w Obj28_Walk
; ===========================================================================
;loc_11C8A
Obj28_DoubleBounce:
bsr.w ObjectMoveAndFall
move.b #1,mapping_frame(a0)
tst.w y_vel(a0)
bmi.s ++
move.b #0,mapping_frame(a0)
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.s ++
not.b objoff_29(a0)
bne.s +
neg.w x_vel(a0)
bchg #0,render_flags(a0)
+
add.w d1,y_pos(a0)
move.w animal_ground_y_vel(a0),y_vel(a0)
+
bra.w Obj28_ChkDel
; ===========================================================================
;loc_11CC8
Obj28_LandJump:
bsr.w ChkAnimalInRange
bpl.s +
clr.w x_vel(a0)
clr.w animal_ground_x_vel(a0)
bsr.w ObjectMoveAndFall
bsr.w AnimalJump
bsr.w AnimalFaceSonic
+
bra.w Obj28_ChkDel
; ===========================================================================
;loc_11CE6
Obj28_SingleBounce:
bsr.w ChkAnimalInRange
bpl.s +
bsr.w ObjectMoveAndFall
move.b #1,mapping_frame(a0)
tst.w y_vel(a0)
bmi.s +
move.b #0,mapping_frame(a0)
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.s +
neg.w x_vel(a0)
bchg #0,render_flags(a0)
add.w d1,y_pos(a0)
move.w animal_ground_y_vel(a0),y_vel(a0)
+
bra.w Obj28_ChkDel
; ===========================================================================
;loc_11D24
Obj28_FlyBounce:
bsr.w ChkAnimalInRange
bpl.s +++
bsr.w ObjectMove
addi.w #$18,y_vel(a0)
tst.w y_vel(a0)
bmi.s ++
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.s ++
not.b objoff_29(a0)
bne.s +
neg.w x_vel(a0)
bchg #0,render_flags(a0)
+
add.w d1,y_pos(a0)
move.w animal_ground_y_vel(a0),y_vel(a0)
+
subq.b #1,anim_frame_duration(a0)
bpl.s +
move.b #1,anim_frame_duration(a0)
addq.b #1,mapping_frame(a0)
andi.b #1,mapping_frame(a0)
+
bra.w Obj28_ChkDel
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_11D78
AnimalJump:
move.b #1,mapping_frame(a0)
tst.w y_vel(a0)
bmi.s + ; rts
move.b #0,mapping_frame(a0)
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.s + ; rts
add.w d1,y_pos(a0)
move.w animal_ground_y_vel(a0),y_vel(a0)
+
rts
; End of function AnimalJump
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_11DA0
AnimalFaceSonic:
bset #0,render_flags(a0)
move.w x_pos(a0),d0
sub.w (MainCharacter+x_pos).w,d0
bcc.s + ; rts
bclr #0,render_flags(a0)
+
rts
; End of function AnimalFaceSonic
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_11DB8
ChkAnimalInRange:
move.w (MainCharacter+x_pos).w,d0
sub.w x_pos(a0),d0
subi.w #$B8,d0
rts
; End of function ChkAnimalInRange
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 29 - "100 points" text
; ----------------------------------------------------------------------------
; Sprite_11DC6:
Obj29:
moveq #0,d0
move.b routine(a0),d0
move.w Obj29_Index(pc,d0.w),d1
jmp Obj29_Index(pc,d1.w)
; ===========================================================================
; off_11DD4:
Obj29_Index: offsetTable
offsetTableEntry.w Obj29_Init ; 0
offsetTableEntry.w Obj29_Main ; 2
; ===========================================================================
Obj29_Init:
addq.b #2,routine(a0)
move.l #Obj29_MapUnc_11ED0,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Numbers,0,1),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #1,priority(a0)
move.b #8,width_pixels(a0)
move.w #-$300,y_vel(a0) ; set initial speed (upwards)
Obj29_Main:
tst.w y_vel(a0) ; test speed
bpl.w DeleteObject ; if it's positive (>= 0), delete the object
bsr.w ObjectMove ; move the points
addi.w #$18,y_vel(a0) ; slow down
bra.w DisplaySprite
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj28_MapUnc_11E1C: BINCLUDE "mappings/sprite/obj28_a.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj28_MapUnc_11E40: BINCLUDE "mappings/sprite/obj28_b.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj28_MapUnc_11E64: BINCLUDE "mappings/sprite/obj28_c.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj28_MapUnc_11E88: BINCLUDE "mappings/sprite/obj28_d.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj28_MapUnc_11EAC: BINCLUDE "mappings/sprite/obj28_e.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj29_MapUnc_11ED0: BINCLUDE "mappings/sprite/obj29.bin"
if ~~removeJmpTos
JmpTo_RandomNumber
jmp (RandomNumber).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 25 - A ring (usually only placed through placement mode)
; ----------------------------------------------------------------------------
; Obj_Ring:
Obj25:
moveq #0,d0
move.b routine(a0),d0
move.w Obj25_Index(pc,d0.w),d1
jmp Obj25_Index(pc,d1.w)
; ===========================================================================
; Obj_25_subtbl:
Obj25_Index: offsetTable
offsetTableEntry.w Obj25_Init ; 0
offsetTableEntry.w Obj25_Animate ; 2
offsetTableEntry.w Obj25_Collect ; 4
offsetTableEntry.w Obj25_Sparkle ; 6
offsetTableEntry.w Obj25_Delete ; 8
; ===========================================================================
; Obj_25_sub_0:
Obj25_Init:
addq.b #2,routine(a0)
move.w x_pos(a0),objoff_32(a0)
move.l #Obj25_MapUnc_12382,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Ring,1,0),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #2,priority(a0)
move.b #$47,collision_flags(a0)
move.b #8,width_pixels(a0)
; Obj_25_sub_2:
Obj25_Animate:
move.b (Rings_anim_frame).w,mapping_frame(a0)
move.w objoff_32(a0),d0
bra.w MarkObjGone2
; ===========================================================================
; Obj_25_sub_4:
Obj25_Collect:
addq.b #2,routine(a0)
move.b #0,collision_flags(a0)
move.b #1,priority(a0)
bsr.s CollectRing
; Obj_25_sub_6:
Obj25_Sparkle:
lea (Ani_Ring).l,a1
bsr.w AnimateSprite
bra.w DisplaySprite
; ===========================================================================
; BranchTo4_DeleteObject
Obj25_Delete:
bra.w DeleteObject
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_11FC2:
CollectRing:
tst.b parent+1(a0) ; did Tails collect the ring?
bne.s CollectRing_Tails ; if yes, branch
CollectRing_Sonic:
cmpi.w #999,(Rings_Collected).w ; did Sonic collect 999 or more rings?
bhs.s CollectRing_1P ; if yes, branch
addq.w #1,(Rings_Collected).w ; add 1 to the number of collected rings
CollectRing_1P:
if gameRevision=0
cmpi.w #999,(Ring_count).w ; does the player 1 have 999 or more rings?
bhs.s + ; if yes, skip the increment
addq.w #1,(Ring_count).w ; add 1 to the ring count
+
ori.b #1,(Update_HUD_rings).w ; set flag to update the ring counter in the HUD
move.w #SndID_Ring,d0 ; prepare to play the ring sound
else
move.w #SndID_Ring,d0 ; prepare to play the ring sound
cmpi.w #999,(Ring_count).w ; does the player 1 have 999 or more rings?
bhs.s JmpTo_PlaySoundStereo ; if yes, play the ring sound
addq.w #1,(Ring_count).w ; add 1 to the ring count
ori.b #1,(Update_HUD_rings).w ; set flag to update the ring counter in the HUD
endif
cmpi.w #100,(Ring_count).w ; does the player 1 have less than 100 rings?
blo.s JmpTo_PlaySoundStereo ; if yes, play the ring sound
bset #1,(Extra_life_flags).w ; test and set the flag for the first extra life
beq.s + ; if it was clear before, branch
cmpi.w #200,(Ring_count).w ; does the player 1 have less than 200 rings?
blo.s JmpTo_PlaySoundStereo ; if yes, play the ring sound
bset #2,(Extra_life_flags).w ; test and set the flag for the second extra life
bne.s JmpTo_PlaySoundStereo ; if it was set before, play the ring sound
+
addq.b #1,(Life_count).w ; add 1 to the life count
addq.b #1,(Update_HUD_lives).w ; add 1 to the displayed life count
move.w #MusID_ExtraLife,d0 ; prepare to play the extra life jingle
JmpTo_PlaySoundStereo
jmp (PlaySoundStereo).l
; ===========================================================================
rts
; ===========================================================================
CollectRing_Tails:
cmpi.w #999,(Rings_Collected_2P).w ; did Tails collect 999 or more rings?
bhs.s + ; if yes, branch
addq.w #1,(Rings_Collected_2P).w ; add 1 to the number of collected rings
+
cmpi.w #999,(Ring_count_2P).w ; does Tails have 999 or more rings?
bhs.s + ; if yes, branch
addq.w #1,(Ring_count_2P).w ; add 1 to the ring count
+
tst.w (Two_player_mode).w ; are we in a 2P game?
beq.s CollectRing_1P ; if not, branch
; CollectRing_2P:
ori.b #1,(Update_HUD_rings_2P).w ; set flag to update the ring counter in the second player's HUD
move.w #SndID_Ring,d0 ; prepare to play the ring sound
cmpi.w #100,(Ring_count_2P).w ; does the player 2 have less than 100 rings?
blo.s JmpTo2_PlaySoundStereo ; if yes, play the ring sound
bset #1,(Extra_life_flags_2P).w ; test and set the flag for the first extra life
beq.s + ; if it was clear before, branch
cmpi.w #200,(Ring_count_2P).w ; does the player 2 have less than 200 rings?
blo.s JmpTo2_PlaySoundStereo ; if yes, play the ring sound
bset #2,(Extra_life_flags_2P).w ; test and set the flag for the second extra life
bne.s JmpTo2_PlaySoundStereo ; if it was set before, play the ring sound
+
addq.b #1,(Life_count_2P).w ; add 1 to the life count
addq.b #1,(Update_HUD_lives_2P).w ; add 1 to the displayed life count
move.w #MusID_ExtraLife,d0 ; prepare to play the extra life jingle
JmpTo2_PlaySoundStereo
jmp (PlaySoundStereo).l
; End of function CollectRing
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 37 - Scattering rings (generated when Sonic is hurt and has rings)
; ----------------------------------------------------------------------------
; Sprite_12078:
Obj37:
moveq #0,d0
move.b routine(a0),d0
move.w Obj37_Index(pc,d0.w),d1
jmp Obj37_Index(pc,d1.w)
; ===========================================================================
; Obj_37_subtbl:
Obj37_Index: offsetTable
offsetTableEntry.w Obj37_Init ; 0
offsetTableEntry.w Obj37_Main ; 2
offsetTableEntry.w Obj37_Collect ; 4
offsetTableEntry.w Obj37_Sparkle ; 6
offsetTableEntry.w Obj37_Delete ; 8
; ===========================================================================
; Obj_37_sub_0:
Obj37_Init:
movea.l a0,a1
moveq #0,d5
move.w (Ring_count).w,d5
tst.b parent+1(a0)
beq.s +
move.w (Ring_count_2P).w,d5
+
moveq #$20,d0
cmp.w d0,d5
blo.s +
move.w d0,d5
+
subq.w #1,d5
move.w #$288,d4
bra.s +
; ===========================================================================
- bsr.w SingleObjLoad
bne.w +++
+
_move.b #ObjID_LostRings,id(a1) ; load obj37
addq.b #2,routine(a1)
move.b #8,y_radius(a1)
move.b #8,x_radius(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.l #Obj25_MapUnc_12382,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_Ring,1,0),art_tile(a1)
bsr.w Adjust2PArtPointer2
move.b #$84,render_flags(a1)
move.b #3,priority(a1)
move.b #$47,collision_flags(a1)
move.b #8,width_pixels(a1)
move.b #-1,(Ring_spill_anim_counter).w
tst.w d4
bmi.s +
move.w d4,d0
jsrto (CalcSine).l, JmpTo4_CalcSine
move.w d4,d2
lsr.w #8,d2
asl.w d2,d0
asl.w d2,d1
move.w d0,d2
move.w d1,d3
addi.b #$10,d4
bcc.s +
subi.w #$80,d4
bcc.s +
move.w #$288,d4
+
move.w d2,x_vel(a1)
move.w d3,y_vel(a1)
neg.w d2
neg.w d4
dbf d5,-
+
move.w #SndID_RingSpill,d0
jsr (PlaySoundStereo).l
tst.b parent+1(a0)
bne.s +
move.w #0,(Ring_count).w
move.b #$80,(Update_HUD_rings).w
move.b #0,(Extra_life_flags).w
bra.s Obj37_Main
; ===========================================================================
+
move.w #0,(Ring_count_2P).w
move.b #$80,(Update_HUD_rings_2P).w
move.b #0,(Extra_life_flags_2P).w
; Obj_37_sub_2:
Obj37_Main:
move.b (Ring_spill_anim_frame).w,mapping_frame(a0)
bsr.w ObjectMove
addi.w #$18,y_vel(a0)
bmi.s loc_121B8
move.b (Vint_runcount+3).w,d0
add.b d7,d0
andi.b #7,d0
bne.s loc_121B8
tst.b render_flags(a0)
bpl.s loc_121D0
jsr (RingCheckFloorDist).l
tst.w d1
bpl.s loc_121B8
add.w d1,y_pos(a0)
move.w y_vel(a0),d0
asr.w #2,d0
sub.w d0,y_vel(a0)
neg.w y_vel(a0)
loc_121B8:
tst.b (Ring_spill_anim_counter).w
beq.s Obj37_Delete
move.w (Camera_Max_Y_pos_now).w,d0
addi.w #$E0,d0
cmp.w y_pos(a0),d0
blo.s Obj37_Delete
bra.w DisplaySprite
; ===========================================================================
loc_121D0:
tst.w (Two_player_mode).w
bne.w Obj37_Delete
bra.s loc_121B8
; ===========================================================================
; Obj_37_sub_4:
Obj37_Collect:
addq.b #2,routine(a0)
move.b #0,collision_flags(a0)
move.b #1,priority(a0)
bsr.w CollectRing
; Obj_37_sub_6:
Obj37_Sparkle:
lea (Ani_Ring).l,a1
bsr.w AnimateSprite
bra.w DisplaySprite
; ===========================================================================
; BranchTo5_DeleteObject
Obj37_Delete:
bra.w DeleteObject
; Unused - dead code/data S1 big ring:
; ===========================================================================
; BigRing:
; a0=object
moveq #0,d0
move.b routine(a0),d0
move.w BigRing_States(pc,d0.w),d1
jmp BigRing_States(pc,d1.w)
; ===========================================================================
BigRing_States: offsetTable
offsetTableEntry.w BigRing_Init ; 0
offsetTableEntry.w BigRing_Main ; 2
offsetTableEntry.w BigRing_Enter ; 4
offsetTableEntry.w BigRing_Delete ; 6
; ===========================================================================
; loc_12216:
BigRing_Init:
move.l #Obj37_MapUnc_123E6,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_BigRing,1,0),art_tile(a0)
bsr.w Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$40,width_pixels(a0)
tst.b render_flags(a0)
bpl.s BigRing_Main
cmpi.b #6,(Got_Emerald).w
beq.w BigRing_Delete
cmpi.w #50,(Ring_count).w
bhs.s +
rts
; ===========================================================================
+
addq.b #2,routine(a0)
move.b #2,priority(a0)
move.b #$52,collision_flags(a0)
move.w #$C40,(BigRingGraphics).w
; loc_12264:
BigRing_Main:
move.b (Rings_anim_frame).w,mapping_frame(a0)
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w DeleteObject
bra.w DisplaySprite
; ===========================================================================
; loc_12282:
BigRing_Enter:
subq.b #2,routine(a0)
move.b #0,collision_flags(a0)
bsr.w SingleObjLoad
bne.w +
; Note: the object ID is not set
; If you want to restore the big ring object, you'll also have to
; restore the ring flash object (right after this) and assign its ID to
; the created object here (a1).
;move.b #ObjID_BigRingFlash,id(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.l a0,objoff_3C(a1)
move.w (MainCharacter+x_pos).w,d0
cmp.w x_pos(a0),d0
blo.s +
bset #0,render_flags(a1)
+
move.w #SndID_EnterGiantRing,d0
jsr (PlaySoundStereo).l
bra.s BigRing_Main
; ===========================================================================
; BranchTo6_DeleteObject
BigRing_Delete:
bra.w DeleteObject
; Unused - dead code/data S1 ring flash:
; ===========================================================================
; BigRingFlash:
; a0=object
moveq #0,d0
move.b routine(a0),d0
move.w BigRingFlash_States(pc,d0.w),d1
jmp BigRingFlash_States(pc,d1.w)
; ===========================================================================
BigRingFlash_States: offsetTable
offsetTableEntry.w BigRingFlash_Init ; 0
offsetTableEntry.w BigRingFlash_Main ; 2
offsetTableEntry.w BigRingFlash_Delete ; 4
; ===========================================================================
; loc_122D8:
BigRingFlash_Init:
addq.b #2,routine(a0)
move.l #Obj37_MapUnc_124E6,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_BigRing_Flash,1,0),art_tile(a0)
bsr.w Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #0,priority(a0)
move.b #$20,width_pixels(a0)
move.b #-1,mapping_frame(a0)
; loc_12306:
BigRingFlash_Main:
bsr.s BigRingFlash_Animate
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w DeleteObject
bra.w DisplaySprite
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_12320:
BigRingFlash_Animate:
subq.b #1,anim_frame_duration(a0) ; subtract 1 from frame duration
bpl.s + ; rts
move.b #1,anim_frame_duration(a0) ; reset frame duration (2 frames)
addq.b #1,mapping_frame(a0) ; use next animation frame
cmpi.b #8,mapping_frame(a0) ; have we reached the end of the animation frames?
bhs.s ++ ; if yes, branch
cmpi.b #3,mapping_frame(a0) ; have we reached the 4th animation frame?
bne.s + ; rts ; if not, return
movea.l objoff_3C(a0),a1 ; a1=object ; get the parent big ring object
move.b #6,routine(a1) ; set its routine to "delete"
move.b #AniIDSonAni_Blank,(MainCharacter+anim).w ; change the character's animation
move.b #1,(SpecialStage_flag_2P).w
lea (MainCharacter).w,a1 ; a1=character
bclr #status_sec_isInvincible,status_secondary(a1)
bclr #status_sec_hasShield,status_secondary(a1)
+ rts
; ===========================================================================
+
addq.b #2,routine(a0)
move.w #0,(MainCharacter).w ; delete the player object
addq.l #4,sp
rts
; End of function BigRingFlash_Animate
; ===========================================================================
; BranchTo7_DeleteObject
BigRingFlash_Delete:
bra.w DeleteObject
; end of dead code/data
; ===========================================================================
; animation script
; byte_1237A:
Ani_Ring: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 5, 4, 5, 6, 7,$FC
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj25_MapUnc_12382: BINCLUDE "mappings/sprite/obj37_a.bin"
; -------------------------------------------------------------------------------
; Unused sprite mappings
; -------------------------------------------------------------------------------
Obj37_MapUnc_123E6: BINCLUDE "mappings/sprite/obj37_b.bin"
; -------------------------------------------------------------------------------
; Unused sprite mappings
; -------------------------------------------------------------------------------
Obj37_MapUnc_124E6: BINCLUDE "mappings/sprite/obj37_c.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object DC - Ring prize from Casino Night Zone
; ----------------------------------------------------------------------------
casino_prize_x_pos = objoff_30 ; X position of the ring with greater precision
casino_prize_y_pos = objoff_34 ; Y position of the ring with greater precision
casino_prize_machine_x_pos = objoff_38 ; X position of the slot machine that generated the ring
casino_prize_machine_y_pos = objoff_3A ; Y position of the slot machine that generated the ring
casino_prize_display_delay = objoff_3C ; number of frames before which the ring is displayed
; Sprite_125E6:
ObjDC:
moveq #0,d0
move.b routine(a0),d0
move.w ObjDC_Index(pc,d0.w),d1
jmp ObjDC_Index(pc,d1.w)
; ===========================================================================
; off_125F4:
ObjDC_Index: offsetTable
offsetTableEntry.w ObjDC_Main ; 0
offsetTableEntry.w ObjDC_Animate ; 2
offsetTableEntry.w ObjDC_Delete ; 4
; ===========================================================================
; loc_125FA:
ObjDC_Main:
moveq #0,d1
move.w casino_prize_machine_x_pos(a0),d1
swap d1
move.l casino_prize_x_pos(a0),d0
sub.l d1,d0
asr.l #4,d0
sub.l d0,casino_prize_x_pos(a0)
move.w casino_prize_x_pos(a0),x_pos(a0)
moveq #0,d1
move.w casino_prize_machine_y_pos(a0),d1
swap d1
move.l casino_prize_y_pos(a0),d0
sub.l d1,d0
asr.l #4,d0
sub.l d0,casino_prize_y_pos(a0)
move.w casino_prize_y_pos(a0),y_pos(a0)
lea Ani_objDC(pc),a1
bsr.w AnimateSprite
subq.w #1,casino_prize_display_delay(a0)
bne.w DisplaySprite
movea.l objoff_2A(a0),a1
subq.w #1,(a1)
bsr.w CollectRing
addi_.b #2,routine(a0)
; loc_1264E:
ObjDC_Animate:
lea Ani_Ring(pc),a1
bsr.w AnimateSprite
bra.w DisplaySprite
; ===========================================================================
; BranchTo8_DeleteObject
ObjDC_Delete:
bra.w DeleteObject
; ===========================================================================
; animation script
; byte_1265E
Ani_objDC: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 1, 0, 1, 2, 3,$FF
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo4_CalcSine
jmp (CalcSine).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 26 - Monitor
;
; The power-ups themselves are handled by the next object. This just does the
; monitor collision and graphics.
; ----------------------------------------------------------------------------
; Obj_Monitor:
Obj26:
moveq #0,d0
move.b routine(a0),d0
move.w Obj26_Index(pc,d0.w),d1
jmp Obj26_Index(pc,d1.w)
; ===========================================================================
; obj_26_subtbl:
Obj26_Index: offsetTable
offsetTableEntry.w Obj26_Init ; 0
offsetTableEntry.w Obj26_Main ; 2
offsetTableEntry.w Obj26_Break ; 4
offsetTableEntry.w Obj26_Animate ; 6
offsetTableEntry.w BranchTo2_MarkObjGone ; 8
; ===========================================================================
; obj_26_sub_0: Obj_26_Init:
Obj26_Init:
addq.b #2,routine(a0)
move.b #$E,y_radius(a0)
move.b #$E,x_radius(a0)
move.l #Obj26_MapUnc_12D36,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Powerups,0,0),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #3,priority(a0)
move.b #$F,width_pixels(a0)
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
bclr #7,2(a2,d0.w)
btst #0,2(a2,d0.w) ; if this bit is set it means the monitor is already broken
beq.s +
move.b #8,routine(a0) ; set monitor to 'broken' state
move.b #$B,mapping_frame(a0)
rts
; ---------------------------------------------------------------------------
+
move.b #$46,collision_flags(a0)
move.b subtype(a0),anim(a0) ; subtype = icon to display
tst.w (Two_player_mode).w ; is it two player mode?
beq.s Obj26_Main ; if not, branch
move.b #9,anim(a0) ; use '?' icon
;obj_26_sub_2:
Obj26_Main:
move.b routine_secondary(a0),d0
beq.s SolidObject_Monitor
; only when secondary routine isn't 0
; make monitor fall
bsr.w ObjectMoveAndFall
jsr (ObjCheckFloorDist).l
tst.w d1 ; is monitor in the ground?
bpl.w SolidObject_Monitor ; if not, branch
add.w d1,y_pos(a0) ; move monitor out of the ground
clr.w y_vel(a0)
clr.b routine_secondary(a0) ; stop monitor from falling
; loc_1271C:
SolidObject_Monitor:
move.w #$1A,d1 ; monitor's width
move.w #$F,d2
move.w d2,d3
addq.w #1,d3
move.w x_pos(a0),d4
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.w SolidObject_Monitor_Sonic
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
bsr.w SolidObject_Monitor_Tails
Obj26_Animate:
lea (Ani_obj26).l,a1
bsr.w AnimateSprite
BranchTo2_MarkObjGone
bra.w MarkObjGone
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_12756:
SolidObject_Monitor_Sonic:
btst d6,status(a0) ; is Sonic standing on the monitor?
bne.s Obj26_ChkOverEdge ; if yes, branch
cmpi.b #AniIDSonAni_Roll,anim(a1) ; is Sonic spinning?
bne.w SolidObject_cont ; if not, branch
rts
; End of function SolidObject_Monitor_Sonic
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_12768:
SolidObject_Monitor_Tails:
btst d6,status(a0) ; is Tails standing on the monitor?
bne.s Obj26_ChkOverEdge ; if yes, branch
tst.w (Two_player_mode).w ; is it two player mode?
beq.w SolidObject_cont ; if not, branch
; in one player mode monitors always behave as solid for Tails
cmpi.b #2,anim(a1) ; is Tails spinning?
bne.w SolidObject_cont ; if not, branch
rts
; End of function SolidObject_Monitor_Tails
; ---------------------------------------------------------------------------
; Checks if the player has walked over the edge of the monitor.
; ---------------------------------------------------------------------------
;loc_12782:
Obj26_ChkOverEdge:
move.w d1,d2
add.w d2,d2
btst #1,status(a1) ; is the character in the air?
bne.s + ; if yes, branch
; check, if character is standing on
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.s + ; branch, if character is behind the left edge of the monitor
cmp.w d2,d0
blo.s Obj26_CharStandOn ; branch, if character is not beyond the right edge of the monitor
+
; if the character isn't standing on the monitor
bclr #3,status(a1) ; clear 'on object' bit
bset #1,status(a1) ; set 'in air' bit
bclr d6,status(a0) ; clear 'standing on' bit for the current character
moveq #0,d4
rts
; ---------------------------------------------------------------------------
;loc_127B2:
Obj26_CharStandOn:
move.w d4,d2
bsr.w MvSonicOnPtfm
moveq #0,d4
rts
; ===========================================================================
;obj_26_sub_4:
Obj26_Break:
move.b status(a0),d0
andi.b #standing_mask|pushing_mask,d0 ; is someone touching the monitor?
beq.s Obj26_SpawnIcon ; if not, branch
move.b d0,d1
andi.b #p1_standing|p1_pushing,d1 ; is it the main character?
beq.s + ; if not, branch
andi.b #$D7,(MainCharacter+status).w
ori.b #2,(MainCharacter+status).w ; prevent Sonic from walking in the air
+
andi.b #p2_standing|p2_pushing,d0 ; is it the sidekick?
beq.s Obj26_SpawnIcon ; if not, branch
andi.b #$D7,(Sidekick+status).w
ori.b #2,(Sidekick+status).w ; prevent Tails from walking in the air
;loc_127EC:
Obj26_SpawnIcon:
clr.b status(a0)
addq.b #2,routine(a0)
move.b #0,collision_flags(a0)
bsr.w SingleObjLoad
bne.s Obj26_SpawnSmoke
_move.b #ObjID_MonitorContents,id(a1) ; load obj2E
move.w x_pos(a0),x_pos(a1) ; set icon's position
move.w y_pos(a0),y_pos(a1)
move.b anim(a0),anim(a1)
move.w parent(a0),parent(a1) ; parent gets the item
;loc_1281E:
Obj26_SpawnSmoke:
bsr.w SingleObjLoad
bne.s +
_move.b #ObjID_Explosion,id(a1) ; load obj27
addq.b #2,routine(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
+
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
bset #0,2(a2,d0.w) ; mark monitor as destroyed
move.b #$A,anim(a0)
bra.w DisplaySprite
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 2E - Monitor contents (code for power-up behavior and rising image)
; ----------------------------------------------------------------------------
Obj2E:
moveq #0,d0
move.b routine(a0),d0
move.w Obj2E_Index(pc,d0.w),d1
jmp Obj2E_Index(pc,d1.w)
; ===========================================================================
; off_12862:
Obj2E_Index: offsetTable
offsetTableEntry.w Obj2E_Init ; 0
offsetTableEntry.w Obj2E_Raise ; 2
offsetTableEntry.w Obj2E_Wait ; 4
; ===========================================================================
; Object initialization. Called if routine counter == 0.
; loc_12868:
Obj2E_Init:
addq.b #2,routine(a0)
move.w #make_art_tile(ArtTile_ArtNem_Powerups,0,1),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #$24,render_flags(a0)
move.b #3,priority(a0)
move.b #8,width_pixels(a0)
move.w #-$300,y_vel(a0)
moveq #0,d0
move.b anim(a0),d0
tst.w (Two_player_mode).w ; is it two player mode?
beq.s loc_128C6 ; if not, branch
; give 'random' item in two player mode
move.w (Timer_frames).w,d0 ; use the timer to determine which item
andi.w #7,d0 ; and 7 means there are 8 different items
addq.w #1,d0 ; add 1 to prevent getting the static monitor
tst.w (Two_player_items).w ; are monitors set to 'teleport only'?
beq.s + ; if not, branch
moveq #8,d0 ; force contents to be teleport
+ ; keep teleport monitor from causing unwanted effects
cmpi.w #8,d0 ; teleport?
bne.s + ; if not, branch
move.b (Update_HUD_timer).w,d1
add.b (Update_HUD_timer_2P).w,d1
cmpi.b #2,d1 ; is either player done with the act?
beq.s + ; if not, branch
moveq #7,d0 ; give invincibility, instead
+
move.b d0,anim(a0)
;loc_128C6:
loc_128C6: ; Determine correct mappings offset.
addq.b #1,d0
move.b d0,mapping_frame(a0)
movea.l #Obj26_MapUnc_12D36,a1
add.b d0,d0
adda.w (a1,d0.w),a1
addq.w #2,a1
move.l a1,mappings(a0)
; loc_128DE:
Obj2E_Raise:
bsr.s +
bra.w DisplaySprite
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
+
tst.w y_vel(a0) ; is icon still floating up?
bpl.w + ; if not, branch
bsr.w ObjectMove ; update position
addi.w #$18,y_vel(a0) ; reduce upward speed
rts
; ---------------------------------------------------------------------------
+
addq.b #2,routine(a0)
move.w #$1D,anim_frame_duration(a0)
movea.w parent(a0),a1 ; a1=character
lea (Monitors_Broken).w,a2
cmpa.w #MainCharacter,a1 ; did Sonic break the monitor?
beq.s + ; if yes, branch
lea (Monitors_Broken_2P).w,a2
+
moveq #0,d0
move.b anim(a0),d0
add.w d0,d0
move.w Obj2E_Types(pc,d0.w),d0
jmp Obj2E_Types(pc,d0.w)
; End of function
; ===========================================================================
Obj2E_Types: offsetTable
offsetTableEntry.w robotnik_monitor ; 0 - Static
offsetTableEntry.w sonic_1up ; 1 - Sonic 1-up
offsetTableEntry.w tails_1up ; 2 - Tails 1-up
offsetTableEntry.w robotnik_monitor ; 3 - Robotnik
offsetTableEntry.w super_ring ; 4 - Super Ring
offsetTableEntry.w super_shoes ; 5 - Speed Shoes
offsetTableEntry.w shield_monitor ; 6 - Shield
offsetTableEntry.w invincible_monitor ; 7 - Invincibility
offsetTableEntry.w teleport_monitor ; 8 - Teleport
offsetTableEntry.w qmark_monitor ; 9 - Question mark
; ===========================================================================
; ---------------------------------------------------------------------------
; Robotnik Monitor
; hurts the player
; ---------------------------------------------------------------------------
; badnik_monitor:
robotnik_monitor:
addq.w #1,(a2)
bra.w Touch_ChkHurt2
; ===========================================================================
; ---------------------------------------------------------------------------
; Sonic 1up Monitor
; gives Sonic an extra life, or Tails in a 'Tails alone' game
; ---------------------------------------------------------------------------
sonic_1up:
addq.w #1,(Monitors_Broken).w
addq.b #1,(Life_count).w
addq.b #1,(Update_HUD_lives).w
move.w #MusID_ExtraLife,d0
jmp (PlayMusic).l ; Play extra life music
; ===========================================================================
; ---------------------------------------------------------------------------
; Tails 1up Monitor
; gives Tails an extra life in two player mode
; ---------------------------------------------------------------------------
tails_1up:
addq.w #1,(Monitors_Broken_2P).w
addq.b #1,(Life_count_2P).w
addq.b #1,(Update_HUD_lives_2P).w
move.w #MusID_ExtraLife,d0
jmp (PlayMusic).l ; Play extra life music
; ===========================================================================
; ---------------------------------------------------------------------------
; Super Ring Monitor
; gives the player 10 rings
; ---------------------------------------------------------------------------
super_ring:
addq.w #1,(a2)
if gameRevision=0
lea (Ring_count).w,a2
lea (Update_HUD_rings).w,a3
lea (Extra_life_flags).w,a4
cmpa.w #MainCharacter,a1
beq.s +
lea (Ring_count_2P).w,a2
lea (Update_HUD_rings_2P).w,a3
lea (Extra_life_flags_2P).w,a4
+ ; give player 10 rings
addi.w #10,(a2)
else
lea (Ring_count).w,a2
lea (Update_HUD_rings).w,a3
lea (Extra_life_flags).w,a4
lea (Rings_Collected).w,a5
cmpa.w #MainCharacter,a1
beq.s +
lea (Ring_count_2P).w,a2
lea (Update_HUD_rings_2P).w,a3
lea (Extra_life_flags_2P).w,a4
lea (Rings_Collected_2P).w,a5
+
addi.w #10,(a5)
cmpi.w #999,(a5)
blo.s +
move.w #999,(a5)
+ ; give player 10 rings and max out at 999
addi.w #10,(a2)
cmpi.w #999,(a2)
blo.s +
move.w #999,(a2)
endif
+
ori.b #1,(a3)
cmpi.w #100,(a2)
blo.s + ; branch, if player has less than 100 rings
bset #1,(a4) ; set flag for first 1up
beq.s ChkPlayer_1up ; branch, if not yet set
cmpi.w #200,(a2)
blo.s + ; branch, if player has less than 200 rings
bset #2,(a4) ; set flag for second 1up
beq.s ChkPlayer_1up ; branch, if not yet set
+
move.w #SndID_Ring,d0
jmp (PlayMusic).l
; ---------------------------------------------------------------------------
;loc_129D4:
ChkPlayer_1up:
; give 1up to correct player
cmpa.w #MainCharacter,a1
beq.w sonic_1up
bra.w tails_1up
; ===========================================================================
; ---------------------------------------------------------------------------
; Super Sneakers Monitor
; speeds the player up temporarily
; ---------------------------------------------------------------------------
super_shoes:
addq.w #1,(a2)
bset #status_sec_hasSpeedShoes,status_secondary(a1) ; give super sneakers status
move.w #$4B0,speedshoes_time(a1)
cmpa.w #MainCharacter,a1 ; did the main character break the monitor?
bne.s super_shoes_Tails ; if not, branch
cmpi.w #2,(Player_mode).w ; is player using Tails?
beq.s super_shoes_Tails ; if yes, branch
move.w #$C00,(Sonic_top_speed).w ; set stats
move.w #$18,(Sonic_acceleration).w
move.w #$80,(Sonic_deceleration).w
bra.s +
; ---------------------------------------------------------------------------
;loc_12A10:
super_shoes_Tails:
move.w #$C00,(Tails_top_speed).w
move.w #$18,(Tails_acceleration).w
move.w #$80,(Tails_deceleration).w
+
move.w #MusID_SpeedUp,d0
jmp (PlayMusic).l ; Speed up tempo
; ===========================================================================
; ---------------------------------------------------------------------------
; Shield Monitor
; gives the player a shield that absorbs one hit
; ---------------------------------------------------------------------------
shield_monitor:
addq.w #1,(a2)
bset #status_sec_hasShield,status_secondary(a1) ; give shield status
move.w #SndID_Shield,d0
jsr (PlayMusic).l
tst.b parent+1(a0)
bne.s +
move.b #ObjID_Shield,(Sonic_Shield+id).w ; load Obj38 (shield) at $FFFFD180
move.w a1,(Sonic_Shield+parent).w
rts
; ---------------------------------------------------------------------------
+ ; give shield to sidekick
move.b #ObjID_Shield,(Tails_Shield+id).w ; load Obj38 (shield) at $FFFFD1C0
move.w a1,(Tails_Shield+parent).w
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Invincibility Monitor
; makes the player temporarily invincible
; ---------------------------------------------------------------------------
invincible_monitor:
addq.w #1,(a2)
tst.b (Super_Sonic_flag).w ; is Sonic super?
bne.s +++ ; rts ; if yes, branch
bset #status_sec_isInvincible,status_secondary(a1) ; give invincibility status
move.w #20*60,invincibility_time(a1) ; 20 seconds
tst.b (Current_Boss_ID).w ; don't change music during boss battles
bne.s +
cmpi.b #$C,air_left(a1) ; or when drowning
bls.s +
move.w #MusID_Invincible,d0
jsr (PlayMusic).l
+
tst.b parent+1(a0)
bne.s +
move.b #ObjID_InvStars,(Sonic_InvincibilityStars+id).w ; load Obj35 (invincibility stars) at $FFFFD200
move.w a1,(Sonic_InvincibilityStars+parent).w
rts
; ---------------------------------------------------------------------------
+ ; give invincibility to sidekick
move.b #ObjID_InvStars,(Tails_InvincibilityStars+id).w ; load Obj35 (invincibility stars) at $FFFFD300
move.w a1,(Tails_InvincibilityStars+parent).w
+
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Teleport Monitor
; swaps both players around
; ---------------------------------------------------------------------------
;loc_12AA6:
teleport_monitor:
addq.w #1,(a2)
cmpi.b #6,(MainCharacter+routine).w ; is player 1 dead or respawning?
bhs.s + ; if yes, branch
cmpi.b #6,(Sidekick+routine).w ; is player 2 dead or respawning?
blo.s swap_players ; if not, branch
+ ; can't teleport if either player is dead
rts
; ---------------------------------------------------------------------------
; Routine to make both players swap positions
; and handle anything else that needs to be done
; ---------------------------------------------------------------------------
swap_players:
lea (teleport_swap_table).l,a3
moveq #(teleport_swap_table_end-teleport_swap_table)/6-1,d2 ; amount of entries in table - 1
process_swap_table:
movea.w (a3)+,a1 ; address for main character
movea.w (a3)+,a2 ; address for sidekick
move.w (a3)+,d1 ; amount of word length data to be swapped
- ; swap data between the main character and the sidekick d1 times
move.w (a1),d0
move.w (a2),(a1)+
move.w d0,(a2)+
dbf d1,-
dbf d2,process_swap_table ; process remaining entries in the list
move.b #1,(MainCharacter+next_anim).w
move.b #1,(Sidekick+next_anim).w
if gameRevision>0
move.b #0,(MainCharacter+mapping_frame).w
move.b #0,(Sidekick+mapping_frame).w
endif
move.b #-1,(Sonic_LastLoadedDPLC).w
move.b #-1,(Tails_LastLoadedDPLC).w
move.b #-1,(TailsTails_LastLoadedDPLC).w
lea (unk_F786).w,a1
lea (unk_F789).w,a2
moveq #2,d1
- move.b (a1),d0
move.b (a2),(a1)+
move.b d0,(a2)+
dbf d1,-
subi.w #$180,(Camera_Y_pos).w
subi.w #$180,(Camera_Y_pos_P2).w
move.w (MainCharacter+art_tile).w,d0
andi.w #drawing_mask,(MainCharacter+art_tile).w
tst.w (Sidekick+art_tile).w
bpl.s +
ori.w #high_priority,(MainCharacter+art_tile).w
+
andi.w #drawing_mask,(Sidekick+art_tile).w
tst.w d0
bpl.s +
ori.w #high_priority,(Sidekick+art_tile).w
+
move.b #1,(Camera_Max_Y_Pos_Changing).w
lea (Dynamic_Object_RAM).w,a1
moveq #(Dynamic_Object_RAM_End-Dynamic_Object_RAM)/object_size-1,d1
; process objects:
swap_loop_objects:
cmpi.b #ObjID_PinballMode,id(a1) ; is it obj84 (pinball mode switcher)?
beq.s + ; if yes, branch
cmpi.b #ObjID_PlaneSwitcher,id(a1) ; is it obj03 (collision plane switcher)?
bne.s ++ ; if not, branch further
+
move.b objoff_34(a1),d0
move.b objoff_35(a1),objoff_34(a1)
move.b d0,objoff_35(a1)
+
cmpi.b #ObjID_PointPokey,id(a1) ; is it objD6 (CNZ point giver)?
bne.s + ; if not, branch
move.l objoff_30(a1),d0
move.l objoff_34(a1),objoff_30(a1)
move.l d0,objoff_34(a1)
+
cmpi.b #ObjID_LauncherSpring,id(a1) ; is it obj85 (CNZ pressure spring)?
bne.s + ; if not, branch
move.b objoff_36(a1),d0
move.b objoff_37(a1),objoff_36(a1)
move.b d0,objoff_37(a1)
+
lea next_object(a1),a1 ; look at next object ; a1=object
dbf d1,swap_loop_objects ; loop
lea (MainCharacter).w,a1 ; a1=character
move.b #ObjID_Shield,(Sonic_Shield+id).w ; load Obj38 (shield) at $FFFFD180
move.w a1,(Sonic_Shield+parent).w
move.b #ObjID_InvStars,(Sonic_InvincibilityStars+id).w ; load Obj35 (invincibility stars) at $FFFFD200
move.w a1,(Sonic_InvincibilityStars+parent).w
btst #2,status(a1) ; is Sonic spinning?
bne.s + ; if yes, branch
move.b #$13,y_radius(a1) ; set to standing height
move.b #9,x_radius(a1)
+
btst #3,status(a1) ; is Sonic on an object?
beq.s + ; if not, branch
moveq #0,d0
move.b interact(a1),d0
if object_size=$40
lsl.w #6,d0
else
mulu.w #object_size,d0
endif
addi.l #Object_RAM,d0
movea.l d0,a2 ; a2=object
bclr #4,status(a2)
bset #3,status(a2)
+
lea (Sidekick).w,a1 ; a1=character
move.b #ObjID_Shield,(Tails_Shield+id).w ; load Obj38 (shield) at $FFFFD1C0
move.w a1,(Tails_Shield+parent).w
move.b #ObjID_InvStars,(Tails_InvincibilityStars+id).w ; load Obj35 (invincibility) at $FFFFD300
move.w a1,(Tails_InvincibilityStars+parent).w
btst #2,status(a1) ; is Tails spinning?
bne.s + ; if yes, branch
move.b #$F,y_radius(a1) ; set to standing height
move.b #9,x_radius(a1)
+
btst #3,status(a1) ; is Tails on an object?
beq.s + ; if not, branch
moveq #0,d0
move.b interact(a1),d0
if object_size=$40
lsl.w #6,d0
else
mulu.w #object_size,d0
endif
addi.l #Object_RAM,d0
movea.l d0,a2 ; a2=object
bclr #3,status(a2)
bset #4,status(a2)
+
move.b #$40,(Teleport_timer).w
move.b #1,(Teleport_flag).w
move.w #SndID_Teleport,d0
jmp (PlayMusic).l
; ===========================================================================
; Table listing all the addresses for players 1 and 2 that need to be swapped
; when a teleport monitor is destroyed
;byte_12C52:
teleport_swap_table:
dc.w MainCharacter+x_pos, Sidekick+x_pos, $1B
dc.w Camera_X_pos_last, Camera_X_pos_last_P2, 0
dc.w Obj_respawn_index, Obj_respawn_index_P2, 0
dc.w Obj_load_addr_right, Obj_load_addr_2, 3
dc.w Sonic_top_speed, Tails_top_speed, 2
dc.w Ring_start_addr, Ring_start_addr_P2, 1
dc.w CNZ_Visible_bumpers_start, CNZ_Visible_bumpers_start_P2, 3
dc.w Camera_X_pos, Camera_X_pos_P2, $F
dc.w Camera_X_pos_coarse, Camera_X_pos_coarse_P2, 0
dc.w Camera_Min_X_pos, Tails_Min_X_pos, 3
dc.w Horiz_scroll_delay_val, Horiz_scroll_delay_val_P2, 1
dc.w Camera_Y_pos_bias, Camera_Y_pos_bias_P2, 0
dc.w Horiz_block_crossed_flag, Horiz_block_crossed_flag_P2, 3
dc.w Scroll_flags, Scroll_flags_P2, 3
dc.w Camera_RAM_copy, Camera_P2_copy, $F
dc.w Scroll_flags_copy, Scroll_flags_copy_P2, 3
dc.w Camera_X_pos_diff, Camera_X_pos_diff_P2, 1
dc.w Sonic_Pos_Record_Buf, Tails_Pos_Record_Buf, $7F
teleport_swap_table_end:
; ===========================================================================
; ---------------------------------------------------------------------------
; '?' Monitor
; doesn't actually do anything other than increase the player's monitor score
; ---------------------------------------------------------------------------
qmark_monitor:
addq.w #1,(a2)
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Holds icon in place for a while, then destroys it
; ---------------------------------------------------------------------------
;loc_12CC2:
Obj2E_Wait:
subq.w #1,anim_frame_duration(a0)
bmi.w DeleteObject
bra.w DisplaySprite
; ===========================================================================
; animation script
; off_12CCE:
Ani_obj26: offsetTable
offsetTableEntry.w Ani_obj26_Static ; 0
offsetTableEntry.w Ani_obj26_Sonic ; 1
offsetTableEntry.w Ani_obj26_Tails ; 2
offsetTableEntry.w Ani_obj26_Eggman ; 3
offsetTableEntry.w Ani_obj26_Ring ; 4
offsetTableEntry.w Ani_obj26_Shoes ; 5
offsetTableEntry.w Ani_obj26_Shield ; 6
offsetTableEntry.w Ani_obj26_Invincibility ; 7
offsetTableEntry.w Ani_obj26_Teleport ; 8
offsetTableEntry.w Ani_obj26_QuestionMark ; 9
offsetTableEntry.w Ani_obj26_Broken ; $A
; byte_12CE4:
Ani_obj26_Static:
dc.b $01 ; duration
dc.b $00 ; frame number (which sprite table to use)
dc.b $01 ; frame number
dc.b $FF ; terminator
; byte_12CE8:
Ani_obj26_Sonic:
dc.b 1, 0, 2, 2, 1, 2, 2,$FF
; byte_12CF0:
Ani_obj26_Tails:
dc.b 1, 0, 3, 3, 1, 3, 3,$FF
; byte_12CF8:
Ani_obj26_Eggman:
dc.b 1, 0, 4, 4, 1, 4, 4,$FF
; byte_12D00:
Ani_obj26_Ring:
dc.b 1, 0, 5, 5, 1, 5, 5,$FF
; byte_12D08:
Ani_obj26_Shoes:
dc.b 1, 0, 6, 6, 1, 6, 6,$FF
; byte_12D10:
Ani_obj26_Shield:
dc.b 1, 0, 7, 7, 1, 7, 7,$FF
; byte_12D18:
Ani_obj26_Invincibility:
dc.b 1, 0, 8, 8, 1, 8, 8,$FF
; byte_12D20:
Ani_obj26_Teleport:
dc.b 1, 0, 9, 9, 1, 9, 9,$FF
; byte_12D28:
Ani_obj26_QuestionMark:
dc.b 1, 0, $A, $A, 1, $A, $A,$FF
; byte_12D30:
Ani_obj26_Broken:
dc.b 2, 0, 1, $B,$FE, 1
even
; ---------------------------------------------------------------------------------
; Sprite Mappings - Sprite table for monitor and monitor contents (26, ??)
; ---------------------------------------------------------------------------------
; MapUnc_12D36: MapUnc_obj26:
Obj26_MapUnc_12D36: BINCLUDE "mappings/sprite/obj26.bin"
; ===========================================================================
if gameRevision<2
nop
endif
; ----------------------------------------------------------------------------
; Object 0E - Flashing stars from intro
; ----------------------------------------------------------------------------
; Sprite_12E18:
Obj0E:
moveq #0,d0
move.b routine(a0),d0
move.w Obj0E_Index(pc,d0.w),d1
jmp Obj0E_Index(pc,d1.w)
; ===========================================================================
; off_12E26: Obj0E_States:
Obj0E_Index: offsetTable
offsetTableEntry.w Obj0E_Init ; 0
offsetTableEntry.w Obj0E_Sonic ; 2
offsetTableEntry.w Obj0E_Tails ; 4
offsetTableEntry.w Obj0E_LogoTop ; 6
offsetTableEntry.w Obj0E_LargeStar ; 8
offsetTableEntry.w Obj0E_SonicHand ; $A
offsetTableEntry.w Obj0E_SmallStar ; $C
offsetTableEntry.w Obj0E_SkyPiece ; $E
offsetTableEntry.w Obj0E_TailsHand ; $10
; ===========================================================================
; loc_12E38:
Obj0E_Init:
addq.b #2,routine(a0) ; useless, because it's overwritten with the subtype below
move.l #Obj0E_MapUnc_136A8,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_TitleSprites,0,0),art_tile(a0)
move.b #4,priority(a0)
move.b subtype(a0),routine(a0)
bra.s Obj0E
; ===========================================================================
Obj0E_Sonic:
addq.w #1,objoff_34(a0)
cmpi.w #$120,objoff_34(a0)
bhs.s +
bsr.w TitleScreen_SetFinalState
+
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_12E76(pc,d0.w),d1
jmp off_12E76(pc,d1.w)
; ===========================================================================
off_12E76: offsetTable
offsetTableEntry.w Obj0E_Sonic_Init ; 0
offsetTableEntry.w loc_12EC2 ; 2
offsetTableEntry.w loc_12EE8 ; 4
offsetTableEntry.w loc_12F18 ; 6
offsetTableEntry.w loc_12F52 ; 8
offsetTableEntry.w Obj0E_Sonic_LastFrame ; $A
offsetTableEntry.w loc_12F7C ; $C
offsetTableEntry.w loc_12F9A ; $E
offsetTableEntry.w loc_12FD6 ; $10
offsetTableEntry.w loc_13014 ; $12
; ===========================================================================
; spawn more stars
Obj0E_Sonic_Init:
addq.b #2,routine_secondary(a0)
move.b #5,mapping_frame(a0)
move.w #$110,x_pixel(a0)
move.w #$E0,y_pixel(a0)
lea (IntroLargeStar).w,a1
move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro stars) at $FFFFB0C0
move.b #8,subtype(a1) ; large star
lea (IntroEmblemTop).w,a1
move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro stars) at $FFFFD140
move.b #6,subtype(a1) ; logo top
moveq #SndID_Sparkle,d0
jmpto (PlaySound).l, JmpTo4_PlaySound
; ===========================================================================
loc_12EC2:
cmpi.w #$38,objoff_34(a0)
bhs.s +
rts
; ===========================================================================
+
addq.b #2,routine_secondary(a0)
lea (TitleScreenPaletteChanger3).w,a1
move.b #ObjID_TtlScrPalChanger,id(a1) ; load objC9 (palette change)
move.b #0,subtype(a1)
st.b objoff_30(a0)
moveq #MusID_Title,d0 ; title music
jmpto (PlayMusic).l, JmpTo4_PlayMusic
; ===========================================================================
loc_12EE8:
cmpi.w #$80,objoff_34(a0)
bhs.s +
rts
; ===========================================================================
+
addq.b #2,routine_secondary(a0)
lea (Pal_133EC).l,a1
lea (Normal_palette).w,a2
moveq #$F,d6
- move.w (a1)+,(a2)+
dbf d6,-
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_12F08:
lea (IntroSmallStar1).w,a1
move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro star) at $FFFFB180
move.b #$E,subtype(a1) ; piece of sky
rts
; End of function sub_12F08
; ===========================================================================
loc_12F18:
moveq #word_13046_end-word_13046+4,d2
lea (word_13046).l,a1
loc_12F20:
move.w objoff_2A(a0),d0
addq.w #1,d0
move.w d0,objoff_2A(a0)
andi.w #3,d0
bne.s +
move.w objoff_2C(a0),d1
addq.w #4,d1
cmp.w d2,d1
bhs.w loc_1310A
move.w d1,objoff_2C(a0)
move.l -4(a1,d1.w),d0
move.w d0,y_pixel(a0)
swap d0
move.w d0,x_pixel(a0)
+
bra.w DisplaySprite
; ===========================================================================
loc_12F52:
lea (Ani_obj0E).l,a1
bsr.w AnimateSprite
bra.w DisplaySprite
; ===========================================================================
Obj0E_Sonic_LastFrame:
addq.b #2,routine_secondary(a0)
move.b #$12,mapping_frame(a0)
lea (IntroSonicHand).w,a1
move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro star) at $FFFFB1C0
move.b #$A,subtype(a1) ; Sonic's hand
bra.w DisplaySprite
; ===========================================================================
loc_12F7C:
cmpi.w #$C0,objoff_34(a0)
blo.s +
addq.b #2,routine_secondary(a0)
lea (IntroTails).w,a1
move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro star) at $FFFFB080
move.b #4,subtype(a1) ; Tails
+
bra.w DisplaySprite
; ===========================================================================
loc_12F9A:
cmpi.w #$120,objoff_34(a0)
blo.s +
addq.b #2,routine_secondary(a0)
clr.w objoff_2C(a0)
st objoff_2F(a0)
lea (Normal_palette_line3).w,a1
move.w #$EEE,d0
moveq #$F,d6
- move.w d0,(a1)+
dbf d6,-
lea (TitleScreenPaletteChanger2).w,a1
move.b #ObjID_TtlScrPalChanger,id(a1) ; load objC9 (palette change handler) at $FFFFB240
move.b #2,subtype(a1)
move.b #ObjID_TitleMenu,(TitleScreenMenu+id).w ; load Obj0F (title screen menu) at $FFFFB400
+
bra.w DisplaySprite
; ===========================================================================
loc_12FD6:
btst #6,(Graphics_Flags).w
beq.s +
cmpi.w #$190,objoff_34(a0)
beq.s ++
bra.w DisplaySprite
; ===========================================================================
+
cmpi.w #$1D0,objoff_34(a0)
beq.s +
bra.w DisplaySprite
; ===========================================================================
+
lea (IntroSmallStar2).w,a1
move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro star) at $FFFFB440
move.b #$C,subtype(a1) ; small star
addq.b #2,routine_secondary(a0)
lea (IntroSmallStar1).w,a1
bsr.w DeleteObject2 ; delete object at $FFFFB180
bra.w DisplaySprite
; ===========================================================================
loc_13014:
move.b (Vint_runcount+3).w,d0
andi.b #7,d0
bne.s ++
move.w objoff_2C(a0),d0
addq.w #2,d0
cmpi.w #CyclingPal_TitleStar_End-CyclingPal_TitleStar,d0
blo.s +
moveq #0,d0
+
move.w d0,objoff_2C(a0)
move.w CyclingPal_TitleStar(pc,d0.w),(Normal_palette_line3+$A).w
+
bra.w DisplaySprite
; ===========================================================================
; word_1303A:
CyclingPal_TitleStar:
binclude "art/palettes/Title Star Cycle.bin"
CyclingPal_TitleStar_End
word_13046:
dc.w $108, $D0
dc.w $100, $C0 ; 2
dc.w $F8, $B0 ; 4
dc.w $F6, $A6 ; 6
dc.w $FA, $9E ; 8
dc.w $100, $9A ; $A
dc.w $104, $99 ; $C
dc.w $108, $98 ; $E
word_13046_end
; ===========================================================================
Obj0E_Tails:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_13074(pc,d0.w),d1
jmp off_13074(pc,d1.w)
; ===========================================================================
off_13074: offsetTable
offsetTableEntry.w Obj0E_Tails_Init ; 0
offsetTableEntry.w loc_13096 ; 2
offsetTableEntry.w loc_12F52 ; 4
offsetTableEntry.w loc_130A2 ; 6
offsetTableEntry.w BranchTo10_DisplaySprite ; 8
; ===========================================================================
Obj0E_Tails_Init:
addq.b #2,routine_secondary(a0)
move.w #$D8,x_pixel(a0)
move.w #$D8,y_pixel(a0)
move.b #1,anim(a0)
rts
; ===========================================================================
loc_13096:
moveq #word_130B8_end-word_130B8+4,d2
lea (word_130B8).l,a1
bra.w loc_12F20
; ===========================================================================
loc_130A2:
addq.b #2,routine_secondary(a0)
lea (IntroTailsHand).w,a1
move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro star) at $FFFFB200
move.b #$10,subtype(a1) ; Tails' hand
BranchTo10_DisplaySprite
bra.w DisplaySprite
; ===========================================================================
word_130B8:
dc.w $D7,$C8
dc.w $D3,$B8 ; 2
dc.w $CE,$AC ; 4
dc.w $CC,$A6 ; 6
dc.w $CA,$A2 ; 8
dc.w $C9,$A1 ; $A
dc.w $C8,$A0 ; $C
word_130B8_end
; ===========================================================================
Obj0E_LogoTop:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_130E2(pc,d0.w),d1
jmp off_130E2(pc,d1.w)
; ===========================================================================
off_130E2: offsetTable
offsetTableEntry.w Obj0E_LogoTop_Init ; 0
offsetTableEntry.w BranchTo11_DisplaySprite ; 2
; ===========================================================================
Obj0E_LogoTop_Init:
move.b #$B,mapping_frame(a0)
tst.b (Graphics_Flags).w
bmi.s +
move.b #$A,mapping_frame(a0)
+
move.b #2,priority(a0)
move.w #$120,x_pixel(a0)
move.w #$E8,y_pixel(a0)
loc_1310A:
addq.b #2,routine_secondary(a0)
BranchTo11_DisplaySprite
bra.w DisplaySprite
; ===========================================================================
Obj0E_SkyPiece:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_13120(pc,d0.w),d1
jmp off_13120(pc,d1.w)
; ===========================================================================
off_13120: offsetTable
offsetTableEntry.w Obj0E_SkyPiece_Init ; 0
offsetTableEntry.w BranchTo12_DisplaySprite ; 2
; ===========================================================================
Obj0E_SkyPiece_Init:
addq.b #2,routine_secondary(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0)
move.b #$11,mapping_frame(a0)
move.b #2,priority(a0)
move.w #$100,x_pixel(a0)
move.w #$F0,y_pixel(a0)
BranchTo12_DisplaySprite
bra.w DisplaySprite
; ===========================================================================
Obj0E_LargeStar:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_13158(pc,d0.w),d1
jmp off_13158(pc,d1.w)
; ===========================================================================
off_13158: offsetTable
offsetTableEntry.w Obj0E_LargeStar_Init ; 0
offsetTableEntry.w loc_12F52 ; 2
offsetTableEntry.w loc_13190 ; 4
offsetTableEntry.w loc_1319E ; 6
; ===========================================================================
Obj0E_LargeStar_Init:
addq.b #2,routine_secondary(a0)
move.b #$C,mapping_frame(a0)
ori.w #high_priority,art_tile(a0)
move.b #2,anim(a0)
move.b #1,priority(a0)
move.w #$100,x_pixel(a0)
move.w #$A8,y_pixel(a0)
move.w #4,objoff_2A(a0)
rts
; ===========================================================================
loc_13190:
subq.w #1,objoff_2A(a0)
bmi.s +
rts
; ===========================================================================
+
addq.b #2,routine_secondary(a0)
rts
; ===========================================================================
loc_1319E:
move.b #2,routine_secondary(a0)
move.b #0,anim_frame(a0)
move.b #0,anim_frame_duration(a0)
move.w #6,objoff_2A(a0)
move.w objoff_2C(a0),d0
addq.w #4,d0
cmpi.w #word_131DC_end-word_131DC+4,d0
bhs.w DeleteObject
move.w d0,objoff_2C(a0)
move.l word_131DC-4(pc,d0.w),d0
move.w d0,y_pixel(a0)
swap d0
move.w d0,x_pixel(a0)
moveq #SndID_Sparkle,d0 ; play intro sparkle sound
jmpto (PlaySound).l, JmpTo4_PlaySound
; ===========================================================================
; unknown
word_131DC:
dc.w $DA, $F2
dc.w $170, $F8 ; 2
dc.w $132,$131 ; 4
dc.w $19E, $A2 ; 6
dc.w $C0, $E3 ; 8
dc.w $180, $E0 ; $A
dc.w $10D,$13B ; $C
dc.w $C0, $AB ; $E
dc.w $165, $107 ; $10
word_131DC_end
; ===========================================================================
Obj0E_SonicHand:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_1320E(pc,d0.w),d1
jmp off_1320E(pc,d1.w)
; ===========================================================================
off_1320E: offsetTable
offsetTableEntry.w Obj0E_SonicHand_Init ; 0
offsetTableEntry.w loc_13234 ; 2
offsetTableEntry.w BranchTo13_DisplaySprite ; 4
; ===========================================================================
Obj0E_SonicHand_Init:
addq.b #2,routine_secondary(a0)
move.b #9,mapping_frame(a0)
move.b #3,priority(a0)
move.w #$145,x_pixel(a0)
move.w #$BF,y_pixel(a0)
BranchTo13_DisplaySprite
bra.w DisplaySprite
; ===========================================================================
loc_13234:
moveq #word_13240_end-word_13240+4,d2
lea (word_13240).l,a1
bra.w loc_12F20
; ===========================================================================
word_13240:
dc.w $143, $C1
dc.w $140, $C2 ; 2
dc.w $141, $C1 ; 4
word_13240_end
; ===========================================================================
Obj0E_TailsHand:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_1325A(pc,d0.w),d1
jmp off_1325A(pc,d1.w)
; ===========================================================================
off_1325A: offsetTable
offsetTableEntry.w Obj0E_TailsHand_Init ; 0
offsetTableEntry.w loc_13280 ; 2
offsetTableEntry.w BranchTo14_DisplaySprite ; 4
; ===========================================================================
Obj0E_TailsHand_Init:
addq.b #2,routine_secondary(a0)
move.b #$13,mapping_frame(a0)
move.b #3,priority(a0)
move.w #$10F,x_pixel(a0)
move.w #$D5,y_pixel(a0)
BranchTo14_DisplaySprite
bra.w DisplaySprite
; ===========================================================================
loc_13280:
moveq #word_1328C_end-word_1328C+4,d2
lea (word_1328C).l,a1
bra.w loc_12F20
; ===========================================================================
word_1328C:
dc.w $10C, $D0
dc.w $10D, $D1 ; 2
word_1328C_end
; ===========================================================================
Obj0E_SmallStar:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_132A2(pc,d0.w),d1
jmp off_132A2(pc,d1.w)
; ===========================================================================
off_132A2: offsetTable
offsetTableEntry.w Obj0E_SmallStar_Init ; 0
offsetTableEntry.w loc_132D2 ; 2
; ===========================================================================
Obj0E_SmallStar_Init:
addq.b #2,routine_secondary(a0)
move.b #$C,mapping_frame(a0)
move.b #5,priority(a0)
move.w #$170,x_pixel(a0)
move.w #$80,y_pixel(a0)
move.b #3,anim(a0)
move.w #$8C,objoff_2A(a0)
bra.w DisplaySprite
; ===========================================================================
loc_132D2:
subq.w #1,objoff_2A(a0)
bmi.w DeleteObject
subq.w #2,x_pixel(a0)
addq.w #1,y_pixel(a0)
lea (Ani_obj0E).l,a1
bsr.w AnimateSprite
bra.w DisplaySprite
; ===========================================================================
; ----------------------------------------------------------------------------
; Object C9 - "Palette changing handler" from title screen
; ----------------------------------------------------------------------------
ttlscrpalchanger_fadein_time_left = objoff_30
ttlscrpalchanger_fadein_time = objoff_31
ttlscrpalchanger_fadein_amount = objoff_32
ttlscrpalchanger_start_offset = objoff_34
ttlscrpalchanger_length = objoff_36
ttlscrpalchanger_codeptr = objoff_3A
; Sprite_132F0:
ObjC9:
moveq #0,d0
move.b routine(a0),d0
move.w ObjC9_Index(pc,d0.w),d1
jmp ObjC9_Index(pc,d1.w)
; ===========================================================================
ObjC9_Index: offsetTable
offsetTableEntry.w ObjC9_Init ; 0
offsetTableEntry.w ObjC9_Main ; 2
; ===========================================================================
ObjC9_Init:
addq.b #2,routine(a0)
moveq #0,d0
move.b subtype(a0),d0
lea (PaletteChangerDataIndex).l,a1
adda.w (a1,d0.w),a1
move.l (a1)+,ttlscrpalchanger_codeptr(a0)
movea.l (a1)+,a2
move.b (a1)+,d0
move.w d0,ttlscrpalchanger_start_offset(a0)
lea (Target_palette).w,a3
adda.w d0,a3
move.b (a1)+,d0
move.w d0,ttlscrpalchanger_length(a0)
- move.w (a2)+,(a3)+
dbf d0,-
move.b (a1)+,d0
move.b d0,ttlscrpalchanger_fadein_time_left(a0)
move.b d0,ttlscrpalchanger_fadein_time(a0)
move.b (a1)+,ttlscrpalchanger_fadein_amount(a0)
rts
; ===========================================================================
ObjC9_Main:
subq.b #1,ttlscrpalchanger_fadein_time_left(a0)
bpl.s +
move.b ttlscrpalchanger_fadein_time(a0),ttlscrpalchanger_fadein_time_left(a0)
subq.b #1,ttlscrpalchanger_fadein_amount(a0)
bmi.w DeleteObject
movea.l ttlscrpalchanger_codeptr(a0),a2
movea.l a0,a3
move.w ttlscrpalchanger_length(a0),d0
move.w ttlscrpalchanger_start_offset(a0),d1
lea (Normal_palette).w,a0
adda.w d1,a0
lea (Target_palette).w,a1
adda.w d1,a1
- jsr (a2) ; dynamic call! to Pal_FadeFromBlack.UpdateColour, loc_1344C, or loc_1348A, assuming the PaletteChangerData pointers haven't been changed
dbf d0,-
movea.l a3,a0
+
rts
; ===========================================================================
; off_1337C:
PaletteChangerDataIndex: offsetTable
offsetTableEntry.w off_1338C ; 0
offsetTableEntry.w off_13398 ; 2
offsetTableEntry.w off_133A4 ; 4
offsetTableEntry.w off_133B0 ; 6
offsetTableEntry.w off_133BC ; 8
offsetTableEntry.w off_133C8 ; $A
offsetTableEntry.w off_133D4 ; $C
offsetTableEntry.w off_133E0 ; $E
C9PalInfo macro codeptr,dataptr,loadtoOffset,length,fadeinTime,fadeinAmount
dc.l codeptr, dataptr
dc.b loadtoOffset, length, fadeinTime, fadeinAmount
endm
off_1338C: C9PalInfo Pal_FadeFromBlack.UpdateColour, Pal_1342C, $60, $F,2,$15
off_13398: C9PalInfo loc_1344C, Pal_1340C, $40, $F,4,7
off_133A4: C9PalInfo loc_1344C, Pal_AD1E, 0, $F,8,7
off_133B0: C9PalInfo loc_1348A, Pal_AD1E, 0, $F,8,7
off_133BC: C9PalInfo loc_1344C, Pal_AC7E, 0,$1F,4,7
off_133C8: C9PalInfo loc_1344C, Pal_ACDE, $40,$1F,4,7
off_133D4: C9PalInfo loc_1344C, Pal_AD3E, 0, $F,4,7
off_133E0: C9PalInfo loc_1344C, Pal_AC9E, 0,$1F,4,7
Pal_133EC: BINCLUDE "art/palettes/Title Sonic.bin"
Pal_1340C: BINCLUDE "art/palettes/Title Background.bin"
Pal_1342C: BINCLUDE "art/palettes/Title Emblem.bin"
; ===========================================================================
loc_1344C:
move.b (a1)+,d2
andi.b #$E,d2
move.b (a0),d3
cmp.b d2,d3
bls.s loc_1345C
subq.b #2,d3
move.b d3,(a0)
loc_1345C:
addq.w #1,a0
move.b (a1)+,d2
move.b d2,d3
andi.b #$E0,d2
andi.b #$E,d3
move.b (a0),d4
move.b d4,d5
andi.b #$E0,d4
andi.b #$E,d5
cmp.b d2,d4
bls.s loc_1347E
subi.b #$20,d4
loc_1347E:
cmp.b d3,d5
bls.s loc_13484
subq.b #2,d5
loc_13484:
or.b d4,d5
move.b d5,(a0)+
rts
; ===========================================================================
loc_1348A:
moveq #$E,d2
move.b (a0),d3
and.b d2,d3
cmp.b d2,d3
bhs.s loc_13498
addq.b #2,d3
move.b d3,(a0)
loc_13498:
addq.w #1,a0
move.b (a0),d3
move.b d3,d4
andi.b #$E0,d3
andi.b #$E,d4
cmpi.b #-$20,d3
bhs.s loc_134B0
addi.b #$20,d3
loc_134B0:
cmp.b d2,d4
bhs.s loc_134B6
addq.b #2,d4
loc_134B6:
or.b d3,d4
move.b d4,(a0)+
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
TitleScreen_SetFinalState:
tst.b objoff_2F(a0)
bne.w + ; rts
move.b (Ctrl_1_Press).w,d0
or.b (Ctrl_2_Press).w,d0
andi.b #button_up_mask|button_down_mask|button_left_mask|button_right_mask|button_B_mask|button_C_mask|button_A_mask,(Ctrl_1_Press).w
andi.b #button_up_mask|button_down_mask|button_left_mask|button_right_mask|button_B_mask|button_C_mask|button_A_mask,(Ctrl_2_Press).w
andi.b #button_start_mask,d0
beq.w + ; rts
st.b objoff_2F(a0)
move.b #$10,routine_secondary(a0)
move.b #$12,mapping_frame(a0)
move.w #$108,x_pixel(a0)
move.w #$98,y_pixel(a0)
lea (IntroSonicHand).w,a1
bsr.w TitleScreen_InitSprite
move.b #ObjID_IntroStars,id(a1) ; load obj0E (flashing intro star) at $FFFFB1C0
move.b #$A,routine(a1) ; Sonic's hand
move.b #2,priority(a1)
move.b #9,mapping_frame(a1)
move.b #4,routine_secondary(a1)
move.w #$141,x_pixel(a1)
move.w #$C1,y_pixel(a1)
lea (IntroTails).w,a1
bsr.w TitleScreen_InitSprite
move.b #ObjID_IntroStars,id(a1) ; load obj0E
move.b #4,routine(a1) ; Tails
move.b #4,mapping_frame(a1)
move.b #6,routine_secondary(a1)
move.b #3,priority(a1)
move.w #$C8,x_pixel(a1)
move.w #$A0,y_pixel(a1)
lea (IntroTailsHand).w,a1
bsr.w TitleScreen_InitSprite
move.b #ObjID_IntroStars,id(a1) ; load obj0E
move.b #$10,routine(a1) ; Tails' hand
move.b #2,priority(a1)
move.b #$13,mapping_frame(a1)
move.b #4,routine_secondary(a1)
move.w #$10D,x_pixel(a1)
move.w #$D1,y_pixel(a1)
lea (IntroEmblemTop).w,a1
move.b #ObjID_IntroStars,id(a1) ; load obj0E
move.b #6,subtype(a1) ; logo top
bsr.w sub_12F08
move.b #ObjID_TitleMenu,(TitleScreenMenu+id).w ; load Obj0F (title screen menu) at $FFFFB400
lea (TitleScreenPaletteChanger).w,a1
bsr.w DeleteObject2
lea_ Pal_1342C,a1
lea (Normal_palette_line4).w,a2
moveq #7,d6
- move.l (a1)+,(a2)+
dbf d6,-
lea_ Pal_1340C,a1
lea (Normal_palette_line3).w,a2
moveq #7,d6
- move.l (a1)+,(a2)+
dbf d6,-
lea_ Pal_133EC,a1
lea (Normal_palette).w,a2
moveq #7,d6
- move.l (a1)+,(a2)+
dbf d6,-
tst.b objoff_30(a0)
bne.s + ; rts
moveq #MusID_Title,d0 ; title music
jsrto (PlayMusic).l, JmpTo4_PlayMusic
+
rts
; End of function sub_134BC
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;sub_135EA:
TitleScreen_InitSprite:
move.l #Obj0E_MapUnc_136A8,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_TitleSprites,0,0),art_tile(a1)
move.b #4,priority(a1)
rts
; End of function TitleScreen_InitSprite
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 0F - Title screen menu
; ----------------------------------------------------------------------------
; Sprite_13600:
Obj0F:
moveq #0,d0
move.b routine(a0),d0
move.w Obj0F_Index(pc,d0.w),d1
jsr Obj0F_Index(pc,d1.w)
bra.w DisplaySprite
; ===========================================================================
; off_13612: Obj0F_States:
Obj0F_Index: offsetTable
offsetTableEntry.w Obj0F_Init ; 0
offsetTableEntry.w Obj0F_Main ; 2
; ===========================================================================
; loc_13616:
Obj0F_Init:
addq.b #2,routine(a0) ; => Obj0F_Main
move.w #$128,x_pixel(a0)
move.w #$14C,y_pixel(a0)
move.l #Obj0F_MapUnc_13B70,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0)
bsr.w Adjust2PArtPointer
andi.b #1,(Title_screen_option).w
move.b (Title_screen_option).w,mapping_frame(a0)
; loc_13644:
Obj0F_Main:
moveq #0,d2
move.b (Title_screen_option).w,d2
move.b (Ctrl_1_Press).w,d0
or.b (Ctrl_2_Press).w,d0
btst #button_up,d0
beq.s +
subq.b #1,d2
bcc.s +
move.b #2,d2
+
btst #button_down,d0
beq.s +
addq.b #1,d2
cmpi.b #3,d2
blo.s +
moveq #0,d2
+
move.b d2,mapping_frame(a0)
move.b d2,(Title_screen_option).w
andi.b #button_up_mask|button_down_mask,d0
beq.s + ; rts
moveq #SndID_Blip,d0 ; selection blip sound
jsrto (PlaySound).l, JmpTo4_PlaySound
+
rts
; ===========================================================================
; animation script
; off_13686:
Ani_obj0E: offsetTable
offsetTableEntry.w byte_1368E ; 0
offsetTableEntry.w byte_13694 ; 1
offsetTableEntry.w byte_1369C ; 2
offsetTableEntry.w byte_136A4 ; 3
byte_1368E:
dc.b 1
dc.b 5 ; 1
dc.b 6 ; 2
dc.b 7 ; 3
dc.b 8 ; 4
dc.b $FA ; 5
even
byte_13694:
dc.b 1
dc.b 0 ; 1
dc.b 1 ; 2
dc.b 2 ; 3
dc.b 3 ; 4
dc.b 4 ; 5
dc.b $FA ; 6
even
byte_1369C:
dc.b 1
dc.b $C ; 1
dc.b $D ; 2
dc.b $E ; 3
dc.b $D ; 4
dc.b $C ; 5
dc.b $FA ; 6
even
byte_136A4:
dc.b 3
dc.b $C ; 1
dc.b $F ; 2
dc.b $FF ; 3
even
; -----------------------------------------------------------------------------
; Sprite Mappings - Flashing stars from intro (Obj0E)
; -----------------------------------------------------------------------------
Obj0E_MapUnc_136A8: BINCLUDE "mappings/sprite/obj0E.bin"
; -----------------------------------------------------------------------------
; sprite mappings
; -----------------------------------------------------------------------------
Obj0F_MapUnc_13B70: BINCLUDE "mappings/sprite/obj0F.bin"
if ~~removeJmpTos
JmpTo4_PlaySound
jmp (PlaySound).l
JmpTo4_PlayMusic
jmp (PlayMusic).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 34 - level title card (screen with red, yellow, and blue)
; ----------------------------------------------------------------------------
titlecard_x_target = objoff_30 ; the X position the object will reach
titlecard_x_source = objoff_32 ; the X position the object starts from and will end at
titlecard_location = objoff_34 ; point up to which titlecard is drawn
titlecard_vram_dest = objoff_36 ; target of VRAM write
titlecard_vram_dest_2P = objoff_38 ; target of VRAM write
titlecard_split_point = objoff_3A ; point to split drawing for yellow and red portions
titlecard_leaveflag = objoff_3E ; whether or not titlecard is leaving screen
; Sprite_13C48:
Obj34: ; (note: screen-space obj)
moveq #0,d0
move.b routine(a0),d0
move.w Obj34_Index(pc,d0.w),d1
jmp Obj34_Index(pc,d1.w)
; ===========================================================================
Obj34_Index: offsetTable
offsetTableEntry.w Obj34_Init ; 0 - create all the title card objects
offsetTableEntry.w Obj34_BackgroundIn ; 2 - the background, coming in
offsetTableEntry.w Obj34_BottomPartIn ; 4 - the yellow part at the bottom, coming in
offsetTableEntry.w Obj34_LeftPartIn ; 6 - the red part on the left, coming in
offsetTableEntry.w Obj34_ZoneName ; 8 - the name of the zone, coming in
offsetTableEntry.w Obj34_Zone ; $A - the word "ZONE", coming in
offsetTableEntry.w Obj34_ActNumber ; $C - the act number, coming in
offsetTableEntry.w Obj34_LeftPartOut ; $E - red part on the left, going out
offsetTableEntry.w Obj34_BottomPartOut ; $10 - yellow part at the bottom, going out
offsetTableEntry.w Obj34_BackgroundOutInit ; $12 - the background, going out (first frame)
offsetTableEntry.w Obj34_BackgroundOut ; $14 - the background, going out
offsetTableEntry.w Obj34_WaitAndGoAway ; $16 - wait and go away, used by the zone name, "ZONE" and the act number
; ===========================================================================
; loc_13C6E:
Obj34_Init:
lea (a0),a1
lea Obj34_TitleCardData(pc),a2
moveq #(Obj34_TitleCardData_End-Obj34_TitleCardData)/$A-1,d1
- _move.b #ObjID_TitleCard,id(a1) ; load obj34
move.b (a2)+,routine(a1)
move.l #Obj34_MapUnc_147BA,mappings(a1)
move.b (a2)+,mapping_frame(a1)
move.b (a2)+,width_pixels(a1)
move.b (a2)+,anim_frame_duration(a1)
move.w (a2),x_pixel(a1)
move.w (a2)+,titlecard_x_source(a1)
move.w (a2)+,titlecard_x_target(a1)
move.w (a2)+,y_pixel(a1)
move.b #0,render_flags(a1)
lea next_object(a1),a1 ; a1=object
dbf d1,-
move.w #$26,(TitleCard_Bottom+titlecard_location).w
clr.w (Vscroll_Factor_FG).w
move.w #-$E0,(Vscroll_Factor_P2_FG).w
clearRAM Horiz_Scroll_Buf,Horiz_Scroll_Buf_End
rts
; ===========================================================================
; This macro declares data for an object. The data includes:
; - the initial routine counter (byte)
; - the initial mapping frame (byte)
; - the width of the object (byte)
; - the number of frames before it appears on screen (byte)
; - the X position where it starts and where it will go back (word)
; - the X position to reach (word)
; - the Y position (word)
titlecardobjdata macro routine,frame,width,duration,xstart,xstop,y
dc.b routine,frame,width,duration
dc.w xstart,xstop,y
endm
; word_13CD4:
Obj34_TitleCardData:
titlecardobjdata 8, 0, $80, $1B, $240, $120, $B8 ; zone name
titlecardobjdata $A, $11, $40, $1C, $28, $148, $D0 ; "ZONE"
titlecardobjdata $C, $12, $18, $1C, $68, $188, $D0 ; act number
titlecardobjdata 2, 0, 0, 0, 0, 0, 0 ; blue background
titlecardobjdata 4, $15, $48, 8, $2A8, $168,$120 ; bottom yellow part
titlecardobjdata 6, $16, 8, $15, $80, $F0, $F0 ; left red part
Obj34_TitleCardData_End:
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_13D10:
Obj34_Wait:
subq.b #1,anim_frame_duration(a0) ; subtract 1
bne.s + ; if it's not 0, branch
move.b #1,anim_frame_duration(a0) ; reset to 1
rts
; ---------------------------------------------------------------------------
+ addq.w #4,sp ; don't run the code after the call to this routine
rts
; End of function Obj34_Wait
; ===========================================================================
; loc_13D22:
Obj34_BackgroundIn: ; the blue background (green when playing as Knuckles), coming in
moveq #$10,d0
moveq #8,d1
tst.w (Two_player_mode).w ; if two-player mode is on (1)
sne d6 ; then set d6 to $FF, else set d6 to $00
beq.s +
moveq #$20,d0
moveq #7,d1
+
move.w titlecard_location(a0),d2
cmp.w d0,d2
beq.s ++ ; rts
lsl.w d1,d2
move.w #VRAM_Plane_A_Name_Table,d0
add.w d2,d0
move.w d0,titlecard_vram_dest(a0)
tst.b d6
beq.s +
addi.w #VRAM_Plane_A_Name_Table_2P,d2
move.w d2,titlecard_vram_dest_2P(a0)
+
addq.w #1,titlecard_location(a0)
+
rts
; ===========================================================================
; loc_13D58:
Obj34_BottomPartIn: ; the yellow part at the bottom, coming in
jsr Obj34_Wait(pc)
move.w titlecard_location(a0),d0
bmi.w Obj34_MoveTowardsTargetPosition
add.w d0,d0
move.w #$80*$14/2,d1 ; $14 half-cells down (for 2P mode)
tst.w (Two_player_mode).w
sne d6
bne.s +
add.w d1,d1 ; double distance down for 1P mode
+
move.w #VRAM_Plane_A_Name_Table,d2
add.w d0,d2
add.w d1,d2
move.w d2,titlecard_vram_dest(a0)
tst.b d6
beq.s +
addi.w #VRAM_Plane_A_Name_Table_2P,d1
add.w d0,d1
move.w d1,titlecard_vram_dest_2P(a0)
+
subq.w #2,titlecard_location(a0)
move.w titlecard_location(a0),titlecard_split_point(a0)
cmpi.w #6,titlecard_location(a0) ; if titlecard_location(a0) is 6,
seq titlecard_location(a0) ; then set it to $FF, else set it to $00
bra.w Obj34_MoveTowardsTargetPosition
; ===========================================================================
; loc_13DA6:
Obj34_LeftPartIn: ; the red part on the left, coming in
jsr Obj34_Wait(pc)
tst.w titlecard_location(a0)
bmi.w Obj34_MoveTowardsTargetPosition
move.w #VRAM_Plane_A_Name_Table,titlecard_vram_dest(a0)
tst.w (Two_player_mode).w
beq.s +
move.w #VRAM_Plane_A_Name_Table_2P,titlecard_vram_dest_2P(a0)
+
addq.w #2,titlecard_location(a0)
move.w titlecard_location(a0),titlecard_split_point(a0)
cmpi.w #$E,titlecard_location(a0)
seq titlecard_location(a0)
bra.w Obj34_MoveTowardsTargetPosition
; ===========================================================================
; loc_13DDC:
Obj34_ZoneName: ; the name of the zone, coming in
jsr Obj34_Wait(pc)
move.b (Current_Zone).w,mapping_frame(a0)
bra.s Obj34_MoveTowardsTargetPosition
; ===========================================================================
; loc_13DE8:
Obj34_Zone: ; the word "ZONE", coming in
jsr Obj34_Wait(pc)
bra.s Obj34_MoveTowardsTargetPosition
; ===========================================================================
; loc_13DEE:
Obj34_ActNumber: ; the act number, coming in
jsr Obj34_Wait(pc)
move.b (Current_Zone).w,d0 ; get the current zone
cmpi.b #sky_chase_zone,d0 ; is it Sky Chase?
beq.s BranchTo9_DeleteObject ; if yes, branch
cmpi.b #wing_fortress_zone,d0 ; is it Wing Fortress?
beq.s BranchTo9_DeleteObject ; if yes, branch
cmpi.b #death_egg_zone,d0 ; is it Death Egg Zone?
beq.s BranchTo9_DeleteObject ; if yes, branch
move.b (Current_Act).w,d1 ; get the current act
addi.b #$12,d1 ; add $12 to it (this is the index of the "1" frame in the mappings)
cmpi.b #metropolis_zone_2,d0 ; are we in Metropolis Zone Act 3?
bne.s + ; if not, branch
moveq #$14,d1 ; use the "3" frame instead
+
move.b d1,mapping_frame(a0) ; set the mapping frame
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_13E1C:
Obj34_MoveTowardsTargetPosition:
moveq #$10,d0 ; set speed
move.w x_pixel(a0),d1 ; get the X position
cmp.w titlecard_x_target(a0),d1 ; compare with target position
beq.s ++ ; if it reached its target position, branch
bhi.s + ; if it's beyond the target position, branch
neg.w d0 ; negate the speed
+
sub.w d0,x_pixel(a0) ; move the object
cmpi.w #$200,x_pixel(a0) ; is it beyond $200?
bhi.s ++ ; if yes, return
+
bra.w DisplaySprite
; ---------------------------------------------------------------------------
+ rts
; End of function Obj34_MoveTowardsTargetPosition
; ===========================================================================
BranchTo9_DeleteObject
bra.w DeleteObject
; ===========================================================================
; loc_13E42:
Obj34_LeftPartOut: ; red part on the left, going out
move.w titlecard_location(a0),d0
bpl.s +
move.b #$10,TitleCard_Bottom-TitleCard_Left+routine(a0)
clr.w TitleCard_Bottom-TitleCard_Left+titlecard_location(a0)
bra.s BranchTo9_DeleteObject
; ===========================================================================
+
add.w d0,d0
move.w #VRAM_Plane_A_Name_Table,titlecard_vram_dest(a0)
add.w d0,titlecard_vram_dest(a0)
tst.w (Two_player_mode).w
beq.s +
move.w #VRAM_Plane_A_Name_Table_2P,titlecard_vram_dest_2P(a0)
add.w d0,titlecard_vram_dest_2P(a0)
+
subq.w #4,titlecard_location(a0)
cmpi.w #-2,titlecard_location(a0)
bne.s +
clr.w titlecard_location(a0)
+
bra.w loc_13EC4
; ===========================================================================
; loc_13E84:
Obj34_BottomPartOut: ; yellow part at the bottom, going out
move.w titlecard_location(a0),d0
cmpi.w #$28,d0
bne.s +
move.b #$12,TitleCard_Background-TitleCard_Bottom+routine(a0)
bra.s BranchTo9_DeleteObject
; ---------------------------------------------------------------------------
+
add.w d0,d0
move.w #$80*$14/2,d1 ; $14 half-cells down (for 2P mode)
tst.w (Two_player_mode).w
sne d6
bne.s +
add.w d1,d1 ; double distance down for 1P mode
+
move.w #VRAM_Plane_A_Name_Table,d2
add.w d0,d2
add.w d1,d2
move.w d2,titlecard_vram_dest(a0)
tst.b d6
beq.s +
addi.w #VRAM_Plane_A_Name_Table_2P,d1
add.w d0,d1
move.w d1,titlecard_vram_dest_2P(a0)
+
addq.w #4,titlecard_location(a0)
loc_13EC4:
moveq #$20,d0
move.w x_pixel(a0),d1
cmp.w titlecard_x_source(a0),d1
beq.s ++ ; rts
bhi.s +
neg.w d0
+
sub.w d0,x_pixel(a0)
cmpi.w #$200,x_pixel(a0)
bhi.s + ; rts
bra.w DisplaySprite
; ---------------------------------------------------------------------------
+ rts
; ===========================================================================
; loc_13EE6:
Obj34_BackgroundOutInit: ; the background, going out
move.l a0,-(sp)
move.l d7,-(sp)
bsr.w DeformBgLayer
move.l (sp)+,d7
movea.l (sp)+,a0 ; load 0bj address
addi_.b #2,routine(a0)
move.w #$F0,titlecard_location(a0)
; loc_13EFE:
Obj34_BackgroundOut:
move.w titlecard_location(a0),d0
subi.w #$20,d0
cmpi.w #-$30,d0
beq.w BranchTo9_DeleteObject
move.w d0,titlecard_location(a0)
move.w d0,titlecard_vram_dest(a0)
rts
; ===========================================================================
; loc_13F18:
Obj34_WaitAndGoAway:
tst.w anim_frame_duration(a0)
beq.s +
subq.w #1,anim_frame_duration(a0)
bra.s +++ ; DisplaySprite
; ---------------------------------------------------------------------------
+
moveq #$20,d0
move.w x_pixel(a0),d1
cmp.w titlecard_x_source(a0),d1
beq.s Obj34_LoadStandardWaterAndAnimalArt
bhi.s +
neg.w d0
+
sub.w d0,x_pixel(a0)
cmpi.w #$200,x_pixel(a0)
bhi.s Obj34_LoadStandardWaterAndAnimalArt
+
bra.w DisplaySprite
; ===========================================================================
; loc_13F44:
Obj34_LoadStandardWaterAndAnimalArt:
cmpa.w #TitleCard_ZoneName,a0 ; is this the zone name object?
bne.s + ; if not, just delete the title card
moveq #PLCID_StdWtr,d0 ; load the standard water graphics
jsrto (LoadPLC).l, JmpTo3_LoadPLC
moveq #0,d0
move.b (Current_Zone).w,d0
move.b Animal_PLCTable(pc,d0.w),d0 ; load the animal graphics for the current zone
jsrto (LoadPLC).l, JmpTo3_LoadPLC
+
bra.w DeleteObject ; delete the title card object
; ===========================================================================
;byte_13F62:
Animal_PLCTable: zoneOrderedTable 1,1
zoneTableEntry.b PLCID_EhzAnimals ; $0
zoneTableEntry.b PLCID_EhzAnimals ; $1
zoneTableEntry.b PLCID_EhzAnimals ; $2
zoneTableEntry.b PLCID_EhzAnimals ; $3
zoneTableEntry.b PLCID_MtzAnimals ; $4
zoneTableEntry.b PLCID_MtzAnimals ; $5
zoneTableEntry.b PLCID_WfzAnimals ; $6
zoneTableEntry.b PLCID_HtzAnimals ; $7
zoneTableEntry.b PLCID_HpzAnimals ; $8
zoneTableEntry.b PLCID_HpzAnimals ; $9
zoneTableEntry.b PLCID_OozAnimals ; $A
zoneTableEntry.b PLCID_MczAnimals ; $B
zoneTableEntry.b PLCID_CnzAnimals ; $C
zoneTableEntry.b PLCID_CpzAnimals ; $D
zoneTableEntry.b PLCID_DezAnimals ; $E
zoneTableEntry.b PLCID_ArzAnimals ; $F
zoneTableEntry.b PLCID_SczAnimals ; $10
zoneTableEnd
dc.b PLCID_SczAnimals ; level slot $11 (non-existent), not part of main table
even
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 39 - Game/Time Over text
; ----------------------------------------------------------------------------
; Sprite_13F74:
Obj39: ; (screen-space obj)
moveq #0,d0
move.b routine(a0),d0
move.w Obj39_Index(pc,d0.w),d1
jmp Obj39_Index(pc,d1.w)
; ===========================================================================
Obj39_Index: offsetTable
offsetTableEntry.w Obj39_Init ; 0
offsetTableEntry.w Obj39_SlideIn ; 2
offsetTableEntry.w Obj39_Wait ; 4
; ===========================================================================
; loc_13F88:
Obj39_Init:
tst.l (Plc_Buffer).w
beq.s +
rts ; wait until the art is loaded
; ---------------------------------------------------------------------------
+
addq.b #2,routine(a0)
move.w #$50,x_pixel(a0)
btst #0,mapping_frame(a0)
beq.s +
move.w #$1F0,x_pixel(a0)
+
move.w #$F0,y_pixel(a0)
move.l #Obj39_MapUnc_14C6C,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Game_Over,0,1),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #0,render_flags(a0)
move.b #0,priority(a0)
; loc_13FCC:
Obj39_SlideIn:
moveq #$10,d1
cmpi.w #$120,x_pixel(a0)
beq.s Obj39_SetTimer
blo.s +
neg.w d1
+
add.w d1,x_pixel(a0)
bra.w DisplaySprite
; ===========================================================================
; loc_13FE2:
Obj39_SetTimer:
move.w #$2D0,anim_frame_duration(a0)
addq.b #2,routine(a0)
rts
; ===========================================================================
; loc_13FEE:
Obj39_Wait:
btst #0,mapping_frame(a0)
bne.w Obj39_Display
move.b (Ctrl_1_Press).w,d0
or.b (Ctrl_2_Press).w,d0
andi.b #button_B_mask|button_C_mask|button_A_mask,d0
bne.s Obj39_Dismiss
tst.w anim_frame_duration(a0)
beq.s Obj39_Dismiss
subq.w #1,anim_frame_duration(a0)
bra.w DisplaySprite
; ===========================================================================
; loc_14014:
Obj39_Dismiss:
tst.b (Time_Over_flag).w
bne.s Obj39_TimeOver
tst.b (Time_Over_flag_2P).w
bne.s Obj39_TimeOver
move.b #GameModeID_ContinueScreen,(Game_Mode).w ; => ContinueScreen
tst.b (Continue_count).w
bne.s Obj39_Check2PMode
move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen
bra.s Obj39_Check2PMode
; ===========================================================================
; loc_14034:
Obj39_TimeOver:
clr.l (Saved_Timer).w
move.w #1,(Level_Inactive_flag).w
; loc_1403E:
Obj39_Check2PMode:
tst.w (Two_player_mode).w
beq.s Obj39_Display
move.w #0,(Level_Inactive_flag).w
move.b #GameModeID_2PResults,(Game_Mode).w ; => TwoPlayerResults
move.w #VsRSID_Act,(Results_Screen_2P).w
tst.b (Time_Over_flag).w
bne.s Obj39_Display
tst.b (Time_Over_flag_2P).w
bne.s Obj39_Display
move.w #1,(Game_Over_2P).w
move.w #VsRSID_Zone,(Results_Screen_2P).w
jsrto (sub_8476).l, JmpTo_sub_8476
move.w #-1,(a4)
tst.b parent+1(a0)
beq.s +
addq.w #1,a4
+
move.b #-2,(a4)
; BranchTo17_DisplaySprite
Obj39_Display:
bra.w DisplaySprite
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 3A - End of level results screen
; ----------------------------------------------------------------------------
; Sprite_14086:
Obj3A: ; (screen-space obj)
moveq #0,d0
move.b routine(a0),d0
move.w Obj3A_Index(pc,d0.w),d1
jmp Obj3A_Index(pc,d1.w)
; ===========================================================================
; off_14094:
Obj3A_Index: offsetTable
offsetTableEntry.w loc_140AC ; 0
offsetTableEntry.w loc_14102 ; 2
offsetTableEntry.w BranchTo_Obj34_MoveTowardsTargetPosition ; 4
offsetTableEntry.w loc_14146 ; 6
offsetTableEntry.w loc_14168 ; 8
offsetTableEntry.w loc_1419C ; $A
offsetTableEntry.w loc_141AA ; $C
offsetTableEntry.w loc_1419C ; $E
offsetTableEntry.w loc_14270 ; $10
offsetTableEntry.w loc_142B0 ; $12
offsetTableEntry.w loc_142CC ; $14
offsetTableEntry.w loc_1413A ; $16
; ===========================================================================
loc_140AC:
tst.l (Plc_Buffer).w
beq.s +
rts
; ---------------------------------------------------------------------------
+
movea.l a0,a1
lea byte_14380(pc),a2
moveq #7,d1
loc_140BC:
_move.b id(a1),d0
beq.s loc_140CE
cmpi.b #ObjID_Results,d0
beq.s loc_140CE
lea next_object(a1),a1 ; a1=object
bra.s loc_140BC
; ===========================================================================
loc_140CE:
_move.b #ObjID_Results,id(a1) ; load obj3A
move.w (a2)+,x_pixel(a1)
move.w (a2)+,objoff_30(a1)
move.w (a2)+,y_pixel(a1)
move.b (a2)+,routine(a1)
move.b (a2)+,mapping_frame(a1)
move.l #Obj3A_MapUnc_14CBC,mappings(a1)
bsr.w Adjust2PArtPointer2
move.b #0,render_flags(a1)
lea next_object(a1),a1 ; a1=object
dbf d1,loc_140BC
loc_14102:
moveq #0,d0
cmpi.w #2,(Player_mode).w
bne.s loc_14118
addq.w #1,d0
btst #7,(Graphics_Flags).w
beq.s loc_14118
addq.w #1,d0
loc_14118:
move.b d0,mapping_frame(a0)
bsr.w Obj34_MoveTowardsTargetPosition
move.w x_pixel(a0),d0
cmp.w objoff_30(a0),d0
bne.w return_14138
move.b #$A,routine(a0)
move.w #$B4,anim_frame_duration(a0)
return_14138:
rts
; ===========================================================================
loc_1413A:
tst.w (Perfect_rings_left).w
bne.w DeleteObject
BranchTo_Obj34_MoveTowardsTargetPosition
bra.w Obj34_MoveTowardsTargetPosition
; ===========================================================================
loc_14146:
move.b (Current_Zone).w,d0
cmpi.b #sky_chase_zone,d0
beq.s loc_1415E
cmpi.b #wing_fortress_zone,d0
beq.s loc_1415E
cmpi.b #death_egg_zone,d0
bne.w Obj34_MoveTowardsTargetPosition
loc_1415E:
move.b #5,mapping_frame(a0)
bra.w Obj34_MoveTowardsTargetPosition
; ===========================================================================
loc_14168:
move.b (Current_Zone).w,d0
cmpi.b #sky_chase_zone,d0
beq.w BranchTo9_DeleteObject
cmpi.b #wing_fortress_zone,d0
beq.w BranchTo9_DeleteObject
cmpi.b #death_egg_zone,d0
beq.w BranchTo9_DeleteObject
cmpi.b #metropolis_zone_2,d0
bne.s loc_1418E
moveq #8,d0
bra.s loc_14194
; ===========================================================================
loc_1418E:
move.b (Current_Act).w,d0
addq.b #6,d0
loc_14194:
move.b d0,mapping_frame(a0)
bra.w Obj34_MoveTowardsTargetPosition
; ===========================================================================
loc_1419C:
subq.w #1,anim_frame_duration(a0)
bne.s BranchTo18_DisplaySprite
addq.b #2,routine(a0)
BranchTo18_DisplaySprite
bra.w DisplaySprite
; ===========================================================================
loc_141AA:
bsr.w DisplaySprite
move.b #1,(Update_Bonus_score).w
moveq #0,d0
tst.w (Bonus_Countdown_1).w
beq.s loc_141C6
addi.w #10,d0
subi.w #10,(Bonus_Countdown_1).w
loc_141C6:
tst.w (Bonus_Countdown_2).w
beq.s loc_141D6
addi.w #10,d0
subi.w #10,(Bonus_Countdown_2).w
loc_141D6:
tst.w (Bonus_Countdown_3).w
beq.s loc_141E6
addi.w #10,d0
subi.w #10,(Bonus_Countdown_3).w
loc_141E6:
add.w d0,(Total_Bonus_Countdown).w
tst.w d0
bne.s loc_14256
move.w #SndID_TallyEnd,d0
jsr (PlaySound).l
addq.b #2,routine(a0)
move.w #$B4,anim_frame_duration(a0)
cmpi.w #1000,(Total_Bonus_Countdown).w
blo.s return_14254
move.w #$12C,anim_frame_duration(a0)
lea next_object(a0),a1 ; a1=object
loc_14214:
_tst.b id(a1)
beq.s loc_14220
lea next_object(a1),a1 ; a1=object
bra.s loc_14214
; ===========================================================================
loc_14220:
_move.b #ObjID_Results,id(a1) ; load obj3A (uses screen-space)
move.b #$12,routine(a1)
move.w #$188,x_pixel(a1)
move.w #$118,y_pixel(a1)
move.l #Obj3A_MapUnc_14CBC,mappings(a1)
bsr.w Adjust2PArtPointer2
move.b #0,render_flags(a1)
move.w #$3C,anim_frame_duration(a1)
addq.b #1,(Continue_count).w
return_14254:
rts
; ===========================================================================
loc_14256:
jsr (AddPoints).l
move.b (Vint_runcount+3).w,d0
andi.b #3,d0
bne.s return_14254
move.w #SndID_Blip,d0
jmp (PlaySound).l
; ===========================================================================
loc_14270:
moveq #0,d0
move.b (Current_Zone).w,d0
add.w d0,d0
add.b (Current_Act).w,d0
add.w d0,d0
lea LevelOrder(pc),a1
tst.w (Two_player_mode).w
beq.s loc_1428C
lea LevelOrder_2P(pc),a1
loc_1428C:
move.w (a1,d0.w),d0
tst.w d0
bpl.s loc_1429C
move.b #GameModeID_SegaScreen,(Game_Mode).w ; => SegaScreen
rts
; ===========================================================================
loc_1429C:
move.w d0,(Current_ZoneAndAct).w
clr.b (Last_star_pole_hit).w
clr.b (Last_star_pole_hit_2P).w
move.w #1,(Level_Inactive_flag).w
rts
; ===========================================================================
loc_142B0:
tst.w anim_frame_duration(a0)
beq.s loc_142BC
subq.w #1,anim_frame_duration(a0)
rts
; ===========================================================================
loc_142BC:
addi_.b #2,routine(a0)
move.w #SndID_ContinueJingle,d0
jsr (PlaySound).l
loc_142CC:
subq.w #1,anim_frame_duration(a0)
bpl.s loc_142E2
move.w #$13,anim_frame_duration(a0)
addq.b #1,anim_frame(a0)
andi.b #1,anim_frame(a0)
loc_142E2:
moveq #$C,d0
add.b anim_frame(a0),d0
move.b d0,mapping_frame(a0)
btst #4,(Timer_frames+1).w
bne.w DisplaySprite
rts
; ===========================================================================
; -------------------------------------------------------------------------------
; Main game level order
; One value per act. That value is the level/act number of the level to load when
; that act finishes.
; -------------------------------------------------------------------------------
;word_142F8:
LevelOrder: zoneOrderedTable 2,2 ; WrdArr_LevelOrder
zoneTableEntry.w emerald_hill_zone_act_2
zoneTableEntry.w chemical_plant_zone_act_1 ; 1
zoneTableEntry.w emerald_hill_zone_act_1 ; 2
zoneTableEntry.w emerald_hill_zone_act_1 ; 3
zoneTableEntry.w wood_zone_act_2 ; 4
zoneTableEntry.w metropolis_zone_act_1 ; 5
zoneTableEntry.w emerald_hill_zone_act_1 ; 6
zoneTableEntry.w emerald_hill_zone_act_1 ; 7
zoneTableEntry.w metropolis_zone_act_2 ; 8
zoneTableEntry.w metropolis_zone_act_3 ; 9
zoneTableEntry.w sky_chase_zone_act_1 ; 10
zoneTableEntry.w emerald_hill_zone_act_1 ; 11
zoneTableEntry.w death_egg_zone_act_1 ; 12
zoneTableEntry.w emerald_hill_zone_act_1 ; 13
zoneTableEntry.w hill_top_zone_act_2 ; 14
zoneTableEntry.w mystic_cave_zone_act_1 ; 15
zoneTableEntry.w hidden_palace_zone_act_2 ; 16
zoneTableEntry.w oil_ocean_zone_act_1 ; 17
zoneTableEntry.w emerald_hill_zone_act_1 ; 18
zoneTableEntry.w emerald_hill_zone_act_1 ; 19
zoneTableEntry.w oil_ocean_zone_act_2 ; 20
zoneTableEntry.w metropolis_zone_act_1 ; 21
zoneTableEntry.w mystic_cave_zone_act_2 ; 22
zoneTableEntry.w oil_ocean_zone_act_1 ; 23
zoneTableEntry.w casino_night_zone_act_2 ; 24
zoneTableEntry.w hill_top_zone_act_1 ; 25
zoneTableEntry.w chemical_plant_zone_act_2 ; 26
zoneTableEntry.w aquatic_ruin_zone_act_1 ; 27
zoneTableEntry.w $FFFF ; 28
zoneTableEntry.w emerald_hill_zone_act_1 ; 29
zoneTableEntry.w aquatic_ruin_zone_act_2 ; 30
zoneTableEntry.w casino_night_zone_act_1 ; 31
zoneTableEntry.w wing_fortress_zone_act_1 ; 32
zoneTableEntry.w emerald_hill_zone_act_1 ; 33
zoneTableEnd
;word_1433C:
LevelOrder_2P: zoneOrderedTable 2,2 ; WrdArr_LevelOrder_2P
zoneTableEntry.w emerald_hill_zone_act_2
zoneTableEntry.w casino_night_zone_act_1 ; 1
zoneTableEntry.w emerald_hill_zone_act_1 ; 2
zoneTableEntry.w emerald_hill_zone_act_1 ; 3
zoneTableEntry.w wood_zone_act_2 ; 4
zoneTableEntry.w metropolis_zone_act_1 ; 5
zoneTableEntry.w emerald_hill_zone_act_1 ; 6
zoneTableEntry.w emerald_hill_zone_act_1 ; 7
zoneTableEntry.w metropolis_zone_act_2 ; 8
zoneTableEntry.w metropolis_zone_act_3 ; 9
zoneTableEntry.w sky_chase_zone_act_1 ; 10
zoneTableEntry.w emerald_hill_zone_act_1 ; 11
zoneTableEntry.w death_egg_zone_act_1 ; 12
zoneTableEntry.w emerald_hill_zone_act_1 ; 13
zoneTableEntry.w hill_top_zone_act_2 ; 14
zoneTableEntry.w mystic_cave_zone_act_1 ; 15
zoneTableEntry.w hidden_palace_zone_act_2 ; 16
zoneTableEntry.w oil_ocean_zone_act_1 ; 17
zoneTableEntry.w emerald_hill_zone_act_1 ; 18
zoneTableEntry.w emerald_hill_zone_act_1 ; 19
zoneTableEntry.w oil_ocean_zone_act_2 ; 20
zoneTableEntry.w metropolis_zone_act_1 ; 21
zoneTableEntry.w mystic_cave_zone_act_2 ; 22
zoneTableEntry.w $FFFF ; 23
zoneTableEntry.w casino_night_zone_act_2 ; 24
zoneTableEntry.w mystic_cave_zone_act_1 ; 25
zoneTableEntry.w chemical_plant_zone_act_2 ; 26
zoneTableEntry.w aquatic_ruin_zone_act_1 ; 27
zoneTableEntry.w $FFFF ; 28
zoneTableEntry.w emerald_hill_zone_act_1 ; 29
zoneTableEntry.w aquatic_ruin_zone_act_2 ; 30
zoneTableEntry.w casino_night_zone_act_1 ; 31
zoneTableEntry.w wing_fortress_zone_act_1 ; 32
zoneTableEntry.w emerald_hill_zone_act_1 ; 33
zoneTableEnd
byte_14380:
results_screen_object macro startx, targetx, y, routine, frame
dc.w startx, targetx, y
dc.b routine, frame
endm
results_screen_object $20, $120, $B8, 2, 0
results_screen_object $200, $100, $CA, 4, 3
results_screen_object $240, $140, $CA, 6, 4
results_screen_object $278, $178, $BE, 8, 6
results_screen_object $350, $120, $120, 4, 9
results_screen_object $320, $120, $F0, 4, $A
results_screen_object $330, $120, $100, 4, $B
results_screen_object $340, $120, $110, $16, $E
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 6F - End of special stage results screen
; ----------------------------------------------------------------------------
; Sprite_143C0:
Obj6F: ; (note: screen-space obj)
moveq #0,d0
moveq #0,d6
move.b routine(a0),d0
move.w Obj6F_Index(pc,d0.w),d1
jmp Obj6F_Index(pc,d1.w)
; ===========================================================================
; off_143D0:
Obj6F_Index: offsetTable
offsetTableEntry.w Obj6F_Init ; 0
offsetTableEntry.w Obj6F_InitEmeraldText ; 2
offsetTableEntry.w Obj6F_InitResultTitle ; 4
offsetTableEntry.w Obj6F_Emerald0 ; 6
offsetTableEntry.w Obj6F_Emerald1 ; 8
offsetTableEntry.w Obj6F_Emerald2 ; $A
offsetTableEntry.w Obj6F_Emerald3 ; $C
offsetTableEntry.w Obj6F_Emerald4 ; $E
offsetTableEntry.w Obj6F_Emerald5 ; $10
offsetTableEntry.w Obj6F_Emerald6 ; $12
offsetTableEntry.w BranchTo3_Obj34_MoveTowardsTargetPosition ; $14
offsetTableEntry.w Obj6F_P1Rings ; $16
offsetTableEntry.w Obj6F_P2Rings ; $18
offsetTableEntry.w Obj6F_DeleteIfNotEmerald ; $1A
offsetTableEntry.w Obj6F_TimedDisplay ; $1C
offsetTableEntry.w Obj6F_TallyScore ; $1E
offsetTableEntry.w Obj6F_TimedDisplay ; $20
offsetTableEntry.w Obj6F_DisplayOnly ; $22
offsetTableEntry.w Obj6F_TimedDisplay ; $24
offsetTableEntry.w Obj6F_TimedDisplay ; $26
offsetTableEntry.w Obj6F_TallyPerfect ; $28
offsetTableEntry.w Obj6F_PerfectBonus ; $2A
offsetTableEntry.w Obj6F_TimedDisplay ; $2C
offsetTableEntry.w Obj6F_DisplayOnly ; $2E
offsetTableEntry.w Obj6F_InitAndMoveSuperMsg ; $30
offsetTableEntry.w Obj6F_MoveToTargetPos ; $32
offsetTableEntry.w Obj6F_MoveAndDisplay ; $34
; ===========================================================================
;loc_14406
Obj6F_Init:
tst.l (Plc_Buffer).w
beq.s +
rts
; ===========================================================================
+
movea.l a0,a1
lea byte_14752(pc),a2
moveq #$C,d1
- _move.b id(a0),id(a1) ; load obj6F
move.w (a2),x_pixel(a1)
move.w (a2)+,objoff_32(a1)
move.w (a2)+,objoff_30(a1)
move.w (a2)+,y_pixel(a1)
move.b (a2)+,routine(a1)
move.b (a2)+,mapping_frame(a1)
move.l #Obj6F_MapUnc_14ED0,mappings(a1)
move.b #$78,width_pixels(a1)
move.b #0,render_flags(a1)
lea next_object(a1),a1 ; go to next object ; a1=object
dbf d1,- ; loop
;loc_14450
Obj6F_InitEmeraldText:
tst.b (Got_Emerald).w
beq.s +
move.b #4,mapping_frame(a0) ; "Chaos Emerald"
+
cmpi.b #7,(Emerald_count).w
bne.s +
move.b #$19,mapping_frame(a0) ; "Chaos Emeralds"
+
move.w objoff_30(a0),d0
cmp.w x_pixel(a0),d0
bne.s BranchTo2_Obj34_MoveTowardsTargetPosition
move.b #$1C,routine(a0) ; => Obj6F_TimedDisplay
move.w #$B4,anim_frame_duration(a0)
BranchTo2_Obj34_MoveTowardsTargetPosition
bra.w Obj34_MoveTowardsTargetPosition
; ===========================================================================
;loc_14484
Obj6F_InitResultTitle:
cmpi.b #7,(Emerald_count).w
bne.s +
moveq #$16,d0 ; "Sonic has all the"
bra.s ++
; ===========================================================================
+
tst.b (Got_Emerald).w
beq.w DeleteObject
moveq #1,d0 ; "Sonic got a"
+
cmpi.w #2,(Player_mode).w
bne.s +
addq.w #1,d0 ; "Miles got a" or "Miles has all the"
btst #7,(Graphics_Flags).w
beq.s +
addq.w #1,d0 ; "Tails got a" or "Tails has all the"
+
move.b d0,mapping_frame(a0)
bra.w Obj34_MoveTowardsTargetPosition
; ===========================================================================
;loc_144B6
Obj6F_Emerald6:
addq.w #1,d6
;loc_144B8
Obj6F_Emerald5:
addq.w #1,d6
;loc_144BA
Obj6F_Emerald4:
addq.w #1,d6
;loc_144BC
Obj6F_Emerald3:
addq.w #1,d6
;loc_144BE
Obj6F_Emerald2:
addq.w #1,d6
;loc_144C0
Obj6F_Emerald1:
addq.w #1,d6
;loc_144C2
Obj6F_Emerald0:
lea (Got_Emeralds_array).w,a1
tst.b (a1,d6.w)
beq.w DeleteObject
btst #0,(Vint_runcount+3).w
beq.s +
bsr.w DisplaySprite
+
rts
; ===========================================================================
;loc_144DC
Obj6F_P2Rings:
tst.w (Player_mode).w
bne.w DeleteObject
cmpi.b #$26,(SpecialStageResults+routine).w ; Do we need space for perfect countdown?
beq.w DeleteObject ; Branch if yes
moveq #$E,d0 ; "Miles rings"
btst #7,(Graphics_Flags).w
beq.s +
addq.w #1,d0 ; "Tails rings"
+
lea (Bonus_Countdown_2).w,a1
bra.s loc_1455A
; ===========================================================================
;loc_14500
Obj6F_P1Rings:
cmpi.b #$26,(SpecialStageResults+routine).w ; Do we need space for perfect countdown?
bne.s + ; Branch if not
move.w #5000,(Bonus_Countdown_1).w ; Perfect bonus
move.b #$2A,routine(a0) ; => Obj6F_PerfectBonus
move.w #$120,y_pixel(a0)
st.b (Update_Bonus_score).w ; set to -1 (update)
move.w #SndID_Signpost,d0
jsr (PlaySound).l
move.w #$5A,(SpecialStageResults+anim_frame_duration).w
bra.w Obj6F_PerfectBonus
; ===========================================================================
+
move.w (Player_mode).w,d0
beq.s ++
move.w #$120,y_pixel(a0)
subq.w #1,d0
beq.s ++
moveq #$E,d0 ; "Miles rings"
btst #7,(Graphics_Flags).w
beq.s +
addq.w #1,d0 ; "Tails rings"
+
lea (Bonus_Countdown_2).w,a1
bra.s loc_1455A
; ===========================================================================
+
moveq #$D,d0 ; "Sonic rings"
lea (Bonus_Countdown_1).w,a1
loc_1455A:
tst.w (a1)
bne.s +
addq.w #5,d0 ; Rings text with zero points
+
move.b d0,mapping_frame(a0)
BranchTo3_Obj34_MoveTowardsTargetPosition
bra.w Obj34_MoveTowardsTargetPosition
; ===========================================================================
;loc_14568
Obj6F_DeleteIfNotEmerald:
tst.b (Got_Emerald).w
beq.w DeleteObject
bra.s BranchTo3_Obj34_MoveTowardsTargetPosition
; ===========================================================================
;loc_14572
Obj6F_TimedDisplay:
subq.w #1,anim_frame_duration(a0)
bne.s BranchTo19_DisplaySprite
addq.b #2,routine(a0)
BranchTo19_DisplaySprite
bra.w DisplaySprite
; ===========================================================================
;loc_14580
Obj6F_TallyScore:
bsr.w DisplaySprite
move.b #1,(Update_Bonus_score).w
moveq #0,d0
tst.w (Bonus_Countdown_1).w
beq.s +
addi.w #10,d0
subq.w #1,(Bonus_Countdown_1).w
+
tst.w (Bonus_Countdown_2).w
beq.s +
addi.w #10,d0
subq.w #1,(Bonus_Countdown_2).w
+
tst.w (Total_Bonus_Countdown).w
beq.s +
addi.w #10,d0
subi.w #10,(Total_Bonus_Countdown).w
+
tst.w d0
bne.s +++
move.w #SndID_TallyEnd,d0
jsr (PlaySound).l
addq.b #2,routine(a0) ; => Obj6F_TimedDisplay
move.w #$78,anim_frame_duration(a0)
tst.w (Perfect_rings_flag).w
bne.s +
cmpi.w #2,(Player_mode).w
beq.s ++ ; rts
tst.b (Got_Emerald).w
beq.s ++ ; rts
cmpi.b #7,(Emerald_count).w
bne.s ++ ; rts
move.b #$30,routine(a0) ; => Obj6F_InitAndMoveSuperMsg
rts
; ===========================================================================
+
move.b #$24,routine(a0) ; => Obj6F_TimedDisplay
move.w #$5A,anim_frame_duration(a0)
/
rts
; ===========================================================================
+
jsr (AddPoints).l
move.b (Vint_runcount+3).w,d0
andi.b #3,d0
bne.s - ; rts
move.w #SndID_Blip,d0
jmp (PlaySound).l
; ===========================================================================
;loc_1461C
Obj6F_DisplayOnly:
move.w #1,(Level_Inactive_flag).w
bra.w DisplaySprite
; ===========================================================================
;loc_14626
Obj6F_TallyPerfect:
bsr.w DisplaySprite
move.b #1,(Update_Bonus_score).w
moveq #0,d0
tst.w (Bonus_Countdown_1).w
beq.s +
addi.w #20,d0
subi.w #20,(Bonus_Countdown_1).w
+
tst.w d0
beq.s +
jsr (AddPoints).l
move.b (Vint_runcount+3).w,d0
andi.b #3,d0
bne.s ++ ; rts
move.w #SndID_Blip,d0
jmp (PlaySound).l
; ===========================================================================
+
move.w #SndID_TallyEnd,d0
jsr (PlaySound).l
addq.b #4,routine(a0)
move.w #$78,anim_frame_duration(a0)
cmpi.w #2,(Player_mode).w
beq.s + ; rts
tst.b (Got_Emerald).w
beq.s + ; rts
cmpi.b #7,(Emerald_count).w
bne.s + ; rts
move.b #$30,routine(a0) ; => Obj6F_InitAndMoveSuperMsg
+
rts
; ===========================================================================
;loc_14692
Obj6F_PerfectBonus:
moveq #$11,d0 ; "Perfect bonus"
btst #3,(Vint_runcount+3).w
beq.s +
moveq #$15,d0 ; null text
+
move.b d0,mapping_frame(a0)
bra.w DisplaySprite
; ===========================================================================
;loc_146A6
Obj6F_InitAndMoveSuperMsg:
move.b #$32,next_object+routine(a0) ; => Obj6F_MoveToTargetPos
move.w x_pos(a0),d0
cmp.w objoff_32(a0),d0
bne.s Obj6F_MoveToTargetPos
move.b #$14,next_object+routine(a0) ; => BranchTo3_Obj34_MoveTowardsTargetPosition
subq.w #8,next_object+y_pixel(a0)
move.b #$1A,next_object+mapping_frame(a0) ; "Now Sonic can"
move.b #$34,routine(a0) ; => Obj6F_MoveAndDisplay
subq.w #8,y_pixel(a0)
move.b #$1B,mapping_frame(a0) ; "Change into"
lea (SpecialStageResults2).w,a1
_move.b id(a0),id(a1) ; load obj6F; (uses screen-space)
clr.w x_pixel(a1)
move.w #$120,objoff_30(a1)
move.w #$B4,y_pixel(a1)
move.b #$14,routine(a1) ; => BranchTo3_Obj34_MoveTowardsTargetPosition
move.b #$1C,mapping_frame(a1) ; "Super Sonic"
move.l #Obj6F_MapUnc_14ED0,mappings(a1)
move.b #$78,width_pixels(a1)
move.b #0,render_flags(a1)
bra.w DisplaySprite
; ===========================================================================
;loc_14714
Obj6F_MoveToTargetPos:
moveq #$20,d0
move.w x_pos(a0),d1
cmp.w objoff_32(a0),d1
beq.s BranchTo20_DisplaySprite
bhi.s +
neg.w d0
+
sub.w d0,x_pos(a0)
cmpi.w #$200,x_pos(a0)
bhi.s +
BranchTo20_DisplaySprite
bra.w DisplaySprite
; ===========================================================================
+
rts
; ===========================================================================
;loc_14736
Obj6F_MoveAndDisplay:
move.w x_pos(a0),d0
cmp.w objoff_30(a0),d0
bne.w Obj34_MoveTowardsTargetPosition
move.w #$B4,anim_frame_duration(a0)
move.b #$20,routine(a0) ; => Obj6F_TimedDisplay
bra.w DisplaySprite
; ===========================================================================
byte_14752:
; startx targx starty routine map frame
results_screen_object $240, $120, $AA, 2, 0 ; "Special Stage"
results_screen_object 0, $120, $98, 4, 1 ; "Sonic got a"
results_screen_object $118, 0, $C4, 6, 5 ; Emerald 0
results_screen_object $130, 0, $D0, 8, 6 ; Emerald 1
results_screen_object $130, 0, $E8, $A, 7 ; Emerald 2
results_screen_object $118, 0, $F4, $C, 8 ; Emerald 3
results_screen_object $100, 0, $E8, $E, 9 ; Emerald 4
results_screen_object $100, 0, $D0, $10, $A ; Emerald 5
results_screen_object $118, 0, $DC, $12, $B ; Emerald 6
results_screen_object $330, $120, $108, $14, $C ; Score
results_screen_object $340, $120, $118, $16, $D ; Sonic Rings
results_screen_object $350, $120, $128, $18, $E ; Miles Rings
results_screen_object $360, $120, $138, $1A, $10 ; Gems Bonus
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj34_MapUnc_147BA: offsetTable
offsetTableEntry.w word_147E8
offsetTableEntry.w word_147E8
offsetTableEntry.w word_147E8
offsetTableEntry.w word_147E8
offsetTableEntry.w word_14842
offsetTableEntry.w word_14842
offsetTableEntry.w word_14B24
offsetTableEntry.w word_14894
offsetTableEntry.w word_148CE
offsetTableEntry.w word_147E8
offsetTableEntry.w word_14930
offsetTableEntry.w word_14972
offsetTableEntry.w word_149C4
offsetTableEntry.w word_14A1E
offsetTableEntry.w word_14B86
offsetTableEntry.w word_14A88
offsetTableEntry.w word_14AE2
offsetTableEntry.w word_14BC8
offsetTableEntry.w word_14BEA
offsetTableEntry.w word_14BF4
offsetTableEntry.w word_14BFE
offsetTableEntry.w word_14C08
offsetTableEntry.w word_14C32
word_147E8: dc.w $B
dc.w 5, $8580, $82C0, $FFC3
dc.w 9, $85DE, $82EF, $FFD0
dc.w 5, $8580, $82C0, $FFE8
dc.w 5, $85E4, $82F2, $FFF8
dc.w 5, $85E8, $82F4, 8
dc.w 5, $85EC, $82F6, $18
dc.w 5, $85F0, $82F8, $28
dc.w 5, $85F4, $82FA, $48
dc.w 1, $85F8, $82FC, $58
dc.w 5, $85EC, $82F6, $60
dc.w 5, $85EC, $82F6, $70
word_14842: dc.w $A
dc.w 9, $85DE, $82EF, $FFE0
dc.w 5, $8580, $82C0, $FFF8
dc.w 5, $85E4, $82F2, 8
dc.w 5, $85E8, $82F4, $18
dc.w 5, $8588, $82C4, $28
dc.w 5, $85EC, $82F6, $38
dc.w 5, $8588, $82C4, $48
dc.w 5, $85F0, $82F8, $58
dc.w 1, $85F4, $82FA, $68
dc.w 5, $85F6, $82FB, $70
word_14894: dc.w 7
dc.w 5, $85DE, $82EF, 8
dc.w 1, $85E2, $82F1, $18
dc.w 5, $85E4, $82F2, $20
dc.w 5, $85E4, $82F2, $30
dc.w 5, $85E8, $82F4, $51
dc.w 5, $8588, $82C4, $60
dc.w 5, $85EC, $82F6, $70
word_148CE: dc.w $C
dc.w 5, $85DE, $82EF, $FFB8
dc.w 1, $85E2, $82F1, $FFC8
dc.w 5, $85E4, $82F2, $FFD0
dc.w 5, $85E4, $82F2, $FFE0
dc.w 5, $8580, $82C0, $FFF0
dc.w 5, $8584, $82C2, 0
dc.w 5, $85E8, $82F4, $20
dc.w 5, $85EC, $82F6, $30
dc.w 5, $85F0, $82F8, $40
dc.w 5, $85EC, $82F6, $50
dc.w 5, $85F4, $82FA, $60
dc.w 5, $8580, $82C0, $70
word_14930: dc.w 8
dc.w 5, $8588, $82C4, $FFFB
dc.w 1, $85DE, $82EF, $B
dc.w 5, $85E0, $82F0, $13
dc.w 5, $8588, $82C4, $33
dc.w 5, $85E4, $82F2, $43
dc.w 5, $8580, $82C0, $53
dc.w 5, $85E8, $82F4, $60
dc.w 5, $8584, $82C2, $70
word_14972: dc.w $A
dc.w 9, $85DE, $82EF, $FFD0
dc.w 5, $85E4, $82F2, $FFE8
dc.w 5, $85E8, $82F4, $FFF8
dc.w 5, $85EC, $82F6, 8
dc.w 1, $85F0, $82F8, $18
dc.w 5, $85F2, $82F9, $20
dc.w 5, $85F2, $82F9, $41
dc.w 5, $85F6, $82FB, $50
dc.w 5, $85FA, $82FD, $60
dc.w 5, $8580, $82C0, $70
word_149C4: dc.w $B
dc.w 5, $85DE, $82EF, $FFD1
dc.w 5, $85E2, $82F1, $FFE0
dc.w 5, $85E6, $82F3, $FFF0
dc.w 1, $85EA, $82F5, 0
dc.w 5, $8584, $82C2, 8
dc.w 5, $8588, $82C4, $18
dc.w 5, $8584, $82C2, $38
dc.w 1, $85EA, $82F5, $48
dc.w 5, $85EC, $82F6, $50
dc.w 5, $85F0, $82F8, $60
dc.w 5, $85F4, $82FA, $70
word_14A1E: dc.w $D
dc.w 5, $85DE, $82EF, $FFA4
dc.w 5, $85E2, $82F1, $FFB4
dc.w 5, $8580, $82C0, $FFC4
dc.w 9, $85E6, $82F3, $FFD1
dc.w 1, $85EC, $82F6, $FFE9
dc.w 5, $85DE, $82EF, $FFF1
dc.w 5, $85EE, $82F7, 0
dc.w 5, $85F2, $82F9, $10
dc.w 5, $85F6, $82FB, $31
dc.w 5, $85F2, $82F9, $41
dc.w 5, $85EE, $82F7, $50
dc.w 5, $8584, $82C2, $60
dc.w 5, $85FA, $82FD, $70
word_14A88: dc.w $B
dc.w 5, $85DE, $82EF, $FFD2
dc.w 5, $85E2, $82F1, $FFE2
dc.w 5, $85E6, $82F3, $FFF2
dc.w 5, $85DE, $82EF, 0
dc.w 5, $85EA, $82F5, $10
dc.w 1, $85EE, $82F7, $20
dc.w 5, $85F0, $82F8, $28
dc.w 5, $85F4, $82FA, $48
dc.w 5, $85E6, $82F3, $58
dc.w 1, $85EE, $82F7, $68
dc.w 5, $8584, $82C2, $70
word_14AE2: dc.w 8
dc.w 5, $85DE, $82EF, $FFF0
dc.w 5, $85E2, $82F1, 0
dc.w 5, $85E6, $82F3, $10
dc.w 5, $85EA, $82F5, $30
dc.w 5, $85EE, $82F7, $40
dc.w 5, $85F2, $82F9, $50
dc.w 5, $85DE, $82EF, $60
dc.w 5, $8580, $82C0, $70
word_14B24: dc.w $C
dc.w 9, $85DE, $82EF, $FFB1
dc.w 1, $85E4, $82F2, $FFC8
dc.w 5, $8584, $82C2, $FFD0
dc.w 5, $85E6, $82F3, $FFE0
dc.w 5, $85EA, $82F5, 1
dc.w 5, $8588, $82C4, $10
dc.w 5, $85EE, $82F7, $20
dc.w 5, $85F2, $82F9, $30
dc.w 5, $85EE, $82F7, $40
dc.w 5, $8580, $82C0, $50
dc.w 5, $85F6, $82FB, $5F
dc.w 5, $85F6, $82FB, $6F
word_14B86: dc.w 8
dc.w 5, $85DE, $82EF, $FFF2
dc.w 5, $8580, $82C0, 2
dc.w 5, $85E2, $82F1, $10
dc.w 5, $85E6, $82F3, $20
dc.w 5, $85EA, $82F5, $30
dc.w 5, $8580, $82C0, $51
dc.w 5, $85EE, $82F7, $60
dc.w 5, $85EE, $82F7, $70
word_14BC8: dc.w 4
dc.w 5, $858C, $82C6, 1
dc.w 5, $8588, $82C4, $10
dc.w 5, $8584, $82C2, $20
dc.w 5, $8580, $82C0, $30
word_14BEA: dc.w 1
dc.w 7, $A590, $A2C8, 0
word_14BF4: dc.w 1
dc.w $B, $A598, $A2CC, 0
word_14BFE: dc.w 1
dc.w $B, $A5A4, $A2D2, 0
word_14C08: dc.w 5
dc.w $D, $85B0, $82D8, $FFB8
dc.w $D, $85B8, $82DC, $FFD8
dc.w $D, $85C0, $82E0, $FFF8
dc.w $D, $85C8, $82E4, $18
dc.w 5, $85D0, $82E8, $38
word_14C32: dc.w 7
dc.w $9003, $85D4, $82EA, 0
dc.w $B003, $85D4, $82EA, 0
dc.w $D003, $85D4, $82EA, 0
dc.w $F003, $85D4, $82EA, 0
dc.w $1003, $85D4, $82EA, 0
dc.w $3003, $85D4, $82EA, 0
dc.w $5003, $85D4, $82EA, 0
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj39_MapUnc_14C6C: BINCLUDE "mappings/sprite/obj39.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj3A_MapUnc_14CBC: offsetTable
offsetTableEntry.w word_14CDA
offsetTableEntry.w word_14D1C
offsetTableEntry.w word_14D5E
offsetTableEntry.w word_14DA0
offsetTableEntry.w word_14DDA
offsetTableEntry.w word_14BC8
offsetTableEntry.w word_14BEA
offsetTableEntry.w word_14BF4
offsetTableEntry.w word_14BFE
offsetTableEntry.w word_14DF4
offsetTableEntry.w word_14E1E
offsetTableEntry.w word_14E50
offsetTableEntry.w word_14E82
offsetTableEntry.w word_14E8C
offsetTableEntry.w word_14E96
word_14CDA: dc.w 8
dc.w 5, $85D0, $82E8, $FFC0
dc.w 5, $8588, $82C4, $FFD0
dc.w 5, $8584, $82C2, $FFE0
dc.w 1, $85C0, $82E0, $FFF0
dc.w 5, $85B4, $82DA, $FFF8
dc.w 5, $85B8, $82DC, $10
dc.w 5, $8588, $82C4, $20
dc.w 5, $85D4, $82EA, $2F
word_14D1C: dc.w 8
dc.w 9, $85C6, $82E3, $FFBC
dc.w 1, $85C0, $82E0, $FFD4
dc.w 5, $85C2, $82E1, $FFDC
dc.w 5, $8580, $82C0, $FFEC
dc.w 5, $85D0, $82E8, $FFFC
dc.w 5, $85B8, $82DC, $14
dc.w 5, $8588, $82C4, $24
dc.w 5, $85D4, $82EA, $33
word_14D5E: dc.w 8
dc.w 5, $85D4, $82EA, $FFC3
dc.w 5, $85B0, $82D8, $FFD0
dc.w 1, $85C0, $82E0, $FFE0
dc.w 5, $85C2, $82E1, $FFE8
dc.w 5, $85D0, $82E8, $FFF8
dc.w 5, $85B8, $82DC, $10
dc.w 5, $8588, $82C4, $20
dc.w 5, $85D4, $82EA, $2F
word_14DA0: dc.w 7
dc.w 5, $85D4, $82EA, $FFC8
dc.w 5, $85BC, $82DE, $FFD8
dc.w 5, $85CC, $82E6, $FFE8
dc.w 5, $8588, $82C4, $FFF8
dc.w 5, $85D8, $82EC, 8
dc.w 5, $85B8, $82DC, $18
dc.w 5, $85BC, $82DE, $28
word_14DDA: dc.w 3
dc.w 5, $85B0, $82D8, 0
dc.w 5, $85B4, $82DA, $10
dc.w 5, $85D4, $82EA, $1F
word_14DF4: dc.w 5
dc.w 9, $A5E6, $A2F3, $FFB8
dc.w 5, $A5EC, $A2F6, $FFD0
dc.w 5, $85F0, $82F8, $FFD4
dc.w $D, $8520, $8290, $38
dc.w 1, $86F0, $8378, $58
word_14E1E: dc.w 6
dc.w $D, $A6DA, $A36D, $FFA4
dc.w $D, $A5DE, $A2EF, $FFCC
dc.w 1, $A6CA, $A365, $FFEC
dc.w 5, $85F0, $82F8, $FFE8
dc.w $D, $8528, $8294, $38
dc.w 1, $86F0, $8378, $58
word_14E50: dc.w 6
dc.w $D, $A6D2, $A369, $FFA4
dc.w $D, $A5DE, $A2EF, $FFCC
dc.w 1, $A6CA, $A365, $FFEC
dc.w 5, $85F0, $82F8, $FFE8
dc.w $D, $8530, $8298, $38
dc.w 1, $86F0, $8378, $58
word_14E82: dc.w 1
dc.w 6, $85F4, $82FA, 0
word_14E8C: dc.w 1
dc.w 6, $85FA, $82FD, 0
word_14E96: dc.w 7
dc.w $D, $A540, $A2A0, $FF98
dc.w 9, $A548, $A2A4, $FFB8
dc.w $D, $A5DE, $A2EF, $FFD8
dc.w 1, $A6CA, $A365, $FFF8
dc.w 5, $85F0, $82F8, $FFF4
dc.w $D, $8538, $829C, $38
dc.w 1, $86F0, $8378, $58
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj6F_MapUnc_14ED0: BINCLUDE "mappings/sprite/obj6F.bin"
; ===========================================================================
;loc_15584: ; level title card drawing function called from Vint
DrawLevelTitleCard:
lea (VDP_data_port).l,a6
tst.w (TitleCard_ZoneName+titlecard_leaveflag).w
bne.w loc_15670
moveq #$3F,d5
move.l #make_block_tile_pair(ArtTile_ArtNem_TitleCard+$5A,0,0,0,1),d6
tst.w (Two_player_mode).w
beq.s loc_155A8
moveq #$1F,d5
move.l #make_block_tile_pair_2p(ArtTile_ArtNem_TitleCard+$5A,0,0,0,1),d6
loc_155A8:
lea (TitleCard_Background+titlecard_vram_dest).w,a0
moveq #1,d7 ; Once for P1, once for P2 (if in 2p mode)
loc_155AE:
move.w (a0)+,d0
beq.s loc_155C6
clr.w -2(a0)
jsr sub_15792(pc)
move.l d0,VDP_control_port-VDP_data_port(a6)
move.w d5,d4
loc_155C0:
move.l d6,(a6)
dbf d4,loc_155C0
loc_155C6:
dbf d7,loc_155AE
moveq #$26,d1
sub.w (TitleCard_Bottom+titlecard_split_point).w,d1
lsr.w #1,d1
subq.w #1,d1
moveq #7,d5
move.l #make_block_tile_pair(ArtTile_ArtNem_TitleCard+$5C,0,0,1,1),d6
tst.w (Two_player_mode).w
beq.s loc_155EA
moveq #3,d5
move.l #make_block_tile_pair_2p(ArtTile_ArtNem_TitleCard+$5C,0,0,1,1),d6
loc_155EA:
lea (TitleCard_Bottom+titlecard_vram_dest).w,a0
moveq #1,d7 ; Once for P1, once for P2 (if in 2p mode)
loc_155F0:
move.w (a0)+,d0
beq.s loc_15614
clr.w -2(a0)
jsr sub_15792(pc)
move.w d5,d4
loc_155FE:
move.l d0,VDP_control_port-VDP_data_port(a6)
move.w d1,d3
loc_15604:
move.l d6,(a6)
dbf d3,loc_15604
addi.l #vdpCommDelta($0080),d0
dbf d4,loc_155FE
loc_15614:
dbf d7,loc_155F0
move.w (TitleCard_Left+titlecard_split_point).w,d1 ; horizontal draw from left until this position
subq.w #1,d1
moveq #$D,d5
move.l #make_block_tile_pair(ArtTile_ArtNem_TitleCard+$58,0,0,0,1),d6 ; VRAM location of graphic to fill on left side
tst.w (Two_player_mode).w
beq.s loc_15634
moveq #6,d5
move.l #make_block_tile_pair_2p(ArtTile_ArtNem_TitleCard+$58,0,0,0,1),d6 ; VRAM location of graphic to fill on left side (2p)
loc_15634:
lea (TitleCard_Left+titlecard_vram_dest).w,a0 ; obj34 red title card left side part
moveq #1,d7 ; Once for P1, once for P2 (if in 2p mode)
move.w #$8F80,VDP_control_port-VDP_data_port(a6) ; VRAM pointer increment: $0080
loc_15640:
move.w (a0)+,d0
beq.s loc_15664
clr.w -2(a0)
jsr sub_15792(pc)
move.w d1,d4
loc_1564E:
move.l d0,VDP_control_port-VDP_data_port(a6)
move.w d5,d3
loc_15654:
move.l d6,(a6)
dbf d3,loc_15654
addi.l #vdpCommDelta($0002),d0
dbf d4,loc_1564E
loc_15664:
dbf d7,loc_15640
move.w #$8F02,VDP_control_port-VDP_data_port(a6) ; VRAM pointer increment: $0002
rts
; ===========================================================================
loc_15670:
moveq #9,d3
moveq #3,d4
move.l #make_block_tile_pair(ArtTile_ArtNem_TitleCard+$5A,0,0,0,1),d5
move.l #make_block_tile_pair(ArtTile_ArtNem_TitleCard+$5C,0,0,1,1),d6
tst.w (Two_player_mode).w
beq.s +
moveq #4,d3
moveq #1,d4
move.l #make_block_tile_pair_2p(ArtTile_ArtNem_TitleCard+$5A,0,0,0,1),d5
move.l #make_block_tile_pair_2p(ArtTile_ArtNem_TitleCard+$5C,0,0,1,1),d6
+
lea (TitleCard_Left+titlecard_vram_dest).w,a0
moveq #1,d7 ; Once for P1, once for P2 (if in 2p mode)
move.w #$8F80,VDP_control_port-VDP_data_port(a6) ; VRAM pointer increment: $0080
loc_156A2:
move.w (a0)+,d0
beq.s loc_156CE
clr.w -2(a0)
jsr sub_15792(pc)
moveq #3,d2
loc_156B0:
move.l d0,VDP_control_port-VDP_data_port(a6)
move.w d3,d1
- move.l d5,(a6)
dbf d1,-
move.w d4,d1
- move.l d6,(a6)
dbf d1,-
addi.l #vdpCommDelta($0002),d0
dbf d2,loc_156B0
loc_156CE:
dbf d7,loc_156A2
move.w #$8F02,VDP_control_port-VDP_data_port(a6) ; VRAM pointer increment: $0002
moveq #7,d5
move.l #make_block_tile_pair(ArtTile_ArtNem_TitleCard+$5A,0,0,0,1),d6
tst.w (Two_player_mode).w
beq.s +
moveq #3,d5
move.l #make_block_tile_pair_2p(ArtTile_ArtNem_TitleCard+$5A,0,0,0,1),d6
+
lea (TitleCard_Bottom+titlecard_vram_dest).w,a0
moveq #1,d7 ; Once for P1, once for P2 (if in 2p mode)
loc_156F4:
move.w (a0)+,d0
beq.s loc_15714
clr.w -2(a0)
jsr sub_15792(pc)
move.w d5,d4
- move.l d0,VDP_control_port-VDP_data_port(a6)
move.l d6,(a6)
move.l d6,(a6)
addi.l #vdpCommDelta($0080),d0
dbf d4,-
loc_15714:
dbf d7,loc_156F4
move.w (TitleCard_Background+titlecard_vram_dest).w,d4
beq.s loc_1578C
lea VDP_control_port-VDP_data_port(a6),a5
tst.w (Two_player_mode).w
beq.s loc_15758
lea (Camera_X_pos_P2).w,a3
lea (Level_Layout).w,a4
move.w #vdpComm(VRAM_Plane_A_Name_Table_2P,VRAM,WRITE)>>16,d2
moveq #1,d6
- movem.l d4-d6,-(sp)
moveq #-$10,d5
move.w d4,d1
bsr.w CalcBlockVRAMPosB
move.w d1,d4
moveq #-$10,d5
moveq #$1F,d6
bsr.w DrawBlockRow
movem.l (sp)+,d4-d6
addi.w #$10,d4
dbf d6,-
loc_15758:
lea (Camera_X_pos).w,a3
lea (Level_Layout).w,a4
move.w #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE)>>16,d2
move.w (TitleCard_Background+titlecard_vram_dest).w,d4
moveq #1,d6
- movem.l d4-d6,-(sp)
moveq #-$10,d5
move.w d4,d1
bsr.w CalcBlockVRAMPos
move.w d1,d4
moveq #-$10,d5
moveq #$1F,d6
bsr.w DrawBlockRow
movem.l (sp)+,d4-d6
addi.w #$10,d4
dbf d6,-
loc_1578C:
clr.w (TitleCard_Background+titlecard_vram_dest).w
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to convert a VRAM address into a 32-bit VRAM write command word
; Input:
; d0 VRAM address (word)
; Output:
; d0 32-bit VDP command word for a VRAM write to specified address.
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_15792:
andi.l #$FFFF,d0
lsl.l #2,d0
lsr.w #2,d0
ori.w #vdpComm($0000,VRAM,WRITE)>>16,d0
swap d0
rts
; End of function sub_15792
; ===========================================================================
;loc_157A4
LoadTitleCardSS:
movem.l d0/a0,-(sp)
bsr.s LoadTitleCard0
movem.l (sp)+,d0/a0
bra.s loc_157EC
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_157B0:
LoadTitleCard0:
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_TitleCard),VRAM,WRITE),(VDP_control_port).l
lea (ArtNem_TitleCard).l,a0
jsrto (NemDec).l, JmpTo2_NemDec
lea (Level_Layout).w,a4
lea (ArtNem_TitleCard2).l,a0
jmpto (NemDecToRAM).l, JmpTo_NemDecToRAM
; ===========================================================================
; loc_157D2:
LoadTitleCard:
bsr.s LoadTitleCard0
moveq #0,d0
move.b (Current_Zone).w,d0
move.b Off_TitleCardLetters(pc,d0.w),d0
lea TitleCardLetters(pc),a0
lea (a0,d0.w),a0
move.l #vdpComm(tiles_to_bytes(ArtTile_LevelName),VRAM,WRITE),d0
loc_157EC:
move #$2700,sr
lea (Level_Layout).w,a1
lea (VDP_data_port).l,a6
move.l d0,4(a6)
loc_157FE:
moveq #0,d0
move.b (a0)+,d0
bmi.s loc_1581A
lsl.w #5,d0
lea (a1,d0.w),a2
moveq #0,d1
move.b (a0)+,d1
lsl.w #3,d1
subq.w #1,d1
loc_15812:
move.l (a2)+,(a6)
dbf d1,loc_15812
bra.s loc_157FE
; ===========================================================================
loc_1581A:
move #$2300,sr
rts
; ===========================================================================
; byte_15820:
Off_TitleCardLetters:
dc.b TitleCardLetters_EHZ - TitleCardLetters ; 0
dc.b TitleCardLetters_EHZ - TitleCardLetters ; 1
dc.b TitleCardLetters_EHZ - TitleCardLetters ; 2
dc.b TitleCardLetters_EHZ - TitleCardLetters ; 3
dc.b TitleCardLetters_MTZ - TitleCardLetters ; 4
dc.b TitleCardLetters_MTZ - TitleCardLetters ; 5
dc.b TitleCardLetters_WFZ - TitleCardLetters ; 6
dc.b TitleCardLetters_HTZ - TitleCardLetters ; 7
dc.b TitleCardLetters_HPZ - TitleCardLetters ; 8
dc.b TitleCardLetters_EHZ - TitleCardLetters ; 9
dc.b TitleCardLetters_OOZ - TitleCardLetters ; A
dc.b TitleCardLetters_MCZ - TitleCardLetters ; B
dc.b TitleCardLetters_CNZ - TitleCardLetters ; C
dc.b TitleCardLetters_CPZ - TitleCardLetters ; D
dc.b TitleCardLetters_DEZ - TitleCardLetters ; E
dc.b TitleCardLetters_ARZ - TitleCardLetters ; F
dc.b TitleCardLetters_SCZ - TitleCardLetters ; 10
even
; temporarily remap characters to title card letter format
; Characters are encoded as Aa, Bb, Cc, etc. through a macro
charset 'A',0 ; can't have an embedded 0 in a string
charset 'B',"\4\8\xC\4\x10\x14\x18\x1C\x1E\x22\x26\x2A\4\4\x30\x34\x38\x3C\x40\x44\x48\x4C\x52\x56\4"
charset 'a',"\4\4\4\4\4\4\4\4\2\4\4\4\6\4\4\4\4\4\4\4\4\4\6\4\4"
charset '.',"\x5A"
; Defines which letters load for the continue screen
; Each letter occurs only once, and the letters ENOZ (i.e. ZONE) aren't loaded here
; However, this is hidden by the titleLetters macro, and normal titles can be used
; (the macro is defined near SpecialStage_ResultsLetters, which uses it before here)
; word_15832:
TitleCardLetters:
TitleCardLetters_EHZ:
titleLetters "EMERALD HILL"
TitleCardLetters_MTZ:
titleLetters "METROPOLIS"
TitleCardLetters_HTZ:
titleLetters "HILL TOP"
TitleCardLetters_HPZ:
titleLetters "HIDDEN PALACE"
TitleCardLetters_OOZ:
titleLetters "OIL OCEAN"
TitleCardLetters_MCZ:
titleLetters "MYSTIC CAVE"
TitleCardLetters_CNZ:
titleLetters "CASINO NIGHT"
TitleCardLetters_CPZ:
titleLetters "CHEMICAL PLANT"
TitleCardLetters_ARZ:
titleLetters "AQUATIC RUIN"
TitleCardLetters_SCZ:
titleLetters "SKY CHASE"
TitleCardLetters_WFZ:
titleLetters "WING FORTRESS"
TitleCardLetters_DEZ:
titleLetters "DEATH EGG"
charset ; revert character set
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo2_NemDec
jmp (NemDec).l
JmpTo_NemDecToRAM
jmp (NemDecToRAM).l
JmpTo3_LoadPLC
jmp (LoadPLC).l
JmpTo_sub_8476
jmp (sub_8476).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 36 - Spikes
; ----------------------------------------------------------------------------
; OST Variables:
spikes_base_x_pos = objoff_30 ; original x-position
spikes_base_y_pos = objoff_32 ; original y-position
spikes_retract_offset = objoff_34 ; actual position relative to base position
spikes_retract_state = objoff_36 ; 0 = positive offset, 1 = original position
spikes_retract_timer = objoff_38 ; delay, before spikes move again
; Sprite_15900:
Obj36:
moveq #0,d0
move.b routine(a0),d0
move.w Obj36_Index(pc,d0.w),d1
jmp Obj36_Index(pc,d1.w)
; ===========================================================================
; off_1590E:
Obj36_Index: offsetTable
offsetTableEntry.w Obj36_Init ; 0
offsetTableEntry.w Obj36_Upright ; 2
offsetTableEntry.w Obj36_Sideways ; 4
offsetTableEntry.w Obj36_Upsidedown ; 6
; ===========================================================================
; byte_15916:
Obj36_InitData:
; width_pixels
; y_radius
dc.b $10,$10 ; 0 - Upright or ceiling spikes
dc.b $20,$10 ; 2
dc.b $30,$10 ; 4
dc.b $40,$10 ; 6
dc.b $10,$10 ; 8 - Sideways spikes
dc.b $10,$20 ; 10
dc.b $10,$30 ; 12
dc.b $10,$40 ; 14
; ===========================================================================
; loc_15926:
Obj36_Init:
addq.b #2,routine(a0) ; => Obj36_Upright
move.l #Obj36_MapUnc_15B68,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Spikes,1,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #4,priority(a0)
move.b subtype(a0),d0
andi.b #$F,subtype(a0) ; lower 4 bits determine behavior, upper bits need to be removed
andi.w #$F0,d0
lea_ Obj36_InitData,a1 ; upper 4 bits determine size and orientation
lsr.w #3,d0 ; use upper 4 bits * 2 as offset
adda.w d0,a1
move.b (a1)+,width_pixels(a0)
move.b (a1)+,y_radius(a0)
lsr.w #1,d0 ; use upper 4 bits to determine mappings frame
move.b d0,mapping_frame(a0)
cmpi.b #4,d0 ; do spikes face sideways?
blo.s + ; if not, branch
addq.b #2,routine(a0) ; => Obj36_Sideways
move.w #make_art_tile(ArtTile_ArtNem_HorizSpike,1,0),art_tile(a0)
+
btst #1,status(a0) ; are spikes upsiede-down?
beq.s + ; if not, branch
move.b #6,routine(a0) ; => Obj36_Upsidedown
+
move.w x_pos(a0),spikes_base_x_pos(a0)
move.w y_pos(a0),spikes_base_y_pos(a0)
bra.w Adjust2PArtPointer
; ===========================================================================
; loc_15996:
Obj36_Upright:
bsr.w MoveSpikes
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
move.w x_pos(a0),d4
bsr.w SolidObject
move.b status(a0),d6
andi.b #standing_mask,d6 ; are Sonic or Tails standing on the object?
beq.s Obj36_UprightEnd ; if not, branch
move.b d6,d0
andi.b #p1_standing,d0 ; is Sonic standing on the object?
beq.s + ; if not, branch
lea (MainCharacter).w,a1 ; a1=character
bsr.w Touch_ChkHurt2
+
andi.b #p2_standing,d6 ; is Tails standing on the object?
beq.s Obj36_UprightEnd ; if not, branch
lea (Sidekick).w,a1 ; a1=character
bsr.w Touch_ChkHurt2
; loc_159DE:
Obj36_UprightEnd:
move.w spikes_base_x_pos(a0),d0
bra.w MarkObjGone2
; ===========================================================================
; loc_159E6:
Obj36_Sideways:
move.w x_pos(a0),-(sp)
bsr.w MoveSpikes
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
move.w (sp)+,d4
bsr.w SolidObject
swap d6
andi.w #touch_side_mask,d6 ; are Sonic or Tails pushing against the side?
beq.s Obj36_SidewaysEnd ; if not, branch
move.b d6,d0
andi.b #p1_touch_side,d0 ; is Sonic pushing against the side?
beq.s + ; if not, branch
lea (MainCharacter).w,a1 ; a1=character
bsr.w Touch_ChkHurt2
bclr #p1_pushing_bit,status(a0)
+
andi.b #p2_touch_side,d6 ; is Tails pushing against the side?
beq.s Obj36_SidewaysEnd ; if not, branch
lea (Sidekick).w,a1 ; a1=character
bsr.w Touch_ChkHurt2
bclr #p2_pushing_bit,status(a0)
; loc_15A3A:
Obj36_SidewaysEnd:
move.w spikes_base_x_pos(a0),d0
bra.w MarkObjGone2
; ===========================================================================
; loc_15A42:
Obj36_Upsidedown:
bsr.w MoveSpikes
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
move.w x_pos(a0),d4
bsr.w SolidObject
swap d6
andi.w #touch_bottom_mask,d6 ; are Sonic or Tails touching the bottom?
beq.s Obj36_UpsidedownEnd ; if not, branch
move.b d6,d0
andi.b #p1_touch_bottom,d0 ; is Sonic touching the bottom?
beq.s + ; if not, branch
lea (MainCharacter).w,a1 ; a1=character
bsr.w Touch_ChkHurt2
+
andi.b #p2_touch_bottom,d6 ; is Tails touching the bottom?
beq.s Obj36_UpsidedownEnd ; if not, branch
lea (Sidekick).w,a1 ; a1=character
bsr.w Touch_ChkHurt2
; loc_15A88:
Obj36_UpsidedownEnd:
move.w spikes_base_x_pos(a0),d0
bra.w MarkObjGone2
; ---------------------------------------------------------------------------
; Subroutine for checking if Sonic/Tails should be hurt and hurting them if so
; unlike Touch_ChkHurt, the character is at a1 instead of a0
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
Touch_ChkHurt2:
btst #status_sec_isInvincible,status_secondary(a1) ; is character invincible?
bne.s + ; rts ; if yes, branch
tst.w invulnerable_time(a1) ; is character invulnerable?
bne.s + ; rts ; if yes, branch
cmpi.b #4,routine(a1) ; is the character hurt, dieing, etc. ?
bhs.s + ; rts ; if yes, branch
move.l y_pos(a1),d3
move.w y_vel(a1),d0
ext.l d0
asl.l #8,d0
sub.l d0,d3
move.l d3,y_pos(a1)
movea.l a0,a2
movea.l a1,a0
jsr (HurtCharacter).l
movea.l a2,a0
+
rts
; End of function Touch_ChkHurt2
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; handles direction, timing and movement of moving spikes
; sub_15AC6:
MoveSpikes:
moveq #0,d0
move.b subtype(a0),d0
add.w d0,d0
move.w MoveSpikes_Behaviors(pc,d0.w),d1
jmp MoveSpikes_Behaviors(pc,d1.w)
; End of function MoveSpikes
; ===========================================================================
; off_15AD6:
MoveSpikes_Behaviors: offsetTable
offsetTableEntry.w MoveSpikes_Still ; 0
offsetTableEntry.w MoveSpikes_Vertical ; 1
offsetTableEntry.w MoveSpikes_Horizontal ; 2
; ===========================================================================
; return_15ADC:
MoveSpikes_Still:
rts
; ===========================================================================
; loc_15ADE:
MoveSpikes_Vertical:
bsr.w MoveSpikes_Delay
moveq #0,d0
move.b spikes_retract_offset(a0),d0
add.w spikes_base_y_pos(a0),d0 ; apply offset to y-position
move.w d0,y_pos(a0)
rts
; ===========================================================================
; loc_15AF2:
MoveSpikes_Horizontal:
bsr.w MoveSpikes_Delay
moveq #0,d0
move.b spikes_retract_offset(a0),d0
add.w spikes_base_x_pos(a0),d0 ; apply offset to x-position
move.w d0,x_pos(a0)
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_15B06:
MoveSpikes_Delay:
tst.w spikes_retract_timer(a0) ; is it time for spikes to move again?
beq.s MoveSpikes_ChkDir ; if yes, branch
subq.w #1,spikes_retract_timer(a0) ; else, decrement timer
bne.s + ; rts ; branch, if timer didn't reach 0
tst.b render_flags(a0) ; are spikes on screen?
bpl.s + ; rts ; if not, branch
move.w #SndID_SpikesMove,d0 ; play spike movement sount
jsr (PlaySound).l
bra.s + ; rts
; ===========================================================================
; loc_15B24:
MoveSpikes_ChkDir:
tst.w spikes_retract_state(a0) ; do spikes need to move away from initial position?
beq.s MoveSpikes_Retract ; if yes, branch
subi.w #$800,spikes_retract_offset(a0) ; subtract 8 pixels from offset
bhs.s + ; rts ; branch, if offset is not yet 0
move.w #0,spikes_retract_offset(a0)
move.w #0,spikes_retract_state(a0) ; switch state
move.w #$3C,spikes_retract_timer(a0) ; reset timer
bra.s + ; rts
; ===========================================================================
; loc_15B46:
MoveSpikes_Retract:
addi.w #$800,spikes_retract_offset(a0) ; add 8 pixels to offset
cmpi.w #$2000,spikes_retract_offset(a0) ; is offset the width of one spike block (32 pixels)?
blo.s + ; rts ; if not, branch
move.w #$2000,spikes_retract_offset(a0)
move.w #1,spikes_retract_state(a0) ; switch state
move.w #$3C,spikes_retract_timer(a0) ; reset timer
+
rts
; End of function MoveSpikes_Delay
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj36_MapUnc_15B68: BINCLUDE "mappings/sprite/obj36.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 3B - Purple rock (leftover from S1)
; ----------------------------------------------------------------------------
; Sprite_15CC8:
Obj3B:
moveq #0,d0
move.b routine(a0),d0
move.w Obj3B_Index(pc,d0.w),d1
jmp Obj3B_Index(pc,d1.w)
; ===========================================================================
; off_15CD6:
Obj3B_Index: offsetTable
offsetTableEntry.w Obj3B_Init ; 0
offsetTableEntry.w Obj3B_Main ; 2
; ===========================================================================
; loc_15CDA:
Obj3B_Init:
addq.b #2,routine(a0)
move.l #Obj3B_MapUnc_15D2E,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_GHZ_Purple_Rock,3,0),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$13,width_pixels(a0)
move.b #4,priority(a0)
; loc_15D02:
Obj3B_Main:
move.w #$1B,d1
move.w #$10,d2
move.w #$10,d3
move.w x_pos(a0),d4
bsr.w SolidObject
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w DeleteObject
bra.w DisplaySprite
; ===========================================================================
; -------------------------------------------------------------------------------
; Unused sprite mappings
; -------------------------------------------------------------------------------
Obj3B_MapUnc_15D2E: BINCLUDE "mappings/sprite/obj3B.bin"
if ~~removeJmpTos
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 3C - Breakable wall (leftover from S1) (mostly unused)
; ----------------------------------------------------------------------------
; Sprite_15D44:
Obj3C:
moveq #0,d0
move.b routine(a0),d0
move.w Obj3C_Index(pc,d0.w),d1
jsr Obj3C_Index(pc,d1.w)
bra.w MarkObjGone
; ===========================================================================
; off_15D56:
Obj3C_Index: offsetTable
offsetTableEntry.w Obj3C_Init ; 0
offsetTableEntry.w Obj3C_Main ; 2
offsetTableEntry.w Obj3C_Fragment ; 4
; ===========================================================================
; loc_15D5C:
Obj3C_Init:
addq.b #2,routine(a0)
move.l #Obj3C_MapUnc_15ECC,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_BreakWall,2,0),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #4,priority(a0)
move.b subtype(a0),mapping_frame(a0)
; loc_15D8A:
Obj3C_Main:
move.w (MainCharacter+x_vel).w,objoff_30(a0)
move.w #$1B,d1
move.w #$20,d2
move.w #$20,d3
move.w x_pos(a0),d4
bsr.w SolidObject
btst #5,status(a0)
bne.s +
- rts
; ===========================================================================
+
lea (MainCharacter).w,a1 ; a1=character
cmpi.b #2,anim(a1)
bne.s - ; rts
mvabs.w objoff_30(a0),d0
cmpi.w #$480,d0
blo.s - ; rts
move.w objoff_30(a0),x_vel(a1)
addq.w #4,x_pos(a1)
lea (Obj3C_FragmentSpeeds_LeftToRight).l,a4
move.w x_pos(a0),d0
cmp.w x_pos(a1),d0
blo.s +
subi_.w #8,x_pos(a1)
lea (Obj3C_FragmentSpeeds_RightToLeft).l,a4
+
move.w x_vel(a1),inertia(a1)
bclr #5,status(a0)
bclr #5,status(a1)
bsr.s BreakObjectToPieces
; loc_15E02:
Obj3C_Fragment:
bsr.w ObjectMove
addi.w #$70,y_vel(a0)
tst.b render_flags(a0)
bpl.w DeleteObject
bra.w DisplaySprite
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_15E18:
BreakObjectToPieces: ; splits up one object into its current mapping frame pieces
moveq #0,d0
move.b mapping_frame(a0),d0
add.w d0,d0
movea.l mappings(a0),a3
adda.w (a3,d0.w),a3 ; put address of appropriate frame to a3
move.w (a3)+,d1 ; amount of pieces the frame consists of
subq.w #1,d1
bset #5,render_flags(a0)
_move.b id(a0),d4
move.b render_flags(a0),d5
movea.l a0,a1
bra.s BreakObjectToPieces_InitObject
; ===========================================================================
; loc_15E3E:
BreakObjectToPieces_Loop:
bsr.w SingleObjLoad2
bne.s loc_15E82
addq.w #8,a3 ; next mapping piece
; loc_15E46:
BreakObjectToPieces_InitObject:
move.b #4,routine(a1)
_move.b d4,id(a1) ; load object with ID of parent object and routine 4
move.l a3,mappings(a1)
move.b d5,render_flags(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w art_tile(a0),art_tile(a1)
move.b priority(a0),priority(a1)
move.b width_pixels(a0),width_pixels(a1)
move.w (a4)+,x_vel(a1)
move.w (a4)+,y_vel(a1)
dbf d1,BreakObjectToPieces_Loop
loc_15E82:
move.w #SndID_SlowSmash,d0
jmp (PlaySound).l
; End of function BreakObjectToPieces
; ===========================================================================
; word_15E8C:
Obj3C_FragmentSpeeds_LeftToRight:
; x_vel,y_vel
dc.w $400,-$500 ; 0
dc.w $600,-$100 ; 2
dc.w $600, $100 ; 4
dc.w $400, $500 ; 6
dc.w $600,-$600 ; 8
dc.w $800,-$200 ; 10
dc.w $800, $200 ; 12
dc.w $600, $600 ; 14
; word_15EAC:
Obj3C_FragmentSpeeds_RightToLeft:
dc.w -$600,-$600 ; 0
dc.w -$800,-$200 ; 2
dc.w -$800, $200 ; 4
dc.w -$600, $600 ; 6
dc.w -$400,-$500 ; 8
dc.w -$600,-$100 ; 10
dc.w -$600, $100 ; 12
dc.w -$400, $500 ; 14
; -------------------------------------------------------------------------------
; Unused sprite mappings
; -------------------------------------------------------------------------------
Obj3C_MapUnc_15ECC: BINCLUDE "mappings/sprite/obj3C.bin"
; ===========================================================================
bra.w ObjNull
; -------------------------------------------------------------------------------
; This runs the code of all the objects that are in Object_RAM
; -------------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_15F9C: ObjectsLoad:
RunObjects:
tst.b (Teleport_flag).w
bne.s RunObjects_End ; rts
lea (Object_RAM).w,a0 ; a0=object
moveq #(Dynamic_Object_RAM_End-Object_RAM)/object_size-1,d7 ; run the first $80 objects out of levels
moveq #0,d0
cmpi.b #GameModeID_Demo,(Game_Mode).w ; demo mode?
beq.s + ; if in a level in a demo, branch
cmpi.b #GameModeID_Level,(Game_Mode).w ; regular level mode?
bne.s RunObject ; if not in a level, branch to RunObject
+
move.w #(Object_RAM_End-Object_RAM)/object_size-1,d7 ; run the first $90 objects in levels
tst.w (Two_player_mode).w
bne.s RunObject ; if in 2 player competition mode, branch to RunObject
cmpi.b #6,(MainCharacter+routine).w
bhs.s RunObjectsWhenPlayerIsDead ; if dead, branch
; continue straight to RunObject
; ---------------------------------------------------------------------------
; -------------------------------------------------------------------------------
; This is THE place where each individual object's code gets called from
; -------------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_15FCC:
RunObject:
move.b id(a0),d0 ; get the object's ID
beq.s RunNextObject ; if it's obj00, skip it
add.w d0,d0
add.w d0,d0 ; d0 = object ID * 4
movea.l Obj_Index-4(pc,d0.w),a1 ; load the address of the object's code
jsr (a1) ; dynamic call! to one of the the entries in Obj_Index
moveq #0,d0
; loc_15FDC:
RunNextObject:
lea next_object(a0),a0 ; load 0bj address
dbf d7,RunObject
; return_15FE4:
RunObjects_End:
rts
; ---------------------------------------------------------------------------
; this skips certain objects to make enemies and things pause when Sonic dies
; loc_15FE6:
RunObjectsWhenPlayerIsDead:
moveq #(Reserved_Object_RAM_End-Reserved_Object_RAM)/object_size-1,d7
bsr.s RunObject ; run the first $10 objects normally
moveq #(Dynamic_Object_RAM_End-Dynamic_Object_RAM)/object_size-1,d7
bsr.s RunObjectDisplayOnly ; all objects in this range are paused
moveq #(LevelOnly_Object_RAM_End-LevelOnly_Object_RAM)/object_size-1,d7
bra.s RunObject ; run the last $10 objects normally
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_15FF2:
RunObjectDisplayOnly:
moveq #0,d0
move.b id(a0),d0 ; get the object's ID
beq.s + ; if it's obj00, skip it
tst.b render_flags(a0) ; should we render it?
bpl.s + ; if not, skip it
bsr.w DisplaySprite
+
lea next_object(a0),a0 ; load 0bj address
dbf d7,RunObjectDisplayOnly
rts
; End of function RunObjectDisplayOnly
; ===========================================================================
; ---------------------------------------------------------------------------
; OBJECT POINTER ARRAY ; object pointers ; sprite pointers ; object list ; sprite list
;
; This array contains the pointers to all the objects used in the game.
; ---------------------------------------------------------------------------
Obj_Index: ; ObjPtrs: ; loc_1600C:
ObjPtr_Sonic: dc.l Obj01 ; Sonic
ObjPtr_Tails: dc.l Obj02 ; Tails
ObjPtr_PlaneSwitcher: dc.l Obj03 ; Collision plane/layer switcher
ObjPtr_WaterSurface: dc.l Obj04 ; Surface of the water
ObjPtr_TailsTails: dc.l Obj05 ; Tails' tails
ObjPtr_Spiral: dc.l Obj06 ; Rotating cylinder in MTZ, twisting spiral pathway in EHZ
ObjPtr_Oil: dc.l Obj07 ; Oil in OOZ
ObjPtr_SpindashDust:
ObjPtr_Splash: dc.l Obj08 ; Water splash in Aquatic Ruin Zone, Spindash dust
ObjPtr_SonicSS: dc.l Obj09 ; Sonic in Special Stage
ObjPtr_SmallBubbles: dc.l Obj0A ; Small bubbles from Sonic's face while underwater
ObjPtr_TippingFloor: dc.l Obj0B ; Section of pipe that tips you off from CPZ
dc.l Obj0C ; Small floating platform (unused)
ObjPtr_Signpost: dc.l Obj0D ; End of level signpost
ObjPtr_IntroStars: dc.l Obj0E ; Flashing stars from intro
ObjPtr_TitleMenu: dc.l Obj0F ; Title screen menu
ObjPtr_TailsSS: dc.l Obj10 ; Tails in Special Stage
ObjPtr_Bridge: dc.l Obj11 ; Bridge in Emerald Hill Zone and Hidden Palace Zone
ObjPtr_HPZEmerald: dc.l Obj12 ; Emerald from Hidden Palace Zone (unused)
ObjPtr_HPZWaterfall: dc.l Obj13 ; Waterfall in Hidden Palace Zone (unused)
ObjPtr_Seesaw: dc.l Obj14 ; Seesaw from Hill Top Zone
ObjPtr_SwingingPlatform:dc.l Obj15 ; Swinging platform from Aquatic Ruin Zone
ObjPtr_HTZLift: dc.l Obj16 ; Diagonally moving lift from HTZ
dc.l Obj17 ; GHZ rotating log helix spikes (from Sonic 1, unused)
ObjPtr_ARZPlatform:
ObjPtr_EHZPlatform: dc.l Obj18 ; Stationary floating platform from ARZ and EHZ
ObjPtr_CPZPlatform:
ObjPtr_OOZMovingPform:
ObjPtr_WFZPlatform: dc.l Obj19 ; Platform from CPZ, OOZ and WFZ
ObjPtr_HPZCollapsPform: dc.l Obj1A ; Collapsing platform from HPZ (and GHZ)
ObjPtr_SpeedBooster: dc.l Obj1B ; Speed booster from from CPZ
ObjPtr_Scenery:
ObjPtr_BridgeStake:
ObjPtr_FallingOil: dc.l Obj1C ; Bridge stake in Emerald Hill Zone and Hill Top Zone, falling oil in Oil Ocean Zone
ObjPtr_BlueBalls: dc.l Obj1D ; Blue balls in CPZ (jumping droplets hazard)
ObjPtr_CPZSpinTube: dc.l Obj1E ; Spin tube from CPZ
ObjPtr_CollapsPform: dc.l Obj1F ; Collapsing platform from ARZ, MCZ and OOZ (and MZ, SLZ and SBZ)
ObjPtr_LavaBubble: dc.l Obj20 ; Lava bubble from Hill Top Zone (boss weapon)
ObjPtr_HUD: dc.l Obj21 ; Score/Rings/Time display (HUD)
ObjPtr_ArrowShooter: dc.l Obj22 ; Arrow shooter from ARZ
ObjPtr_FallingPillar: dc.l Obj23 ; Pillar that drops its lower part from ARZ
ObjPtr_ARZBubbles: dc.l Obj24 ; Bubbles in Aquatic Ruin Zone
ObjPtr_Ring: dc.l Obj25 ; A ring
ObjPtr_Monitor: dc.l Obj26 ; Monitor
ObjPtr_Explosion: dc.l Obj27 ; An explosion, giving off an animal and 100 points
ObjPtr_Animal: dc.l Obj28 ; Animal and the 100 points from a badnik
ObjPtr_Points: dc.l Obj29 ; "100 points" text
ObjPtr_Stomper: dc.l Obj2A ; Stomper from MCZ
ObjPtr_RisingPillar: dc.l Obj2B ; Rising pillar from ARZ
ObjPtr_LeavesGenerator: dc.l Obj2C ; Sprite that makes leaves fly off when you hit it from ARZ
ObjPtr_Barrier: dc.l Obj2D ; One way barrier from CPZ and DEZ
ObjPtr_MonitorContents: dc.l Obj2E ; Monitor contents (code for power-up behavior and rising image)
ObjPtr_SmashableGround: dc.l Obj2F ; Smashable ground in Hill Top Zone
ObjPtr_RisingLava: dc.l Obj30 ; Large rising lava during earthquake in HTZ
ObjPtr_LavaMarker: dc.l Obj31 ; Lava collision marker
ObjPtr_BreakableBlock:
ObjPtr_BreakableRock: dc.l Obj32 ; Breakable block/rock from CPZ and HTZ
ObjPtr_OOZPoppingPform: dc.l Obj33 ; Green platform from OOZ
ObjPtr_TitleCard: dc.l Obj34 ; level title card (screen with red, yellow, and blue)
ObjPtr_InvStars: dc.l Obj35 ; Invincibility Stars
ObjPtr_Spikes: dc.l Obj36 ; Vertical spikes
ObjPtr_LostRings: dc.l Obj37 ; Scattering rings (generated when Sonic is hurt and has rings)
ObjPtr_Shield: dc.l Obj38 ; Shield
ObjPtr_GameOver:
ObjPtr_TimeOver: dc.l Obj39 ; Game/Time Over text
ObjPtr_Results: dc.l Obj3A ; End of level results screen
dc.l Obj3B ; Purple rock (from Sonic 1, unused)
dc.l Obj3C ; Breakable wall (leftover from S1) (mostly unused)
ObjPtr_OOZLauncher: dc.l Obj3D ; Block thingy in OOZ that launches you into the round ball things
ObjPtr_EggPrison: dc.l Obj3E ; Egg prison
ObjPtr_Fan: dc.l Obj3F ; Fan from OOZ
ObjPtr_Springboard: dc.l Obj40 ; Pressure spring from CPZ, ARZ, and MCZ (the red "diving board" springboard)
ObjPtr_Spring: dc.l Obj41 ; Spring
ObjPtr_SteamSpring: dc.l Obj42 ; Steam Spring from MTZ
ObjPtr_SlidingSpike: dc.l Obj43 ; Sliding spike obstacle thing from OOZ
ObjPtr_RoundBumper: dc.l Obj44 ; Round bumper from Casino Night Zone
ObjPtr_OOZSpring: dc.l Obj45 ; Pressure spring from OOZ
ObjPtr_OOZBall: dc.l Obj46 ; Ball from OOZ (unused, beta leftover)
ObjPtr_Button: dc.l Obj47 ; Button
ObjPtr_LauncherBall: dc.l Obj48 ; Round ball thing from OOZ that fires you off in a different direction
ObjPtr_EHZWaterfall: dc.l Obj49 ; Waterfall from EHZ
ObjPtr_Octus: dc.l Obj4A ; Octus (octopus badnik) from OOZ
ObjPtr_Buzzer: dc.l Obj4B ; Buzzer (Buzz bomber) from EHZ
dc.l ObjNull ; Obj4C
dc.l ObjNull ; Obj4D
dc.l ObjNull ; Obj4E
dc.l ObjNull ; Obj4F
ObjPtr_Aquis: dc.l Obj50 ; Aquis (seahorse badnik) from OOZ
ObjPtr_CNZBoss: dc.l Obj51 ; CNZ boss
ObjPtr_HTZBoss: dc.l Obj52 ; HTZ boss
ObjPtr_MTZBossOrb: dc.l Obj53 ; Shield orbs that surround MTZ boss
ObjPtr_MTZBoss: dc.l Obj54 ; MTZ boss
ObjPtr_OOZBoss: dc.l Obj55 ; OOZ boss
ObjPtr_EHZBoss: dc.l Obj56 ; EHZ boss
ObjPtr_MCZBoss: dc.l Obj57 ; MCZ boss
ObjPtr_BossExplosion: dc.l Obj58 ; Boss explosion
ObjPtr_SSEmerald: dc.l Obj59 ; Emerald from Special Stage
ObjPtr_SSMessage: dc.l Obj5A ; Messages/checkpoint from Special Stage
ObjPtr_SSRingSpill: dc.l Obj5B ; Ring spray/spill in Special Stage
ObjPtr_Masher: dc.l Obj5C ; Masher (jumping piranha fish badnik) from EHZ
ObjPtr_CPZBoss: dc.l Obj5D ; CPZ boss
ObjPtr_SSHUD: dc.l Obj5E ; HUD from Special Stage
ObjPtr_StartBanner:
ObjPtr_EndingController:dc.l Obj5F ; Start banner/"Ending controller" from Special Stage
ObjPtr_SSRing: dc.l Obj60 ; Rings from Special Stage
ObjPtr_SSBomb: dc.l Obj61 ; Bombs from Special Stage
dc.l ObjNull ; Obj62
ObjPtr_SSShadow: dc.l Obj63 ; Character shadow from Special Stage
ObjPtr_MTZTwinStompers: dc.l Obj64 ; Twin stompers from MTZ
ObjPtr_MTZLongPlatform: dc.l Obj65 ; Long moving platform from MTZ
ObjPtr_MTZSpringWall: dc.l Obj66 ; Yellow spring walls from MTZ
ObjPtr_MTZSpinTube: dc.l Obj67 ; Spin tube from MTZ
ObjPtr_SpikyBlock: dc.l Obj68 ; Block with a spike that comes out of each side sequentially from MTZ
ObjPtr_Nut: dc.l Obj69 ; Nut from MTZ
ObjPtr_MCZRotPforms:
ObjPtr_MTZMovingPforms: dc.l Obj6A ; Platform that moves when you walk off of it, from MTZ
ObjPtr_MTZPlatform:
ObjPtr_CPZSquarePform: dc.l Obj6B ; Immobile platform from MTZ
ObjPtr_Conveyor: dc.l Obj6C ; Small platform on pulleys (like at the start of MTZ2)
ObjPtr_FloorSpike: dc.l Obj6D ; Floor spike from MTZ
ObjPtr_LargeRotPform: dc.l Obj6E ; Platform moving in a circle (like at the start of MTZ3)
ObjPtr_SSResults: dc.l Obj6F ; End of special stage results screen
ObjPtr_Cog: dc.l Obj70 ; Giant rotating cog from MTZ
ObjPtr_MTZLavaBubble:
ObjPtr_HPZBridgeStake:
ObjPtr_PulsingOrb: dc.l Obj71 ; Bridge stake and pulsing orb from Hidden Palace Zone
ObjPtr_CNZConveyorBelt: dc.l Obj72 ; Conveyor belt from CNZ
ObjPtr_RotatingRings: dc.l Obj73 ; Solid rotating ring thing from Mystic Cave Zone (mostly unused)
ObjPtr_InvisibleBlock: dc.l Obj74 ; Invisible solid block
ObjPtr_MCZBrick: dc.l Obj75 ; Brick from MCZ
ObjPtr_SlidingSpikes: dc.l Obj76 ; Spike block that slides out of the wall from MCZ
ObjPtr_MCZBridge: dc.l Obj77 ; Bridge from MCZ
ObjPtr_CPZStaircase: dc.l Obj78 ; Stairs from CPZ that move down to open the way
ObjPtr_Starpost: dc.l Obj79 ; Star pole / starpost / checkpoint
ObjPtr_SidewaysPform: dc.l Obj7A ; Platform that moves back and fourth on top of water in CPZ
ObjPtr_PipeExitSpring: dc.l Obj7B ; Warp pipe exit spring from CPZ
ObjPtr_CPZPylon: dc.l Obj7C ; Big pylon in foreground of CPZ
dc.l Obj7D ; Points that can be gotten at the end of an act (unused leftover from S1)
ObjPtr_SuperSonicStars: dc.l Obj7E ; Super Sonic's stars
ObjPtr_VineSwitch: dc.l Obj7F ; Vine switch that you hang off in MCZ
ObjPtr_MovingVine: dc.l Obj80 ; Vine that you hang off and it moves down from MCZ
ObjPtr_MCZDrawbridge: dc.l Obj81 ; Long invisible vertical barrier
ObjPtr_SwingingPform: dc.l Obj82 ; Platform that is usually swinging, from ARZ
ObjPtr_ARZRotPforms: dc.l Obj83 ; 3 adjoined platforms from ARZ that rotate in a circle
ObjPtr_ForcedSpin:
ObjPtr_PinballMode: dc.l Obj84 ; Pinball mode enable/disable (CNZ)
ObjPtr_LauncherSpring: dc.l Obj85 ; Spring from CNZ that you hold jump on to pull back further
ObjPtr_Flipper: dc.l Obj86 ; Flipper from CNZ
ObjPtr_SSNumberOfRings: dc.l Obj87 ; Number of rings in Special Stage
ObjPtr_SSTailsTails: dc.l Obj88 ; Tails' tails in Special Stage
ObjPtr_ARZBoss: dc.l Obj89 ; ARZ boss
dc.l Obj8A ; Sonic Team Presents/Credits (seemingly unused leftover from S1)
ObjPtr_WFZPalSwitcher: dc.l Obj8B ; Cycling palette switcher from Wing Fortress Zone
ObjPtr_Whisp: dc.l Obj8C ; Whisp (blowfly badnik) from ARZ
ObjPtr_GrounderInWall: dc.l Obj8D ; Grounder in wall, from ARZ
ObjPtr_GrounderInWall2: dc.l Obj8D ; Obj8E = Obj8D
ObjPtr_GrounderWall: dc.l Obj8F ; Wall behind which Grounder hides, from ARZ
ObjPtr_GrounderRocks: dc.l Obj90 ; Rocks thrown by Grounder behind wall, from ARZ
ObjPtr_ChopChop: dc.l Obj91 ; Chop Chop (piranha/shark badnik) from ARZ
ObjPtr_Spiker: dc.l Obj92 ; Spiker (drill badnik) from HTZ
ObjPtr_SpikerDrill: dc.l Obj93 ; Drill thrown by Spiker from HTZ
ObjPtr_Rexon: dc.l Obj94 ; Rexon (lava snake badnik), from HTZ
ObjPtr_Sol: dc.l Obj95 ; Sol (fireball-throwing orbit badnik) from HTZ
ObjPtr_Rexon2: dc.l Obj94 ; Obj96 = Obj94
ObjPtr_RexonHead: dc.l Obj97 ; Rexon's head, from HTZ
ObjPtr_Projectile: dc.l Obj98 ; Projectile with optional gravity (EHZ coconut, CPZ spiny, etc.)
ObjPtr_Nebula: dc.l Obj99 ; Nebula (bomber badnik) from SCZ
ObjPtr_Turtloid: dc.l Obj9A ; Turtloid (turtle badnik) from Sky Chase Zone
ObjPtr_TurtloidRider: dc.l Obj9B ; Turtloid rider from Sky Chase Zone
ObjPtr_BalkiryJet: dc.l Obj9C ; Balkiry's jet from Sky Chase Zone
ObjPtr_Coconuts: dc.l Obj9D ; Coconuts (monkey badnik) from EHZ
ObjPtr_Crawlton: dc.l Obj9E ; Crawlton (snake badnik) from MCZ
ObjPtr_Shellcracker: dc.l Obj9F ; Shellcraker (crab badnik) from MTZ
ObjPtr_ShellcrackerClaw:dc.l ObjA0 ; Shellcracker's claw from MTZ
ObjPtr_Slicer: dc.l ObjA1 ; Slicer (praying mantis dude) from MTZ
ObjPtr_SlicerPincers: dc.l ObjA2 ; Slicer's pincers from MTZ
ObjPtr_Flasher: dc.l ObjA3 ; Flasher (firefly/glowbug badnik) from MCZ
ObjPtr_Asteron: dc.l ObjA4 ; Asteron (exploding starfish badnik) from MTZ
ObjPtr_Spiny: dc.l ObjA5 ; Spiny (crawling badnik) from CPZ
ObjPtr_SpinyOnWall: dc.l ObjA6 ; Spiny (on wall) from CPZ
ObjPtr_Grabber: dc.l ObjA7 ; Grabber (spider badnik) from CPZ
ObjPtr_GrabberLegs: dc.l ObjA8 ; Grabber's legs from CPZ
ObjPtr_GrabberBox: dc.l ObjA9 ; The little hanger box thing a Grabber's string comes out of
ObjPtr_GrabberString: dc.l ObjAA ; The thin white string a Grabber hangs from
dc.l ObjAB ; Unknown (maybe unused?)
ObjPtr_Balkiry: dc.l ObjAC ; Balkiry (jet badnik) from SCZ
ObjPtr_CluckerBase: dc.l ObjAD ; Clucker's base from WFZ
ObjPtr_Clucker: dc.l ObjAE ; Clucker (chicken badnik) from WFZ
ObjPtr_MechaSonic: dc.l ObjAF ; Mecha Sonic / Silver Sonic from DEZ
ObjPtr_SonicOnSegaScr: dc.l ObjB0 ; Sonic on the Sega screen
ObjPtr_SegaHideTM: dc.l ObjB1 ; Object that hides TM symbol on JP region
ObjPtr_Tornado: dc.l ObjB2 ; The Tornado (Tails' plane)
ObjPtr_Cloud: dc.l ObjB3 ; Clouds (placeable object) from SCZ
ObjPtr_VPropeller: dc.l ObjB4 ; Vertical propeller from WFZ
ObjPtr_HPropeller: dc.l ObjB5 ; Horizontal propeller from WFZ
ObjPtr_TiltingPlatform: dc.l ObjB6 ; Tilting platform from WFZ
ObjPtr_VerticalLaser: dc.l ObjB7 ; Unused huge vertical laser from WFZ
ObjPtr_WallTurret: dc.l ObjB8 ; Wall turret from WFZ
ObjPtr_Laser: dc.l ObjB9 ; Laser from WFZ that shoots down the Tornado
ObjPtr_WFZWheel: dc.l ObjBA ; Wheel from WFZ
dc.l ObjBB ; Unknown
ObjPtr_WFZShipFire: dc.l ObjBC ; Fire coming out of Robotnik's ship in WFZ
ObjPtr_SmallMetalPform: dc.l ObjBD ; Ascending/descending metal platforms from WFZ
ObjPtr_LateralCannon: dc.l ObjBE ; Lateral cannon (temporary platform that pops in/out) from WFZ
ObjPtr_WFZStick: dc.l ObjBF ; Rotaty-stick badnik from WFZ
ObjPtr_SpeedLauncher: dc.l ObjC0 ; Speed launcher from WFZ
ObjPtr_BreakablePlating:dc.l ObjC1 ; Breakable plating from WFZ / what sonic hangs onto on the back of Robotnic's getaway ship
ObjPtr_Rivet: dc.l ObjC2 ; Rivet thing you bust to get into ship at the end of WFZ
ObjPtr_TornadoSmoke: dc.l ObjC3 ; Plane's smoke from WFZ
ObjPtr_TornadoSmoke2: dc.l ObjC3 ; ObjC4 = ObjC3
ObjPtr_WFZBoss: dc.l ObjC5 ; WFZ boss
ObjPtr_Eggman: dc.l ObjC6 ; Eggman
ObjPtr_Eggrobo: dc.l ObjC7 ; Eggrobo (final boss) from Death Egg
ObjPtr_Crawl: dc.l ObjC8 ; Crawl (shield badnik) from CNZ
ObjPtr_TtlScrPalChanger:dc.l ObjC9 ; "Palette changing handler" from title screen
ObjPtr_CutScene: dc.l ObjCA ; Cut scene at end of game
ObjPtr_EndingSeqClouds: dc.l ObjCB ; Background clouds from ending sequence
ObjPtr_EndingSeqTrigger:dc.l ObjCC ; Trigger for rescue plane and birds from ending sequence
ObjPtr_EndingSeqBird: dc.l ObjCD ; Birds from ending sequence
ObjPtr_EndingSeqSonic:
ObjPtr_EndingSeqTails: dc.l ObjCE ; Sonic and Tails jumping off the plane from ending sequence
ObjPtr_TornadoHelixes: dc.l ObjCF ;"Plane's helixes" from ending sequence
dc.l ObjNull ; ObjD0
dc.l ObjNull ; ObjD1
ObjPtr_CNZRectBlocks: dc.l ObjD2 ; Flashing blocks that appear and disappear in a rectangular shape that you can walk across, from CNZ
ObjPtr_BombPrize: dc.l ObjD3 ; Bomb prize from CNZ
ObjPtr_CNZBigBlock: dc.l ObjD4 ; Big block from CNZ that moves back and fourth
ObjPtr_Elevator: dc.l ObjD5 ; Elevator from CNZ
ObjPtr_PointPokey: dc.l ObjD6 ; Pokey that gives out points from CNZ
ObjPtr_Bumper: dc.l ObjD7 ; Bumper from Casino Night Zone
ObjPtr_BonusBlock: dc.l ObjD8 ; Block thingy from CNZ that disappears after 3 hits
ObjPtr_Grab: dc.l ObjD9 ; Invisible sprite that you can hang on to, like the blocks in WFZ
ObjPtr_ContinueText:
ObjPtr_ContinueIcons: dc.l ObjDA ; Continue text
ObjPtr_ContinueChars: dc.l ObjDB ; Sonic lying down or Tails nagging (continue screen)
ObjPtr_RingPrize: dc.l ObjDC ; Ring prize from Casino Night Zone
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 4C, 4D, 4E, 4F, 62, D0, and D1
; Object removed from the game. All it does is deallocate its array.
; ----------------------------------------------------------------------------
ObjNull: ;;
bra.w DeleteObject
; ---------------------------------------------------------------------------
; Subroutine to make an object move and fall downward increasingly fast
; This moves the object horizontally and vertically
; and also applies gravity to its speed
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_16380: ObjectFall:
ObjectMoveAndFall:
move.l x_pos(a0),d2 ; load x position
move.l y_pos(a0),d3 ; load y position
move.w x_vel(a0),d0 ; load x speed
ext.l d0
asl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position
add.l d0,d2 ; add x speed to x position ; note this affects the subpixel position x_sub(a0) = 2+x_pos(a0)
move.w y_vel(a0),d0 ; load y speed
addi.w #$38,y_vel(a0) ; increase vertical speed (apply gravity)
ext.l d0
asl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position
add.l d0,d3 ; add old y speed to y position ; note this affects the subpixel position y_sub(a0) = 2+y_pos(a0)
move.l d2,x_pos(a0) ; store new x position
move.l d3,y_pos(a0) ; store new y position
rts
; End of function ObjectMoveAndFall
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; ---------------------------------------------------------------------------
; Subroutine translating object speed to update object position
; This moves the object horizontally and vertically
; but does not apply gravity to it
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_163AC: SpeedToPos:
ObjectMove:
move.l x_pos(a0),d2 ; load x position
move.l y_pos(a0),d3 ; load y position
move.w x_vel(a0),d0 ; load horizontal speed
ext.l d0
asl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position
add.l d0,d2 ; add to x-axis position ; note this affects the subpixel position x_sub(a0) = 2+x_pos(a0)
move.w y_vel(a0),d0 ; load vertical speed
ext.l d0
asl.l #8,d0 ; shift velocity to line up with the middle 16 bits of the 32-bit position
add.l d0,d3 ; add to y-axis position ; note this affects the subpixel position y_sub(a0) = 2+y_pos(a0)
move.l d2,x_pos(a0) ; update x-axis position
move.l d3,y_pos(a0) ; update y-axis position
rts
; End of function ObjectMove
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; ---------------------------------------------------------------------------
; Routines to mark an enemy/monitor/ring/platform as destroyed
; ---------------------------------------------------------------------------
; ===========================================================================
; input: a0 = the object
; loc_163D2:
MarkObjGone:
tst.w (Two_player_mode).w ; is it two player mode?
beq.s + ; if not, branch
bra.w DisplaySprite
+
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$80+320+$40+$80,d0 ; This gives an object $80 pixels of room offscreen before being unloaded (the $40 is there to round up 320 to a multiple of $80)
bhi.w +
bra.w DisplaySprite
+ lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s +
bclr #7,2(a2,d0.w)
+
bra.w DeleteObject
; ===========================================================================
; input: d0 = the object's x position
; loc_1640A:
MarkObjGone2:
tst.w (Two_player_mode).w
beq.s +
bra.w DisplaySprite
+
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$80+320+$40+$80,d0 ; This gives an object $80 pixels of room offscreen before being unloaded (the $40 is there to round up 320 to a multiple of $80)
bhi.w +
bra.w DisplaySprite
+
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s +
bclr #7,2(a2,d0.w)
+
bra.w DeleteObject
; ===========================================================================
; input: a0 = the object
; does nothing instead of calling DisplaySprite in the case of no deletion
; loc_1643E:
MarkObjGone3:
tst.w (Two_player_mode).w
beq.s +
rts
+
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$80+320+$40+$80,d0 ; This gives an object $80 pixels of room offscreen before being unloaded (the $40 is there to round up 320 to a multiple of $80)
bhi.w +
rts
+
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s +
bclr #7,2(a2,d0.w)
+
bra.w DeleteObject
; ===========================================================================
; input: a0 = the object
; loc_16472:
MarkObjGone_P1:
tst.w (Two_player_mode).w
bne.s MarkObjGone_P2
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$80+320+$40+$80,d0 ; This gives an object $80 pixels of room offscreen before being unloaded (the $40 is there to round up 320 to a multiple of $80)
bhi.w +
bra.w DisplaySprite
+
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s +
bclr #7,2(a2,d0.w)
+
bra.w DeleteObject
; ---------------------------------------------------------------------------
; input: a0 = the object
; loc_164A6:
MarkObjGone_P2:
move.w x_pos(a0),d0
andi.w #$FF00,d0
move.w d0,d1
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$300,d0
bhi.w +
bra.w DisplaySprite
+
sub.w (Camera_X_pos_coarse_P2).w,d1
cmpi.w #$300,d1
bhi.w +
bra.w DisplaySprite
+
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s +
bclr #7,2(a2,d0.w)
+
bra.w DeleteObject ; useless branch...
; ---------------------------------------------------------------------------
; Subroutine to delete an object
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; freeObject:
DeleteObject:
movea.l a0,a1
; sub_164E8:
DeleteObject2:
moveq #0,d1
moveq #bytesToLcnt(next_object),d0 ; we want to clear up to the next object
; delete the object by setting all of its bytes to 0
- move.l d1,(a1)+
dbf d0,-
if object_size&3
move.w d1,(a1)+
endif
rts
; End of function DeleteObject2
; ---------------------------------------------------------------------------
; Subroutine to display a sprite/object, when a0 is the object RAM
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_164F4:
DisplaySprite:
lea (Sprite_Table_Input).w,a1
move.w priority(a0),d0
lsr.w #1,d0
andi.w #$380,d0
adda.w d0,a1
cmpi.w #$7E,(a1)
bhs.s return_16510
addq.w #2,(a1)
adda.w (a1),a1
move.w a0,(a1)
return_16510:
rts
; End of function DisplaySprite
; ---------------------------------------------------------------------------
; Subroutine to display a sprite/object, when a1 is the object RAM
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_16512:
DisplaySprite2:
lea (Sprite_Table_Input).w,a2
move.w priority(a1),d0
lsr.w #1,d0
andi.w #$380,d0
adda.w d0,a2
cmpi.w #$7E,(a2)
bhs.s return_1652E
addq.w #2,(a2)
adda.w (a2),a2
move.w a1,(a2)
return_1652E:
rts
; End of function DisplaySprite2
; ---------------------------------------------------------------------------
; Subroutine to display a sprite/object, when a0 is the object RAM
; and d0 is already (priority/2)&$380
; ---------------------------------------------------------------------------
; loc_16530:
DisplaySprite3:
lea (Sprite_Table_Input).w,a1
adda.w d0,a1
cmpi.w #$7E,(a1)
bhs.s return_16542
addq.w #2,(a1)
adda.w (a1),a1
move.w a0,(a1)
return_16542:
rts
; ---------------------------------------------------------------------------
; Subroutine to animate a sprite using an animation script
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_16544:
AnimateSprite:
moveq #0,d0
move.b anim(a0),d0 ; move animation number to d0
cmp.b next_anim(a0),d0 ; is animation set to change?
beq.s Anim_Run ; if not, branch
move.b d0,next_anim(a0) ; set next anim to current current
move.b #0,anim_frame(a0) ; reset animation
move.b #0,anim_frame_duration(a0) ; reset frame duration
; loc_16560:
Anim_Run:
subq.b #1,anim_frame_duration(a0) ; subtract 1 from frame duration
bpl.s Anim_Wait ; if time remains, branch
add.w d0,d0
adda.w (a1,d0.w),a1 ; calculate address of appropriate animation script
move.b (a1),anim_frame_duration(a0) ; load frame duration
moveq #0,d1
move.b anim_frame(a0),d1 ; load current frame number
move.b 1(a1,d1.w),d0 ; read sprite number from script
bmi.s Anim_End_FF ; if animation is complete, branch
; loc_1657C:
Anim_Next:
andi.b #$7F,d0 ; clear sign bit
move.b d0,mapping_frame(a0) ; load sprite number
move.b status(a0),d1 ;* match the orientaion dictated by the object
andi.b #3,d1 ;* with the orientation used by the object engine
andi.b #$FC,render_flags(a0) ;*
or.b d1,render_flags(a0) ;*
addq.b #1,anim_frame(a0) ; next frame number
; return_1659A:
Anim_Wait:
rts
; ===========================================================================
; loc_1659C:
Anim_End_FF:
addq.b #1,d0 ; is the end flag = $FF ?
bne.s Anim_End_FE ; if not, branch
move.b #0,anim_frame(a0) ; restart the animation
move.b 1(a1),d0 ; read sprite number
bra.s Anim_Next
; ===========================================================================
; loc_165AC:
Anim_End_FE:
addq.b #1,d0 ; is the end flag = $FE ?
bne.s Anim_End_FD ; if not, branch
move.b 2(a1,d1.w),d0 ; read the next byte in the script
sub.b d0,anim_frame(a0) ; jump back d0 bytes in the script
sub.b d0,d1
move.b 1(a1,d1.w),d0 ; read sprite number
bra.s Anim_Next
; ===========================================================================
; loc_165C0:
Anim_End_FD:
addq.b #1,d0 ; is the end flag = $FD ?
bne.s Anim_End_FC ; if not, branch
move.b 2(a1,d1.w),anim(a0) ; read next byte, run that animation
rts
; ===========================================================================
; loc_165CC:
Anim_End_FC:
addq.b #1,d0 ; is the end flag = $FC ?
bne.s Anim_End_FB ; if not, branch
addq.b #2,routine(a0) ; jump to next routine
move.b #0,anim_frame_duration(a0)
addq.b #1,anim_frame(a0)
rts
; ===========================================================================
; loc_165E0:
Anim_End_FB:
addq.b #1,d0 ; is the end flag = $FB ?
bne.s Anim_End_FA ; if not, branch
move.b #0,anim_frame(a0) ; reset animation
clr.b routine_secondary(a0) ; reset 2nd routine counter
rts
; ===========================================================================
; loc_165F0:
Anim_End_FA:
addq.b #1,d0 ; is the end flag = $FA ?
bne.s Anim_End_F9 ; if not, branch
addq.b #2,routine_secondary(a0) ; jump to next routine
rts
; ===========================================================================
; loc_165FA:
Anim_End_F9:
addq.b #1,d0 ; is the end flag = $F9 ?
bne.s Anim_End ; if not, branch
addq.b #2,objoff_2A(a0)
; return_16602:
Anim_End:
rts
; End of function AnimateSprite
; ---------------------------------------------------------------------------
; Subroutine to convert mappings (etc) to proper Megadrive sprites
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_16604:
BuildSprites:
tst.w (Two_player_mode).w
bne.w BuildSprites_2P
lea (Sprite_Table).w,a2
moveq #0,d5
moveq #0,d4
tst.b (Level_started_flag).w
beq.s +
jsrto (BuildHUD).l, JmpTo_BuildHUD
bsr.w BuildRings
+
lea (Sprite_Table_Input).w,a4
moveq #7,d7 ; 8 priority levels
; loc_16628:
BuildSprites_LevelLoop:
tst.w (a4) ; does this level have any objects?
beq.w BuildSprites_NextLevel ; if not, check the next one
moveq #2,d6
; loc_16630:
BuildSprites_ObjLoop:
movea.w (a4,d6.w),a0 ; a0=object
if gameRevision=0
; the additional check prevents a crash triggered by placing an object in debug mode while dead
; unfortunately, the code it branches *to* causes a crash of its own
tst.b id(a0) ; is this object slot occupied?
beq.w BuildSprites_Unknown ; if not, branch
tst.l mappings(a0) ; does this object have any mappings?
beq.w BuildSprites_Unknown ; if not, branch
else
; REV01 uses a better branch, but removed the useful check
tst.b id(a0) ; is this object slot occupied?
beq.w BuildSprites_NextObj ; if not, check next one
endif
andi.b #$7F,render_flags(a0) ; clear on-screen flag
move.b render_flags(a0),d0
move.b d0,d4
btst #6,d0 ; is the multi-draw flag set?
bne.w BuildSprites_MultiDraw ; if it is, branch
andi.w #$C,d0 ; is this to be positioned by screen coordinates?
beq.s BuildSprites_ScreenSpaceObj ; if it is, branch
lea (Camera_X_pos_copy).w,a1
moveq #0,d0
move.b width_pixels(a0),d0
move.w x_pos(a0),d3
sub.w (a1),d3
move.w d3,d1
add.w d0,d1 ; is the object right edge to the left of the screen?
bmi.w BuildSprites_NextObj ; if it is, branch
move.w d3,d1
sub.w d0,d1
cmpi.w #320,d1 ; is the object left edge to the right of the screen?
bge.w BuildSprites_NextObj ; if it is, branch
addi.w #128,d3
btst #4,d4 ; is the accurate Y check flag set?
beq.s BuildSprites_ApproxYCheck ; if not, branch
moveq #0,d0
move.b y_radius(a0),d0
move.w y_pos(a0),d2
sub.w 4(a1),d2
move.w d2,d1
add.w d0,d1
bmi.s BuildSprites_NextObj ; if the object is above the screen
move.w d2,d1
sub.w d0,d1
cmpi.w #224,d1
bge.s BuildSprites_NextObj ; if the object is below the screen
addi.w #128,d2
bra.s BuildSprites_DrawSprite
; ===========================================================================
; loc_166A6:
BuildSprites_ScreenSpaceObj:
move.w y_pixel(a0),d2
move.w x_pixel(a0),d3
bra.s BuildSprites_DrawSprite
; ===========================================================================
; loc_166B0:
BuildSprites_ApproxYCheck:
move.w y_pos(a0),d2
sub.w 4(a1),d2
addi.w #128,d2
andi.w #$7FF,d2
cmpi.w #-32+128,d2 ; assume Y radius to be 32 pixels
blo.s BuildSprites_NextObj
cmpi.w #32+128+224,d2
bhs.s BuildSprites_NextObj
; loc_166CC:
BuildSprites_DrawSprite:
movea.l mappings(a0),a1
moveq #0,d1
btst #5,d4 ; is the static mappings flag set?
bne.s + ; if it is, branch
move.b mapping_frame(a0),d1
add.w d1,d1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1 ; get number of pieces
bmi.s ++ ; if there are 0 pieces, branch
+
bsr.w DrawSprite ; draw the sprite
+
ori.b #$80,render_flags(a0) ; set on-screen flag
; loc_166F2:
BuildSprites_NextObj:
addq.w #2,d6 ; load next object
subq.w #2,(a4) ; decrement object count
bne.w BuildSprites_ObjLoop ; if there are objects left, repeat
; loc_166FA:
BuildSprites_NextLevel:
lea $80(a4),a4 ; load next priority level
dbf d7,BuildSprites_LevelLoop ; loop
move.b d5,(Sprite_count).w
cmpi.b #80,d5 ; was the sprite limit reached?
beq.s + ; if it was, branch
move.l #0,(a2) ; set link field to 0
rts
+
move.b #0,-5(a2) ; set link field to 0
rts
; ===========================================================================
if gameRevision=0
BuildSprites_Unknown:
; in the Simon Wai beta, this was a simple BranchTo, but later builds have this mystery line
move.w (1).w,d0 ; causes a crash on hardware because of the word operation at an odd address
bra.s BuildSprites_NextObj
endif
; loc_1671C:
BuildSprites_MultiDraw:
move.l a4,-(sp)
lea (Camera_X_pos).w,a4
movea.w art_tile(a0),a3
movea.l mappings(a0),a5
moveq #0,d0
; check if object is within X bounds
move.b mainspr_width(a0),d0 ; load pixel width
move.w x_pos(a0),d3
sub.w (a4),d3
move.w d3,d1
add.w d0,d1
bmi.w BuildSprites_MultiDraw_NextObj
move.w d3,d1
sub.w d0,d1
cmpi.w #320,d1
bge.w BuildSprites_MultiDraw_NextObj
addi.w #128,d3
; check if object is within Y bounds
btst #4,d4
beq.s +
moveq #0,d0
move.b mainspr_height(a0),d0 ; load pixel height
move.w y_pos(a0),d2
sub.w 4(a4),d2
move.w d2,d1
add.w d0,d1
bmi.w BuildSprites_MultiDraw_NextObj
move.w d2,d1
sub.w d0,d1
cmpi.w #224,d1
bge.w BuildSprites_MultiDraw_NextObj
addi.w #128,d2
bra.s ++
+
move.w y_pos(a0),d2
sub.w 4(a4),d2
addi.w #128,d2
andi.w #$7FF,d2
cmpi.w #-32+128,d2
blo.s BuildSprites_MultiDraw_NextObj
cmpi.w #32+128+224,d2
bhs.s BuildSprites_MultiDraw_NextObj
+
moveq #0,d1
move.b mainspr_mapframe(a0),d1 ; get current frame
beq.s +
add.w d1,d1
movea.l a5,a1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
bmi.s +
move.w d4,-(sp)
bsr.w ChkDrawSprite ; draw the sprite
move.w (sp)+,d4
+
ori.b #$80,render_flags(a0) ; set onscreen flag
lea sub2_x_pos(a0),a6
moveq #0,d0
move.b mainspr_childsprites(a0),d0 ; get child sprite count
subq.w #1,d0 ; if there are 0, go to next object
bcs.s BuildSprites_MultiDraw_NextObj
- swap d0
move.w (a6)+,d3 ; get X pos
sub.w (a4),d3
addi.w #128,d3
move.w (a6)+,d2 ; get Y pos
sub.w 4(a4),d2
addi.w #128,d2
andi.w #$7FF,d2
addq.w #1,a6
moveq #0,d1
move.b (a6)+,d1 ; get mapping frame
add.w d1,d1
movea.l a5,a1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
bmi.s +
move.w d4,-(sp)
bsr.w ChkDrawSprite
move.w (sp)+,d4
+
swap d0
dbf d0,- ; repeat for number of child sprites
; loc_16804:
BuildSprites_MultiDraw_NextObj:
movea.l (sp)+,a4
bra.w BuildSprites_NextObj
; End of function BuildSprites
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_1680A:
ChkDrawSprite:
cmpi.b #80,d5 ; has the sprite limit been reached?
blo.s DrawSprite_Cont ; if it hasn't, branch
rts ; otherwise, return
; End of function ChkDrawSprite
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_16812:
DrawSprite:
movea.w art_tile(a0),a3
cmpi.b #80,d5
bhs.s DrawSprite_Done
; loc_1681C:
DrawSprite_Cont:
btst #0,d4 ; is the sprite to be X-flipped?
bne.s DrawSprite_FlipX ; if it is, branch
btst #1,d4 ; is the sprite to be Y-flipped?
bne.w DrawSprite_FlipY ; if it is, branch
; loc__1682A:
DrawSprite_Loop:
move.b (a1)+,d0
ext.w d0
add.w d2,d0
move.w d0,(a2)+ ; set Y pos
move.b (a1)+,(a2)+ ; set sprite size
addq.b #1,d5
move.b d5,(a2)+ ; set link field
move.w (a1)+,d0
add.w a3,d0
move.w d0,(a2)+ ; set art tile and flags
addq.w #2,a1
move.w (a1)+,d0
add.w d3,d0
andi.w #$1FF,d0
bne.s +
addq.w #1,d0 ; avoid activating sprite masking
+
move.w d0,(a2)+ ; set X pos
dbf d1,DrawSprite_Loop ; repeat for next sprite
; return_16852:
DrawSprite_Done:
rts
; ===========================================================================
; loc_16854:
DrawSprite_FlipX:
btst #1,d4 ; is it to be Y-flipped as well?
bne.w DrawSprite_FlipXY ; if it is, branch
- move.b (a1)+,d0
ext.w d0
add.w d2,d0
move.w d0,(a2)+
move.b (a1)+,d4 ; store size for later use
move.b d4,(a2)+
addq.b #1,d5
move.b d5,(a2)+
move.w (a1)+,d0
add.w a3,d0
eori.w #$800,d0 ; toggle X flip flag
move.w d0,(a2)+
addq.w #2,a1
move.w (a1)+,d0
neg.w d0 ; negate X offset
move.b CellOffsets_XFlip(pc,d4.w),d4
sub.w d4,d0 ; subtract sprite size
add.w d3,d0
andi.w #$1FF,d0
bne.s +
addq.w #1,d0
+
move.w d0,(a2)+
dbf d1,-
rts
; ===========================================================================
; offsets for horizontally mirrored sprite pieces
CellOffsets_XFlip:
dc.b 8, 8, 8, 8 ; 4
dc.b $10,$10,$10,$10 ; 8
dc.b $18,$18,$18,$18 ; 12
dc.b $20,$20,$20,$20 ; 16
; offsets for vertically mirrored sprite pieces
CellOffsets_YFlip:
dc.b 8,$10,$18,$20 ; 4
dc.b 8,$10,$18,$20 ; 8
dc.b 8,$10,$18,$20 ; 12
dc.b 8,$10,$18,$20 ; 16
; ===========================================================================
; loc_168B4:
DrawSprite_FlipY:
move.b (a1)+,d0
move.b (a1),d4
ext.w d0
neg.w d0
move.b CellOffsets_YFlip(pc,d4.w),d4
sub.w d4,d0
add.w d2,d0
move.w d0,(a2)+ ; set Y pos
move.b (a1)+,(a2)+ ; set size
addq.b #1,d5
move.b d5,(a2)+ ; set link field
move.w (a1)+,d0
add.w a3,d0
eori.w #$1000,d0 ; toggle Y flip flag
move.w d0,(a2)+ ; set art tile and flags
addq.w #2,a1
move.w (a1)+,d0
add.w d3,d0
andi.w #$1FF,d0
bne.s +
addq.w #1,d0
+
move.w d0,(a2)+ ; set X pos
dbf d1,DrawSprite_FlipY
rts
; ===========================================================================
; offsets for vertically mirrored sprite pieces
CellOffsets_YFlip2:
dc.b 8,$10,$18,$20 ; 4
dc.b 8,$10,$18,$20 ; 8
dc.b 8,$10,$18,$20 ; 12
dc.b 8,$10,$18,$20 ; 16
; ===========================================================================
; loc_168FC:
DrawSprite_FlipXY:
move.b (a1)+,d0
move.b (a1),d4
ext.w d0
neg.w d0
move.b CellOffsets_YFlip2(pc,d4.w),d4
sub.w d4,d0
add.w d2,d0
move.w d0,(a2)+
move.b (a1)+,d4
move.b d4,(a2)+
addq.b #1,d5
move.b d5,(a2)+
move.w (a1)+,d0
add.w a3,d0
eori.w #$1800,d0 ; toggle X and Y flip flags
move.w d0,(a2)+
addq.w #2,a1
move.w (a1)+,d0
neg.w d0
move.b CellOffsets_XFlip2(pc,d4.w),d4
sub.w d4,d0
add.w d3,d0
andi.w #$1FF,d0
bne.s +
addq.w #1,d0
+
move.w d0,(a2)+
dbf d1,DrawSprite_FlipXY
rts
; End of function DrawSprite
; ===========================================================================
; offsets for horizontally mirrored sprite pieces
CellOffsets_XFlip2:
dc.b 8, 8, 8, 8 ; 4
dc.b $10,$10,$10,$10 ; 8
dc.b $18,$18,$18,$18 ; 12
dc.b $20,$20,$20,$20 ; 16
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to convert mappings (etc) to proper Megadrive sprites
; for 2-player (split screen) mode
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1694E:
BuildSprites_2P:
lea (Sprite_Table).w,a2
moveq #2,d5
moveq #0,d4
move.l #$1D80F01,(a2)+ ; mask all sprites
move.l #1,(a2)+
move.l #$1D80F02,(a2)+ ; from 216px to 248px
move.l #0,(a2)+
tst.b (Level_started_flag).w
beq.s +
jsrto (BuildHUD_P1).l, JmpTo_BuildHUD_P1
bsr.w BuildRings_P1
+
lea (Sprite_Table_Input).w,a4
moveq #7,d7
; loc_16982:
BuildSprites_P1_LevelLoop:
move.w (a4),d0 ; does this priority level have any objects?
beq.w BuildSprites_P1_NextLevel ; if not, check next one
move.w d0,-(sp)
moveq #2,d6
; loc_1698C:
BuildSprites_P1_ObjLoop:
movea.w (a4,d6.w),a0 ; a0=object
tst.b id(a0)
beq.w BuildSprites_P1_NextObj
andi.b #$7F,render_flags(a0)
move.b render_flags(a0),d0
move.b d0,d4
btst #6,d0
bne.w BuildSprites_P1_MultiDraw
andi.w #$C,d0
beq.s BuildSprites_P1_ScreenSpaceObj
lea (Camera_X_pos).w,a1
moveq #0,d0
move.b width_pixels(a0),d0
move.w x_pos(a0),d3
sub.w (a1),d3
move.w d3,d1
add.w d0,d1
bmi.w BuildSprites_P1_NextObj
move.w d3,d1
sub.w d0,d1
cmpi.w #320,d1
bge.s BuildSprites_P1_NextObj
addi.w #128,d3
btst #4,d4
beq.s BuildSprites_P1_ApproxYCheck
moveq #0,d0
move.b y_radius(a0),d0
move.w y_pos(a0),d2
sub.w 4(a1),d2
move.w d2,d1
add.w d0,d1
bmi.s BuildSprites_P1_NextObj
move.w d2,d1
sub.w d0,d1
cmpi.w #224,d1
bge.s BuildSprites_P1_NextObj
addi.w #256,d2
bra.s BuildSprites_P1_DrawSprite
; ===========================================================================
; loc_16A00:
BuildSprites_P1_ScreenSpaceObj:
move.w y_pixel(a0),d2
move.w x_pixel(a0),d3
addi.w #128,d2
bra.s BuildSprites_P1_DrawSprite
; ===========================================================================
; loc_16A0E:
BuildSprites_P1_ApproxYCheck:
move.w y_pos(a0),d2
sub.w 4(a1),d2
addi.w #128,d2
cmpi.w #-32+128,d2
blo.s BuildSprites_P1_NextObj
cmpi.w #32+128+224,d2
bhs.s BuildSprites_P1_NextObj
addi.w #128,d2
; loc_16A2A:
BuildSprites_P1_DrawSprite:
movea.l mappings(a0),a1
moveq #0,d1
btst #5,d4
bne.s +
move.b mapping_frame(a0),d1
add.w d1,d1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
bmi.s ++
+
bsr.w DrawSprite_2P
+
ori.b #$80,render_flags(a0)
; loc_16A50:
BuildSprites_P1_NextObj:
addq.w #2,d6
subq.w #2,(sp)
bne.w BuildSprites_P1_ObjLoop
addq.w #2,sp
; loc_16A5A:
BuildSprites_P1_NextLevel:
lea $80(a4),a4
dbf d7,BuildSprites_P1_LevelLoop
move.b d5,(Sprite_count).w
cmpi.b #80,d5
bhs.s +
move.l #0,(a2)
bra.s BuildSprites_P2
+
move.b #0,-5(a2)
; build sprites for player 2
; loc_16A7A:
BuildSprites_P2:
tst.w (Hint_flag).w ; has H-int occured yet?
bne.s BuildSprites_P2 ; if not, wait
lea (Sprite_Table_2).w,a2
moveq #0,d5
moveq #0,d4
tst.b (Level_started_flag).w
beq.s +
jsrto (BuildHUD_P2).l, JmpTo_BuildHUD_P2
bsr.w BuildRings_P2
+
lea (Sprite_Table_Input).w,a4
moveq #7,d7
; loc_16A9C:
BuildSprites_P2_LevelLoop:
move.w (a4),d0
beq.w BuildSprites_P2_NextLevel
move.w d0,-(sp)
moveq #2,d6
; loc_16AA6:
BuildSprites_P2_ObjLoop:
movea.w (a4,d6.w),a0 ; a0=object
tst.b id(a0)
beq.w BuildSprites_P2_NextObj
move.b render_flags(a0),d0
move.b d0,d4
btst #6,d0
bne.w BuildSprites_P2_MultiDraw
andi.w #$C,d0
beq.s BuildSprites_P2_ScreenSpaceObj
lea (Camera_X_pos_P2).w,a1
moveq #0,d0
move.b width_pixels(a0),d0
move.w x_pos(a0),d3
sub.w (a1),d3
move.w d3,d1
add.w d0,d1
bmi.w BuildSprites_P2_NextObj
move.w d3,d1
sub.w d0,d1
cmpi.w #320,d1
bge.s BuildSprites_P2_NextObj
addi.w #128,d3
btst #4,d4
beq.s BuildSprites_P2_ApproxYCheck
moveq #0,d0
move.b y_radius(a0),d0
move.w y_pos(a0),d2
sub.w 4(a1),d2
move.w d2,d1
add.w d0,d1
bmi.s BuildSprites_P2_NextObj
move.w d2,d1
sub.w d0,d1
cmpi.w #224,d1
bge.s BuildSprites_P2_NextObj
addi.w #256+224,d2
bra.s BuildSprites_P2_DrawSprite
; ===========================================================================
; loc_16B14:
BuildSprites_P2_ScreenSpaceObj:
move.w y_pixel(a0),d2
move.w x_pixel(a0),d3
addi.w #$160,d2
bra.s BuildSprites_P2_DrawSprite
; ===========================================================================
; loc_16B22:
BuildSprites_P2_ApproxYCheck:
move.w y_pos(a0),d2
sub.w 4(a1),d2
addi.w #128,d2
cmpi.w #-32+128,d2
blo.s BuildSprites_P2_NextObj
cmpi.w #32+128+224,d2
bhs.s BuildSprites_P2_NextObj
addi.w #128+224,d2
; loc_16B3E:
BuildSprites_P2_DrawSprite:
movea.l mappings(a0),a1
moveq #0,d1
btst #5,d4
bne.s +
move.b mapping_frame(a0),d1
add.w d1,d1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
bmi.s ++
+
bsr.w DrawSprite_2P
+
ori.b #$80,render_flags(a0)
; loc_16B64:
BuildSprites_P2_NextObj:
addq.w #2,d6
subq.w #2,(sp)
bne.w BuildSprites_P2_ObjLoop
addq.w #2,sp
tst.b (Teleport_flag).w
bne.s BuildSprites_P2_NextLevel
move.w #0,(a4)
; loc_16B78:
BuildSprites_P2_NextLevel:
lea $80(a4),a4
dbf d7,BuildSprites_P2_LevelLoop
move.b d5,(Sprite_count).w
cmpi.b #80,d5
beq.s +
move.l #0,(a2)
rts
+
move.b #0,-5(a2)
rts
; ===========================================================================
; loc_16B9A:
BuildSprites_P1_MultiDraw:
move.l a4,-(sp)
lea (Camera_X_pos).w,a4
movea.w art_tile(a0),a3
movea.l mappings(a0),a5
moveq #0,d0
move.b mainspr_width(a0),d0
move.w x_pos(a0),d3
sub.w (a4),d3
move.w d3,d1
add.w d0,d1
bmi.w BuildSprites_P1_MultiDraw_NextObj
move.w d3,d1
sub.w d0,d1
cmpi.w #320,d1
bge.w BuildSprites_P1_MultiDraw_NextObj
addi.w #128,d3
btst #4,d4
beq.s +
moveq #0,d0
move.b mainspr_height(a0),d0
move.w y_pos(a0),d2
sub.w 4(a4),d2
move.w d2,d1
add.w d0,d1
bmi.w BuildSprites_P1_MultiDraw_NextObj
move.w d2,d1
sub.w d0,d1
cmpi.w #224,d1
bge.w BuildSprites_P1_MultiDraw_NextObj
addi.w #256,d2
bra.s ++
+
move.w y_pos(a0),d2
sub.w 4(a4),d2
addi.w #128,d2
cmpi.w #-32+128,d2
blo.s BuildSprites_P1_MultiDraw_NextObj
cmpi.w #32+128+224,d2
bhs.s BuildSprites_P1_MultiDraw_NextObj
addi.w #128,d2
+
moveq #0,d1
move.b mainspr_mapframe(a0),d1
beq.s +
add.w d1,d1
movea.l a5,a1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
bmi.s +
move.w d4,-(sp)
bsr.w ChkDrawSprite_2P
move.w (sp)+,d4
+
ori.b #$80,render_flags(a0)
lea sub2_x_pos(a0),a6
moveq #0,d0
move.b mainspr_childsprites(a0),d0
subq.w #1,d0
bcs.s BuildSprites_P1_MultiDraw_NextObj
- swap d0
move.w (a6)+,d3
sub.w (a4),d3
addi.w #128,d3
move.w (a6)+,d2
sub.w 4(a4),d2
addi.w #256,d2
addq.w #1,a6
moveq #0,d1
move.b (a6)+,d1
add.w d1,d1
movea.l a5,a1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
bmi.s +
move.w d4,-(sp)
bsr.w ChkDrawSprite_2P
move.w (sp)+,d4
+
swap d0
dbf d0,-
; loc_16C7E:
BuildSprites_P1_MultiDraw_NextObj:
movea.l (sp)+,a4
bra.w BuildSprites_P1_NextObj
; ===========================================================================
; loc_16C84:
BuildSprites_P2_MultiDraw:
move.l a4,-(sp)
lea (Camera_X_pos_P2).w,a4
movea.w art_tile(a0),a3
movea.l mappings(a0),a5
moveq #0,d0
move.b mainspr_width(a0),d0
move.w x_pos(a0),d3
sub.w (a4),d3
move.w d3,d1
add.w d0,d1
bmi.w BuildSprites_P2_MultiDraw_NextObj
move.w d3,d1
sub.w d0,d1
cmpi.w #320,d1
bge.w BuildSprites_P2_MultiDraw_NextObj
addi.w #128,d3
btst #4,d4
beq.s +
moveq #0,d0
move.b mainspr_height(a0),d0
move.w y_pos(a0),d2
sub.w 4(a4),d2
move.w d2,d1
add.w d0,d1
bmi.w BuildSprites_P2_MultiDraw_NextObj
move.w d2,d1
sub.w d0,d1
cmpi.w #224,d1
bge.w BuildSprites_P2_MultiDraw_NextObj
addi.w #256+224,d2
bra.s ++
+
move.w y_pos(a0),d2
sub.w 4(a4),d2
addi.w #128,d2
cmpi.w #-32+128,d2
blo.s BuildSprites_P2_MultiDraw_NextObj
cmpi.w #32+128+224,d2
bhs.s BuildSprites_P2_MultiDraw_NextObj
addi.w #128+224,d2
+
moveq #0,d1
move.b mainspr_mapframe(a0),d1
beq.s +
add.w d1,d1
movea.l a5,a1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
bmi.s +
move.w d4,-(sp)
bsr.w ChkDrawSprite_2P
move.w (sp)+,d4
+
ori.b #$80,render_flags(a0)
lea sub2_x_pos(a0),a6
moveq #0,d0
move.b mainspr_childsprites(a0),d0
subq.w #1,d0
bcs.s BuildSprites_P2_MultiDraw_NextObj
- swap d0
move.w (a6)+,d3
sub.w (a4),d3
addi.w #128,d3
move.w (a6)+,d2
sub.w 4(a4),d2
addi.w #256+224,d2
addq.w #1,a6
moveq #0,d1
move.b (a6)+,d1
add.w d1,d1
movea.l a5,a1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
bmi.s +
move.w d4,-(sp)
bsr.w ChkDrawSprite_2P
move.w (sp)+,d4
+
swap d0
dbf d0,-
; loc_16D68:
BuildSprites_P2_MultiDraw_NextObj:
movea.l (sp)+,a4
bra.w BuildSprites_P2_NextObj
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; adjust art pointer of object at a0 for 2-player mode
; sub_16D6E:
Adjust2PArtPointer:
tst.w (Two_player_mode).w
beq.s + ; rts
move.w art_tile(a0),d0
andi.w #tile_mask,d0
lsr.w #1,d0
andi.w #nontile_mask,art_tile(a0)
add.w d0,art_tile(a0)
+
rts
; End of function Adjust2PArtPointer
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; adjust art pointer of object at a1 for 2-player mode
; sub_16D8A:
Adjust2PArtPointer2:
tst.w (Two_player_mode).w
beq.s + ; rts
move.w art_tile(a1),d0
andi.w #tile_mask,d0
lsr.w #1,d0
andi.w #nontile_mask,art_tile(a1)
add.w d0,art_tile(a1)
+
rts
; End of function Adjust2PArtPointer2
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_16DA6:
ChkDrawSprite_2P:
cmpi.b #80,d5
blo.s DrawSprite_2P_Loop
rts
; End of function ChkDrawSprite_2P
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; copy sprite art to VRAM, in 2-player mode
; sub_16DAE:
DrawSprite_2P:
movea.w art_tile(a0),a3
cmpi.b #80,d5
bhs.s DrawSprite_2P_Done
btst #0,d4
bne.s DrawSprite_2P_FlipX
btst #1,d4
bne.w DrawSprite_2P_FlipY
; loc_16DC6:
DrawSprite_2P_Loop:
move.b (a1)+,d0
ext.w d0
add.w d2,d0
move.w d0,(a2)+
move.b (a1)+,d4
move.b SpriteSizes_2P(pc,d4.w),(a2)+
addq.b #1,d5
move.b d5,(a2)+
addq.w #2,a1
move.w (a1)+,d0
add.w a3,d0
move.w d0,(a2)+
move.w (a1)+,d0
add.w d3,d0
andi.w #$1FF,d0
bne.s +
addq.w #1,d0
+
move.w d0,(a2)+
dbf d1,DrawSprite_2P_Loop
; return_16DF2:
DrawSprite_2P_Done:
rts
; ===========================================================================
; cells are double the height in 2P mode, so halve the number of rows
;byte_16DF4:
SpriteSizes_2P:
dc.b 0,0
dc.b 1,1
dc.b 4,4
dc.b 5,5
dc.b 8,8
dc.b 9,9
dc.b $C,$C
dc.b $D,$D
; ===========================================================================
; loc_16E04:
DrawSprite_2P_FlipX:
btst #1,d4
bne.w DrawSprite_2P_FlipXY
- move.b (a1)+,d0
ext.w d0
add.w d2,d0
move.w d0,(a2)+
move.b (a1)+,d4
move.b SpriteSizes_2P(pc,d4.w),(a2)+
addq.b #1,d5
move.b d5,(a2)+
addq.w #2,a1
move.w (a1)+,d0
add.w a3,d0
eori.w #$800,d0
move.w d0,(a2)+
move.w (a1)+,d0
neg.w d0
move.b byte_16E46(pc,d4.w),d4
sub.w d4,d0
add.w d3,d0
andi.w #$1FF,d0
bne.s +
addq.w #1,d0
+
move.w d0,(a2)+
dbf d1,-
rts
; ===========================================================================
; offsets for horizontally mirrored sprite pieces (2P)
byte_16E46:
dc.b 8, 8, 8, 8 ; 4
dc.b $10,$10,$10,$10 ; 8
dc.b $18,$18,$18,$18 ; 12
dc.b $20,$20,$20,$20 ; 16
; offsets for vertically mirrored sprite pieces (2P)
byte_16E56:
dc.b 8,$10,$18,$20 ; 4
dc.b 8,$10,$18,$20 ; 8
dc.b 8,$10,$18,$20 ; 12
dc.b 8,$10,$18,$20 ; 16
; ===========================================================================
; loc_16E66:
DrawSprite_2P_FlipY:
move.b (a1)+,d0
move.b (a1),d4
ext.w d0
neg.w d0
move.b byte_16E56(pc,d4.w),d4
sub.w d4,d0
add.w d2,d0
move.w d0,(a2)+
move.b (a1)+,d4
move.b SpriteSizes_2P_2(pc,d4.w),(a2)+
addq.b #1,d5
move.b d5,(a2)+
addq.w #2,a1
move.w (a1)+,d0
add.w a3,d0
eori.w #$1000,d0
move.w d0,(a2)+
move.w (a1)+,d0
add.w d3,d0
andi.w #$1FF,d0
bne.s +
addq.w #1,d0
+
move.w d0,(a2)+
dbf d1,DrawSprite_2P_FlipY
rts
; ===========================================================================
; cells are double the height in 2P mode, so halve the number of rows
; byte_16EA2:
SpriteSizes_2P_2:
dc.b 0,0
dc.b 1,1 ; 2
dc.b 4,4 ; 4
dc.b 5,5 ; 6
dc.b 8,8 ; 8
dc.b 9,9 ; 10
dc.b $C,$C ; 12
dc.b $D,$D ; 14
; offsets for vertically mirrored sprite pieces (2P)
byte_16EB2:
dc.b 8,$10,$18,$20 ; 4
dc.b 8,$10,$18,$20 ; 8
dc.b 8,$10,$18,$20 ; 12
dc.b 8,$10,$18,$20 ; 16
; ===========================================================================
; loc_16EC2:
DrawSprite_2P_FlipXY:
move.b (a1)+,d0
move.b (a1),d4
ext.w d0
neg.w d0
move.b byte_16EB2(pc,d4.w),d4
sub.w d4,d0
add.w d2,d0
move.w d0,(a2)+
move.b (a1)+,d4
move.b SpriteSizes_2P_2(pc,d4.w),(a2)+
addq.b #1,d5
move.b d5,(a2)+
addq.w #2,a1
move.w (a1)+,d0
add.w a3,d0
eori.w #$1800,d0
move.w d0,(a2)+
move.w (a1)+,d0
neg.w d0
move.b byte_16F06(pc,d4.w),d4
sub.w d4,d0
add.w d3,d0
andi.w #$1FF,d0
bne.s +
addq.w #1,d0
+
move.w d0,(a2)+
dbf d1,DrawSprite_2P_FlipXY
rts
; End of function DrawSprite_2P
; ===========================================================================
; offsets for horizontally mirrored sprite pieces (2P)
byte_16F06:
dc.b 8, 8, 8, 8 ; 4
dc.b $10,$10,$10,$10 ; 8
dc.b $18,$18,$18,$18 ; 12
dc.b $20,$20,$20,$20 ; 16
; ===========================================================================
; loc_16F16: ; unused/dead code? ; a0=object
move.w x_pos(a0),d0
sub.w (Camera_X_pos).w,d0
bmi.s +
cmpi.w #320,d0
bge.s +
move.w y_pos(a0),d1
sub.w (Camera_Y_pos).w,d1
bmi.s +
cmpi.w #$E0,d1
bge.s +
moveq #0,d0
rts
+ moveq #1,d0
rts
; ===========================================================================
; loc_16F3E: ; unused/dead code? ; a0=object
moveq #0,d1
move.b width_pixels(a0),d1
move.w x_pos(a0),d0
sub.w (Camera_X_pos).w,d0
add.w d1,d0
bmi.s +
add.w d1,d1
sub.w d1,d0
cmpi.w #320,d0
bge.s +
move.w y_pos(a0),d1
sub.w (Camera_Y_pos).w,d1
bmi.s +
cmpi.w #$E0,d1
bge.s +
moveq #0,d0
rts
+ moveq #1,d0
rts
; ===========================================================================
if gameRevision=1
nop
endif
if ~~removeJmpTos
JmpTo_BuildHUD
jmp (BuildHUD).l
JmpTo_BuildHUD_P1
jmp (BuildHUD_P1).l
JmpTo_BuildHUD_P2
jmp (BuildHUD_P2).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Pseudo-object that manages where rings are placed onscreen
; as you move through the level, and otherwise updates them.
; ----------------------------------------------------------------------------
; loc_16F88:
RingsManager:
moveq #0,d0
move.b (Rings_manager_routine).w,d0
move.w RingsManager_States(pc,d0.w),d0
jmp RingsManager_States(pc,d0.w)
; ===========================================================================
; off_16F96:
RingsManager_States: offsetTable
offsetTableEntry.w RingsManager_Init ; 0
offsetTableEntry.w RingsManager_Main ; 2
; ===========================================================================
; loc_16F9A:
RingsManager_Init:
addq.b #2,(Rings_manager_routine).w ; => RingsManager_Main
bsr.w RingsManager_Setup ; perform initial setup
lea (Ring_Positions).w,a1
move.w (Camera_X_pos).w,d4
subq.w #8,d4
bhi.s +
moveq #1,d4 ; no negative values allowed
bra.s +
-
lea 6(a1),a1 ; load next ring
+
cmp.w 2(a1),d4 ; is the X pos of the ring < camera X pos?
bhi.s - ; if it is, check next ring
move.w a1,(Ring_start_addr).w ; set start addresses
move.w a1,(Ring_start_addr_P2).w
addi.w #320+16,d4 ; advance by a screen
bra.s +
-
lea 6(a1),a1 ; load next ring
+
cmp.w 2(a1),d4 ; is the X pos of the ring < camera X + 336?
bhi.s - ; if it is, check next ring
move.w a1,(Ring_end_addr).w ; set end addresses
move.w a1,(Ring_end_addr_P2).w
rts
; ===========================================================================
; loc_16FDE:
RingsManager_Main:
lea (Ring_consumption_table).w,a2
move.w (a2)+,d1
subq.w #1,d1 ; are any rings currently being consumed?
bcs.s ++ ; if not, branch
- move.w (a2)+,d0 ; is there a ring in this slot?
beq.s - ; if not, branch
movea.w d0,a1 ; load ring address
subq.b #1,(a1) ; decrement timer
bne.s + ; if it's not 0 yet, branch
move.b #6,(a1) ; reset timer
addq.b #1,1(a1); increment frame
cmpi.b #8,1(a1); is it destruction time yet?
bne.s + ; if not, branch
move.w #-1,(a1); destroy ring
move.w #0,-2(a2) ; clear ring entry
subq.w #1,(Ring_consumption_table).w ; subtract count
+ dbf d1,- ; repeat for all rings in table
+
; update ring start and end addresses
movea.w (Ring_start_addr).w,a1
move.w (Camera_X_pos).w,d4
subq.w #8,d4
bhi.s +
moveq #1,d4
bra.s +
-
lea 6(a1),a1
+
cmp.w 2(a1),d4
bhi.s -
bra.s +
-
subq.w #6,a1
+
cmp.w -4(a1),d4
bls.s -
move.w a1,(Ring_start_addr).w ; update start address
movea.w (Ring_end_addr).w,a2
addi.w #320+16,d4
bra.s +
-
lea 6(a2),a2
+
cmp.w 2(a2),d4
bhi.s -
bra.s +
-
subq.w #6,a2
+
cmp.w -4(a2),d4
bls.s -
move.w a2,(Ring_end_addr).w ; update end address
tst.w (Two_player_mode).w ; are we in 2P mode?
bne.s + ; if we are, update P2 addresses
move.w a1,(Ring_start_addr_P2).w ; otherwise, copy over P1 addresses
move.w a2,(Ring_end_addr_P2).w
rts
+
; update ring start and end addresses for P2
movea.w (Ring_start_addr_P2).w,a1
move.w (Camera_X_pos_P2).w,d4
subq.w #8,d4
bhi.s +
moveq #1,d4
bra.s +
-
lea 6(a1),a1
+
cmp.w 2(a1),d4
bhi.s -
bra.s +
-
subq.w #6,a1
+
cmp.w -4(a1),d4
bls.s -
move.w a1,(Ring_start_addr_P2).w ; update start address
movea.w (Ring_end_addr_P2).w,a2
addi.w #320+16,d4
bra.s +
-
lea 6(a2),a2
+
cmp.w 2(a2),d4
bhi.s -
bra.s +
-
subq.w #6,a2
+
cmp.w -4(a2),d4
bls.s -
move.w a2,(Ring_end_addr_P2).w ; update end address
rts
; ---------------------------------------------------------------------------
; Subroutine to handle ring collision
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_170BA:
Touch_Rings:
movea.w (Ring_start_addr).w,a1
movea.w (Ring_end_addr).w,a2
cmpa.w #MainCharacter,a0
beq.s +
movea.w (Ring_start_addr_P2).w,a1
movea.w (Ring_end_addr_P2).w,a2
+
cmpa.l a1,a2 ; are there no rings in this area?
beq.w Touch_Rings_Done ; if so, return
cmpi.w #$5A,invulnerable_time(a0)
bhs.w Touch_Rings_Done
move.w x_pos(a0),d2
move.w y_pos(a0),d3
subi_.w #8,d2 ; assume X radius to be 8
moveq #0,d5
move.b y_radius(a0),d5
subq.b #3,d5
sub.w d5,d3 ; subtract (Y radius - 3) from Y pos
cmpi.b #$4D,mapping_frame(a0)
bne.s + ; if you're not ducking, branch
addi.w #$C,d3
moveq #$A,d5
+
move.w #6,d1 ; set ring radius
move.w #12,d6 ; set ring diameter
move.w #16,d4 ; set Sonic's X diameter
add.w d5,d5 ; set Y diameter
; loc_17112:
Touch_Rings_Loop:
tst.w (a1) ; has this ring already been collided with?
bne.w Touch_NextRing ; if it has, branch
move.w 2(a1),d0 ; get ring X pos
sub.w d1,d0 ; get ring left edge X pos
sub.w d2,d0 ; subtract Sonic's left edge X pos
bcc.s + ; if Sonic's to the left of the ring, branch
add.w d6,d0 ; add ring diameter
bcs.s ++ ; if Sonic's colliding, branch
bra.w Touch_NextRing ; otherwise, test next ring
+
cmp.w d4,d0 ; has Sonic crossed the ring?
bhi.w Touch_NextRing ; if he has, branch
+
move.w 4(a1),d0 ; get ring Y pos
sub.w d1,d0 ; get ring top edge pos
sub.w d3,d0 ; subtract Sonic's top edge pos
bcc.s + ; if Sonic's above the ring, branch
add.w d6,d0 ; add ring diameter
bcs.s ++ ; if Sonic's colliding, branch
bra.w Touch_NextRing ; otherwise, test next ring
+
cmp.w d5,d0 ; has Sonic crossed the ring?
bhi.w Touch_NextRing ; if he has, branch
+
move.w #$604,(a1) ; set frame and destruction timer
bsr.s Touch_ConsumeRing
lea (Ring_consumption_table+2).w,a3
- tst.w (a3)+ ; is this slot free?
bne.s - ; if not, repeat until you find one
move.w a1,-(a3) ; set ring address
addq.w #1,(Ring_consumption_table).w ; increase count
; loc_1715C:
Touch_NextRing:
lea 6(a1),a1
cmpa.l a1,a2 ; are we at the last ring for this area?
bne.w Touch_Rings_Loop ; if not, branch
; return_17166:
Touch_Rings_Done:
rts
; ===========================================================================
; loc_17168:
Touch_ConsumeRing:
subq.w #1,(Perfect_rings_left).w
cmpa.w #MainCharacter,a0 ; who collected the ring?
beq.w CollectRing_Sonic ; if it was Sonic, branch here
bra.w CollectRing_Tails ; if it was Tails, branch here
; ---------------------------------------------------------------------------
; Subroutine to draw on-screen rings
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_17178:
BuildRings:
movea.w (Ring_start_addr).w,a0
movea.w (Ring_end_addr).w,a4
cmpa.l a0,a4 ; are there any rings on-screen?
bne.s + ; if there are, branch
rts ; otherwise, return
+
lea (Camera_X_pos).w,a3
; loc_1718A:
BuildRings_Loop:
tst.w (a0) ; has this ring been consumed?
bmi.w BuildRings_NextRing ; if it has, branch
move.w 2(a0),d3 ; get ring X pos
sub.w (a3),d3 ; subtract camera X pos
addi.w #128,d3 ; screen top is 128x128 not 0x0
move.w 4(a0),d2 ; get ring Y pos
sub.w 4(a3),d2 ; subtract camera Y pos
andi.w #$7FF,d2
addi_.w #8,d2
bmi.s BuildRings_NextRing ; dunno how this check is supposed to work
cmpi.w #240,d2
bge.s BuildRings_NextRing ; if the ring is not on-screen, branch
addi.w #128-8,d2
lea (MapUnc_Rings).l,a1
moveq #0,d1
move.b 1(a0),d1 ; get ring frame
bne.s + ; if this ring is using a specific frame, branch
move.b (Rings_anim_frame).w,d1 ; use global frame
+
add.w d1,d1
adda.w (a1,d1.w),a1 ; get frame data address
move.b (a1)+,d0 ; get Y offset
ext.w d0
add.w d2,d0 ; add Y offset to Y pos
move.w d0,(a2)+ ; set Y pos
move.b (a1)+,(a2)+ ; set size
addq.b #1,d5
move.b d5,(a2)+ ; set link field
move.w (a1)+,d0 ; get art tile
addi.w #make_art_tile(ArtTile_ArtNem_Ring,1,0),d0 ; add base art tile
move.w d0,(a2)+ ; set art tile and flags
addq.w #2,a1 ; skip 2P art tile
move.w (a1)+,d0 ; get X offset
add.w d3,d0 ; add base X pos
move.w d0,(a2)+ ; set X pos
; loc_171EC:
BuildRings_NextRing:
lea 6(a0),a0
cmpa.l a0,a4
bne.w BuildRings_Loop
rts
; ---------------------------------------------------------------------------
; Subroutine to draw on-screen rings for player 1 in a 2P versus game
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_171F8:
BuildRings_P1:
lea (Camera_X_pos).w,a3
move.w #128-8,d6
movea.w (Ring_start_addr).w,a0
movea.w (Ring_end_addr).w,a4
cmpa.l a0,a4 ; are there rings on-screen?
bne.s BuildRings_2P_Loop ; if there are, draw them
rts ; otherwise, return
; ---------------------------------------------------------------------------
; Subroutine to draw on-screen rings for player 2 in a 2P versus game
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1720E:
BuildRings_P2:
lea (Camera_X_pos_P2).w,a3
move.w #224+128-8,d6
movea.w (Ring_start_addr_P2).w,a0
movea.w (Ring_end_addr_P2).w,a4
cmpa.l a0,a4 ; are there rings on-screen?
bne.s BuildRings_2P_Loop ; if there are, draw them
rts ; otherwise, return
; ===========================================================================
; loc_17224:
BuildRings_2P_Loop:
tst.w (a0) ; has this ring been consumed?
bmi.w BuildRings_2P_NextRing ; if it has, branch
move.w 2(a0),d3 ; get ring X pos
sub.w (a3),d3 ; subtract camera X pos
addi.w #128,d3
move.w 4(a0),d2 ; get ring Y pos
sub.w 4(a3),d2 ; subtract camera Y pos
andi.w #$7FF,d2
addi.w #128+8,d2
bmi.s BuildRings_2P_NextRing
cmpi.w #240+128,d2
bge.s BuildRings_2P_NextRing
add.w d6,d2 ; add base Y pos
lea (MapUnc_Rings).l,a1
moveq #0,d1
move.b 1(a0),d1 ; use ring-specific frame
bne.s + ; if there is one
move.b (Rings_anim_frame).w,d1 ; otherwise use global frame
+
add.w d1,d1
adda.w (a1,d1.w),a1
move.b (a1)+,d0
ext.w d0
add.w d2,d0
move.w d0,(a2)+ ; set Y pos
move.b (a1)+,d4
move.b SpriteSizes_2P_3(pc,d4.w),(a2)+ ; set size
addq.b #1,d5
move.b d5,(a2)+ ; set link field
addq.w #2,a1
move.w (a1)+,d0
addi.w #make_art_tile_2p(ArtTile_ArtNem_Ring,1,0),d0
move.w d0,(a2)+ ; set art tile and flags
move.w (a1)+,d0
add.w d3,d0
move.w d0,(a2)+ ; set X pos
BuildRings_2P_NextRing:
lea 6(a0),a0 ; load next ring
cmpa.l a0,a4 ; are there any rings left?
bne.w BuildRings_2P_Loop ; if there are, loop
rts
; ===========================================================================
; cells are double the height in 2P mode, so halve the number of rows
; byte_17294:
SpriteSizes_2P_3:
dc.b 0,0 ; 1
dc.b 1,1 ; 3
dc.b 4,4 ; 5
dc.b 5,5 ; 7
dc.b 8,8 ; 9
dc.b 9,9 ; 11
dc.b $C,$C ; 13
dc.b $D,$D ; 15
; ---------------------------------------------------------------------------
; Subroutine to perform initial rings manager setup
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_172A4:
RingsManager_Setup:
clearRAM Ring_Positions,Ring_Positions_End
; d0 = 0
lea (Ring_consumption_table).w,a1
move.w #bytesToLcnt(Ring_consumption_table_End-Ring_consumption_table-$40),d1 ; coding error, that '-$40' shouldn't be there
- move.l d0,(a1)+ ; only half of Ring_consumption_table is cleared
dbf d1,-
moveq #0,d5
moveq #0,d0
move.w (Current_ZoneAndAct).w,d0
ror.b #1,d0
lsr.w #6,d0
lea (Off_Rings).l,a1
move.w (a1,d0.w),d0
lea (a1,d0.w),a1
lea (Ring_Positions+6).w,a2 ; first ring is left blank
; loc_172E0:
RingsMgr_NextRowOrCol:
move.w (a1)+,d2 ; is this the last ring?
bmi.s RingsMgr_SortRings ; if it is, sort the rings
move.w (a1)+,d3 ; is this a column of rings?
bmi.s RingsMgr_RingCol ; if it is, branch
move.w d3,d0
rol.w #4,d0
andi.w #7,d0 ; store number of rings
andi.w #$FFF,d3 ; store Y pos
; loc_172F4:
RingsMgr_NextRingInRow:
move.w #0,(a2)+ ; set initial status
move.w d2,(a2)+ ; set X pos
move.w d3,(a2)+ ; set Y pos
addi.w #$18,d2 ; increment X pos
addq.w #1,d5 ; increment perfect counter
dbf d0,RingsMgr_NextRingInRow
bra.s RingsMgr_NextRowOrCol
; ===========================================================================
; loc_17308:
RingsMgr_RingCol:
move.w d3,d0
rol.w #4,d0
andi.w #7,d0 ; store number of rings
andi.w #$FFF,d3 ; store Y pos
; loc_17314:
RingsMgr_NextRingInCol:
move.w #0,(a2)+ ; set initial status
move.w d2,(a2)+ ; set X pos
move.w d3,(a2)+ ; set Y pos
addi.w #$18,d3 ; increment Y pos
addq.w #1,d5 ; increment perfect counter
dbf d0,RingsMgr_NextRingInCol
bra.s RingsMgr_NextRowOrCol
; ===========================================================================
; loc_17328:
RingsMgr_SortRings:
move.w d5,(Perfect_rings_left).w
move.w #0,(Perfect_rings_flag).w ; no idea what this is
moveq #-1,d0
move.l d0,(a2)+ ; set X pos of last ring to -1
lea (Ring_Positions+2).w,a1 ; X pos of first ring
move.w #$FE,d3 ; sort 255 rings
- move.w d3,d4
lea 6(a1),a2 ; load next ring for comparison
move.w (a1),d0 ; get X pos of current ring
- tst.w (a2) ; is the next ring blank?
beq.s + ; if it is, branch
cmp.w (a2),d0 ; is the X pos of current ring <= X pos of next ring?
bls.s + ; if so, branch
move.l (a1),d1 ; otherwise, swap the rings
move.l (a2),d0
move.l d0,(a1)
move.l d1,(a2)
swap d0
+
lea 6(a2),a2 ; load next comparison ring
dbf d4,- ; repeat
lea 6(a1),a1 ; load next ring
dbf d3,-- ; repeat
rts
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
; off_1736A:
MapUnc_Rings: BINCLUDE "mappings/sprite/Rings.bin"
if ~~removeJmpTos
align 4
endif
; ---------------------------------------------------------------------------
; Pseudo-object to do collision with (and initialize?) the special bumpers in CNZ.
; These are the bumpers that are part of the level layout but have object-like collision.
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_173BC:
SpecialCNZBumpers:
moveq #0,d0
move.b (CNZ_Bumper_routine).w,d0
move.w SpecialCNZBumpers_Index(pc,d0.w),d0
jmp SpecialCNZBumpers_Index(pc,d0.w)
; ===========================================================================
; off_173CA:
SpecialCNZBumpers_Index: offsetTable
offsetTableEntry.w SpecialCNZBumpers_Init ; 0
offsetTableEntry.w SpecialCNZBumpers_Main ; 2
; ===========================================================================
; loc_173CE:
SpecialCNZBumpers_Init:
addq.b #2,(CNZ_Bumper_routine).w
lea (SpecialCNZBumpers_Act1).l,a1
tst.b (Current_Act).w
beq.s +
lea (SpecialCNZBumpers_Act2).l,a1
+
move.w (Camera_X_pos).w,d4
subq.w #8,d4
bhi.s +
moveq #1,d4
bra.s +
; ===========================================================================
-
lea next_bumper(a1),a1
+
cmp.w bumper_x(a1),d4
bhi.s -
move.l a1,(CNZ_Visible_bumpers_start).w
move.l a1,(CNZ_Visible_bumpers_start_P2).w
addi.w #$150,d4
bra.s +
; ===========================================================================
-
lea next_bumper(a1),a1
+
cmp.w bumper_x(a1),d4
bhi.s -
move.l a1,(CNZ_Visible_bumpers_end).w
move.l a1,(CNZ_Visible_bumpers_end_P2).w
move.b #1,(CNZ_Bumper_UnkFlag).w
rts
; ===========================================================================
; loc_17422:
SpecialCNZBumpers_Main:
movea.l (CNZ_Visible_bumpers_start).w,a1
move.w (Camera_X_pos).w,d4
subq.w #8,d4
bhi.s +
moveq #1,d4
bra.s +
; ===========================================================================
-
lea next_bumper(a1),a1
+
cmp.w bumper_x(a1),d4
bhi.s -
bra.s +
; ===========================================================================
-
subq.w #next_bumper,a1
+
cmp.w prev_bumper_x(a1),d4
bls.s -
move.l a1,(CNZ_Visible_bumpers_start).w
movea.l (CNZ_Visible_bumpers_end).w,a2
addi.w #$150,d4
bra.s +
; ===========================================================================
-
lea next_bumper(a2),a2
+
cmp.w bumper_x(a2),d4
bhi.s -
bra.s +
; ===========================================================================
-
subq.w #next_bumper,a2
+
cmp.w prev_bumper_x(a2),d4
bls.s -
move.l a2,(CNZ_Visible_bumpers_end).w
tst.w (Two_player_mode).w
bne.s +
move.l a1,(CNZ_Visible_bumpers_start_P2).w
move.l a2,(CNZ_Visible_bumpers_end_P2).w
rts
; ===========================================================================
+
movea.l (CNZ_Visible_bumpers_start_P2).w,a1
move.w (Camera_X_pos_P2).w,d4
subq.w #8,d4
bhi.s +
moveq #1,d4
bra.s +
; ===========================================================================
-
lea next_bumper(a1),a1
+
cmp.w bumper_x(a1),d4
bhi.s -
bra.s +
; ===========================================================================
-
subq.w #next_bumper,a1
+
cmp.w prev_bumper_x(a1),d4
bls.s -
move.l a1,(CNZ_Visible_bumpers_start_P2).w
movea.l (CNZ_Visible_bumpers_end_P2).w,a2
addi.w #$150,d4
bra.s +
; ===========================================================================
-
lea next_bumper(a2),a2
+
cmp.w bumper_x(a2),d4
bhi.s -
bra.s +
; ===========================================================================
-
subq.w #next_bumper,a2
+
cmp.w prev_bumper_x(a2),d4
bls.s -
move.l a2,(CNZ_Visible_bumpers_end_P2).w
rts
; ===========================================================================
Check_CNZ_bumpers:
movea.l (CNZ_Visible_bumpers_start).w,a1
movea.l (CNZ_Visible_bumpers_end).w,a2
cmpa.w #MainCharacter,a0
beq.s +
movea.l (CNZ_Visible_bumpers_start_P2).w,a1
movea.l (CNZ_Visible_bumpers_end_P2).w,a2
+
cmpa.l a1,a2
beq.w return_17578
move.w x_pos(a0),d2
move.w y_pos(a0),d3
subi.w #9,d2
moveq #0,d5
move.b y_radius(a0),d5
subq.b #3,d5
sub.w d5,d3
cmpi.b #$4D,mapping_frame(a0)
bne.s +
addi.w #$C,d3
moveq #$A,d5
+
move.w #$12,d4
add.w d5,d5
CNZ_Bumper_loop:
move.w bumper_id(a1),d0
andi.w #$E,d0
lea byte_17558(pc,d0.w),a3
moveq #0,d1
move.b (a3)+,d1
move.w bumper_x(a1),d0
sub.w d1,d0
sub.w d2,d0
bcc.s loc_17530
add.w d1,d1
add.w d1,d0
bcs.s loc_17536
bra.w CNZ_Bumper_next
; ===========================================================================
loc_17530:
cmp.w d4,d0
bhi.w CNZ_Bumper_next
loc_17536:
moveq #0,d1
move.b (a3)+,d1
move.w bumper_y(a1),d0
sub.w d1,d0
sub.w d3,d0
bcc.s loc_17550
add.w d1,d1
add.w d1,d0
bcs.w loc_17564
bra.w CNZ_Bumper_next
; ===========================================================================
loc_17550:
cmp.w d5,d0
bhi.w CNZ_Bumper_next
bra.s loc_17564
; ===========================================================================
byte_17558:
dc.b $20
dc.b $20 ; 1
dc.b $20 ; 2
dc.b $20 ; 3
dc.b $40 ; 4
dc.b 8 ; 5
dc.b $40 ; 6
dc.b 8 ; 7
dc.b 8 ; 8
dc.b $40 ; 9
dc.b 8 ; 10
dc.b $40 ; 11
; ===========================================================================
loc_17564:
move.w (a1),d0
move.w off_1757A(pc,d0.w),d0
jmp off_1757A(pc,d0.w)
; ===========================================================================
CNZ_Bumper_next:
lea next_bumper(a1),a1
cmpa.l a1,a2
bne.w CNZ_Bumper_loop
return_17578:
rts
; ===========================================================================
off_1757A: offsetTable
offsetTableEntry.w loc_17586 ; 0
offsetTableEntry.w loc_17638 ; 2
offsetTableEntry.w loc_1769E ; 4
offsetTableEntry.w loc_176F6 ; 6
offsetTableEntry.w loc_1774C ; 8
offsetTableEntry.w loc_177A4 ; $A
; ===========================================================================
loc_17586:
move.w bumper_y(a1),d0
sub.w y_pos(a0),d0
neg.w d0
cmpi.w #$20,d0
blt.s loc_175A0
move.w #$A00,y_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_175A0:
move.w bumper_x(a1),d0
sub.w x_pos(a0),d0
neg.w d0
cmpi.w #$20,d0
blt.s loc_175BA
move.w #$A00,x_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_175BA:
move.w bumper_x(a1),d0
sub.w x_pos(a0),d0
cmpi.w #$20,d0
blt.s loc_175CC
move.w #$20,d0
loc_175CC:
add.w bumper_y(a1),d0
subq.w #8,d0
move.w y_pos(a0),d1
addi.w #$E,d1
sub.w d1,d0
bcc.s return_175E8
move.w #$20,d3
bsr.s loc_175EA
bra.w loc_177FA
; ===========================================================================
return_175E8:
rts
; ===========================================================================
loc_175EA:
move.w x_vel(a0),d1
move.w y_vel(a0),d2
jsr (CalcAngle).l
move.b d0,(unk_FFDC).w
sub.w d3,d0
mvabs.w d0,d1
neg.w d0
add.w d3,d0
move.b d0,(unk_FFDD).w
move.b d1,(unk_FFDF).w
cmpi.b #$38,d1
blo.s loc_17618
move.w d3,d0
loc_17618:
move.b d0,(unk_FFDE).w
jsr (CalcSine).l
muls.w #-$A00,d1
asr.l #8,d1
move.w d1,x_vel(a0)
muls.w #-$A00,d0
asr.l #8,d0
move.w d0,y_vel(a0)
rts
; ===========================================================================
loc_17638:
move.w bumper_y(a1),d0
sub.w y_pos(a0),d0
neg.w d0
cmpi.w #$20,d0
blt.s loc_17652
move.w #$A00,y_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_17652:
move.w bumper_x(a1),d0
sub.w x_pos(a0),d0
cmpi.w #$20,d0
blt.s loc_1766A
move.w #-$A00,x_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_1766A:
move.w bumper_x(a1),d0
sub.w x_pos(a0),d0
neg.w d0
cmpi.w #$20,d0
blt.s loc_1767E
move.w #$20,d0
loc_1767E:
add.w bumper_y(a1),d0
subq.w #8,d0
move.w y_pos(a0),d1
addi.w #$E,d1
sub.w d1,d0
bcc.s return_1769C
move.w #$60,d3
bsr.w loc_175EA
bra.w loc_177FA
; ===========================================================================
return_1769C:
rts
; ===========================================================================
loc_1769E:
move.w bumper_y(a1),d0
sub.w y_pos(a0),d0
neg.w d0
cmpi.w #8,d0
blt.s loc_176B8
move.w #$A00,y_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_176B8:
move.w bumper_x(a1),d0
sub.w x_pos(a0),d0
cmpi.w #$40,d0
blt.s loc_176D0
move.w #-$A00,x_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_176D0:
neg.w d0
cmpi.w #$40,d0
blt.s loc_176E2
move.w #$A00,x_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_176E2:
move.w #$38,d3
tst.w d0
bmi.s loc_176EE
move.w #$48,d3
loc_176EE:
bsr.w loc_175EA
bra.w loc_177FA
; ===========================================================================
loc_176F6:
move.w bumper_y(a1),d0
sub.w y_pos(a0),d0
cmpi.w #8,d0
blt.s loc_1770E
move.w #-$A00,y_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_1770E:
move.w bumper_x(a1),d0
sub.w x_pos(a0),d0
cmpi.w #$40,d0
blt.s loc_17726
move.w #-$A00,x_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_17726:
neg.w d0
cmpi.w #$40,d0
blt.s loc_17738
move.w #$A00,x_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_17738:
move.w #$C8,d3
tst.w d0
bmi.s loc_17744
move.w #$B8,d3
loc_17744:
bsr.w loc_175EA
bra.w loc_177FA
; ===========================================================================
loc_1774C:
move.w bumper_x(a1),d0
sub.w x_pos(a0),d0
neg.w d0
cmpi.w #8,d0
blt.s loc_17766
move.w #$A00,x_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_17766:
move.w bumper_y(a1),d0
sub.w y_pos(a0),d0
cmpi.w #$40,d0
blt.s loc_1777E
move.w #-$A00,y_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_1777E:
neg.w d0
cmpi.w #$40,d0
blt.s loc_17790
move.w #$A00,x_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_17790:
move.w #8,d3
tst.w d0
bmi.s loc_1779C
move.w #$F8,d3
loc_1779C:
bsr.w loc_175EA
bra.w loc_177FA
; ===========================================================================
loc_177A4:
move.w bumper_x(a1),d0
sub.w x_pos(a0),d0
cmpi.w #8,d0
blt.s loc_177BC
move.w #$A00,x_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_177BC:
move.w bumper_y(a1),d0
sub.w y_pos(a0),d0
cmpi.w #$40,d0
blt.s loc_177D4
move.w #-$A00,y_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_177D4:
neg.w d0
cmpi.w #$40,d0
blt.s loc_177E6
move.w #$A00,x_vel(a0)
bra.w loc_177FA
; ===========================================================================
loc_177E6:
move.w #$78,d3
tst.w d0
bmi.s loc_177F2
move.w #$88,d3
loc_177F2:
bsr.w loc_175EA
bra.w loc_177FA
loc_177FA:
bset #1,status(a0)
bclr #4,status(a0)
bclr #5,status(a0)
clr.b jumping(a0)
move.w #SndID_LargeBumper,d0
jmp (PlaySound).l
; ===========================================================================
SpecialCNZBumpers_Act1: BINCLUDE "level/objects/CNZ 1 bumpers.bin" ; byte_1781A
SpecialCNZBumpers_Act2: BINCLUDE "level/objects/CNZ 2 bumpers.bin" ; byte_1795E
; ===========================================================================
if gameRevision<2
nop
endif
; ===========================================================================
; ---------------------------------------------------------------------------
; Objects Manager
; Subroutine that keeps track of any objects that need to remember
; their state, such as monitors or enemies.
;
; input variables:
; -none-
;
; writes:
; d0, d1
; d2 = respawn index of object to load
; d6 = camera position
;
; a0 = address in object placement list
; a2 = respawn table
; ---------------------------------------------------------------------------
; loc_17AA4
ObjectsManager:
moveq #0,d0
move.b (Obj_placement_routine).w,d0
move.w ObjectsManager_States(pc,d0.w),d0
jmp ObjectsManager_States(pc,d0.w)
; ===========================================================================
ObjectsManager_States: offsetTable
offsetTableEntry.w ObjectsManager_Init ; 0
offsetTableEntry.w ObjectsManager_Main ; 2
offsetTableEntry.w ObjectsManager_2P_Main ; 4
; ===========================================================================
; loc_17AB8
ObjectsManager_Init:
addq.b #2,(Obj_placement_routine).w
move.w (Current_ZoneAndAct).w,d0 ; If level == $0F01 (ARZ 2)...
ror.b #1,d0 ; then this yields $0F80...
lsr.w #6,d0 ; and this yields $003E.
lea (Off_Objects).l,a0 ; Next, we load the first pointer in the object layout list pointer index,
movea.l a0,a1 ; then copy it for quicker use later.
adda.w (a0,d0.w),a0 ; (Point1 * 2) + $003E
tst.w (Two_player_mode).w ; skip if not in 2-player vs mode
beq.s +
cmpi.b #casino_night_zone,(Current_Zone).w ; skip if not Casino Night Zone
bne.s +
lea (Objects_CNZ1_2P).l,a0 ; CNZ 1 2-player object layout
tst.b (Current_Act).w ; skip if not past act 1
beq.s +
lea (Objects_CNZ2_2P).l,a0 ; CNZ 2 2-player object layout
+
; initialize each object load address with the first object in the layout
move.l a0,(Obj_load_addr_right).w
move.l a0,(Obj_load_addr_left).w
move.l a0,(Obj_load_addr_2).w
move.l a0,(Obj_load_addr_3).w
lea (Object_Respawn_Table).w,a2
move.w #$101,(a2)+ ; the first two bytes are not used as respawn values
; instead, they are used to keep track of the current respawn indexes
; Bug: The '+7E' shouldn't be here; this loop accidentally clears an additional $7E bytes
move.w #bytesToLcnt(Obj_respawn_data_End-Obj_respawn_data+$7E),d0 ; set loop counter
- clr.l (a2)+ ; loop clears all other respawn values
dbf d0,-
lea (Obj_respawn_index).w,a2 ; reset a2
moveq #0,d2
move.w (Camera_X_pos).w,d6
subi.w #$80,d6 ; look one chunk to the left
bcc.s + ; if the result was negative,
moveq #0,d6 ; cap at zero
+
andi.w #$FF80,d6 ; limit to increments of $80 (width of a chunk)
movea.l (Obj_load_addr_right).w,a0 ; load address of object placement list
- ; at the beginning of a level this gives respawn table entries to any object that is one chunk
; behind the left edge of the screen that needs to remember its state (Monitors, Badniks, etc.)
cmp.w (a0),d6 ; is object's x position >= d6?
bls.s loc_17B3E ; if yes, branch
tst.b 2(a0) ; does the object get a respawn table entry?
bpl.s + ; if not, branch
move.b (a2),d2
addq.b #1,(a2) ; respawn index of next object to the right
+
addq.w #6,a0 ; next object
bra.s -
; ---------------------------------------------------------------------------
loc_17B3E:
move.l a0,(Obj_load_addr_right).w ; remember rightmost object that has been processed, so far (we still need to look forward)
move.l a0,(Obj_load_addr_2).w
movea.l (Obj_load_addr_left).w,a0 ; reset a0
subi.w #$80,d6 ; look even farther left (any object behind this is out of range)
bcs.s loc_17B62 ; branch, if camera position would be behind level's left boundary
- ; count how many objects are behind the screen that are not in range and need to remember their state
cmp.w (a0),d6 ; is object's x position >= d6?
bls.s loc_17B62 ; if yes, branch
tst.b 2(a0) ; does the object get a respawn table entry?
bpl.s + ; if not, branch
addq.b #1,1(a2) ; respawn index of current object to the left
+
addq.w #6,a0
bra.s - ; continue with next object
; ---------------------------------------------------------------------------
loc_17B62:
move.l a0,(Obj_load_addr_left).w ; remember current object from the left
move.l a0,(Obj_load_addr_3).w
move.w #-1,(Camera_X_pos_last).w ; make sure ObjectsManager_GoingForward is run
move.w #-1,(Camera_X_pos_last_P2).w
tst.w (Two_player_mode).w ; is it two player mode?
beq.s ObjectsManager_Main ; if not, branch
addq.b #2,(Obj_placement_routine).w
bra.w ObjectsManager_2P_Init
; ---------------------------------------------------------------------------
; loc_17B84
ObjectsManager_Main:
move.w (Camera_X_pos).w,d1
subi.w #$80,d1
andi.w #$FF80,d1
move.w d1,(Camera_X_pos_coarse).w
lea (Obj_respawn_index).w,a2
moveq #0,d2
move.w (Camera_X_pos).w,d6
andi.w #$FF80,d6
cmp.w (Camera_X_pos_last).w,d6 ; is the X range the same as last time?
beq.w ObjectsManager_SameXRange ; if yes, branch (rts)
bge.s ObjectsManager_GoingForward ; if new pos is greater than old pos, branch
; if the player is moving back
move.w d6,(Camera_X_pos_last).w ; remember current position for next time
movea.l (Obj_load_addr_left).w,a0 ; get current object from the left
subi.w #$80,d6 ; look one chunk to the left
bcs.s loc_17BE6 ; branch, if camera position would be behind level's left boundary
- ; load all objects left of the screen that are now in range
cmp.w -6(a0),d6 ; is the previous object's X pos less than d6?
bge.s loc_17BE6 ; if it is, branch
subq.w #6,a0 ; get object's address
tst.b 2(a0) ; does the object get a respawn table entry?
bpl.s + ; if not, branch
subq.b #1,1(a2) ; respawn index of this object
move.b 1(a2),d2
+
bsr.w ChkLoadObj ; load object
bne.s + ; branch, if SST is full
subq.w #6,a0
bra.s - ; continue with previous object
; ---------------------------------------------------------------------------
+ ; undo a few things, if the object couldn't load
tst.b 2(a0) ; does the object get a respawn table entry?
bpl.s + ; if not, branch
addq.b #1,1(a2) ; since we didn't load the object, undo last change
+
addq.w #6,a0 ; go back to last object
loc_17BE6:
move.l a0,(Obj_load_addr_left).w ; remember current object from the left
movea.l (Obj_load_addr_right).w,a0 ; get next object from the right
addi.w #$300,d6 ; look two chunks beyond the right edge of the screen
- ; subtract number of objects that have been moved out of range (from the right side)
cmp.w -6(a0),d6 ; is the previous object's X pos less than d6?
bgt.s loc_17C04 ; if it is, branch
tst.b -4(a0) ; does the previous object get a respawn table entry?
bpl.s + ; if not, branch
subq.b #1,(a2) ; respawn index of next object to the right
+
subq.w #6,a0
bra.s - ; continue with previous object
; ---------------------------------------------------------------------------
loc_17C04:
move.l a0,(Obj_load_addr_right).w ; remember next object from the right
rts
; ---------------------------------------------------------------------------
ObjectsManager_GoingForward:
move.w d6,(Camera_X_pos_last).w
movea.l (Obj_load_addr_right).w,a0 ; get next object from the right
addi.w #$280,d6 ; look two chunks forward
- ; load all objects right of the screen that are now in range
cmp.w (a0),d6 ; is object's x position >= d6?
bls.s loc_17C2A ; if yes, branch
tst.b 2(a0) ; does the object get a respawn table entry?
bpl.s + ; if not, branch
move.b (a2),d2 ; respawn index of this object
addq.b #1,(a2) ; respawn index of next object to the right
+
bsr.w ChkLoadObj ; load object (and get address of next object)
beq.s - ; continue loading objects, if the SST isn't full
loc_17C2A:
move.l a0,(Obj_load_addr_right).w ; remember next object from the right
movea.l (Obj_load_addr_left).w,a0 ; get current object from the left
subi.w #$300,d6 ; look one chunk behind the left edge of the screen
bcs.s loc_17C4A ; branch, if camera position would be behind level's left boundary
- ; subtract number of objects that have been moved out of range (from the left)
cmp.w (a0),d6 ; is object's x position >= d6?
bls.s loc_17C4A ; if yes, branch
tst.b 2(a0) ; does the object get a respawn table entry?
bpl.s + ; if not, branch
addq.b #1,1(a2) ; respawn index of next object to the left
+
addq.w #6,a0
bra.s - ; continue with previous object
; ---------------------------------------------------------------------------
loc_17C4A:
move.l a0,(Obj_load_addr_left).w ; remember current object from the left
ObjectsManager_SameXRange:
rts
; ---------------------------------------------------------------------------
; loc_17C50
ObjectsManager_2P_Init:
moveq #-1,d0
move.l d0,(unk_F780).w
move.l d0,(unk_F780+4).w
move.l d0,(unk_F780+8).w
move.l d0,(Camera_X_pos_last_P2).w ; both words that this sets to -1 are overwritten directly underneath, so this line is rather pointless...
move.w #0,(Camera_X_pos_last).w
move.w #0,(Camera_X_pos_last_P2).w
lea (Obj_respawn_index).w,a2
move.w (a2),(Obj_respawn_index_P2).w ; mirrior first two bytes (respawn indices) for player 2(?)
moveq #0,d2
; run initialization for player 1
lea (Obj_respawn_index).w,a5
lea (Obj_load_addr_right).w,a4
lea (unk_F786).w,a1 ; = -1, -1, -1
lea (unk_F789).w,a6 ; = -1, -1, -1
moveq #-2,d6
bsr.w ObjMan2P_GoingForward
lea (unk_F786).w,a1
moveq #-1,d6
bsr.w ObjMan2P_GoingForward
lea (unk_F786).w,a1
moveq #0,d6
bsr.w ObjMan2P_GoingForward
; run initialization for player 2
lea (Obj_respawn_index_P2).w,a5
lea (Obj_load_addr_2).w,a4
lea (unk_F789).w,a1
lea (unk_F786).w,a6
moveq #-2,d6
bsr.w ObjMan2P_GoingForward
lea (unk_F789).w,a1
moveq #-1,d6
bsr.w ObjMan2P_GoingForward
lea (unk_F789).w,a1
moveq #0,d6
bsr.w ObjMan2P_GoingForward
; loc_17CCC
ObjectsManager_2P_Main:
move.w (Camera_X_pos).w,d1
andi.w #$FF00,d1
move.w d1,(Camera_X_pos_coarse).w
move.w (Camera_X_pos_P2).w,d1
andi.w #$FF00,d1
move.w d1,(Camera_X_pos_coarse_P2).w
move.b (Camera_X_pos).w,d6 ; get upper byte of camera positon
andi.w #$FF,d6
move.w (Camera_X_pos_last).w,d0
cmp.w (Camera_X_pos_last).w,d6 ; is the X range the same as last time?
beq.s + ; if yes, branch
move.w d6,(Camera_X_pos_last).w ; remember current position for next time
lea (Obj_respawn_index).w,a5
lea (Obj_load_addr_right).w,a4
lea (unk_F786).w,a1
lea (unk_F789).w,a6
bsr.s ObjectsManager_2P_Run
+
move.b (Camera_X_pos_P2).w,d6 ; get upper byte of camera positon
andi.w #$FF,d6
move.w (Camera_X_pos_last_P2).w,d0
cmp.w (Camera_X_pos_last_P2).w,d6 ; is the X range the same as last time?
beq.s return_17D34 ; if yes, branch (rts)
move.w d6,(Camera_X_pos_last_P2).w
lea (Obj_respawn_index_P2).w,a5
lea (Obj_load_addr_2).w,a4
lea (unk_F789).w,a1
lea (unk_F786).w,a6
bsr.s ObjectsManager_2P_Run
return_17D34:
rts
; ===========================================================================
ObjectsManager_2P_Run:
lea (Obj_respawn_index).w,a2
moveq #0,d2
cmp.w d0,d6 ; is the X range the same as last time?
beq.w ObjectsManager_SameXRange ; if yes, branch (rts)
bge.w ObjMan2P_GoingForward ; if new pos is greater than old pos, branch
; if the player is moving back
move.b 2(a1),d2
move.b 1(a1),2(a1)
move.b (a1),1(a1)
move.b d6,(a1)
cmp.b (a6),d2
beq.s +
cmp.b 1(a6),d2
beq.s +
cmp.b 2(a6),d2
beq.s +
bsr.w ObjectsManager_2P_UnkSub3
bra.s loc_17D70
; ---------------------------------------------------------------------------
+
bsr.w ObjMan_2P_UnkSub2
loc_17D70:
bsr.w ObjMan_2P_UnkSub1
bne.s loc_17D94 ; if whatever checks were just performed were all not equal, branch
movea.l 4(a4),a0
-
cmp.b -6(a0),d6
bne.s loc_17D8E
tst.b -4(a0)
bpl.s +
subq.b #1,1(a5)
+
subq.w #6,a0
bra.s -
; ---------------------------------------------------------------------------
loc_17D8E:
move.l a0,4(a4)
bra.s loc_17DCA
; ---------------------------------------------------------------------------
loc_17D94:
movea.l 4(a4),a0
move.b d6,(a1)
-
cmp.b -6(a0),d6
bne.s loc_17DC6
subq.w #6,a0
tst.b 2(a0)
bpl.s +
subq.b #1,1(a5)
move.b 1(a5),d2
+
bsr.w ChkLoadObj_2P
bne.s loc_17DBA
subq.w #6,a0
bra.s -
; ---------------------------------------------------------------------------
loc_17DBA:
tst.b 2(a0)
bpl.s +
addq.b #1,1(a5)
+
addq.w #6,a0
loc_17DC6:
move.l a0,4(a4)
loc_17DCA:
movea.l (a4),a0
addq.w #3,d6
-
cmp.b -6(a0),d6
bne.s loc_17DE0
tst.b -4(a0)
bpl.s +
subq.b #1,(a5)
+
subq.w #6,a0
bra.s -
; ---------------------------------------------------------------------------
loc_17DE0:
move.l a0,(a4)
rts
; ===========================================================================
;loc_17DE4:
ObjMan2P_GoingForward:
addq.w #2,d6 ; look forward two chunks
move.b (a1),d2 ; shift positions in array left once
move.b 1(a1),(a1) ; nearest chunk to the right
move.b 2(a1),1(a1) ; middle chunk to the right
move.b d6,2(a1) ; farthest chunk to the right
cmp.b (a6),d2 ; compare farthset distance
beq.s +
cmp.b 1(a6),d2
beq.s +
cmp.b 2(a6),d2
beq.s +
bsr.w ObjectsManager_2P_UnkSub3 ; if not, run this sub-routine
bra.s loc_17E10
; ---------------------------------------------------------------------------
+
bsr.w ObjMan_2P_UnkSub2
loc_17E10:
bsr.w ObjMan_2P_UnkSub1
bne.s loc_17E2C ; if whatever checks were just performed were all not equal, branch
movea.l (a4),a0
-
cmp.b (a0),d6
bne.s loc_17E28
tst.b 2(a0) ; does the object get a respawn table entry?
bpl.s + ; if not, branch
addq.b #1,(a5)
+
addq.w #6,a0
bra.s -
; ===========================================================================
loc_17E28:
move.l a0,(a4)
bra.s loc_17E46
; ===========================================================================
loc_17E2C:
movea.l (a4),a0
move.b d6,(a1)
-
cmp.b (a0),d6
bne.s loc_17E44
tst.b 2(a0) ; does the object get a respawn table entry?
bpl.s + ; if not, branch
move.b (a5),d2
addq.b #1,(a5)
+
bsr.w ChkLoadObj_2P
beq.s -
loc_17E44:
move.l a0,(a4)
loc_17E46:
movea.l 4(a4),a0
subq.w #3,d6
bcs.s loc_17E60
loc_17E4E:
cmp.b (a0),d6
bne.s loc_17E60
tst.b 2(a0)
bpl.s loc_17E5C
addq.b #1,1(a5)
loc_17E5C:
addq.w #6,a0
bra.s loc_17E4E
; ===========================================================================
loc_17E60:
move.l a0,4(a4)
rts
; ===========================================================================
;loc_17E66:
ObjMan_2P_UnkSub1:
move.l a1,-(sp)
lea (unk_F780).w,a1
cmp.b (a1)+,d6
beq.s +
cmp.b (a1)+,d6
beq.s +
cmp.b (a1)+,d6
beq.s +
cmp.b (a1)+,d6
beq.s +
cmp.b (a1)+,d6
beq.s +
cmp.b (a1)+,d6
beq.s +
moveq #1,d0
+
movea.l (sp)+,a1
rts
; ===========================================================================
;loc_17E8A:
ObjMan_2P_UnkSub2:
lea (unk_F780).w,a1
lea (Dynamic_Object_RAM_2P_End).w,a3
tst.b (a1)+
bmi.s +
lea (Dynamic_Object_RAM_2P_End+$C*object_size).w,a3
tst.b (a1)+
bmi.s +
lea (Dynamic_Object_RAM_2P_End+$18*object_size).w,a3
tst.b (a1)+
bmi.s +
lea (Dynamic_Object_RAM_2P_End+$24*object_size).w,a3
tst.b (a1)+
bmi.s +
lea (Dynamic_Object_RAM_2P_End+$30*object_size).w,a3
tst.b (a1)+
bmi.s +
lea (Dynamic_Object_RAM_2P_End+$3C*object_size).w,a3
tst.b (a1)+
bmi.s +
nop
nop
+
subq.w #1,a1
rts
; ===========================================================================
; this sub-routine appears to determine which 12 byte block of object RAM
; corresponds to the current out-of-range camera positon (in d2) and deletes
; the objects in this block. This most likely takes over the functionality
; of markObjGone, as that routine isn't called in two player mode.
;loc_17EC6:
ObjectsManager_2P_UnkSub3:
lea (unk_F780).w,a1
lea (Dynamic_Object_RAM_2P_End).w,a3
cmp.b (a1)+,d2
beq.s +
lea (Dynamic_Object_RAM_2P_End+$C*object_size).w,a3
cmp.b (a1)+,d2
beq.s +
lea (Dynamic_Object_RAM_2P_End+$18*object_size).w,a3
cmp.b (a1)+,d2
beq.s +
lea (Dynamic_Object_RAM_2P_End+$24*object_size).w,a3
cmp.b (a1)+,d2
beq.s +
lea (Dynamic_Object_RAM_2P_End+$30*object_size).w,a3
cmp.b (a1)+,d2
beq.s +
lea (Dynamic_Object_RAM_2P_End+$3C*object_size).w,a3
cmp.b (a1)+,d2
beq.s +
nop
nop
+
move.b #-1,-(a1)
movem.l a1/a3,-(sp)
moveq #0,d1 ; used later to delete objects
moveq #$C-1,d2
;loc_17F0A:
ObjMan2P_UnkSub3_DeleteBlockLoop:
tst.b (a3)
beq.s ObjMan2P_UnkSub3_DeleteBlock_SkipObj ; branch if slot is empty
movea.l a3,a1
moveq #0,d0
move.b respawn_index(a1),d0 ; does object remember its state?
beq.s + ; if not, branch
bclr #7,2(a2,d0.w) ; else, clear entry in respawn table
; inlined DeleteObject2:
+
moveq #bytesToLcnt(next_object),d0 ; we want to clear up to the next object
; note: d1 is already 0
; delete the object by setting all of its bytes to 0
- move.l d1,(a1)+
dbf d0,-
if object_size&3
move.w d1,(a1)+
endif
;loc_17F26:
ObjMan2P_UnkSub3_DeleteBlock_SkipObj:
lea next_object(a3),a3 ; a3=object
dbf d2,ObjMan2P_UnkSub3_DeleteBlockLoop
moveq #0,d2
movem.l (sp)+,a1/a3
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to check if an object needs to be loaded.
;
; input variables:
; d2 = respawn index of object to be loaded
;
; a0 = address in object placement list
; a2 = object respawn table
;
; writes:
; d0, d1
; a1 = object
; ---------------------------------------------------------------------------
;loc_17F36:
ChkLoadObj:
tst.b 2(a0) ; does the object get a respawn table entry?
bpl.s + ; if not, branch
bset #7,2(a2,d2.w) ; mark object as loaded
beq.s + ; branch if it wasn't already loaded
addq.w #6,a0 ; next object
moveq #0,d0 ; let the objects manager know that it can keep going
rts
; ---------------------------------------------------------------------------
+
bsr.w SingleObjLoad ; find empty slot
bne.s return_17F7E ; branch, if there is no room left in the SST
move.w (a0)+,x_pos(a1)
move.w (a0)+,d0 ; there are three things stored in this word
bpl.s + ; branch, if the object doesn't get a respawn table entry
move.b d2,respawn_index(a1)
+
move.w d0,d1 ; copy for later
andi.w #$FFF,d0 ; get y-position
move.w d0,y_pos(a1)
rol.w #3,d1 ; adjust bits
andi.b #3,d1 ; get render flags
move.b d1,render_flags(a1)
move.b d1,status(a1)
_move.b (a0)+,id(a1) ; load obj
move.b (a0)+,subtype(a1)
moveq #0,d0
return_17F7E:
rts
; ===========================================================================
;loc_17F80:
ChkLoadObj_2P:
tst.b 2(a0) ; does the object get a respawn table entry?
bpl.s + ; if not, branch
bset #7,2(a2,d2.w) ; mark object as loaded
beq.s + ; branch if it wasn't already loaded
addq.w #6,a0 ; next object
moveq #0,d0 ; let the objects manager know that it can keep going
rts
; ---------------------------------------------------------------------------
+
btst #4,2(a0) ; the bit that's being tested for here should always be zero,
beq.s + ; but assuming it weren't and this branch isn't taken,
bsr.w SingleObjLoad ; then this object would not be loaded into one of the 12
bne.s return_17FD8 ; byte blocks after Dynamic_Object_RAM_2P_End and would most
bra.s ChkLoadObj_2P_LoadData ; likely end up somwhere before this in Dynamic_Object_RAM
; ---------------------------------------------------------------------------
+
bsr.w SingleObjLoad3 ; find empty slot in current 12 object block
bne.s return_17FD8 ; branch, if there is no room left in this block
;loc_17FAA:
ChkLoadObj_2P_LoadData:
move.w (a0)+,x_pos(a1)
move.w (a0)+,d0 ; there are three things stored in this word
bpl.s + ; branch, if the object doesn't get a respawn table entry
move.b d2,respawn_index(a1)
+
move.w d0,d1 ; copy for later
andi.w #$FFF,d0 ; get y-position
move.w d0,y_pos(a1)
rol.w #3,d1 ; adjust bits
andi.b #3,d1 ; get render flags
move.b d1,render_flags(a1)
move.b d1,status(a1)
_move.b (a0)+,id(a1) ; load obj
move.b (a0)+,subtype(a1)
moveq #0,d0
return_17FD8:
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Single object loading subroutine
; Find an empty object array
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_17FDA: ; allocObject:
SingleObjLoad:
lea (Dynamic_Object_RAM).w,a1 ; a1=object
move.w #(Dynamic_Object_RAM_End-Dynamic_Object_RAM)/object_size-1,d0 ; search to end of table
tst.w (Two_player_mode).w
beq.s +
move.w #(Dynamic_Object_RAM_2P_End-Dynamic_Object_RAM)/object_size-1,d0 ; search to $BF00 exclusive
/
tst.b id(a1) ; is object RAM slot empty?
beq.s return_17FF8 ; if yes, branch
lea next_object(a1),a1 ; load obj address ; goto next object RAM slot
dbf d0,- ; repeat until end
return_17FF8:
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Single object loading subroutine
; Find an empty object array AFTER the current one in the table
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_17FFA: ; allocObjectAfterCurrent:
SingleObjLoad2:
movea.l a0,a1
move.w #Dynamic_Object_RAM_End,d0 ; $D000
sub.w a0,d0 ; subtract current object location
if object_size=$40
lsr.w #6,d0 ; divide by $40
else
divu.w #object_size,d0
endif
subq.w #1,d0 ; keep from going over the object zone
bcs.s return_18014
-
tst.b id(a1) ; is object RAM slot empty?
beq.s return_18014 ; if yes, branch
lea next_object(a1),a1 ; load obj address ; goto next object RAM slot
dbf d0,- ; repeat until end
return_18014:
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Single object loading subroutine
; Find an empty object at or within < 12 slots after a3
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_18016:
SingleObjLoad3:
movea.l a3,a1
move.w #$B,d0
-
tst.b id(a1) ; is object RAM slot empty?
beq.s return_18028 ; if yes, branch
lea next_object(a1),a1 ; load obj address ; goto next object RAM slot
dbf d0,- ; repeat until end
return_18028:
rts
; ===========================================================================
;---------------------------------------------------------------------------------------
; CNZ act 1 object layout for 2-player mode (various objects were deleted)
;---------------------------------------------------------------------------------------
; byte_1802A;
if gameRevision=0
Objects_CNZ1_2P: BINCLUDE "level/objects/CNZ_1_2P (REV00).bin"
else
; a Crawl badnik was moved slightly further away from a ledge
; 2 flippers were moved closer to a wall
Objects_CNZ1_2P: BINCLUDE "level/objects/CNZ_1_2P.bin"
endif
;---------------------------------------------------------------------------------------
; CNZ act 2 object layout for 2-player mode (various objects were deleted)
;---------------------------------------------------------------------------------------
; byte_18492:
if gameRevision=0
Objects_CNZ2_2P: BINCLUDE "level/objects/CNZ_2_2P (REV00).bin"
else
; 4 Crawl badniks were slightly moved, placing them closer/farther away from ledges
; 2 flippers were moved away from a wall to keep players from getting stuck behind them
Objects_CNZ2_2P: BINCLUDE "level/objects/CNZ_2_2P.bin"
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 41 - Spring
; ----------------------------------------------------------------------------
; Sprite_18888:
Obj41:
moveq #0,d0
move.b routine(a0),d0
move.w Obj41_Index(pc,d0.w),d1
jsr Obj41_Index(pc,d1.w)
jmp (MarkObjGone).l
; ===========================================================================
; off_1889C:
Obj41_Index: offsetTable
offsetTableEntry.w Obj41_Init ; 0
offsetTableEntry.w Obj41_Up ; 2
offsetTableEntry.w Obj41_Horizontal ; 4
offsetTableEntry.w Obj41_Down ; 6
offsetTableEntry.w Obj41_DiagonallyUp ; 8
offsetTableEntry.w Obj41_DiagonallyDown ; $A
; ===========================================================================
; loc_188A8:
Obj41_Init:
addq.b #2,routine(a0)
move.l #Obj41_MapUnc_1901C,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #4,priority(a0)
move.b subtype(a0),d0
lsr.w #3,d0
andi.w #$E,d0
move.w Obj41_Init_Subtypes(pc,d0.w),d0
jmp Obj41_Init_Subtypes(pc,d0.w)
; ===========================================================================
; off_188DE:
Obj41_Init_Subtypes: offsetTable
offsetTableEntry.w Obj41_Init_Up ; 0
offsetTableEntry.w Obj41_Init_Horizontal ; 2
offsetTableEntry.w Obj41_Init_Down ; 4
offsetTableEntry.w Obj41_Init_DiagonallyUp ; 6
offsetTableEntry.w Obj41_Init_DiagonallyDown ; 8
; ===========================================================================
; loc_188E8:
Obj41_Init_Horizontal:
move.b #4,routine(a0)
move.b #2,anim(a0)
move.b #3,mapping_frame(a0)
move.w #make_art_tile(ArtTile_ArtNem_HrzntlSprng,0,0),art_tile(a0)
move.b #8,width_pixels(a0)
bra.s Obj41_Init_Common
; ===========================================================================
; loc_18908:
Obj41_Init_Down:
move.b #6,routine(a0)
move.b #6,mapping_frame(a0)
bset #1,status(a0)
bra.s Obj41_Init_Common
; ===========================================================================
; loc_1891C:
Obj41_Init_DiagonallyUp:
move.b #8,routine(a0)
move.b #4,anim(a0)
move.b #7,mapping_frame(a0)
move.w #make_art_tile(ArtTile_ArtNem_DignlSprng,0,0),art_tile(a0)
bra.s Obj41_Init_Common
; ===========================================================================
; loc_18936:
Obj41_Init_DiagonallyDown:
move.b #$A,routine(a0)
move.b #4,anim(a0)
move.b #$A,mapping_frame(a0)
move.w #make_art_tile(ArtTile_ArtNem_DignlSprng,0,0),art_tile(a0)
bset #1,status(a0)
; loc_18954:
Obj41_Init_Up:
Obj41_Init_Common:
; checks color of spring
move.b subtype(a0),d0
andi.w #2,d0
move.w Obj41_Strengths(pc,d0.w),objoff_30(a0)
btst #1,d0
beq.s +
bset #palette_bit_0,art_tile(a0)
move.l #Obj41_MapUnc_19032,mappings(a0)
+
bsr.w Adjust2PArtPointer
rts
; ===========================================================================
; word_1897C:
Obj41_Strengths:
; Speed applied on Sonic
dc.w -$1000
dc.w -$A00
; ===========================================================================
; loc_18980:
Obj41_Up:
move.w #$1B,d1
move.w #8,d2
move.w #$10,d3
move.w x_pos(a0),d4
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.w SolidObject_Always_SingleCharacter
btst #p1_standing_bit,status(a0)
beq.s loc_189A8
bsr.s loc_189CA
loc_189A8:
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
bsr.w SolidObject_Always_SingleCharacter
btst #p2_standing_bit,status(a0)
beq.s loc_189C0
bsr.s loc_189CA
loc_189C0:
lea (Ani_obj41).l,a1
bra.w AnimateSprite
; ===========================================================================
loc_189CA:
move.w #$100,anim(a0)
addq.w #8,y_pos(a1)
move.w objoff_30(a0),y_vel(a1)
bset #1,status(a1)
bclr #3,status(a1)
move.b #AniIDSonAni_Spring,anim(a1)
move.b #2,routine(a1)
move.b subtype(a0),d0
bpl.s loc_189FE
move.w #0,x_vel(a1)
loc_189FE:
btst #0,d0
beq.s loc_18A3E
move.w #1,inertia(a1)
move.b #1,flip_angle(a1)
move.b #AniIDSonAni_Walk,anim(a1)
move.b #0,flips_remaining(a1)
move.b #4,flip_speed(a1)
btst #1,d0
bne.s loc_18A2E
move.b #1,flips_remaining(a1)
loc_18A2E:
btst #0,status(a1)
beq.s loc_18A3E
neg.b flip_angle(a1)
neg.w inertia(a1)
loc_18A3E:
andi.b #$C,d0
cmpi.b #4,d0
bne.s loc_18A54
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
loc_18A54:
cmpi.b #8,d0
bne.s loc_18A66
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
loc_18A66:
move.w #SndID_Spring,d0
jmp (PlaySound).l
; ===========================================================================
; loc_18A70:
Obj41_Horizontal:
move.w #$13,d1
move.w #$E,d2
move.w #$F,d3
move.w x_pos(a0),d4
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.w SolidObject_Always_SingleCharacter
btst #p1_pushing_bit,status(a0)
beq.s loc_18AB0
move.b status(a0),d1
move.w x_pos(a0),d0
sub.w x_pos(a1),d0
bcs.s loc_18AA8
eori.b #1,d1
loc_18AA8:
andi.b #1,d1
bne.s loc_18AB0
bsr.s loc_18AEE
loc_18AB0:
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
bsr.w SolidObject_Always_SingleCharacter
btst #p2_pushing_bit,status(a0)
beq.s loc_18AE0
move.b status(a0),d1
move.w x_pos(a0),d0
sub.w x_pos(a1),d0
bcs.s loc_18AD8
eori.b #1,d1
loc_18AD8:
andi.b #1,d1
bne.s loc_18AE0
bsr.s loc_18AEE
loc_18AE0:
bsr.w loc_18BC6
lea (Ani_obj41).l,a1
bra.w AnimateSprite
; ===========================================================================
loc_18AEE:
move.w #$300,anim(a0)
move.w objoff_30(a0),x_vel(a1)
addq.w #8,x_pos(a1)
bset #0,status(a1)
btst #0,status(a0)
bne.s loc_18B1C
bclr #0,status(a1)
subi.w #$10,x_pos(a1)
neg.w x_vel(a1)
loc_18B1C:
move.w #$F,move_lock(a1)
move.w x_vel(a1),inertia(a1)
btst #2,status(a1)
bne.s loc_18B36
move.b #AniIDSonAni_Walk,anim(a1)
loc_18B36:
move.b subtype(a0),d0
bpl.s loc_18B42
move.w #0,y_vel(a1)
loc_18B42:
btst #0,d0
beq.s loc_18B82
move.w #1,inertia(a1)
move.b #1,flip_angle(a1)
move.b #AniIDSonAni_Walk,anim(a1)
move.b #1,flips_remaining(a1)
move.b #8,flip_speed(a1)
btst #1,d0
bne.s loc_18B72
move.b #3,flips_remaining(a1)
loc_18B72:
btst #0,status(a1)
beq.s loc_18B82
neg.b flip_angle(a1)
neg.w inertia(a1)
loc_18B82:
andi.b #$C,d0
cmpi.b #4,d0
bne.s loc_18B98
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
loc_18B98:
cmpi.b #8,d0
bne.s loc_18BAA
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
loc_18BAA:
bclr #p1_pushing_bit,status(a0)
bclr #p2_pushing_bit,status(a0)
bclr #5,status(a1)
move.w #SndID_Spring,d0
jmp (PlaySound).l
; ===========================================================================
loc_18BC6:
cmpi.b #3,anim(a0)
beq.w return_18C7E
move.w x_pos(a0),d0
move.w d0,d1
addi.w #$28,d1
btst #0,status(a0)
beq.s loc_18BE8
move.w d0,d1
subi.w #$28,d0
loc_18BE8:
move.w y_pos(a0),d2
move.w d2,d3
subi.w #$18,d2
addi.w #$18,d3
lea (MainCharacter).w,a1 ; a1=character
btst #1,status(a1)
bne.s loc_18C3C
move.w inertia(a1),d4
btst #0,status(a0)
beq.s loc_18C10
neg.w d4
loc_18C10:
tst.w d4
bmi.s loc_18C3C
move.w x_pos(a1),d4
cmp.w d0,d4
blo.w loc_18C3C
cmp.w d1,d4
bhs.w loc_18C3C
move.w y_pos(a1),d4
cmp.w d2,d4
blo.w loc_18C3C
cmp.w d3,d4
bhs.w loc_18C3C
move.w d0,-(sp)
bsr.w loc_18AEE
move.w (sp)+,d0
loc_18C3C:
lea (Sidekick).w,a1 ; a1=character
btst #1,status(a1)
bne.s return_18C7E
move.w inertia(a1),d4
btst #0,status(a0)
beq.s loc_18C56
neg.w d4
loc_18C56:
tst.w d4
bmi.s return_18C7E
move.w x_pos(a1),d4
cmp.w d0,d4
blo.w return_18C7E
cmp.w d1,d4
bhs.w return_18C7E
move.w y_pos(a1),d4
cmp.w d2,d4
blo.w return_18C7E
cmp.w d3,d4
bhs.w return_18C7E
bsr.w loc_18AEE
return_18C7E:
rts
; ===========================================================================
; loc_18C80:
Obj41_Down:
move.w #$1B,d1
move.w #8,d2
move.w #$10,d3
move.w x_pos(a0),d4
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.w SolidObject_Always_SingleCharacter
cmpi.w #-2,d4
bne.s loc_18CA6
bsr.s loc_18CC6
loc_18CA6:
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
bsr.w SolidObject_Always_SingleCharacter
cmpi.w #-2,d4
bne.s loc_18CBC
bsr.s loc_18CC6
loc_18CBC:
lea (Ani_obj41).l,a1
bra.w AnimateSprite
; ===========================================================================
loc_18CC6:
move.w #$100,anim(a0)
subq.w #8,y_pos(a1)
move.w objoff_30(a0),y_vel(a1)
neg.w y_vel(a1)
move.b subtype(a0),d0
bpl.s loc_18CE6
move.w #0,x_vel(a1)
loc_18CE6:
btst #0,d0
beq.s loc_18D26
move.w #1,inertia(a1)
move.b #1,flip_angle(a1)
move.b #AniIDSonAni_Walk,anim(a1)
move.b #0,flips_remaining(a1)
move.b #4,flip_speed(a1)
btst #1,d0
bne.s loc_18D16
move.b #1,flips_remaining(a1)
loc_18D16:
btst #0,status(a1)
beq.s loc_18D26
neg.b flip_angle(a1)
neg.w inertia(a1)
loc_18D26:
andi.b #$C,d0
cmpi.b #4,d0
bne.s loc_18D3C
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
loc_18D3C:
cmpi.b #8,d0
bne.s loc_18D4E
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
loc_18D4E:
bset #1,status(a1)
bclr #3,status(a1)
move.b #2,routine(a1)
move.w #SndID_Spring,d0
jmp (PlaySound).l
; ===========================================================================
; loc_18D6A:
Obj41_DiagonallyUp:
move.w #$1B,d1
move.w #$10,d2
move.w x_pos(a0),d4
lea Obj41_SlopeData_DiagUp(pc),a2
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.w SlopedSolid_SingleCharacter
btst #p1_standing_bit,status(a0)
beq.s loc_18D92
bsr.s loc_18DB4
loc_18D92:
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
bsr.w SlopedSolid_SingleCharacter
btst #p2_standing_bit,status(a0)
beq.s loc_18DAA
bsr.s loc_18DB4
loc_18DAA:
lea (Ani_obj41).l,a1
bra.w AnimateSprite
; ===========================================================================
loc_18DB4:
btst #0,status(a0)
bne.s loc_18DCA
move.w x_pos(a0),d0
subq.w #4,d0
cmp.w x_pos(a1),d0
blo.s loc_18DD8
rts
; ===========================================================================
loc_18DCA:
move.w x_pos(a0),d0
addq.w #4,d0
cmp.w x_pos(a1),d0
bhs.s loc_18DD8
rts
; ===========================================================================
loc_18DD8:
move.w #$500,anim(a0)
move.w objoff_30(a0),y_vel(a1)
move.w objoff_30(a0),x_vel(a1)
addq.w #6,y_pos(a1)
addq.w #6,x_pos(a1)
bset #0,status(a1)
btst #0,status(a0)
bne.s loc_18E10
bclr #0,status(a1)
subi.w #$C,x_pos(a1)
neg.w x_vel(a1)
loc_18E10:
bset #1,status(a1)
bclr #3,status(a1)
move.b #AniIDSonAni_Spring,anim(a1)
move.b #2,routine(a1)
move.b subtype(a0),d0
btst #0,d0
beq.s loc_18E6C
move.w #1,inertia(a1)
move.b #1,flip_angle(a1)
move.b #AniIDSonAni_Walk,anim(a1)
move.b #1,flips_remaining(a1)
move.b #8,flip_speed(a1)
btst #1,d0
bne.s loc_18E5C
move.b #3,flips_remaining(a1)
loc_18E5C:
btst #0,status(a1)
beq.s loc_18E6C
neg.b flip_angle(a1)
neg.w inertia(a1)
loc_18E6C:
andi.b #$C,d0
cmpi.b #4,d0
bne.s loc_18E82
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
loc_18E82:
cmpi.b #8,d0
bne.s loc_18E94
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
loc_18E94:
move.w #SndID_Spring,d0
jmp (PlaySound).l
; ===========================================================================
; loc_18E9E:
Obj41_DiagonallyDown:
move.w #$1B,d1
move.w #$10,d2
move.w x_pos(a0),d4
lea Obj41_SlopeData_DiagDown(pc),a2
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.w SlopedSolid_SingleCharacter
cmpi.w #-2,d4
bne.s loc_18EC4
bsr.s loc_18EE6
loc_18EC4:
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
bsr.w SlopedSolid_SingleCharacter
cmpi.w #-2,d4
bne.s loc_18EDA
bsr.s loc_18EE6
loc_18EDA:
lea (Ani_obj41).l,a1
bra.w AnimateSprite
; ===========================================================================
rts
; ===========================================================================
loc_18EE6:
move.w #$500,anim(a0)
move.w objoff_30(a0),y_vel(a1)
neg.w y_vel(a1)
move.w objoff_30(a0),x_vel(a1)
subq.w #6,y_pos(a1)
addq.w #6,x_pos(a1)
bset #0,status(a1)
btst #0,status(a0)
bne.s loc_18F22
bclr #0,status(a1)
subi.w #$C,x_pos(a1)
neg.w x_vel(a1)
loc_18F22:
bset #1,status(a1)
bclr #3,status(a1)
move.b #2,routine(a1)
move.b subtype(a0),d0
btst #0,d0
beq.s loc_18F78
move.w #1,inertia(a1)
move.b #1,flip_angle(a1)
move.b #AniIDSonAni_Walk,anim(a1)
move.b #1,flips_remaining(a1)
move.b #8,flip_speed(a1)
btst #1,d0
bne.s loc_18F68
move.b #3,flips_remaining(a1)
loc_18F68:
btst #0,status(a1)
beq.s loc_18F78
neg.b flip_angle(a1)
neg.w inertia(a1)
loc_18F78:
andi.b #$C,d0
cmpi.b #4,d0
bne.s loc_18F8E
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
loc_18F8E:
cmpi.b #8,d0
bne.s loc_18FA0
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
loc_18FA0:
move.w #SndID_Spring,d0
jmp (PlaySound).l
; ===========================================================================
;byte_18FAA:
Obj41_SlopeData_DiagUp:
dc.b $10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10, $E, $C, $A, 8
dc.b 6, 4, 2, 0,$FE,$FC,$FC,$FC,$FC,$FC,$FC,$FC; 16
;byte_18FC6:
Obj41_SlopeData_DiagDown:
dc.b $F4,$F0,$F0,$F0,$F0,$F0,$F0,$F0,$F0,$F0,$F0,$F0,$F2,$F4,$F6,$F8
dc.b $FA,$FC,$FE, 0, 2, 4, 4, 4, 4, 4, 4, 4; 16
; animation script
; off_18FE2:
Ani_obj41: offsetTable
offsetTableEntry.w byte_18FEE ; 0
offsetTableEntry.w byte_18FF1 ; 1
offsetTableEntry.w byte_18FFD ; 2
offsetTableEntry.w byte_19000 ; 3
offsetTableEntry.w byte_1900C ; 4
offsetTableEntry.w byte_1900F ; 5
byte_18FEE:
dc.b $F
dc.b 0 ; 1
dc.b $FF ; 2
rev02even
byte_18FF1:
dc.b 0
dc.b 1 ; 1
dc.b 0 ; 2
dc.b 0 ; 3
dc.b 2 ; 4
dc.b 2 ; 5
dc.b 2 ; 6
dc.b 2 ; 7
dc.b 2 ; 8
dc.b 2 ; 9
dc.b $FD ; 10
dc.b 0 ; 11
rev02even
byte_18FFD:
dc.b $F
dc.b 3 ; 1
dc.b $FF ; 2
rev02even
byte_19000:
dc.b 0
dc.b 4 ; 1
dc.b 3 ; 2
dc.b 3 ; 3
dc.b 5 ; 4
dc.b 5 ; 5
dc.b 5 ; 6
dc.b 5 ; 7
dc.b 5 ; 8
dc.b 5 ; 9
dc.b $FD ; 10
dc.b 2 ; 11
rev02even
byte_1900C:
dc.b $F
dc.b 7 ; 1
dc.b $FF ; 2
rev02even
byte_1900F:
dc.b 0
dc.b 8 ; 1
dc.b 7 ; 2
dc.b 7 ; 3
dc.b 9 ; 4
dc.b 9 ; 5
dc.b 9 ; 6
dc.b 9 ; 7
dc.b 9 ; 8
dc.b 9 ; 9
dc.b $FD ; 10
dc.b 4 ; 11
even
; ----------------------------------------------------------------------------
; Primary sprite mappings for springs
; ----------------------------------------------------------------------------
Obj41_MapUnc_1901C: offsetTable
offsetTableEntry.w word_19048 ; 0
offsetTableEntry.w word_1905A ; 1
offsetTableEntry.w word_19064 ; 2
offsetTableEntry.w word_19076 ; 3
offsetTableEntry.w word_19088 ; 4
offsetTableEntry.w word_19092 ; 5
offsetTableEntry.w word_190A4 ; 6
offsetTableEntry.w word_190B6 ; 7
offsetTableEntry.w word_190D8 ; 8
offsetTableEntry.w word_190F2 ; 9
offsetTableEntry.w word_19114 ; $A
; -------------------------------------------------------------------------------
; Secondary sprite mappings for springs
; merged with the above mappings; can't split to file in a useful way...
; -------------------------------------------------------------------------------
Obj41_MapUnc_19032: offsetTable
offsetTableEntry.w word_19048 ; 0
offsetTableEntry.w word_1905A ; 1
offsetTableEntry.w word_19064 ; 2
offsetTableEntry.w word_19076 ; 3
offsetTableEntry.w word_19088 ; 4
offsetTableEntry.w word_19092 ; 5
offsetTableEntry.w word_190A4 ; 6
offsetTableEntry.w word_19136 ; 7
offsetTableEntry.w word_19158 ; 8
offsetTableEntry.w word_19172 ; 9
offsetTableEntry.w word_19194 ; $A
word_19048:
dc.w 2
dc.w $F00D, 0, 0,$FFF0
dc.w 5, 8, 4,$FFF8; 4
word_1905A:
dc.w 1
dc.w $F80D, 0, 0,$FFF0
word_19064:
dc.w 2
dc.w $E00D, 0, 0,$FFF0
dc.w $F007, $C, 6,$FFF8; 4
word_19076:
dc.w 2
dc.w $F003, 0, 0, 0
dc.w $F801, 4, 2,$FFF8; 4
word_19088:
dc.w 1
dc.w $F003, 0, 0,$FFF8
word_19092:
dc.w 2
dc.w $F003, 0, 0, $10
dc.w $F809, 6, 3,$FFF8; 4
word_190A4:
dc.w 2
dc.w $D,$1000,$1000,$FFF0
dc.w $F005,$1008,$1004,$FFF8; 4
word_190B6:
dc.w 4
dc.w $F00D, 0, 0,$FFF0
dc.w 5, 8, 4, 0; 4
dc.w $FB05, $C, 6,$FFF6; 8
dc.w 5,$201C,$200E,$FFF0; 12
word_190D8:
dc.w 3
dc.w $F60D, 0, 0,$FFEA
dc.w $605, 8, 4,$FFFA; 4
dc.w 5,$201C,$200E,$FFF0; 8
word_190F2:
dc.w 4
dc.w $E60D, 0, 0,$FFFB
dc.w $F605, 8, 4, $B; 4
dc.w $F30B, $10, 8,$FFF6; 8
dc.w 5,$201C,$200E,$FFF0; 12
word_19114:
dc.w 4
dc.w $D,$1000,$1000,$FFF0
dc.w $F005,$1008,$1004, 0; 4
dc.w $F505,$100C,$1006,$FFF6; 8
dc.w $F005,$301C,$300E,$FFF0; 12
word_19136:
dc.w 4
dc.w $F00D, 0, 0,$FFF0
dc.w 5, 8, 4, 0; 4
dc.w $FB05, $C, 6,$FFF6; 8
dc.w 5, $1C, $E,$FFF0; 12
word_19158:
dc.w 3
dc.w $F60D, 0, 0,$FFEA
dc.w $605, 8, 4,$FFFA; 4
dc.w 5, $1C, $E,$FFF0; 8
word_19172:
dc.w 4
dc.w $E60D, 0, 0,$FFFB
dc.w $F605, 8, 4, $B; 4
dc.w $F30B, $10, 8,$FFF6; 8
dc.w 5, $1C, $E,$FFF0; 12
word_19194:
dc.w 4
dc.w $D,$1000,$1000,$FFF0
dc.w $F005,$1008,$1004, 0; 4
dc.w $F505,$100C,$1006,$FFF6; 8
dc.w $F005,$101C,$100E,$FFF0; 12
; ===========================================================================
if gameRevision<2
nop
endif
; ----------------------------------------------------------------------------
; Object 0D - End of level sign post
; ----------------------------------------------------------------------------
; OST:
obj0D_spinframe = objoff_30 ; $30(a0)
obj0D_sparkleframe = objoff_34 ; $34(a0)
obj0D_finalanim = objoff_36 ; $36(a0) ; 4 if Tails only, 3 otherwise (determines what character to show)
; ----------------------------------------------------------------------------
Obj0D:
moveq #0,d0
move.b routine(a0),d0
move.w Obj0D_Index(pc,d0.w),d1
jsr Obj0D_Index(pc,d1.w)
lea (Ani_obj0D).l,a1
bsr.w AnimateSprite
bsr.w PLCLoad_Signpost
bra.w MarkObjGone
; ===========================================================================
; off_191D8: Obj_0D_subtbl: Obj0D_States:
Obj0D_Index: offsetTable
offsetTableEntry.w Obj0D_Init ; 0
offsetTableEntry.w Obj0D_Main ; 2
; ===========================================================================
; loc_191DC: Obj_0D_sub_0:
Obj0D_Init:
tst.w (Two_player_mode).w
beq.s loc_19208
move.l #Obj0D_MapUnc_19656,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_2p_Signpost,0,0),art_tile(a0)
move.b #-1,(Signpost_prev_frame).w
moveq #0,d1
move.w #$1020,d1
move.w #-$80,d4
moveq #0,d5
bsr.w loc_19564
bra.s loc_1922C
; ---------------------------------------------------------------------------
loc_19208:
cmpi.w #metropolis_zone_act_2,(Current_ZoneAndAct).w
beq.s loc_1921E
tst.b (Current_Act).w
beq.s loc_1921E
move.w #0,x_pos(a0)
rts
; ---------------------------------------------------------------------------
loc_1921E:
move.l #Obj0D_MapUnc_195BE,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Signpost,0,0),art_tile(a0)
loc_1922C:
addq.b #2,routine(a0) ; => Obj0D_Main
bsr.w Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$18,width_pixels(a0)
move.b #4,priority(a0)
move.w #$3C3C,(Loser_Time_Left).w
; loc_1924C: Obj_0D_sub_2:
Obj0D_Main:
tst.b (Update_HUD_timer).w
beq.w loc_192D6
lea (MainCharacter).w,a1 ; a1=character
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
bcs.s loc_192D6
cmpi.w #$20,d0
bhs.s loc_192D6
move.w #SndID_Signpost,d0
jsr (PlayMusic).l ; play spinning sound
clr.b (Update_HUD_timer).w
move.w #1,anim(a0)
move.w #0,obj0D_spinframe(a0)
move.w (Camera_Max_X_pos).w,(Camera_Min_X_pos).w ; lock screen
move.b #2,routine_secondary(a0) ; => Obj0D_Main_State2
cmpi.b #$C,(Loser_Time_Left).w
bhi.s loc_192A0
move.w (Level_Music).w,d0
jsr (PlayMusic).l ; play zone music
loc_192A0:
tst.b obj0D_finalanim(a0)
bne.w loc_19350
move.b #3,obj0D_finalanim(a0)
cmpi.w #2,(Player_mode).w
bne.s loc_192BC
move.b #4,obj0D_finalanim(a0)
loc_192BC:
tst.w (Two_player_mode).w
beq.w loc_19350
move.w #$3C3C,(Loser_Time_Left).w
move.w #SndID_Signpost2P,d0 ; play different spinning sound
jsr (PlaySound).l
bra.s loc_19350
; ---------------------------------------------------------------------------
loc_192D6:
tst.w (Two_player_mode).w
beq.s loc_19350
tst.b (Update_HUD_timer_2P).w
beq.s loc_19350
lea (Sidekick).w,a1 ; a1=character
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
bcs.s loc_19350
cmpi.w #$20,d0
bhs.s loc_19350
move.w #SndID_Signpost,d0
jsr (PlayMusic).l
clr.b (Update_HUD_timer_2P).w
move.w #1,anim(a0)
move.w #0,obj0D_spinframe(a0)
move.w (Tails_Max_X_pos).w,(Tails_Min_X_pos).w
move.b #2,routine_secondary(a0) ; => Obj0D_Main_State2
cmpi.b #$C,(Loser_Time_Left).w
bhi.s loc_1932E
move.w (Level_Music).w,d0
jsr (PlayMusic).l
loc_1932E:
tst.b obj0D_finalanim(a0)
bne.s loc_19350
move.b #4,obj0D_finalanim(a0)
tst.w (Two_player_mode).w
beq.s loc_19350
move.w #$3C3C,(Loser_Time_Left).w
move.w #SndID_Signpost2P,d0
jsr (PlaySound).l
loc_19350:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj0D_Main_States(pc,d0.w),d1
jmp Obj0D_Main_States(pc,d1.w)
; ===========================================================================
Obj0D_Main_States: offsetTable
offsetTableEntry.w Obj0D_Main_StateNull ; 0
offsetTableEntry.w Obj0D_Main_State2 ; 2
offsetTableEntry.w Obj0D_Main_State3 ; 4
offsetTableEntry.w Obj0D_Main_State4 ; 6
; ===========================================================================
; return_19366:
Obj0D_Main_StateNull:
rts
; ===========================================================================
; loc_19368:
Obj0D_Main_State2:
subq.w #1,obj0D_spinframe(a0)
bpl.s loc_19398
move.w #$3C,obj0D_spinframe(a0)
addq.b #1,anim(a0)
cmpi.b #3,anim(a0)
bne.s loc_19398
move.b #4,routine_secondary(a0) ; => Obj0D_Main_State3
move.b obj0D_finalanim(a0),anim(a0)
tst.w (Two_player_mode).w
beq.s loc_19398
move.b #6,routine_secondary(a0) ; => Obj0D_Main_State4
loc_19398:
subq.w #1,objoff_32(a0)
bpl.s return_19406
move.w #$B,objoff_32(a0)
moveq #0,d0
move.b obj0D_sparkleframe(a0),d0
addq.b #2,obj0D_sparkleframe(a0)
andi.b #$E,obj0D_sparkleframe(a0)
lea Obj0D_RingSparklePositions(pc,d0.w),a2
bsr.w SingleObjLoad
bne.s return_19406
_move.b #ObjID_Ring,id(a1) ; load obj25 (a ring) for the sparkly effects over the signpost
move.b #6,routine(a1) ; => Obj_25_sub_6
move.b (a2)+,d0
ext.w d0
add.w x_pos(a0),d0
move.w d0,x_pos(a1)
move.b (a2)+,d0
ext.w d0
add.w y_pos(a0),d0
move.w d0,y_pos(a1)
move.l #Obj25_MapUnc_12382,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_Ring,1,0),art_tile(a1)
bsr.w Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #2,priority(a1)
move.b #8,width_pixels(a1)
return_19406:
rts
; ===========================================================================
; byte_19408:
Obj0D_RingSparklePositions:
dc.b -24,-16 ; 1
dc.b 8, 8 ; 3
dc.b -16, 0 ; 5
dc.b 24, -8 ; 7
dc.b 0, -8 ; 9
dc.b 16, 0 ; 11
dc.b -24, 8 ; 13
dc.b 24, 16 ; 15
; ===========================================================================
; loc_19418:
Obj0D_Main_State3:
tst.w (Debug_placement_mode).w
bne.w return_194D0
btst #1,(MainCharacter+status).w
bne.s loc_19434
move.b #1,(Control_Locked).w
move.w #(button_right_mask<<8)|0,(Ctrl_1_Logical).w
loc_19434:
tst.b (MainCharacter).w
beq.s loc_1944C
move.w (MainCharacter+x_pos).w,d0
move.w (Camera_Max_X_pos).w,d1
addi.w #$128,d1
cmp.w d1,d0
blo.w return_194D0
loc_1944C:
move.b #0,routine_secondary(a0) ; => Obj0D_Main_StateNull
;loc_19452:
Load_EndOfAct:
lea (MainCharacter).w,a1 ; a1=character
clr.b status_secondary(a1)
clr.b (Update_HUD_timer).w
bsr.w SingleObjLoad
bne.s +
move.b #ObjID_Results,id(a1) ; load obj3A (end of level results screen)
+
moveq #PLCID_Results,d0
cmpi.w #2,(Player_mode).w
bne.s +
moveq #PLCID_ResultsTails,d0
+
jsr (LoadPLC2).l
move.b #1,(Update_Bonus_score).w
moveq #0,d0
move.b (Timer_minute).w,d0
mulu.w #$3C,d0
moveq #0,d1
move.b (Timer_second).w,d1
add.w d1,d0
divu.w #$F,d0
moveq #$14,d1
cmp.w d1,d0
blo.s +
move.w d1,d0
+
add.w d0,d0
move.w TimeBonuses(pc,d0.w),(Bonus_Countdown_1).w
move.w (Ring_count).w,d0
mulu.w #$A,d0
move.w d0,(Bonus_Countdown_2).w
clr.w (Total_Bonus_Countdown).w
clr.w (Bonus_Countdown_3).w
tst.w (Perfect_rings_left).w
bne.s +
move.w #5000,(Bonus_Countdown_3).w
+
move.w #MusID_EndLevel,d0
jsr (PlayMusic).l
return_194D0:
rts
; ===========================================================================
; word_194D2:
TimeBonuses:
dc.w 5000, 5000, 1000, 500, 400, 400, 300, 300
dc.w 200, 200, 200, 200, 100, 100, 100, 100
dc.w 50, 50, 50, 50, 0
; ===========================================================================
; loc_194FC:
Obj0D_Main_State4:
subq.w #1,obj0D_spinframe(a0)
bpl.s return_19532
tst.b (Time_Over_flag).w
bne.s return_19532
tst.b (Time_Over_flag_2P).w
bne.s return_19532
tst.b (Update_HUD_timer).w
bne.s return_19532
tst.b (Update_HUD_timer_2P).w
bne.s return_19532
move.b #0,(Last_star_pole_hit).w
move.b #0,(Last_star_pole_hit_2P).w
move.b #GameModeID_2PResults,(Game_Mode).w ; => TwoPlayerResults
move.w #VsRSID_Act,(Results_Screen_2P).w
return_19532:
rts
; ===========================================================================
PLCLoad_Signpost:
tst.w (Two_player_mode).w
beq.s return_1958C
moveq #0,d0
move.b mapping_frame(a0),d0
cmp.b (Signpost_prev_frame).w,d0
beq.s return_1958C
move.b d0,(Signpost_prev_frame).w
lea (Obj0D_MapRUnc_196EE).l,a2
add.w d0,d0
adda.w (a2,d0.w),a2
move.w (a2)+,d5
subq.w #1,d5
bmi.s return_1958C
move.w #tiles_to_bytes(ArtTile_ArtUnc_Signpost),d4
loc_19560:
moveq #0,d1
move.w (a2)+,d1
loc_19564:
move.w d1,d3
lsr.w #8,d3
andi.w #$F0,d3
addi.w #$10,d3
andi.w #$FFF,d1
lsl.l #5,d1
addi.l #ArtUnc_Signpost,d1
move.w d4,d2
add.w d3,d4
add.w d3,d4
jsr (QueueDMATransfer).l
dbf d5,loc_19560
return_1958C:
rts
; ===========================================================================
; animation script
; off_1958E:
Ani_obj0D: offsetTable
offsetTableEntry.w byte_19598 ; 0
offsetTableEntry.w byte_1959B ; 1
offsetTableEntry.w byte_195A9 ; 2
offsetTableEntry.w byte_195B7 ; 3
offsetTableEntry.w byte_195BA ; 4
byte_19598: dc.b $0F, $02, $FF
rev02even
byte_1959B: dc.b $01, $02, $03, $04, $05, $01, $03, $04, $05, $00, $03, $04, $05, $FF
rev02even
byte_195A9: dc.b $01, $02, $03, $04, $05, $01, $03, $04, $05, $00, $03, $04, $05, $FF
rev02even
byte_195B7: dc.b $0F, $00, $FF
rev02even
byte_195BA: dc.b $0F, $01, $FF
even
; -------------------------------------------------------------------------------
; sprite mappings - Primary sprite table for object 0D (signpost)
; -------------------------------------------------------------------------------
; SprTbl_0D_Primary:
Obj0D_MapUnc_195BE: BINCLUDE "mappings/sprite/obj0D_a.bin"
; -------------------------------------------------------------------------------
; sprite mappings - Secondary sprite table for object 0D (signpost)
; -------------------------------------------------------------------------------
; SprTbl_0D_Scndary:
Obj0D_MapUnc_19656: BINCLUDE "mappings/sprite/obj0D_b.bin"
; -------------------------------------------------------------------------------
; dynamic pattern loading cues
; -------------------------------------------------------------------------------
Obj0D_MapRUnc_196EE: BINCLUDE "mappings/spriteDPLC/obj0D.bin"
; ===========================================================================
if gameRevision<2
nop
endif
; ---------------------------------------------------------------------------
; Solid object subroutines (includes spikes, blocks, rocks etc)
; These check collision of Sonic/Tails with objects on the screen
;
; input variables:
; d1 = object width
; d2 = object height / 2 (when jumping)
; d3 = object height / 2 (when walking)
; d4 = object x-axis position
;
; address registers:
; a0 = the object to check collision with
; a1 = sonic or tails (set inside these subroutines)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_19718:
SolidObject:
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp) ; store input registers
bsr.s + ; first check collision with Sonic
movem.l (sp)+,d1-d4 ; restore input registers
lea (Sidekick).w,a1 ; a1=character ; now check collision with Tails
tst.b render_flags(a1)
bpl.w return_19776 ; return if no Tails
addq.b #1,d6
+
btst d6,status(a0)
beq.w SolidObject_OnScreenTest
move.w d1,d2
add.w d2,d2
btst #1,status(a1)
bne.s loc_1975A
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.s loc_1975A
cmp.w d2,d0
blo.s loc_1976E
loc_1975A:
bclr #3,status(a1)
bset #1,status(a1)
bclr d6,status(a0)
moveq #0,d4
rts
; ---------------------------------------------------------------------------
loc_1976E:
move.w d4,d2
bsr.w MvSonicOnPtfm
moveq #0,d4
return_19776:
rts
; ===========================================================================
; there are a few slightly different SolidObject functions
; specialized for certain objects, in this case, obj74 and obj30
; These check for solidity even if the object is off-screen
; loc_19778: SolidObject74_30:
SolidObject_Always:
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.s SolidObject_Always_SingleCharacter
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
addq.b #1,d6
;loc_1978E:
SolidObject_Always_SingleCharacter:
btst d6,status(a0)
beq.w SolidObject_cont
move.w d1,d2
add.w d2,d2
btst #1,status(a1)
bne.s loc_197B2
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.s loc_197B2
cmp.w d2,d0
blo.s loc_197C6
loc_197B2:
bclr #3,status(a1)
bset #1,status(a1)
bclr d6,status(a0)
moveq #0,d4
rts
; ---------------------------------------------------------------------------
loc_197C6:
move.w d4,d2
bsr.w MvSonicOnPtfm
moveq #0,d4
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to collide Sonic/Tails with the top of a sloped solid like diagonal springs
; ---------------------------------------------------------------------------
;
; input variables:
; d1 = object width
; d2 = object height / 2 (when jumping)
; d3 = object height / 2 (when walking)
; d4 = object x-axis position
;
; address registers:
; a0 = the object to check collision with
; a1 = sonic or tails (set inside these subroutines)
; a2 = height data for slope
; loc_197D0: SolidObject86_30:
SlopedSolid:
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.s SlopedSolid_SingleCharacter
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
addq.b #1,d6
; this gets called from a few more places...
; loc_197E6: SolidObject_Simple:
SlopedSolid_SingleCharacter:
btst d6,status(a0)
beq.w SlopedSolid_cont
move.w d1,d2
add.w d2,d2
btst #1,status(a1)
bne.s loc_1980A
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.s loc_1980A
cmp.w d2,d0
blo.s loc_1981E
loc_1980A:
bclr #3,status(a1)
bset #1,status(a1)
bclr d6,status(a0)
moveq #0,d4
rts
; ---------------------------------------------------------------------------
loc_1981E:
move.w d4,d2
bsr.w MvSonicOnSlope
moveq #0,d4
rts
; ===========================================================================
; unused/dead code for some SolidObject check
; This is for a sloped object that is sloped at the top and at the bottom.
; SolidObject_Unk: loc_19828:
;DoubleSlopedSolid:
; a0=object
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.s +
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
addq.b #1,d6
+
btst d6,status(a0)
beq.w DoubleSlopedSolid_cont
move.w d1,d2
add.w d2,d2
btst #1,status(a1)
bne.s loc_19862
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.s loc_19862
cmp.w d2,d0
blo.s loc_19876
loc_19862:
bclr #3,status(a1)
bset #1,status(a1)
bclr d6,status(a0)
moveq #0,d4
rts
; ---------------------------------------------------------------------------
loc_19876:
move.w d4,d2
bsr.w MvSonicOnDoubleSlope
moveq #0,d4
rts
; ===========================================================================
; loc_19880:
SolidObject45:
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.s loc_19896
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
addq.b #1,d6
loc_19896:
btst d6,status(a0)
beq.w SolidObject45_cont
btst #1,status(a1)
bne.s loc_198B8
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.s loc_198B8
add.w d1,d1
cmp.w d1,d0
blo.s loc_198CC
loc_198B8:
bclr #3,status(a1)
bset #1,status(a1)
bclr d6,status(a0)
moveq #0,d4
rts
; ---------------------------------------------------------------------------
loc_198CC:
; Inlined call to MvSonicOnPtfm
move.w y_pos(a0),d0
sub.w d2,d0
add.w d3,d0
moveq #0,d1
move.b y_radius(a1),d1
sub.w d1,d0
move.w d0,y_pos(a1)
sub.w x_pos(a0),d4
sub.w d4,x_pos(a1)
moveq #0,d4
rts
; ===========================================================================
; loc_198EC: SolidObject45_alt:
SolidObject45_cont:
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.w SolidObject_TestClearPush
move.w d1,d4
add.w d4,d4
cmp.w d4,d0
bhi.w SolidObject_TestClearPush
move.w y_pos(a0),d5
add.w d3,d5
move.b y_radius(a1),d3
ext.w d3
add.w d3,d2
move.w y_pos(a1),d3
sub.w d5,d3
addq.w #4,d3
add.w d2,d3
bmi.w SolidObject_TestClearPush
move.w d2,d4
add.w d4,d4
cmp.w d4,d3
bhs.w SolidObject_TestClearPush
bra.w SolidObject_ChkBounds
; ===========================================================================
; loc_1992E: SolidObject86_30_alt:
SlopedSolid_cont:
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.w SolidObject_TestClearPush
move.w d1,d3
add.w d3,d3
cmp.w d3,d0
bhi.w SolidObject_TestClearPush
move.w d0,d5
btst #0,render_flags(a0)
beq.s +
not.w d5
add.w d3,d5
+
lsr.w #1,d5
move.b (a2,d5.w),d3
sub.b (a2),d3
ext.w d3
move.w y_pos(a0),d5
sub.w d3,d5
move.b y_radius(a1),d3
ext.w d3
add.w d3,d2
move.w y_pos(a1),d3
sub.w d5,d3
addq.w #4,d3
add.w d2,d3
bmi.w SolidObject_TestClearPush
move.w d2,d4
add.w d4,d4
cmp.w d4,d3
bhs.w SolidObject_TestClearPush
bra.w SolidObject_ChkBounds
; ===========================================================================
; unused/dead code
; loc_19988: SolidObject_Unk_cont:
DoubleSlopedSolid_cont:
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.w SolidObject_TestClearPush
move.w d1,d3
add.w d3,d3
cmp.w d3,d0
bhi.w SolidObject_TestClearPush
move.w d0,d5
btst #0,render_flags(a0)
beq.s +
not.w d5
add.w d3,d5
+
andi.w #$FFFE,d5
move.b (a2,d5.w),d3
move.b 1(a2,d5.w),d2
ext.w d2
ext.w d3
move.w y_pos(a0),d5
sub.w d3,d5
move.w y_pos(a1),d3
sub.w d5,d3
move.b y_radius(a1),d5
ext.w d5
add.w d5,d3
addq.w #4,d3
bmi.w SolidObject_TestClearPush
add.w d5,d2
move.w d2,d4
add.w d5,d4
cmp.w d4,d3
bhs.w SolidObject_TestClearPush
bra.w SolidObject_ChkBounds
; ===========================================================================
; loc_199E8: SolidObject_cont:
SolidObject_OnScreenTest:
tst.b render_flags(a0)
bpl.w SolidObject_TestClearPush
;loc_199F0:
SolidObject_cont:
; We now perform the x portion of a bounding box check. To do this, we assume a
; coordinate system where the x origin is at the object's left edge.
move.w x_pos(a1),d0 ; load Sonic's x position...
sub.w x_pos(a0),d0 ; ... and calculate his x position relative to the object
add.w d1,d0 ; assume object's left edge is at (0,0). This is also Sonic's distance to the object's left edge.
bmi.w SolidObject_TestClearPush ; branch, if Sonic is outside the object's left edge
move.w d1,d3
add.w d3,d3 ; calculate object's width
cmp.w d3,d0
bhi.w SolidObject_TestClearPush ; branch, if Sonic is outside the object's right edge
; We now perform the y portion of a bounding box check. To do this, we assume a
; coordinate system where the y origin is at the highest y position relative to the object
; at which Sonic would still collide with it. This point is
; y_pos(object) - width(object)/2 - y_radius(Sonic) - 4,
; where object is stored in (a0), Sonic in (a1), and height(object)/2 in d2. This way
; of doing it causes the object's hitbox to be vertically off-center by -4 pixels.
move.b y_radius(a1),d3 ; load Sonic's y radius
ext.w d3
add.w d3,d2 ; calculate maximum distance for a top collision
move.w y_pos(a1),d3 ; load Sonic's y position...
sub.w y_pos(a0),d3 ; ... and calculate his y position relative to the object
addq.w #4,d3 ; assume a slightly lower position for Sonic
add.w d2,d3 ; assume the highest position where Sonic would still be colliding with the object to be (0,0)
bmi.w SolidObject_TestClearPush ; branch, if Sonic is above this point
andi.w #$7FF,d3
move.w d2,d4
add.w d4,d4 ; calculate minimum distance for a bottom collision
cmp.w d4,d3
bhs.w SolidObject_TestClearPush ; branch, if Sonic is below this point
;loc_19A2E:
SolidObject_ChkBounds:
tst.b obj_control(a1)
bmi.w SolidObject_TestClearPush ; branch, if object collisions are disabled for Sonic
cmpi.b #6,routine(a1) ; is Sonic dead?
bhs.w loc_19AEA ; if yes, branch
tst.w (Debug_placement_mode).w
bne.w loc_19AEA ; branch, if in debug mode
move.w d0,d5
cmp.w d0,d1
bhs.s + ; branch, if Sonic is to the object's left
add.w d1,d1
sub.w d1,d0
move.w d0,d5 ; calculate Sonic's distance to the object's right edge...
neg.w d5 ; ... and calculate the absolute value
+
move.w d3,d1
cmp.w d3,d2
bhs.s +
subq.w #4,d3
sub.w d4,d3
move.w d3,d1
neg.w d1
+
cmp.w d1,d5
bhi.w loc_19AEE ; branch, if horizontal distance is greater than vertical distance
loc_19A6A:
cmpi.w #4,d1
bls.s loc_19AB6
tst.w d0
beq.s loc_19A90
bmi.s loc_19A7E
tst.w x_vel(a1)
bmi.s loc_19A90
bra.s loc_19A84
; ===========================================================================
loc_19A7E:
tst.w x_vel(a1)
bpl.s loc_19A90
loc_19A84:
move.w #0,inertia(a1)
move.w #0,x_vel(a1)
loc_19A90:
sub.w d0,x_pos(a1)
btst #1,status(a1)
bne.s loc_19AB6
move.l d6,d4
addq.b #pushing_bit_delta,d4 ; Character is pushing, not standing
bset d4,status(a0)
bset #5,status(a1)
move.w d6,d4
addi.b #($10-p1_standing_bit+p1_touch_side_bit),d4
bset d4,d6 ; This sets bits 0 (Sonic) or 1 (Tails) of high word of d6
moveq #1,d4
rts
; ===========================================================================
loc_19AB6:
bsr.s loc_19ADC
move.w d6,d4
addi.b #($10-p1_standing_bit+p1_touch_side_bit),d4
bset d4,d6 ; This sets bits 0 (Sonic) or 1 (Tails) of high word of d6
moveq #1,d4
rts
; ===========================================================================
;loc_19AC4:
SolidObject_TestClearPush:
move.l d6,d4
addq.b #pushing_bit_delta,d4
btst d4,status(a0)
beq.s loc_19AEA
cmpi.b #AniIDSonAni_Roll,anim(a1)
beq.s loc_19ADC
move.w #AniIDSonAni_Run,anim(a1)
loc_19ADC:
move.l d6,d4
addq.b #pushing_bit_delta,d4
bclr d4,status(a0)
bclr #5,status(a1)
loc_19AEA:
moveq #0,d4
rts
; ===========================================================================
loc_19AEE:
tst.w d3
bmi.s loc_19B06
cmpi.w #$10,d3
blo.s loc_19B56
cmpi.b #ObjID_LauncherSpring,id(a0)
bne.s SolidObject_TestClearPush
cmpi.w #$14,d3
blo.s loc_19B56
bra.s SolidObject_TestClearPush
; ===========================================================================
loc_19B06:
tst.w y_vel(a1)
beq.s loc_19B28
bpl.s loc_19B1C
tst.w d3
bpl.s loc_19B1C
sub.w d3,y_pos(a1)
move.w #0,y_vel(a1)
loc_19B1C:
move.w d6,d4
addi.b #($10-p1_standing_bit+p1_touch_bottom_bit),d4
bset d4,d6 ; This sets bits 2 (Sonic) or 3 (Tails) of high word of d6
moveq #-2,d4
rts
; ===========================================================================
loc_19B28:
btst #1,status(a1)
bne.s loc_19B1C
mvabs.w d0,d4
cmpi.w #$10,d4
blo.w loc_19A6A
move.l a0,-(sp)
movea.l a1,a0
jsr (KillCharacter).l
movea.l (sp)+,a0 ; load 0bj address
move.w d6,d4
addi.b #($10-p1_standing_bit+p1_touch_bottom_bit),d4
bset d4,d6 ; This sets bits 2 (Sonic) or 3 (Tails) of high word of d6
moveq #-2,d4
rts
; ===========================================================================
loc_19B56:
subq.w #4,d3
moveq #0,d1
move.b width_pixels(a0),d1
move.w d1,d2
add.w d2,d2
add.w x_pos(a1),d1
sub.w x_pos(a0),d1
bmi.s loc_19B8E
cmp.w d2,d1
bhs.s loc_19B8E
tst.w y_vel(a1)
bmi.s loc_19B8E
sub.w d3,y_pos(a1)
subq.w #1,y_pos(a1)
bsr.w RideObject_SetRide
move.w d6,d4
addi.b #($10-p1_standing_bit+p1_touch_top_bit),d4
bset d4,d6 ; This sets bits 4 (Sonic) or 5 (Tails) of high word of d6
moveq #-1,d4
rts
; ===========================================================================
loc_19B8E:
moveq #0,d4
rts
; ===========================================================================
; Subroutine to change Sonic's position with a platform
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_19B92:
MvSonicOnPtfm:
move.w y_pos(a0),d0
sub.w d3,d0
bra.s loc_19BA2
; ===========================================================================
; a couple lines of unused/leftover/dead code from Sonic 1 ; a0=object
move.w y_pos(a0),d0
subi.w #9,d0
loc_19BA2:
tst.b obj_control(a1)
bmi.s return_19BCA
cmpi.b #6,routine(a1)
bhs.s return_19BCA
tst.w (Debug_placement_mode).w
bne.s return_19BCA
moveq #0,d1
move.b y_radius(a1),d1
sub.w d1,d0
move.w d0,y_pos(a1)
sub.w x_pos(a0),d2
sub.w d2,x_pos(a1)
return_19BCA:
rts
; ===========================================================================
;loc_19BCC:
MvSonicOnSlope:
btst #3,status(a1)
beq.s return_19C0C
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
lsr.w #1,d0
btst #0,render_flags(a0)
beq.s loc_19BEC
not.w d0
add.w d1,d0
loc_19BEC:
move.b (a2,d0.w),d1
ext.w d1
move.w y_pos(a0),d0
sub.w d1,d0
moveq #0,d1
move.b y_radius(a1),d1
sub.w d1,d0
move.w d0,y_pos(a1)
sub.w x_pos(a0),d2
sub.w d2,x_pos(a1)
return_19C0C:
rts
; ===========================================================================
; unused/dead code.
; loc_19C0E:
MvSonicOnDoubleSlope:
btst #3,status(a1)
beq.s return_19C0C
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
btst #0,render_flags(a0)
beq.s loc_19C2C
not.w d0
add.w d1,d0
loc_19C2C:
andi.w #$FFFE,d0
bra.s loc_19BEC
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to collide Sonic/Tails with the top of a platform
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;
; input variables:
; d1 = object width
; d3 = object height / 2
; d4 = object x-axis position
;
; address registers:
; a0 = the object to check collision with
; a1 = sonic or tails (set inside these subroutines)
; loc_19C32:
PlatformObject:
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.s PlatformObject_SingleCharacter
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
addq.b #1,d6
; loc_19C48:
PlatformObject_SingleCharacter:
btst d6,status(a0)
beq.w PlatformObject_cont
move.w d1,d2
add.w d2,d2
btst #1,status(a1)
bne.s +
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.s +
cmp.w d2,d0
blo.s loc_19C80
+
bclr #3,status(a1)
bset #1,status(a1)
bclr d6,status(a0)
moveq #0,d4
rts
; ---------------------------------------------------------------------------
loc_19C80:
move.w d4,d2
bsr.w MvSonicOnPtfm
moveq #0,d4
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to collide Sonic/Tails with the top of a sloped platform like a seesaw
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;
; input variables:
; d1 = object width
; d3 = object height
; d4 = object x-axis position
;
; address registers:
; a0 = the object to check collision with
; a1 = sonic or tails (set inside these subroutines)
; a2 = height data for slope
; loc_19C8A: SlopeObject:
SlopedPlatform:
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.s SlopedPlatform_SingleCharacter
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
addq.b #1,d6
; loc_19CA0:
SlopedPlatform_SingleCharacter:
btst d6,status(a0)
beq.w SlopedPlatform_cont
move.w d1,d2
add.w d2,d2
btst #1,status(a1)
bne.s loc_19CC4
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.s loc_19CC4
cmp.w d2,d0
blo.s loc_19CD8
loc_19CC4:
bclr #3,status(a1)
bset #1,status(a1)
bclr d6,status(a0)
moveq #0,d4
rts
; ---------------------------------------------------------------------------
loc_19CD8:
move.w d4,d2
bsr.w MvSonicOnSlope
moveq #0,d4
rts
; ===========================================================================
; Identical to PlatformObject.
;loc_19CE2:
PlatformObject2:
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.s loc_19CF8
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
addq.b #1,d6
loc_19CF8:
btst d6,status(a0)
beq.w PlatformObject2_cont
move.w d1,d2
add.w d2,d2
btst #1,status(a1)
bne.s loc_19D1C
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.s loc_19D1C
cmp.w d2,d0
blo.s loc_19D30
loc_19D1C:
bclr #3,status(a1)
bset #1,status(a1)
bclr d6,status(a0)
moveq #0,d4
rts
; ===========================================================================
loc_19D30:
move.w d4,d2
bsr.w MvSonicOnPtfm
moveq #0,d4
rts
; ===========================================================================
; Almost identical to PlatformObject, except that this function does nothing if
; the character is already standing on a platform. Used only by the elevators
; in CNZ.
;loc_19D3A:
PlatformObjectD5:
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.s loc_19D50
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
addq.b #1,d6
loc_19D50:
btst d6,status(a0)
bne.s loc_19D62
btst #3,status(a1)
bne.s loc_19D8E
bra.w PlatformObject_cont
; ===========================================================================
loc_19D62:
move.w d1,d2
add.w d2,d2
btst #1,status(a1)
bne.s loc_19D7E
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.s loc_19D7E
cmp.w d2,d0
blo.s loc_19D92
loc_19D7E:
bclr #3,status(a1)
bset #1,status(a1)
bclr d6,status(a0)
loc_19D8E:
moveq #0,d4
rts
; ===========================================================================
loc_19D92:
move.w d4,d2
bsr.w MvSonicOnPtfm
moveq #0,d4
rts
; ===========================================================================
; Used only by EHZ/HPZ log bridges. Very similar to PlatformObject_cont, but
; d2 already has the full width of the log.
;loc_19D9C:
PlatformObject11_cont:
tst.w y_vel(a1)
bmi.w return_19E8E
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.w return_19E8E
cmp.w d2,d0
bhs.w return_19E8E
bra.s loc_19DD8
; ===========================================================================
;loc_19DBA:
PlatformObject_cont:
tst.w y_vel(a1)
bmi.w return_19E8E
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.w return_19E8E
add.w d1,d1
cmp.w d1,d0
bhs.w return_19E8E
loc_19DD8:
move.w y_pos(a0),d0
sub.w d3,d0
;loc_19DDE:
PlatformObject_ChkYRange:
move.w y_pos(a1),d2
move.b y_radius(a1),d1
ext.w d1
add.w d2,d1
addq.w #4,d1
sub.w d1,d0
bhi.w return_19E8E
cmpi.w #-$10,d0
blo.w return_19E8E
tst.b obj_control(a1)
bmi.w return_19E8E
cmpi.b #6,routine(a1)
bhs.w return_19E8E
add.w d0,d2
addq.w #3,d2
move.w d2,y_pos(a1)
;loc_19E14:
RideObject_SetRide:
btst #3,status(a1)
beq.s loc_19E30
moveq #0,d0
move.b interact(a1),d0
if object_size=$40
lsl.w #6,d0
else
mulu.w #object_size,d0
endif
addi.l #Object_RAM,d0
movea.l d0,a3 ; a3=object
bclr d6,status(a3)
loc_19E30:
move.w a0,d0
subi.w #Object_RAM,d0
if object_size=$40
lsr.w #6,d0
else
divu.w #object_size,d0
endif
andi.w #$7F,d0
move.b d0,interact(a1)
move.b #0,angle(a1)
move.w #0,y_vel(a1)
move.w x_vel(a1),inertia(a1)
btst #1,status(a1)
beq.s loc_19E7E
move.l a0,-(sp)
movea.l a1,a0
move.w a0,d1
subi.w #Object_RAM,d1
bne.s loc_19E76
cmpi.w #2,(Player_mode).w
beq.s loc_19E76
jsr (Sonic_ResetOnFloor_Part2).l
bra.s loc_19E7C
; ===========================================================================
loc_19E76:
jsr (Tails_ResetOnFloor_Part2).l
loc_19E7C:
movea.l (sp)+,a0 ; a0=character
loc_19E7E:
bset #3,status(a1)
bclr #1,status(a1)
bset d6,status(a0)
return_19E8E:
rts
; ===========================================================================
;loc_19E90:
SlopedPlatform_cont:
tst.w y_vel(a1)
bmi.w return_19E8E
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.s return_19E8E
add.w d1,d1
cmp.w d1,d0
bhs.s return_19E8E
btst #0,render_flags(a0)
beq.s loc_19EB6
not.w d0
add.w d1,d0
loc_19EB6:
lsr.w #1,d0
move.b (a2,d0.w),d3
ext.w d3
move.w y_pos(a0),d0
sub.w d3,d0
bra.w PlatformObject_ChkYRange
; ===========================================================================
; Basically identical to PlatformObject_cont
;loc_19EC8:
PlatformObject2_cont:
tst.w y_vel(a1)
bmi.w return_19E8E
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d1,d0
bmi.w return_19E8E
add.w d1,d1
cmp.w d1,d0
bhs.w return_19E8E
move.w y_pos(a0),d0
sub.w d3,d0
bra.w PlatformObject_ChkYRange
; ===========================================================================
; If a character is being dragged through terrain by this object, drop the
; character on terrain instead.
;loc_19EF0:
DropOnFloor:
lea (MainCharacter).w,a1 ; a1=character
btst #p1_standing_bit,status(a0)
beq.s loc_19F1E
jsr (ChkFloorEdge2).l
tst.w d1
beq.s loc_19F08
bpl.s loc_19F1E
loc_19F08:
lea (MainCharacter).w,a1 ; a1=character
bclr #3,status(a1)
bset #1,status(a1)
bclr #p1_standing_bit,status(a0)
loc_19F1E:
lea (Sidekick).w,a1 ; a1=character
btst #p2_standing_bit,status(a0)
beq.s loc_19F4C
jsr (ChkFloorEdge2).l
tst.w d1
beq.s loc_19F36
bpl.s loc_19F4C
loc_19F36:
lea (Sidekick).w,a1 ; a1=character
bclr #3,status(a1)
bset #1,status(a1)
bclr #p2_standing_bit,status(a0)
loc_19F4C:
moveq #0,d4
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 01 - Sonic
; ----------------------------------------------------------------------------
; Sprite_19F50: Object_Sonic:
Obj01:
; a0=character
tst.w (Debug_placement_mode).w ; is debug mode being used?
beq.s Obj01_Normal ; if not, branch
jmp (DebugMode).l
; ---------------------------------------------------------------------------
; loc_19F5C:
Obj01_Normal:
moveq #0,d0
move.b routine(a0),d0
move.w Obj01_Index(pc,d0.w),d1
jmp Obj01_Index(pc,d1.w)
; ===========================================================================
; off_19F6A: Obj01_States:
Obj01_Index: offsetTable
offsetTableEntry.w Obj01_Init ; 0
offsetTableEntry.w Obj01_Control ; 2
offsetTableEntry.w Obj01_Hurt ; 4
offsetTableEntry.w Obj01_Dead ; 6
offsetTableEntry.w Obj01_Gone ; 8
offsetTableEntry.w Obj01_Respawning ; $A
; ===========================================================================
; loc_19F76: Obj_01_Sub_0: Obj01_Main:
Obj01_Init:
addq.b #2,routine(a0) ; => Obj01_Control
move.b #$13,y_radius(a0) ; this sets Sonic's collision height (2*pixels)
move.b #9,x_radius(a0)
move.l #Mapunc_Sonic,mappings(a0)
move.b #2,priority(a0)
move.b #$18,width_pixels(a0)
move.b #4,render_flags(a0)
move.w #$600,(Sonic_top_speed).w ; set Sonic's top speed
move.w #$C,(Sonic_acceleration).w ; set Sonic's acceleration
move.w #$80,(Sonic_deceleration).w ; set Sonic's deceleration
tst.b (Last_star_pole_hit).w
bne.s Obj01_Init_Continued
; only happens when not starting at a checkpoint:
move.w #make_art_tile(ArtTile_ArtUnc_Sonic,0,0),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #$C,top_solid_bit(a0)
move.b #$D,lrb_solid_bit(a0)
move.w x_pos(a0),(Saved_x_pos).w
move.w y_pos(a0),(Saved_y_pos).w
move.w art_tile(a0),(Saved_art_tile).w
move.w top_solid_bit(a0),(Saved_Solid_bits).w
Obj01_Init_Continued:
move.b #0,flips_remaining(a0)
move.b #4,flip_speed(a0)
move.b #0,(Super_Sonic_flag).w
move.b #$1E,air_left(a0)
subi.w #$20,x_pos(a0)
addi_.w #4,y_pos(a0)
move.w #0,(Sonic_Pos_Record_Index).w
move.w #$3F,d2
- bsr.w Sonic_RecordPos
subq.w #4,a1
move.l #0,(a1)
dbf d2,-
addi.w #$20,x_pos(a0)
subi_.w #4,y_pos(a0)
; ---------------------------------------------------------------------------
; Normal state for Sonic
; ---------------------------------------------------------------------------
; loc_1A030: Obj_01_Sub_2:
Obj01_Control:
tst.w (Debug_mode_flag).w ; is debug cheat enabled?
beq.s + ; if not, branch
btst #button_B,(Ctrl_1_Press).w ; is button B pressed?
beq.s + ; if not, branch
move.w #1,(Debug_placement_mode).w ; change Sonic into a ring/item
clr.b (Control_Locked).w ; unlock control
rts
; -----------------------------------------------------------------------
+ tst.b (Control_Locked).w ; are controls locked?
bne.s + ; if yes, branch
move.w (Ctrl_1).w,(Ctrl_1_Logical).w ; copy new held buttons, to enable joypad control
+
btst #0,obj_control(a0) ; is Sonic interacting with another object that holds him in place or controls his movement somehow?
bne.s + ; if yes, branch to skip Sonic's control
moveq #0,d0
move.b status(a0),d0
andi.w #6,d0 ; %0000 %0110
move.w Obj01_Modes(pc,d0.w),d1
jsr Obj01_Modes(pc,d1.w) ; run Sonic's movement control code
+
cmpi.w #-$100,(Camera_Min_Y_pos).w ; is vertical wrapping enabled?
bne.s + ; if not, branch
andi.w #$7FF,y_pos(a0) ; perform wrapping of Sonic's y position
+
bsr.s Sonic_Display
bsr.w Sonic_Super
bsr.w Sonic_RecordPos
bsr.w Sonic_Water
move.b (Primary_Angle).w,next_tilt(a0)
move.b (Secondary_Angle).w,tilt(a0)
tst.b (WindTunnel_flag).w
beq.s +
tst.b anim(a0)
bne.s +
move.b next_anim(a0),anim(a0)
+
bsr.w Sonic_Animate
tst.b obj_control(a0)
bmi.s +
jsr (TouchResponse).l
+
bra.w LoadSonicDynPLC
; ===========================================================================
; secondary states under state Obj01_Control
; off_1A0BE:
Obj01_Modes: offsetTable
offsetTableEntry.w Obj01_MdNormal_Checks ; 0 - not airborne or rolling
offsetTableEntry.w Obj01_MdAir ; 2 - airborne
offsetTableEntry.w Obj01_MdRoll ; 4 - rolling
offsetTableEntry.w Obj01_MdJump ; 6 - jumping
; ===========================================================================
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1A0C6:
Sonic_Display:
move.w invulnerable_time(a0),d0
beq.s Obj01_Display
subq.w #1,invulnerable_time(a0)
lsr.w #3,d0
bcc.s Obj01_ChkInvin
; loc_1A0D4:
Obj01_Display:
jsr (DisplaySprite).l
; loc_1A0DA:
Obj01_ChkInvin: ; Checks if invincibility has expired and disables it if it has.
btst #status_sec_isInvincible,status_secondary(a0)
beq.s Obj01_ChkShoes
tst.w invincibility_time(a0)
beq.s Obj01_ChkShoes ; If there wasn't any time left, that means we're in Super Sonic mode.
subq.w #1,invincibility_time(a0)
bne.s Obj01_ChkShoes
tst.b (Current_Boss_ID).w ; Don't change music if in a boss fight
bne.s Obj01_RmvInvin
cmpi.b #$C,air_left(a0) ; Don't change music if drowning
blo.s Obj01_RmvInvin
move.w (Level_Music).w,d0
jsr (PlayMusic).l
;loc_1A106:
Obj01_RmvInvin:
bclr #status_sec_isInvincible,status_secondary(a0)
; loc_1A10C:
Obj01_ChkShoes: ; Checks if Speed Shoes have expired and disables them if they have.
btst #status_sec_hasSpeedShoes,status_secondary(a0)
beq.s Obj01_ExitChk
tst.w speedshoes_time(a0)
beq.s Obj01_ExitChk
subq.w #1,speedshoes_time(a0)
bne.s Obj01_ExitChk
move.w #$600,(Sonic_top_speed).w
move.w #$C,(Sonic_acceleration).w
move.w #$80,(Sonic_deceleration).w
tst.b (Super_Sonic_flag).w
beq.s Obj01_RmvSpeed
move.w #$A00,(Sonic_top_speed).w
move.w #$30,(Sonic_acceleration).w
move.w #$100,(Sonic_deceleration).w
; loc_1A14A:
Obj01_RmvSpeed:
bclr #status_sec_hasSpeedShoes,status_secondary(a0)
move.w #MusID_SlowDown,d0 ; Slow down tempo
jmp (PlayMusic).l
; ---------------------------------------------------------------------------
; return_1A15A:
Obj01_ExitChk:
rts
; End of subroutine Sonic_Display
; ---------------------------------------------------------------------------
; Subroutine to record Sonic's previous positions for invincibility stars
; and input/status flags for Tails' AI to follow
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1A15C:
Sonic_RecordPos:
move.w (Sonic_Pos_Record_Index).w,d0
lea (Sonic_Pos_Record_Buf).w,a1
lea (a1,d0.w),a1
move.w x_pos(a0),(a1)+
move.w y_pos(a0),(a1)+
addq.b #4,(Sonic_Pos_Record_Index+1).w
lea (Sonic_Stat_Record_Buf).w,a1
lea (a1,d0.w),a1
move.w (Ctrl_1_Logical).w,(a1)+
move.w status(a0),(a1)+
rts
; End of subroutine Sonic_RecordPos
; ---------------------------------------------------------------------------
; Subroutine for Sonic when he's underwater
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1A186:
Sonic_Water:
tst.b (Water_flag).w ; does level have water?
bne.s Obj01_InWater ; if yes, branch
return_1A18C:
rts
; ---------------------------------------------------------------------------
; loc_1A18E:
Obj01_InWater:
move.w (Water_Level_1).w,d0
cmp.w y_pos(a0),d0 ; is Sonic above the water?
bge.s Obj01_OutWater ; if yes, branch
bset #6,status(a0) ; set underwater flag
bne.s return_1A18C ; if already underwater, branch
movea.l a0,a1
bsr.w ResumeMusic
move.b #ObjID_SmallBubbles,(Sonic_BreathingBubbles+id).w ; load Obj0A (sonic's breathing bubbles) at $FFFFD080
move.b #$81,(Sonic_BreathingBubbles+subtype).w
move.l a0,(Sonic_BreathingBubbles+$3C).w
move.w #$300,(Sonic_top_speed).w
move.w #6,(Sonic_acceleration).w
move.w #$40,(Sonic_deceleration).w
tst.b (Super_Sonic_flag).w
beq.s +
move.w #$500,(Sonic_top_speed).w
move.w #$18,(Sonic_acceleration).w
move.w #$80,(Sonic_deceleration).w
+
asr.w x_vel(a0)
asr.w y_vel(a0) ; memory operands can only be shifted one bit at a time
asr.w y_vel(a0)
beq.s return_1A18C
move.w #$100,(Sonic_Dust+anim).w ; splash animation
move.w #SndID_Splash,d0 ; splash sound
jmp (PlaySound).l
; ---------------------------------------------------------------------------
; loc_1A1FE:
Obj01_OutWater:
bclr #6,status(a0) ; unset underwater flag
beq.s return_1A18C ; if already above water, branch
movea.l a0,a1
bsr.w ResumeMusic
move.w #$600,(Sonic_top_speed).w
move.w #$C,(Sonic_acceleration).w
move.w #$80,(Sonic_deceleration).w
tst.b (Super_Sonic_flag).w
beq.s +
move.w #$A00,(Sonic_top_speed).w
move.w #$30,(Sonic_acceleration).w
move.w #$100,(Sonic_deceleration).w
+
cmpi.b #4,routine(a0) ; is Sonic falling back from getting hurt?
beq.s + ; if yes, branch
asl y_vel(a0)
+
tst.w y_vel(a0)
beq.w return_1A18C
move.w #$100,(Sonic_Dust+anim).w ; splash animation
movea.l a0,a1
bsr.w ResumeMusic
cmpi.w #-$1000,y_vel(a0)
bgt.s +
move.w #-$1000,y_vel(a0) ; limit upward y velocity exiting the water
+
move.w #SndID_Splash,d0 ; splash sound
jmp (PlaySound).l
; End of subroutine Sonic_Water
; ===========================================================================
; ---------------------------------------------------------------------------
; Start of subroutine Obj01_MdNormal
; Called if Sonic is neither airborne nor rolling this frame
; ---------------------------------------------------------------------------
; loc_1A26E:
Obj01_MdNormal_Checks:
move.b (Ctrl_1_Press_Logical).w,d0
andi.b #button_B_mask|button_C_mask|button_A_mask,d0
bne.s Obj01_MdNormal
cmpi.b #$A,anim(a0)
beq.s return_1A2DE
cmpi.b #$B,anim(a0)
beq.s return_1A2DE
cmpi.b #5,anim(a0)
bne.s Obj01_MdNormal
cmpi.b #$1E,anim_frame(a0)
blo.s Obj01_MdNormal
move.b (Ctrl_1_Held_Logical).w,d0
andi.b #button_up_mask|button_down_mask|button_left_mask|button_right_mask|button_B_mask|button_C_mask|button_A_mask,d0
beq.s return_1A2DE
move.b #$A,anim(a0)
cmpi.b #$AC,anim_frame(a0)
blo.s return_1A2DE
move.b #$B,anim(a0)
bra.s return_1A2DE
; ---------------------------------------------------------------------------
; loc_1A2B8:
Obj01_MdNormal:
bsr.w Sonic_CheckSpindash
bsr.w Sonic_Jump
bsr.w Sonic_SlopeResist
bsr.w Sonic_Move
bsr.w Sonic_Roll
bsr.w Sonic_LevelBound
jsr (ObjectMove).l
bsr.w AnglePos
bsr.w Sonic_SlopeRepel
return_1A2DE:
rts
; End of subroutine Obj01_MdNormal
; ===========================================================================
; Start of subroutine Obj01_MdAir
; Called if Sonic is airborne, but not in a ball (thus, probably not jumping)
; loc_1A2E0: Obj01_MdJump
Obj01_MdAir:
bsr.w Sonic_JumpHeight
bsr.w Sonic_ChgJumpDir
bsr.w Sonic_LevelBound
jsr (ObjectMoveAndFall).l
btst #6,status(a0) ; is Sonic underwater?
beq.s + ; if not, branch
subi.w #$28,y_vel(a0) ; reduce gravity by $28 ($38-$28=$10)
+
bsr.w Sonic_JumpAngle
bsr.w Sonic_DoLevelCollision
rts
; End of subroutine Obj01_MdAir
; ===========================================================================
; Start of subroutine Obj01_MdRoll
; Called if Sonic is in a ball, but not airborne (thus, probably rolling)
; loc_1A30A:
Obj01_MdRoll:
tst.b pinball_mode(a0)
bne.s +
bsr.w Sonic_Jump
+
bsr.w Sonic_RollRepel
bsr.w Sonic_RollSpeed
bsr.w Sonic_LevelBound
jsr (ObjectMove).l
bsr.w AnglePos
bsr.w Sonic_SlopeRepel
rts
; End of subroutine Obj01_MdRoll
; ===========================================================================
; Start of subroutine Obj01_MdJump
; Called if Sonic is in a ball and airborne (he could be jumping but not necessarily)
; Notes: This is identical to Obj01_MdAir, at least at this outer level.
; Why they gave it a separate copy of the code, I don't know.
; loc_1A330: Obj01_MdJump2:
Obj01_MdJump:
bsr.w Sonic_JumpHeight
bsr.w Sonic_ChgJumpDir
bsr.w Sonic_LevelBound
jsr (ObjectMoveAndFall).l
btst #6,status(a0) ; is Sonic underwater?
beq.s + ; if not, branch
subi.w #$28,y_vel(a0) ; reduce gravity by $28 ($38-$28=$10)
+
bsr.w Sonic_JumpAngle
bsr.w Sonic_DoLevelCollision
rts
; End of subroutine Obj01_MdJump
; ---------------------------------------------------------------------------
; Subroutine to make Sonic walk/run
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1A35A:
Sonic_Move:
move.w (Sonic_top_speed).w,d6
move.w (Sonic_acceleration).w,d5
move.w (Sonic_deceleration).w,d4
if status_sec_isSliding = 7
tst.b status_secondary(a0)
bmi.w Obj01_Traction
else
btst #status_sec_isSliding,status_secondary(a0)
bne.w Obj01_Traction
endif
tst.w move_lock(a0)
bne.w Obj01_ResetScr
btst #button_left,(Ctrl_1_Held_Logical).w ; is left being pressed?
beq.s Obj01_NotLeft ; if not, branch
bsr.w Sonic_MoveLeft
; loc_1A382:
Obj01_NotLeft:
btst #button_right,(Ctrl_1_Held_Logical).w ; is right being pressed?
beq.s Obj01_NotRight ; if not, branch
bsr.w Sonic_MoveRight
; loc_1A38E:
Obj01_NotRight:
move.b angle(a0),d0
addi.b #$20,d0
andi.b #$C0,d0 ; is Sonic on a slope?
bne.w Obj01_ResetScr ; if yes, branch
tst.w inertia(a0) ; is Sonic moving?
bne.w Obj01_ResetScr ; if yes, branch
bclr #5,status(a0)
move.b #AniIDSonAni_Wait,anim(a0) ; use "standing" animation
btst #3,status(a0)
beq.w Sonic_Balance
moveq #0,d0
move.b interact(a0),d0
if object_size=$40
lsl.w #6,d0
else
mulu.w #object_size,d0
endif
lea (Object_RAM).w,a1 ; a1=character
lea (a1,d0.w),a1 ; a1=object
tst.b status(a1)
bmi.w Sonic_Lookup
moveq #0,d1
move.b width_pixels(a1),d1
move.w d1,d2
add.w d2,d2
subq.w #2,d2
add.w x_pos(a0),d1
sub.w x_pos(a1),d1
tst.b (Super_Sonic_flag).w
bne.w SuperSonic_Balance
cmpi.w #2,d1
blt.s Sonic_BalanceOnObjLeft
cmp.w d2,d1
bge.s Sonic_BalanceOnObjRight
bra.w Sonic_Lookup
; ---------------------------------------------------------------------------
; loc_1A3FE:
SuperSonic_Balance:
cmpi.w #2,d1
blt.w SuperSonic_BalanceOnObjLeft
cmp.w d2,d1
bge.w SuperSonic_BalanceOnObjRight
bra.w Sonic_Lookup
; ---------------------------------------------------------------------------
; balancing checks for when you're on the right edge of an object
; loc_1A410:
Sonic_BalanceOnObjRight:
btst #0,status(a0)
bne.s +
move.b #AniIDSonAni_Balance,anim(a0)
addq.w #6,d2
cmp.w d2,d1
blt.w Obj01_ResetScr
move.b #AniIDSonAni_Balance2,anim(a0)
bra.w Obj01_ResetScr
; on right edge of object but facing left:
+ move.b #AniIDSonAni_Balance3,anim(a0)
addq.w #6,d2
cmp.w d2,d1
blt.w Obj01_ResetScr
move.b #AniIDSonAni_Balance4,anim(a0)
bclr #0,status(a0)
bra.w Obj01_ResetScr
; ---------------------------------------------------------------------------
; balancing checks for when you're on the left edge of an object
; loc_1A44E:
Sonic_BalanceOnObjLeft:
btst #0,status(a0)
beq.s +
move.b #AniIDSonAni_Balance,anim(a0)
cmpi.w #-4,d1
bge.w Obj01_ResetScr
move.b #AniIDSonAni_Balance2,anim(a0)
bra.w Obj01_ResetScr
; on left edge of object but facing right:
+ move.b #AniIDSonAni_Balance3,anim(a0)
cmpi.w #-4,d1
bge.w Obj01_ResetScr
move.b #AniIDSonAni_Balance4,anim(a0)
bset #0,status(a0)
bra.w Obj01_ResetScr
; ---------------------------------------------------------------------------
; balancing checks for when you're on the edge of part of the level
; loc_1A48C:
Sonic_Balance:
jsr (ChkFloorEdge).l
cmpi.w #$C,d1
blt.w Sonic_Lookup
tst.b (Super_Sonic_flag).w
bne.w SuperSonic_Balance2
cmpi.b #3,next_tilt(a0)
bne.s Sonic_BalanceLeft
btst #0,status(a0)
bne.s +
move.b #AniIDSonAni_Balance,anim(a0)
move.w x_pos(a0),d3
subq.w #6,d3
jsr (ChkFloorEdge_Part2).l
cmpi.w #$C,d1
blt.w Obj01_ResetScr
move.b #AniIDSonAni_Balance2,anim(a0)
bra.w Obj01_ResetScr
; on right edge but facing left:
+ move.b #AniIDSonAni_Balance3,anim(a0)
move.w x_pos(a0),d3
subq.w #6,d3
jsr (ChkFloorEdge_Part2).l
cmpi.w #$C,d1
blt.w Obj01_ResetScr
move.b #AniIDSonAni_Balance4,anim(a0)
bclr #0,status(a0)
bra.w Obj01_ResetScr
; ---------------------------------------------------------------------------
Sonic_BalanceLeft:
cmpi.b #3,tilt(a0)
bne.s Sonic_Lookup
btst #0,status(a0)
beq.s +
move.b #AniIDSonAni_Balance,anim(a0)
move.w x_pos(a0),d3
addq.w #6,d3
jsr (ChkFloorEdge_Part2).l
cmpi.w #$C,d1
blt.w Obj01_ResetScr
move.b #AniIDSonAni_Balance2,anim(a0)
bra.w Obj01_ResetScr
; on left edge but facing right:
+ move.b #AniIDSonAni_Balance3,anim(a0)
move.w x_pos(a0),d3
addq.w #6,d3
jsr (ChkFloorEdge_Part2).l
cmpi.w #$C,d1
blt.w Obj01_ResetScr
move.b #AniIDSonAni_Balance4,anim(a0)
bset #0,status(a0)
bra.w Obj01_ResetScr
; ---------------------------------------------------------------------------
; loc_1A55E:
SuperSonic_Balance2:
cmpi.b #3,next_tilt(a0)
bne.s loc_1A56E
; loc_1A566:
SuperSonic_BalanceOnObjRight:
bclr #0,status(a0)
bra.s loc_1A57C
; ---------------------------------------------------------------------------
loc_1A56E:
cmpi.b #3,tilt(a0)
bne.s Sonic_Lookup
; loc_1A576:
SuperSonic_BalanceOnObjLeft:
bset #0,status(a0)
loc_1A57C:
move.b #AniIDSonAni_Balance,anim(a0)
bra.s Obj01_ResetScr
; ---------------------------------------------------------------------------
; loc_1A584:
Sonic_Lookup:
btst #button_up,(Ctrl_1_Held_Logical).w ; is up being pressed?
beq.s Sonic_Duck ; if not, branch
move.b #AniIDSonAni_LookUp,anim(a0) ; use "looking up" animation
addq.w #1,(Sonic_Look_delay_counter).w
cmpi.w #$78,(Sonic_Look_delay_counter).w
blo.s Obj01_ResetScr_Part2
move.w #$78,(Sonic_Look_delay_counter).w
cmpi.w #$C8,(Camera_Y_pos_bias).w
beq.s Obj01_UpdateSpeedOnGround
addq.w #2,(Camera_Y_pos_bias).w
bra.s Obj01_UpdateSpeedOnGround
; ---------------------------------------------------------------------------
; loc_1A5B2:
Sonic_Duck:
btst #button_down,(Ctrl_1_Held_Logical).w ; is down being pressed?
beq.s Obj01_ResetScr ; if not, branch
move.b #AniIDSonAni_Duck,anim(a0) ; use "ducking" animation
addq.w #1,(Sonic_Look_delay_counter).w
cmpi.w #$78,(Sonic_Look_delay_counter).w
blo.s Obj01_ResetScr_Part2
move.w #$78,(Sonic_Look_delay_counter).w
cmpi.w #8,(Camera_Y_pos_bias).w
beq.s Obj01_UpdateSpeedOnGround
subq.w #2,(Camera_Y_pos_bias).w
bra.s Obj01_UpdateSpeedOnGround
; ===========================================================================
; moves the screen back to its normal position after looking up or down
; loc_1A5E0:
Obj01_ResetScr:
move.w #0,(Sonic_Look_delay_counter).w
; loc_1A5E6:
Obj01_ResetScr_Part2:
cmpi.w #(224/2)-16,(Camera_Y_pos_bias).w ; is screen in its default position?
beq.s Obj01_UpdateSpeedOnGround ; if yes, branch.
bhs.s + ; depending on the sign of the difference,
addq.w #4,(Camera_Y_pos_bias).w ; either add 2
+ subq.w #2,(Camera_Y_pos_bias).w ; or subtract 2
; ---------------------------------------------------------------------------
; updates Sonic's speed on the ground
; ---------------------------------------------------------------------------
; sub_1A5F8:
Obj01_UpdateSpeedOnGround:
tst.b (Super_Sonic_flag).w
beq.w +
move.w #$C,d5
+
move.b (Ctrl_1_Held_Logical).w,d0
andi.b #button_left_mask|button_right_mask,d0 ; is left/right pressed?
bne.s Obj01_Traction ; if yes, branch
move.w inertia(a0),d0
beq.s Obj01_Traction
bmi.s Obj01_SettleLeft
; slow down when facing right and not pressing a direction
; Obj01_SettleRight:
sub.w d5,d0
bcc.s +
move.w #0,d0
+
move.w d0,inertia(a0)
bra.s Obj01_Traction
; ---------------------------------------------------------------------------
; slow down when facing left and not pressing a direction
; loc_1A624:
Obj01_SettleLeft:
add.w d5,d0
bcc.s +
move.w #0,d0
+
move.w d0,inertia(a0)
; increase or decrease speed on the ground
; loc_1A630:
Obj01_Traction:
move.b angle(a0),d0
jsr (CalcSine).l
muls.w inertia(a0),d1
asr.l #8,d1
move.w d1,x_vel(a0)
muls.w inertia(a0),d0
asr.l #8,d0
move.w d0,y_vel(a0)
; stops Sonic from running through walls that meet the ground
; loc_1A64E:
Obj01_CheckWallsOnGround:
move.b angle(a0),d0
addi.b #$40,d0
bmi.s return_1A6BE
move.b #$40,d1 ; Rotate 90 degrees clockwise
tst.w inertia(a0) ; Check inertia
beq.s return_1A6BE ; If not moving, don't do anything
bmi.s + ; If negative, branch
neg.w d1 ; Otherwise, we want to rotate counterclockwise
+
move.b angle(a0),d0
add.b d1,d0
move.w d0,-(sp)
bsr.w CalcRoomInFront
move.w (sp)+,d0
tst.w d1
bpl.s return_1A6BE
asl.w #8,d1
addi.b #$20,d0
andi.b #$C0,d0
beq.s loc_1A6BA
cmpi.b #$40,d0
beq.s loc_1A6A8
cmpi.b #$80,d0
beq.s loc_1A6A2
add.w d1,x_vel(a0)
bset #5,status(a0)
move.w #0,inertia(a0)
rts
; ---------------------------------------------------------------------------
loc_1A6A2:
sub.w d1,y_vel(a0)
rts
; ---------------------------------------------------------------------------
loc_1A6A8:
sub.w d1,x_vel(a0)
bset #5,status(a0)
move.w #0,inertia(a0)
rts
; ---------------------------------------------------------------------------
loc_1A6BA:
add.w d1,y_vel(a0)
return_1A6BE:
rts
; End of subroutine Sonic_Move
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1A6C0:
Sonic_MoveLeft:
move.w inertia(a0),d0
beq.s +
bpl.s Sonic_TurnLeft ; if Sonic is already moving to the right, branch
+
bset #0,status(a0)
bne.s +
bclr #5,status(a0)
move.b #AniIDSonAni_Run,next_anim(a0)
+
sub.w d5,d0 ; add acceleration to the left
move.w d6,d1
neg.w d1
cmp.w d1,d0 ; compare new speed with top speed
bgt.s + ; if new speed is less than the maximum, branch
add.w d5,d0 ; remove this frame's acceleration change
cmp.w d1,d0 ; compare speed with top speed
ble.s + ; if speed was already greater than the maximum, branch
move.w d1,d0 ; limit speed on ground going left
+
move.w d0,inertia(a0)
move.b #AniIDSonAni_Walk,anim(a0) ; use walking animation
rts
; ---------------------------------------------------------------------------
; loc_1A6FA:
Sonic_TurnLeft:
sub.w d4,d0
bcc.s +
move.w #-$80,d0
+
move.w d0,inertia(a0)
move.b angle(a0),d0
addi.b #$20,d0
andi.b #$C0,d0
bne.s return_1A744
cmpi.w #$400,d0
blt.s return_1A744
move.b #AniIDSonAni_Stop,anim(a0) ; use "stopping" animation
bclr #0,status(a0)
move.w #SndID_Skidding,d0
jsr (PlaySound).l
cmpi.b #$C,air_left(a0)
blo.s return_1A744 ; if he's drowning, branch to not make dust
move.b #6,(Sonic_Dust+routine).w
move.b #$15,(Sonic_Dust+mapping_frame).w
return_1A744:
rts
; End of subroutine Sonic_MoveLeft
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1A746:
Sonic_MoveRight:
move.w inertia(a0),d0
bmi.s Sonic_TurnRight ; if Sonic is already moving to the left, branch
bclr #0,status(a0)
beq.s +
bclr #5,status(a0)
move.b #AniIDSonAni_Run,next_anim(a0)
+
add.w d5,d0 ; add acceleration to the right
cmp.w d6,d0 ; compare new speed with top speed
blt.s + ; if new speed is less than the maximum, branch
sub.w d5,d0 ; remove this frame's acceleration change
cmp.w d6,d0 ; compare speed with top speed
bge.s + ; if speed was already greater than the maximum, branch
move.w d6,d0 ; limit speed on ground going right
+
move.w d0,inertia(a0)
move.b #AniIDSonAni_Walk,anim(a0) ; use walking animation
rts
; ---------------------------------------------------------------------------
; loc_1A77A:
Sonic_TurnRight:
add.w d4,d0
bcc.s +
move.w #$80,d0
+
move.w d0,inertia(a0)
move.b angle(a0),d0
addi.b #$20,d0
andi.b #$C0,d0
bne.s return_1A7C4
cmpi.w #-$400,d0
bgt.s return_1A7C4
move.b #AniIDSonAni_Stop,anim(a0) ; use "stopping" animation
bset #0,status(a0)
move.w #SndID_Skidding,d0 ; use "stopping" sound
jsr (PlaySound).l
cmpi.b #$C,air_left(a0)
blo.s return_1A7C4 ; if he's drowning, branch to not make dust
move.b #6,(Sonic_Dust+routine).w
move.b #$15,(Sonic_Dust+mapping_frame).w
return_1A7C4:
rts
; End of subroutine Sonic_MoveRight
; ---------------------------------------------------------------------------
; Subroutine to change Sonic's speed as he rolls
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1A7C6:
Sonic_RollSpeed:
move.w (Sonic_top_speed).w,d6
asl.w #1,d6
move.w (Sonic_acceleration).w,d5
asr.w #1,d5 ; natural roll deceleration = 1/2 normal acceleration
move.w #$20,d4 ; controlled roll deceleration... interestingly,
; this should be Sonic_deceleration/4 according to Tails_RollSpeed,
; which means Sonic is much better than Tails at slowing down his rolling when he's underwater
if status_sec_isSliding = 7
tst.b status_secondary(a0)
bmi.w Obj01_Roll_ResetScr
else
btst #status_sec_isSliding,status_secondary(a0)
bne.w Obj01_Roll_ResetScr
endif
tst.w move_lock(a0)
bne.s Sonic_ApplyRollSpeed
btst #button_left,(Ctrl_1_Held_Logical).w ; is left being pressed?
beq.s + ; if not, branch
bsr.w Sonic_RollLeft
+
btst #button_right,(Ctrl_1_Held_Logical).w ; is right being pressed?
beq.s Sonic_ApplyRollSpeed ; if not, branch
bsr.w Sonic_RollRight
; loc_1A7FC:
Sonic_ApplyRollSpeed:
move.w inertia(a0),d0
beq.s Sonic_CheckRollStop
bmi.s Sonic_ApplyRollSpeedLeft
; Sonic_ApplyRollSpeedRight:
sub.w d5,d0
bcc.s +
move.w #0,d0
+
move.w d0,inertia(a0)
bra.s Sonic_CheckRollStop
; ---------------------------------------------------------------------------
; loc_1A812:
Sonic_ApplyRollSpeedLeft:
add.w d5,d0
bcc.s +
move.w #0,d0
+
move.w d0,inertia(a0)
; loc_1A81E:
Sonic_CheckRollStop:
tst.w inertia(a0)
bne.s Obj01_Roll_ResetScr
tst.b pinball_mode(a0) ; note: the spindash flag has a different meaning when Sonic's already rolling -- it's used to mean he's not allowed to stop rolling
bne.s Sonic_KeepRolling
bclr #2,status(a0)
move.b #$13,y_radius(a0)
move.b #9,x_radius(a0)
move.b #AniIDSonAni_Wait,anim(a0)
subq.w #5,y_pos(a0)
bra.s Obj01_Roll_ResetScr
; ---------------------------------------------------------------------------
; magically gives Sonic an extra push if he's going to stop rolling where it's not allowed
; (such as in an S-curve in HTZ or a stopper chamber in CNZ)
; loc_1A848:
Sonic_KeepRolling:
move.w #$400,inertia(a0)
btst #0,status(a0)
beq.s Obj01_Roll_ResetScr
neg.w inertia(a0)
; resets the screen to normal while rolling, like Obj01_ResetScr
; loc_1A85A:
Obj01_Roll_ResetScr:
cmpi.w #(224/2)-16,(Camera_Y_pos_bias).w ; is screen in its default position?
beq.s Sonic_SetRollSpeeds ; if yes, branch
bhs.s + ; depending on the sign of the difference,
addq.w #4,(Camera_Y_pos_bias).w ; either add 2
+ subq.w #2,(Camera_Y_pos_bias).w ; or subtract 2
; loc_1A86C:
Sonic_SetRollSpeeds:
move.b angle(a0),d0
jsr (CalcSine).l
muls.w inertia(a0),d0
asr.l #8,d0
move.w d0,y_vel(a0) ; set y velocity based on $14 and angle
muls.w inertia(a0),d1
asr.l #8,d1
cmpi.w #$1000,d1
ble.s +
move.w #$1000,d1 ; limit Sonic's speed rolling right
+
cmpi.w #-$1000,d1
bge.s +
move.w #-$1000,d1 ; limit Sonic's speed rolling left
+
move.w d1,x_vel(a0) ; set x velocity based on $14 and angle
bra.w Obj01_CheckWallsOnGround
; End of function Sonic_RollSpeed
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1A8A2:
Sonic_RollLeft:
move.w inertia(a0),d0
beq.s +
bpl.s Sonic_BrakeRollingRight
+
bset #0,status(a0)
move.b #AniIDSonAni_Roll,anim(a0) ; use "rolling" animation
rts
; ---------------------------------------------------------------------------
; loc_1A8B8:
Sonic_BrakeRollingRight:
sub.w d4,d0 ; reduce rightward rolling speed
bcc.s +
move.w #-$80,d0
+
move.w d0,inertia(a0)
rts
; End of function Sonic_RollLeft
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1A8C6:
Sonic_RollRight:
move.w inertia(a0),d0
bmi.s Sonic_BrakeRollingLeft
bclr #0,status(a0)
move.b #AniIDSonAni_Roll,anim(a0) ; use "rolling" animation
rts
; ---------------------------------------------------------------------------
; loc_1A8DA:
Sonic_BrakeRollingLeft:
add.w d4,d0 ; reduce leftward rolling speed
bcc.s +
move.w #$80,d0
+
move.w d0,inertia(a0)
rts
; End of subroutine Sonic_RollRight
; ---------------------------------------------------------------------------
; Subroutine for moving Sonic left or right when he's in the air
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1A8E8:
Sonic_ChgJumpDir:
move.w (Sonic_top_speed).w,d6
move.w (Sonic_acceleration).w,d5
asl.w #1,d5
btst #4,status(a0) ; did Sonic jump from rolling?
bne.s Obj01_Jump_ResetScr ; if yes, branch to skip midair control
move.w x_vel(a0),d0
btst #button_left,(Ctrl_1_Held_Logical).w
beq.s + ; if not holding left, branch
bset #0,status(a0)
sub.w d5,d0 ; add acceleration to the left
move.w d6,d1
neg.w d1
cmp.w d1,d0 ; compare new speed with top speed
bgt.s + ; if new speed is less than the maximum, branch
move.w d1,d0 ; limit speed in air going left, even if Sonic was already going faster (speed limit/cap)
+
btst #button_right,(Ctrl_1_Held_Logical).w
beq.s + ; if not holding right, branch
bclr #0,status(a0)
add.w d5,d0 ; accelerate right in the air
cmp.w d6,d0 ; compare new speed with top speed
blt.s + ; if new speed is less than the maximum, branch
move.w d6,d0 ; limit speed in air going right, even if Sonic was already going faster (speed limit/cap)
; Obj01_JumpMove:
+ move.w d0,x_vel(a0)
; loc_1A932: Obj01_ResetScr2:
Obj01_Jump_ResetScr:
cmpi.w #(224/2)-16,(Camera_Y_pos_bias).w ; is screen in its default position?
beq.s Sonic_JumpPeakDecelerate ; if yes, branch
bhs.s + ; depending on the sign of the difference,
addq.w #4,(Camera_Y_pos_bias).w ; either add 2
+ subq.w #2,(Camera_Y_pos_bias).w ; or subtract 2
; loc_1A944:
Sonic_JumpPeakDecelerate:
cmpi.w #-$400,y_vel(a0) ; is Sonic moving faster than -$400 upwards?
blo.s return_1A972 ; if yes, return
move.w x_vel(a0),d0
move.w d0,d1
asr.w #5,d1 ; d1 = x_velocity / 32
beq.s return_1A972 ; return if d1 is 0
bmi.s Sonic_JumpPeakDecelerateLeft ; branch if moving left
; Sonic_JumpPeakDecelerateRight:
sub.w d1,d0 ; reduce x velocity by d1
bcc.s +
move.w #0,d0
+
move.w d0,x_vel(a0)
rts
;-------------------------------------------------------------
; loc_1A966:
Sonic_JumpPeakDecelerateLeft:
sub.w d1,d0 ; reduce x velocity by d1
bcs.s +
move.w #0,d0
+
move.w d0,x_vel(a0)
return_1A972:
rts
; End of subroutine Sonic_ChgJumpDir
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to prevent Sonic from leaving the boundaries of a level
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1A974:
Sonic_LevelBound:
move.l x_pos(a0),d1
move.w x_vel(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d1
swap d1
move.w (Camera_Min_X_pos).w,d0
addi.w #$10,d0
cmp.w d1,d0 ; has Sonic touched the left boundary?
bhi.s Sonic_Boundary_Sides ; if yes, branch
move.w (Camera_Max_X_pos).w,d0
addi.w #$128,d0
tst.b (Current_Boss_ID).w
bne.s +
addi.w #$40,d0
+
cmp.w d1,d0 ; has Sonic touched the right boundary?
bls.s Sonic_Boundary_Sides ; if yes, branch
; loc_1A9A6:
Sonic_Boundary_CheckBottom:
move.w (Camera_Max_Y_pos_now).w,d0
addi.w #$E0,d0
cmp.w y_pos(a0),d0 ; has Sonic touched the bottom boundary?
blt.s Sonic_Boundary_Bottom ; if yes, branch
rts
; ---------------------------------------------------------------------------
Sonic_Boundary_Bottom: ;;
jmpto (KillCharacter).l, JmpTo_KillCharacter
; ===========================================================================
; loc_1A9BA:
Sonic_Boundary_Sides:
move.w d0,x_pos(a0)
move.w #0,2+x_pos(a0) ; subpixel x
move.w #0,x_vel(a0)
move.w #0,inertia(a0)
bra.s Sonic_Boundary_CheckBottom
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine allowing Sonic to start rolling when he's moving
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1A9D2:
Sonic_Roll:
if status_sec_isSliding = 7
tst.b status_secondary(a0)
bmi.s Obj01_NoRoll
else
btst #status_sec_isSliding,status_secondary(a0)
bne.s Obj01_NoRoll
endif
mvabs.w inertia(a0),d0
cmpi.w #$80,d0 ; is Sonic moving at $80 speed or faster?
blo.s Obj01_NoRoll ; if not, branch
move.b (Ctrl_1_Held_Logical).w,d0
andi.b #button_left_mask|button_right_mask,d0 ; is left/right being pressed?
bne.s Obj01_NoRoll ; if yes, branch
btst #button_down,(Ctrl_1_Held_Logical).w ; is down being pressed?
bne.s Obj01_ChkRoll ; if yes, branch
; return_1A9F8:
Obj01_NoRoll:
rts
; ---------------------------------------------------------------------------
; loc_1A9FA:
Obj01_ChkRoll:
btst #2,status(a0) ; is Sonic already rolling?
beq.s Obj01_DoRoll ; if not, branch
rts
; ---------------------------------------------------------------------------
; loc_1AA04:
Obj01_DoRoll:
bset #2,status(a0)
move.b #$E,y_radius(a0)
move.b #7,x_radius(a0)
move.b #AniIDSonAni_Roll,anim(a0) ; use "rolling" animation
addq.w #5,y_pos(a0)
move.w #SndID_Roll,d0
jsr (PlaySound).l ; play rolling sound
tst.w inertia(a0)
bne.s return_1AA36
move.w #$200,inertia(a0)
return_1AA36:
rts
; End of function Sonic_Roll
; ---------------------------------------------------------------------------
; Subroutine allowing Sonic to jump
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1AA38:
Sonic_Jump:
move.b (Ctrl_1_Press_Logical).w,d0
andi.b #button_B_mask|button_C_mask|button_A_mask,d0 ; is A, B or C pressed?
beq.w return_1AAE6 ; if not, return
moveq #0,d0
move.b angle(a0),d0
addi.b #$80,d0
bsr.w CalcRoomOverHead
cmpi.w #6,d1 ; does Sonic have enough room to jump?
blt.w return_1AAE6 ; if not, branch
move.w #$680,d2
tst.b (Super_Sonic_flag).w
beq.s +
move.w #$800,d2 ; set higher jump speed if super
+
btst #6,status(a0) ; Test if underwater
beq.s +
move.w #$380,d2 ; set lower jump speed if under
+
moveq #0,d0
move.b angle(a0),d0
subi.b #$40,d0
jsr (CalcSine).l
muls.w d2,d1
asr.l #8,d1
add.w d1,x_vel(a0) ; make Sonic jump (in X... this adds nothing on level ground)
muls.w d2,d0
asr.l #8,d0
add.w d0,y_vel(a0) ; make Sonic jump (in Y)
bset #1,status(a0)
bclr #5,status(a0)
addq.l #4,sp
move.b #1,jumping(a0)
clr.b stick_to_convex(a0)
move.w #SndID_Jump,d0
jsr (PlaySound).l ; play jumping sound
move.b #$13,y_radius(a0)
move.b #9,x_radius(a0)
btst #2,status(a0)
bne.s Sonic_RollJump
move.b #$E,y_radius(a0)
move.b #7,x_radius(a0)
move.b #AniIDSonAni_Roll,anim(a0) ; use "jumping" animation
bset #2,status(a0)
addq.w #5,y_pos(a0)
return_1AAE6:
rts
; ---------------------------------------------------------------------------
; loc_1AAE8:
Sonic_RollJump:
bset #4,status(a0) ; set the rolling+jumping flag
rts
; End of function Sonic_Jump
; ---------------------------------------------------------------------------
; Subroutine letting Sonic control the height of the jump
; when the jump button is released
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; ===========================================================================
; loc_1AAF0:
Sonic_JumpHeight:
tst.b jumping(a0) ; is Sonic jumping?
beq.s Sonic_UpVelCap ; if not, branch
move.w #-$400,d1
btst #6,status(a0) ; is Sonic underwater?
beq.s + ; if not, branch
move.w #-$200,d1
+
cmp.w y_vel(a0),d1 ; is Sonic going up faster than d1?
ble.s + ; if not, branch
move.b (Ctrl_1_Held_Logical).w,d0
andi.b #button_B_mask|button_C_mask|button_A_mask,d0 ; is a jump button pressed?
bne.s + ; if yes, branch
move.w d1,y_vel(a0) ; immediately reduce Sonic's upward speed to d1
+
tst.b y_vel(a0) ; is Sonic exactly at the height of his jump?
beq.s Sonic_CheckGoSuper ; if yes, test for turning into Super Sonic
rts
; ---------------------------------------------------------------------------
; loc_1AB22:
Sonic_UpVelCap:
tst.b pinball_mode(a0) ; is Sonic charging a spindash or in a rolling-only area?
bne.s return_1AB36 ; if yes, return
cmpi.w #-$FC0,y_vel(a0) ; is Sonic moving up really fast?
bge.s return_1AB36 ; if not, return
move.w #-$FC0,y_vel(a0) ; cap upward speed
return_1AB36:
rts
; End of subroutine Sonic_JumpHeight
; ---------------------------------------------------------------------------
; Subroutine called at the peak of a jump that transforms Sonic into Super Sonic
; if he has enough rings and emeralds
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1AB38: test_set_SS:
Sonic_CheckGoSuper:
tst.b (Super_Sonic_flag).w ; is Sonic already Super?
bne.s return_1ABA4 ; if yes, branch
cmpi.b #7,(Emerald_count).w ; does Sonic have exactly 7 emeralds?
bne.s return_1ABA4 ; if not, branch
cmpi.w #50,(Ring_count).w ; does Sonic have at least 50 rings?
blo.s return_1ABA4 ; if not, branch
if gameRevision=2
; fixes a bug where the player can get stuck if transforming at the end of a level
tst.b (Update_HUD_timer).w ; has Sonic reached the end of the act?
beq.s return_1ABA4 ; if yes, branch
endif
move.b #1,(Super_Sonic_palette).w
move.b #$F,(Palette_timer).w
move.b #1,(Super_Sonic_flag).w
move.b #$81,obj_control(a0)
move.b #AniIDSupSonAni_Transform,anim(a0) ; use transformation animation
move.b #ObjID_SuperSonicStars,(SuperSonicStars+id).w ; load Obj7E (super sonic stars object) at $FFFFD040
move.w #$A00,(Sonic_top_speed).w
move.w #$30,(Sonic_acceleration).w
move.w #$100,(Sonic_deceleration).w
move.w #0,invincibility_time(a0)
bset #status_sec_isInvincible,status_secondary(a0) ; make Sonic invincible
move.w #SndID_SuperTransform,d0
jsr (PlaySound).l ; Play transformation sound effect.
move.w #MusID_SuperSonic,d0
jmp (PlayMusic).l ; load the Super Sonic song and return
; ---------------------------------------------------------------------------
return_1ABA4:
rts
; End of subroutine Sonic_CheckGoSuper
; ---------------------------------------------------------------------------
; Subroutine doing the extra logic for Super Sonic
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1ABA6:
Sonic_Super:
tst.b (Super_Sonic_flag).w ; Ignore all this code if not Super Sonic
beq.w return_1AC3C
tst.b (Update_HUD_timer).w
beq.s Sonic_RevertToNormal ; ?
subq.w #1,(Super_Sonic_frame_count).w
bpl.w return_1AC3C
move.w #60,(Super_Sonic_frame_count).w ; Reset frame counter to 60
tst.w (Ring_count).w
beq.s Sonic_RevertToNormal
ori.b #1,(Update_HUD_rings).w
cmpi.w #1,(Ring_count).w
beq.s +
cmpi.w #10,(Ring_count).w
beq.s +
cmpi.w #100,(Ring_count).w
bne.s ++
+
ori.b #$80,(Update_HUD_rings).w
+
subq.w #1,(Ring_count).w
bne.s return_1AC3C
; loc_1ABF2:
Sonic_RevertToNormal:
move.b #2,(Super_Sonic_palette).w ; Remove rotating palette
move.w #$28,(Palette_frame).w
move.b #0,(Super_Sonic_flag).w
move.b #1,next_anim(a0) ; Change animation back to normal ?
move.w #1,invincibility_time(a0) ; Remove invincibility
move.w #$600,(Sonic_top_speed).w
move.w #$C,(Sonic_acceleration).w
move.w #$80,(Sonic_deceleration).w
btst #6,status(a0) ; Check if underwater, return if not
beq.s return_1AC3C
move.w #$300,(Sonic_top_speed).w
move.w #6,(Sonic_acceleration).w
move.w #$40,(Sonic_deceleration).w
return_1AC3C:
rts
; End of subroutine Sonic_Super
; ---------------------------------------------------------------------------
; Subroutine to check for starting to charge a spindash
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1AC3E:
Sonic_CheckSpindash:
tst.b spindash_flag(a0)
bne.s Sonic_UpdateSpindash
cmpi.b #AniIDSonAni_Duck,anim(a0)
bne.s return_1AC8C
move.b (Ctrl_1_Press_Logical).w,d0
andi.b #button_B_mask|button_C_mask|button_A_mask,d0
beq.w return_1AC8C
move.b #AniIDSonAni_Spindash,anim(a0)
move.w #SndID_SpindashRev,d0
jsr (PlaySound).l
addq.l #4,sp
move.b #1,spindash_flag(a0)
move.w #0,spindash_counter(a0)
cmpi.b #$C,air_left(a0) ; if he's drowning, branch to not make dust
blo.s +
move.b #2,(Sonic_Dust+anim).w
+
bsr.w Sonic_LevelBound
bsr.w AnglePos
return_1AC8C:
rts
; End of subroutine Sonic_CheckSpindash
; ---------------------------------------------------------------------------
; Subrouting to update an already-charging spindash
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1AC8E:
Sonic_UpdateSpindash:
move.b (Ctrl_1_Held_Logical).w,d0
btst #button_down,d0
bne.w Sonic_ChargingSpindash
; unleash the charged spindash and start rolling quickly:
move.b #$E,y_radius(a0)
move.b #7,x_radius(a0)
move.b #AniIDSonAni_Roll,anim(a0)
addq.w #5,y_pos(a0) ; add the difference between Sonic's rolling and standing heights
move.b #0,spindash_flag(a0)
moveq #0,d0
move.b spindash_counter(a0),d0
add.w d0,d0
move.w SpindashSpeeds(pc,d0.w),inertia(a0)
tst.b (Super_Sonic_flag).w
beq.s +
move.w SpindashSpeedsSuper(pc,d0.w),inertia(a0)
+
move.w inertia(a0),d0
subi.w #$800,d0
add.w d0,d0
andi.w #$1F00,d0
neg.w d0
addi.w #$2000,d0
move.w d0,(Horiz_scroll_delay_val).w
btst #0,status(a0)
beq.s +
neg.w inertia(a0)
+
bset #2,status(a0)
move.b #0,(Sonic_Dust+anim).w
move.w #SndID_SpindashRelease,d0 ; spindash zoom sound
jsr (PlaySound).l
bra.s Obj01_Spindash_ResetScr
; ===========================================================================
; word_1AD0C:
SpindashSpeeds:
dc.w $800 ; 0
dc.w $880 ; 1
dc.w $900 ; 2
dc.w $980 ; 3
dc.w $A00 ; 4
dc.w $A80 ; 5
dc.w $B00 ; 6
dc.w $B80 ; 7
dc.w $C00 ; 8
; word_1AD1E:
SpindashSpeedsSuper:
dc.w $B00 ; 0
dc.w $B80 ; 1
dc.w $C00 ; 2
dc.w $C80 ; 3
dc.w $D00 ; 4
dc.w $D80 ; 5
dc.w $E00 ; 6
dc.w $E80 ; 7
dc.w $F00 ; 8
; ===========================================================================
; loc_1AD30:
Sonic_ChargingSpindash: ; If still charging the dash...
tst.w spindash_counter(a0)
beq.s +
move.w spindash_counter(a0),d0
lsr.w #5,d0
sub.w d0,spindash_counter(a0)
bcc.s +
move.w #0,spindash_counter(a0)
+
move.b (Ctrl_1_Press_Logical).w,d0
andi.b #button_B_mask|button_C_mask|button_A_mask,d0
beq.w Obj01_Spindash_ResetScr
move.w #(AniIDSonAni_Spindash<<8),anim(a0)
move.w #SndID_SpindashRev,d0
jsr (PlaySound).l
addi.w #$200,spindash_counter(a0)
cmpi.w #$800,spindash_counter(a0)
blo.s Obj01_Spindash_ResetScr
move.w #$800,spindash_counter(a0)
; loc_1AD78:
Obj01_Spindash_ResetScr:
addq.l #4,sp
cmpi.w #(224/2)-16,(Camera_Y_pos_bias).w
beq.s loc_1AD8C
bhs.s +
addq.w #4,(Camera_Y_pos_bias).w
+ subq.w #2,(Camera_Y_pos_bias).w
loc_1AD8C:
bsr.w Sonic_LevelBound
bsr.w AnglePos
rts
; End of subroutine Sonic_UpdateSpindash
; ---------------------------------------------------------------------------
; Subroutine to slow Sonic walking up a slope
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1AD96:
Sonic_SlopeResist:
move.b angle(a0),d0
addi.b #$60,d0
cmpi.b #$C0,d0
bhs.s return_1ADCA
move.b angle(a0),d0
jsr (CalcSine).l
muls.w #$20,d0
asr.l #8,d0
tst.w inertia(a0)
beq.s return_1ADCA
bmi.s loc_1ADC6
tst.w d0
beq.s +
add.w d0,inertia(a0) ; change Sonic's $14
+
rts
; ---------------------------------------------------------------------------
loc_1ADC6:
add.w d0,inertia(a0)
return_1ADCA:
rts
; End of subroutine Sonic_SlopeResist
; ---------------------------------------------------------------------------
; Subroutine to push Sonic down a slope while he's rolling
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1ADCC:
Sonic_RollRepel:
move.b angle(a0),d0
addi.b #$60,d0
cmpi.b #-$40,d0
bhs.s return_1AE06
move.b angle(a0),d0
jsr (CalcSine).l
muls.w #$50,d0
asr.l #8,d0
tst.w inertia(a0)
bmi.s loc_1ADFC
tst.w d0
bpl.s loc_1ADF6
asr.l #2,d0
loc_1ADF6:
add.w d0,inertia(a0)
rts
; ===========================================================================
loc_1ADFC:
tst.w d0
bmi.s loc_1AE02
asr.l #2,d0
loc_1AE02:
add.w d0,inertia(a0)
return_1AE06:
rts
; End of function Sonic_RollRepel
; ---------------------------------------------------------------------------
; Subroutine to push Sonic down a slope
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1AE08:
Sonic_SlopeRepel:
nop
tst.b stick_to_convex(a0)
bne.s return_1AE42
tst.w move_lock(a0)
bne.s loc_1AE44
move.b angle(a0),d0
addi.b #$20,d0
andi.b #$C0,d0
beq.s return_1AE42
mvabs.w inertia(a0),d0
cmpi.w #$280,d0
bhs.s return_1AE42
clr.w inertia(a0)
bset #1,status(a0)
move.w #$1E,move_lock(a0)
return_1AE42:
rts
; ===========================================================================
loc_1AE44:
subq.w #1,move_lock(a0)
rts
; End of function Sonic_SlopeRepel
; ---------------------------------------------------------------------------
; Subroutine to return Sonic's angle to 0 as he jumps
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1AE4A:
Sonic_JumpAngle:
move.b angle(a0),d0 ; get Sonic's angle
beq.s Sonic_JumpFlip ; if already 0, branch
bpl.s loc_1AE5A ; if higher than 0, branch
addq.b #2,d0 ; increase angle
bcc.s BranchTo_Sonic_JumpAngleSet
moveq #0,d0
BranchTo_Sonic_JumpAngleSet
bra.s Sonic_JumpAngleSet
; ===========================================================================
loc_1AE5A:
subq.b #2,d0 ; decrease angle
bcc.s Sonic_JumpAngleSet
moveq #0,d0
; loc_1AE60:
Sonic_JumpAngleSet:
move.b d0,angle(a0)
; End of function Sonic_JumpAngle
; continue straight to Sonic_JumpFlip
; ---------------------------------------------------------------------------
; Updates Sonic's secondary angle if he's tumbling
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1AE64:
Sonic_JumpFlip:
move.b flip_angle(a0),d0
beq.s return_1AEA8
tst.w inertia(a0)
bmi.s Sonic_JumpLeftFlip
; loc_1AE70:
Sonic_JumpRightFlip:
move.b flip_speed(a0),d1
add.b d1,d0
bcc.s BranchTo_Sonic_JumpFlipSet
subq.b #1,flips_remaining(a0)
bcc.s BranchTo_Sonic_JumpFlipSet
move.b #0,flips_remaining(a0)
moveq #0,d0
BranchTo_Sonic_JumpFlipSet
bra.s Sonic_JumpFlipSet
; ===========================================================================
; loc_1AE88:
Sonic_JumpLeftFlip:
tst.b flip_turned(a0)
bne.s Sonic_JumpRightFlip
move.b flip_speed(a0),d1
sub.b d1,d0
bcc.s Sonic_JumpFlipSet
subq.b #1,flips_remaining(a0)
bcc.s Sonic_JumpFlipSet
move.b #0,flips_remaining(a0)
moveq #0,d0
; loc_1AEA4:
Sonic_JumpFlipSet:
move.b d0,flip_angle(a0)
return_1AEA8:
rts
; End of function Sonic_JumpFlip
; ---------------------------------------------------------------------------
; Subroutine for Sonic to interact with the floor and walls when he's in the air
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1AEAA: Sonic_Floor:
Sonic_DoLevelCollision:
move.l #Primary_Collision,(Collision_addr).w
cmpi.b #$C,top_solid_bit(a0)
beq.s +
move.l #Secondary_Collision,(Collision_addr).w
+
move.b lrb_solid_bit(a0),d5
move.w x_vel(a0),d1
move.w y_vel(a0),d2
jsr (CalcAngle).l
subi.b #$20,d0
andi.b #$C0,d0
cmpi.b #$40,d0
beq.w Sonic_HitLeftWall
cmpi.b #$80,d0
beq.w Sonic_HitCeilingAndWalls
cmpi.b #$C0,d0
beq.w Sonic_HitRightWall
bsr.w CheckLeftWallDist
tst.w d1
bpl.s +
sub.w d1,x_pos(a0)
move.w #0,x_vel(a0) ; stop Sonic since he hit a wall
+
bsr.w CheckRightWallDist
tst.w d1
bpl.s +
add.w d1,x_pos(a0)
move.w #0,x_vel(a0) ; stop Sonic since he hit a wall
+
bsr.w Sonic_CheckFloor
tst.w d1
bpl.s return_1AF8A
move.b y_vel(a0),d2
addq.b #8,d2
neg.b d2
cmp.b d2,d1
bge.s +
cmp.b d2,d0
blt.s return_1AF8A
+
add.w d1,y_pos(a0)
move.b d3,angle(a0)
bsr.w Sonic_ResetOnFloor
move.b d3,d0
addi.b #$20,d0
andi.b #$40,d0
bne.s loc_1AF68
move.b d3,d0
addi.b #$10,d0
andi.b #$20,d0
beq.s loc_1AF5A
asr y_vel(a0)
bra.s loc_1AF7C
; ===========================================================================
loc_1AF5A:
move.w #0,y_vel(a0)
move.w x_vel(a0),inertia(a0)
rts
; ===========================================================================
loc_1AF68:
move.w #0,x_vel(a0) ; stop Sonic since he hit a wall
cmpi.w #$FC0,y_vel(a0)
ble.s loc_1AF7C
move.w #$FC0,y_vel(a0)
loc_1AF7C:
move.w y_vel(a0),inertia(a0)
tst.b d3
bpl.s return_1AF8A
neg.w inertia(a0)
return_1AF8A:
rts
; ===========================================================================
; loc_1AF8C:
Sonic_HitLeftWall:
bsr.w CheckLeftWallDist
tst.w d1
bpl.s Sonic_HitCeiling ; branch if distance is positive (not inside wall)
sub.w d1,x_pos(a0)
move.w #0,x_vel(a0) ; stop Sonic since he hit a wall
move.w y_vel(a0),inertia(a0)
rts
; ===========================================================================
; loc_1AFA6:
Sonic_HitCeiling:
bsr.w Sonic_CheckCeiling
tst.w d1
bpl.s Sonic_HitFloor ; branch if distance is positive (not inside ceiling)
sub.w d1,y_pos(a0)
tst.w y_vel(a0)
bpl.s return_1AFBE
move.w #0,y_vel(a0) ; stop Sonic in y since he hit a ceiling
return_1AFBE:
rts
; ===========================================================================
; loc_1AFC0:
Sonic_HitFloor:
tst.w y_vel(a0)
bmi.s return_1AFE6
bsr.w Sonic_CheckFloor
tst.w d1
bpl.s return_1AFE6
add.w d1,y_pos(a0)
move.b d3,angle(a0)
bsr.w Sonic_ResetOnFloor
move.w #0,y_vel(a0)
move.w x_vel(a0),inertia(a0)
return_1AFE6:
rts
; ===========================================================================
; loc_1AFE8:
Sonic_HitCeilingAndWalls:
bsr.w CheckLeftWallDist
tst.w d1
bpl.s +
sub.w d1,x_pos(a0)
move.w #0,x_vel(a0) ; stop Sonic since he hit a wall
+
bsr.w CheckRightWallDist
tst.w d1
bpl.s +
add.w d1,x_pos(a0)
move.w #0,x_vel(a0) ; stop Sonic since he hit a wall
+
bsr.w Sonic_CheckCeiling
tst.w d1
bpl.s return_1B042
sub.w d1,y_pos(a0)
move.b d3,d0
addi.b #$20,d0
andi.b #$40,d0
bne.s loc_1B02C
move.w #0,y_vel(a0) ; stop Sonic in y since he hit a ceiling
rts
; ===========================================================================
loc_1B02C:
move.b d3,angle(a0)
bsr.w Sonic_ResetOnFloor
move.w y_vel(a0),inertia(a0)
tst.b d3
bpl.s return_1B042
neg.w inertia(a0)
return_1B042:
rts
; ===========================================================================
; loc_1B044:
Sonic_HitRightWall:
bsr.w CheckRightWallDist
tst.w d1
bpl.s Sonic_HitCeiling2
add.w d1,x_pos(a0)
move.w #0,x_vel(a0) ; stop Sonic since he hit a wall
move.w y_vel(a0),inertia(a0)
rts
; ===========================================================================
; identical to Sonic_HitCeiling...
; loc_1B05E:
Sonic_HitCeiling2:
bsr.w Sonic_CheckCeiling
tst.w d1
bpl.s Sonic_HitFloor2
sub.w d1,y_pos(a0)
tst.w y_vel(a0)
bpl.s return_1B076
move.w #0,y_vel(a0) ; stop Sonic in y since he hit a ceiling
return_1B076:
rts
; ===========================================================================
; identical to Sonic_HitFloor...
; loc_1B078:
Sonic_HitFloor2:
tst.w y_vel(a0)
bmi.s return_1B09E
bsr.w Sonic_CheckFloor
tst.w d1
bpl.s return_1B09E
add.w d1,y_pos(a0)
move.b d3,angle(a0)
bsr.w Sonic_ResetOnFloor
move.w #0,y_vel(a0)
move.w x_vel(a0),inertia(a0)
return_1B09E:
rts
; End of function Sonic_DoLevelCollision
; ---------------------------------------------------------------------------
; Subroutine to reset Sonic's mode when he lands on the floor
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1B0A0:
Sonic_ResetOnFloor:
tst.b pinball_mode(a0)
bne.s Sonic_ResetOnFloor_Part3
move.b #AniIDSonAni_Walk,anim(a0)
; loc_1B0AC:
Sonic_ResetOnFloor_Part2:
; some routines outside of Tails' code can call Sonic_ResetOnFloor_Part2
; when they mean to call Tails_ResetOnFloor_Part2, so fix that here
_cmpi.b #ObjID_Sonic,id(a0) ; is this object ID Sonic (obj01)?
bne.w Tails_ResetOnFloor_Part2 ; if not, branch to the Tails version of this code
btst #2,status(a0)
beq.s Sonic_ResetOnFloor_Part3
bclr #2,status(a0)
move.b #$13,y_radius(a0) ; this increases Sonic's collision height to standing
move.b #9,x_radius(a0)
move.b #AniIDSonAni_Walk,anim(a0) ; use running/walking/standing animation
subq.w #5,y_pos(a0) ; move Sonic up 5 pixels so the increased height doesn't push him into the ground
; loc_1B0DA:
Sonic_ResetOnFloor_Part3:
bclr #1,status(a0)
bclr #5,status(a0)
bclr #4,status(a0)
move.b #0,jumping(a0)
move.w #0,(Chain_Bonus_counter).w
move.b #0,flip_angle(a0)
move.b #0,flip_turned(a0)
move.b #0,flips_remaining(a0)
move.w #0,(Sonic_Look_delay_counter).w
cmpi.b #AniIDSonAni_Hang2,anim(a0)
bne.s return_1B11E
move.b #AniIDSonAni_Walk,anim(a0)
return_1B11E:
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Sonic when he gets hurt
; ---------------------------------------------------------------------------
; loc_1B120: Obj_01_Sub_4:
Obj01_Hurt:
tst.w (Debug_mode_flag).w
beq.s Obj01_Hurt_Normal
btst #button_B,(Ctrl_1_Press).w
beq.s Obj01_Hurt_Normal
move.w #1,(Debug_placement_mode).w
clr.b (Control_Locked).w
rts
; ---------------------------------------------------------------------------
; loc_1B13A:
Obj01_Hurt_Normal:
tst.b routine_secondary(a0)
bmi.w Sonic_HurtInstantRecover
jsr (ObjectMove).l
addi.w #$30,y_vel(a0)
btst #6,status(a0)
beq.s +
subi.w #$20,y_vel(a0)
+
cmpi.w #-$100,(Camera_Min_Y_pos).w
bne.s +
andi.w #$7FF,y_pos(a0)
+
bsr.w Sonic_HurtStop
bsr.w Sonic_LevelBound
bsr.w Sonic_RecordPos
bsr.w Sonic_Animate
bsr.w LoadSonicDynPLC
jmp (DisplaySprite).l
; ===========================================================================
; loc_1B184:
Sonic_HurtStop:
move.w (Camera_Max_Y_pos_now).w,d0
addi.w #$E0,d0
cmp.w y_pos(a0),d0
blt.w JmpTo_KillCharacter
bsr.w Sonic_DoLevelCollision
btst #1,status(a0)
bne.s return_1B1C8
moveq #0,d0
move.w d0,y_vel(a0)
move.w d0,x_vel(a0)
move.w d0,inertia(a0)
move.b d0,obj_control(a0)
move.b #AniIDSonAni_Walk,anim(a0)
subq.b #2,routine(a0) ; => Obj01_Control
move.w #$78,invulnerable_time(a0)
move.b #0,spindash_flag(a0)
return_1B1C8:
rts
; ===========================================================================
; makes Sonic recover control after being hurt before landing
; seems to be unused
; loc_1B1CA:
Sonic_HurtInstantRecover:
subq.b #2,routine(a0) ; => Obj01_Control
move.b #0,routine_secondary(a0)
bsr.w Sonic_RecordPos
bsr.w Sonic_Animate
bsr.w LoadSonicDynPLC
jmp (DisplaySprite).l
; ===========================================================================
; ---------------------------------------------------------------------------
; Sonic when he dies
; ...poor Sonic
; ---------------------------------------------------------------------------
; loc_1B1E6: Obj_01_Sub_6:
Obj01_Dead:
tst.w (Debug_mode_flag).w
beq.s +
btst #button_B,(Ctrl_1_Press).w
beq.s +
move.w #1,(Debug_placement_mode).w
clr.b (Control_Locked).w
rts
+
bsr.w CheckGameOver
jsr (ObjectMoveAndFall).l
bsr.w Sonic_RecordPos
bsr.w Sonic_Animate
bsr.w LoadSonicDynPLC
jmp (DisplaySprite).l
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1B21C:
CheckGameOver:
move.b #1,(Scroll_lock).w
move.b #0,spindash_flag(a0)
move.w (Camera_Max_Y_pos_now).w,d0
addi.w #$100,d0
cmp.w y_pos(a0),d0
bge.w return_1B31A
move.b #8,routine(a0) ; => Obj01_Gone
move.w #$3C,restart_countdown(a0)
addq.b #1,(Update_HUD_lives).w ; update lives counter
subq.b #1,(Life_count).w ; subtract 1 from number of lives
bne.s Obj01_ResetLevel ; if it's not a game over, branch
move.w #0,restart_countdown(a0)
move.b #ObjID_GameOver,(GameOver_GameText+id).w ; load Obj39 (game over text)
move.b #ObjID_GameOver,(GameOver_OverText+id).w ; load Obj39 (game over text)
move.b #1,(GameOver_OverText+mapping_frame).w
move.w a0,(GameOver_GameText+parent).w
clr.b (Time_Over_flag).w
; loc_1B26E:
Obj01_Finished:
clr.b (Update_HUD_timer).w
clr.b (Update_HUD_timer_2P).w
move.b #8,routine(a0) ; => Obj01_Gone
move.w #MusID_GameOver,d0
jsr (PlayMusic).l
moveq #PLCID_GameOver,d0
jmp (LoadPLC).l
; End of function CheckGameOver
; ===========================================================================
; ---------------------------------------------------------------------------
; Sonic when the level is restarted
; ---------------------------------------------------------------------------
; loc_1B28E:
Obj01_ResetLevel:
tst.b (Time_Over_flag).w
beq.s Obj01_ResetLevel_Part2
move.w #0,restart_countdown(a0)
move.b #ObjID_TimeOver,(TimeOver_TimeText+id).w ; load Obj39
move.b #ObjID_TimeOver,(TimeOver_OverText+id).w ; load Obj39
move.b #2,(TimeOver_TimeText+mapping_frame).w
move.b #3,(TimeOver_OverText+mapping_frame).w
move.w a0,(TimeOver_TimeText+parent).w
bra.s Obj01_Finished
; ---------------------------------------------------------------------------
Obj01_ResetLevel_Part2:
tst.w (Two_player_mode).w
beq.s return_1B31A
move.b #0,(Scroll_lock).w
move.b #$A,routine(a0) ; => Obj01_Respawning
move.w (Saved_x_pos).w,x_pos(a0)
move.w (Saved_y_pos).w,y_pos(a0)
move.w (Saved_art_tile).w,art_tile(a0)
move.w (Saved_Solid_bits).w,top_solid_bit(a0)
clr.w (Ring_count).w
clr.b (Extra_life_flags).w
move.b #0,obj_control(a0)
move.b #5,anim(a0)
move.w #0,x_vel(a0)
move.w #0,y_vel(a0)
move.w #0,inertia(a0)
move.b #2,status(a0)
move.w #0,move_lock(a0)
move.w #0,restart_countdown(a0)
return_1B31A:
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Sonic when he's offscreen and waiting for the level to restart
; ---------------------------------------------------------------------------
; loc_1B31C: Obj_01_Sub_8:
Obj01_Gone:
tst.w restart_countdown(a0)
beq.s +
subq.w #1,restart_countdown(a0)
bne.s +
move.w #1,(Level_Inactive_flag).w
+
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Sonic when he's waiting for the camera to scroll back to where he respawned
; ---------------------------------------------------------------------------
; loc_1B330: Obj_01_Sub_A:
Obj01_Respawning:
tst.w (Camera_X_pos_diff).w
bne.s +
tst.w (Camera_Y_pos_diff).w
bne.s +
move.b #2,routine(a0) ; => Obj01_Control
+
bsr.w Sonic_Animate
bsr.w LoadSonicDynPLC
jmp (DisplaySprite).l
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to animate Sonic's sprites
; See also: AnimateSprite
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1B350:
Sonic_Animate:
lea (SonicAniData).l,a1
tst.b (Super_Sonic_flag).w
beq.s +
lea (SuperSonicAniData).l,a1
+
moveq #0,d0
move.b anim(a0),d0
cmp.b next_anim(a0),d0 ; has animation changed?
beq.s SAnim_Do ; if not, branch
move.b d0,next_anim(a0) ; set to next animation
move.b #0,anim_frame(a0) ; reset animation frame
move.b #0,anim_frame_duration(a0) ; reset frame duration
bclr #5,status(a0)
; loc_1B384:
SAnim_Do:
add.w d0,d0
adda.w (a1,d0.w),a1 ; calculate address of appropriate animation script
move.b (a1),d0
bmi.s SAnim_WalkRun ; if animation is walk/run/roll/jump, branch
move.b status(a0),d1
andi.b #1,d1
andi.b #$FC,render_flags(a0)
or.b d1,render_flags(a0)
subq.b #1,anim_frame_duration(a0) ; subtract 1 from frame duration
bpl.s SAnim_Delay ; if time remains, branch
move.b d0,anim_frame_duration(a0) ; load frame duration
; loc_1B3AA:
SAnim_Do2:
moveq #0,d1
move.b anim_frame(a0),d1 ; load current frame number
move.b 1(a1,d1.w),d0 ; read sprite number from script
cmpi.b #$F0,d0
bhs.s SAnim_End_FF ; if animation is complete, branch
; loc_1B3BA:
SAnim_Next:
move.b d0,mapping_frame(a0) ; load sprite number
addq.b #1,anim_frame(a0) ; go to next frame
; return_1B3C2:
SAnim_Delay:
rts
; ===========================================================================
; loc_1B3C4:
SAnim_End_FF:
addq.b #1,d0 ; is the end flag = $FF ?
bne.s SAnim_End_FE ; if not, branch
move.b #0,anim_frame(a0) ; restart the animation
move.b 1(a1),d0 ; read sprite number
bra.s SAnim_Next
; ===========================================================================
; loc_1B3D4:
SAnim_End_FE:
addq.b #1,d0 ; is the end flag = $FE ?
bne.s SAnim_End_FD ; if not, branch
move.b 2(a1,d1.w),d0 ; read the next byte in the script
sub.b d0,anim_frame(a0) ; jump back d0 bytes in the script
sub.b d0,d1
move.b 1(a1,d1.w),d0 ; read sprite number
bra.s SAnim_Next
; ===========================================================================
; loc_1B3E8:
SAnim_End_FD:
addq.b #1,d0 ; is the end flag = $FD ?
bne.s SAnim_End ; if not, branch
move.b 2(a1,d1.w),anim(a0) ; read next byte, run that animation
; return_1B3F2:
SAnim_End:
rts
; ===========================================================================
; loc_1B3F4:
SAnim_WalkRun:
addq.b #1,d0 ; is the start flag = $FF ?
bne.w SAnim_Roll ; if not, branch
moveq #0,d0 ; is animation walking/running?
move.b flip_angle(a0),d0 ; if not, branch
bne.w SAnim_Tumble
moveq #0,d1
move.b angle(a0),d0 ; get Sonic's angle
bmi.s +
beq.s +
subq.b #1,d0
+
move.b status(a0),d2
andi.b #1,d2 ; is Sonic mirrored horizontally?
bne.s + ; if yes, branch
not.b d0 ; reverse angle
+
addi.b #$10,d0 ; add $10 to angle
bpl.s + ; if angle is $0-$7F, branch
moveq #3,d1
+
andi.b #$FC,render_flags(a0)
eor.b d1,d2
or.b d2,render_flags(a0)
btst #5,status(a0)
bne.w SAnim_Push
lsr.b #4,d0 ; divide angle by 16
andi.b #6,d0 ; angle must be 0, 2, 4 or 6
mvabs.w inertia(a0),d2 ; get Sonic's "speed" for animation purposes
if status_sec_isSliding = 7
tst.b status_secondary(a0)
bpl.w +
else
btst #status_sec_isSliding,status_secondary(a0)
beq.w +
endif
add.w d2,d2
+
tst.b (Super_Sonic_flag).w
bne.s SAnim_Super
lea (SonAni_Run).l,a1 ; use running animation
cmpi.w #$600,d2 ; is Sonic at running speed?
bhs.s + ; use running animation
lea (SonAni_Walk).l,a1 ; if yes, branch
add.b d0,d0
+
add.b d0,d0
move.b d0,d3
moveq #0,d1
move.b anim_frame(a0),d1
move.b 1(a1,d1.w),d0
cmpi.b #-1,d0
bne.s +
move.b #0,anim_frame(a0)
move.b 1(a1),d0
+
move.b d0,mapping_frame(a0)
add.b d3,mapping_frame(a0)
subq.b #1,anim_frame_duration(a0)
bpl.s return_1B4AC
neg.w d2
addi.w #$800,d2
bpl.s +
moveq #0,d2
+
lsr.w #8,d2
move.b d2,anim_frame_duration(a0) ; modify frame duration
addq.b #1,anim_frame(a0) ; modify frame number
return_1B4AC:
rts
; ===========================================================================
; loc_1B4AE:
SAnim_Super:
lea (SupSonAni_Run).l,a1 ; use fast animation
cmpi.w #$800,d2 ; is Sonic moving fast?
bhs.s SAnim_SuperRun ; if yes, branch
lea (SupSonAni_Walk).l,a1 ; use slower animation
add.b d0,d0
add.b d0,d0
bra.s SAnim_SuperWalk
; ---------------------------------------------------------------------------
; loc_1B4C6:
SAnim_SuperRun:
lsr.b #1,d0
; loc_1B4C8:
SAnim_SuperWalk:
move.b d0,d3
moveq #0,d1
move.b anim_frame(a0),d1
move.b 1(a1,d1.w),d0
cmpi.b #-1,d0
bne.s +
move.b #0,anim_frame(a0)
move.b 1(a1),d0
+
move.b d0,mapping_frame(a0)
add.b d3,mapping_frame(a0)
move.b (Timer_frames+1).w,d1
andi.b #3,d1
bne.s +
cmpi.b #$B5,mapping_frame(a0)
bhs.s +
addi.b #$20,mapping_frame(a0)
+
subq.b #1,anim_frame_duration(a0)
bpl.s return_1B51E
neg.w d2
addi.w #$800,d2
bpl.s +
moveq #0,d2
+
lsr.w #8,d2
move.b d2,anim_frame_duration(a0)
addq.b #1,anim_frame(a0)
return_1B51E:
rts
; ===========================================================================
; loc_1B520:
SAnim_Tumble:
move.b flip_angle(a0),d0
moveq #0,d1
move.b status(a0),d2
andi.b #1,d2
bne.s SAnim_Tumble_Left
andi.b #$FC,render_flags(a0)
addi.b #$B,d0
divu.w #$16,d0
addi.b #$5F,d0
move.b d0,mapping_frame(a0)
move.b #0,anim_frame_duration(a0)
rts
; ===========================================================================
; loc_1B54E:
SAnim_Tumble_Left:
andi.b #$FC,render_flags(a0)
tst.b flip_turned(a0)
beq.s loc_1B566
ori.b #1,render_flags(a0)
addi.b #$B,d0
bra.s loc_1B572
; ===========================================================================
loc_1B566:
ori.b #3,render_flags(a0)
neg.b d0
addi.b #$8F,d0
loc_1B572:
divu.w #$16,d0
addi.b #$5F,d0
move.b d0,mapping_frame(a0)
move.b #0,anim_frame_duration(a0)
rts
; ===========================================================================
; loc_1B586:
SAnim_Roll:
subq.b #1,anim_frame_duration(a0) ; subtract 1 from frame duration
bpl.w SAnim_Delay ; if time remains, branch
addq.b #1,d0 ; is the start flag = $FE ?
bne.s SAnim_Push ; if not, branch
mvabs.w inertia(a0),d2
lea (SonAni_Roll2).l,a1
cmpi.w #$600,d2
bhs.s +
lea (SonAni_Roll).l,a1
+
neg.w d2
addi.w #$400,d2
bpl.s +
moveq #0,d2
+
lsr.w #8,d2
move.b d2,anim_frame_duration(a0)
move.b status(a0),d1
andi.b #1,d1
andi.b #$FC,render_flags(a0)
or.b d1,render_flags(a0)
bra.w SAnim_Do2
; ===========================================================================
SAnim_Push:
subq.b #1,anim_frame_duration(a0) ; subtract 1 from frame duration
bpl.w SAnim_Delay ; if time remains, branch
move.w inertia(a0),d2
bmi.s +
neg.w d2
+
addi.w #$800,d2
bpl.s +
moveq #0,d2
+
lsr.w #6,d2
move.b d2,anim_frame_duration(a0)
lea (SonAni_Push).l,a1
tst.b (Super_Sonic_flag).w
beq.s +
lea (SupSonAni_Push).l,a1
+
move.b status(a0),d1
andi.b #1,d1
andi.b #$FC,render_flags(a0)
or.b d1,render_flags(a0)
bra.w SAnim_Do2
; ===========================================================================
; ---------------------------------------------------------------------------
; Animation script - Sonic
; ---------------------------------------------------------------------------
; off_1B618:
SonicAniData: offsetTable
SonAni_Walk_ptr: offsetTableEntry.w SonAni_Walk ; 0 ; 0
SonAni_Run_ptr: offsetTableEntry.w SonAni_Run ; 1 ; 1
SonAni_Roll_ptr: offsetTableEntry.w SonAni_Roll ; 2 ; 2
SonAni_Roll2_ptr: offsetTableEntry.w SonAni_Roll2 ; 3 ; 3
SonAni_Push_ptr: offsetTableEntry.w SonAni_Push ; 4 ; 4
SonAni_Wait_ptr: offsetTableEntry.w SonAni_Wait ; 5 ; 5
SonAni_Balance_ptr: offsetTableEntry.w SonAni_Balance ; 6 ; 6
SonAni_LookUp_ptr: offsetTableEntry.w SonAni_LookUp ; 7 ; 7
SonAni_Duck_ptr: offsetTableEntry.w SonAni_Duck ; 8 ; 8
SonAni_Spindash_ptr: offsetTableEntry.w SonAni_Spindash ; 9 ; 9
SonAni_Blink_ptr: offsetTableEntry.w SonAni_Blink ; 10 ; $A
SonAni_GetUp_ptr: offsetTableEntry.w SonAni_GetUp ; 11 ; $B
SonAni_Balance2_ptr: offsetTableEntry.w SonAni_Balance2 ; 12 ; $C
SonAni_Stop_ptr: offsetTableEntry.w SonAni_Stop ; 13 ; $D
SonAni_Float_ptr: offsetTableEntry.w SonAni_Float ; 14 ; $E
SonAni_Float2_ptr: offsetTableEntry.w SonAni_Float2 ; 15 ; $F
SonAni_Spring_ptr: offsetTableEntry.w SonAni_Spring ; 16 ; $10
SonAni_Hang_ptr: offsetTableEntry.w SonAni_Hang ; 17 ; $11
SonAni_Dash2_ptr: offsetTableEntry.w SonAni_Dash2 ; 18 ; $12
SonAni_Dash3_ptr: offsetTableEntry.w SonAni_Dash3 ; 19 ; $13
SonAni_Hang2_ptr: offsetTableEntry.w SonAni_Hang2 ; 20 ; $14
SonAni_Bubble_ptr: offsetTableEntry.w SonAni_Bubble ; 21 ; $15
SonAni_DeathBW_ptr: offsetTableEntry.w SonAni_DeathBW ; 22 ; $16
SonAni_Drown_ptr: offsetTableEntry.w SonAni_Drown ; 23 ; $17
SonAni_Death_ptr: offsetTableEntry.w SonAni_Death ; 24 ; $18
SonAni_Hurt_ptr: offsetTableEntry.w SonAni_Hurt ; 25 ; $19
SonAni_Hurt2_ptr: offsetTableEntry.w SonAni_Hurt ; 26 ; $1A
SonAni_Slide_ptr: offsetTableEntry.w SonAni_Slide ; 27 ; $1B
SonAni_Blank_ptr: offsetTableEntry.w SonAni_Blank ; 28 ; $1C
SonAni_Balance3_ptr: offsetTableEntry.w SonAni_Balance3 ; 29 ; $1D
SonAni_Balance4_ptr: offsetTableEntry.w SonAni_Balance4 ; 30 ; $1E
SupSonAni_Transform_ptr: offsetTableEntry.w SupSonAni_Transform ; 31 ; $1F
SonAni_Lying_ptr: offsetTableEntry.w SonAni_Lying ; 32 ; $20
SonAni_LieDown_ptr: offsetTableEntry.w SonAni_LieDown ; 33 ; $21
SonAni_Walk: dc.b $FF, $F,$10,$11,$12,$13,$14, $D, $E,$FF
rev02even
SonAni_Run: dc.b $FF,$2D,$2E,$2F,$30,$FF,$FF,$FF,$FF,$FF
rev02even
SonAni_Roll: dc.b $FE,$3D,$41,$3E,$41,$3F,$41,$40,$41,$FF
rev02even
SonAni_Roll2: dc.b $FE,$3D,$41,$3E,$41,$3F,$41,$40,$41,$FF
rev02even
SonAni_Push: dc.b $FD,$48,$49,$4A,$4B,$FF,$FF,$FF,$FF,$FF
rev02even
SonAni_Wait:
dc.b 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
dc.b 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2
dc.b 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 4, 4, 4, 5, 5
dc.b 5, 4, 4, 4, 5, 5, 5, 4, 4, 4, 5, 5, 5, 6, 6, 6
dc.b 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 5, 5, 5, 4, 4, 4
dc.b 5, 5, 5, 4, 4, 4, 5, 5, 5, 4, 4, 4, 5, 5, 5, 6
dc.b 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 5, 5, 5, 4
dc.b 4, 4, 5, 5, 5, 4, 4, 4, 5, 5, 5, 4, 4, 4, 5, 5
dc.b 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 5, 5
dc.b 5, 4, 4, 4, 5, 5, 5, 4, 4, 4, 5, 5, 5, 4, 4, 4
dc.b 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 8, 8
dc.b 8, 9, 9, 9,$FE, 6
rev02even
SonAni_Balance: dc.b 9,$CC,$CD,$CE,$CD,$FF
rev02even
SonAni_LookUp: dc.b 5, $B, $C,$FE, 1
rev02even
SonAni_Duck: dc.b 5,$4C,$4D,$FE, 1
rev02even
SonAni_Spindash:dc.b 0,$42,$43,$42,$44,$42,$45,$42,$46,$42,$47,$FF
rev02even
SonAni_Blink: dc.b 1, 2,$FD, 0
rev02even
SonAni_GetUp: dc.b 3, $A,$FD, 0
rev02even
SonAni_Balance2:dc.b 3,$C8,$C9,$CA,$CB,$FF
rev02even
SonAni_Stop: dc.b 5,$D2,$D3,$D4,$D5,$FD, 0 ; halt/skidding animation
rev02even
SonAni_Float: dc.b 7,$54,$59,$FF
rev02even
SonAni_Float2: dc.b 7,$54,$55,$56,$57,$58,$FF
rev02even
SonAni_Spring: dc.b $2F,$5B,$FD, 0
rev02even
SonAni_Hang: dc.b 1,$50,$51,$FF
rev02even
SonAni_Dash2: dc.b $F,$43,$43,$43,$FE, 1
rev02even
SonAni_Dash3: dc.b $F,$43,$44,$FE, 1
rev02even
SonAni_Hang2: dc.b $13,$6B,$6C,$FF
rev02even
SonAni_Bubble: dc.b $B,$5A,$5A,$11,$12,$FD, 0 ; breathe
rev02even
SonAni_DeathBW: dc.b $20,$5E,$FF
rev02even
SonAni_Drown: dc.b $20,$5D,$FF
rev02even
SonAni_Death: dc.b $20,$5C,$FF
rev02even
SonAni_Hurt: dc.b $40,$4E,$FF
rev02even
SonAni_Slide: dc.b 9,$4E,$4F,$FF
rev02even
SonAni_Blank: dc.b $77, 0,$FD, 0
rev02even
SonAni_Balance3:dc.b $13,$D0,$D1,$FF
rev02even
SonAni_Balance4:dc.b 3,$CF,$C8,$C9,$CA,$CB,$FE, 4
rev02even
SonAni_Lying: dc.b 9, 8, 9,$FF
rev02even
SonAni_LieDown: dc.b 3, 7,$FD, 0
even
; ---------------------------------------------------------------------------
; Animation script - Super Sonic
; (many of these point to the data above this)
; ---------------------------------------------------------------------------
SuperSonicAniData: offsetTable
offsetTableEntry.w SupSonAni_Walk ; 0 ; 0
offsetTableEntry.w SupSonAni_Run ; 1 ; 1
offsetTableEntry.w SonAni_Roll ; 2 ; 2
offsetTableEntry.w SonAni_Roll2 ; 3 ; 3
offsetTableEntry.w SupSonAni_Push ; 4 ; 4
offsetTableEntry.w SupSonAni_Stand ; 5 ; 5
offsetTableEntry.w SupSonAni_Balance ; 6 ; 6
offsetTableEntry.w SonAni_LookUp ; 7 ; 7
offsetTableEntry.w SupSonAni_Duck ; 8 ; 8
offsetTableEntry.w SonAni_Spindash ; 9 ; 9
offsetTableEntry.w SonAni_Blink ; 10 ; $A
offsetTableEntry.w SonAni_GetUp ; 11 ; $B
offsetTableEntry.w SonAni_Balance2 ; 12 ; $C
offsetTableEntry.w SonAni_Stop ; 13 ; $D
offsetTableEntry.w SonAni_Float ; 14 ; $E
offsetTableEntry.w SonAni_Float2 ; 15 ; $F
offsetTableEntry.w SonAni_Spring ; 16 ; $10
offsetTableEntry.w SonAni_Hang ; 17 ; $11
offsetTableEntry.w SonAni_Dash2 ; 18 ; $12
offsetTableEntry.w SonAni_Dash3 ; 19 ; $13
offsetTableEntry.w SonAni_Hang2 ; 20 ; $14
offsetTableEntry.w SonAni_Bubble ; 21 ; $15
offsetTableEntry.w SonAni_DeathBW ; 22 ; $16
offsetTableEntry.w SonAni_Drown ; 23 ; $17
offsetTableEntry.w SonAni_Death ; 24 ; $18
offsetTableEntry.w SonAni_Hurt ; 25 ; $19
offsetTableEntry.w SonAni_Hurt ; 26 ; $1A
offsetTableEntry.w SonAni_Slide ; 27 ; $1B
offsetTableEntry.w SonAni_Blank ; 28 ; $1C
offsetTableEntry.w SonAni_Balance3 ; 29 ; $1D
offsetTableEntry.w SonAni_Balance4 ; 30 ; $1E
offsetTableEntry.w SupSonAni_Transform ; 31 ; $1F
SupSonAni_Walk: dc.b $FF,$77,$78,$79,$7A,$7B,$7C,$75,$76,$FF
rev02even
SupSonAni_Run: dc.b $FF,$B5,$B9,$FF,$FF,$FF,$FF,$FF,$FF,$FF
rev02even
SupSonAni_Push: dc.b $FD,$BD,$BE,$BF,$C0,$FF,$FF,$FF,$FF,$FF
rev02even
SupSonAni_Stand: dc.b 7,$72,$73,$74,$73,$FF
rev02even
SupSonAni_Balance: dc.b 9,$C2,$C3,$C4,$C3,$C5,$C6,$C7,$C6,$FF
rev02even
SupSonAni_Duck: dc.b 5,$C1,$FF
rev02even
SupSonAni_Transform: dc.b 2,$6D,$6D,$6E,$6E,$6F,$70,$71,$70,$71,$70,$71,$70,$71,$FD, 0
even
; ---------------------------------------------------------------------------
; Sonic pattern loading subroutine
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1B848:
LoadSonicDynPLC:
moveq #0,d0
move.b mapping_frame(a0),d0 ; load frame number
; loc_1B84E:
LoadSonicDynPLC_Part2:
cmp.b (Sonic_LastLoadedDPLC).w,d0
beq.s return_1B89A
move.b d0,(Sonic_LastLoadedDPLC).w
lea (MapRUnc_Sonic).l,a2
add.w d0,d0
adda.w (a2,d0.w),a2
move.w (a2)+,d5
subq.w #1,d5
bmi.s return_1B89A
move.w #tiles_to_bytes(ArtTile_ArtUnc_Sonic),d4
; loc_1B86E:
SPLC_ReadEntry:
moveq #0,d1
move.w (a2)+,d1
move.w d1,d3
lsr.w #8,d3
andi.w #$F0,d3
addi.w #$10,d3
andi.w #$FFF,d1
lsl.l #5,d1
addi.l #ArtUnc_Sonic,d1
move.w d4,d2
add.w d3,d4
add.w d3,d4
jsr (QueueDMATransfer).l
dbf d5,SPLC_ReadEntry ; repeat for number of entries
return_1B89A:
rts
; ===========================================================================
JmpTo_KillCharacter
jmp (KillCharacter).l
if ~~removeJmpTos
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 02 - Tails
; ----------------------------------------------------------------------------
; Sprite_1B8A4: Object_Tails:
Obj02:
; a0=character
cmpi.w #2,(Player_mode).w
bne.s +
move.w (Camera_Min_X_pos).w,(Tails_Min_X_pos).w
move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w
move.w (Camera_Max_Y_pos_now).w,(Tails_Max_Y_pos).w
+
moveq #0,d0
move.b routine(a0),d0
move.w Obj02_Index(pc,d0.w),d1
jmp Obj02_Index(pc,d1.w)
; ===========================================================================
; off_1B8CC: Obj02_States:
Obj02_Index: offsetTable
offsetTableEntry.w Obj02_Init ; 0
offsetTableEntry.w Obj02_Control ; 2
offsetTableEntry.w Obj02_Hurt ; 4
offsetTableEntry.w Obj02_Dead ; 6
offsetTableEntry.w Obj02_Gone ; 8
offsetTableEntry.w Obj02_Respawning ; $A
; ===========================================================================
; loc_1B8D8: Obj02_Main:
Obj02_Init:
addq.b #2,routine(a0) ; => Obj02_Normal
move.b #$F,y_radius(a0) ; this sets Tails' collision height (2*pixels) to less than Sonic's height
move.b #9,x_radius(a0)
move.l #MapUnc_Tails,mappings(a0)
move.b #2,priority(a0)
move.b #$18,width_pixels(a0)
move.b #$84,render_flags(a0) ; render_flags(Tails) = $80 | initial render_flags(Sonic)
move.w #$600,(Tails_top_speed).w ; set Tails' top speed
move.w #$C,(Tails_acceleration).w ; set Tails' acceleration
move.w #$80,(Tails_deceleration).w ; set Tails' deceleration
cmpi.w #2,(Player_mode).w
bne.s Obj02_Init_2Pmode
tst.b (Last_star_pole_hit).w
bne.s Obj02_Init_Continued
; only happens when not starting at a checkpoint:
move.w #make_art_tile(ArtTile_ArtUnc_Tails,0,0),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #$C,top_solid_bit(a0)
move.b #$D,lrb_solid_bit(a0)
move.w x_pos(a0),(Saved_x_pos).w
move.w y_pos(a0),(Saved_y_pos).w
move.w art_tile(a0),(Saved_art_tile).w
move.w top_solid_bit(a0),(Saved_Solid_bits).w
bra.s Obj02_Init_Continued
; ===========================================================================
; loc_1B952:
Obj02_Init_2Pmode:
move.w #make_art_tile(ArtTile_ArtUnc_Tails,0,0),art_tile(a0)
bsr.w Adjust2PArtPointer
move.w (MainCharacter+top_solid_bit).w,top_solid_bit(a0)
tst.w (MainCharacter+art_tile).w
bpl.s Obj02_Init_Continued
ori.w #high_priority,art_tile(a0)
; loc_1B96E:
Obj02_Init_Continued:
move.w x_pos(a0),(Saved_x_pos_2P).w
move.w y_pos(a0),(Saved_y_pos_2P).w
move.w art_tile(a0),(Saved_art_tile_2P).w
move.w top_solid_bit(a0),(Saved_Solid_bits_2P).w
move.b #0,flips_remaining(a0)
move.b #4,flip_speed(a0)
move.b #$1E,air_left(a0)
move.w #0,(Tails_CPU_routine).w ; set AI state to TailsCPU_Init
move.w #0,(Tails_control_counter).w
move.w #0,(Tails_respawn_counter).w
move.b #ObjID_TailsTails,(Tails_Tails+id).w ; load Obj05 (Tails' Tails) at $FFFFD000
move.w a0,(Tails_Tails+parent).w ; set its parent object to this
; ---------------------------------------------------------------------------
; Normal state for Tails
; ---------------------------------------------------------------------------
; loc_1B9B4:
Obj02_Control:
cmpa.w #MainCharacter,a0
bne.s Obj02_Control_Joypad2
move.w (Ctrl_1_Logical).w,(Ctrl_2_Logical).w
tst.b (Control_Locked).w ; are controls locked?
bne.s Obj02_Control_Part2 ; if yes, branch
move.w (Ctrl_1).w,(Ctrl_2_Logical).w ; copy new held buttons, to enable joypad control
move.w (Ctrl_1).w,(Ctrl_1_Logical).w
bra.s Obj02_Control_Part2
; ---------------------------------------------------------------------------
; loc_1B9D4:
Obj02_Control_Joypad2:
tst.b (Control_Locked_P2).w
bne.s +
move.w (Ctrl_2).w,(Ctrl_2_Logical).w
+
tst.w (Two_player_mode).w
bne.s Obj02_Control_Part2
bsr.w TailsCPU_Control
; loc_1B9EA:
Obj02_Control_Part2:
btst #0,obj_control(a0) ; is Tails flying, or interacting with another object that holds him in place or controls his movement somehow?
bne.s + ; if yes, branch to skip Tails' control
moveq #0,d0
move.b status(a0),d0
andi.w #6,d0 ; %0000 %0110
move.w Obj02_Modes(pc,d0.w),d1
jsr Obj02_Modes(pc,d1.w) ; run Tails' movement control code
+
cmpi.w #-$100,(Camera_Min_Y_pos).w ; is vertical wrapping enabled?
bne.s + ; if not, branch
andi.w #$7FF,y_pos(a0) ; perform wrapping of Sonic's y position
+
bsr.s Tails_Display
bsr.w Tails_RecordPos
bsr.w Tails_Water
move.b (Primary_Angle).w,next_tilt(a0)
move.b (Secondary_Angle).w,tilt(a0)
tst.b (WindTunnel_flag).w
beq.s +
tst.b anim(a0)
bne.s +
move.b next_anim(a0),anim(a0)
+
bsr.w Tails_Animate
tst.b obj_control(a0)
bmi.s +
jsr (TouchResponse).l
+
bra.w LoadTailsDynPLC
; ===========================================================================
; secondary states under state Obj02_Normal
; off_1BA4E:
Obj02_Modes: offsetTable
offsetTableEntry.w Obj02_MdNormal ; 0 - not airborne or rolling
offsetTableEntry.w Obj02_MdAir ; 2 - airborne
offsetTableEntry.w Obj02_MdRoll ; 4 - rolling
offsetTableEntry.w Obj02_MdJump ; 6 - jumping
; ===========================================================================
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1BA56:
Tails_Display:
move.w invulnerable_time(a0),d0
beq.s Obj02_Display
subq.w #1,invulnerable_time(a0)
lsr.w #3,d0
bcc.s Obj02_ChkInvinc
; loc_1BA64:
Obj02_Display:
jsr (DisplaySprite).l
; loc_1BA6A:
Obj02_ChkInvinc: ; Checks if invincibility has expired and disables it if it has.
btst #status_sec_isInvincible,status_secondary(a0)
beq.s Obj02_ChkShoes
tst.w invincibility_time(a0)
beq.s Obj02_ChkShoes
subq.w #1,invincibility_time(a0)
bne.s Obj02_ChkShoes
tst.b (Current_Boss_ID).w ; Don't change music if in a boss fight
bne.s Obj02_RmvInvin
cmpi.b #$C,air_left(a0) ; Don't change music if drowning
blo.s Obj02_RmvInvin
move.w (Level_Music).w,d0
jsr (PlayMusic).l
; loc_1BA96:
Obj02_RmvInvin:
bclr #status_sec_isInvincible,status_secondary(a0)
; loc_1BA9C:
Obj02_ChkShoes: ; Checks if Speed Shoes have expired and disables them if they have.
btst #status_sec_hasSpeedShoes,status_secondary(a0)
beq.s Obj02_ExitChk
tst.w speedshoes_time(a0)
beq.s Obj02_ExitChk
subq.w #1,speedshoes_time(a0)
bne.s Obj02_ExitChk
move.w #$600,(Tails_top_speed).w
move.w #$C,(Tails_acceleration).w
move.w #$80,(Tails_deceleration).w
; Obj02_RmvSpeed:
bclr #status_sec_hasSpeedShoes,status_secondary(a0)
move.w #MusID_SlowDown,d0 ; Slow down tempo
jmp (PlayMusic).l
; ===========================================================================
; return_1BAD2:
Obj02_ExitChk:
rts
; End of subroutine Tails_Display
; ---------------------------------------------------------------------------
; Tails' AI code for the Sonic and Tails mode 1-player game
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1BAD4:
TailsCPU_Control: ; a0=Tails
move.b (Ctrl_2_Held).w,d0 ; did the real player 2 hit something?
andi.b #button_up_mask|button_down_mask|button_left_mask|button_right_mask|button_B_mask|button_C_mask|button_A_mask,d0
beq.s + ; if not, branch
move.w #600,(Tails_control_counter).w ; give player 2 control for 10 seconds (minimum)
+
lea (MainCharacter).w,a1 ; a1=character ; a1=Sonic
move.w (Tails_CPU_routine).w,d0
move.w TailsCPU_States(pc,d0.w),d0
jmp TailsCPU_States(pc,d0.w)
; ===========================================================================
; off_1BAF4:
TailsCPU_States: offsetTable
offsetTableEntry.w TailsCPU_Init ; 0
offsetTableEntry.w TailsCPU_Spawning ; 2
offsetTableEntry.w TailsCPU_Flying ; 4
offsetTableEntry.w TailsCPU_Normal ; 6
offsetTableEntry.w TailsCPU_Panic ; 8
; ===========================================================================
; initial AI State
; ---------------------------------------------------------------------------
; loc_1BAFE:
TailsCPU_Init:
move.w #6,(Tails_CPU_routine).w ; => TailsCPU_Normal
move.b #0,obj_control(a0)
move.b #AniIDTailsAni_Walk,anim(a0)
move.w #0,x_vel(a0)
move.w #0,y_vel(a0)
move.w #0,inertia(a0)
move.b #0,status(a0)
move.w #0,(Tails_respawn_counter).w
rts
; ===========================================================================
; AI State where Tails is waiting to respawn
; ---------------------------------------------------------------------------
; loc_1BB30:
TailsCPU_Spawning:
move.b (Ctrl_2_Held_Logical).w,d0
andi.b #button_B_mask|button_C_mask|button_A_mask|button_start_mask,d0
bne.s TailsCPU_Respawn
move.w (Timer_frames).w,d0
andi.w #$3F,d0
bne.s return_1BB88
tst.b obj_control(a1)
bne.s return_1BB88
move.b status(a1),d0
andi.b #$D2,d0
bne.s return_1BB88
; loc_1BB54:
TailsCPU_Respawn:
move.w #4,(Tails_CPU_routine).w ; => TailsCPU_Flying
move.w x_pos(a1),d0
move.w d0,x_pos(a0)
move.w d0,(Tails_CPU_target_x).w
move.w y_pos(a1),d0
move.w d0,(Tails_CPU_target_y).w
subi.w #$C0,d0
move.w d0,y_pos(a0)
ori.w #high_priority,art_tile(a0)
move.b #0,spindash_flag(a0)
move.w #0,spindash_counter(a0)
return_1BB88:
rts
; ===========================================================================
; AI State where Tails pretends to be a helicopter
; ---------------------------------------------------------------------------
; loc_1BB8A:
TailsCPU_Flying:
tst.b render_flags(a0)
bmi.s TailsCPU_FlyingOnscreen
addq.w #1,(Tails_respawn_counter).w
cmpi.w #$12C,(Tails_respawn_counter).w
blo.s TailsCPU_Flying_Part2
move.w #0,(Tails_respawn_counter).w
move.w #2,(Tails_CPU_routine).w ; => TailsCPU_Spawning
move.b #$81,obj_control(a0)
move.b #2,status(a0)
move.w #0,x_pos(a0)
move.w #0,y_pos(a0)
move.b #AniIDTailsAni_Fly,anim(a0)
rts
; ---------------------------------------------------------------------------
; loc_1BBC8:
TailsCPU_FlyingOnscreen:
move.w #0,(Tails_respawn_counter).w
; loc_1BBCE:
TailsCPU_Flying_Part2:
lea (Sonic_Pos_Record_Buf).w,a2
move.w #$10,d2
lsl.b #2,d2
addq.b #4,d2
move.w (Sonic_Pos_Record_Index).w,d3
sub.b d2,d3
move.w (a2,d3.w),(Tails_CPU_target_x).w
move.w 2(a2,d3.w),(Tails_CPU_target_y).w
tst.b (Water_flag).w
beq.s +
move.w (Water_Level_1).w,d0
subi.w #$10,d0
cmp.w (Tails_CPU_target_y).w,d0
bge.s +
move.w d0,(Tails_CPU_target_y).w
+
move.w x_pos(a0),d0
sub.w (Tails_CPU_target_x).w,d0
beq.s loc_1BC54
mvabs.w d0,d2
lsr.w #4,d2
cmpi.w #$C,d2
blo.s +
moveq #$C,d2
+
mvabs.b x_vel(a1),d1
add.b d1,d2
addq.w #1,d2
tst.w d0
bmi.s loc_1BC40
bset #0,status(a0)
cmp.w d0,d2
blo.s +
move.w d0,d2
moveq #0,d0
+
neg.w d2
bra.s loc_1BC50
; ---------------------------------------------------------------------------
loc_1BC40:
bclr #0,status(a0)
neg.w d0
cmp.w d0,d2
blo.s loc_1BC50
move.b d0,d2
moveq #0,d0
loc_1BC50:
add.w d2,x_pos(a0)
loc_1BC54:
moveq #1,d2
move.w y_pos(a0),d1
sub.w (Tails_CPU_target_y).w,d1
beq.s loc_1BC68
bmi.s loc_1BC64
neg.w d2
loc_1BC64:
add.w d2,y_pos(a0)
loc_1BC68:
lea (Sonic_Stat_Record_Buf).w,a2
move.b 2(a2,d3.w),d2
andi.b #$D2,d2
bne.s return_1BCDE
or.w d0,d1
bne.s return_1BCDE
move.w #6,(Tails_CPU_routine).w ; => TailsCPU_Normal
move.b #0,obj_control(a0)
move.b #AniIDTailsAni_Walk,anim(a0)
move.w #0,x_vel(a0)
move.w #0,y_vel(a0)
move.w #0,inertia(a0)
move.b #2,status(a0)
move.w #0,move_lock(a0)
andi.w #drawing_mask,art_tile(a0)
tst.b art_tile(a1)
bpl.s +
ori.w #high_priority,art_tile(a0)
+
move.b top_solid_bit(a1),top_solid_bit(a0)
move.b lrb_solid_bit(a1),lrb_solid_bit(a0)
cmpi.b #AniIDTailsAni_Spindash,anim(a1)
beq.s return_1BCDE
move.b spindash_flag(a0),d0
beq.s return_1BCDE
move.b d0,spindash_flag(a1)
bsr.w loc_212C4
return_1BCDE:
rts
; ===========================================================================
; AI State where Tails follows the player normally
; ---------------------------------------------------------------------------
; loc_1BCE0:
TailsCPU_Normal:
cmpi.b #6,(MainCharacter+routine).w ; is Sonic dead?
blo.s TailsCPU_Normal_SonicOK ; if not, branch
; Sonic's dead; fly down to his corpse
move.w #4,(Tails_CPU_routine).w ; => TailsCPU_Flying
move.b #0,spindash_flag(a0)
move.w #0,spindash_counter(a0)
move.b #$81,obj_control(a0)
move.b #2,status(a0)
move.b #AniIDTailsAni_Fly,anim(a0)
rts
; ---------------------------------------------------------------------------
; loc_1BD0E:
TailsCPU_Normal_SonicOK:
bsr.w TailsCPU_CheckDespawn
tst.w (Tails_control_counter).w ; if CPU has control
bne.w TailsCPU_Normal_HumanControl ; (if not, branch)
tst.b obj_control(a0) ; and Tails isn't fully object controlled (&$80)
bmi.w TailsCPU_Normal_HumanControl ; (if not, branch)
tst.w move_lock(a0) ; and Tails' movement is locked (usually because he just fell down a slope)
beq.s + ; (if not, branch)
tst.w inertia(a0) ; and Tails is stopped, then...
bne.s + ; (if not, branch)
move.w #8,(Tails_CPU_routine).w ; => TailsCPU_Panic
+
lea (Sonic_Pos_Record_Buf).w,a1
move.w #$10,d1
lsl.b #2,d1
addq.b #4,d1
move.w (Sonic_Pos_Record_Index).w,d0
sub.b d1,d0
move.w (a1,d0.w),d2 ; d2 = earlier x position of Sonic
move.w 2(a1,d0.w),d3 ; d3 = earlier y position of Sonic
lea (Sonic_Stat_Record_Buf).w,a1
move.w (a1,d0.w),d1 ; d1 = earlier input of Sonic
move.b 2(a1,d0.w),d4 ; d4 = earlier status of Sonic
move.w d1,d0
btst #5,status(a0) ; is Tails pushing against something?
beq.s + ; if not, branch
btst #5,d4 ; was Sonic pushing against something?
beq.w TailsCPU_Normal_FilterAction_Part2 ; if not, branch elsewhere
; either Tails isn't pushing, or Tails and Sonic are both pushing
+ sub.w x_pos(a0),d2
beq.s TailsCPU_Normal_Stand ; branch if Tails is already lined up horizontally with Sonic
bpl.s TailsCPU_Normal_FollowRight
neg.w d2
; Tails wants to go left because that's where Sonic is
; loc_1BD76: TailsCPU_Normal_FollowLeft:
cmpi.w #$10,d2
blo.s +
andi.w #~(((button_left_mask|button_right_mask)<<8)|(button_left_mask|button_right_mask)),d1 ; AND out Sonic's left/right input...
ori.w #(button_left_mask<<8)|button_left_mask,d1 ; ...and give Tails his own
+
tst.w inertia(a0)
beq.s TailsCPU_Normal_FilterAction
btst #0,status(a0)
beq.s TailsCPU_Normal_FilterAction
subq.w #1,x_pos(a0)
bra.s TailsCPU_Normal_FilterAction
; ===========================================================================
; Tails wants to go right because that's where Sonic is
; loc_1BD98:
TailsCPU_Normal_FollowRight:
cmpi.w #$10,d2
blo.s +
andi.w #~(((button_left_mask|button_right_mask)<<8)|(button_left_mask|button_right_mask)),d1 ; AND out Sonic's left/right input
ori.w #(button_right_mask<<8)|button_right_mask,d1 ; ...and give Tails his own
+
tst.w inertia(a0)
beq.s TailsCPU_Normal_FilterAction
btst #0,status(a0)
bne.s TailsCPU_Normal_FilterAction
addq.w #1,x_pos(a0)
bra.s TailsCPU_Normal_FilterAction
; ===========================================================================
; Tails is happy where he is
; loc_1BDBA:
TailsCPU_Normal_Stand:
bclr #0,status(a0)
move.b d4,d0
andi.b #1,d0
beq.s TailsCPU_Normal_FilterAction
bset #0,status(a0)
; Filter the action we chose depending on a few things
; loc_1BDCE:
TailsCPU_Normal_FilterAction:
tst.b (Tails_CPU_jumping).w
beq.s +
ori.w #((button_B_mask|button_C_mask|button_A_mask)<<8),d1
btst #1,status(a0)
bne.s TailsCPU_Normal_SendAction
move.b #0,(Tails_CPU_jumping).w
+
move.w (Timer_frames).w,d0
andi.w #$FF,d0
beq.s +
cmpi.w #$40,d2
bhs.s TailsCPU_Normal_SendAction
+
sub.w y_pos(a0),d3
beq.s TailsCPU_Normal_SendAction
bpl.s TailsCPU_Normal_SendAction
neg.w d3
cmpi.w #$20,d3
blo.s TailsCPU_Normal_SendAction
; loc_1BE06:
TailsCPU_Normal_FilterAction_Part2:
move.b (Timer_frames+1).w,d0
andi.b #$3F,d0
bne.s TailsCPU_Normal_SendAction
cmpi.b #AniIDTailsAni_Duck,anim(a0)
beq.s TailsCPU_Normal_SendAction
ori.w #((button_B_mask|button_C_mask|button_A_mask)<<8)|(button_B_mask|button_C_mask|button_A_mask),d1
move.b #1,(Tails_CPU_jumping).w
; Send the action we chose by storing it into player 2's input
; loc_1BE22:
TailsCPU_Normal_SendAction:
move.w d1,(Ctrl_2_Logical).w
rts
; ===========================================================================
; Follow orders from controller 2
; and decrease the counter to when the CPU will regain control
; loc_1BE28:
TailsCPU_Normal_HumanControl:
tst.w (Tails_control_counter).w
beq.s + ; don't decrease if it's already 0
subq.w #1,(Tails_control_counter).w
+
rts
; ===========================================================================
; loc_1BE34:
TailsCPU_Despawn:
move.w #0,(Tails_control_counter).w
move.w #0,(Tails_respawn_counter).w
move.w #2,(Tails_CPU_routine).w ; => TailsCPU_Spawning
move.b #$81,obj_control(a0)
move.b #2,status(a0)
move.w #$4000,x_pos(a0)
move.w #0,y_pos(a0)
move.b #AniIDTailsAni_Fly,anim(a0)
rts
; ===========================================================================
; sub_1BE66:
TailsCPU_CheckDespawn:
tst.b render_flags(a0)
bmi.s TailsCPU_ResetRespawnTimer
btst #3,status(a0)
beq.s TailsCPU_TickRespawnTimer
moveq #0,d0
move.b interact(a0),d0
if object_size=$40
lsl.w #6,d0
else
mulu.w #object_size,d0
endif
addi.l #Object_RAM,d0
movea.l d0,a3 ; a3=object
move.b (Tails_interact_ID).w,d0
cmp.b (a3),d0
bne.s BranchTo_TailsCPU_Despawn
; loc_1BE8C:
TailsCPU_TickRespawnTimer:
addq.w #1,(Tails_respawn_counter).w
cmpi.w #$12C,(Tails_respawn_counter).w
blo.s TailsCPU_UpdateObjInteract
BranchTo_TailsCPU_Despawn
bra.w TailsCPU_Despawn
; ===========================================================================
; loc_1BE9C:
TailsCPU_ResetRespawnTimer:
move.w #0,(Tails_respawn_counter).w
; loc_1BEA2:
TailsCPU_UpdateObjInteract:
moveq #0,d0
move.b interact(a0),d0
if object_size=$40
lsl.w #6,d0
else
mulu.w #object_size,d0
endif
addi.l #Object_RAM,d0
movea.l d0,a3 ; a3=object
move.b (a3),(Tails_interact_ID).w
rts
; ===========================================================================
; AI State where Tails stops, drops, and spindashes in Sonic's direction
; ---------------------------------------------------------------------------
; loc_1BEB8:
TailsCPU_Panic:
bsr.w TailsCPU_CheckDespawn
tst.w (Tails_control_counter).w
bne.w return_1BF36
tst.w move_lock(a0)
bne.s return_1BF36
tst.b spindash_flag(a0)
bne.s TailsCPU_Panic_ChargingDash
tst.w inertia(a0)
bne.s return_1BF36
bclr #0,status(a0)
move.w x_pos(a0),d0
sub.w x_pos(a1),d0
bcs.s +
bset #0,status(a0)
+
move.w #(button_down_mask<<8)|button_down_mask,(Ctrl_2_Logical).w
move.b (Timer_frames+1).w,d0
andi.b #$7F,d0
beq.s TailsCPU_Panic_ReleaseDash
cmpi.b #AniIDTailsAni_Duck,anim(a0)
bne.s return_1BF36
move.w #((button_down_mask|button_B_mask|button_C_mask|button_A_mask)<<8)|(button_down_mask|button_B_mask|button_C_mask|button_A_mask),(Ctrl_2_Logical).w
rts
; ---------------------------------------------------------------------------
; loc_1BF0C:
TailsCPU_Panic_ChargingDash:
move.w #(button_down_mask<<8)|button_down_mask,(Ctrl_2_Logical).w
move.b (Timer_frames+1).w,d0
andi.b #$7F,d0
bne.s TailsCPU_Panic_RevDash
; loc_1BF1C:
TailsCPU_Panic_ReleaseDash:
move.w #0,(Ctrl_2_Logical).w
move.w #6,(Tails_CPU_routine).w ; => TailsCPU_Normal
rts
; ---------------------------------------------------------------------------
; loc_1BF2A:
TailsCPU_Panic_RevDash:
andi.b #$1F,d0
bne.s return_1BF36
ori.w #((button_B_mask|button_C_mask|button_A_mask)<<8)|(button_B_mask|button_C_mask|button_A_mask),(Ctrl_2_Logical).w
return_1BF36:
rts
; End of function TailsCPU_Control
; ---------------------------------------------------------------------------
; Subroutine to record Tails' previous positions for invincibility stars
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1BF38:
Tails_RecordPos:
move.w (Tails_Pos_Record_Index).w,d0
lea (Tails_Pos_Record_Buf).w,a1
lea (a1,d0.w),a1
move.w x_pos(a0),(a1)+
move.w y_pos(a0),(a1)+
addq.b #4,(Tails_Pos_Record_Index+1).w
rts
; End of subroutine Tails_RecordPos
; ---------------------------------------------------------------------------
; Subroutine for Tails when he's underwater
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1BF52:
Tails_Water:
tst.b (Water_flag).w ; does level have water?
bne.s Obj02_InWater ; if yes, branch
return_1BF58:
rts
; ---------------------------------------------------------------------------
; loc_1BF5A:
Obj02_InWater:
move.w (Water_Level_1).w,d0
cmp.w y_pos(a0),d0 ; is Sonic above the water?
bge.s Obj02_OutWater ; if yes, branch
bset #6,status(a0) ; set underwater flag
bne.s return_1BF58 ; if already underwater, branch
movea.l a0,a1
bsr.w ResumeMusic
move.b #ObjID_SmallBubbles,(Tails_BreathingBubbles+id).w ; load Obj0A (tail's breathing bubbles) at $FFFFD0C0
move.b #$81,(Tails_BreathingBubbles+subtype).w
move.l a0,(Tails_BreathingBubbles+$3C).w ; set its parent to be this (obj0A uses $3C instead of $3E for some reason)
move.w #$300,(Tails_top_speed).w
move.w #6,(Tails_acceleration).w
move.w #$40,(Tails_deceleration).w
asr x_vel(a0)
asr y_vel(a0)
asr y_vel(a0)
beq.s return_1BF58
move.w #$100,(Tails_Dust+anim).w ; splash animation
move.w #SndID_Splash,d0 ; splash sound
jmp (PlaySound).l
; ---------------------------------------------------------------------------
; loc_1BFB2:
Obj02_OutWater:
bclr #6,status(a0) ; unset underwater flag
beq.s return_1BF58 ; if already above water, branch
movea.l a0,a1
bsr.w ResumeMusic
move.w #$600,(Tails_top_speed).w
move.w #$C,(Tails_acceleration).w
move.w #$80,(Tails_deceleration).w
cmpi.b #4,routine(a0) ; is Tails falling back from getting hurt?
beq.s + ; if yes, branch
asl y_vel(a0)
+
tst.w y_vel(a0)
beq.w return_1BF58
move.w #$100,(Tails_Dust+anim).w ; splash animation
movea.l a0,a1
bsr.w ResumeMusic
cmpi.w #-$1000,y_vel(a0)
bgt.s +
move.w #-$1000,y_vel(a0) ; limit upward y velocity exiting the water
+
move.w #SndID_Splash,d0 ; splash sound
jmp (PlaySound).l
; End of subroutine Tails_Water
; ===========================================================================
; ---------------------------------------------------------------------------
; Start of subroutine Obj02_MdNormal
; Called if Tails is neither airborne nor rolling this frame
; ---------------------------------------------------------------------------
; loc_1C00A:
Obj02_MdNormal:
bsr.w Tails_CheckSpindash
bsr.w Tails_Jump
bsr.w Tails_SlopeResist
bsr.w Tails_Move
bsr.w Tails_Roll
bsr.w Tails_LevelBound
jsr (ObjectMove).l
bsr.w AnglePos
bsr.w Tails_SlopeRepel
rts
; End of subroutine Obj02_MdNormal
; ===========================================================================
; Start of subroutine Obj02_MdAir
; Called if Tails is airborne, but not in a ball (thus, probably not jumping)
; loc_1C032: Obj02_MdJump
Obj02_MdAir:
bsr.w Tails_JumpHeight
bsr.w Tails_ChgJumpDir
bsr.w Tails_LevelBound
jsr (ObjectMoveAndFall).l
btst #6,status(a0) ; is Tails underwater?
beq.s + ; if not, branch
subi.w #$28,y_vel(a0) ; reduce gravity by $28 ($38-$28=$10)
+
bsr.w Tails_JumpAngle
bsr.w Tails_DoLevelCollision
rts
; End of subroutine Obj02_MdAir
; ===========================================================================
; Start of subroutine Obj02_MdRoll
; Called if Tails is in a ball, but not airborne (thus, probably rolling)
; loc_1C05C:
Obj02_MdRoll:
tst.b pinball_mode(a0)
bne.s +
bsr.w Tails_Jump
+
bsr.w Tails_RollRepel
bsr.w Tails_RollSpeed
bsr.w Tails_LevelBound
jsr (ObjectMove).l
bsr.w AnglePos
bsr.w Tails_SlopeRepel
rts
; End of subroutine Obj02_MdRoll
; ===========================================================================
; Start of subroutine Obj02_MdJump
; Called if Tails is in a ball and airborne (he could be jumping but not necessarily)
; Notes: This is identical to Obj02_MdAir, at least at this outer level.
; Why they gave it a separate copy of the code, I don't know.
; loc_1C082: Obj02_MdJump2:
Obj02_MdJump:
bsr.w Tails_JumpHeight
bsr.w Tails_ChgJumpDir
bsr.w Tails_LevelBound
jsr (ObjectMoveAndFall).l
btst #6,status(a0) ; is Tails underwater?
beq.s + ; if not, branch
subi.w #$28,y_vel(a0) ; reduce gravity by $28 ($38-$28=$10)
+
bsr.w Tails_JumpAngle
bsr.w Tails_DoLevelCollision
rts
; End of subroutine Obj02_MdJump
; ---------------------------------------------------------------------------
; Subroutine to make Tails walk/run
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C0AC:
Tails_Move:
move.w (Tails_top_speed).w,d6
move.w (Tails_acceleration).w,d5
move.w (Tails_deceleration).w,d4
if status_sec_isSliding = 7
tst.b status_secondary(a0)
bmi.w Obj02_Traction
else
btst #status_sec_isSliding,status_secondary(a0)
bne.w Obj02_Traction
endif
tst.w move_lock(a0)
bne.w Obj02_ResetScr
btst #button_left,(Ctrl_2_Held_Logical).w ; is left being pressed?
beq.s Obj02_NotLeft ; if not, branch
bsr.w Tails_MoveLeft
; loc_1C0D4:
Obj02_NotLeft:
btst #button_right,(Ctrl_2_Held_Logical).w ; is right being pressed?
beq.s Obj02_NotRight ; if not, branch
bsr.w Tails_MoveRight
; loc_1C0E0:
Obj02_NotRight:
move.b angle(a0),d0
addi.b #$20,d0
andi.b #$C0,d0 ; is Tails on a slope?
bne.w Obj02_ResetScr ; if yes, branch
tst.w inertia(a0) ; is Tails moving?
bne.w Obj02_ResetScr ; if yes, branch
bclr #5,status(a0)
move.b #AniIDTailsAni_Wait,anim(a0) ; use "standing" animation
btst #3,status(a0)
beq.s Tails_Balance
moveq #0,d0
move.b interact(a0),d0
if object_size=$40
lsl.w #6,d0
else
mulu.w #object_size,d0
endif
lea (Object_RAM).w,a1 ; a1=character
lea (a1,d0.w),a1 ; a1=object
tst.b status(a1)
bmi.s Tails_Lookup
moveq #0,d1
move.b width_pixels(a1),d1
move.w d1,d2
add.w d2,d2
subq.w #4,d2
add.w x_pos(a0),d1
sub.w x_pos(a1),d1
cmpi.w #4,d1
blt.s Tails_BalanceOnObjLeft
cmp.w d2,d1
bge.s Tails_BalanceOnObjRight
bra.s Tails_Lookup
; ---------------------------------------------------------------------------
; balancing checks for Tails
; loc_1C142:
Tails_Balance:
jsr (ChkFloorEdge).l
cmpi.w #$C,d1
blt.s Tails_Lookup
cmpi.b #3,next_tilt(a0)
bne.s Tails_BalanceLeft
; loc_1C156:
Tails_BalanceOnObjRight:
bclr #0,status(a0)
bra.s Tails_BalanceDone
; ---------------------------------------------------------------------------
; loc_1C15E:
Tails_BalanceLeft:
cmpi.b #3,tilt(a0)
bne.s Tails_Lookup
; loc_1C166:
Tails_BalanceOnObjLeft:
bset #0,status(a0)
; loc_1C16C:
Tails_BalanceDone:
move.b #AniIDTailsAni_Balance,anim(a0)
bra.s Obj02_ResetScr
; ---------------------------------------------------------------------------
; loc_1C174:
Tails_Lookup:
btst #button_up,(Ctrl_2_Held_Logical).w ; is up being pressed?
beq.s Tails_Duck ; if not, branch
move.b #AniIDTailsAni_LookUp,anim(a0) ; use "looking up" animation
addq.w #1,(Tails_Look_delay_counter).w
cmpi.w #$78,(Tails_Look_delay_counter).w
blo.s Obj02_ResetScr_Part2
move.w #$78,(Tails_Look_delay_counter).w
cmpi.w #$C8,(Camera_Y_pos_bias_P2).w
beq.s Obj02_UpdateSpeedOnGround
addq.w #2,(Camera_Y_pos_bias_P2).w
bra.s Obj02_UpdateSpeedOnGround
; ---------------------------------------------------------------------------
; loc_1C1A2:
Tails_Duck:
btst #button_down,(Ctrl_2_Held_Logical).w ; is down being pressed?
beq.s Obj02_ResetScr ; if not, branch
move.b #AniIDTailsAni_Duck,anim(a0) ; use "ducking" animation
addq.w #1,(Tails_Look_delay_counter).w
cmpi.w #$78,(Tails_Look_delay_counter).w
blo.s Obj02_ResetScr_Part2
move.w #$78,(Tails_Look_delay_counter).w
cmpi.w #8,(Camera_Y_pos_bias_P2).w
beq.s Obj02_UpdateSpeedOnGround
subq.w #2,(Camera_Y_pos_bias_P2).w
bra.s Obj02_UpdateSpeedOnGround
; ===========================================================================
; moves the screen back to its normal position after looking up or down
; loc_1C1D0:
Obj02_ResetScr:
move.w #0,(Tails_Look_delay_counter).w
; loc_1C1D6:
Obj02_ResetScr_Part2:
cmpi.w #(224/2)-16,(Camera_Y_pos_bias_P2).w ; is screen in its default position?
beq.s Obj02_UpdateSpeedOnGround ; if yes, branch.
bhs.s + ; depending on the sign of the difference,
addq.w #4,(Camera_Y_pos_bias_P2).w ; either add 2
+ subq.w #2,(Camera_Y_pos_bias_P2).w ; or subtract 2
; ---------------------------------------------------------------------------
; updates Tails' speed on the ground
; ---------------------------------------------------------------------------
; loc_1C1E8:
Obj02_UpdateSpeedOnGround:
move.b (Ctrl_2_Held_Logical).w,d0
andi.b #button_left_mask|button_right_mask,d0 ; is left/right pressed?
bne.s Obj02_Traction ; if yes, branch
move.w inertia(a0),d0
beq.s Obj02_Traction
bmi.s Obj02_SettleLeft
; slow down when facing right and not pressing a direction
; Obj02_SettleRight:
sub.w d5,d0
bcc.s +
move.w #0,d0
+
move.w d0,inertia(a0)
bra.s Obj02_Traction
; ---------------------------------------------------------------------------
; slow down when facing left and not pressing a direction
; loc_1C208:
Obj02_SettleLeft:
add.w d5,d0
bcc.s +
move.w #0,d0
+
move.w d0,inertia(a0)
; increase or decrease speed on the ground
; loc_1C214:
Obj02_Traction:
move.b angle(a0),d0
jsr (CalcSine).l
muls.w inertia(a0),d1
asr.l #8,d1
move.w d1,x_vel(a0)
muls.w inertia(a0),d0
asr.l #8,d0
move.w d0,y_vel(a0)
; stops Tails from running through walls that meet the ground
; loc_1C232:
Obj02_CheckWallsOnGround:
move.b angle(a0),d0
addi.b #$40,d0
bmi.s return_1C2A2
move.b #$40,d1
tst.w inertia(a0)
beq.s return_1C2A2
bmi.s +
neg.w d1
+
move.b angle(a0),d0
add.b d1,d0
move.w d0,-(sp)
bsr.w CalcRoomInFront
move.w (sp)+,d0
tst.w d1
bpl.s return_1C2A2
asl.w #8,d1
addi.b #$20,d0
andi.b #$C0,d0
beq.s loc_1C29E
cmpi.b #$40,d0
beq.s loc_1C28C
cmpi.b #$80,d0
beq.s loc_1C286
add.w d1,x_vel(a0)
bset #5,status(a0)
move.w #0,inertia(a0)
rts
; ---------------------------------------------------------------------------
loc_1C286:
sub.w d1,y_vel(a0)
rts
; ---------------------------------------------------------------------------
loc_1C28C:
sub.w d1,x_vel(a0)
bset #5,status(a0)
move.w #0,inertia(a0)
rts
; ---------------------------------------------------------------------------
loc_1C29E:
add.w d1,y_vel(a0)
return_1C2A2:
rts
; End of subroutine Tails_Move
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C2A4:
Tails_MoveLeft:
move.w inertia(a0),d0
beq.s +
bpl.s Tails_TurnLeft ; if Tails is already moving to the right, branch
+
bset #0,status(a0)
bne.s +
bclr #5,status(a0)
move.b #AniIDTailsAni_Run,next_anim(a0)
+
sub.w d5,d0 ; add acceleration to the left
move.w d6,d1
neg.w d1
cmp.w d1,d0 ; compare new speed with top speed
bgt.s + ; if new speed is less than the maximum, branch
add.w d5,d0 ; remove this frame's acceleration change
cmp.w d1,d0 ; compare speed with top speed
ble.s + ; if speed was already greater than the maximum, branch
move.w d1,d0 ; limit speed on ground going left
+
move.w d0,inertia(a0)
move.b #AniIDTailsAni_Walk,anim(a0) ; use walking animation
rts
; ---------------------------------------------------------------------------
; loc_1C2DE:
Tails_TurnLeft:
sub.w d4,d0
bcc.s +
move.w #-$80,d0
+
move.w d0,inertia(a0)
move.b angle(a0),d0
addi.b #$20,d0
andi.b #$C0,d0
bne.s return_1C328
cmpi.w #$400,d0
blt.s return_1C328
move.b #AniIDTailsAni_Stop,anim(a0) ; use "stopping" animation
bclr #0,status(a0)
move.w #SndID_Skidding,d0
jsr (PlaySound).l
cmpi.b #$C,air_left(a0)
blo.s return_1C328 ; if he's drowning, branch to not make dust
move.b #6,(Tails_Dust+routine).w
move.b #$15,(Tails_Dust+mapping_frame).w
return_1C328:
rts
; End of subroutine Tails_MoveLeft
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C32A:
Tails_MoveRight:
move.w inertia(a0),d0
bmi.s Tails_TurnRight
bclr #0,status(a0)
beq.s +
bclr #5,status(a0)
move.b #AniIDTailsAni_Run,next_anim(a0)
+
add.w d5,d0 ; add acceleration to the right
cmp.w d6,d0 ; compare new speed with top speed
blt.s + ; if new speed is less than the maximum, branch
sub.w d5,d0 ; remove this frame's acceleration change
cmp.w d6,d0 ; compare speed with top speed
bge.s + ; if speed was already greater than the maximum, branch
move.w d6,d0 ; limit speed on ground going right
+
move.w d0,inertia(a0)
move.b #AniIDTailsAni_Walk,anim(a0) ; use walking animation
rts
; ---------------------------------------------------------------------------
; loc_1C35E:
Tails_TurnRight:
add.w d4,d0
bcc.s +
move.w #$80,d0
+
move.w d0,inertia(a0)
move.b angle(a0),d0
addi.b #$20,d0
andi.b #$C0,d0
bne.s return_1C3A8
cmpi.w #-$400,d0
bgt.s return_1C3A8
move.b #AniIDTailsAni_Stop,anim(a0) ; use "stopping" animation
bset #0,status(a0)
move.w #SndID_Skidding,d0 ; use "stopping" sound
jsr (PlaySound).l
cmpi.b #$C,air_left(a0)
blo.s return_1C3A8 ; if he's drowning, branch to not make dust
move.b #6,(Tails_Dust+routine).w
move.b #$15,(Tails_Dust+mapping_frame).w
return_1C3A8:
rts
; End of subroutine Tails_MoveRight
; ---------------------------------------------------------------------------
; Subroutine to change Tails' speed as he rolls
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C3AA:
Tails_RollSpeed:
move.w (Tails_top_speed).w,d6
asl.w #1,d6
move.w (Tails_acceleration).w,d5
asr.w #1,d5 ; natural roll deceleration = 1/2 normal acceleration
move.w (Tails_deceleration).w,d4
asr.w #2,d4 ; controlled roll deceleration...
; interestingly, Tails is much worse at this than Sonic when underwater
if status_sec_isSliding = 7
tst.b status_secondary(a0)
bmi.w Obj02_Roll_ResetScr
else
btst #status_sec_isSliding,status_secondary(a0)
bne.w Obj02_Roll_ResetScr
endif
tst.w move_lock(a0)
bne.s Tails_ApplyRollSpeed
btst #button_left,(Ctrl_2_Held_Logical).w ; is left being pressed?
beq.s + ; if not, branch
bsr.w Tails_RollLeft
+
btst #button_right,(Ctrl_2_Held_Logical).w ; is right being pressed?
beq.s Tails_ApplyRollSpeed ; if not, branch
bsr.w Tails_RollRight
; loc_1C3E2:
Tails_ApplyRollSpeed:
move.w inertia(a0),d0
beq.s Tails_CheckRollStop
bmi.s Tails_ApplyRollSpeedLeft
; Tails_ApplyRollSpeedRight:
sub.w d5,d0
bcc.s +
move.w #0,d0
+
move.w d0,inertia(a0)
bra.s Tails_CheckRollStop
; ---------------------------------------------------------------------------
; loc_1C3F8:
Tails_ApplyRollSpeedLeft:
add.w d5,d0
bcc.s +
move.w #0,d0
+
move.w d0,inertia(a0)
; loc_1C404
Tails_CheckRollStop:
tst.w inertia(a0)
bne.s Obj02_Roll_ResetScr
tst.b pinball_mode(a0) ; note: the spindash flag has a different meaning when Tails is already rolling -- it's used to mean he's not allowed to stop rolling
bne.s Tails_KeepRolling
bclr #2,status(a0)
move.b #$F,y_radius(a0) ; sets standing height to only slightly higher than rolling height, unlike Sonic
move.b #9,x_radius(a0)
move.b #AniIDTailsAni_Wait,anim(a0)
subq.w #1,y_pos(a0)
bra.s Obj02_Roll_ResetScr
; ---------------------------------------------------------------------------
; magically gives Tails an extra push if he's going to stop rolling where it's not allowed
; (such as in an S-curve in HTZ or a stopper chamber in CNZ)
; loc_1C42E:
Tails_KeepRolling:
move.w #$400,inertia(a0)
btst #0,status(a0)
beq.s Obj02_Roll_ResetScr
neg.w inertia(a0)
; resets the screen to normal while rolling, like Obj02_ResetScr
; loc_1C440:
Obj02_Roll_ResetScr:
cmpi.w #(224/2)-16,(Camera_Y_pos_bias_P2).w ; is screen in its default position?
beq.s Tails_SetRollSpeed ; if yes, branch
bhs.s + ; depending on the sign of the difference,
addq.w #4,(Camera_Y_pos_bias_P2).w ; either add 2
+ subq.w #2,(Camera_Y_pos_bias_P2).w ; or subtract 2
; loc_1C452:
Tails_SetRollSpeed:
move.b angle(a0),d0
jsr (CalcSine).l
muls.w inertia(a0),d0
asr.l #8,d0
move.w d0,y_vel(a0) ; set y velocity based on $14 and angle
muls.w inertia(a0),d1
asr.l #8,d1
cmpi.w #$1000,d1
ble.s +
move.w #$1000,d1 ; limit Tails' speed rolling right
+
cmpi.w #-$1000,d1
bge.s +
move.w #-$1000,d1 ; limit Tails' speed rolling left
+
move.w d1,x_vel(a0) ; set x velocity based on $14 and angle
bra.w Obj02_CheckWallsOnGround
; End of function Tails_RollSpeed
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C488:
Tails_RollLeft:
move.w inertia(a0),d0
beq.s +
bpl.s Tails_BrakeRollingRight
+
bset #0,status(a0)
move.b #AniIDTailsAni_Roll,anim(a0) ; use "rolling" animation
rts
; ---------------------------------------------------------------------------
; loc_1C49E:
Tails_BrakeRollingRight:
sub.w d4,d0 ; reduce rightward rolling speed
bcc.s +
move.w #-$80,d0
+
move.w d0,inertia(a0)
rts
; End of function Tails_RollLeft
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C4AC:
Tails_RollRight:
move.w inertia(a0),d0
bmi.s Tails_BrakeRollingLeft
bclr #0,status(a0)
move.b #AniIDTailsAni_Roll,anim(a0) ; use "rolling" animation
rts
; ---------------------------------------------------------------------------
; loc_1C4C0:
Tails_BrakeRollingLeft:
add.w d4,d0 ; reduce leftward rolling speed
bcc.s +
move.w #$80,d0
+
move.w d0,inertia(a0)
rts
; End of subroutine Tails_RollRight
; ---------------------------------------------------------------------------
; Subroutine for moving Tails left or right when he's in the air
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C4CE:
Tails_ChgJumpDir:
move.w (Tails_top_speed).w,d6
move.w (Tails_acceleration).w,d5
asl.w #1,d5
btst #4,status(a0) ; did Tails jump from rolling?
bne.s Obj02_Jump_ResetScr ; if yes, branch to skip midair control
move.w x_vel(a0),d0
btst #button_left,(Ctrl_2_Held_Logical).w
beq.s + ; if not holding left, branch
bset #0,status(a0)
sub.w d5,d0 ; add acceleration to the left
move.w d6,d1
neg.w d1
cmp.w d1,d0 ; compare new speed with top speed
bgt.s + ; if new speed is less than the maximum, branch
move.w d1,d0 ; limit speed in air going left, even if Tails was already going faster (speed limit/cap)
+
btst #button_right,(Ctrl_2_Held_Logical).w
beq.s + ; if not holding right, branch
bclr #0,status(a0)
add.w d5,d0 ; accelerate right in the air
cmp.w d6,d0 ; compare new speed with top speed
blt.s + ; if new speed is less than the maximum, branch
move.w d6,d0 ; limit speed in air going right, even if Tails was already going faster (speed limit/cap)
; Obj02_JumpMove:
+ move.w d0,x_vel(a0)
; loc_1C518: Obj02_ResetScr2:
Obj02_Jump_ResetScr:
cmpi.w #(224/2)-16,(Camera_Y_pos_bias_P2).w ; is screen in its default position?
beq.s Tails_JumpPeakDecelerate ; if yes, branch
bhs.s + ; depending on the sign of the difference,
addq.w #4,(Camera_Y_pos_bias_P2).w ; either add 2
+ subq.w #2,(Camera_Y_pos_bias_P2).w ; or subtract 2
; loc_1C52A:
Tails_JumpPeakDecelerate:
cmpi.w #-$400,y_vel(a0) ; is Tails moving faster than -$400 upwards?
blo.s return_1C558 ; if yes, return
move.w x_vel(a0),d0
move.w d0,d1
asr.w #5,d1 ; d1 = x_velocity / 32
beq.s return_1C558 ; return if d1 is 0
bmi.s Tails_JumpPeakDecelerateLeft
; Tails_JumpPeakDecelerateRight:
sub.w d1,d0 ; reduce x velocity by d1
bcc.s +
move.w #0,d0
+
move.w d0,x_vel(a0)
rts
; ---------------------------------------------------------------------------
; loc_1C54C:
Tails_JumpPeakDecelerateLeft:
sub.w d1,d0 ; reduce x velocity by d1
bcs.s +
move.w #0,d0
+
move.w d0,x_vel(a0)
return_1C558:
rts
; End of subroutine Tails_ChgJumpDir
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to prevent Tails from leaving the boundaries of a level
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C55A:
Tails_LevelBound:
move.l x_pos(a0),d1
move.w x_vel(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d1
swap d1
move.w (Tails_Min_X_pos).w,d0
addi.w #$10,d0
cmp.w d1,d0 ; has Tails touched the left boundary?
bhi.s Tails_Boundary_Sides ; if yes, branch
move.w (Tails_Max_X_pos).w,d0
addi.w #$128,d0
tst.b (Current_Boss_ID).w
bne.s +
addi.w #$40,d0
+
cmp.w d1,d0 ; has Tails touched the right boundary?
bls.s Tails_Boundary_Sides ; if yes, branch
; loc_1C58C:
Tails_Boundary_CheckBottom:
move.w (Tails_Max_Y_pos).w,d0
addi.w #$E0,d0
cmp.w y_pos(a0),d0 ; has Tails touched the bottom boundary?
blt.s Tails_Boundary_Bottom ; if yes, branch
rts
; ---------------------------------------------------------------------------
Tails_Boundary_Bottom: ;;
jmpto (KillCharacter).l, JmpTo2_KillCharacter
; ===========================================================================
; loc_1C5A0:
Tails_Boundary_Sides:
move.w d0,x_pos(a0)
move.w #0,2+x_pos(a0) ; subpixel x
move.w #0,x_vel(a0)
move.w #0,inertia(a0)
bra.s Tails_Boundary_CheckBottom
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine allowing Tails to start rolling when he's moving
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C5B8:
Tails_Roll:
if status_sec_isSliding = 7
tst.b status_secondary(a0)
bmi.s Obj02_NoRoll
else
btst #status_sec_isSliding,status_secondary(a0)
bne.w Obj02_NoRoll
endif
mvabs.w inertia(a0),d0
cmpi.w #$80,d0 ; is Tails moving at $80 speed or faster?
blo.s Obj02_NoRoll ; if not, branch
move.b (Ctrl_2_Held_Logical).w,d0
andi.b #button_left_mask|button_right_mask,d0 ; is left/right being pressed?
bne.s Obj02_NoRoll ; if yes, branch
btst #button_down,(Ctrl_2_Held_Logical).w ; is down being pressed?
bne.s Obj02_ChkRoll ; if yes, branch
; return_1C5DE:
Obj02_NoRoll:
rts
; ---------------------------------------------------------------------------
; loc_1C5E0:
Obj02_ChkRoll:
btst #2,status(a0) ; is Tails already rolling?
beq.s Obj02_DoRoll ; if not, branch
rts
; ---------------------------------------------------------------------------
; loc_1C5EA:
Obj02_DoRoll:
bset #2,status(a0)
move.b #$E,y_radius(a0)
move.b #7,x_radius(a0)
move.b #AniIDTailsAni_Roll,anim(a0) ; use "rolling" animation
addq.w #1,y_pos(a0)
move.w #SndID_Roll,d0
jsr (PlaySound).l ; play rolling sound
tst.w inertia(a0)
bne.s return_1C61C
move.w #$200,inertia(a0)
return_1C61C:
rts
; End of function Tails_Roll
; ---------------------------------------------------------------------------
; Subroutine allowing Tails to jump
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C61E:
Tails_Jump:
move.b (Ctrl_2_Press_Logical).w,d0
andi.b #button_B_mask|button_C_mask|button_A_mask,d0 ; is A, B or C pressed?
beq.w return_1C6C2 ; if not, return
moveq #0,d0
move.b angle(a0),d0
addi.b #$80,d0
bsr.w CalcRoomOverHead
cmpi.w #6,d1 ; does Tails have enough room to jump?
blt.w return_1C6C2 ; if not, branch
move.w #$680,d2
btst #6,status(a0) ; Test if underwater
beq.s +
move.w #$380,d2 ; set lower jump speed if underwater
+
moveq #0,d0
move.b angle(a0),d0
subi.b #$40,d0
jsr (CalcSine).l
muls.w d2,d1
asr.l #8,d1
add.w d1,x_vel(a0) ; make Tails jump (in X... this adds nothing on level ground)
muls.w d2,d0
asr.l #8,d0
add.w d0,y_vel(a0) ; make Tails jump (in Y)
bset #1,status(a0)
bclr #5,status(a0)
addq.l #4,sp
move.b #1,jumping(a0)
clr.b stick_to_convex(a0)
move.w #SndID_Jump,d0
jsr (PlaySound).l ; play jumping sound
move.b #$F,y_radius(a0)
move.b #9,x_radius(a0)
btst #2,status(a0)
bne.s Tails_RollJump
move.b #$E,y_radius(a0)
move.b #7,x_radius(a0)
move.b #AniIDTailsAni_Roll,anim(a0) ; use "jumping" animation
bset #2,status(a0)
addq.w #1,y_pos(a0)
return_1C6C2:
rts
; ---------------------------------------------------------------------------
; loc_1C6C4:
Tails_RollJump:
bset #4,status(a0) ; set the rolling+jumping flag
rts
; End of function Tails_Jump
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; ===========================================================================
; loc_1C6CC:
Tails_JumpHeight:
tst.b jumping(a0) ; is Tails jumping?
beq.s Tails_UpVelCap ; if not, branch
move.w #-$400,d1
btst #6,status(a0) ; is Tails underwater?
beq.s + ; if not, branch
move.w #-$200,d1
+
cmp.w y_vel(a0),d1 ; is Tails going up faster than d1?
ble.s + ; if not, branch
move.b (Ctrl_2_Held_Logical).w,d0
andi.b #button_B_mask|button_C_mask|button_A_mask,d0 ; is a jump button pressed?
bne.s + ; if yes, branch
move.w d1,y_vel(a0) ; immediately reduce Tails's upward speed to d1
+
rts
; ---------------------------------------------------------------------------
; loc_1C6F8:
Tails_UpVelCap:
tst.b pinball_mode(a0) ; is Tails charging a spindash or in a rolling-only area?
bne.s return_1C70C ; if yes, return
cmpi.w #-$FC0,y_vel(a0) ; is Tails moving up really fast?
bge.s return_1C70C ; if not, return
move.w #-$FC0,y_vel(a0) ; cap upward speed
return_1C70C:
rts
; End of subroutine Tails_JumpHeight
; ---------------------------------------------------------------------------
; Subroutine to check for starting to charge a spindash
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C70E:
Tails_CheckSpindash:
tst.b spindash_flag(a0)
bne.s Tails_UpdateSpindash
cmpi.b #AniIDTailsAni_Duck,anim(a0)
bne.s return_1C75C
move.b (Ctrl_2_Press_Logical).w,d0
andi.b #button_B_mask|button_C_mask|button_A_mask,d0
beq.w return_1C75C
move.b #AniIDTailsAni_Spindash,anim(a0)
move.w #SndID_SpindashRev,d0
jsr (PlaySound).l
addq.l #4,sp
move.b #1,spindash_flag(a0)
move.w #0,spindash_counter(a0)
cmpi.b #$C,air_left(a0) ; if he's drowning, branch to not make dust
blo.s loc_1C754
move.b #2,(Tails_Dust+anim).w
loc_1C754:
bsr.w Tails_LevelBound
bsr.w AnglePos
return_1C75C:
rts
; End of subroutine Tails_CheckSpindash
; ---------------------------------------------------------------------------
; Subrouting to update an already-charging spindash
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C75E:
Tails_UpdateSpindash:
move.b (Ctrl_2_Held_Logical).w,d0
btst #button_down,d0
bne.s Tails_ChargingSpindash
; unleash the charged spindash and start rolling quickly:
move.b #$E,y_radius(a0)
move.b #7,x_radius(a0)
move.b #AniIDTailsAni_Roll,anim(a0)
addq.w #1,y_pos(a0) ; add the difference between Tails' rolling and standing heights
move.b #0,spindash_flag(a0)
moveq #0,d0
move.b spindash_counter(a0),d0
add.w d0,d0
move.w Tails_SpindashSpeeds(pc,d0.w),inertia(a0)
move.w inertia(a0),d0
subi.w #$800,d0
add.w d0,d0
andi.w #$1F00,d0
neg.w d0
addi.w #$2000,d0
move.w d0,(Horiz_scroll_delay_val_P2).w
btst #0,status(a0)
beq.s +
neg.w inertia(a0)
+
bset #2,status(a0)
move.b #0,(Tails_Dust+anim).w
move.w #SndID_SpindashRelease,d0 ; spindash zoom sound
jsr (PlaySound).l
bra.s loc_1C828
; ===========================================================================
; word_1C7CE:
Tails_SpindashSpeeds:
dc.w $800 ; 0
dc.w $880 ; 1
dc.w $900 ; 2
dc.w $980 ; 3
dc.w $A00 ; 4
dc.w $A80 ; 5
dc.w $B00 ; 6
dc.w $B80 ; 7
dc.w $C00 ; 8
; ===========================================================================
; loc_1C7E0:
Tails_ChargingSpindash: ; If still charging the dash...
tst.w spindash_counter(a0)
beq.s loc_1C7F8
move.w spindash_counter(a0),d0
lsr.w #5,d0
sub.w d0,spindash_counter(a0)
bcc.s loc_1C7F8
move.w #0,spindash_counter(a0)
loc_1C7F8:
move.b (Ctrl_2_Press_Logical).w,d0
andi.b #button_B_mask|button_C_mask|button_A_mask,d0
beq.w loc_1C828
move.w #(AniIDTailsAni_Spindash<<8),anim(a0)
move.w #SndID_SpindashRev,d0
jsr (PlaySound).l
addi.w #$200,spindash_counter(a0)
cmpi.w #$800,spindash_counter(a0)
blo.s loc_1C828
move.w #$800,spindash_counter(a0)
loc_1C828:
addq.l #4,sp
cmpi.w #(224/2)-16,(Camera_Y_pos_bias_P2).w
beq.s loc_1C83C
bhs.s +
addq.w #4,(Camera_Y_pos_bias_P2).w
+ subq.w #2,(Camera_Y_pos_bias_P2).w
loc_1C83C:
bsr.w Tails_LevelBound
bsr.w AnglePos
rts
; End of subroutine Tails_UpdateSpindash
; ---------------------------------------------------------------------------
; Subroutine to slow Tails walking up a slope
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C846:
Tails_SlopeResist:
move.b angle(a0),d0
addi.b #$60,d0
cmpi.b #$C0,d0
bhs.s return_1C87A
move.b angle(a0),d0
jsr (CalcSine).l
muls.w #$20,d0
asr.l #8,d0
tst.w inertia(a0)
beq.s return_1C87A
bmi.s loc_1C876
tst.w d0
beq.s +
add.w d0,inertia(a0) ; change Tails' $14
+
rts
; ---------------------------------------------------------------------------
loc_1C876:
add.w d0,inertia(a0)
return_1C87A:
rts
; End of subroutine Tails_SlopeResist
; ---------------------------------------------------------------------------
; Subroutine to push Tails down a slope while he's rolling
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C87C:
Tails_RollRepel:
move.b angle(a0),d0
addi.b #$60,d0
cmpi.b #-$40,d0
bhs.s return_1C8B6
move.b angle(a0),d0
jsr (CalcSine).l
muls.w #$50,d0
asr.l #8,d0
tst.w inertia(a0)
bmi.s loc_1C8AC
tst.w d0
bpl.s loc_1C8A6
asr.l #2,d0
loc_1C8A6:
add.w d0,inertia(a0)
rts
; ===========================================================================
loc_1C8AC:
tst.w d0
bmi.s loc_1C8B2
asr.l #2,d0
loc_1C8B2:
add.w d0,inertia(a0)
return_1C8B6:
rts
; End of function Tails_RollRepel
; ---------------------------------------------------------------------------
; Subroutine to push Tails down a slope
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C8B8:
Tails_SlopeRepel:
nop
tst.b stick_to_convex(a0)
bne.s return_1C8F2
tst.w move_lock(a0)
bne.s loc_1C8F4
move.b angle(a0),d0
addi.b #$20,d0
andi.b #$C0,d0
beq.s return_1C8F2
mvabs.w inertia(a0),d0
cmpi.w #$280,d0
bhs.s return_1C8F2
clr.w inertia(a0)
bset #1,status(a0)
move.w #$1E,move_lock(a0)
return_1C8F2:
rts
; ===========================================================================
loc_1C8F4:
subq.w #1,move_lock(a0)
rts
; End of function Tails_SlopeRepel
; ---------------------------------------------------------------------------
; Subroutine to return Tails' angle to 0 as he jumps
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C8FA:
Tails_JumpAngle:
move.b angle(a0),d0 ; get Tails' angle
beq.s Tails_JumpFlip ; if already 0, branch
bpl.s loc_1C90A ; if higher than 0, branch
addq.b #2,d0 ; increase angle
bcc.s BranchTo_Tails_JumpAngleSet
moveq #0,d0
BranchTo_Tails_JumpAngleSet
bra.s Tails_JumpAngleSet
; ===========================================================================
loc_1C90A:
subq.b #2,d0 ; decrease angle
bcc.s Tails_JumpAngleSet
moveq #0,d0
; loc_1C910:
Tails_JumpAngleSet:
move.b d0,angle(a0)
; End of function Tails_JumpAngle
; continue straight to Tails_JumpFlip
; ---------------------------------------------------------------------------
; Updates Tails' secondary angle if he's tumbling
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C914:
Tails_JumpFlip:
move.b flip_angle(a0),d0
beq.s return_1C958
tst.w inertia(a0)
bmi.s Tails_JumpLeftFlip
; loc_1C920:
Tails_JumpRightFlip:
move.b flip_speed(a0),d1
add.b d1,d0
bcc.s BranchTo_Tails_JumpFlipSet
subq.b #1,flips_remaining(a0)
bcc.s BranchTo_Tails_JumpFlipSet
move.b #0,flips_remaining(a0)
moveq #0,d0
BranchTo_Tails_JumpFlipSet
bra.s Tails_JumpFlipSet
; ===========================================================================
; loc_1C938:
Tails_JumpLeftFlip:
tst.b flip_turned(a0)
bne.s Tails_JumpRightFlip
move.b flip_speed(a0),d1
sub.b d1,d0
bcc.s Tails_JumpFlipSet
subq.b #1,flips_remaining(a0)
bcc.s Tails_JumpFlipSet
move.b #0,flips_remaining(a0)
moveq #0,d0
; loc_1C954:
Tails_JumpFlipSet:
move.b d0,flip_angle(a0)
return_1C958:
rts
; End of function Tails_JumpFlip
; ---------------------------------------------------------------------------
; Subroutine for Tails to interact with the floor and walls when he's in the air
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1C95A: Tails_Floor:
Tails_DoLevelCollision:
move.l #Primary_Collision,(Collision_addr).w
cmpi.b #$C,top_solid_bit(a0)
beq.s +
move.l #Secondary_Collision,(Collision_addr).w
+
move.b lrb_solid_bit(a0),d5
move.w x_vel(a0),d1
move.w y_vel(a0),d2
jsr (CalcAngle).l
subi.b #$20,d0
andi.b #$C0,d0
cmpi.b #$40,d0
beq.w Tails_HitLeftWall
cmpi.b #$80,d0
beq.w Tails_HitCeilingAndWalls
cmpi.b #$C0,d0
beq.w Tails_HitRightWall
bsr.w CheckLeftWallDist
tst.w d1
bpl.s +
sub.w d1,x_pos(a0)
move.w #0,x_vel(a0) ; stop Tails since he hit a wall
+
bsr.w CheckRightWallDist
tst.w d1
bpl.s +
add.w d1,x_pos(a0)
move.w #0,x_vel(a0) ; stop Tails since he hit a wall
+
bsr.w Sonic_CheckFloor
tst.w d1
bpl.s return_1CA3A
move.b y_vel(a0),d2
addq.b #8,d2
neg.b d2
cmp.b d2,d1
bge.s +
cmp.b d2,d0
blt.s return_1CA3A
+
add.w d1,y_pos(a0)
move.b d3,angle(a0)
bsr.w Tails_ResetOnFloor
move.b d3,d0
addi.b #$20,d0
andi.b #$40,d0
bne.s loc_1CA18
move.b d3,d0
addi.b #$10,d0
andi.b #$20,d0
beq.s loc_1CA0A
asr y_vel(a0)
bra.s loc_1CA2C
; ===========================================================================
loc_1CA0A:
move.w #0,y_vel(a0)
move.w x_vel(a0),inertia(a0)
rts
; ===========================================================================
loc_1CA18:
move.w #0,x_vel(a0) ; stop Tails since he hit a wall
cmpi.w #$FC0,y_vel(a0)
ble.s loc_1CA2C
move.w #$FC0,y_vel(a0)
loc_1CA2C:
move.w y_vel(a0),inertia(a0)
tst.b d3
bpl.s return_1CA3A
neg.w inertia(a0)
return_1CA3A:
rts
; ===========================================================================
; loc_1CA3C:
Tails_HitLeftWall:
bsr.w CheckLeftWallDist
tst.w d1
bpl.s Tails_HitCeiling ; branch if distance is positive (not inside wall)
sub.w d1,x_pos(a0)
move.w #0,x_vel(a0) ; stop Tails since he hit a wall
move.w y_vel(a0),inertia(a0)
rts
; ===========================================================================
; loc_1CA56:
Tails_HitCeiling:
bsr.w Sonic_CheckCeiling
tst.w d1
bpl.s Tails_HitFloor ; branch if distance is positive (not inside ceiling)
sub.w d1,y_pos(a0)
tst.w y_vel(a0)
bpl.s return_1CA6E
move.w #0,y_vel(a0) ; stop Tails in y since he hit a ceiling
return_1CA6E:
rts
; ===========================================================================
; loc_1CA70:
Tails_HitFloor:
tst.w y_vel(a0)
bmi.s return_1CA96
bsr.w Sonic_CheckFloor
tst.w d1
bpl.s return_1CA96
add.w d1,y_pos(a0)
move.b d3,angle(a0)
bsr.w Tails_ResetOnFloor
move.w #0,y_vel(a0)
move.w x_vel(a0),inertia(a0)
return_1CA96:
rts
; ===========================================================================
; loc_1CA98:
Tails_HitCeilingAndWalls:
bsr.w CheckLeftWallDist
tst.w d1
bpl.s +
sub.w d1,x_pos(a0)
move.w #0,x_vel(a0) ; stop Tails since he hit a wall
+
bsr.w CheckRightWallDist
tst.w d1
bpl.s +
add.w d1,x_pos(a0)
move.w #0,x_vel(a0) ; stop Tails since he hit a wall
+
bsr.w Sonic_CheckCeiling
tst.w d1
bpl.s return_1CAF2
sub.w d1,y_pos(a0)
move.b d3,d0
addi.b #$20,d0
andi.b #$40,d0
bne.s loc_1CADC
move.w #0,y_vel(a0) ; stop Tails in y since he hit a ceiling
rts
; ===========================================================================
loc_1CADC:
move.b d3,angle(a0)
bsr.w Tails_ResetOnFloor
move.w y_vel(a0),inertia(a0)
tst.b d3
bpl.s return_1CAF2
neg.w inertia(a0)
return_1CAF2:
rts
; ===========================================================================
; loc_1CAF4:
Tails_HitRightWall:
bsr.w CheckRightWallDist
tst.w d1
bpl.s Tails_HitCeiling2
add.w d1,x_pos(a0)
move.w #0,x_vel(a0) ; stop Tails since he hit a wall
move.w y_vel(a0),inertia(a0)
rts
; ===========================================================================
; identical to Tails_HitCeiling...
; loc_1CB0E:
Tails_HitCeiling2:
bsr.w Sonic_CheckCeiling
tst.w d1
bpl.s Tails_HitFloor2
sub.w d1,y_pos(a0)
tst.w y_vel(a0)
bpl.s return_1CB26
move.w #0,y_vel(a0) ; stop Tails in y since he hit a ceiling
return_1CB26:
rts
; ===========================================================================
; identical to Tails_HitFloor...
; loc_1CB28:
Tails_HitFloor2:
tst.w y_vel(a0)
bmi.s return_1CB4E
bsr.w Sonic_CheckFloor
tst.w d1
bpl.s return_1CB4E
add.w d1,y_pos(a0)
move.b d3,angle(a0)
bsr.w Tails_ResetOnFloor
move.w #0,y_vel(a0)
move.w x_vel(a0),inertia(a0)
return_1CB4E:
rts
; End of function Tails_DoLevelCollision
; ---------------------------------------------------------------------------
; Subroutine to reset Tails' mode when he lands on the floor
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1CB50:
Tails_ResetOnFloor:
tst.b pinball_mode(a0)
bne.s Tails_ResetOnFloor_Part3
move.b #AniIDTailsAni_Walk,anim(a0)
; loc_1CB5C:
Tails_ResetOnFloor_Part2:
btst #2,status(a0)
beq.s Tails_ResetOnFloor_Part3
bclr #2,status(a0)
move.b #$F,y_radius(a0) ; this slightly increases Tails' collision height to standing
move.b #9,x_radius(a0)
move.b #AniIDTailsAni_Walk,anim(a0) ; use running/walking/standing animation
subq.w #1,y_pos(a0) ; move Tails up 1 pixel so the increased height doesn't push him slightly into the ground
; loc_1CB80:
Tails_ResetOnFloor_Part3:
bclr #1,status(a0)
bclr #5,status(a0)
bclr #4,status(a0)
move.b #0,jumping(a0)
move.w #0,(Chain_Bonus_counter).w
move.b #0,flip_angle(a0)
move.b #0,flip_turned(a0)
move.b #0,flips_remaining(a0)
move.w #0,(Tails_Look_delay_counter).w
cmpi.b #AniIDTailsAni_Hang2,anim(a0)
bne.s return_1CBC4
move.b #AniIDTailsAni_Walk,anim(a0)
return_1CBC4:
rts
; End of subroutine Tails_ResetOnFloor
; ===========================================================================
; ---------------------------------------------------------------------------
; Tails when he gets hurt
; ---------------------------------------------------------------------------
; loc_1CBC6:
Obj02_Hurt:
jsr (ObjectMove).l
addi.w #$30,y_vel(a0)
btst #6,status(a0)
beq.s +
subi.w #$20,y_vel(a0)
+
cmpi.w #-$100,(Camera_Min_Y_pos).w
bne.s +
andi.w #$7FF,y_pos(a0)
+
bsr.w Tails_HurtStop
bsr.w Tails_LevelBound
bsr.w Tails_RecordPos
bsr.w Tails_Animate
bsr.w LoadTailsDynPLC
jmp (DisplaySprite).l
; ===========================================================================
; loc_1CC08:
Tails_HurtStop:
move.w (Tails_Max_Y_pos).w,d0
addi.w #$E0,d0
cmp.w y_pos(a0),d0
blt.w JmpTo2_KillCharacter
bsr.w Tails_DoLevelCollision
btst #1,status(a0)
bne.s return_1CC4E
moveq #0,d0
move.w d0,y_vel(a0)
move.w d0,x_vel(a0)
move.w d0,inertia(a0)
move.b d0,obj_control(a0)
move.b #AniIDTailsAni_Walk,anim(a0)
move.b #2,routine(a0) ; => Obj02_Control
move.w #$78,invulnerable_time(a0)
move.b #0,spindash_flag(a0)
return_1CC4E:
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Tails when he dies
; .
; ---------------------------------------------------------------------------
; loc_1CC50:
Obj02_Dead:
bsr.w Obj02_CheckGameOver
jsr (ObjectMoveAndFall).l
bsr.w Tails_RecordPos
bsr.w Tails_Animate
bsr.w LoadTailsDynPLC
jmp (DisplaySprite).l
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1CC6C:
Obj02_CheckGameOver:
cmpi.w #2,(Player_mode).w ; is it a Tails Alone game?
beq.w CheckGameOver ; if yes, branch... goodness, code reuse
move.b #1,(Scroll_lock_P2).w
move.b #0,spindash_flag(a0)
move.w (Tails_Max_Y_pos).w,d0
addi.w #$100,d0
cmp.w y_pos(a0),d0
bge.w return_1CD8E
move.b #2,routine(a0)
tst.w (Two_player_mode).w
bne.s Obj02_CheckGameOver_2Pmode
bra.w TailsCPU_Despawn
; ---------------------------------------------------------------------------
; loc_1CCA2:
Obj02_CheckGameOver_2Pmode:
addq.b #1,(Update_HUD_lives_2P).w
subq.b #1,(Life_count_2P).w
bne.s Obj02_ResetLevel
move.w #0,restart_countdown(a0)
move.b #ObjID_GameOver,(GameOver_GameText+id).w ; load Obj39
move.b #ObjID_GameOver,(GameOver_OverText+id).w ; load Obj39
move.b #1,(GameOver_OverText+mapping_frame).w
move.w a0,(GameOver_GameText+parent).w
clr.b (Time_Over_flag_2P).w
; loc_1CCCC:
Obj02_Finished:
clr.b (Update_HUD_timer).w
clr.b (Update_HUD_timer_2P).w
move.b #8,routine(a0)
move.w #MusID_GameOver,d0
jsr (PlayMusic).l
moveq #PLCID_GameOver,d0
jmp (LoadPLC).l
; End of function Obj02_CheckGameOver
; ===========================================================================
; ---------------------------------------------------------------------------
; Tails when the level is restarted
; ---------------------------------------------------------------------------
; loc_1CCEC:
Obj02_ResetLevel:
tst.b (Time_Over_flag).w
if gameRevision=0
bne.s Obj02_ResetLevel_Part3
else
beq.s Obj02_ResetLevel_Part2
tst.b (Time_Over_flag_2P).w
beq.s Obj02_ResetLevel_Part3
move.w #0,restart_countdown(a0)
clr.b (Update_HUD_timer).w
clr.b (Update_HUD_timer_2P).w
move.b #8,routine(a0)
rts
endif
; ---------------------------------------------------------------------------
Obj02_ResetLevel_Part2:
tst.b (Time_Over_flag_2P).w
beq.s Obj02_ResetLevel_Part3
move.w #0,restart_countdown(a0)
move.b #ObjID_TimeOver,(TimeOver_TimeText+id).w ; load Obj39
move.b #ObjID_TimeOver,(TimeOver_OverText+id).w ; load Obj39
move.b #2,(TimeOver_TimeText+mapping_frame).w
move.b #3,(TimeOver_OverText+mapping_frame).w
move.w a0,(TimeOver_TimeText+parent).w
bra.s Obj02_Finished
; ---------------------------------------------------------------------------
Obj02_ResetLevel_Part3:
move.b #0,(Scroll_lock_P2).w
move.b #$A,routine(a0) ; => Obj02_Respawning
move.w (Saved_x_pos_2P).w,x_pos(a0)
move.w (Saved_y_pos_2P).w,y_pos(a0)
move.w (Saved_art_tile_2P).w,art_tile(a0)
move.w (Saved_Solid_bits_2P).w,top_solid_bit(a0)
clr.w (Ring_count_2P).w
clr.b (Extra_life_flags_2P).w
move.b #0,obj_control(a0)
move.b #5,anim(a0)
move.w #0,x_vel(a0)
move.w #0,y_vel(a0)
move.w #0,inertia(a0)
move.b #2,status(a0)
move.w #0,move_lock(a0)
return_1CD8E:
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Tails when he's offscreen and waiting for the level to restart
; ---------------------------------------------------------------------------
; loc_1CD90:
Obj02_Gone:
tst.w restart_countdown(a0)
beq.s +
subq.w #1,restart_countdown(a0)
bne.s +
move.w #1,(Level_Inactive_flag).w
+
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Tails when he's waiting for the camera to scroll back to where he respawned
; ---------------------------------------------------------------------------
; loc_1CDA4:
Obj02_Respawning:
tst.w (Camera_X_pos_diff_P2).w
bne.s +
tst.w (Camera_Y_pos_diff_P2).w
bne.s +
move.b #2,routine(a0)
+
bsr.w Tails_Animate
bsr.w LoadTailsDynPLC
jmp (DisplaySprite).l
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to animate Tails' sprites
; See also: AnimateSprite and Sonic_Animate
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1CDC4:
Tails_Animate:
lea (TailsAniData).l,a1
; loc_1CDCA:
Tails_Animate_Part2:
moveq #0,d0
move.b anim(a0),d0
cmp.b next_anim(a0),d0 ; has animation changed?
beq.s TAnim_Do ; if not, branch
move.b d0,next_anim(a0) ; set to next animation
move.b #0,anim_frame(a0) ; reset animation frame
move.b #0,anim_frame_duration(a0) ; reset frame duration
bclr #5,status(a0)
; loc_1CDEC:
TAnim_Do:
add.w d0,d0
adda.w (a1,d0.w),a1 ; calculate address of appropriate animation script
move.b (a1),d0
bmi.s TAnim_WalkRunZoom ; if animation is walk/run/roll/jump, branch
move.b status(a0),d1
andi.b #1,d1
andi.b #$FC,render_flags(a0)
or.b d1,render_flags(a0)
subq.b #1,anim_frame_duration(a0) ; subtract 1 from frame duration
bpl.s TAnim_Delay ; if time remains, branch
move.b d0,anim_frame_duration(a0) ; load frame duration
; loc_1CE12:
TAnim_Do2:
moveq #0,d1
move.b anim_frame(a0),d1 ; load current frame number
move.b 1(a1,d1.w),d0 ; read sprite number from script
cmpi.b #$F0,d0
bhs.s TAnim_End_FF ; if animation is complete, branch
; loc_1CE22:
TAnim_Next:
move.b d0,mapping_frame(a0) ; load sprite number
addq.b #1,anim_frame(a0) ; go to next frame
; return_1CE2A:
TAnim_Delay:
rts
; ===========================================================================
; loc_1CE2C:
TAnim_End_FF:
addq.b #1,d0 ; is the end flag = $FF ?
bne.s TAnim_End_FE ; if not, branch
move.b #0,anim_frame(a0) ; restart the animation
move.b 1(a1),d0 ; read sprite number
bra.s TAnim_Next
; ===========================================================================
; loc_1CE3C:
TAnim_End_FE:
addq.b #1,d0 ; is the end flag = $FE ?
bne.s TAnim_End_FD ; if not, branch
move.b 2(a1,d1.w),d0 ; read the next byte in the script
sub.b d0,anim_frame(a0) ; jump back d0 bytes in the script
sub.b d0,d1
move.b 1(a1,d1.w),d0 ; read sprite number
bra.s TAnim_Next
; ===========================================================================
; loc_1CE50:
TAnim_End_FD:
addq.b #1,d0 ; is the end flag = $FD ?
bne.s TAnim_End ; if not, branch
move.b 2(a1,d1.w),anim(a0) ; read next byte, run that animation
; return_1CE5A:
TAnim_End:
rts
; ===========================================================================
; loc_1CE5C:
TAnim_WalkRunZoom: ; a0=character
; note: for some reason SAnim_WalkRun doesn't need to do this here...
subq.b #1,anim_frame_duration(a0) ; subtract 1 from Tails' frame duration
bpl.s TAnim_Delay ; if time remains, branch
addq.b #1,d0 ; is the end flag = $FF ?
bne.w TAnim_Roll ; if not, branch
moveq #0,d0 ; is animation walking/running?
move.b flip_angle(a0),d0 ; if not, branch
bne.w TAnim_Tumble
moveq #0,d1
move.b angle(a0),d0 ; get Tails' angle
bmi.s +
beq.s +
subq.b #1,d0
+
move.b status(a0),d2
andi.b #1,d2 ; is Tails mirrored horizontally?
bne.s + ; if yes, branch
not.b d0 ; reverse angle
+
addi.b #$10,d0 ; add $10 to angle
bpl.s + ; if angle is $0-$7F, branch
moveq #3,d1
+
andi.b #$FC,render_flags(a0)
eor.b d1,d2
or.b d2,render_flags(a0)
btst #5,status(a0)
bne.w TAnim_Push
lsr.b #4,d0 ; divide angle by 16
andi.b #6,d0 ; angle must be 0, 2, 4 or 6
mvabs.w inertia(a0),d2 ; get Tails' "speed" for animation purposes
if status_sec_isSliding = 7
tst.b status_secondary(a0)
bpl.w +
else
btst #status_sec_isSliding,status_secondary(a0)
beq.w +
endif
add.w d2,d2
+
move.b d0,d3
add.b d3,d3
add.b d3,d3
lea (TailsAni_Walk).l,a1
cmpi.w #$600,d2 ; is Tails going pretty fast?
blo.s TAnim_SpeedSelected ; if not, branch
lea (TailsAni_Run).l,a1
move.b d0,d1
lsr.b #1,d1
add.b d1,d0
add.b d0,d0
move.b d0,d3
cmpi.w #$700,d2 ; is Tails going really fast?
blo.s TAnim_SpeedSelected ; if not, branch
lea (TailsAni_HaulAss).l,a1
; loc_1CEEE:
TAnim_SpeedSelected:
neg.w d2
addi.w #$800,d2
bpl.s +
moveq #0,d2
+
lsr.w #8,d2
move.b d2,anim_frame_duration(a0) ; modify frame duration
bsr.w TAnim_Do2
add.b d3,mapping_frame(a0)
rts
; ===========================================================================
; loc_1CF08
TAnim_Tumble:
move.b flip_angle(a0),d0
moveq #0,d1
move.b status(a0),d2
andi.b #1,d2
bne.s TAnim_Tumble_Left
andi.b #$FC,render_flags(a0)
addi.b #$B,d0
divu.w #$16,d0
addi.b #$75,d0
move.b d0,mapping_frame(a0)
move.b #0,anim_frame_duration(a0)
rts
; ===========================================================================
; loc_1CF36
TAnim_Tumble_Left:
andi.b #$FC,render_flags(a0)
tst.b flip_turned(a0)
beq.s +
ori.b #1,render_flags(a0)
addi.b #$B,d0
bra.s ++
; ===========================================================================
+
ori.b #3,render_flags(a0)
neg.b d0
addi.b #$8F,d0
+
divu.w #$16,d0
addi.b #$75,d0
move.b d0,mapping_frame(a0)
move.b #0,anim_frame_duration(a0)
rts
; ===========================================================================
; loc_1CF6E:
TAnim_Roll:
addq.b #1,d0 ; is the end flag = $FE ?
bne.s TAnim_GetTailFrame ; if not, branch
mvabs.w inertia(a0),d2
lea (TailsAni_Roll2).l,a1
cmpi.w #$600,d2
bhs.s +
lea (TailsAni_Roll).l,a1
+
neg.w d2
addi.w #$400,d2
bpl.s +
moveq #0,d2
+
lsr.w #8,d2
move.b d2,anim_frame_duration(a0)
move.b status(a0),d1
andi.b #1,d1
andi.b #$FC,render_flags(a0)
or.b d1,render_flags(a0)
bra.w TAnim_Do2
; ===========================================================================
; loc_1CFB2
TAnim_Push:
move.w inertia(a0),d2
bmi.s +
neg.w d2
+
addi.w #$800,d2
bpl.s +
moveq #0,d2
+
lsr.w #6,d2
move.b d2,anim_frame_duration(a0)
lea (TailsAni_Push).l,a1
move.b status(a0),d1
andi.b #1,d1
andi.b #$FC,render_flags(a0)
or.b d1,render_flags(a0)
bra.w TAnim_Do2
; ===========================================================================
; loc_1CFE4:
TAnim_GetTailFrame:
move.w x_vel(a2),d1
move.w y_vel(a2),d2
jsr (CalcAngle).l
moveq #0,d1
move.b status(a0),d2
andi.b #1,d2
bne.s loc_1D002
not.b d0
bra.s loc_1D006
; ===========================================================================
loc_1D002:
addi.b #$80,d0
loc_1D006:
addi.b #$10,d0
bpl.s +
moveq #3,d1
+
andi.b #$FC,render_flags(a0)
eor.b d1,d2
or.b d2,render_flags(a0)
lsr.b #3,d0
andi.b #$C,d0
move.b d0,d3
lea (Obj05Ani_Directional).l,a1
move.b #3,anim_frame_duration(a0)
bsr.w TAnim_Do2
add.b d3,mapping_frame(a0)
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Animation script - Tails
; ---------------------------------------------------------------------------
; off_1D038:
TailsAniData: offsetTable
TailsAni_Walk_ptr: offsetTableEntry.w TailsAni_Walk ; 0 ; 0
TailsAni_Run_ptr: offsetTableEntry.w TailsAni_Run ; 1 ; 1
TailsAni_Roll_ptr: offsetTableEntry.w TailsAni_Roll ; 2 ; 2
TailsAni_Roll2_ptr: offsetTableEntry.w TailsAni_Roll2 ; 3 ; 3
TailsAni_Push_ptr: offsetTableEntry.w TailsAni_Push ; 4 ; 4
TailsAni_Wait_ptr: offsetTableEntry.w TailsAni_Wait ; 5 ; 5
TailsAni_Balance_ptr: offsetTableEntry.w TailsAni_Balance ; 6 ; 6
TailsAni_LookUp_ptr: offsetTableEntry.w TailsAni_LookUp ; 7 ; 7
TailsAni_Duck_ptr: offsetTableEntry.w TailsAni_Duck ; 8 ; 8
TailsAni_Spindash_ptr: offsetTableEntry.w TailsAni_Spindash ; 9 ; 9
TailsAni_Dummy1_ptr: offsetTableEntry.w TailsAni_Dummy1 ; 10 ; $A
TailsAni_Dummy2_ptr: offsetTableEntry.w TailsAni_Dummy2 ; 11 ; $B
TailsAni_Dummy3_ptr: offsetTableEntry.w TailsAni_Dummy3 ; 12 ; $C
TailsAni_Stop_ptr: offsetTableEntry.w TailsAni_Stop ; 13 ; $D
TailsAni_Float_ptr: offsetTableEntry.w TailsAni_Float ; 14 ; $E
TailsAni_Float2_ptr: offsetTableEntry.w TailsAni_Float2 ; 15 ; $F
TailsAni_Spring_ptr: offsetTableEntry.w TailsAni_Spring ; 16 ; $10
TailsAni_Hang_ptr: offsetTableEntry.w TailsAni_Hang ; 17 ; $11
TailsAni_Blink_ptr: offsetTableEntry.w TailsAni_Blink ; 18 ; $12
TailsAni_Blink2_ptr: offsetTableEntry.w TailsAni_Blink2 ; 19 ; $13
TailsAni_Hang2_ptr: offsetTableEntry.w TailsAni_Hang2 ; 20 ; $14
TailsAni_Bubble_ptr: offsetTableEntry.w TailsAni_Bubble ; 21 ; $15
TailsAni_DeathBW_ptr: offsetTableEntry.w TailsAni_DeathBW ; 22 ; $16
TailsAni_Drown_ptr: offsetTableEntry.w TailsAni_Drown ; 23 ; $17
TailsAni_Death_ptr: offsetTableEntry.w TailsAni_Death ; 24 ; $18
TailsAni_Hurt_ptr: offsetTableEntry.w TailsAni_Hurt ; 25 ; $19
TailsAni_Hurt2_ptr: offsetTableEntry.w TailsAni_Hurt2 ; 26 ; $1A
TailsAni_Slide_ptr: offsetTableEntry.w TailsAni_Slide ; 27 ; $1B
TailsAni_Blank_ptr: offsetTableEntry.w TailsAni_Blank ; 28 ; $1C
TailsAni_Dummy4_ptr: offsetTableEntry.w TailsAni_Dummy4 ; 29 ; $1D
TailsAni_Dummy5_ptr: offsetTableEntry.w TailsAni_Dummy5 ; 30 ; $1E
TailsAni_HaulAss_ptr: offsetTableEntry.w TailsAni_HaulAss ; 31 ; $1F
TailsAni_Fly_ptr: offsetTableEntry.w TailsAni_Fly ; 32 ; $20
TailsAni_Walk: dc.b $FF,$10,$11,$12,$13,$14,$15, $E, $F,$FF
rev02even
TailsAni_Run: dc.b $FF,$2E,$2F,$30,$31,$FF,$FF,$FF,$FF,$FF
rev02even
TailsAni_Roll: dc.b 1,$48,$47,$46,$FF
rev02even
TailsAni_Roll2: dc.b 1,$48,$47,$46,$FF
rev02even
TailsAni_Push: dc.b $FD,$63,$64,$65,$66,$FF,$FF,$FF,$FF,$FF
rev02even
TailsAni_Wait: dc.b 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1
dc.b 1, 1, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1
dc.b 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
dc.b 6, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 6,$FE,$1C
rev02even
TailsAni_Balance: dc.b 9,$69,$69,$6A,$6A,$69,$69,$6A,$6A,$69,$69,$6A,$6A,$69,$69,$6A
dc.b $6A,$69,$69,$6A,$6A,$69,$6A,$FF
rev02even
TailsAni_LookUp: dc.b $3F, 4,$FF
rev02even
TailsAni_Duck: dc.b $3F,$5B,$FF
rev02even
TailsAni_Spindash: dc.b 0,$60,$61,$62,$FF
rev02even
TailsAni_Dummy1: dc.b $3F,$82,$FF
rev02even
TailsAni_Dummy2: dc.b 7, 8, 8, 9,$FD, 5
rev02even
TailsAni_Dummy3: dc.b 7, 9,$FD, 5
rev02even
TailsAni_Stop: dc.b 7,$67,$68,$67,$68,$FD, 0
rev02even
TailsAni_Float: dc.b 9,$6E,$73,$FF
rev02even
TailsAni_Float2: dc.b 9,$6E,$6F,$70,$71,$72,$FF
rev02even
TailsAni_Spring: dc.b 3,$59,$5A,$59,$5A,$59,$5A,$59,$5A,$59,$5A,$59,$5A,$FD, 0
rev02even
TailsAni_Hang: dc.b 5,$6C,$6D,$FF
rev02even
TailsAni_Blink: dc.b $F, 1, 2, 3,$FE, 1
rev02even
TailsAni_Blink2: dc.b $F, 1, 2,$FE, 1
rev02even
TailsAni_Hang2: dc.b $13,$85,$86,$FF
rev02even
TailsAni_Bubble: dc.b $B,$74,$74,$12,$13,$FD, 0
rev02even
TailsAni_DeathBW: dc.b $20,$5D,$FF
rev02even
TailsAni_Drown: dc.b $2F,$5D,$FF
rev02even
TailsAni_Death: dc.b 3,$5D,$FF
rev02even
TailsAni_Hurt: dc.b 3,$5D,$FF
rev02even
TailsAni_Hurt2: dc.b 3,$5C,$FF
rev02even
TailsAni_Slide: dc.b 9,$6B,$5C,$FF
rev02even
TailsAni_Blank: dc.b $77, 0,$FD, 0
rev02even
TailsAni_Dummy4: dc.b 3, 1, 2, 3, 4, 5, 6, 7, 8,$FF
rev02even
TailsAni_Dummy5: dc.b 3, 1, 2, 3, 4, 5, 6, 7, 8,$FF
rev02even
TailsAni_HaulAss: dc.b $FF,$32,$33,$FF
dc.b $FF,$FF,$FF,$FF,$FF,$FF
rev02even
TailsAni_Fly: dc.b 1,$5E,$5F,$FF
even
; ===========================================================================
; ---------------------------------------------------------------------------
; Tails' Tails pattern loading subroutine
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1D184:
LoadTailsTailsDynPLC:
moveq #0,d0
move.b mapping_frame(a0),d0
cmp.b (TailsTails_LastLoadedDPLC).w,d0
beq.s return_1D1FE
move.b d0,(TailsTails_LastLoadedDPLC).w
lea (MapRUnc_Tails).l,a2
add.w d0,d0
adda.w (a2,d0.w),a2
move.w (a2)+,d5
subq.w #1,d5
bmi.s return_1D1FE
move.w #tiles_to_bytes(ArtTile_ArtUnc_Tails_Tails),d4
bra.s TPLC_ReadEntry
; ---------------------------------------------------------------------------
; Tails pattern loading subroutine
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1D1AC:
LoadTailsDynPLC:
moveq #0,d0
move.b mapping_frame(a0),d0 ; load frame number
; loc_1D1B2:
LoadTailsDynPLC_Part2:
cmp.b (Tails_LastLoadedDPLC).w,d0
beq.s return_1D1FE
move.b d0,(Tails_LastLoadedDPLC).w
lea (MapRUnc_Tails).l,a2
add.w d0,d0
adda.w (a2,d0.w),a2
move.w (a2)+,d5
subq.w #1,d5
bmi.s return_1D1FE
move.w #tiles_to_bytes(ArtTile_ArtUnc_Tails),d4
; loc_1D1D2:
TPLC_ReadEntry:
moveq #0,d1
move.w (a2)+,d1
move.w d1,d3
lsr.w #8,d3
andi.w #$F0,d3
addi.w #$10,d3
andi.w #$FFF,d1
lsl.l #5,d1
addi.l #ArtUnc_Tails,d1
move.w d4,d2
add.w d3,d4
add.w d3,d4
jsr (QueueDMATransfer).l
dbf d5,TPLC_ReadEntry ; repeat for number of entries
return_1D1FE:
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 05 - Tails' tails
; ----------------------------------------------------------------------------
; Sprite_1D200:
Obj05:
moveq #0,d0
move.b routine(a0),d0
move.w Obj05_Index(pc,d0.w),d1
jmp Obj05_Index(pc,d1.w)
; ===========================================================================
; off_1D20E: Obj05_States:
Obj05_Index: offsetTable
offsetTableEntry.w Obj05_Init ; 0
offsetTableEntry.w Obj05_Main ; 2
; ===========================================================================
Obj05_parent_prev_anim = objoff_30
; loc_1D212
Obj05_Init:
addq.b #2,routine(a0) ; => Obj05_Main
move.l #MapUnc_Tails,mappings(a0)
move.w #make_art_tile(ArtTile_ArtUnc_Tails_Tails,0,0),art_tile(a0)
bsr.w Adjust2PArtPointer
move.b #2,priority(a0)
move.b #$18,width_pixels(a0)
move.b #4,render_flags(a0)
; loc_1D23A:
Obj05_Main:
movea.w parent(a0),a2 ; a2=character
move.b angle(a2),angle(a0)
move.b status(a2),status(a0)
move.w x_pos(a2),x_pos(a0)
move.w y_pos(a2),y_pos(a0)
andi.w #drawing_mask,art_tile(a0)
tst.w art_tile(a2)
bpl.s +
ori.w #high_priority,art_tile(a0)
+
moveq #0,d0
move.b anim(a2),d0
btst #5,status(a2)
beq.s +
moveq #4,d0
+
; This is here so Obj05Ani_Flick works
; It changes anim(a0) itself, so we don't want the below code changing it as well
cmp.b Obj05_parent_prev_anim(a0),d0 ; Did Tails' animation change?
beq.s .display
move.b d0,Obj05_parent_prev_anim(a0)
move.b Obj05AniSelection(pc,d0.w),anim(a0) ; If so, update Tails' tails' animation
; loc_1D288:
.display:
lea (Obj05AniData).l,a1
bsr.w Tails_Animate_Part2
bsr.w LoadTailsTailsDynPLC
jsr (DisplaySprite).l
rts
; ===========================================================================
; animation master script table for the tails
; chooses which animation script to run depending on what Tails is doing
; byte_1D29E:
Obj05AniSelection:
dc.b 0,0 ; TailsAni_Walk,Run ->
dc.b 3 ; TailsAni_Roll -> Directional
dc.b 3 ; TailsAni_Roll2 -> Directional
dc.b 9 ; TailsAni_Push -> Pushing
dc.b 1 ; TailsAni_Wait -> Swish
dc.b 0 ; TailsAni_Balance -> Blank
dc.b 2 ; TailsAni_LookUp -> Flick
dc.b 1 ; TailsAni_Duck -> Swish
dc.b 7 ; TailsAni_Spindash -> Spindash
dc.b 0,0,0 ; TailsAni_Dummy1,2,3 ->
dc.b 8 ; TailsAni_Stop -> Skidding
dc.b 0,0 ; TailsAni_Float,2 ->
dc.b 0 ; TailsAni_Spring ->
dc.b 0 ; TailsAni_Hang ->
dc.b 0,0 ; TailsAni_Blink,2 ->
dc.b $A ; TailsAni_Hang2 -> Hanging
dc.b 0 ; TailsAni_Bubble ->
dc.b 0,0,0,0 ; TailsAni_Death,2,3,4 ->
dc.b 0,0 ; TailsAni_Hurt,Slide ->
dc.b 0 ; TailsAni_Blank ->
dc.b 0,0 ; TailsAni_Dummy4,5 ->
dc.b 0 ; TailsAni_HaulAss ->
dc.b 0 ; TailsAni_Fly ->
even
; ---------------------------------------------------------------------------
; Animation script - Tails' tails
; ---------------------------------------------------------------------------
; off_1D2C0:
Obj05AniData: offsetTable
offsetTableEntry.w Obj05Ani_Blank ; 0
offsetTableEntry.w Obj05Ani_Swish ; 1
offsetTableEntry.w Obj05Ani_Flick ; 2
offsetTableEntry.w Obj05Ani_Directional ; 3
offsetTableEntry.w Obj05Ani_DownLeft ; 4
offsetTableEntry.w Obj05Ani_Down ; 5
offsetTableEntry.w Obj05Ani_DownRight ; 6
offsetTableEntry.w Obj05Ani_Spindash ; 7
offsetTableEntry.w Obj05Ani_Skidding ; 8
offsetTableEntry.w Obj05Ani_Pushing ; 9
offsetTableEntry.w Obj05Ani_Hanging ; $A
Obj05Ani_Blank: dc.b $20, 0,$FF
rev02even
Obj05Ani_Swish: dc.b 7, 9, $A, $B, $C, $D,$FF
rev02even
Obj05Ani_Flick: dc.b 3, 9, $A, $B, $C, $D,$FD, 1
rev02even
Obj05Ani_Directional: dc.b $FC,$49,$4A,$4B,$4C,$FF ; Tails is moving right
rev02even
Obj05Ani_DownLeft: dc.b 3,$4D,$4E,$4F,$50,$FF ; Tails is moving up-right
rev02even
Obj05Ani_Down: dc.b 3,$51,$52,$53,$54,$FF ; Tails is moving up
rev02even
Obj05Ani_DownRight: dc.b 3,$55,$56,$57,$58,$FF ; Tails is moving up-left
rev02even
Obj05Ani_Spindash: dc.b 2,$81,$82,$83,$84,$FF
rev02even
Obj05Ani_Skidding: dc.b 2,$87,$88,$89,$8A,$FF
rev02even
Obj05Ani_Pushing: dc.b 9,$87,$88,$89,$8A,$FF
rev02even
Obj05Ani_Hanging: dc.b 9,$81,$82,$83,$84,$FF
even
; ===========================================================================
JmpTo2_KillCharacter
jmp (KillCharacter).l
; ===========================================================================
align 4
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 0A - Small bubbles from Sonic's face while underwater
; ----------------------------------------------------------------------------
; Sprite_1D320:
Obj0A:
moveq #0,d0
move.b routine(a0),d0
move.w Obj0A_Index(pc,d0.w),d1
jmp Obj0A_Index(pc,d1.w)
; ===========================================================================
; off_1D32E: Obj0A_States:
Obj0A_Index: offsetTable
offsetTableEntry.w Obj0A_Init ; 0
offsetTableEntry.w Obj0A_Animate ; 2
offsetTableEntry.w Obj0A_ChkWater ; 4
offsetTableEntry.w Obj0A_Display ; 6
offsetTableEntry.w JmpTo5_DeleteObject ; 8
offsetTableEntry.w Obj0A_Countdown ; $A
offsetTableEntry.w Obj0A_AirLeft ; $C
offsetTableEntry.w Obj0A_DisplayNumber ; $E
offsetTableEntry.w JmpTo5_DeleteObject ; $10
; ===========================================================================
; loc_1D340: Obj0A_Main:
Obj0A_Init:
addq.b #2,routine(a0)
move.l #Obj24_MapUnc_1FBF6,mappings(a0)
tst.b parent+1(a0)
beq.s +
move.l #Obj24_MapUnc_1FC18,mappings(a0)
+
move.w #make_art_tile(ArtTile_ArtNem_BigBubbles,0,1),art_tile(a0)
move.b #$84,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #1,priority(a0)
move.b subtype(a0),d0
bpl.s loc_1D388
addq.b #8,routine(a0)
andi.w #$7F,d0
move.b d0,objoff_33(a0)
bra.w Obj0A_Countdown
; ===========================================================================
loc_1D388:
move.b d0,anim(a0)
move.w x_pos(a0),objoff_30(a0)
move.w #-$88,y_vel(a0)
; loc_1D398:
Obj0A_Animate:
lea (Ani_obj0A).l,a1
jsr (AnimateSprite).l
; loc_1D3A4:
Obj0A_ChkWater:
move.w (Water_Level_1).w,d0
cmp.w y_pos(a0),d0 ; has bubble reached the water surface?
blo.s Obj0A_Wobble ; if not, branch
; pop the bubble:
move.b #6,routine(a0)
addq.b #7,anim(a0)
cmpi.b #$D,anim(a0)
beq.s Obj0A_Display
blo.s Obj0A_Display
move.b #$D,anim(a0)
bra.s Obj0A_Display
; ===========================================================================
; loc_1D3CA:
Obj0A_Wobble:
tst.b (WindTunnel_flag).w
beq.s +
addq.w #4,objoff_30(a0)
+
move.b angle(a0),d0
addq.b #1,angle(a0)
andi.w #$7F,d0
lea (Obj0A_WobbleData).l,a1
move.b (a1,d0.w),d0
ext.w d0
add.w objoff_30(a0),d0
move.w d0,x_pos(a0)
bsr.s Obj0A_ShowNumber
jsr (ObjectMove).l
tst.b render_flags(a0)
bpl.s JmpTo4_DeleteObject
jmp (DisplaySprite).l
; ===========================================================================
JmpTo4_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
; loc_1D40E:
Obj0A_DisplayNumber:
movea.l objoff_3C(a0),a2 ; a2=character
cmpi.b #$C,air_left(a2)
bhi.s JmpTo5_DeleteObject
; loc_1D41A:
Obj0A_Display:
bsr.s Obj0A_ShowNumber
lea (Ani_obj0A).l,a1
jsr (AnimateSprite).l
jmp (DisplaySprite).l
; ===========================================================================
JmpTo5_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
; loc_1D434:
Obj0A_AirLeft:
movea.l objoff_3C(a0),a2 ; a2=character
cmpi.b #$C,air_left(a2) ; check air remaining
bhi.s JmpTo6_DeleteObject ; if higher than $C, branch
subq.w #1,objoff_38(a0)
bne.s Obj0A_Display2
move.b #$E,routine(a0)
addq.b #7,anim(a0)
bra.s Obj0A_Display
; ===========================================================================
; loc_1D452:
Obj0A_Display2:
lea (Ani_obj0A).l,a1
jsr (AnimateSprite).l
bsr.w Obj0A_LoadCountdownArt
tst.b render_flags(a0)
bpl.s JmpTo6_DeleteObject
jmp (DisplaySprite).l
; ===========================================================================
JmpTo6_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
; loc_1D474:
Obj0A_ShowNumber:
tst.w objoff_38(a0)
beq.s return_1D4BE
subq.w #1,objoff_38(a0)
bne.s return_1D4BE
cmpi.b #7,anim(a0)
bhs.s return_1D4BE
move.w #$F,objoff_38(a0)
clr.w y_vel(a0)
move.b #$80,render_flags(a0)
move.w x_pos(a0),d0
sub.w (Camera_X_pos).w,d0
addi.w #$80,d0
move.w d0,x_pixel(a0)
move.w y_pos(a0),d0
sub.w (Camera_Y_pos).w,d0
addi.w #$80,d0
move.w d0,y_pixel(a0)
move.b #$C,routine(a0)
return_1D4BE:
rts
; ===========================================================================
; byte_1D4C0:
Obj0A_WobbleData:
dc.b 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2;16
dc.b 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3;32
dc.b 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2;48
dc.b 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0;64
dc.b 0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2,-3,-3,-3,-3,-3;80
dc.b -3,-3,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4;96
dc.b -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-3;112
dc.b -3,-3,-3,-3,-3,-3,-2,-2,-2,-2,-2,-1,-1,-1,-1,-1;128
; Unused S1 leftover
; This was used by LZ's water ripple effect in REV01
dc.b 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2;144
dc.b 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3;160
dc.b 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2;176
dc.b 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0;192
dc.b 0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2,-3,-3,-3,-3,-3;208
dc.b -3,-3,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4;224
dc.b -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-3;240
dc.b -3,-3,-3,-3,-3,-3,-2,-2,-2,-2,-2,-1,-1,-1,-1,-1;256
; ===========================================================================
; the countdown numbers go over the dust and splash effect tiles in VRAM
; loc_1D5C0:
Obj0A_LoadCountdownArt:
moveq #0,d1
move.b mapping_frame(a0),d1
cmpi.b #8,d1
blo.s return_1D604
cmpi.b #$E,d1
bhs.s return_1D604
cmp.b objoff_2E(a0),d1
beq.s return_1D604
move.b d1,objoff_2E(a0)
subq.w #8,d1
move.w d1,d0
add.w d1,d1
add.w d0,d1
lsl.w #6,d1
addi.l #ArtUnc_Countdown,d1
move.w #tiles_to_bytes(ArtTile_ArtNem_SonicDust),d2
tst.b parent+1(a0)
beq.s +
move.w #tiles_to_bytes(ArtTile_ArtNem_TailsDust),d2
+
move.w #$60,d3
jsr (QueueDMATransfer).l
return_1D604:
rts
; ===========================================================================
; loc_1D606:
Obj0A_Countdown:
movea.l objoff_3C(a0),a2 ; a2=character
tst.w objoff_2C(a0)
bne.w loc_1D708
cmpi.b #6,routine(a2)
bhs.w return_1D81C
btst #6,status(a2)
beq.w return_1D81C
subq.w #1,objoff_38(a0)
bpl.w loc_1D72C
move.w #$3B,objoff_38(a0)
move.w #1,objoff_36(a0)
jsr (RandomNumber).l
andi.w #1,d0
move.b d0,objoff_34(a0)
moveq #0,d0
move.b air_left(a2),d0 ; check air remaining
cmpi.w #$19,d0
beq.s Obj0A_WarnSound ; play ding sound if air is $19
cmpi.w #$14,d0
beq.s Obj0A_WarnSound ; play ding sound if air is $14
cmpi.w #$F,d0
beq.s Obj0A_WarnSound ; play ding sound if air is $F
cmpi.w #$C,d0
bhi.s Obj0A_ReduceAir ; if air is above $C, branch
bne.s +
tst.b parent+1(a0)
bne.s +
move.w #MusID_Countdown,d0
jsr (PlayMusic).l ; play countdown music
+
subq.b #1,objoff_32(a0)
bpl.s Obj0A_ReduceAir
move.b objoff_33(a0),objoff_32(a0)
bset #7,objoff_36(a0)
bra.s Obj0A_ReduceAir
; ===========================================================================
; loc_1D68C:
Obj0A_WarnSound:
tst.b parent+1(a0)
bne.s Obj0A_ReduceAir
move.w #SndID_WaterWarning,d0
jsr (PlaySound).l ; play "ding-ding" warning sound
; loc_1D69C:
Obj0A_ReduceAir:
subq.b #1,air_left(a2) ; subtract 1 from air remaining
bcc.w BranchTo_Obj0A_MakeItem ; if air is above 0, branch
move.b #$81,obj_control(a2) ; lock controls
move.w #SndID_Drown,d0
jsr (PlaySound).l ; play drowning sound
move.b #$A,objoff_34(a0)
move.w #1,objoff_36(a0)
move.w #$78,objoff_2C(a0)
movea.l a2,a1
bsr.w ResumeMusic
move.l a0,-(sp)
movea.l a2,a0
bsr.w Sonic_ResetOnFloor_Part2
move.b #$17,anim(a0) ; use Sonic's drowning animation
bset #1,status(a0)
bset #high_priority_bit,art_tile(a0)
move.w #0,y_vel(a0)
move.w #0,x_vel(a0)
move.w #0,inertia(a0)
movea.l (sp)+,a0 ; load 0bj address ; restore a0 = obj0A
cmpa.w #MainCharacter,a2
bne.s + ; if it isn't player 1, branch
move.b #1,(Deform_lock).w
+
rts
; ===========================================================================
loc_1D708:
subq.w #1,objoff_2C(a0)
bne.s +
move.b #6,routine(a2)
rts
; ---------------------------------------------------------------------------
+ move.l a0,-(sp)
movea.l a2,a0
jsr (ObjectMove).l
addi.w #$10,y_vel(a0)
movea.l (sp)+,a0 ; load 0bj address
bra.s loc_1D72C
; ===========================================================================
BranchTo_Obj0A_MakeItem
bra.s Obj0A_MakeItem
; ===========================================================================
loc_1D72C:
tst.w objoff_36(a0)
beq.w return_1D81C
subq.w #1,objoff_3A(a0)
bpl.w return_1D81C
; loc_1D73C:
Obj0A_MakeItem:
jsr (RandomNumber).l
andi.w #$F,d0
addq.w #8,d0
move.w d0,objoff_3A(a0)
jsr (SingleObjLoad).l
bne.w return_1D81C
_move.b id(a0),id(a1) ; load obj0A
move.w x_pos(a2),x_pos(a1) ; match its X position to Sonic
moveq #6,d0
btst #0,status(a2)
beq.s +
neg.w d0
move.b #$40,angle(a1)
+
add.w d0,x_pos(a1)
move.w y_pos(a2),y_pos(a1)
move.l objoff_3C(a0),objoff_3C(a1)
move.b #6,subtype(a1)
tst.w objoff_2C(a0)
beq.w loc_1D7C6
andi.w #7,objoff_3A(a0)
addi.w #0,objoff_3A(a0)
move.w y_pos(a2),d0
subi.w #$C,d0
move.w d0,y_pos(a1)
jsr (RandomNumber).l
move.b d0,angle(a1)
move.w (Timer_frames).w,d0
andi.b #3,d0
bne.s loc_1D812
move.b #$E,subtype(a1)
bra.s loc_1D812
; ---------------------------------------------------------------------------
; has something to do with making bubbles come out less regularly
; when Sonic is almost drowning
loc_1D7C6:
btst #7,objoff_36(a0)
beq.s loc_1D812
moveq #0,d2
move.b air_left(a2),d2
cmpi.b #$C,d2
bhs.s loc_1D812
lsr.w #1,d2
jsr (RandomNumber).l
andi.w #3,d0
bne.s +
bset #6,objoff_36(a0)
bne.s loc_1D812
move.b d2,subtype(a1)
move.w #$1C,objoff_38(a1)
+
tst.b objoff_34(a0)
bne.s loc_1D812
bset #6,objoff_36(a0)
bne.s loc_1D812
move.b d2,subtype(a1)
move.w #$1C,objoff_38(a1)
loc_1D812:
subq.b #1,objoff_34(a0)
bpl.s return_1D81C
clr.w objoff_36(a0)
return_1D81C:
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to play music after a countdown (when Sonic leaves the water)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1D81E:
ResumeMusic:
cmpi.b #$C,air_left(a1)
bhi.s ResumeMusic_Done ; branch if countdown hasn't started yet
cmpa.w #MainCharacter,a1
bne.s ResumeMusic_Done ; branch if it isn't player 1
move.w (Level_Music).w,d0 ; prepare to play current level's music
btst #status_sec_isInvincible,status_secondary(a1)
beq.s + ; branch if Sonic is not invincible
move.w #MusID_Invincible,d0 ; prepare to play invincibility music
+
tst.b (Super_Sonic_flag).w
beq.w + ; branch if it isn't Super Sonic
move.w #MusID_SuperSonic,d0 ; prepare to play super sonic music
+
tst.b (Current_Boss_ID).w
beq.s + ; branch if not in a boss fight
move.w #MusID_Boss,d0 ; prepare to play boss music
+
jsr (PlayMusic).l
; return_1D858:
ResumeMusic_Done:
move.b #$1E,air_left(a1) ; reset air to full
rts
; ===========================================================================
; animation script for the bubbles
; off_1D860:
Ani_obj0A: offsetTable
offsetTableEntry.w byte_1D87E ; 0
offsetTableEntry.w byte_1D887 ; 1
offsetTableEntry.w byte_1D890 ; 2
offsetTableEntry.w byte_1D899 ; 3
offsetTableEntry.w byte_1D8A2 ; 4
offsetTableEntry.w byte_1D8AB ; 5
offsetTableEntry.w byte_1D8B4 ; 6
offsetTableEntry.w byte_1D8B9 ; 7
offsetTableEntry.w byte_1D8C1 ; 8
offsetTableEntry.w byte_1D8C9 ; 9
offsetTableEntry.w byte_1D8D1 ; $A
offsetTableEntry.w byte_1D8D9 ; $B
offsetTableEntry.w byte_1D8E1 ; $C
offsetTableEntry.w byte_1D8E9 ; $D
offsetTableEntry.w byte_1D8EB ; $E
byte_1D87E: dc.b 5, 0, 1, 2, 3, 4, 8, 8,$FC
rev02even
byte_1D887: dc.b 5, 0, 1, 2, 3, 4, 9, 9,$FC
rev02even
byte_1D890: dc.b 5, 0, 1, 2, 3, 4, $A, $A,$FC
rev02even
byte_1D899: dc.b 5, 0, 1, 2, 3, 4, $B, $B,$FC
rev02even
byte_1D8A2: dc.b 5, 0, 1, 2, 3, 4, $C, $C,$FC
rev02even
byte_1D8AB: dc.b 5, 0, 1, 2, 3, 4, $D, $D,$FC
rev02even
byte_1D8B4: dc.b $E, 0, 1, 2,$FC
rev02even
byte_1D8B9: dc.b 7,$10, 8,$10, 8,$10, 8,$FC
rev02even
byte_1D8C1: dc.b 7,$10, 9,$10, 9,$10, 9,$FC
rev02even
byte_1D8C9: dc.b 7,$10, $A,$10, $A,$10, $A,$FC
rev02even
byte_1D8D1: dc.b 7,$10, $B,$10, $B,$10, $B,$FC
rev02even
byte_1D8D9: dc.b 7,$10, $C,$10, $C,$10, $C,$FC
rev02even
byte_1D8E1: dc.b 7,$10, $D,$10, $D,$10, $D,$FC
rev02even
byte_1D8E9: dc.b $E,$FC
rev02even
byte_1D8EB: dc.b $E, 1, 2, 3, 4,$FC
even
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 38 - Shield
; ----------------------------------------------------------------------------
; Sprite_1D8F2:
Obj38:
moveq #0,d0
move.b routine(a0),d0
move.w Obj38_Index(pc,d0.w),d1
jmp Obj38_Index(pc,d1.w)
; ===========================================================================
; off_1D900:
Obj38_Index: offsetTable
offsetTableEntry.w Obj38_Main ; 0
offsetTableEntry.w Obj38_Shield ; 2
; ===========================================================================
; loc_1D904:
Obj38_Main:
addq.b #2,routine(a0)
move.l #Obj38_MapUnc_1DBE4,mappings(a0)
move.b #4,render_flags(a0)
move.b #1,priority(a0)
move.b #$18,width_pixels(a0)
move.w #make_art_tile(ArtTile_ArtNem_Shield,0,0),art_tile(a0)
bsr.w Adjust2PArtPointer
; loc_1D92C:
Obj38_Shield:
movea.w parent(a0),a2 ; a2=character
btst #status_sec_isInvincible,status_secondary(a2)
bne.s return_1D976
btst #status_sec_hasShield,status_secondary(a2)
beq.s JmpTo7_DeleteObject
move.w x_pos(a2),x_pos(a0)
move.w y_pos(a2),y_pos(a0)
move.b status(a2),status(a0)
andi.w #drawing_mask,art_tile(a0)
tst.w art_tile(a2)
bpl.s Obj38_Display
ori.w #high_priority,art_tile(a0)
; loc_1D964:
Obj38_Display:
lea (Ani_obj38).l,a1
jsr (AnimateSprite).l
jmp (DisplaySprite).l
; ===========================================================================
return_1D976:
rts
; ===========================================================================
JmpTo7_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 35 - Invincibility Stars
; ----------------------------------------------------------------------------
; Sprite_1D97E:
Obj35:
moveq #0,d0
move.b objoff_A(a0),d0
move.w Obj35_Index(pc,d0.w),d1
jmp Obj35_Index(pc,d1.w)
; ===========================================================================
; off_1D98C:
Obj35_Index: offsetTable
offsetTableEntry.w loc_1D9A4 ; 0
offsetTableEntry.w loc_1DA0C ; 2
offsetTableEntry.w loc_1DA80 ; 4
off_1D992:
dc.l byte_1DB8F
dc.w $B
dc.l byte_1DBA4
dc.w $160D
dc.l byte_1DBBD
dc.w $2C0D
; ===========================================================================
loc_1D9A4:
moveq #0,d2
lea off_1D992-6(pc),a2
lea (a0),a1
moveq #3,d1
- _move.b id(a0),id(a1) ; load obj35
move.b #4,objoff_A(a1) ; => loc_1DA80
move.l #Obj35_MapUnc_1DCBC,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_Invincible_stars,0,0),art_tile(a1)
bsr.w Adjust2PArtPointer2
move.b #4,render_flags(a1)
bset #6,render_flags(a1)
move.b #$10,mainspr_width(a1)
move.b #2,mainspr_childsprites(a1)
move.w parent(a0),parent(a1)
move.b d2,objoff_36(a1)
addq.w #1,d2
move.l (a2)+,objoff_30(a1)
move.w (a2)+,objoff_34(a1)
lea next_object(a1),a1 ; a1=object
dbf d1,-
move.b #2,objoff_A(a0) ; => loc_1DA0C
move.b #4,objoff_34(a0)
loc_1DA0C:
movea.w parent(a0),a1 ; a1=character
btst #status_sec_isInvincible,status_secondary(a1)
beq.w DeleteObject
move.w x_pos(a1),d0
move.w d0,x_pos(a0)
move.w y_pos(a1),d1
move.w d1,y_pos(a0)
lea sub2_x_pos(a0),a2
lea byte_1DB82(pc),a3
moveq #0,d5
loc_1DA34:
move.w objoff_38(a0),d2
move.b (a3,d2.w),d5
bpl.s loc_1DA44
clr.w objoff_38(a0)
bra.s loc_1DA34
; ===========================================================================
loc_1DA44:
addq.w #1,objoff_38(a0)
lea byte_1DB42(pc),a6
move.b objoff_34(a0),d6
jsr loc_1DB2C(pc)
move.w d2,(a2)+ ; sub2_x_pos
move.w d3,(a2)+ ; sub2_y_pos
move.w d5,(a2)+ ; sub2_mapframe
addi.w #$20,d6
jsr loc_1DB2C(pc)
move.w d2,(a2)+ ; sub3_x_pos
move.w d3,(a2)+ ; sub3_y_pos
move.w d5,(a2)+ ; sub3_mapframe
moveq #$12,d0
btst #0,status(a1)
beq.s loc_1DA74
neg.w d0
loc_1DA74:
add.b d0,objoff_34(a0)
move.w #$80,d0
bra.w DisplaySprite3
; ===========================================================================
loc_1DA80:
movea.w parent(a0),a1 ; a1=character
btst #status_sec_isInvincible,status_secondary(a1)
beq.w DeleteObject
cmpi.w #2,(Player_mode).w
beq.s loc_1DAA4
lea (Sonic_Pos_Record_Index).w,a5
lea (Sonic_Pos_Record_Buf).w,a6
tst.b parent+1(a0)
beq.s loc_1DAAC
loc_1DAA4:
lea (Tails_Pos_Record_Index).w,a5
lea (Tails_Pos_Record_Buf).w,a6
loc_1DAAC:
move.b objoff_36(a0),d1
lsl.b #2,d1
move.w d1,d2
add.w d1,d1
add.w d2,d1
move.w (a5),d0
sub.b d1,d0
lea (a6,d0.w),a2
move.w (a2)+,d0
move.w (a2)+,d1
move.w d0,x_pos(a0)
move.w d1,y_pos(a0)
lea sub2_x_pos(a0),a2
movea.l objoff_30(a0),a3
loc_1DAD4:
move.w objoff_38(a0),d2
move.b (a3,d2.w),d5
bpl.s loc_1DAE4
clr.w objoff_38(a0)
bra.s loc_1DAD4
; ===========================================================================
loc_1DAE4:
swap d5
add.b objoff_35(a0),d2
move.b (a3,d2.w),d5
addq.w #1,objoff_38(a0)
lea byte_1DB42(pc),a6
move.b objoff_34(a0),d6
jsr loc_1DB2C(pc)
move.w d2,(a2)+ ; sub2_x_pos
move.w d3,(a2)+ ; sub2_y_pos
move.w d5,(a2)+ ; sub2_mapframe
addi.w #$20,d6
swap d5
jsr loc_1DB2C(pc)
move.w d2,(a2)+ ; sub3_x_pos
move.w d3,(a2)+ ; sub3_y_pos
move.w d5,(a2)+ ; sub3_mapframe
moveq #2,d0
btst #0,status(a1)
beq.s loc_1DB20
neg.w d0
loc_1DB20:
add.b d0,objoff_34(a0)
move.w #$80,d0
bra.w DisplaySprite3
; ===========================================================================
loc_1DB2C:
andi.w #$3E,d6
move.b (a6,d6.w),d2
move.b 1(a6,d6.w),d3
ext.w d2
ext.w d3
add.w d0,d2
add.w d1,d3
rts
; ===========================================================================
; unknown
byte_1DB42: dc.w $F00, $F03, $E06, $D08, $B0B, $80D, $60E, $30F
dc.w $10, -$3F1, -$6F2, -$8F3, -$BF5, -$DF8, -$EFA, -$FFD
dc.w $F000, -$F04, -$E07, -$D09, -$B0C, -$80E, -$60F, -$310
dc.w -$10, $3F0, $6F1, $8F2, $BF4, $DF7, $EF9, $FFC
byte_1DB82: dc.b 8, 5, 7, 6, 6, 7, 5, 8, 6, 7, 7, 6,$FF
rev02even
byte_1DB8F: dc.b 8, 7, 6, 5, 4, 3, 4, 5, 6, 7,$FF
dc.b 3, 4, 5, 6, 7, 8, 7, 6, 5, 4
rev02even
byte_1DBA4: dc.b 8, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7,$FF
dc.b 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3
rev02even
byte_1DBBD: dc.b 7, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5, 6,$FF
dc.b 1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2
even
; animation script
; byte_1DBD6
Ani_obj38: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 0, 5, 0, 5, 1, 5, 2, 5, 3, 5, 4,$FF
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj38_MapUnc_1DBE4: BINCLUDE "mappings/sprite/obj38.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj35_MapUnc_1DCBC: BINCLUDE "mappings/sprite/obj35.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 08 - Water splash in Aquatic Ruin Zone, Spindash dust
; ----------------------------------------------------------------------------
; Sprite_1DD20:
Obj08:
moveq #0,d0
move.b routine(a0),d0
move.w Obj08_Index(pc,d0.w),d1
jmp Obj08_Index(pc,d1.w)
; ===========================================================================
; off_1DD2E:
Obj08_Index: offsetTable
offsetTableEntry.w Obj08_Init ; 0
offsetTableEntry.w Obj08_Main ; 2
offsetTableEntry.w BranchTo16_DeleteObject ; 4
offsetTableEntry.w Obj08_CheckSkid ; 6
; ===========================================================================
; loc_1DD36:
Obj08_Init:
addq.b #2,routine(a0)
move.l #Obj08_MapUnc_1DF5E,mappings(a0)
ori.b #4,render_flags(a0)
move.b #1,priority(a0)
move.b #$10,width_pixels(a0)
move.w #make_art_tile(ArtTile_ArtNem_SonicDust,0,0),art_tile(a0)
move.w #MainCharacter,parent(a0)
move.w #tiles_to_bytes(ArtTile_ArtNem_SonicDust),objoff_3C(a0)
cmpa.w #Sonic_Dust,a0
beq.s +
move.b #1,objoff_34(a0)
cmpi.w #2,(Player_mode).w
beq.s +
move.w #make_art_tile(ArtTile_ArtNem_TailsDust,0,0),art_tile(a0)
move.w #Sidekick,parent(a0)
move.w #tiles_to_bytes(ArtTile_ArtNem_TailsDust),objoff_3C(a0)
+
bsr.w Adjust2PArtPointer
; loc_1DD90:
Obj08_Main:
movea.w parent(a0),a2 ; a2=character
moveq #0,d0
move.b anim(a0),d0 ; use current animation as a secondary routine counter
add.w d0,d0
move.w Obj08_DisplayModes(pc,d0.w),d1
jmp Obj08_DisplayModes(pc,d1.w)
; ===========================================================================
; off_1DDA4:
Obj08_DisplayModes: offsetTable
offsetTableEntry.w Obj08_Display ; 0
offsetTableEntry.w Obj08_MdSplash ; 2
offsetTableEntry.w Obj08_MdSpindashDust ; 4
offsetTableEntry.w Obj08_MdSkidDust ; 6
; ===========================================================================
; loc_1DDAC:
Obj08_MdSplash:
move.w (Water_Level_1).w,y_pos(a0)
tst.b next_anim(a0)
bne.s Obj08_Display
move.w x_pos(a2),x_pos(a0)
move.b #0,status(a0)
andi.w #drawing_mask,art_tile(a0)
bra.s Obj08_Display
; ===========================================================================
; loc_1DDCC:
Obj08_MdSpindashDust:
cmpi.b #$C,air_left(a2)
blo.s Obj08_ResetDisplayMode
cmpi.b #4,routine(a2)
bhs.s Obj08_ResetDisplayMode
tst.b spindash_flag(a2)
beq.s Obj08_ResetDisplayMode
move.w x_pos(a2),x_pos(a0)
move.w y_pos(a2),y_pos(a0)
move.b status(a2),status(a0)
andi.b #1,status(a0)
tst.b objoff_34(a0)
beq.s +
subi_.w #4,y_pos(a0)
+
tst.b next_anim(a0)
bne.s Obj08_Display
andi.w #drawing_mask,art_tile(a0)
tst.w art_tile(a2)
bpl.s Obj08_Display
ori.w #high_priority,art_tile(a0)
bra.s Obj08_Display
; ===========================================================================
; loc_1DE20:
Obj08_MdSkidDust:
cmpi.b #$C,air_left(a2)
blo.s Obj08_ResetDisplayMode
; loc_1DE28:
Obj08_Display:
lea (Ani_obj08).l,a1
jsr (AnimateSprite).l
bsr.w Obj08_LoadDustOrSplashArt
jmp (DisplaySprite).l
; ===========================================================================
; loc_1DE3E:
Obj08_ResetDisplayMode:
move.b #0,anim(a0)
rts
; ===========================================================================
BranchTo16_DeleteObject
bra.w DeleteObject
; ===========================================================================
; loc_1DE4A:
Obj08_CheckSkid:
movea.w parent(a0),a2 ; a2=character
cmpi.b #AniIDSonAni_Stop,anim(a2) ; SonAni_Stop
beq.s Obj08_SkidDust
move.b #2,routine(a0)
move.b #0,objoff_32(a0)
rts
; ===========================================================================
; loc_1DE64:
Obj08_SkidDust:
subq.b #1,objoff_32(a0)
bpl.s loc_1DEE0
move.b #3,objoff_32(a0)
bsr.w SingleObjLoad
bne.s loc_1DEE0
_move.b id(a0),id(a1) ; load obj08
move.w x_pos(a2),x_pos(a1)
move.w y_pos(a2),y_pos(a1)
addi.w #$10,y_pos(a1)
tst.b objoff_34(a0)
beq.s +
subi_.w #4,y_pos(a1)
+
move.b #0,status(a1)
move.b #3,anim(a1)
addq.b #2,routine(a1)
move.l mappings(a0),mappings(a1)
move.b render_flags(a0),render_flags(a1)
move.b #1,priority(a1)
move.b #4,width_pixels(a1)
move.w art_tile(a0),art_tile(a1)
move.w parent(a0),parent(a1)
andi.w #drawing_mask,art_tile(a1)
tst.w art_tile(a2)
bpl.s loc_1DEE0
ori.w #high_priority,art_tile(a1)
loc_1DEE0:
bsr.s Obj08_LoadDustOrSplashArt
rts
; ===========================================================================
; loc_1DEE4:
Obj08_LoadDustOrSplashArt:
moveq #0,d0
move.b mapping_frame(a0),d0
cmp.b objoff_30(a0),d0
beq.s return_1DF36
move.b d0,objoff_30(a0)
lea (Obj08_MapRUnc_1E074).l,a2
add.w d0,d0
adda.w (a2,d0.w),a2
move.w (a2)+,d5
subq.w #1,d5
bmi.s return_1DF36
move.w objoff_3C(a0),d4
- moveq #0,d1
move.w (a2)+,d1
move.w d1,d3
lsr.w #8,d3
andi.w #$F0,d3
addi.w #$10,d3
andi.w #$FFF,d1
lsl.l #5,d1
addi.l #ArtUnc_Splash,d1
move.w d4,d2
add.w d3,d4
add.w d3,d4
jsr (QueueDMATransfer).l
dbf d5,-
return_1DF36:
rts
; ===========================================================================
; animation script
; off_1DF38:
Ani_obj08: offsetTable
offsetTableEntry.w Obj08Ani_Null ; 0
offsetTableEntry.w Obj08Ani_Splash ; 1
offsetTableEntry.w Obj08Ani_Dash ; 2
offsetTableEntry.w Obj08Ani_Skid ; 3
Obj08Ani_Null: dc.b $1F, 0,$FF
rev02even
Obj08Ani_Splash:dc.b 3, 1, 2, 3, 4, 5, 6, 7, 8, 9,$FD, 0
rev02even
Obj08Ani_Dash: dc.b 1, $A, $B, $C, $D, $E, $F,$10,$FF
rev02even
Obj08Ani_Skid: dc.b 3,$11,$12,$13,$14,$FC
even
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj08_MapUnc_1DF5E: BINCLUDE "mappings/sprite/obj08.bin"
; -------------------------------------------------------------------------------
; dynamic pattern loading cues
; -------------------------------------------------------------------------------
Obj08_MapRUnc_1E074: BINCLUDE "mappings/spriteDPLC/obj08.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 7E - Super Sonic's stars
; ----------------------------------------------------------------------------
; Sprite_1E0F0:
Obj7E:
moveq #0,d0
move.b routine(a0),d0
move.w Obj7E_Index(pc,d0.w),d1
jmp Obj7E_Index(pc,d1.w)
; ===========================================================================
; off_1E0FE: Obj7E_States:
Obj7E_Index: offsetTable
offsetTableEntry.w Obj7E_Init ; 0
offsetTableEntry.w Obj7E_Main ; 2
; ===========================================================================
; loc_1E102:
Obj7E_Init:
addq.b #2,routine(a0)
move.l #Obj7E_MapUnc_1E1BE,mappings(a0)
move.b #4,render_flags(a0)
move.b #1,priority(a0)
move.b #$18,width_pixels(a0)
move.w #make_art_tile(ArtTile_ArtNem_SuperSonic_stars,0,0),art_tile(a0)
bsr.w Adjust2PArtPointer
btst #high_priority_bit,(MainCharacter+art_tile).w
beq.s Obj7E_Main
bset #high_priority_bit,art_tile(a0)
; loc_1E138:
Obj7E_Main:
tst.b (Super_Sonic_flag).w
beq.s JmpTo8_DeleteObject
tst.b objoff_30(a0)
beq.s loc_1E188
subq.b #1,anim_frame_duration(a0)
bpl.s loc_1E170
move.b #1,anim_frame_duration(a0)
addq.b #1,mapping_frame(a0)
cmpi.b #6,mapping_frame(a0)
blo.s loc_1E170
move.b #0,mapping_frame(a0)
move.b #0,objoff_30(a0)
move.b #1,objoff_31(a0)
rts
; ===========================================================================
loc_1E170:
tst.b objoff_31(a0)
bne.s JmpTo6_DisplaySprite
loc_1E176:
move.w (MainCharacter+x_pos).w,x_pos(a0)
move.w (MainCharacter+y_pos).w,y_pos(a0)
JmpTo6_DisplaySprite
jmp (DisplaySprite).l
; ===========================================================================
loc_1E188:
tst.b (MainCharacter+obj_control).w
bne.s loc_1E1AA
mvabs.w (MainCharacter+inertia).w,d0
cmpi.w #$800,d0
blo.s loc_1E1AA
move.b #0,mapping_frame(a0)
move.b #1,objoff_30(a0)
bra.s loc_1E176
; ===========================================================================
loc_1E1AA:
move.b #0,objoff_30(a0)
move.b #0,objoff_31(a0)
rts
; ===========================================================================
JmpTo8_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj7E_MapUnc_1E1BE: BINCLUDE "mappings/sprite/obj7E.bin"
; ===========================================================================
if gameRevision<2
nop
endif
; ---------------------------------------------------------------------------
; Subroutine to change Sonic's angle & position as he walks along the floor
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1E234: Sonic_AnglePos:
AnglePos:
move.l #Primary_Collision,(Collision_addr).w
cmpi.b #$C,top_solid_bit(a0)
beq.s +
move.l #Secondary_Collision,(Collision_addr).w
+
move.b top_solid_bit(a0),d5
btst #3,status(a0)
beq.s +
moveq #0,d0
move.b d0,(Primary_Angle).w
move.b d0,(Secondary_Angle).w
rts
; ---------------------------------------------------------------------------
+ moveq #3,d0
move.b d0,(Primary_Angle).w
move.b d0,(Secondary_Angle).w
move.b angle(a0),d0
addi.b #$20,d0
bpl.s loc_1E286
move.b angle(a0),d0
bpl.s +
subq.b #1,d0
+
addi.b #$20,d0
bra.s loc_1E292
; ---------------------------------------------------------------------------
loc_1E286:
move.b angle(a0),d0
bpl.s loc_1E28E
addq.b #1,d0
loc_1E28E:
addi.b #$1F,d0
loc_1E292:
andi.b #$C0,d0
cmpi.b #$40,d0
beq.w Sonic_WalkVertL
cmpi.b #$80,d0
beq.w Sonic_WalkCeiling
cmpi.b #$C0,d0
beq.w Sonic_WalkVertR
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b y_radius(a0),d0
ext.w d0
add.w d0,d2
move.b x_radius(a0),d0
ext.w d0
add.w d0,d3
lea (Primary_Angle).w,a4
movea.w #$10,a3
move.w #0,d6
bsr.w FindFloor
move.w d1,-(sp)
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b y_radius(a0),d0
ext.w d0
add.w d0,d2
move.b x_radius(a0),d0
ext.w d0
neg.w d0
add.w d0,d3
lea (Secondary_Angle).w,a4
movea.w #$10,a3
move.w #0,d6
bsr.w FindFloor
move.w (sp)+,d0
bsr.w Sonic_Angle
tst.w d1
beq.s return_1E31C
bpl.s loc_1E31E
cmpi.w #-$E,d1
blt.s return_1E31C
add.w d1,y_pos(a0)
return_1E31C:
rts
; ===========================================================================
loc_1E31E:
mvabs.b x_vel(a0),d0
addq.b #4,d0
cmpi.b #$E,d0
blo.s +
move.b #$E,d0
+
cmp.b d0,d1
bgt.s loc_1E33C
loc_1E336:
add.w d1,y_pos(a0)
rts
; ===========================================================================
loc_1E33C:
tst.b stick_to_convex(a0)
bne.s loc_1E336
bset #1,status(a0)
bclr #5,status(a0)
move.b #AniIDSonAni_Run,next_anim(a0)
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to change Sonic's angle as he walks along the floor
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1E356:
Sonic_Angle:
move.b (Secondary_Angle).w,d2
cmp.w d0,d1
ble.s +
move.b (Primary_Angle).w,d2
move.w d0,d1
+
btst #0,d2
bne.s loc_1E380
move.b d2,d0
sub.b angle(a0),d0
bpl.s +
neg.b d0
+
cmpi.b #$20,d0
bhs.s loc_1E380
move.b d2,angle(a0)
rts
; ===========================================================================
loc_1E380:
move.b angle(a0),d2
addi.b #$20,d2
andi.b #$C0,d2
move.b d2,angle(a0)
rts
; End of function Sonic_Angle
; ---------------------------------------------------------------------------
; Subroutine allowing Sonic to walk up a vertical slope/wall to his right
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1E392:
Sonic_WalkVertR:
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b x_radius(a0),d0
ext.w d0
neg.w d0
add.w d0,d2
move.b y_radius(a0),d0
ext.w d0
add.w d0,d3
lea (Primary_Angle).w,a4
movea.w #$10,a3
move.w #0,d6
bsr.w FindWall
move.w d1,-(sp)
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b x_radius(a0),d0
ext.w d0
add.w d0,d2
move.b y_radius(a0),d0
ext.w d0
add.w d0,d3
lea (Secondary_Angle).w,a4
movea.w #$10,a3
move.w #0,d6
bsr.w FindWall
move.w (sp)+,d0
bsr.w Sonic_Angle
tst.w d1
beq.s return_1E400
bpl.s loc_1E402
cmpi.w #-$E,d1
blt.s return_1E400
add.w d1,x_pos(a0)
return_1E400:
rts
; ===========================================================================
loc_1E402:
mvabs.b y_vel(a0),d0
addq.b #4,d0
cmpi.b #$E,d0
blo.s +
move.b #$E,d0
+
cmp.b d0,d1
bgt.s loc_1E420
loc_1E41A:
add.w d1,x_pos(a0)
rts
; ===========================================================================
loc_1E420:
tst.b stick_to_convex(a0)
bne.s loc_1E41A
bset #1,status(a0)
bclr #5,status(a0)
move.b #AniIDSonAni_Run,next_anim(a0)
rts
; ===========================================================================
;loc_1E43A
Sonic_WalkCeiling:
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b y_radius(a0),d0
ext.w d0
sub.w d0,d2
eori.w #$F,d2
move.b x_radius(a0),d0
ext.w d0
add.w d0,d3
lea (Primary_Angle).w,a4
movea.w #-$10,a3
move.w #$800,d6
bsr.w FindFloor
move.w d1,-(sp)
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b y_radius(a0),d0
ext.w d0
sub.w d0,d2
eori.w #$F,d2
move.b x_radius(a0),d0
ext.w d0
sub.w d0,d3
lea (Secondary_Angle).w,a4
movea.w #-$10,a3
move.w #$800,d6
bsr.w FindFloor
move.w (sp)+,d0
bsr.w Sonic_Angle
tst.w d1
beq.s return_1E4AE
bpl.s loc_1E4B0
cmpi.w #-$E,d1
blt.s return_1E4AE
sub.w d1,y_pos(a0)
return_1E4AE:
rts
; ===========================================================================
loc_1E4B0:
mvabs.b x_vel(a0),d0
addq.b #4,d0
cmpi.b #$E,d0
blo.s +
move.b #$E,d0
+
cmp.b d0,d1
bgt.s loc_1E4CE
loc_1E4C8:
sub.w d1,y_pos(a0)
rts
; ===========================================================================
loc_1E4CE:
tst.b stick_to_convex(a0)
bne.s loc_1E4C8
bset #1,status(a0)
bclr #5,status(a0)
move.b #AniIDSonAni_Run,next_anim(a0)
rts
; ===========================================================================
;loc_1E4E8
Sonic_WalkVertL:
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b x_radius(a0),d0
ext.w d0
sub.w d0,d2
move.b y_radius(a0),d0
ext.w d0
sub.w d0,d3
eori.w #$F,d3
lea (Primary_Angle).w,a4
movea.w #-$10,a3
move.w #$400,d6
bsr.w FindWall
move.w d1,-(sp)
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b x_radius(a0),d0
ext.w d0
add.w d0,d2
move.b y_radius(a0),d0
ext.w d0
sub.w d0,d3
eori.w #$F,d3
lea (Secondary_Angle).w,a4
movea.w #-$10,a3
move.w #$400,d6
bsr.w FindWall
move.w (sp)+,d0
bsr.w Sonic_Angle
tst.w d1
beq.s return_1E55C
bpl.s loc_1E55E
cmpi.w #-$E,d1
blt.s return_1E55C
sub.w d1,x_pos(a0)
return_1E55C:
rts
; ===========================================================================
loc_1E55E:
mvabs.b y_vel(a0),d0
addq.b #4,d0
cmpi.b #$E,d0
blo.s +
move.b #$E,d0
+
cmp.b d0,d1
bgt.s loc_1E57C
loc_1E576:
sub.w d1,x_pos(a0)
rts
; ===========================================================================
loc_1E57C:
tst.b stick_to_convex(a0)
bne.s loc_1E576
bset #1,status(a0)
bclr #5,status(a0)
move.b #AniIDSonAni_Run,next_anim(a0)
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to find which tile is in the specified location
; d2 = y_pos
; d3 = x_pos
; returns relevant block ID in (a1)
; a1 is pointer to block in chunk table
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1E596: Floor_ChkTile:
Find_Tile:
move.w d2,d0 ; y_pos
add.w d0,d0
andi.w #$F00,d0 ; rounded 2*y_pos
move.w d3,d1 ; x_pos
lsr.w #3,d1
move.w d1,d4
lsr.w #4,d1 ; x_pos/128 = x_of_chunk
andi.w #$7F,d1
add.w d1,d0 ; d0 is relevant chunk ID now
moveq #-1,d1
clr.w d1 ; d1 is now $FFFF0000 = Chunk_Table
lea (Level_Layout).w,a1
move.b (a1,d0.w),d1 ; move 128*128 chunk ID to d1
add.w d1,d1
move.w word_1E5D0(pc,d1.w),d1
move.w d2,d0 ; y_pos
andi.w #$70,d0
add.w d0,d1
andi.w #$E,d4 ; x_pos/8
add.w d4,d1
movea.l d1,a1 ; address of block ID
rts
; ===========================================================================
; precalculated values for Find_Tile
; (Sonic 1 calculated it every time instead of using a table)
word_1E5D0:
c := 0
rept 256
dc.w c
c := c+$80
endm
; ===========================================================================
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Scans vertically for up to 2 16x16 blocks to find solid ground or ceiling.
; d2 = y_pos
; d3 = x_pos
; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top)
; d6 = $0000 for no flip, $0800 for vertical flip
; a3 = delta-y for next location to check if current one is empty
; a4 = pointer to angle buffer
; returns relevant block ID in (a1)
; returns distance in d1
; returns angle in (a4)
; loc_1E7D0:
FindFloor:
bsr.w Find_Tile
move.w (a1),d0
move.w d0,d4
andi.w #$3FF,d0
beq.s loc_1E7E2
btst d5,d4
bne.s loc_1E7F0
loc_1E7E2:
add.w a3,d2
bsr.w FindFloor2
sub.w a3,d2
addi.w #$10,d1
rts
; ===========================================================================
loc_1E7F0: ; block has some solidity
movea.l (Collision_addr).w,a2 ; pointer to collision data, i.e. blockID -> collisionID array
move.b (a2,d0.w),d0 ; get collisionID
andi.w #$FF,d0
beq.s loc_1E7E2
lea (ColCurveMap).l,a2
move.b (a2,d0.w),(a4) ; get angle from AngleMap --> (a4)
lsl.w #4,d0
move.w d3,d1 ; x_pos
btst #$A,d4 ; adv.blockID in d4 - X flipping
beq.s +
not.w d1
neg.b (a4)
+
btst #$B,d4 ; Y flipping
beq.s +
addi.b #$40,(a4)
neg.b (a4)
subi.b #$40,(a4)
+
andi.w #$F,d1 ; x_pos (mod 16)
add.w d0,d1 ; d0 = 16*blockID -> offset in ColArray to look up
lea (ColArray).l,a2
move.b (a2,d1.w),d0 ; heigth from ColArray
ext.w d0
eor.w d6,d4
btst #$B,d4 ; Y flipping
beq.s +
neg.w d0
+
tst.w d0
beq.s loc_1E7E2 ; no collision
bmi.s loc_1E85E
cmpi.b #$10,d0
beq.s loc_1E86A
move.w d2,d1
andi.w #$F,d1
add.w d1,d0
move.w #$F,d1
sub.w d0,d1
rts
; ===========================================================================
loc_1E85E:
move.w d2,d1
andi.w #$F,d1
add.w d1,d0
bpl.w loc_1E7E2
loc_1E86A:
sub.w a3,d2
bsr.w FindFloor2
add.w a3,d2
subi.w #$10,d1
rts
; End of function FindFloor
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Checks a 16x16 block to find solid ground or ceiling.
; d2 = y_pos
; d3 = x_pos
; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top)
; d6 = $0000 for no flip, $0800 for vertical flip
; a4 = pointer to angle buffer
; returns relevant block ID in (a1)
; returns distance in d1
; returns angle in (a4)
; loc_1E878:
FindFloor2:
bsr.w Find_Tile
move.w (a1),d0
move.w d0,d4
andi.w #$3FF,d0
beq.s loc_1E88A
btst d5,d4
bne.s loc_1E898
loc_1E88A:
move.w #$F,d1
move.w d2,d0
andi.w #$F,d0
sub.w d0,d1
rts
; ===========================================================================
loc_1E898:
movea.l (Collision_addr).w,a2
move.b (a2,d0.w),d0
andi.w #$FF,d0
beq.s loc_1E88A
lea (ColCurveMap).l,a2
move.b (a2,d0.w),(a4)
lsl.w #4,d0
move.w d3,d1
btst #$A,d4
beq.s +
not.w d1
neg.b (a4)
+
btst #$B,d4
beq.s +
addi.b #$40,(a4)
neg.b (a4)
subi.b #$40,(a4)
+
andi.w #$F,d1
add.w d0,d1
lea (ColArray).l,a2
move.b (a2,d1.w),d0
ext.w d0
eor.w d6,d4
btst #$B,d4
beq.s +
neg.w d0
+
tst.w d0
beq.s loc_1E88A
bmi.s loc_1E900
move.w d2,d1
andi.w #$F,d1
add.w d1,d0
move.w #$F,d1
sub.w d0,d1
rts
; ===========================================================================
loc_1E900:
move.w d2,d1
andi.w #$F,d1
add.w d1,d0
bpl.w loc_1E88A
not.w d1
rts
; ===========================================================================
; Checks a 16x16 block to find solid ground or ceiling. May check an additional
; 16x16 block up for ceilings.
; d2 = y_pos
; d3 = x_pos
; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top)
; d6 = $0000 for no flip, $0800 for vertical flip
; a4 = pointer to angle buffer
; returns relevant block ID in (a1)
; returns distance in d1
; returns angle in (a4)
; loc_1E910: Obj_CheckInFloor:
Ring_FindFloor:
bsr.w Find_Tile
move.w (a1),d0
move.w d0,d4
andi.w #$3FF,d0
beq.s loc_1E922
btst d5,d4
bne.s loc_1E928
loc_1E922:
move.w #$10,d1
rts
; ===========================================================================
loc_1E928:
movea.l (Collision_addr).w,a2
move.b (a2,d0.w),d0
andi.w #$FF,d0
beq.s loc_1E922
lea (ColCurveMap).l,a2
move.b (a2,d0.w),(a4)
lsl.w #4,d0
move.w d3,d1
btst #$A,d4
beq.s +
not.w d1
neg.b (a4)
+
btst #$B,d4
beq.s +
addi.b #$40,(a4)
neg.b (a4)
subi.b #$40,(a4)
+
andi.w #$F,d1
add.w d0,d1
lea (ColArray).l,a2
move.b (a2,d1.w),d0
ext.w d0
eor.w d6,d4
btst #$B,d4
beq.s +
neg.w d0
+
tst.w d0
beq.s loc_1E922
bmi.s loc_1E996
cmpi.b #$10,d0
beq.s loc_1E9A2
move.w d2,d1
andi.w #$F,d1
add.w d1,d0
move.w #$F,d1
sub.w d0,d1
rts
; ===========================================================================
loc_1E996:
move.w d2,d1
andi.w #$F,d1
add.w d1,d0
bpl.w loc_1E922
loc_1E9A2:
sub.w a3,d2
bsr.w FindFloor2
add.w a3,d2
subi.w #$10,d1
rts
; ===========================================================================
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Scans horizontally for up to 2 16x16 blocks to find solid walls.
; d2 = y_pos
; d3 = x_pos
; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top)
; d6 = $0000 for no flip, $0400 for horizontal flip
; a3 = delta-x for next location to check if current one is empty
; a4 = pointer to angle buffer
; returns relevant block ID in (a1)
; returns distance to left/right in d1
; returns angle in (a4)
; loc_1E9B0:
FindWall:
bsr.w Find_Tile
move.w (a1),d0
move.w d0,d4
andi.w #$3FF,d0 ; plain blockID
beq.s loc_1E9C2 ; no collision
btst d5,d4
bne.s loc_1E9D0
loc_1E9C2:
add.w a3,d3
bsr.w FindWall2
sub.w a3,d3
addi.w #$10,d1
rts
; ===========================================================================
loc_1E9D0:
movea.l (Collision_addr).w,a2
move.b (a2,d0.w),d0
andi.w #$FF,d0 ; relevant collisionArrayEntry
beq.s loc_1E9C2
lea (ColCurveMap).l,a2
move.b (a2,d0.w),(a4)
lsl.w #4,d0 ; offset in collision array
move.w d2,d1 ; y
btst #$B,d4 ; y-mirror?
beq.s +
not.w d1
addi.b #$40,(a4)
neg.b (a4)
subi.b #$40,(a4)
+
btst #$A,d4 ; x-mirror?
beq.s +
neg.b (a4)
+
andi.w #$F,d1 ; y
add.w d0,d1 ; line to look up
lea (ColArray2).l,a2 ; rotated collision array
move.b (a2,d1.w),d0 ; collision value
ext.w d0
eor.w d6,d4 ; set x-flip flag if from the right
btst #$A,d4 ; x-mirror?
beq.s +
neg.w d0
+
tst.w d0
beq.s loc_1E9C2
bmi.s loc_1EA3E
cmpi.b #$10,d0
beq.s loc_1EA4A
move.w d3,d1 ; x
andi.w #$F,d1
add.w d1,d0
move.w #$F,d1
sub.w d0,d1
rts
; ===========================================================================
loc_1EA3E:
move.w d3,d1
andi.w #$F,d1
add.w d1,d0
bpl.w loc_1E9C2 ; no collision
loc_1EA4A:
sub.w a3,d3
bsr.w FindWall2
add.w a3,d3
subi.w #$10,d1
rts
; End of function FindWall
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Checks a 16x16 blocks to find solid walls.
; d2 = y_pos
; d3 = x_pos
; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top)
; d6 = $0000 for no flip, $0400 for horizontal flip
; a4 = pointer to angle buffer
; returns relevant block ID in (a1)
; returns distance to left/right in d1
; returns angle in (a4)
; loc_1EA58:
FindWall2:
bsr.w Find_Tile
move.w (a1),d0
move.w d0,d4
andi.w #$3FF,d0
beq.s loc_1EA6A
btst d5,d4
bne.s loc_1EA78
loc_1EA6A:
move.w #$F,d1
move.w d3,d0
andi.w #$F,d0
sub.w d0,d1
rts
; ===========================================================================
loc_1EA78:
movea.l (Collision_addr).w,a2
move.b (a2,d0.w),d0
andi.w #$FF,d0
beq.s loc_1EA6A
lea (ColCurveMap).l,a2
move.b (a2,d0.w),(a4)
lsl.w #4,d0
move.w d2,d1
btst #$B,d4
beq.s +
not.w d1
addi.b #$40,(a4)
neg.b (a4)
subi.b #$40,(a4)
+
btst #$A,d4
beq.s +
neg.b (a4)
+
andi.w #$F,d1
add.w d0,d1
lea (ColArray2).l,a2
move.b (a2,d1.w),d0
ext.w d0
eor.w d6,d4
btst #$A,d4
beq.s +
neg.w d0
+
tst.w d0
beq.s loc_1EA6A
bmi.s loc_1EAE0
move.w d3,d1
andi.w #$F,d1
add.w d1,d0
move.w #$F,d1
sub.w d0,d1
rts
; ===========================================================================
loc_1EAE0:
move.w d3,d1
andi.w #$F,d1
add.w d1,d0
bpl.w loc_1EA6A
not.w d1
rts
; End of function FindWall2
; ---------------------------------------------------------------------------
; Unused floor/wall subroutine - logs something to do with collision
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; return_1EAF0:
FloorLog_Unk:
rts
; ---------------------------------------------------------------------------
lea (ColArray).l,a1
lea (ColArray).l,a2
; for d3 from 255 to 0
move.w #$FF,d3
- moveq #$10,d5
; for d2 from 15 to 0
move.w #$F,d2
- moveq #0,d4
; for d1 from 15 to 0
move.w #$F,d1
- move.w (a1)+,d0
lsr.l d5,d0
addx.w d4,d4
dbf d1,- ; end for d1
move.w d4,(a2)+
suba.w #$20,a1
subq.w #1,d5
dbf d2,-- ; end for d2
adda.w #$20,a1
dbf d3,--- ; end for d3
lea (ColArray).l,a1
lea (ColArray2).l,a2
bsr.s FloorLog_Unk2
lea (ColArray).l,a1
lea (ColArray).l,a2
; End of function FloorLog_Unk
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1EB46:
FloorLog_Unk2:
move.w #$FFF,d3
- moveq #0,d2
move.w #$F,d1
move.w (a1)+,d0
beq.s loc_1EB78
bmi.s ++
- lsr.w #1,d0
bcc.s +
addq.b #1,d2
+ dbf d1,-
bra.s loc_1EB7A
; ===========================================================================
+
cmpi.w #-1,d0
beq.s ++
- lsl.w #1,d0
bcc.s +
subq.b #1,d2
+ dbf d1,-
bra.s loc_1EB7A
; ===========================================================================
+
move.w #$10,d0
loc_1EB78:
move.w d0,d2
loc_1EB7A:
move.b d2,(a2)+
dbf d3,---
rts
; End of function FloorLog_Unk2
if gameRevision<2
nop
endif
; ---------------------------------------------------------------------------
; Subroutine to calculate how much space is in front of Sonic or Tails on the ground
; d0 = some input angle
; d1 = output about how many pixels (up to some high enough amount)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1EB84: Sonic_WalkSpeed:
CalcRoomInFront:
move.l #Primary_Collision,(Collision_addr).w
cmpi.b #$C,top_solid_bit(a0)
beq.s +
move.l #Secondary_Collision,(Collision_addr).w
+
move.b lrb_solid_bit(a0),d5 ; Want walls or ceilings
move.l x_pos(a0),d3
move.l y_pos(a0),d2
move.w x_vel(a0),d1
ext.l d1
asl.l #8,d1
add.l d1,d3
move.w y_vel(a0),d1
ext.l d1
asl.l #8,d1
add.l d1,d2
swap d2
swap d3
move.b d0,(Primary_Angle).w
move.b d0,(Secondary_Angle).w
move.b d0,d1
addi.b #$20,d0
bpl.s loc_1EBDC
move.b d1,d0
bpl.s +
subq.b #1,d0
+
addi.b #$20,d0
bra.s loc_1EBE6
; ---------------------------------------------------------------------------
loc_1EBDC:
move.b d1,d0
bpl.s +
addq.b #1,d0
+
addi.b #$1F,d0
loc_1EBE6:
andi.b #$C0,d0
beq.w CheckFloorDist_Part2 ; Player is going mostly down
cmpi.b #$80,d0
beq.w CheckCeilingDist_Part2 ; Player is going mostly up
andi.b #$38,d1
bne.s +
addq.w #8,d2
+
cmpi.b #$40,d0
beq.w CheckLeftWallDist_Part2 ; Player is going mostly left
bra.w CheckRightWallDist_Part2 ; Player is going mostly right
; End of function CalcRoomInFront
; ---------------------------------------------------------------------------
; Subroutine to calculate how much space is empty above Sonic's/Tails' head
; d0 = input angle perpendicular to the spine
; d1 = output about how many pixels are overhead (up to some high enough amount)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_1EC0A:
CalcRoomOverHead:
move.l #Primary_Collision,(Collision_addr).w
cmpi.b #$C,top_solid_bit(a0)
beq.s +
move.l #Secondary_Collision,(Collision_addr).w
+
move.b lrb_solid_bit(a0),d5
move.b d0,(Primary_Angle).w
move.b d0,(Secondary_Angle).w
addi.b #$20,d0
andi.b #$C0,d0
cmpi.b #$40,d0
beq.w CheckLeftCeilingDist
cmpi.b #$80,d0
beq.w Sonic_CheckCeiling
cmpi.b #$C0,d0
beq.w CheckRightCeilingDist
; End of function CalcRoomOverHead
; ---------------------------------------------------------------------------
; Subroutine to check if Sonic/Tails is near the floor
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1EC4E: Sonic_HitFloor:
Sonic_CheckFloor:
move.l #Primary_Collision,(Collision_addr).w
cmpi.b #$C,top_solid_bit(a0)
beq.s +
move.l #Secondary_Collision,(Collision_addr).w
+
move.b top_solid_bit(a0),d5
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b y_radius(a0),d0
ext.w d0
add.w d0,d2
move.b x_radius(a0),d0
ext.w d0
add.w d0,d3
lea (Primary_Angle).w,a4
movea.w #$10,a3
move.w #0,d6
bsr.w FindFloor
move.w d1,-(sp)
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b y_radius(a0),d0
ext.w d0
add.w d0,d2
move.b x_radius(a0),d0
ext.w d0
sub.w d0,d3
lea (Secondary_Angle).w,a4
movea.w #$10,a3
move.w #0,d6
bsr.w FindFloor
move.w (sp)+,d0
move.b #0,d2
loc_1ECC6:
move.b (Secondary_Angle).w,d3
cmp.w d0,d1
ble.s loc_1ECD4
move.b (Primary_Angle).w,d3
exg d0,d1
loc_1ECD4:
btst #0,d3
beq.s +
move.b d2,d3
+
rts
; ===========================================================================
; a bit of unused/dead code here
;CheckFloorDist:
move.w y_pos(a0),d2 ; a0=character
move.w x_pos(a0),d3
; Checks a 16x16 block to find solid ground. May check an additional
; 16x16 block up for ceilings.
; d2 = y_pos
; d3 = x_pos
; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top)
; returns relevant block ID in (a1)
; returns distance in d1
; returns angle in d3, or zero if angle was odd
;loc_1ECE6:
CheckFloorDist_Part2:
addi.w #$A,d2
lea (Primary_Angle).w,a4
movea.w #$10,a3
move.w #0,d6
bsr.w FindFloor
move.b #0,d2
; d2 what to use as angle if (Primary_Angle).w is odd
; returns angle in d3, or value in d2 if angle was odd
loc_1ECFE:
move.b (Primary_Angle).w,d3
btst #0,d3
beq.s +
move.b d2,d3
+
rts
; ===========================================================================
; Unused collision checking subroutine
move.w x_pos(a0),d3 ; a0=character
move.w y_pos(a0),d2
subq.w #4,d2
move.l #Primary_Collision,(Collision_addr).w
cmpi.b #$D,lrb_solid_bit(a0)
beq.s +
move.l #Secondary_Collision,(Collision_addr).w
+
lea (Primary_Angle).w,a4
move.b #0,(a4)
movea.w #$10,a3
move.w #0,d6
move.b lrb_solid_bit(a0),d5
bsr.w FindFloor
move.b (Primary_Angle).w,d3
btst #0,d3
beq.s +
move.b #0,d3
+
rts
; ===========================================================================
; loc_1ED56:
ChkFloorEdge:
move.w x_pos(a0),d3
; loc_1ED5A:
ChkFloorEdge_Part2:
move.w y_pos(a0),d2
moveq #0,d0
move.b y_radius(a0),d0
ext.w d0
add.w d0,d2
move.l #Primary_Collision,(Collision_addr).w
cmpi.b #$C,top_solid_bit(a0)
beq.s +
move.l #Secondary_Collision,(Collision_addr).w
+
lea (Primary_Angle).w,a4
move.b #0,(a4)
movea.w #$10,a3
move.w #0,d6
move.b top_solid_bit(a0),d5
bsr.w FindFloor
move.b (Primary_Angle).w,d3
btst #0,d3
beq.s +
move.b #0,d3
+
rts
; ===========================================================================
; Identical to ChkFloorEdge except that this uses a1 instead of a0
;loc_1EDA8:
ChkFloorEdge2:
move.w x_pos(a1),d3
move.w y_pos(a1),d2
moveq #0,d0
move.b y_radius(a1),d0
ext.w d0
add.w d0,d2
move.l #Primary_Collision,(Collision_addr).w
cmpi.b #$C,top_solid_bit(a1)
beq.s +
move.l #Secondary_Collision,(Collision_addr).w
+
lea (Primary_Angle).w,a4
move.b #0,(a4)
movea.w #$10,a3
move.w #0,d6
move.b top_solid_bit(a1),d5
bsr.w FindFloor
move.b (Primary_Angle).w,d3
btst #0,d3
beq.s return_1EDF8
move.b #0,d3
return_1EDF8:
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine checking if an object should interact with the floor
; (objects such as a monitor Sonic bumps from underneath)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1EDFA: ObjHitFloor:
ObjCheckFloorDist:
move.w x_pos(a0),d3
move.w y_pos(a0),d2
move.b y_radius(a0),d0
ext.w d0
add.w d0,d2
lea (Primary_Angle).w,a4
move.b #0,(a4)
movea.w #$10,a3
move.w #0,d6
moveq #$C,d5
bsr.w FindFloor
move.b (Primary_Angle).w,d3
btst #0,d3
beq.s +
move.b #0,d3
+
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Collision check used to let the HTZ boss fire attack to hit the ground
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1EE30:
FireCheckFloorDist:
move.w x_pos(a1),d3
move.w y_pos(a1),d2
move.b y_radius(a1),d0
ext.w d0
add.w d0,d2
lea (Primary_Angle).w,a4
move.b #0,(a4)
movea.w #$10,a3
move.w #0,d6
moveq #$C,d5
bra.w FindFloor
; End of function FireCheckFloorDist
; ---------------------------------------------------------------------------
; Collision check used to let scattered rings bounce on the ground
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1EE56:
RingCheckFloorDist:
move.w x_pos(a0),d3
move.w y_pos(a0),d2
move.b y_radius(a0),d0
ext.w d0
add.w d0,d2
lea (Primary_Angle).w,a4
move.b #0,(a4)
movea.w #$10,a3
move.w #0,d6
moveq #$C,d5
bra.w Ring_FindFloor
; End of function RingCheckFloorDist
; ---------------------------------------------------------------------------
; Stores a distance to the nearest wall above Sonic/Tails,
; where "above" = right, into d1
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1EE7C:
CheckRightCeilingDist:
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b x_radius(a0),d0
ext.w d0
sub.w d0,d2
move.b y_radius(a0),d0
ext.w d0
add.w d0,d3
lea (Primary_Angle).w,a4
movea.w #$10,a3
move.w #0,d6
bsr.w FindWall
move.w d1,-(sp)
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b x_radius(a0),d0
ext.w d0
add.w d0,d2
move.b y_radius(a0),d0
ext.w d0
add.w d0,d3
lea (Secondary_Angle).w,a4
movea.w #$10,a3
move.w #0,d6
bsr.w FindWall
move.w (sp)+,d0
move.b #-$40,d2
bra.w loc_1ECC6
; End of function CheckRightCeilingDist
; ---------------------------------------------------------------------------
; Stores a distance to the nearest wall on the right of Sonic/Tails into d1
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Checks a 16x16 block to find solid walls. May check an additional
; 16x16 block up for walls.
; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top)
; returns relevant block ID in (a1)
; returns distance in d1
; returns angle in d3, or zero if angle was odd
; sub_1EEDC:
CheckRightWallDist:
move.w y_pos(a0),d2
move.w x_pos(a0),d3
; loc_1EEE4:
CheckRightWallDist_Part2:
addi.w #$A,d3
lea (Primary_Angle).w,a4
movea.w #$10,a3
move.w #0,d6
bsr.w FindWall
move.b #-$40,d2
bra.w loc_1ECFE
; End of function CheckRightWallDist
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1EF00: ObjCheckLeftWallDist:
ObjCheckRightWallDist:
add.w x_pos(a0),d3
move.w y_pos(a0),d2
lea (Primary_Angle).w,a4
move.b #0,(a4)
movea.w #$10,a3
move.w #0,d6
moveq #$D,d5
bsr.w FindWall
move.b (Primary_Angle).w,d3
btst #0,d3
beq.s +
move.b #-$40,d3
+
rts
; End of function ObjCheckRightWallDist
; ---------------------------------------------------------------------------
; Stores a distance from Sonic/Tails to the nearest ceiling into d1
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1EF2E: Sonic_DontRunOnWalls: CheckCeilingDist:
Sonic_CheckCeiling:
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b y_radius(a0),d0
ext.w d0
sub.w d0,d2
eori.w #$F,d2 ; flip position upside-down within the current 16x16 block?
move.b x_radius(a0),d0
ext.w d0
add.w d0,d3
lea (Primary_Angle).w,a4
movea.w #-$10,a3
move.w #$800,d6
bsr.w FindFloor
move.w d1,-(sp)
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b y_radius(a0),d0
ext.w d0
sub.w d0,d2
eori.w #$F,d2
move.b x_radius(a0),d0
ext.w d0
sub.w d0,d3
lea (Secondary_Angle).w,a4
movea.w #-$10,a3
move.w #$800,d6
bsr.w FindFloor
move.w (sp)+,d0
move.b #$80,d2
bra.w loc_1ECC6
; End of function Sonic_CheckCeiling
; ===========================================================================
; a bit of unused/dead code here
;CheckCeilingDist:
move.w y_pos(a0),d2 ; a0=character
move.w x_pos(a0),d3
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Checks a 16x16 block to find solid ceiling. May check an additional
; 16x16 block up for ceilings.
; d2 = y_pos
; d3 = x_pos
; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top)
; returns relevant block ID in (a1)
; returns distance in d1
; returns angle in d3, or zero if angle was odd
; loc_1EF9E: CheckSlopeDist:
CheckCeilingDist_Part2:
subi.w #$A,d2
eori.w #$F,d2
lea (Primary_Angle).w,a4
movea.w #-$10,a3
move.w #$800,d6
bsr.w FindFloor
move.b #$80,d2
bra.w loc_1ECFE
; End of function CheckCeilingDist
; ---------------------------------------------------------------------------
; Stores a distance to the nearest wall above the object into d1
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1EFBE: ObjHitCeiling:
ObjCheckCeilingDist:
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b y_radius(a0),d0
ext.w d0
sub.w d0,d2
eori.w #$F,d2
lea (Primary_Angle).w,a4
movea.w #-$10,a3
move.w #$800,d6
moveq #$D,d5
bsr.w FindFloor
move.b (Primary_Angle).w,d3
btst #0,d3
beq.s +
move.b #$80,d3
+
rts
; End of function ObjCheckCeilingDist
; ---------------------------------------------------------------------------
; Stores a distance to the nearest wall above Sonic/Tails,
; where "above" = left, into d1
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1EFF6:
CheckLeftCeilingDist:
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b x_radius(a0),d0
ext.w d0
sub.w d0,d2
move.b y_radius(a0),d0
ext.w d0
sub.w d0,d3
eori.w #$F,d3
lea (Primary_Angle).w,a4
movea.w #-$10,a3
move.w #$400,d6
bsr.w FindWall
move.w d1,-(sp)
move.w y_pos(a0),d2
move.w x_pos(a0),d3
moveq #0,d0
move.b x_radius(a0),d0
ext.w d0
add.w d0,d2
move.b y_radius(a0),d0
ext.w d0
sub.w d0,d3
eori.w #$F,d3
lea (Secondary_Angle).w,a4
movea.w #-$10,a3
move.w #$400,d6
bsr.w FindWall
move.w (sp)+,d0
move.b #$40,d2
bra.w loc_1ECC6
; End of function CheckLeftCeilingDist
; ---------------------------------------------------------------------------
; Stores a distance to the nearest wall on the left of Sonic/Tails into d1
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; Checks a 16x16 block to find solid walls. May check an additional
; 16x16 block up for walls.
; d5 = ($c,$d) or ($e,$f) - solidity type bit (L/R/B or top)
; returns relevant block ID in (a1)
; returns distance in d1
; returns angle in d3, or zero if angle was odd
; loc_1F05E: Sonic_HitWall:
CheckLeftWallDist:
move.w y_pos(a0),d2
move.w x_pos(a0),d3
; loc_1F066:
CheckLeftWallDist_Part2:
subi.w #$A,d3
eori.w #$F,d3
lea (Primary_Angle).w,a4
movea.w #-$10,a3
move.w #$400,d6
bsr.w FindWall
move.b #$40,d2
bra.w loc_1ECFE
; End of function CheckLeftWallDist
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_1F086: ObjCheckRightWallDist:
ObjCheckLeftWallDist:
add.w x_pos(a0),d3
move.w y_pos(a0),d2
; Engine bug: colliding with left walls is erratic with this function.
; The cause is this: a missing instruction to flip collision on the found
; 16x16 block; this one:
;eori.w #$F,d3
lea (Primary_Angle).w,a4
move.b #0,(a4)
movea.w #-$10,a3
move.w #$400,d6
moveq #$D,d5
bsr.w FindWall
move.b (Primary_Angle).w,d3
btst #0,d3
beq.s +
move.b #$40,d3
+
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 79 - Star pole / starpost / checkpoint
; ----------------------------------------------------------------------------
; Sprite_1F0B4:
Obj79:
moveq #0,d0
move.b routine(a0),d0
move.w Obj79_Index(pc,d0.w),d1
jmp Obj79_Index(pc,d1.w)
; ===========================================================================
; off_1F0C2: Obj79_States:
Obj79_Index: offsetTable
offsetTableEntry.w Obj79_Init ; 0
offsetTableEntry.w Obj79_Main ; 2
offsetTableEntry.w Obj79_Animate ; 4
offsetTableEntry.w Obj79_Dongle ; 6
offsetTableEntry.w Obj79_Star ; 8
; ===========================================================================
; loc_1F0CC:
Obj79_Init:
addq.b #2,routine(a0) ; => Obj79_Main
move.l #Obj79_MapUnc_1F424,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Checkpoint,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo3_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #8,width_pixels(a0)
move.b #5,priority(a0)
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
bclr #7,2(a2,d0.w)
btst #0,2(a2,d0.w)
bne.s loc_1F120
move.b (Last_star_pole_hit).w,d1
andi.b #$7F,d1
move.b subtype(a0),d2
andi.b #$7F,d2
cmp.b d2,d1
blo.s Obj79_Main
loc_1F120:
bset #0,2(a2,d0.w)
move.b #2,anim(a0)
; loc_1F12C:
Obj79_Main:
tst.w (Debug_placement_mode).w
bne.w Obj79_Animate
lea (MainCharacter).w,a3 ; a3=character
move.b (Last_star_pole_hit).w,d1
bsr.s Obj79_CheckActivation
tst.w (Two_player_mode).w
beq.w Obj79_Animate
lea (Sidekick).w,a3 ; a3=character
move.b (Last_star_pole_hit_2P).w,d1
bsr.s Obj79_CheckActivation
bra.w Obj79_Animate
; ---------------------------------------------------------------------------
; loc_1F154:
Obj79_CheckActivation:
andi.b #$7F,d1
move.b subtype(a0),d2
andi.b #$7F,d2
cmp.b d2,d1
bhs.w loc_1F222
move.w x_pos(a3),d0
sub.w x_pos(a0),d0
addi_.w #8,d0
cmpi.w #$10,d0
bhs.w return_1F220
move.w y_pos(a3),d0
sub.w y_pos(a0),d0
addi.w #$40,d0
cmpi.w #$68,d0
bhs.w return_1F220
move.w #SndID_Checkpoint,d0 ; checkpoint ding-dong sound
jsr (PlaySound).l
jsr (SingleObjLoad).l
bne.s loc_1F206
_move.b #ObjID_Starpost,id(a1) ; load obj79
move.b #6,routine(a1) ; => Obj79_Dongle
move.w x_pos(a0),objoff_30(a1)
move.w y_pos(a0),objoff_32(a1)
subi.w #$14,objoff_32(a1)
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #8,width_pixels(a1)
move.b #4,priority(a1)
move.b #2,mapping_frame(a1)
move.w #$20,objoff_36(a1)
move.w a0,parent(a1)
tst.w (Two_player_mode).w
bne.s loc_1F206
cmpi.b #7,(Emerald_count).w
beq.s loc_1F206
cmpi.w #50,(Ring_count).w
blo.s loc_1F206
bsr.w Obj79_MakeSpecialStars
loc_1F206:
move.b #1,anim(a0)
bsr.w Obj79_SaveData
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
bset #0,2(a2,d0.w)
return_1F220:
rts
; ===========================================================================
loc_1F222:
tst.b anim(a0)
bne.s return_1F22E
move.b #2,anim(a0)
return_1F22E:
rts
; ===========================================================================
; loc_1F230:
Obj79_Animate:
lea (Ani_obj79).l,a1
jsrto (AnimateSprite).l, JmpTo2_AnimateSprite
jmp (MarkObjGone).l
; ===========================================================================
; loc_1F240:
Obj79_Dongle:
subq.w #1,objoff_36(a0)
bpl.s Obj79_MoveDonglyThing
movea.w parent(a0),a1 ; a1=object
cmpi.b #ObjID_Starpost,id(a1)
bne.s +
move.b #2,anim(a1)
move.b #0,mapping_frame(a1)
+
jmp (DeleteObject).l
; ===========================================================================
; loc_1F262:
Obj79_MoveDonglyThing:
move.b angle(a0),d0
subi.b #$10,angle(a0)
subi.b #$40,d0
jsr (CalcSine).l
muls.w #$C00,d1
swap d1
add.w objoff_30(a0),d1
move.w d1,x_pos(a0)
muls.w #$C00,d0
swap d0
add.w objoff_32(a0),d0
move.w d0,y_pos(a0)
jmp (MarkObjGone).l
; ===========================================================================
; hit a starpost / save checkpoint
; loc_1F298:
Obj79_SaveData:
cmpa.w #MainCharacter,a3 ; is it player 1?
bne.w Obj79_SaveDataPlayer2 ; if not, branch
move.b subtype(a0),(Last_star_pole_hit).w
move.b (Last_star_pole_hit).w,(Saved_Last_star_pole_hit).w
move.w x_pos(a0),(Saved_x_pos).w
move.w y_pos(a0),(Saved_y_pos).w
move.w (MainCharacter+art_tile).w,(Saved_art_tile).w
move.w (MainCharacter+top_solid_bit).w,(Saved_Solid_bits).w
move.w (Ring_count).w,(Saved_Ring_count).w
move.b (Extra_life_flags).w,(Saved_Extra_life_flags).w
move.l (Timer).w,(Saved_Timer).w
move.b (Dynamic_Resize_Routine).w,(Saved_Dynamic_Resize_Routine).w
move.w (Camera_Max_Y_pos_now).w,(Saved_Camera_Max_Y_pos).w
move.w (Camera_X_pos).w,(Saved_Camera_X_pos).w
move.w (Camera_Y_pos).w,(Saved_Camera_Y_pos).w
move.w (Camera_BG_X_pos).w,(Saved_Camera_BG_X_pos).w
move.w (Camera_BG_Y_pos).w,(Saved_Camera_BG_Y_pos).w
move.w (Camera_BG2_X_pos).w,(Saved_Camera_BG2_X_pos).w
move.w (Camera_BG2_Y_pos).w,(Saved_Camera_BG2_Y_pos).w
move.w (Camera_BG3_X_pos).w,(Saved_Camera_BG3_X_pos).w
move.w (Camera_BG3_Y_pos).w,(Saved_Camera_BG3_Y_pos).w
move.w (Water_Level_2).w,(Saved_Water_Level).w
move.b (Water_routine).w,(Saved_Water_routine).w
move.b (Water_fullscreen_flag).w,(Saved_Water_move).w
rts
; ===========================================================================
; second player hit a checkpoint in 2-player mode
; loc_1F326:
Obj79_SaveDataPlayer2:
move.b subtype(a0),(Last_star_pole_hit_2P).w
move.b (Last_star_pole_hit_2P).w,(Saved_Last_star_pole_hit_2P).w
move.w x_pos(a0),(Saved_x_pos_2P).w
move.w y_pos(a0),(Saved_y_pos_2P).w
move.w (Sidekick+art_tile).w,(Saved_art_tile_2P).w
move.w (Sidekick+top_solid_bit).w,(Saved_Solid_bits_2P).w
move.w (Ring_count_2P).w,(Saved_Ring_count_2P).w
move.b (Extra_life_flags_2P).w,(Saved_Extra_life_flags_2P).w
move.l (Timer_2P).w,(Saved_Timer_2P).w
rts
; ===========================================================================
; continue from a starpost / load checkpoint
; loc_1F35E:
Obj79_LoadData:
move.b (Saved_Last_star_pole_hit).w,(Last_star_pole_hit).w
move.w (Saved_x_pos).w,(MainCharacter+x_pos).w
move.w (Saved_y_pos).w,(MainCharacter+y_pos).w
move.w (Saved_Ring_count).w,(Ring_count).w
move.b (Saved_Extra_life_flags).w,(Extra_life_flags).w
clr.w (Ring_count).w
clr.b (Extra_life_flags).w
move.l (Saved_Timer).w,(Timer).w
move.b #59,(Timer_frame).w
subq.b #1,(Timer_second).w
move.w (Saved_art_tile).w,(MainCharacter+art_tile).w
move.w (Saved_Solid_bits).w,(MainCharacter+top_solid_bit).w
move.b (Saved_Dynamic_Resize_Routine).w,(Dynamic_Resize_Routine).w
move.b (Saved_Water_routine).w,(Water_routine).w
move.w (Saved_Camera_Max_Y_pos).w,(Camera_Max_Y_pos_now).w
move.w (Saved_Camera_Max_Y_pos).w,(Camera_Max_Y_pos).w
move.w (Saved_Camera_X_pos).w,(Camera_X_pos).w
move.w (Saved_Camera_Y_pos).w,(Camera_Y_pos).w
move.w (Saved_Camera_BG_X_pos).w,(Camera_BG_X_pos).w
move.w (Saved_Camera_BG_Y_pos).w,(Camera_BG_Y_pos).w
move.w (Saved_Camera_BG2_X_pos).w,(Camera_BG2_X_pos).w
move.w (Saved_Camera_BG2_Y_pos).w,(Camera_BG2_Y_pos).w
move.w (Saved_Camera_BG3_X_pos).w,(Camera_BG3_X_pos).w
move.w (Saved_Camera_BG3_Y_pos).w,(Camera_BG3_Y_pos).w
tst.b (Water_flag).w ; does the level have water?
beq.s + ; if not, branch to skip loading water stuff
move.w (Saved_Water_Level).w,(Water_Level_2).w
move.b (Saved_Water_routine).w,(Water_routine).w
move.b (Saved_Water_move).w,(Water_fullscreen_flag).w
+
tst.b (Last_star_pole_hit).w
bpl.s return_1F412
move.w (Saved_x_pos).w,d0
subi.w #$A0,d0
move.w d0,(Camera_Min_X_pos).w
return_1F412:
rts
; ===========================================================================
; animation script
; off_1F414:
Ani_obj79: offsetTable
offsetTableEntry.w byte_1F41A ; 0
offsetTableEntry.w byte_1F41D ; 1
offsetTableEntry.w byte_1F420 ; 2
byte_1F41A:
dc.b $F, 0,$FF
rev02even
byte_1F41D:
dc.b $F, 1,$FF
rev02even
byte_1F420:
dc.b 3, 0, 4,$FF
even
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj79_MapUnc_1F424: BINCLUDE "mappings/sprite/obj79_a.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj79_MapUnc_1F4A0: BINCLUDE "mappings/sprite/obj79_b.bin"
; ===========================================================================
; loc_1F4C4:
Obj79_MakeSpecialStars:
moveq #4-1,d1 ; execute the loop 4 times (1 for each star)
moveq #0,d2
- bsr.w SingleObjLoad2
bne.s + ; rts
_move.b id(a0),id(a1) ; load obj79
move.l #Obj79_MapUnc_1F4A0,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_Checkpoint,0,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #8,routine(a1) ; => Obj79_Star
move.w x_pos(a0),d0
move.w d0,x_pos(a1)
move.w d0,objoff_30(a1)
move.w y_pos(a0),d0
subi.w #$30,d0
move.w d0,y_pos(a1)
move.w d0,objoff_32(a1)
move.b priority(a0),priority(a1)
move.b #8,width_pixels(a1)
move.b #1,mapping_frame(a1)
move.w #-$400,x_vel(a1)
move.w #0,y_vel(a1)
move.w d2,objoff_34(a1) ; set the angle
addi.w #$40,d2 ; increase the angle for next time
dbf d1,- ; loop
+
rts
; ===========================================================================
; loc_1F536:
Obj79_Star:
move.b collision_property(a0),d0
beq.w loc_1F554
andi.b #1,d0
beq.s +
move.b #1,(SpecialStage_flag_2P).w
move.b #GameModeID_SpecialStage,(Game_Mode).w ; => SpecialStage
+
clr.b collision_property(a0)
loc_1F554:
addi.w #$A,objoff_34(a0)
move.w objoff_34(a0),d0
andi.w #$FF,d0
jsr (CalcSine).l
asr.w #5,d0
asr.w #3,d1
move.w d1,d3
move.w objoff_34(a0),d2
andi.w #$3E0,d2
lsr.w #5,d2
moveq #2,d5
moveq #0,d4
cmpi.w #$10,d2
ble.s +
neg.w d1
+
andi.w #$F,d2
cmpi.w #8,d2
ble.s loc_1F594
neg.w d2
andi.w #7,d2
loc_1F594:
lsr.w #1,d2
beq.s +
add.w d1,d4
+
asl.w #1,d1
dbf d5,loc_1F594
asr.w #4,d4
add.w d4,d0
addq.w #1,objoff_36(a0)
move.w objoff_36(a0),d1
cmpi.w #$80,d1
beq.s loc_1F5BE
bgt.s loc_1F5C4
loc_1F5B4:
muls.w d1,d0
muls.w d1,d3
asr.w #7,d0
asr.w #7,d3
bra.s loc_1F5D6
; ===========================================================================
loc_1F5BE:
move.b #$D8,collision_flags(a0)
loc_1F5C4:
cmpi.w #$180,d1
ble.s loc_1F5D6
neg.w d1
addi.w #$200,d1
bmi.w JmpTo10_DeleteObject
bra.s loc_1F5B4
; ===========================================================================
loc_1F5D6:
move.w objoff_30(a0),d2
add.w d3,d2
move.w d2,x_pos(a0)
move.w objoff_32(a0),d2
add.w d0,d2
move.w d2,y_pos(a0)
addq.b #1,anim_frame(a0)
move.b anim_frame(a0),d0
andi.w #6,d0
lsr.w #1,d0
cmpi.b #3,d0
bne.s +
moveq #1,d0
+
move.b d0,mapping_frame(a0)
jmpto (MarkObjGone).l, JmpTo_MarkObjGone
; ===========================================================================
JmpTo10_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo_MarkObjGone
jmp (MarkObjGone).l
JmpTo2_AnimateSprite
jmp (AnimateSprite).l
JmpTo3_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 7D - Points that can be gotten at the end of an act (leftover from S1) (unused)
; ----------------------------------------------------------------------------
; Sprite_1F624:
Obj7D:
moveq #0,d0
move.b routine(a0),d0
move.w Obj7D_Index(pc,d0.w),d1
jmp Obj7D_Index(pc,d1.w)
; ===========================================================================
; off_1F632: Obj7D_States:
Obj7D_Index: offsetTable
offsetTableEntry.w Obj7D_Init ; 0
offsetTableEntry.w Obj7D_Main ; 2
; ===========================================================================
; loc_1F636:
Obj7D_Init:
moveq #$10,d2
move.w d2,d3
add.w d3,d3
lea (MainCharacter).w,a1 ; a1=character
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d2,d0
cmp.w d3,d0
bhs.s Obj7D_NoAdd
move.w y_pos(a1),d1
sub.w y_pos(a0),d1
add.w d2,d1
cmp.w d3,d1
bhs.s Obj7D_NoAdd
tst.w (Debug_placement_mode).w
bne.s Obj7D_NoAdd
tst.b (SpecialStage_flag_2P).w
bne.s Obj7D_NoAdd
addq.b #2,routine(a0)
move.l #Obj7D_MapUnc_1F6FE,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_EndPoints,0,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo4_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #0,priority(a0)
move.b #$10,width_pixels(a0)
move.b subtype(a0),mapping_frame(a0)
move.w #$77,objoff_30(a0)
move.w #SndID_Bonus,d0
jsr (PlaySound).l
moveq #0,d0
move.b subtype(a0),d0
add.w d0,d0
move.w word_1F6D2(pc,d0.w),d0
jsr (AddPoints).l
Obj7D_NoAdd:
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.s JmpTo11_DeleteObject
rts
; ===========================================================================
JmpTo11_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
word_1F6D2:
dc.w 0
dc.w 1000 ; 1
dc.w 100 ; 2
dc.w 1 ; 3
; ===========================================================================
; loc_1F6DA:
Obj7D_Main:
subq.w #1,objoff_30(a0)
bmi.s JmpTo12_DeleteObject
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.s JmpTo12_DeleteObject
jmp (DisplaySprite).l
; ===========================================================================
JmpTo12_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
; -------------------------------------------------------------------------------
; Unused sprite mappings
; -------------------------------------------------------------------------------
Obj7D_MapUnc_1F6FE: BINCLUDE "mappings/sprite/obj7D.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo4_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 44 - Round bumper from Casino Night Zone
; ----------------------------------------------------------------------------
; Sprite_1F730:
Obj44:
moveq #0,d0
move.b routine(a0),d0
move.w Obj44_Index(pc,d0.w),d1
jmp Obj44_Index(pc,d1.w)
; ===========================================================================
; off_1F73E: Obj44_States:
Obj44_Index: offsetTable
offsetTableEntry.w Obj44_Init ; 0
offsetTableEntry.w Obj44_Main ; 2
; ===========================================================================
; loc_1F742:
Obj44_Init:
addq.b #2,routine(a0) ; => Obj44_Main
move.l #Obj44_MapUnc_1F85A,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CNZRoundBumper,2,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo5_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #1,priority(a0)
move.b #$D7,collision_flags(a0)
; loc_1F770:
Obj44_Main:
move.b collision_property(a0),d0
beq.w loc_1F83E
lea (MainCharacter).w,a1 ; a1=character
bclr #0,collision_property(a0)
beq.s +
bsr.s Obj44_BumpCharacter
+
lea (Sidekick).w,a1 ; a1=character
bclr #1,collision_property(a0)
beq.s +
bsr.s Obj44_BumpCharacter
+
clr.b collision_property(a0)
bra.w loc_1F83E
; ===========================================================================
; loc_1F79C:
Obj44_BumpCharacter:
move.w x_pos(a0),d1
move.w y_pos(a0),d2
sub.w x_pos(a1),d1
sub.w y_pos(a1),d2
jsr (CalcAngle).l
move.b (Timer_frames).w,d1
andi.w #3,d1
add.w d1,d0
jsr (CalcSine).l
muls.w #-$700,d1
asr.l #8,d1
move.w d1,x_vel(a1)
muls.w #-$700,d0
asr.l #8,d0
move.w d0,y_vel(a1)
bset #1,status(a1)
bclr #4,status(a1)
bclr #5,status(a1)
clr.b jumping(a1)
move.b #1,anim(a0)
move.w #SndID_Bumper,d0
jsr (PlaySound).l
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s +
cmpi.b #$8A,2(a2,d0.w)
bhs.s return_1F83C
addq.b #1,2(a2,d0.w)
+
moveq #1,d0
movea.w a1,a3
jsr (AddPoints2).l
bsr.w SingleObjLoad
bne.s return_1F83C
_move.b #ObjID_Points,id(a1) ; load obj29
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.b #4,mapping_frame(a1)
return_1F83C:
rts
; ===========================================================================
loc_1F83E:
lea (Ani_obj44).l,a1
jsrto (AnimateSprite).l, JmpTo3_AnimateSprite
jmpto (MarkObjGone).l, JmpTo2_MarkObjGone
; ===========================================================================
; animation script
; off_1F84C:
Ani_obj44: offsetTable
offsetTableEntry.w byte_1F850 ; 0
offsetTableEntry.w byte_1F853 ; 1
byte_1F850: dc.b $F, 0,$FF
rev02even
byte_1F853: dc.b 3, 1, 0, 1,$FD, 0
even
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj44_MapUnc_1F85A: BINCLUDE "mappings/sprite/obj44.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo2_MarkObjGone
jmp (MarkObjGone).l
JmpTo3_AnimateSprite
jmp (AnimateSprite).l
JmpTo5_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 24 - Bubbles in Aquatic Ruin Zone
; ----------------------------------------------------------------------------
; Sprite_1F8A8:
Obj24:
moveq #0,d0
move.b routine(a0),d0
move.w Obj24_Index(pc,d0.w),d1
jmp Obj24_Index(pc,d1.w)
; ===========================================================================
; off_1F8B6:
Obj24_Index: offsetTable
offsetTableEntry.w Obj24_Init ; 0
offsetTableEntry.w loc_1F924 ; 2
offsetTableEntry.w loc_1F93E ; 4
offsetTableEntry.w loc_1F99E ; 6
offsetTableEntry.w BranchTo_JmpTo15_DeleteObject ; 8
offsetTableEntry.w loc_1F9C0 ; $A
; ===========================================================================
; loc_1F8C2:
Obj24_Init:
addq.b #2,routine(a0)
move.l #Obj24_MapUnc_1FBF6,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_BigBubbles,0,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo6_Adjust2PArtPointer
move.b #$84,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #1,priority(a0)
move.b subtype(a0),d0
bpl.s loc_1F90A
addq.b #8,routine(a0)
andi.w #$7F,d0
move.b d0,objoff_32(a0)
move.b d0,objoff_33(a0)
move.b #6,anim(a0)
bra.w loc_1F9C0
; ===========================================================================
loc_1F90A:
move.b d0,anim(a0)
move.w x_pos(a0),objoff_30(a0)
move.w #-$88,y_vel(a0)
jsr (RandomNumber).l
move.b d0,angle(a0)
loc_1F924:
lea (Ani_obj24).l,a1
jsr (AnimateSprite).l
cmpi.b #6,mapping_frame(a0)
bne.s loc_1F93E
move.b #1,objoff_2E(a0)
loc_1F93E:
move.w (Water_Level_1).w,d0
cmp.w y_pos(a0),d0
blo.s loc_1F956
move.b #6,routine(a0)
addq.b #3,anim(a0)
bra.w loc_1F99E
; ===========================================================================
loc_1F956:
move.b angle(a0),d0
addq.b #1,angle(a0)
andi.w #$7F,d0
lea (Obj0A_WobbleData).l,a1
move.b (a1,d0.w),d0
ext.w d0
add.w objoff_30(a0),d0
move.w d0,x_pos(a0)
tst.b objoff_2E(a0)
beq.s loc_1F988
bsr.w loc_1FB02
cmpi.b #6,routine(a0)
beq.s loc_1F99E
loc_1F988:
jsrto (ObjectMove).l, JmpTo3_ObjectMove
tst.b render_flags(a0)
bpl.s JmpTo13_DeleteObject
jmp (DisplaySprite).l
; ===========================================================================
JmpTo13_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
loc_1F99E:
lea (Ani_obj24).l,a1
jsr (AnimateSprite).l
tst.b render_flags(a0)
bpl.s JmpTo14_DeleteObject
jmp (DisplaySprite).l
; ===========================================================================
JmpTo14_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
if removeJmpTos
JmpTo15_DeleteObject
endif
BranchTo_JmpTo15_DeleteObject
jmpto (DeleteObject).l, JmpTo15_DeleteObject
; ===========================================================================
loc_1F9C0:
tst.w objoff_36(a0)
bne.s loc_1FA22
move.w (Water_Level_1).w,d0
cmp.w y_pos(a0),d0
bhs.w loc_1FACE
tst.b render_flags(a0)
bpl.w loc_1FACE
subq.w #1,objoff_38(a0)
bpl.w loc_1FAC2
move.w #1,objoff_36(a0)
loc_1F9E8:
jsr (RandomNumber).l
move.w d0,d1
andi.w #7,d0
cmpi.w #6,d0
bhs.s loc_1F9E8
move.b d0,objoff_34(a0)
andi.w #$C,d1
lea (byte_1FAF0).l,a1
adda.w d1,a1
move.l a1,objoff_3C(a0)
subq.b #1,objoff_32(a0)
bpl.s BranchTo_loc_1FA2A
move.b objoff_33(a0),objoff_32(a0)
bset #7,objoff_36(a0)
BranchTo_loc_1FA2A
bra.s loc_1FA2A
; ===========================================================================
loc_1FA22:
subq.w #1,objoff_38(a0)
bpl.w loc_1FAC2
loc_1FA2A:
jsr (RandomNumber).l
andi.w #$1F,d0
move.w d0,objoff_38(a0)
bsr.w SingleObjLoad
bne.s loc_1FAA6
_move.b id(a0),id(a1) ; load obj24
move.w x_pos(a0),x_pos(a1)
jsr (RandomNumber).l
andi.w #$F,d0
subq.w #8,d0
add.w d0,x_pos(a1)
move.w y_pos(a0),y_pos(a1)
moveq #0,d0
move.b objoff_34(a0),d0
movea.l objoff_3C(a0),a2 ; a2=object
move.b (a2,d0.w),subtype(a1)
btst #7,objoff_36(a0)
beq.s loc_1FAA6
jsr (RandomNumber).l
andi.w #3,d0
bne.s loc_1FA92
bset #6,objoff_36(a0)
bne.s loc_1FAA6
move.b #2,subtype(a1)
loc_1FA92:
tst.b objoff_34(a0)
bne.s loc_1FAA6
bset #6,objoff_36(a0)
bne.s loc_1FAA6
move.b #2,subtype(a1)
loc_1FAA6:
subq.b #1,objoff_34(a0)
bpl.s loc_1FAC2
jsr (RandomNumber).l
andi.w #$7F,d0
addi.w #$80,d0
add.w d0,objoff_38(a0)
clr.w objoff_36(a0)
loc_1FAC2:
lea (Ani_obj24).l,a1
jsr (AnimateSprite).l
loc_1FACE:
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w JmpTo15_DeleteObject
move.w (Water_Level_1).w,d0
cmp.w y_pos(a0),d0
blo.w JmpTo7_DisplaySprite
rts
if removeJmpTos
JmpTo7_DisplaySprite
jmp (DisplaySprite).l
endif
; ===========================================================================
byte_1FAF0:
dc.b 0
dc.b 1 ; 1
dc.b 0 ; 2
dc.b 0 ; 3
dc.b 0 ; 4
dc.b 0 ; 5
dc.b 1 ; 6
dc.b 0 ; 7
dc.b 0 ; 8
dc.b 0 ; 9
dc.b 0 ; 10
dc.b 1 ; 11
dc.b 0 ; 12
dc.b 1 ; 13
dc.b 0 ; 14
dc.b 0 ; 15
dc.b 1 ; 16
dc.b 0 ; 17
; ===========================================================================
loc_1FB02:
lea (MainCharacter).w,a1 ; a1=character
bsr.s loc_1FB0C
lea (Sidekick).w,a1 ; a1=character
loc_1FB0C:
tst.b obj_control(a1)
bmi.w return_1FBCA
move.w x_pos(a1),d0
move.w x_pos(a0),d1
subi.w #$10,d1
cmp.w d0,d1
bhs.w return_1FBCA
addi.w #$20,d1
cmp.w d0,d1
blo.w return_1FBCA
move.w y_pos(a1),d0
move.w y_pos(a0),d1
cmp.w d0,d1
bhs.w return_1FBCA
addi.w #$10,d1
cmp.w d0,d1
blo.w return_1FBCA
bsr.w ResumeMusic
move.w #SndID_InhalingBubble,d0
jsr (PlaySound).l
clr.w x_vel(a1)
clr.w y_vel(a1)
clr.w inertia(a1)
move.b #AniIDSonAni_Bubble,anim(a1)
move.w #$23,move_lock(a1)
move.b #0,jumping(a1)
bclr #5,status(a1)
bclr #4,status(a1)
btst #2,status(a1)
beq.w loc_1FBB8
cmpi.b #1,(a1)
bne.s loc_1FBA8
bclr #2,status(a1)
move.b #$13,y_radius(a1)
move.b #9,x_radius(a1)
subq.w #5,y_pos(a1)
bra.s loc_1FBB8
; ===========================================================================
loc_1FBA8:
move.b #$F,y_radius(a1)
move.b #9,x_radius(a1)
subq.w #1,y_pos(a1)
loc_1FBB8:
cmpi.b #6,routine(a0)
beq.s return_1FBCA
move.b #6,routine(a0)
addq.b #3,anim(a0)
return_1FBCA:
rts
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite animations
; -------------------------------------------------------------------------------
; animation script
; off_1FBCC:
Ani_obj24: offsetTable
offsetTableEntry.w byte_1FBDA ; 0
offsetTableEntry.w byte_1FBDF ; 1
offsetTableEntry.w byte_1FBE5 ; 2
offsetTableEntry.w byte_1FBEC ; 3
offsetTableEntry.w byte_1FBEC ; 4
offsetTableEntry.w byte_1FBEE ; 5
offsetTableEntry.w byte_1FBF2 ; 6
byte_1FBDA: dc.b $E, 0, 1, 2,$FC
rev02even
byte_1FBDF: dc.b $E, 1, 2, 3, 4,$FC
rev02even
byte_1FBE5: dc.b $E, 2, 3, 4, 5, 6,$FC
rev02even
byte_1FBEC: dc.b 4,$FC
rev02even
byte_1FBEE: dc.b 4, 6, 7,$FC
rev02even
byte_1FBF2: dc.b $F, $E, $F,$FF
even
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj24_MapUnc_1FBF6: offsetTable
offsetTableEntry.w word_1FC3A ; 0
offsetTableEntry.w word_1FC44 ; 1
offsetTableEntry.w word_1FC44 ; 2
offsetTableEntry.w word_1FC4E ; 3
offsetTableEntry.w word_1FC58 ; 4
offsetTableEntry.w word_1FC62 ; 5
offsetTableEntry.w word_1FC6C ; 6
offsetTableEntry.w word_1FC76 ; 7
offsetTableEntry.w word_1FC98 ; 8
offsetTableEntry.w word_1FC98 ; 9
offsetTableEntry.w word_1FC98 ; $A
offsetTableEntry.w word_1FC98 ; $B
offsetTableEntry.w word_1FC98 ; $C
offsetTableEntry.w word_1FC98 ; $D
offsetTableEntry.w word_1FCA2 ; $E
offsetTableEntry.w word_1FCAC ; $F
offsetTableEntry.w word_1FCB6 ; $10
; -------------------------------------------------------------------------------
; sprite mappings
; merged with the above mappings, can't split to file in a useful way...
; -------------------------------------------------------------------------------
Obj24_MapUnc_1FC18: offsetTable
offsetTableEntry.w word_1FC3A ; 0
offsetTableEntry.w word_1FC44 ; 1
offsetTableEntry.w word_1FC44 ; 2
offsetTableEntry.w word_1FC4E ; 3
offsetTableEntry.w word_1FC58 ; 4
offsetTableEntry.w word_1FC62 ; 5
offsetTableEntry.w word_1FC6C ; 6
offsetTableEntry.w word_1FC76 ; 7
offsetTableEntry.w word_1FCB8 ; 8
offsetTableEntry.w word_1FCB8 ; 9
offsetTableEntry.w word_1FCB8 ; $A
offsetTableEntry.w word_1FCB8 ; $B
offsetTableEntry.w word_1FCB8 ; $C
offsetTableEntry.w word_1FCB8 ; $D
offsetTableEntry.w word_1FCA2 ; $E
offsetTableEntry.w word_1FCAC ; $F
offsetTableEntry.w word_1FCB6 ; $10
word_1FC3A:
dc.w 1
dc.w $FC00, $008D, $0046, $FFFC
word_1FC44:
dc.w 1
dc.w $FC00, $008E, $0047, $FFFC
word_1FC4E:
dc.w 1
dc.w $F805, $008F, $0047, $FFF8
word_1FC58:
dc.w 1
dc.w $F805, $0093, $0049, $FFF8
word_1FC62:
dc.w 1
dc.w $F40A, $001C, $000E, $FFF4
word_1FC6C:
dc.w 1
dc.w $F00F, $0008, $0004, $FFF0
word_1FC76:
dc.w 4
dc.w $F005, $0018, $000C, $FFF0
dc.w $F005, $0818, $080C, $0000
dc.w $0005, $1018, $100C, $FFF0
dc.w $0005, $1818, $180C, $0000
word_1FC98:
dc.w 1
dc.w $F406, $1F41, $1BA0, $FFF8
word_1FCA2:
dc.w 1
dc.w $F805, $0000, $0000, $FFF8
word_1FCAC:
dc.w 1
dc.w $F805, $0004, $0002, $FFF8
word_1FCB6:
dc.w 0
word_1FCB8:
dc.w 1
dc.w $F406, $1F31, $1B98, $FFF8
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo7_DisplaySprite
jmp (DisplaySprite).l
JmpTo15_DeleteObject
jmp (DeleteObject).l
JmpTo6_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
; loc_1FCD6:
JmpTo3_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 03 - Collision plane/layer switcher
; ----------------------------------------------------------------------------
; Sprite_1FCDC:
Obj03:
moveq #0,d0
move.b routine(a0),d0
move.w Obj03_Index(pc,d0.w),d1
jsr Obj03_Index(pc,d1.w)
jmp (MarkObjGone3).l
; ===========================================================================
; off_1FCF0:
Obj03_Index: offsetTable
offsetTableEntry.w Obj03_Init ; 0
offsetTableEntry.w Obj03_MainX ; 2
offsetTableEntry.w Obj03_MainY ; 4
; ===========================================================================
; loc_1FCF6:
Obj03_Init:
addq.b #2,routine(a0) ; => Obj03_MainX
move.l #Obj03_MapUnc_1FFB8,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Ring,1,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo7_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #5,priority(a0)
move.b subtype(a0),d0
btst #2,d0
beq.s Obj03_Init_CheckX
;Obj03_Init_CheckY:
addq.b #2,routine(a0) ; => Obj03_MainY
andi.w #7,d0
move.b d0,mapping_frame(a0)
andi.w #3,d0
add.w d0,d0
move.w word_1FD68(pc,d0.w),objoff_32(a0)
move.w y_pos(a0),d1
lea (MainCharacter).w,a1 ; a1=character
cmp.w y_pos(a1),d1
bhs.s +
move.b #1,objoff_34(a0)
+
lea (Sidekick).w,a1 ; a1=character
cmp.w y_pos(a1),d1
bhs.s +
move.b #1,objoff_35(a0)
+
bra.w Obj03_MainY
; ===========================================================================
word_1FD68:
dc.w $20
dc.w $40 ; 1
dc.w $80 ; 2
dc.w $100 ; 3
; ===========================================================================
; loc_1FD70:
Obj03_Init_CheckX:
andi.w #3,d0
move.b d0,mapping_frame(a0)
add.w d0,d0
move.w word_1FD68(pc,d0.w),objoff_32(a0)
move.w x_pos(a0),d1
lea (MainCharacter).w,a1 ; a1=character
cmp.w x_pos(a1),d1
bhs.s +
move.b #1,objoff_34(a0)
+
lea (Sidekick).w,a1 ; a1=character
cmp.w x_pos(a1),d1
bhs.s +
move.b #1,objoff_35(a0)
+
; loc_1FDA4:
Obj03_MainX:
tst.w (Debug_placement_mode).w
bne.w return_1FEAC
move.w x_pos(a0),d1
lea objoff_34(a0),a2
lea (MainCharacter).w,a1 ; a1=character
bsr.s +
lea (Sidekick).w,a1 ; a1=character
+ tst.b (a2)+
bne.s Obj03_MainX_Alt
cmp.w x_pos(a1),d1
bhi.w return_1FEAC
move.b #1,-1(a2)
move.w y_pos(a0),d2
move.w d2,d3
move.w objoff_32(a0),d4
sub.w d4,d2
add.w d4,d3
move.w y_pos(a1),d4
cmp.w d2,d4
blt.w return_1FEAC
cmp.w d3,d4
bge.w return_1FEAC
move.b subtype(a0),d0
bpl.s +
btst #1,status(a1)
bne.w return_1FEAC
+
btst #0,render_flags(a0)
bne.s +
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
btst #3,d0
beq.s +
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
+
andi.w #drawing_mask,art_tile(a1)
btst #5,d0
beq.s return_1FEAC
ori.w #high_priority,art_tile(a1)
bra.s return_1FEAC
; ===========================================================================
; loc_1FE38:
Obj03_MainX_Alt:
cmp.w x_pos(a1),d1
bls.w return_1FEAC
move.b #0,-1(a2)
move.w y_pos(a0),d2
move.w d2,d3
move.w objoff_32(a0),d4
sub.w d4,d2
add.w d4,d3
move.w y_pos(a1),d4
cmp.w d2,d4
blt.w return_1FEAC
cmp.w d3,d4
bge.w return_1FEAC
move.b subtype(a0),d0
bpl.s +
btst #1,status(a1)
bne.w return_1FEAC
+
btst #0,render_flags(a0)
bne.s +
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
btst #4,d0
beq.s +
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
+
andi.w #drawing_mask,art_tile(a1)
btst #6,d0
beq.s return_1FEAC
ori.w #high_priority,art_tile(a1)
return_1FEAC:
rts
; ===========================================================================
Obj03_MainY:
tst.w (Debug_placement_mode).w
bne.w return_1FFB6
move.w y_pos(a0),d1
lea objoff_34(a0),a2
lea (MainCharacter).w,a1 ; a1=character
bsr.s +
lea (Sidekick).w,a1 ; a1=character
+ tst.b (a2)+
bne.s Obj03_MainY_Alt
cmp.w y_pos(a1),d1
bhi.w return_1FFB6
move.b #1,-1(a2)
move.w x_pos(a0),d2
move.w d2,d3
move.w objoff_32(a0),d4
sub.w d4,d2
add.w d4,d3
move.w x_pos(a1),d4
cmp.w d2,d4
blt.w return_1FFB6
cmp.w d3,d4
bge.w return_1FFB6
move.b subtype(a0),d0
bpl.s +
btst #1,status(a1)
bne.w return_1FFB6
+
btst #0,render_flags(a0)
bne.s +
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
btst #3,d0
beq.s +
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
+
andi.w #drawing_mask,art_tile(a1)
btst #5,d0
beq.s return_1FFB6
ori.w #high_priority,art_tile(a1)
bra.s return_1FFB6
; ===========================================================================
; loc_1FF42:
Obj03_MainY_Alt:
cmp.w y_pos(a1),d1
bls.w return_1FFB6
move.b #0,-1(a2)
move.w x_pos(a0),d2
move.w d2,d3
move.w objoff_32(a0),d4
sub.w d4,d2
add.w d4,d3
move.w x_pos(a1),d4
cmp.w d2,d4
blt.w return_1FFB6
cmp.w d3,d4
bge.w return_1FFB6
move.b subtype(a0),d0
bpl.s +
btst #1,status(a1)
bne.w return_1FFB6
+
btst #0,render_flags(a0)
bne.s +
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
btst #4,d0
beq.s +
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
+
andi.w #drawing_mask,art_tile(a1)
btst #6,d0
beq.s return_1FFB6
ori.w #high_priority,art_tile(a1)
return_1FFB6:
rts
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj03_MapUnc_1FFB8: BINCLUDE "mappings/sprite/obj03.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo7_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 0B - Section of pipe that tips you off from CPZ
; ----------------------------------------------------------------------------
; Sprite_2009C:
Obj0B:
moveq #0,d0
move.b routine(a0),d0
move.w Obj0B_Index(pc,d0.w),d1
jmp Obj0B_Index(pc,d1.w)
; ===========================================================================
; off_200AA:
Obj0B_Index: offsetTable
offsetTableEntry.w Obj0B_Init ; 0
offsetTableEntry.w loc_20104 ; 2
offsetTableEntry.w loc_20112 ; 4
; ===========================================================================
obj0B_duration_current = objoff_30
obj0B_duration_initial = objoff_32
obj0B_delay = objoff_36
; loc_200B0:
Obj0B_Init:
addq.b #2,routine(a0)
move.l #Obj0B_MapUnc_201A0,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CPZAnimatedBits,3,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo8_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #4,priority(a0)
moveq #0,d0
move.b subtype(a0),d0
andi.w #$F0,d0
addi.w #$10,d0
move.w d0,d1
subq.w #1,d0
move.w d0,obj0B_duration_current(a0)
move.w d0,obj0B_duration_initial(a0)
moveq #0,d0
move.b subtype(a0),d0
andi.w #$F,d0
addq.w #1,d0
lsl.w #4,d0
move.b d0,obj0B_delay(a0)
loc_20104:
move.b (Vint_runcount+3).w,d0
add.b obj0B_delay(a0),d0
bne.s loc_2013C
addq.b #2,routine(a0)
loc_20112:
subq.w #1,obj0B_duration_current(a0)
bpl.s loc_20130
move.w #$7F,obj0B_duration_current(a0)
tst.b anim(a0)
beq.s +
move.w obj0B_duration_initial(a0),obj0B_duration_current(a0)
+
bchg #0,anim(a0)
loc_20130:
lea (Ani_obj0B).l,a1
jsr (AnimateSprite).l
loc_2013C:
tst.b mapping_frame(a0)
bne.s +
moveq #0,d1
move.b width_pixels(a0),d1
moveq #$11,d3
move.w x_pos(a0),d4
bsr.w PlatformObject
jmpto (MarkObjGone).l, JmpTo3_MarkObjGone
; ---------------------------------------------------------------------------
+
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s BranchTo_JmpTo3_MarkObjGone
bclr #p1_standing_bit,status(a0)
beq.s +
bclr #3,(MainCharacter+status).w
bset #1,(MainCharacter+status).w
+
bclr #p2_standing_bit,status(a0)
beq.s BranchTo_JmpTo3_MarkObjGone
bclr #3,(Sidekick+status).w
bset #1,(Sidekick+status).w
BranchTo_JmpTo3_MarkObjGone
jmpto (MarkObjGone).l, JmpTo3_MarkObjGone
; ===========================================================================
; animation script
; off_2018C:
Ani_obj0B: offsetTable
offsetTableEntry.w byte_20190 ; 0
offsetTableEntry.w byte_20198 ; 1
byte_20190:
dc.b 7, 0, 1, 2, 3, 4,$FE, 1
byte_20198:
dc.b 7, 4, 3, 2, 1, 0,$FE, 1
even
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj0B_MapUnc_201A0: BINCLUDE "mappings/sprite/obj0B.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo3_MarkObjGone
jmp (MarkObjGone).l
JmpTo8_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 0C - Small floating platform (unused)
; (used in CPZ in the Nick Arcade prototype)
; ----------------------------------------------------------------------------
; Sprite_20210:
Obj0C:
moveq #0,d0
move.b routine(a0),d0
move.w Obj0C_Index(pc,d0.w),d1
jmp Obj0C_Index(pc,d1.w)
; ===========================================================================
; off_2021E
Obj0C_Index: offsetTable
offsetTableEntry.w Obj0C_Init ; 0
offsetTableEntry.w Obj0C_Main ; 2
; ===========================================================================
; loc_20222:
Obj0C_Init:
addq.b #2,routine(a0)
move.l #Obj0C_MapUnc_202FA,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_FloatPlatform,3,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo9_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #4,priority(a0)
move.w y_pos(a0),d0
subi.w #$10,d0
move.w d0,objoff_3A(a0)
moveq #0,d0
move.b subtype(a0),d0
andi.w #$F0,d0
addi.w #$10,d0
move.w d0,d1
subq.w #1,d0
move.w d0,objoff_30(a0)
move.w d0,objoff_32(a0)
moveq #0,d0
move.b subtype(a0),d0
andi.w #$F,d0
move.b d0,objoff_3E(a0)
move.b d0,objoff_3F(a0)
; loc_20282:
Obj0C_Main:
move.b objoff_3C(a0),d0
beq.s loc_202C0
cmpi.b #$80,d0
bne.s loc_202D0
move.b objoff_3D(a0),d1
bne.s loc_202A2
subq.b #1,objoff_3E(a0)
bpl.s loc_202A2
move.b objoff_3F(a0),objoff_3E(a0)
bra.s loc_202D0
; ===========================================================================
loc_202A2:
addq.b #1,objoff_3D(a0)
move.b d1,d0
jsrto (CalcSine).l, JmpTo5_CalcSine
addi_.w #8,d0
asr.w #6,d0
subi.w #$10,d0
add.w objoff_3A(a0),d0
move.w d0,y_pos(a0)
bra.s loc_202E6
; ===========================================================================
loc_202C0:
move.w (Vint_runcount+2).w,d1
andi.w #$3FF,d1
bne.s loc_202D4
move.b #1,objoff_3D(a0)
loc_202D0:
addq.b #1,objoff_3C(a0)
loc_202D4:
jsrto (CalcSine).l, JmpTo5_CalcSine
addi_.w #8,d1
asr.w #4,d1
add.w objoff_3A(a0),d1
move.w d1,y_pos(a0)
loc_202E6:
moveq #0,d1
move.b width_pixels(a0),d1
moveq #9,d3
move.w x_pos(a0),d4
bsr.w PlatformObject
jmpto (MarkObjGone).l, JmpTo4_MarkObjGone
; ===========================================================================
; ----------------------------------------------------------------------------
; Unused sprite mappings
; ----------------------------------------------------------------------------
Obj0C_MapUnc_202FA: BINCLUDE "mappings/sprite/obj0C.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo4_MarkObjGone
jmp (MarkObjGone).l
JmpTo9_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo5_CalcSine
jmp (CalcSine).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 12 - Emerald from Hidden Palace Zone (unused)
; ----------------------------------------------------------------------------
; Sprite_2031C:
Obj12:
moveq #0,d0
move.b routine(a0),d0
move.w Obj12_Index(pc,d0.w),d1
jmp Obj12_Index(pc,d1.w)
; ===========================================================================
; off_2032A
Obj12_Index: offsetTable
offsetTableEntry.w Obj12_Init ; 0
offsetTableEntry.w Obj12_Main ; 2
; ===========================================================================
; loc_2032E:
Obj12_Init:
addq.b #2,routine(a0)
move.l #Obj12_MapUnc_20382,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_HPZ_Emerald,3,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo10_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$20,width_pixels(a0)
move.b #4,priority(a0)
; loc_20356:
Obj12_Main:
move.w #$20,d1
move.w #$10,d2
move.w #$10,d3
move.w x_pos(a0),d4
bsr.w SolidObject
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w JmpTo16_DeleteObject
jmpto (DisplaySprite).l, JmpTo8_DisplaySprite
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings (unused)
; -------------------------------------------------------------------------------
Obj12_MapUnc_20382: BINCLUDE "mappings/sprite/obj12.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo8_DisplaySprite
jmp (DisplaySprite).l
JmpTo16_DeleteObject
jmp (DeleteObject).l
JmpTo10_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
else
JmpTo16_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 13 - Waterfall in Hidden Palace Zone (unused)
; ----------------------------------------------------------------------------
; Sprite_203AC:
Obj13:
moveq #0,d0
move.b routine(a0),d0
move.w Obj13_Index(pc,d0.w),d1
jmp Obj13_Index(pc,d1.w)
; ===========================================================================
; off_203BA
Obj13_Index: offsetTable
offsetTableEntry.w Obj13_Init ; 0
offsetTableEntry.w Obj13_Main ; 2
offsetTableEntry.w Obj13_ChkDel ; 4
; ===========================================================================
; loc_203C0:
Obj13_Init:
addq.b #2,routine(a0)
move.l #Obj13_MapUnc_20528,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_HPZ_Waterfall,3,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo11_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #1,priority(a0)
move.b #$12,mapping_frame(a0)
bsr.s Obj13_LoadSubObject
move.b #$A0,y_radius(a1)
bset #4,render_flags(a1)
move.l a1,objoff_38(a0)
move.w y_pos(a0),objoff_34(a0)
move.w y_pos(a0),objoff_36(a0)
cmpi.b #$10,subtype(a0)
blo.s loc_2046C
bsr.s Obj13_LoadSubObject
move.l a1,objoff_3C(a0)
move.w y_pos(a0),y_pos(a1)
addi.w #$98,y_pos(a1)
bra.s loc_2046C
; ===========================================================================
; loc_20428:
Obj13_LoadSubObject:
jsr (SingleObjLoad2).l
bne.s + ; rts
_move.b #ObjID_HPZWaterfall,id(a1) ; load obj13
addq.b #4,routine(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.l #Obj13_MapUnc_20528,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_HPZ_Waterfall,3,1),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo2_Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #$10,width_pixels(a1)
move.b #1,priority(a1)
+ rts
; ===========================================================================
loc_2046C:
moveq #0,d1
move.b subtype(a0),d1
move.w objoff_34(a0),d0
subi.w #$78,d0
lsl.w #4,d1
add.w d1,d0
move.w d0,y_pos(a0)
move.w d0,objoff_34(a0)
; loc_20486:
Obj13_Main:
movea.l objoff_38(a0),a1 ; a1=object
move.b #$12,mapping_frame(a0)
move.w objoff_34(a0),d0
move.w (Water_Level_1).w,d1
cmp.w d0,d1
bhs.s +
move.w d1,d0
+
move.w d0,y_pos(a0)
sub.w objoff_36(a0),d0
addi.w #$80,d0
bmi.s loc_204F0
lsr.w #4,d0
move.w d0,d1
cmpi.w #$F,d0
blo.s +
moveq #$F,d0
+
move.b d0,mapping_frame(a1)
cmpi.b #$10,subtype(a0)
blo.s loc_204D8
movea.l objoff_3C(a0),a1 ; a1=object
subi.w #$F,d1
bcc.s +
moveq #0,d1
+
addi.w #$13,d1
move.b d1,mapping_frame(a1)
loc_204D8:
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w JmpTo17_DeleteObject
jmpto (DisplaySprite).l, JmpTo9_DisplaySprite
; ===========================================================================
loc_204F0:
moveq #$13,d0
move.b d0,mapping_frame(a0)
move.b d0,mapping_frame(a1)
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w JmpTo17_DeleteObject
rts
; ===========================================================================
; loc_20510:
Obj13_ChkDel:
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w JmpTo17_DeleteObject
jmpto (DisplaySprite).l, JmpTo9_DisplaySprite
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings (unused)
; -------------------------------------------------------------------------------
Obj13_MapUnc_20528: BINCLUDE "mappings/sprite/obj13.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo9_DisplaySprite
jmp (DisplaySprite).l
JmpTo17_DeleteObject
jmp (DeleteObject).l
JmpTo2_Adjust2PArtPointer2
jmp (Adjust2PArtPointer2).l
JmpTo11_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
else
JmpTo17_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 04 - Surface of the water - water surface
; ----------------------------------------------------------------------------
Obj04:
moveq #0,d0
move.b routine(a0),d0
move.w Obj04_Index(pc,d0.w),d1
jmp Obj04_Index(pc,d1.w)
; ===========================================================================
; off_208EA:
Obj04_Index: offsetTable
offsetTableEntry.w Obj04_Init ; 0
offsetTableEntry.w Obj04_Action ; 2
offsetTableEntry.w Obj04_Action2 ; 4
; ===========================================================================
; loc_208F0: Obj04_Main:
Obj04_Init:
addq.b #2,routine(a0) ; => Obj04_Action
move.l #Obj04_MapUnc_20A0E,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_WaterSurface,0,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo12_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$80,width_pixels(a0)
move.w x_pos(a0),objoff_30(a0)
cmpi.b #aquatic_ruin_zone,(Current_Zone).w
bne.s Obj04_Action
addq.b #2,routine(a0) ; Obj04_Action2
move.l #Obj04_MapUnc_20AFE,mappings(a0)
bra.w Obj04_Action2
; ===========================================================================
; loc_20930:
Obj04_Action:
move.w (Water_Level_1).w,d1
move.w d1,y_pos(a0)
tst.b objoff_32(a0)
bne.s Obj04_Animate
btst #button_start,(Ctrl_1_Press).w ; is Start button pressed?
beq.s loc_20962 ; if not, branch
addq.b #3,mapping_frame(a0) ; use different frames
move.b #1,objoff_32(a0) ; stop animation
bra.s loc_20962
; ===========================================================================
; loc_20952:
Obj04_Animate:
tst.w (Game_paused).w ; is the game paused?
bne.s loc_20962 ; if yes, branch
move.b #0,objoff_32(a0) ; resume animation
subq.b #3,mapping_frame(a0) ; use normal frames
loc_20962:
lea (Anim_obj04).l,a1
moveq #0,d1
move.b anim_frame(a0),d1
move.b (a1,d1.w),mapping_frame(a0)
addq.b #1,anim_frame(a0)
andi.b #$3F,anim_frame(a0)
jmpto (DisplaySprite).l, JmpTo10_DisplaySprite
; ===========================================================================
; water sprite animation 'script' (custom format for this object)
; byte_20982:
Anim_obj04:
dc.b 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1
dc.b 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2
dc.b 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1
dc.b 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0
; ===========================================================================
; loc_209C2:
Obj04_Action2:
move.w (Water_Level_1).w,d1
move.w d1,y_pos(a0)
tst.b objoff_32(a0)
bne.s Obj04_Animate2
btst #button_start,(Ctrl_1_Press).w ; is Start button pressed?
beq.s loc_209F4 ; if not, branch
addq.b #2,mapping_frame(a0) ; use different frames
move.b #1,objoff_32(a0) ; stop animation
bra.s BranchTo_JmpTo10_DisplaySprite
; ===========================================================================
; loc_209E4:
Obj04_Animate2:
tst.w (Game_paused).w ; is the game paused?
bne.s BranchTo_JmpTo10_DisplaySprite ; if yes, branch
move.b #0,objoff_32(a0) ; resume animation
subq.b #2,mapping_frame(a0) ; use normal frames
loc_209F4:
subq.b #1,anim_frame_duration(a0)
bpl.s BranchTo_JmpTo10_DisplaySprite
move.b #5,anim_frame_duration(a0)
addq.b #1,mapping_frame(a0)
andi.b #1,mapping_frame(a0)
BranchTo_JmpTo10_DisplaySprite
jmpto (DisplaySprite).l, JmpTo10_DisplaySprite
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj04_MapUnc_20A0E: BINCLUDE "mappings/sprite/obj04_a.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj04_MapUnc_20AFE: BINCLUDE "mappings/sprite/obj04_b.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 49 - Waterfall from EHZ
; ----------------------------------------------------------------------------
; Sprite_20B9E:
Obj49:
moveq #0,d0
move.b routine(a0),d0
move.w Obj49_Index(pc,d0.w),d1
jmp Obj49_Index(pc,d1.w)
; ===========================================================================
; off_20BAC:
Obj49_Index: offsetTable
offsetTableEntry.w Obj49_Init ; 0
offsetTableEntry.w Obj49_ChkDel ; 2
; ===========================================================================
; loc_20BB0: Obj49_Main:
Obj49_Init:
addq.b #2,routine(a0)
move.l #Obj49_MapUnc_20C50,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Waterfall,1,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo12_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$20,width_pixels(a0)
move.w x_pos(a0),objoff_30(a0)
move.b #0,priority(a0)
move.b #$80,y_radius(a0)
bset #4,render_flags(a0)
; loc_20BEA:
Obj49_ChkDel:
tst.w (Two_player_mode).w
bne.s +
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w JmpTo18_DeleteObject
+
move.w x_pos(a0),d1
move.w d1,d2
subi.w #$40,d1
addi.w #$40,d2
move.b subtype(a0),d3
move.b #0,mapping_frame(a0)
move.w (MainCharacter+x_pos).w,d0
cmp.w d1,d0
blo.s loc_20C36
cmp.w d2,d0
bhs.s loc_20C36
move.b #1,mapping_frame(a0)
add.b d3,mapping_frame(a0)
jmpto (DisplaySprite).l, JmpTo10_DisplaySprite
; ===========================================================================
loc_20C36:
move.w (Sidekick+x_pos).w,d0
cmp.w d1,d0
blo.s Obj49_Display
cmp.w d2,d0
bhs.s Obj49_Display
move.b #1,mapping_frame(a0)
; loc_20C48:
Obj49_Display:
add.b d3,mapping_frame(a0)
jmpto (DisplaySprite).l, JmpTo10_DisplaySprite
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj49_MapUnc_20C50: BINCLUDE "mappings/sprite/obj49.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 31 - Lava collision marker
; ----------------------------------------------------------------------------
; Sprite_20DEC:
Obj31:
moveq #0,d0
move.b routine(a0),d0
move.w Obj31_Index(pc,d0.w),d1
jmp Obj31_Index(pc,d1.w)
; ===========================================================================
; off_20DFA: Obj31_States:
Obj31_Index: offsetTable
offsetTableEntry.w Obj31_Init ; 0
offsetTableEntry.w Obj31_Main ; 2
; ---------------------------------------------------------------------------
; byte_20DFE:
Obj31_CollisionFlagsBySubtype:
dc.b $96 ; 0
dc.b $94 ; 1
dc.b $95 ; 2
dc.b 0 ; 3
; ===========================================================================
; loc_20E02:
Obj31_Init:
addq.b #2,routine(a0) ; => Obj31_Main
moveq #0,d0
move.b subtype(a0),d0
move.b Obj31_CollisionFlagsBySubtype(pc,d0.w),collision_flags(a0)
move.l #Obj31_MapUnc_20E6C,mappings(a0)
tst.w (Debug_placement_mode).w
beq.s +
move.l #Obj31_MapUnc_20E74,mappings(a0)
+
move.w #make_art_tile(ArtTile_ArtNem_Powerups,0,1),art_tile(a0)
move.b #$84,render_flags(a0)
move.b #$80,width_pixels(a0)
move.b #4,priority(a0)
move.b subtype(a0),mapping_frame(a0)
; loc_20E46:
Obj31_Main:
tst.w (Two_player_mode).w
bne.s +
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w JmpTo18_DeleteObject
+
tst.w (Debug_placement_mode).w
beq.s + ; rts
jsrto (DisplaySprite).l, JmpTo10_DisplaySprite
+
rts
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite non-mappings
; -------------------------------------------------------------------------------
Obj31_MapUnc_20E6C: BINCLUDE "mappings/sprite/obj31_a.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj31_MapUnc_20E74: BINCLUDE "mappings/sprite/obj31_b.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 74 - Invisible solid block
; ----------------------------------------------------------------------------
; Sprite_20EE0:
Obj74:
moveq #0,d0
move.b routine(a0),d0
move.w Obj74_Index(pc,d0.w),d1
jmp Obj74_Index(pc,d1.w)
; ===========================================================================
; off_20EEE: Obj74_States:
Obj74_Index: offsetTable
offsetTableEntry.w Obj74_Init ; 0
offsetTableEntry.w Obj74_Main ; 2
; ===========================================================================
; loc_20EF2:
Obj74_Init:
addq.b #2,routine(a0) ; => Obj74_Main
move.l #Obj74_MapUnc_20F66,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Powerups,0,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo12_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b subtype(a0),d0
move.b d0,d1
andi.w #$F0,d0
addi.w #$10,d0
lsr.w #1,d0
move.b d0,width_pixels(a0)
andi.w #$F,d1
addq.w #1,d1
lsl.w #3,d1
move.b d1,y_radius(a0)
; loc_20F2E:
Obj74_Main:
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
move.w x_pos(a0),d4
bsr.w SolidObject_Always
tst.w (Two_player_mode).w
bne.s +
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w JmpTo18_DeleteObject
if gameRevision=0
; this object was visible with debug mode in REV00
+
tst.w (Debug_placement_mode).w
beq.s + ; rts
jmp (DisplaySprite).l
endif
+
rts
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj74_MapUnc_20F66: BINCLUDE "mappings/sprite/obj74.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 7C - Big pylon in foreground of CPZ
; ----------------------------------------------------------------------------
; Sprite_20FD2:
Obj7C:
moveq #0,d0
move.b routine(a0),d0
move.w Obj7C_Index(pc,d0.w),d1
jmp Obj7C_Index(pc,d1.w)
; ===========================================================================
; off_20FE0: Obj7C_States:
Obj7C_Index: offsetTable
offsetTableEntry.w Obj7C_Init ; 0
offsetTableEntry.w Obj7C_Main ; 2
; ===========================================================================
; loc_20FE4:
Obj7C_Init:
addq.b #2,routine(a0) ; => Obj7C_Main
move.l #Obj7C_MapUnc_2103C,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CPZMetalThings,2,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo12_Adjust2PArtPointer
move.b #$10,width_pixels(a0)
move.b #7,priority(a0)
; loc_21006:
Obj7C_Main:
move.w (Camera_X_pos).w,d1
andi.w #$3FF,d1
cmpi.w #$2E0,d1
bhs.s + ; rts
asr.w #1,d1
move.w d1,d0
asr.w #1,d1
add.w d1,d0
neg.w d0
move.w d0,x_pixel(a0)
move.w (Camera_Y_pos).w,d1
asr.w #1,d1
andi.w #$3F,d1
neg.w d1
addi.w #$100,d1
move.w d1,y_pixel(a0)
jmpto (DisplaySprite).l, JmpTo10_DisplaySprite
; ---------------------------------------------------------------------------
+ rts
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj7C_MapUnc_2103C: BINCLUDE "mappings/sprite/obj7C.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 27 - An explosion, giving off an animal and 100 points
; ----------------------------------------------------------------------------
; Sprite_21088:
Obj27:
moveq #0,d0
move.b routine(a0),d0
move.w Obj27_Index(pc,d0.w),d1
jmp Obj27_Index(pc,d1.w)
; ===========================================================================
; off_21096: Obj27_States:
Obj27_Index: offsetTable
offsetTableEntry.w Obj27_InitWithAnimal ; 0
offsetTableEntry.w Obj27_Init ; 2
offsetTableEntry.w Obj27_Main ; 4
; ===========================================================================
; loc_2109C: Obj27_Init:
Obj27_InitWithAnimal:
addq.b #2,routine(a0) ; => Obj27_Init
jsrto (SingleObjLoad).l, JmpTo2_SingleObjLoad
bne.s Obj27_Init
_move.b #ObjID_Animal,id(a1) ; load obj28 (Animal and 100 points)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w parent(a0),parent(a1)
; loc_210BE: Obj27_Init2:
Obj27_Init:
addq.b #2,routine(a0) ; => Obj27_Main
move.l #Obj27_MapUnc_21120,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Explosion,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo12_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #1,priority(a0)
move.b #0,collision_flags(a0)
move.b #$C,width_pixels(a0)
move.b #3,anim_frame_duration(a0)
move.b #0,mapping_frame(a0)
move.w #SndID_Explosion,d0
jsr (PlaySound).l
; loc_21102:
Obj27_Main:
subq.b #1,anim_frame_duration(a0)
bpl.s +
move.b #7,anim_frame_duration(a0)
addq.b #1,mapping_frame(a0)
cmpi.b #5,mapping_frame(a0)
beq.w JmpTo18_DeleteObject
+
jmpto (DisplaySprite).l, JmpTo10_DisplaySprite
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj27_MapUnc_21120: BINCLUDE "mappings/sprite/obj27.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 84 - Pinball mode enable/disable
; (used in Casino Night Zone to determine when Sonic should stay in a ball)
; ----------------------------------------------------------------------------
; Sprite_2115C:
Obj84:
moveq #0,d0
move.b routine(a0),d0
move.w Obj84_Index(pc,d0.w),d1
jsr Obj84_Index(pc,d1.w)
jmp (MarkObjGone3).l
; ===========================================================================
; off_21170: Obj84_States:
Obj84_Index: offsetTable
offsetTableEntry.w Obj84_Init ; 0
offsetTableEntry.w Obj84_MainX ; 2
offsetTableEntry.w Obj84_MainY ; 4
; ===========================================================================
; loc_21176:
Obj84_Init:
addq.b #2,routine(a0) ; => Obj84_MainX
move.l #Obj03_MapUnc_1FFB8,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Ring,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo12_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #5,priority(a0)
move.b subtype(a0),d0
btst #2,d0
beq.s Obj84_Init_CheckX
addq.b #2,routine(a0) ; => Obj84_MainY
andi.w #7,d0
move.b d0,mapping_frame(a0)
andi.w #3,d0
add.w d0,d0
move.w word_211E8(pc,d0.w),objoff_32(a0)
move.w y_pos(a0),d1
lea (MainCharacter).w,a1 ; a1=character
cmp.w y_pos(a1),d1
bhs.s +
move.b #1,objoff_34(a0)
+
lea (Sidekick).w,a1 ; a1=character
cmp.w y_pos(a1),d1
bhs.s +
move.b #1,objoff_35(a0)
+
bra.w Obj84_MainY
; ===========================================================================
word_211E8:
dc.w $20
dc.w $40 ; 1
dc.w $80 ; 2
dc.w $100 ; 3
; ===========================================================================
; loc_211F0:
Obj84_Init_CheckX:
andi.w #3,d0
move.b d0,mapping_frame(a0)
add.w d0,d0
move.w word_211E8(pc,d0.w),objoff_32(a0)
move.w x_pos(a0),d1
lea (MainCharacter).w,a1 ; a1=character
cmp.w x_pos(a1),d1
bhs.s +
move.b #1,objoff_34(a0)
+
lea (Sidekick).w,a1 ; a1=character
cmp.w x_pos(a1),d1
bhs.s Obj84_MainX
move.b #1,objoff_35(a0)
; loc_21224:
Obj84_MainX:
tst.w (Debug_placement_mode).w
bne.s return_21284
move.w x_pos(a0),d1
lea objoff_34(a0),a2 ; a2=object
lea (MainCharacter).w,a1 ; a1=character
bsr.s +
lea (Sidekick).w,a1 ; a1=character
cmpi.w #4,(Tails_CPU_routine).w ; TailsCPU_Flying
beq.s return_21284
+ tst.b (a2)+
bne.s Obj84_MainX_Alt
cmp.w x_pos(a1),d1
bhi.s return_21284
move.b #1,-1(a2)
move.w y_pos(a0),d2
move.w d2,d3
move.w objoff_32(a0),d4
sub.w d4,d2
add.w d4,d3
move.w y_pos(a1),d4
cmp.w d2,d4
blo.s return_21284
cmp.w d3,d4
bhs.s return_21284
btst #0,render_flags(a0)
bne.s +
move.b #1,pinball_mode(a1) ; enable must-roll "pinball mode"
bra.s loc_212C4
; ---------------------------------------------------------------------------
+ move.b #0,pinball_mode(a1) ; disable pinball mode
return_21284:
rts
; ===========================================================================
; loc_21286:
Obj84_MainX_Alt:
cmp.w x_pos(a1),d1
bls.s return_21284
move.b #0,-1(a2)
move.w y_pos(a0),d2
move.w d2,d3
move.w objoff_32(a0),d4
sub.w d4,d2
add.w d4,d3
move.w y_pos(a1),d4
cmp.w d2,d4
blo.s return_21284
cmp.w d3,d4
bhs.s return_21284
btst #0,render_flags(a0)
beq.s +
move.b #1,pinball_mode(a1)
bra.s loc_212C4
; ---------------------------------------------------------------------------
+ move.b #0,pinball_mode(a1)
rts
; ===========================================================================
loc_212C4:
btst #2,status(a1)
beq.s +
rts
; ---------------------------------------------------------------------------
+ bset #2,status(a1)
move.b #$E,y_radius(a1)
move.b #7,x_radius(a1)
move.b #AniIDSonAni_Roll,anim(a1)
addq.w #5,y_pos(a1)
move.w #SndID_Roll,d0
jsr (PlaySound).l
rts
; ===========================================================================
; loc_212F6:
Obj84_MainY:
tst.w (Debug_placement_mode).w
bne.s return_21350
move.w y_pos(a0),d1
lea objoff_34(a0),a2 ; a2=object
lea (MainCharacter).w,a1 ; a1=character
bsr.s +
lea (Sidekick).w,a1 ; a1=character
+
tst.b (a2)+
bne.s Obj84_MainY_Alt
cmp.w y_pos(a1),d1
bhi.s return_21350
move.b #1,-1(a2)
move.w x_pos(a0),d2
move.w d2,d3
move.w objoff_32(a0),d4
sub.w d4,d2
add.w d4,d3
move.w x_pos(a1),d4
cmp.w d2,d4
blo.s return_21350
cmp.w d3,d4
bhs.s return_21350
btst #0,render_flags(a0)
bne.s +
move.b #1,pinball_mode(a1)
bra.w loc_212C4
; ---------------------------------------------------------------------------
+ move.b #0,pinball_mode(a1)
return_21350:
rts
; ===========================================================================
; loc_21352:
Obj84_MainY_Alt:
cmp.w y_pos(a1),d1
bls.s return_21350
move.b #0,-1(a2)
move.w x_pos(a0),d2
move.w d2,d3
move.w objoff_32(a0),d4
sub.w d4,d2
add.w d4,d3
move.w x_pos(a1),d4
cmp.w d2,d4
blo.s return_21350
cmp.w d3,d4
bhs.s return_21350
btst #0,render_flags(a0)
beq.s +
move.b #1,pinball_mode(a1)
bra.w loc_212C4
; ---------------------------------------------------------------------------
+ move.b #0,pinball_mode(a1)
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 8B - Cycling palette switcher from Wing Fortress Zone
; ----------------------------------------------------------------------------
; Sprite_21392:
Obj8B:
moveq #0,d0
move.b routine(a0),d0
move.w Obj8B_Index(pc,d0.w),d1
jsr Obj8B_Index(pc,d1.w)
jmp (MarkObjGone3).l
; ===========================================================================
; off_213A6:
Obj8B_Index: offsetTable
offsetTableEntry.w Obj8B_Init ; 0
offsetTableEntry.w Obj8B_Main ; 2
; ===========================================================================
word_213AA:
dc.w $20
dc.w $40 ; 1
dc.w $80 ; 2
dc.w $100 ; 3
; ===========================================================================
; loc_213B2:
Obj8B_Init:
addq.b #2,routine(a0)
move.l #Obj03_MapUnc_1FFB8,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Ring,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo12_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #5,priority(a0)
move.b subtype(a0),d0
andi.w #3,d0
move.b d0,mapping_frame(a0)
add.w d0,d0
move.w word_213AA(pc,d0.w),objoff_32(a0)
move.w x_pos(a0),d1
lea (MainCharacter).w,a1 ; a1=character
cmp.w x_pos(a1),d1
bhs.s loc_21402
move.b #1,objoff_34(a0)
loc_21402:
lea (Sidekick).w,a1 ; a1=character
cmp.w x_pos(a1),d1
bhs.s Obj8B_Main
move.b #1,objoff_35(a0)
; loc_21412:
Obj8B_Main:
tst.w (Debug_placement_mode).w
bne.s return_2146A
move.w x_pos(a0),d1
lea objoff_34(a0),a2 ; a2=object
lea (MainCharacter).w,a1 ; a1=character
bsr.s loc_2142A
lea (Sidekick).w,a1 ; a1=character
loc_2142A:
tst.b (a2)+
bne.s loc_2146C
cmp.w x_pos(a1),d1
bhi.s return_2146A
move.b #1,-1(a2)
move.w y_pos(a0),d2
move.w d2,d3
move.w objoff_32(a0),d4
sub.w d4,d2
add.w d4,d3
move.w y_pos(a1),d4
cmp.w d2,d4
blo.s return_2146A
cmp.w d3,d4
bhs.s return_2146A
btst #0,render_flags(a0)
bne.s +
move.b #1,(WFZ_SCZ_Fire_Toggle).w
rts
; ---------------------------------------------------------------------------
+ move.b #0,(WFZ_SCZ_Fire_Toggle).w
return_2146A:
rts
; ===========================================================================
loc_2146C:
cmp.w x_pos(a1),d1
bls.s return_2146A
move.b #0,-1(a2)
move.w y_pos(a0),d2
move.w d2,d3
move.w objoff_32(a0),d4
sub.w d4,d2
add.w d4,d3
move.w y_pos(a1),d4
cmp.w d2,d4
blo.s return_2146A
cmp.w d3,d4
bhs.s return_2146A
btst #0,render_flags(a0)
beq.s +
move.b #1,(WFZ_SCZ_Fire_Toggle).w
rts
; ---------------------------------------------------------------------------
+ move.b #0,(WFZ_SCZ_Fire_Toggle).w
rts
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
; loc_214AC:
JmpTo10_DisplaySprite
jmp (DisplaySprite).l
JmpTo18_DeleteObject
jmp (DeleteObject).l
JmpTo2_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo12_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
else
JmpTo18_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 06 - Rotating cylinder in MTZ, twisting spiral pathway in EHZ
; ----------------------------------------------------------------------------
; Sprite_214C4:
Obj06:
moveq #0,d0
move.b routine(a0),d0
move.w Obj06_Index(pc,d0.w),d1
jsr Obj06_Index(pc,d1.w)
tst.w (Two_player_mode).w
beq.s Obj06_ChkDel
rts
; ---------------------------------------------------------------------------
; seems to be an optimization to delete the object the instant it goes offscreen
; only in 1-player mode, because it would screw up the other player
; loc_214DA:
Obj06_ChkDel:
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.s JmpTo19_DeleteObject
rts
; ---------------------------------------------------------------------------
JmpTo19_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
; off_214F4:
Obj06_Index: offsetTable
offsetTableEntry.w Obj06_Init ; 0
offsetTableEntry.w Obj06_Spiral ; 2
offsetTableEntry.w Obj06_Cylinder ; 4
; ===========================================================================
; loc_214FA:
Obj06_Init:
addq.b #2,routine(a0) ; => Obj06_Spiral
move.b #$D0,width_pixels(a0)
tst.b subtype(a0)
bpl.s Obj06_Spiral
addq.b #2,routine(a0) ; => Obj06_Cylinder
bra.w Obj06_Cylinder
; ===========================================================================
; spiral pathway from EHZ
; loc_21512:
Obj06_Spiral:
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
bsr.s +
lea (Sidekick).w,a1 ; a1=character
addq.b #1,d6
+
btst d6,status(a0)
bne.w loc_215C0
btst #1,status(a1)
bne.w return_215BE
btst #3,status(a1)
bne.s loc_21580
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
tst.w x_vel(a1)
bmi.s loc_21556
cmpi.w #-$C0,d0
bgt.s return_215BE
cmpi.w #-$D0,d0
blt.s return_215BE
bra.s loc_21562
; ---------------------------------------------------------------------------
loc_21556:
cmpi.w #$C0,d0
blt.s return_215BE
cmpi.w #$D0,d0
bgt.s return_215BE
loc_21562:
move.w y_pos(a1),d1
sub.w y_pos(a0),d1
subi.w #$10,d1
cmpi.w #$30,d1
bhs.s return_215BE
tst.b obj_control(a1)
bne.s return_215BE
bsr.w RideObject_SetRide
rts
; ---------------------------------------------------------------------------
loc_21580:
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
tst.w x_vel(a1)
bmi.s loc_2159C
cmpi.w #-$B0,d0
bgt.s return_215BE
cmpi.w #-$C0,d0
blt.s return_215BE
bra.s loc_215A8
; ---------------------------------------------------------------------------
loc_2159C:
cmpi.w #$B0,d0
blt.s return_215BE
cmpi.w #$C0,d0
bgt.s return_215BE
loc_215A8:
move.w y_pos(a1),d1
sub.w y_pos(a0),d1
subi.w #$10,d1
cmpi.w #$30,d1
bhs.s return_215BE
bsr.w RideObject_SetRide
return_215BE:
rts
; ---------------------------------------------------------------------------
loc_215C0:
mvabs.w inertia(a1),d0
cmpi.w #$600,d0
blo.s Obj06_Spiral_CharacterFallsOff
btst #1,status(a1)
bne.s Obj06_Spiral_CharacterFallsOff
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
addi.w #$D0,d0
bmi.s Obj06_Spiral_CharacterFallsOff
cmpi.w #$1A0,d0
blo.s Obj06_Spiral_MoveCharacter
; loc_215EA:
Obj06_Spiral_CharacterFallsOff:
bclr #3,status(a1)
bclr d6,status(a0)
move.b #0,flips_remaining(a1)
move.b #4,flip_speed(a1)
rts
; ---------------------------------------------------------------------------
; loc_21602:
Obj06_Spiral_MoveCharacter:
btst #3,status(a1)
beq.s return_215BE
move.b Obj06_CosineTable(pc,d0.w),d1
ext.w d1
move.w y_pos(a0),d2
add.w d1,d2
moveq #0,d1
move.b y_radius(a1),d1
subi.w #$13,d1
sub.w d1,d2
move.w d2,y_pos(a1)
lsr.w #3,d0
andi.w #$3F,d0
move.b Obj06_FlipAngleTable(pc,d0.w),flip_angle(a1)
rts
; ===========================================================================
; byte_21634:
Obj06_FlipAngleTable:
dc.b 0, 0, 1, 1; 4
dc.b $16, $16, $16, $16; 8
dc.b $2C, $2C, $2C, $2C; 12
dc.b $42, $42, $42, $42; 16
dc.b $58, $58, $58, $58; 20
dc.b $6E, $6E, $6E, $6E; 24
dc.b $84, $84, $84, $84; 28
dc.b $9A, $9A, $9A, $9A; 32
dc.b $B0, $B0, $B0, $B0; 36
dc.b $C6, $C6, $C6, $C6; 40
dc.b $DC, $DC, $DC, $DC; 44
dc.b $F2, $F2, $F2, $F2; 48
dc.b 1, 1, 0, 0; 52
; byte_21668:
Obj06_CosineTable:
dc.b 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32; 16
dc.b 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 31, 31; 32
dc.b 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 30, 30; 48
dc.b 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 28, 28, 28, 28, 27; 64
dc.b 27, 27, 27, 26, 26, 26, 25, 25, 25, 24, 24, 24, 23, 23, 22, 22; 80
dc.b 21, 21, 20, 20, 19, 18, 18, 17, 16, 16, 15, 14, 14, 13, 12, 12; 96
dc.b 11, 10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1; 112
dc.b 0, -1, -2, -2, -3, -4, -4, -5, -6, -7, -7, -8, -9, -9,-10,-10; 128
dc.b -11,-11,-12,-12,-13,-14,-14,-15,-15,-16,-16,-17,-17,-18,-18,-19; 144
dc.b -19,-19,-20,-21,-21,-22,-22,-23,-23,-24,-24,-25,-25,-26,-26,-27; 160
dc.b -27,-28,-28,-28,-29,-29,-30,-30,-30,-31,-31,-31,-32,-32,-32,-33; 176
dc.b -33,-33,-33,-34,-34,-34,-35,-35,-35,-35,-35,-35,-35,-35,-36,-36; 192
dc.b -36,-36,-36,-36,-36,-36,-36,-37,-37,-37,-37,-37,-37,-37,-37,-37; 208
dc.b -37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37; 224
dc.b -37,-37,-37,-37,-36,-36,-36,-36,-36,-36,-36,-35,-35,-35,-35,-35; 240
dc.b -35,-35,-35,-34,-34,-34,-33,-33,-33,-33,-32,-32,-32,-31,-31,-31; 256
dc.b -30,-30,-30,-29,-29,-28,-28,-28,-27,-27,-26,-26,-25,-25,-24,-24; 272
dc.b -23,-23,-22,-22,-21,-21,-20,-19,-19,-18,-18,-17,-16,-16,-15,-14; 288
dc.b -14,-13,-12,-11,-11,-10, -9, -8, -7, -7, -6, -5, -4, -3, -2, -1; 304
dc.b 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 10, 11, 12, 13; 320
dc.b 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21; 336
dc.b 21, 22, 22, 23, 23, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26; 352
dc.b 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29; 368
dc.b 29, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31; 384
dc.b 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32; 400
dc.b 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32; 416
; ===========================================================================
; rotating meshed cage from MTZ
; loc_21808:
Obj06_Cylinder:
lea (MainCharacter).w,a1 ; a1=character
lea (MTZCylinder_Angle_Sonic).w,a2
moveq #p1_standing_bit,d6
bsr.s +
lea (Sidekick).w,a1 ; a1=character
lea (MTZCylinder_Angle_Tails).w,a2
addq.b #1,d6
+
btst d6,status(a0)
bne.w loc_2188C
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
cmpi.w #-$C0,d0
blt.s return_2188A
cmpi.w #$C0,d0
bge.s return_2188A
move.w y_pos(a0),d0
addi.w #$3C,d0
move.w y_pos(a1),d2
move.b y_radius(a1),d1
ext.w d1
add.w d2,d1
addq.w #4,d1
sub.w d1,d0
bhi.s return_2188A
cmpi.w #-$10,d0
blo.s return_2188A
cmpi.b #6,routine(a1)
bhs.s return_2188A
add.w d0,d2
addq.w #3,d2
move.w d2,y_pos(a1)
move.b #1,flip_turned(a1) ; face the other way
bsr.w RideObject_SetRide
move.w #AniIDSonAni_Run,anim(a1)
move.b #0,(a2)
tst.w inertia(a1)
bne.s return_2188A
move.w #1,inertia(a1)
return_2188A:
rts
; ===========================================================================
loc_2188C:
btst #1,status(a1)
bne.s loc_218C6
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
addi.w #$C0,d0
bmi.s loc_218A8
cmpi.w #$180,d0
blo.s loc_218E0
loc_218A8:
bclr #3,status(a1)
bclr d6,status(a0)
move.b #0,flips_remaining(a1)
move.b #4,flip_speed(a1)
bset #1,status(a1)
rts
; ---------------------------------------------------------------------------
loc_218C6:
move.b (a2),d0
addi.b #$20,d0
cmpi.b #$40,d0
bhs.s +
asr y_vel(a1)
bra.s loc_218A8
; ---------------------------------------------------------------------------
+ move.w #0,y_vel(a1)
bra.s loc_218A8
; ===========================================================================
loc_218E0:
btst #3,status(a1)
beq.s return_2188A
move.b (a2),d0
jsrto (CalcSine).l, JmpTo6_CalcSine
muls.w #$2800,d1
swap d1
move.w y_pos(a0),d2
add.w d1,d2
moveq #0,d1
move.b y_radius(a1),d1
subi.w #$13,d1
sub.w d1,d2
move.w d2,y_pos(a1)
move.b (a2),d0
move.b d0,flip_angle(a1)
addq.b #4,(a2)
tst.w inertia(a1)
bne.s return_2191E
move.w #1,inertia(a1)
return_2191E:
rts
; ===========================================================================
if ~~removeJmpTos
JmpTo6_CalcSine
jmp (CalcSine).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 14 - See saw from Hill Top Zone
; ----------------------------------------------------------------------------
; Sprite_21928:
Obj14:
moveq #0,d0
move.b routine(a0),d0
move.w Obj14_Index(pc,d0.w),d1
jsr Obj14_Index(pc,d1.w)
move.w objoff_30(a0),d0
jmpto (MarkObjGone2).l, JmpTo_MarkObjGone2
; ===========================================================================
; off_2193E:
Obj14_Index: offsetTable
offsetTableEntry.w Obj14_Init ; 0
offsetTableEntry.w Obj14_Main ; 2
offsetTableEntry.w return_21A74 ; 4
offsetTableEntry.w Obj14_Ball_Init ; 6
offsetTableEntry.w Obj14_Ball_Main ; 8
offsetTableEntry.w Obj14_Ball_Fly ; $A
; ===========================================================================
; loc_2194A:
Obj14_Init:
addq.b #2,routine(a0)
move.l #Obj14_MapUnc_21CF0,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_HtzSeeSaw,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo13_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #4,priority(a0)
move.b #$30,width_pixels(a0)
move.w x_pos(a0),objoff_30(a0)
tst.b subtype(a0)
bne.s loc_219A4
jsrto (SingleObjLoad2).l, JmpTo3_SingleObjLoad2
bne.s loc_219A4
_move.b #ObjID_Seesaw,id(a1) ; load obj14
addq.b #6,routine(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.b status(a0),status(a1)
move.l a0,objoff_3C(a1)
loc_219A4:
btst #0,status(a0)
beq.s loc_219B2
move.b #2,mapping_frame(a0)
loc_219B2:
move.b mapping_frame(a0),objoff_3A(a0)
Obj14_Main:
move.b objoff_3A(a0),d1
btst #p1_standing_bit,status(a0)
beq.s loc_21A12
moveq #2,d1
lea (MainCharacter).w,a1 ; a1=character
move.w x_pos(a0),d0
sub.w x_pos(a1),d0
bcc.s +
neg.w d0
moveq #0,d1
+
cmpi.w #8,d0
bhs.s +
moveq #1,d1
+
btst #p2_standing_bit,status(a0)
beq.s Obj14_UpdateMappingAndCollision
moveq #2,d2
lea (Sidekick).w,a1 ; a1=character
move.w x_pos(a0),d0
sub.w x_pos(a1),d0
bcc.s +
neg.w d0
moveq #0,d2
+
cmpi.w #8,d0
bhs.s +
moveq #1,d2
+
add.w d2,d1
cmpi.w #3,d1
bne.s +
addq.w #1,d1
+
lsr.w #1,d1
bra.s Obj14_UpdateMappingAndCollision
; ===========================================================================
loc_21A12:
btst #p2_standing_bit,status(a0)
beq.s loc_21A38
moveq #2,d1
lea (Sidekick).w,a1 ; a1=character
move.w x_pos(a0),d0
sub.w x_pos(a1),d0
bcc.s +
neg.w d0
moveq #0,d1
+
cmpi.w #8,d0
bhs.s Obj14_UpdateMappingAndCollision
moveq #1,d1
bra.s Obj14_UpdateMappingAndCollision
; ===========================================================================
loc_21A38:
move.w (MainCharacter+y_vel).w,d0
move.w (Sidekick+y_vel).w,d2
cmp.w d0,d2
blt.s +
move.w d2,d0
+
move.w d0,objoff_38(a0)
; loc_21A4A:
Obj14_UpdateMappingAndCollision:
bsr.w Obj14_SetMapping
lea (byte_21C8E).l,a2
btst #0,mapping_frame(a0)
beq.s +
lea (byte_21CBF).l,a2
+
move.w x_pos(a0),-(sp)
moveq #0,d1
move.b width_pixels(a0),d1
moveq #8,d3
move.w (sp)+,d4
bra.w SlopedPlatform
; ===========================================================================
return_21A74:
rts
; ===========================================================================
; loc_21A76:
Obj14_SetMapping:
move.b mapping_frame(a0),d0
cmp.b d1,d0
beq.s return_21AA0
bhs.s +
addq.b #2,d0
+
subq.b #1,d0
move.b d0,mapping_frame(a0)
move.b d1,objoff_3A(a0)
bclr #0,render_flags(a0)
btst #1,mapping_frame(a0)
beq.s return_21AA0
bset #0,render_flags(a0)
return_21AA0:
rts
; ===========================================================================
; loc_21AA2:
Obj14_Ball_Init:
addq.b #2,routine(a0)
move.l #Obj14_MapUnc_21D7C,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Sol,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo13_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #4,priority(a0)
move.b #$8B,collision_flags(a0)
move.b #$C,width_pixels(a0)
move.w x_pos(a0),objoff_30(a0) ; save seesaw x position
addi.w #$28,x_pos(a0)
addi.w #$10,y_pos(a0)
move.w y_pos(a0),objoff_34(a0) ; save bottom of seesaw y position
btst #0,status(a0)
beq.s Obj14_Ball_Main
subi.w #$50,x_pos(a0)
move.b #2,objoff_3A(a0)
; loc_21AFC:
Obj14_Ball_Main:
bsr.w Obj14_Animate
movea.l objoff_3C(a0),a1 ; a1=parent object (seesaw)
moveq #0,d0
move.b objoff_3A(a0),d0 ; d0 = ball angle - seesaw angle
sub.b objoff_3A(a1),d0
beq.s Obj14_SetBallToRestOnSeeSaw
bcc.s +
neg.b d0
+
move.w #-$818,d1
move.w #-$114,d2
cmpi.b #1,d0
beq.s +
move.w #-$AF0,d1
move.w #-$CC,d2
cmpi.w #$A00,objoff_38(a1) ; check if character y_vel that jumped on
blt.s + ; seesaw > 2560
move.w #-$E00,d1
move.w #-$A0,d2
+
move.w d1,y_vel(a0)
move.w d2,x_vel(a0)
move.w x_pos(a0),d0
sub.w objoff_30(a0),d0
bcc.s +
neg.w x_vel(a0)
+
addq.b #2,routine(a0)
bra.s Obj14_Ball_Fly
; ===========================================================================
; loc_21B56:
Obj14_SetBallToRestOnSeeSaw:
lea (Obj14_YOffsets).l,a2
moveq #0,d0
move.b mapping_frame(a1),d0
move.w #$28,d2
move.w x_pos(a0),d1
sub.w objoff_30(a0),d1
bcc.s +
neg.w d2
addq.w #2,d0
+
add.w d0,d0
move.w objoff_34(a0),d1 ; d1 = bottom of seesaw y position
add.w (a2,d0.w),d1 ; + offset for current angle
move.w d1,y_pos(a0) ; set y position so ball rests on seesaw
add.w objoff_30(a0),d2
move.w d2,x_pos(a0)
clr.w y_sub(a0)
clr.w x_sub(a0)
rts
; ===========================================================================
Obj14_Ball_Fly:
bsr.w Obj14_Animate
tst.w y_vel(a0)
bpl.s loc_21BB6
jsrto (ObjectMoveAndFall).l, JmpTo_ObjectMoveAndFall
move.w objoff_34(a0),d0 ; d0 = bottom of seesaw y position
subi.w #$2F,d0
cmp.w y_pos(a0),d0
bgt.s return_21BB4
jsrto (ObjectMoveAndFall).l, JmpTo_ObjectMoveAndFall
return_21BB4:
rts
; ===========================================================================
loc_21BB6:
jsrto (ObjectMoveAndFall).l, JmpTo_ObjectMoveAndFall
movea.l objoff_3C(a0),a1 ; a1=parent object (seesaw)
lea (Obj14_YOffsets).l,a2
moveq #0,d0
move.b mapping_frame(a1),d0
move.w x_pos(a0),d1
sub.w objoff_30(a0),d1
bcc.s +
addq.w #2,d0
+
add.w d0,d0
move.w objoff_34(a0),d1 ; d1 = bottom of seesaw y position
add.w (a2,d0.w),d1 ; + offset for current angle
cmp.w y_pos(a0),d1 ; return if y position < d1
bgt.s return_21C2A
movea.l objoff_3C(a0),a1 ; a1=parent object (seesaw)
moveq #2,d1 ; d1 = x_vel >= 0 ? 0 : 2
tst.w x_vel(a0)
bmi.s +
moveq #0,d1
+
move.b d1,objoff_3A(a1) ; set seesaw angle to d1
move.b d1,objoff_3A(a0) ; set ball angle to d1
cmp.b mapping_frame(a1),d1
beq.s loc_21C1E
; launch main character if stood on seesaw
lea (MainCharacter).w,a2 ; a2=character
bclr #p1_standing_bit,status(a1)
beq.s +
bsr.s Obj14_LaunchCharacter
+
; launch sidekick if stood on seesaw
lea (Sidekick).w,a2 ; a2=character
bclr #p2_standing_bit,status(a1)
beq.s loc_21C1E
bsr.s Obj14_LaunchCharacter
loc_21C1E:
clr.w x_vel(a0) ; clear ball velocity
clr.w y_vel(a0)
subq.b #2,routine(a0) ; set ball to main state
return_21C2A:
rts
; ===========================================================================
; loc_21C2C:
Obj14_LaunchCharacter:
move.w y_vel(a0),y_vel(a2) ; set character y velocity to inverse of sol
neg.w y_vel(a2) ; y velocity
bset #1,status(a2) ; set character airborne flag
bclr #3,status(a2) ; clear character on object flag
clr.b jumping(a2) ; clear character jumping flag
move.b #AniIDSonAni_Spring,anim(a2) ; set character to spring animation
move.b #2,routine(a2) ; set character to airborne state
move.w #SndID_Spring,d0 ; play spring sound
jmp (PlaySound).l
; ===========================================================================
; heights of the contact point of the ball on the seesaw
; word_21C5C:
Obj14_YOffsets:
dc.w -8, -28, -47, -28, -8 ; low, balanced, high, balanced, low
; ===========================================================================
; loc_21C66:
Obj14_Animate:
move.b (Timer_frames+1).w,d0
andi.b #3,d0
bne.s Obj14_SetSolToFaceMainCharacter
bchg #palette_bit_0,art_tile(a0)
Obj14_SetSolToFaceMainCharacter:
andi.b #$FE,render_flags(a0)
move.w (MainCharacter+x_pos).w,d0
sub.w x_pos(a0),d0
bcs.s return_21C8C
ori.b #1,render_flags(a0)
return_21C8C:
rts
; ===========================================================================
byte_21C8E:
dc.b $14,$14,$16,$18,$1A,$1C,$1A,$18,$16,$14,$13,$12,$11,$10, $F, $E
dc.b $D, $C, $B, $A, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,$FF,$FE; 16
dc.b $FD,$FC,$FB,$FA,$F9,$F8,$F7,$F6,$F5,$F4,$F3,$F2,$F2,$F2,$F2,$F2; 32
dc.b $F2 ; 48
rev02even
byte_21CBF:
dc.b 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
dc.b 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5; 16
dc.b 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5; 32
even
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj14_MapUnc_21CF0: BINCLUDE "mappings/sprite/obj14_a.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj14_MapUnc_21D7C: BINCLUDE "mappings/sprite/obj14_b.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo3_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo13_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo_ObjectMoveAndFall
jmp (ObjectMoveAndFall).l
JmpTo_MarkObjGone2
jmp (MarkObjGone2).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 16 - Diagonally moving lift from HTZ
; ----------------------------------------------------------------------------
; Sprite_21DAC:
Obj16:
moveq #0,d0
move.b routine(a0),d0
move.w Obj16_Index(pc,d0.w),d1
jmp Obj16_Index(pc,d1.w)
; ===========================================================================
; off_21DBA:
Obj16_Index: offsetTable
offsetTableEntry.w Obj16_Init ; 0
offsetTableEntry.w Obj16_Main ; 2
; ===========================================================================
; loc_21DBE:
Obj16_Init:
addq.b #2,routine(a0)
move.l #Obj16_MapUnc_21F14,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_HtzZipline,2,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo14_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$20,width_pixels(a0)
move.b #0,mapping_frame(a0)
move.b #1,priority(a0)
move.w x_pos(a0),objoff_30(a0)
move.w y_pos(a0),objoff_32(a0)
move.b #$40,y_radius(a0)
bset #4,render_flags(a0)
moveq #0,d0
move.b subtype(a0),d0
lsl.w #3,d0
move.w d0,objoff_34(a0)
; loc_21E10:
Obj16_Main:
move.w x_pos(a0),-(sp)
bsr.w Obj16_RunSecondaryRoutine
moveq #0,d1
move.b width_pixels(a0),d1
move.w #-$28,d3
move.w (sp)+,d4
jsrto (PlatformObject).l, JmpTo3_PlatformObject
jmpto (MarkObjGone).l, JmpTo5_MarkObjGone
; ===========================================================================
; loc_21E2C:
Obj16_RunSecondaryRoutine:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj16_Main_States(pc,d0.w),d1
jmp Obj16_Main_States(pc,d1.w)
; ===========================================================================
; off_21E3A:
Obj16_Main_States: offsetTable
offsetTableEntry.w Obj16_Wait ; 0
offsetTableEntry.w Obj16_Slide ; 2
offsetTableEntry.w Obj16_Fall ; 4
; ===========================================================================
; loc_21E40:
Obj16_Wait:
move.b status(a0),d0 ; get the status flags
andi.b #standing_mask,d0 ; is one of the players standing on it?
beq.s ++ ; if not, branch
addq.b #2,routine_secondary(a0)
move.w #$200,x_vel(a0)
btst #0,status(a0)
beq.s +
neg.w x_vel(a0)
+
move.w #$100,y_vel(a0)
+
rts
; ===========================================================================
; loc_21E68:
Obj16_Slide:
move.w (Timer_frames).w,d0
andi.w #$F,d0 ; play the sound only every 16 frames
bne.s +
move.w #SndID_HTZLiftClick,d0
jsr (PlaySound).l
+
jsrto (ObjectMove).l, JmpTo4_ObjectMove
subq.w #1,objoff_34(a0)
bne.s + ; rts
addq.b #2,routine_secondary(a0)
move.b #2,mapping_frame(a0)
move.w #0,x_vel(a0)
move.w #0,y_vel(a0)
jsrto (SingleObjLoad2).l, JmpTo4_SingleObjLoad2
bne.s + ; rts
_move.b #ObjID_Scenery,id(a1) ; load obj1C
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.b render_flags(a0),render_flags(a1)
move.b #6,subtype(a1)
+ rts
; ===========================================================================
; loc_21EC2:
Obj16_Fall:
jsrto (ObjectMove).l, JmpTo4_ObjectMove
addi.w #$38,y_vel(a0)
move.w (Camera_Max_Y_pos_now).w,d0
addi.w #$E0,d0
cmp.w y_pos(a0),d0
bhs.s +++ ; rts
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s ++
bclr #p1_standing_bit,status(a0)
beq.s +
bclr #3,(MainCharacter+status).w
bset #1,(MainCharacter+status).w
+
bclr #p2_standing_bit,status(a0)
beq.s +
bclr #3,(Sidekick+status).w
bset #1,(Sidekick+status).w
+
move.w #$4000,x_pos(a0)
+
rts
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj16_MapUnc_21F14: BINCLUDE "mappings/sprite/obj16.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo5_MarkObjGone
jmp (MarkObjGone).l
JmpTo4_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo14_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo3_PlatformObject
jmp (PlatformObject).l
; loc_22010:
JmpTo4_ObjectMove
jmp (ObjectMove).l
align 4
else
dc.b $01,$02,$1E,$42 ; ??? (unused)
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 19 - Platform from CPZ, OOZ and WFZ
; ----------------------------------------------------------------------------
; Sprite_22018:
Obj19:
moveq #0,d0
move.b routine(a0),d0
move.w Obj19_Index(pc,d0.w),d1
jmp Obj19_Index(pc,d1.w)
; ===========================================================================
; off_22026: Obj19_States:
Obj19_Index: offsetTable
offsetTableEntry.w Obj19_Init ; 0
offsetTableEntry.w Obj19_Main ; 2
; ---------------------------------------------------------------------------
; word_2202A:
Obj19_SubtypeProperties:
; width_pixels
; mapping_frame
dc.b $20, 0
dc.b $18, 1
dc.b $40, 2
dc.b $20, 3
; ===========================================================================
; loc_22032:
Obj19_Init:
addq.b #2,routine(a0) ; => Obj19_Main
move.l #Obj19_MapUnc_2222A,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CPZElevator,3,0),art_tile(a0) ; set default art
cmpi.b #oil_ocean_zone,(Current_Zone).w ; are we in OOZ?
bne.s + ; if not, branch
move.w #make_art_tile(ArtTile_ArtNem_OOZElevator,3,0),art_tile(a0) ; set OOZ art
+
cmpi.b #wing_fortress_zone,(Current_Zone).w ; are we in WFZ?
bne.s + ; if not, branch
move.w #make_art_tile(ArtTile_ArtNem_WfzFloatingPlatform,1,1),art_tile(a0) ; set WTZ art
+
jsrto (Adjust2PArtPointer).l, JmpTo15_Adjust2PArtPointer
move.b #4,render_flags(a0)
moveq #0,d0
move.b subtype(a0),d0
lsr.w #3,d0
andi.w #$1E,d0
lea Obj19_SubtypeProperties(pc,d0.w),a2
move.b (a2)+,width_pixels(a0)
move.b (a2)+,mapping_frame(a0)
move.b #4,priority(a0)
move.w x_pos(a0),objoff_30(a0)
move.w y_pos(a0),objoff_32(a0)
andi.b #$F,subtype(a0)
cmpi.b #3,subtype(a0)
bne.s loc_220AA
btst #0,status(a0)
bne.s loc_220B2
loc_220AA:
cmpi.b #7,subtype(a0)
bne.s Obj19_Main
loc_220B2:
subi.w #$C0,y_pos(a0)
; loc_220B8:
Obj19_Main:
move.w x_pos(a0),-(sp)
bsr.w Obj19_Move
moveq #0,d1
move.b width_pixels(a0),d1
move.w #$11,d3
move.w (sp)+,d4
jsrto (PlatformObject).l, JmpTo4_PlatformObject
move.w objoff_30(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w JmpTo20_DeleteObject
jmpto (DisplaySprite).l, JmpTo11_DisplaySprite
; ---------------------------------------------------------------------------
; loc_220E8:
Obj19_Move:
moveq #0,d0
move.b subtype(a0),d0
andi.w #$F,d0
add.w d0,d0
move.w Obj19_MoveTypes(pc,d0.w),d1
jmp Obj19_MoveTypes(pc,d1.w)
; ===========================================================================
; platform movement routine table
; off_220FC:
Obj19_MoveTypes:offsetTable
offsetTableEntry.w Obj19_MoveRoutine1 ; 0
offsetTableEntry.w Obj19_MoveRoutine2 ; 1
offsetTableEntry.w Obj19_MoveRoutine3 ; 2
offsetTableEntry.w Obj19_MoveRoutine4 ; 3
offsetTableEntry.w Obj19_MoveRoutine5 ; 4
offsetTableEntry.w Obj19_MoveRoutineNull ; 5
offsetTableEntry.w Obj19_MoveRoutine6 ; 6
offsetTableEntry.w Obj19_MoveRoutine6 ; 7
offsetTableEntry.w Obj19_MoveRoutine7 ; 8
offsetTableEntry.w Obj19_MoveRoutine7 ; 9
offsetTableEntry.w Obj19_MoveRoutine7 ; $A
offsetTableEntry.w Obj19_MoveRoutine7 ; $B
offsetTableEntry.w Obj19_MoveRoutine8 ; $C
offsetTableEntry.w Obj19_MoveRoutine8 ; $D
offsetTableEntry.w Obj19_MoveRoutine8 ; $E
offsetTableEntry.w Obj19_MoveRoutine8 ; $F
; ===========================================================================
; loc_2211C:
Obj19_MoveRoutine1:
move.b (Oscillating_Data+8).w,d0
move.w #$40,d1
bra.s Obj19_MoveRoutine2_Part2
; ===========================================================================
; loc_22126:
Obj19_MoveRoutine2:
move.b (Oscillating_Data+$C).w,d0
move.w #$60,d1
; loc_2212E:
Obj19_MoveRoutine2_Part2:
btst #0,status(a0)
beq.s +
neg.w d0
add.w d1,d0
+
move.w objoff_30(a0),d1
sub.w d0,d1
move.w d1,x_pos(a0)
rts
; ===========================================================================
; loc_22146:
Obj19_MoveRoutine3:
move.b (Oscillating_Data+$1C).w,d0
move.w #$80,d1
btst #0,status(a0)
beq.s +
neg.w d0
add.w d1,d0
+
move.w objoff_32(a0),d1
sub.w d0,d1
move.w d1,y_pos(a0)
rts
; ===========================================================================
; loc_22166:
Obj19_MoveRoutine4:
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s + ; rts
addq.b #1,subtype(a0)
+ rts
; ===========================================================================
; loc_22176:
Obj19_MoveRoutine5:
jsrto (ObjectMove).l, JmpTo5_ObjectMove
moveq #8,d1
move.w objoff_32(a0),d0
subi.w #$60,d0
cmp.w y_pos(a0),d0
bhs.s +
neg.w d1
+
add.w d1,y_vel(a0)
bne.s Obj19_MoveRoutineNull
addq.b #1,subtype(a0)
; return_22196:
Obj19_MoveRoutineNull:
rts
; ===========================================================================
; loc_22198:
Obj19_MoveRoutine6:
jsrto (ObjectMove).l, JmpTo5_ObjectMove
moveq #8,d1
move.w objoff_32(a0),d0
subi.w #$60,d0
cmp.w y_pos(a0),d0
bhs.s +
neg.w d1
+
add.w d1,y_vel(a0)
rts
; ===========================================================================
; loc_221B4:
Obj19_MoveRoutine7:
move.b (Oscillating_Data+$38).w,d1
subi.b #$40,d1
ext.w d1
move.b (Oscillating_Data+$3C).w,d2
subi.b #$40,d2
ext.w d2
btst #2,d0
beq.s +
neg.w d1
neg.w d2
+
btst #1,d0
beq.s +
neg.w d1
exg d1,d2
+
add.w objoff_30(a0),d1
move.w d1,x_pos(a0)
add.w objoff_32(a0),d2
move.w d2,y_pos(a0)
rts
; ===========================================================================
; loc_221EE:
Obj19_MoveRoutine8:
move.b (Oscillating_Data+$38).w,d1
subi.b #$40,d1
ext.w d1
move.b (Oscillating_Data+$3C).w,d2
subi.b #$40,d2
ext.w d2
btst #2,d0
beq.s +
neg.w d1
neg.w d2
+
btst #1,d0
beq.s +
neg.w d1
exg d1,d2
+
neg.w d1
add.w objoff_30(a0),d1
move.w d1,x_pos(a0)
add.w objoff_32(a0),d2
move.w d2,y_pos(a0)
rts
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj19_MapUnc_2222A: BINCLUDE "mappings/sprite/obj19.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo11_DisplaySprite
jmp (DisplaySprite).l
JmpTo20_DeleteObject
jmp (DeleteObject).l
JmpTo15_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo4_PlatformObject
jmp (PlatformObject).l
; loc_222A4:
JmpTo5_ObjectMove
jmp (ObjectMove).l
align 4
else
JmpTo20_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 1B - Speed booster from CPZ
; ----------------------------------------------------------------------------
speedbooster_boostspeed = objoff_30
; Sprite_222AC:
Obj1B:
moveq #0,d0
move.b routine(a0),d0
move.w Obj1B_Index(pc,d0.w),d1
jmp Obj1B_Index(pc,d1.w)
; ===========================================================================
; off_222BA:
Obj1B_Index: offsetTable
offsetTableEntry.w Obj1B_Init ; 0
offsetTableEntry.w Obj1B_Main ; 2
; ---------------------------------------------------------------------------
; word_222BE:
Obj1B_BoosterSpeeds:
dc.w $1000
dc.w $A00
; ===========================================================================
; loc_222C2:
Obj1B_Init:
addq.b #2,routine(a0) ; => Obj1B_Main
move.l #Obj1B_MapUnc_223E2,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CPZBooster,3,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo16_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$20,width_pixels(a0)
move.b #1,priority(a0)
move.b subtype(a0),d0
andi.w #2,d0
move.w Obj1B_BoosterSpeeds(pc,d0.w),speedbooster_boostspeed(a0)
; loc_222F8:
Obj1B_Main:
move.b (Timer_frames+1).w,d0
andi.b #2,d0
move.b d0,mapping_frame(a0)
move.w x_pos(a0),d0
move.w d0,d1
subi.w #$10,d0
addi.w #$10,d1
move.w y_pos(a0),d2
move.w d2,d3
subi.w #$10,d2
addi.w #$10,d3
lea (MainCharacter).w,a1 ; a1=character
btst #1,status(a1)
bne.s +
move.w x_pos(a1),d4
cmp.w d0,d4
blo.w +
cmp.w d1,d4
bhs.w +
move.w y_pos(a1),d4
cmp.w d2,d4
blo.w +
cmp.w d3,d4
bhs.w +
move.w d0,-(sp)
bsr.w Obj1B_GiveBoost
move.w (sp)+,d0
+
lea (Sidekick).w,a1 ; a1=character
btst #1,status(a1)
bne.s +
move.w x_pos(a1),d4
cmp.w d0,d4
blo.w +
cmp.w d1,d4
bhs.w +
move.w y_pos(a1),d4
cmp.w d2,d4
blo.w +
cmp.w d3,d4
bhs.w +
bsr.w Obj1B_GiveBoost
+
jmpto (MarkObjGone).l, JmpTo6_MarkObjGone
; ===========================================================================
; sub_22388:
Obj1B_GiveBoost:
move.w x_vel(a1),d0
btst #0,status(a0)
beq.s +
neg.w d0 ; d0 = absolute value of character's x velocity
+
cmpi.w #$1000,d0 ; is the character already going super fast?
bge.s Obj1B_GiveBoost_Done ; if yes, branch to not change the speed
move.w speedbooster_boostspeed(a0),x_vel(a1) ; make the character go super fast
bclr #0,status(a1) ; turn him right
btst #0,status(a0) ; was that the correct direction?
beq.s + ; if yes, branch
bset #0,status(a1) ; turn him left
neg.w x_vel(a1) ; make the boosting direction left
+
move.w #$F,move_lock(a1) ; don't let him turn around for a few frames
move.w x_vel(a1),inertia(a1) ; update his inertia value
bclr #5,status(a0)
bclr #6,status(a0)
bclr #5,status(a1)
; loc_223D8:
Obj1B_GiveBoost_Done:
move.w #SndID_Spring,d0 ; spring boing sound
jmp (PlaySound).l
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj1B_MapUnc_223E2: BINCLUDE "mappings/sprite/obj1B.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo6_MarkObjGone
jmp (MarkObjGone).l
JmpTo16_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 1D - Blue balls in CPZ
; ----------------------------------------------------------------------------
; Sprite_22408:
Obj1D:
moveq #0,d0
move.b routine(a0),d0
move.w Obj1D_Index(pc,d0.w),d1
jmp Obj1D_Index(pc,d1.w)
; ===========================================================================
; off_22416: Obj1D_States:
Obj1D_Index: offsetTable
offsetTableEntry.w Obj1D_Init ; 0
offsetTableEntry.w Obj1D_Wait ; 2
offsetTableEntry.w Obj1D_MoveArc ; 4
offsetTableEntry.w Obj1D_Wait ; 6
offsetTableEntry.w Obj1D_MoveStraight ; 8
; ---------------------------------------------------------------------------
; unused table of speed values
; word_22420:
dc.w -$480
dc.w -$500
dc.w -$600
dc.w -$700
; ===========================================================================
; loc_22428:
Obj1D_Init:
addq.b #2,routine(a0) ; => Obj1D_Wait
move.w #-$480,y_vel(a0)
moveq #0,d1
move.b subtype(a0),d1
move.b d1,d0
andi.b #$F,d1 ; number of blue balls
moveq #2,d5 ; routine number
andi.b #$F0,d0
beq.s +
moveq #6,d5 ; routine number
+
move.b status(a0),d4
moveq #0,d2
movea.l a0,a1
bra.s Obj1D_InitBall
; ---------------------------------------------------------------------------
Obj1D_LoadBall:
jsrto (SingleObjLoad2).l, JmpTo5_SingleObjLoad2
bne.s ++
; loc_22458:
Obj1D_InitBall:
_move.b id(a0),id(a1) ; load obj1D
move.b d5,routine(a1) ; => Obj1D_Wait (either one)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.l #Obj1D_MapUnc_22576,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_CPZDroplet,3,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo3_Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #3,priority(a1)
move.b #%10001011,collision_flags(a1)
move.w x_pos(a1),objoff_38(a1)
move.w y_pos(a1),objoff_30(a1)
move.w y_vel(a0),y_vel(a1)
move.w y_vel(a1),objoff_34(a1)
move.b #8,width_pixels(a1)
move.w #$60,objoff_3A(a1)
move.w #$B,objoff_36(a1)
andi.b #1,d4
beq.s +
neg.w objoff_36(a1)
neg.w objoff_3A(a1)
+
move.w d2,objoff_32(a1)
addq.w #3,d2
+
dbf d1,Obj1D_LoadBall
rts
; ===========================================================================
; loc_224D6:
Obj1D_Wait:
subq.w #1,objoff_32(a0)
bpl.s BranchTo_JmpTo7_MarkObjGone
addq.b #2,routine(a0) ; => Obj1D_MoveArc or Obj1D_MoveStraight
move.w #$3B,objoff_32(a0)
move.w #SndID_Gloop,d0
jsr (PlaySoundLocal).l
BranchTo_JmpTo7_MarkObjGone
jmpto (MarkObjGone).l, JmpTo7_MarkObjGone
; ===========================================================================
; loc_224F4:
Obj1D_MoveArc:
jsrto (ObjectMove).l, JmpTo6_ObjectMove
move.w objoff_36(a0),d0
add.w d0,x_vel(a0)
addi.w #$18,y_vel(a0)
bne.s +
neg.w objoff_36(a0)
+
move.w objoff_30(a0),d0
cmp.w y_pos(a0),d0
bhi.s BranchTo2_JmpTo7_MarkObjGone
move.w objoff_34(a0),y_vel(a0)
clr.w x_vel(a0)
subq.b #2,routine(a0) ; => Obj1D_Wait
BranchTo2_JmpTo7_MarkObjGone
jmpto (MarkObjGone).l, JmpTo7_MarkObjGone
; ===========================================================================
; loc_22528:
Obj1D_MoveStraight:
jsrto (ObjectMove).l, JmpTo6_ObjectMove
addi.w #$18,y_vel(a0)
bne.s +
move.w objoff_3A(a0),d0
add.w objoff_38(a0),d0
move.w d0,x_pos(a0)
+
cmpi.w #$180,y_vel(a0)
bne.s +
move.w #SndID_Gloop,d0
jsr (PlaySoundLocal).l
+
move.w objoff_30(a0),d0
cmp.w y_pos(a0),d0
bhi.s BranchTo3_JmpTo7_MarkObjGone
move.w objoff_34(a0),y_vel(a0)
move.w objoff_38(a0),x_pos(a0)
move.w #SndID_Gloop,d0
jsr (PlaySoundLocal).l
BranchTo3_JmpTo7_MarkObjGone
jmpto (MarkObjGone).l, JmpTo7_MarkObjGone
; ===========================================================================
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj1D_MapUnc_22576: BINCLUDE "mappings/sprite/obj1D.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo7_MarkObjGone
jmp (MarkObjGone).l
JmpTo5_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo3_Adjust2PArtPointer2
jmp (Adjust2PArtPointer2).l
; loc_22596:
JmpTo6_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 1E - Spin tube from CPZ
; ----------------------------------------------------------------------------
; Sprite_2259C:
Obj1E:
moveq #0,d0
move.b routine(a0),d0
move.w Obj1E_Index(pc,d0.w),d1
jsr Obj1E_Index(pc,d1.w)
move.b objoff_2C(a0),d0
add.b objoff_36(a0),d0
beq.w JmpTo_MarkObjGone3
rts
if removeJmpTos
JmpTo_MarkObjGone3
jmp (MarkObjGone3).l
endif
; ===========================================================================
; JmpTbl_225B8: Obj1E_States:
Obj1E_Index: offsetTable
offsetTableEntry.w Obj1E_Init ; 0
offsetTableEntry.w Obj1E_Main ; 2
; ===========================================================================
word_225BC:
dc.w $A0 ; 0
dc.w $100 ; 2
dc.w $120 ; 4
; ===========================================================================
; loc_225C2: LoadSubtype_1E:
Obj1E_Init:
addq.b #2,routine(a0)
move.b subtype(a0),d0
add.w d0,d0
andi.w #6,d0
move.w word_225BC(pc,d0.w),objoff_2A(a0)
; loc_225D6:
Obj1E_Main:
lea (MainCharacter).w,a1 ; a1=character
lea objoff_2C(a0),a4
bsr.s +
lea (Sidekick).w,a1 ; a1=character
lea objoff_36(a0),a4
+
moveq #0,d0
move.b (a4),d0
move.w Obj1E_Modes(pc,d0.w),d0
jmp Obj1E_Modes(pc,d0.w)
; ===========================================================================
; off_225F4:
Obj1E_Modes: offsetTable
offsetTableEntry.w loc_225FC ; 0
offsetTableEntry.w loc_2271A ; 2
offsetTableEntry.w loc_227FE ; 4
offsetTableEntry.w loc_2286A ; 6
; ===========================================================================
loc_225FC:
tst.w (Debug_placement_mode).w
bne.w return_22718
move.w objoff_2A(a0),d2
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
cmp.w d2,d0
bhs.w return_22718
move.w y_pos(a1),d1
sub.w y_pos(a0),d1
cmpi.w #$80,d1
bhs.w return_22718
cmpi.b #$20,anim(a1)
beq.w return_22718
moveq #0,d3
cmpi.w #$A0,d2
beq.s +
moveq #8,d3
cmpi.w #$120,d2
beq.s +
moveq #4,d3
neg.w d0
addi.w #$100,d0
+
cmpi.w #$80,d0
blo.s loc_2267E
moveq #0,d2
move.b subtype(a0),d0
lsr.w #2,d0
andi.w #$F,d0
move.b byte_2266E(pc,d0.w),d2
cmpi.b #2,d2
bne.s loc_22688
move.b (Timer_second).w,d2
andi.b #1,d2
bra.s loc_22688
; ===========================================================================
byte_2266E:
dc.b 2
dc.b 2 ; 1
dc.b 2 ; 2
dc.b 2 ; 3
dc.b 2 ; 4
dc.b 2 ; 5
dc.b 2 ; 6
dc.b 2 ; 7
dc.b 2 ; 8
dc.b 2 ; 9
dc.b 0 ; 10
dc.b 2 ; 11
dc.b 0 ; 12
dc.b 1 ; 13
dc.b 2 ; 14
dc.b 1 ; 15
; ===========================================================================
loc_2267E:
moveq #2,d2
cmpi.w #$40,d1
bhs.s loc_22688
moveq #3,d2
loc_22688:
move.b d2,1(a4)
add.w d3,d2
add.w d2,d2
andi.w #$1E,d2
lea off_22980(pc),a2
adda.w (a2,d2.w),a2
move.w (a2)+,4(a4)
subq.w #4,4(a4)
move.w (a2)+,d4
add.w x_pos(a0),d4
move.w d4,x_pos(a1)
move.w (a2)+,d5
add.w y_pos(a0),d5
move.w d5,y_pos(a1)
move.l a2,6(a4)
move.w (a2)+,d4
add.w x_pos(a0),d4
move.w (a2)+,d5
add.w y_pos(a0),d5
addq.b #2,(a4)
move.b #$81,obj_control(a1)
move.b #AniIDSonAni_Roll,anim(a1)
move.w #$800,inertia(a1)
move.w #0,x_vel(a1)
move.w #0,y_vel(a1)
bclr #5,status(a0)
bclr #5,status(a1)
bset #1,status(a1)
move.b #0,jumping(a1)
bclr #high_priority_bit,art_tile(a1)
move.w #$800,d2
bsr.w loc_22902
move.w #SndID_Roll,d0
jsr (PlaySound).l
return_22718:
rts
; ===========================================================================
loc_2271A:
subq.b #1,2(a4)
bpl.s Obj1E_MoveCharacter
movea.l 6(a4),a2
move.w (a2)+,d4
add.w x_pos(a0),d4
move.w d4,x_pos(a1)
move.w (a2)+,d5
add.w y_pos(a0),d5
move.w d5,y_pos(a1)
tst.b 1(a4)
bpl.s +
subq.w #8,a2
+
move.l a2,6(a4)
subq.w #4,4(a4)
beq.s loc_22784
move.w (a2)+,d4
add.w x_pos(a0),d4
move.w (a2)+,d5
add.w y_pos(a0),d5
move.w #$800,d2
bra.w loc_22902
; ===========================================================================
; update the position of Sonic/Tails in the CPZ tube
; loc_2275E:
Obj1E_MoveCharacter:
move.l x_pos(a1),d2
move.l y_pos(a1),d3
move.w x_vel(a1),d0
ext.l d0
asl.l #8,d0
add.l d0,d2
move.w y_vel(a1),d0
ext.l d0
asl.l #8,d0
add.l d0,d3
move.l d2,x_pos(a1)
move.l d3,y_pos(a1)
rts
; ===========================================================================
loc_22784:
cmpi.b #4,1(a4)
bhs.s loc_227A6
move.b subtype(a0),d0
andi.w #$FC,d0
add.b 1(a4),d0
move.b #4,1(a4)
move.b byte_227BE(pc,d0.w),d0
bne.w loc_22892
loc_227A6:
andi.w #$7FF,y_pos(a1)
move.b #6,(a4)
clr.b obj_control(a1)
move.w #SndID_SpindashRelease,d0
jmp (PlaySound).l
; ===========================================================================
byte_227BE:
dc.b 2, 1, 0, 0
dc.b -1, 3, 0, 0
dc.b 4, -2, 0, 0
dc.b -3, -4, 0, 0
dc.b -5, -5, 0, 0
dc.b 7, 6, 0, 0
dc.b -7, -6, 0, 0
dc.b 8, 9, 0, 0
dc.b -8, -9, 0, 0
dc.b 11, 10, 0, 0
dc.b 12, 0, 0, 0
dc.b -11,-10, 0, 0
dc.b -12, 0, 0, 0
dc.b 0, 13, 0, 0
dc.b -13, 14, 0, 0
dc.b 0,-14, 0, 0
; ===========================================================================
loc_227FE:
subq.b #1,2(a4)
bpl.s Obj1E_MoveCharacter_2
movea.l 6(a4),a2
move.w (a2)+,d4
move.w d4,x_pos(a1)
move.w (a2)+,d5
move.w d5,y_pos(a1)
tst.b 1(a4)
bpl.s loc_2281C
subq.w #8,a2
loc_2281C:
move.l a2,6(a4)
subq.w #4,4(a4)
beq.s loc_22858
move.w (a2)+,d4
move.w (a2)+,d5
move.w #$800,d2
bra.w loc_22902
; ===========================================================================
; update the position of Sonic/Tails in the CPZ tube
; loc_22832:
Obj1E_MoveCharacter_2:
move.l x_pos(a1),d2
move.l y_pos(a1),d3
move.w x_vel(a1),d0
ext.l d0
asl.l #8,d0
add.l d0,d2
move.w y_vel(a1),d0
ext.l d0
asl.l #8,d0
add.l d0,d3
move.l d2,x_pos(a1)
move.l d3,y_pos(a1)
rts
; ===========================================================================
loc_22858:
andi.w #$7FF,y_pos(a1)
clr.b (a4)
move.w #SndID_SpindashRelease,d0
jmp (PlaySound).l
; ===========================================================================
loc_2286A:
move.w objoff_2A(a0),d2
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
cmp.w d2,d0
bhs.w loc_2288E
move.w y_pos(a1),d1
sub.w y_pos(a0),d1
cmpi.w #$80,d1
bhs.w loc_2288E
rts
; ===========================================================================
loc_2288E:
clr.b (a4)
rts
; ===========================================================================
loc_22892:
bpl.s loc_228C4
neg.b d0
move.b #-4,1(a4)
add.w d0,d0
lea (off_22E88).l,a2
adda.w (a2,d0.w),a2
move.w (a2)+,d0
subq.w #4,d0
move.w d0,4(a4)
lea (a2,d0.w),a2
move.w (a2)+,d4
move.w d4,x_pos(a1)
move.w (a2)+,d5
move.w d5,y_pos(a1)
subq.w #8,a2
bra.s loc_228E4
; ===========================================================================
loc_228C4:
add.w d0,d0
lea (off_22E88).l,a2
adda.w (a2,d0.w),a2
move.w (a2)+,4(a4)
subq.w #4,4(a4)
move.w (a2)+,d4
move.w d4,x_pos(a1)
move.w (a2)+,d5
move.w d5,y_pos(a1)
loc_228E4:
move.l a2,6(a4)
move.w (a2)+,d4
move.w (a2)+,d5
move.w #$800,d2
bsr.w loc_22902
move.w #SndID_Roll,d0
jsr (PlaySound).l
addq.b #2,(a4)
rts
; ===========================================================================
loc_22902:
moveq #0,d0
move.w d2,d3
move.w d4,d0
sub.w x_pos(a1),d0
bge.s +
neg.w d0
neg.w d2
+
moveq #0,d1
move.w d5,d1
sub.w y_pos(a1),d1
bge.s +
neg.w d1
neg.w d3
+
cmp.w d0,d1
blo.s loc_22952
moveq #0,d1
move.w d5,d1
sub.w y_pos(a1),d1
swap d1
divs.w d3,d1
moveq #0,d0
move.w d4,d0
sub.w x_pos(a1),d0
beq.s +
swap d0
divs.w d1,d0
+
move.w d0,x_vel(a1)
move.w d3,y_vel(a1)
abs.w d1
move.w d1,2(a4)
rts
; ===========================================================================
loc_22952:
moveq #0,d0
move.w d4,d0
sub.w x_pos(a1),d0
swap d0
divs.w d2,d0
moveq #0,d1
move.w d5,d1
sub.w y_pos(a1),d1
beq.s +
swap d1
divs.w d0,d1
+
move.w d1,y_vel(a1)
move.w d2,x_vel(a1)
abs.w d0
move.w d0,2(a4)
rts
; ===========================================================================
obj1E67Size macro {INTLABEL}
__LABEL__ label *
dc.w __LABEL___End-__LABEL__-2
endm
; -------------------------------------------------------------------------------
; spin tube data - entry/exit
; -------------------------------------------------------------------------------
; off_22980:
include "misc/obj1E_a.asm"
; -------------------------------------------------------------------------------
; spin tube data - main tube
; -------------------------------------------------------------------------------
; off_22E88:
include "misc/obj1E_b.asm"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo_MarkObjGone3
jmp (MarkObjGone3).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 20 - Lava bubble from Hill Top Zone (boss weapon)
; ----------------------------------------------------------------------------
; Sprite_22FF8:
Obj20:
moveq #0,d0
move.b routine(a0),d0
move.w Obj20_Index(pc,d0.w),d1
jmp Obj20_Index(pc,d1.w)
; ===========================================================================
; off_23006:
Obj20_Index: offsetTable
offsetTableEntry.w Obj20_Init ; 0
offsetTableEntry.w loc_23076 ; 2
offsetTableEntry.w loc_23084 ; 4
offsetTableEntry.w loc_2311E ; 6
offsetTableEntry.w loc_23144 ; 8
offsetTableEntry.w loc_231D2 ; $A
offsetTableEntry.w BranchTo_JmpTo21_DeleteObject ; $C
; ===========================================================================
; loc_23014:
Obj20_Init:
addq.b #2,routine(a0)
move.b #8,y_radius(a0)
move.b #8,x_radius(a0)
move.l #Obj20_MapUnc_23254,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_HtzFireball,0,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo17_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #3,priority(a0)
move.b #8,width_pixels(a0)
move.w y_pos(a0),objoff_30(a0)
moveq #0,d0
move.b subtype(a0),d0
lsl.w #3,d0
andi.w #$780,d0
neg.w d0
move.w d0,x_vel(a0)
move.w d0,y_vel(a0)
move.b subtype(a0),d0
andi.w #$F,d0
lsl.w #4,d0
move.w d0,objoff_32(a0)
move.w d0,objoff_34(a0)
loc_23076:
lea (Ani_obj20).l,a1
jsrto (AnimateSprite).l, JmpTo4_AnimateSprite
jmpto (MarkObjGone).l, JmpTo8_MarkObjGone
; ===========================================================================
loc_23084:
cmpi.b #5,anim_frame_duration(a0)
bne.s loc_230B4
jsrto (SingleObjLoad2).l, JmpTo6_SingleObjLoad2
bne.s loc_230A6
bsr.s loc_230C2
jsrto (SingleObjLoad2).l, JmpTo6_SingleObjLoad2
bne.s loc_230A6
bsr.s loc_230C2
neg.w x_vel(a1)
bset #0,render_flags(a1)
loc_230A6:
move.w #SndID_ArrowFiring,d0
jsr (PlaySound).l
addq.b #2,routine(a0)
loc_230B4:
lea (Ani_obj20).l,a1
jsrto (AnimateSprite).l, JmpTo4_AnimateSprite
jmpto (MarkObjGone).l, JmpTo8_MarkObjGone
; ===========================================================================
loc_230C2:
_move.b #ObjID_LavaBubble,id(a1) ; load obj20
move.b #8,routine(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w x_vel(a0),x_vel(a1)
move.w y_vel(a0),y_vel(a1)
move.b #8,y_radius(a1)
move.b #8,x_radius(a1)
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
ori.b #4,render_flags(a1)
move.b #3,priority(a1)
move.b #8,width_pixels(a1)
move.b #$8B,collision_flags(a1)
move.w y_pos(a1),objoff_30(a1)
rts
; ===========================================================================
loc_2311E:
subq.w #1,objoff_32(a0)
bpl.s loc_23136
move.w objoff_34(a0),objoff_32(a0)
move.b #2,routine(a0)
move.w #1,anim(a0)
loc_23136:
lea (Ani_obj20).l,a1
jsrto (AnimateSprite).l, JmpTo4_AnimateSprite
jmpto (MarkObjGone).l, JmpTo8_MarkObjGone
; ===========================================================================
loc_23144:
subq.b #1,anim_frame_duration(a0)
bpl.s loc_2315A
move.b #7,anim_frame_duration(a0)
addq.b #1,mapping_frame(a0)
andi.b #1,mapping_frame(a0)
loc_2315A:
jsrto (ObjectMove).l, JmpTo7_ObjectMove
addi.w #$18,y_vel(a0)
move.w (Camera_Max_Y_pos_now).w,d0
addi.w #$E0,d0
cmp.w y_pos(a0),d0
bhs.s loc_23176
jmpto (DeleteObject).l, JmpTo21_DeleteObject
; ===========================================================================
loc_23176:
bclr #1,render_flags(a0)
tst.w y_vel(a0)
bmi.s BranchTo_JmpTo8_MarkObjGone
bset #1,render_flags(a0)
bsr.w ObjCheckFloorDist
tst.w d1
bpl.s BranchTo_JmpTo8_MarkObjGone
add.w d1,y_pos(a0)
addq.b #2,routine(a0)
move.b #2,anim(a0)
move.b #4,mapping_frame(a0)
move.w #0,y_vel(a0)
move.l #Obj20_MapUnc_23294,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Buzzer_Fireball_1,0,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo17_Adjust2PArtPointer
move.b #0,mapping_frame(a0)
move.w #9,objoff_32(a0)
move.b #3,objoff_36(a0)
BranchTo_JmpTo8_MarkObjGone
jmpto (MarkObjGone).l, JmpTo8_MarkObjGone
; ===========================================================================
loc_231D2:
subq.w #1,objoff_32(a0)
bpl.s loc_23224
move.w #$7F,objoff_32(a0)
subq.b #1,objoff_36(a0)
bmi.s loc_23224
jsrto (SingleObjLoad2).l, JmpTo6_SingleObjLoad2
bne.s loc_23224
moveq #0,d0
move.w #bytesToLcnt(object_size),d1
loc_231F0:
move.l (a0,d0.w),(a1,d0.w)
addq.w #4,d0
dbf d1,loc_231F0
if object_size&3
move.w (a0,d0.w),(a1,d0.w)
endif
move.w #9,objoff_32(a1)
move.w #$200,anim(a1)
move.w #$E,d0
tst.w x_vel(a1)
bpl.s loc_23214
neg.w d0
loc_23214:
add.w d0,x_pos(a1)
move.l a1,-(sp)
bsr.w FireCheckFloorDist
movea.l (sp)+,a1 ; a1=object
add.w d1,y_pos(a1)
loc_23224:
lea (Ani_obj20).l,a1
jsrto (AnimateSprite).l, JmpTo4_AnimateSprite
jmpto (MarkObjGone).l, JmpTo8_MarkObjGone
; ===========================================================================
BranchTo_JmpTo21_DeleteObject
jmpto (DeleteObject).l, JmpTo21_DeleteObject
; ===========================================================================
; animation script
; off_23236:
Ani_obj20: offsetTable
offsetTableEntry.w byte_2323C ; 0
offsetTableEntry.w byte_23243 ; 1
offsetTableEntry.w byte_23246 ; 2
byte_2323C: dc.b $B, 2, 3,$FC, 4,$FD, 1
rev02even
byte_23243: dc.b $7F, 5,$FF
rev02even
byte_23246: dc.b 5, 4, 5, 2, 3, 0, 1, 0, 1, 2, 3, 4, 5,$FC
even
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj20_MapUnc_23254: BINCLUDE "mappings/sprite/obj20_a.bin"
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj20_MapUnc_23294: BINCLUDE "mappings/sprite/obj20_b.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo21_DeleteObject
jmp (DeleteObject).l
JmpTo8_MarkObjGone
jmp (MarkObjGone).l
JmpTo6_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo4_AnimateSprite
jmp (AnimateSprite).l
JmpTo17_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
; loc_232FA:
JmpTo7_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 2F - Smashable ground in Hill Top Zone
; ----------------------------------------------------------------------------
; Sprite_23300:
Obj2F:
moveq #0,d0
move.b routine(a0),d0
move.w Obj2F_Index(pc,d0.w),d1
jmp Obj2F_Index(pc,d1.w)
; ===========================================================================
; off_2330E:
Obj2F_Index: offsetTable
offsetTableEntry.w Obj2F_Init ; 0
offsetTableEntry.w Obj2F_Main ; 2
offsetTableEntry.w Obj2F_Fragment ; 4
; ===========================================================================
; byte_23314:
Obj2F_Properties:
; y_radius
; mapping_frame
dc.b $24, 0 ; 0
dc.b $20, 2 ; 2
dc.b $18, 4 ; 4
dc.b $10, 6 ; 6
dc.b 8, 8 ; 8
; ===========================================================================
; loc_2331E:
Obj2F_Init:
addq.b #2,routine(a0)
move.l #Obj2F_MapUnc_236FA,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,2,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo18_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #4,priority(a0)
moveq #0,d0
move.b subtype(a0),d0
andi.w #$1E,d0
lea Obj2F_Properties(pc,d0.w),a2
move.b (a2)+,y_radius(a0)
move.b (a2)+,mapping_frame(a0)
move.b #$20,y_radius(a0)
bset #4,render_flags(a0)
; loc_23368:
Obj2F_Main:
move.w (Chain_Bonus_counter).w,objoff_38(a0)
move.b (MainCharacter+anim).w,objoff_32(a0)
move.b (Sidekick+anim).w,objoff_33(a0)
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
move.w x_pos(a0),d4
jsrto (SolidObject).l, JmpTo3_SolidObject
move.b status(a0),d0
andi.b #standing_mask,d0
bne.s +
BranchTo_JmpTo9_MarkObjGone
jmpto (MarkObjGone).l, JmpTo9_MarkObjGone
; ===========================================================================
+
cmpi.b #standing_mask,d0
bne.s loc_23408
cmpi.b #AniIDSonAni_Roll,objoff_32(a0)
bne.s loc_233C0
tst.b subtype(a0)
bmi.s loc_233F0
cmpi.b #$E,(MainCharacter+top_solid_bit).w
beq.s loc_233F0
loc_233C0:
move.b #$C,(MainCharacter+top_solid_bit).w
move.b #$D,(MainCharacter+lrb_solid_bit).w
cmpi.b #AniIDSonAni_Roll,objoff_33(a0)
bne.s loc_233E2
tst.b subtype(a0)
bmi.s loc_233F0
cmpi.b #$E,(Sidekick+top_solid_bit).w
beq.s loc_233F0
loc_233E2:
move.b #$C,(Sidekick+top_solid_bit).w
move.b #$D,(Sidekick+lrb_solid_bit).w
bra.s BranchTo_JmpTo9_MarkObjGone
; ===========================================================================
loc_233F0:
lea (MainCharacter).w,a1 ; a1=character
move.b objoff_32(a0),d0
bsr.s loc_2343E
lea (Sidekick).w,a1 ; a1=character
move.b objoff_33(a0),d0
bsr.s loc_2343E
bra.w loc_234A4
; ===========================================================================
loc_23408:
move.b d0,d1
andi.b #p1_standing,d1
beq.s loc_23470
cmpi.b #AniIDSonAni_Roll,objoff_32(a0)
bne.s loc_23426
tst.b subtype(a0)
bmi.s loc_23436
cmpi.b #$E,(MainCharacter+top_solid_bit).w
beq.s loc_23436
loc_23426:
move.b #$C,(MainCharacter+top_solid_bit).w
move.b #$D,(MainCharacter+lrb_solid_bit).w
bra.w BranchTo_JmpTo9_MarkObjGone
; ===========================================================================
loc_23436:
lea (MainCharacter).w,a1 ; a1=character
bsr.s loc_23444
bra.s loc_234A4
; ===========================================================================
loc_2343E:
cmpi.b #AniIDSonAni_Roll,d0
bne.s loc_2345C
loc_23444:
bset #2,status(a1)
move.b #$E,y_radius(a1)
move.b #7,x_radius(a1)
move.b #AniIDSonAni_Roll,anim(a1)
loc_2345C:
bset #1,status(a1)
bclr #3,status(a1)
move.b #2,routine(a1)
rts
; ===========================================================================
loc_23470:
andi.b #p2_standing,d0
beq.w BranchTo_JmpTo9_MarkObjGone
cmpi.b #AniIDSonAni_Roll,objoff_33(a0)
bne.s loc_2348E
tst.b subtype(a0)
bmi.s loc_2349E
cmpi.b #$E,(Sidekick+top_solid_bit).w
beq.s loc_2349E
loc_2348E:
move.b #$C,(Sidekick+top_solid_bit).w
move.b #$D,(Sidekick+lrb_solid_bit).w
bra.w BranchTo_JmpTo9_MarkObjGone
; ===========================================================================
loc_2349E:
lea (Sidekick).w,a1 ; a1=character
bsr.s loc_23444
loc_234A4:
move.w objoff_38(a0),(Chain_Bonus_counter).w
andi.b #~standing_mask,status(a0)
lea (byte_234F2).l,a4
moveq #0,d0
move.b mapping_frame(a0),d0
addq.b #1,mapping_frame(a0)
move.l d0,d1
add.w d0,d0
add.w d0,d0
lea (a4,d0.w),a4
neg.w d1
addi.w #9,d1
move.w #$18,d2
jsrto (BreakObjectToPieces).l, JmpTo_BreakObjectToPieces
bsr.w SmashableObject_LoadPoints
; loc_234DC:
Obj2F_Fragment:
jsrto (ObjectMove).l, JmpTo8_ObjectMove
addi.w #$18,y_vel(a0)
tst.b render_flags(a0)
bpl.w JmpTo22_DeleteObject
jmpto (DisplaySprite).l, JmpTo12_DisplaySprite
; ===========================================================================
byte_234F2:
dc.b $FF
dc.b 0 ; 1
dc.b $F8 ; 2
dc.b 0 ; 3
dc.b 1 ; 4
dc.b 0 ; 5
dc.b $F8 ; 6
dc.b 0 ; 7
dc.b $FF ; 8
dc.b $20 ; 9
dc.b $F9 ; 10
dc.b 0 ; 11
dc.b 0 ; 12
dc.b $E0 ; 13
dc.b $F9 ; 14
dc.b 0 ; 15
dc.b $FF ; 16
dc.b $40 ; 17
dc.b $FA ; 18
dc.b 0 ; 19
dc.b 0 ; 20
dc.b $C0 ; 21
dc.b $FA ; 22
dc.b 0 ; 23
dc.b $FF ; 24
dc.b $60 ; 25
dc.b $FB ; 26
dc.b 0 ; 27
dc.b 0 ; 28
dc.b $A0 ; 29
dc.b $FB ; 30
dc.b 0 ; 31
dc.b $FF ; 32
dc.b $80 ; 33
dc.b $FC ; 34
dc.b 0 ; 35
dc.b 0 ; 36
dc.b $80 ; 37
dc.b $FC ; 38
dc.b 0 ; 39
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 32 - Breakable block/rock from CPZ and HTZ
; ----------------------------------------------------------------------------
breakableblock_mainchar_anim = objoff_32
breakableblock_sidekick_anim = objoff_33
; Sprite_2351A:
Obj32:
moveq #0,d0
move.b routine(a0),d0
move.w Obj32_Index(pc,d0.w),d1
jmp Obj32_Index(pc,d1.w)
; ===========================================================================
; off_23528:
Obj32_Index: offsetTable
offsetTableEntry.w Obj32_Init ; 0
offsetTableEntry.w Obj32_Main ; 2
offsetTableEntry.w Obj32_Fragment ; 4
; ===========================================================================
; loc_2352E:
Obj32_Init:
addq.b #2,routine(a0)
move.l #Obj32_MapUnc_23852,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_HtzRock,2,0),art_tile(a0)
move.b #$18,width_pixels(a0)
move.l #Obj32_VelArray1,objoff_3C(a0)
cmpi.b #chemical_plant_zone,(Current_Zone).w
bne.s +
move.l #Obj32_MapUnc_23886,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CPZMetalBlock,3,0),art_tile(a0)
move.b #$10,width_pixels(a0)
move.l #Obj32_VelArray2,objoff_3C(a0)
+
jsrto (Adjust2PArtPointer).l, JmpTo18_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #4,priority(a0)
; loc_23582:
Obj32_Main:
move.w (Chain_Bonus_counter).w,objoff_38(a0)
move.b (MainCharacter+anim).w,breakableblock_mainchar_anim(a0)
move.b (Sidekick+anim).w,breakableblock_sidekick_anim(a0)
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
move.w #$10,d2
move.w #$11,d3
move.w x_pos(a0),d4
jsrto (SolidObject).l, JmpTo3_SolidObject
move.b status(a0),d0
andi.b #standing_mask,d0 ; is at least one player standing on the object?
bne.s Obj32_SupportingSomeone
BranchTo2_JmpTo9_MarkObjGone
jmpto (MarkObjGone).l, JmpTo9_MarkObjGone
; ===========================================================================
; loc_235BC:
Obj32_SupportingSomeone:
cmpi.b #standing_mask,d0 ; are BOTH players standing on the object?
bne.s Obj32_SupportingOnePlayerOnly ; if not, branch
cmpi.b #AniIDSonAni_Roll,breakableblock_mainchar_anim(a0)
beq.s +
cmpi.b #AniIDSonAni_Roll,breakableblock_sidekick_anim(a0)
bne.s BranchTo2_JmpTo9_MarkObjGone
+
lea (MainCharacter).w,a1 ; a1=character
move.b breakableblock_mainchar_anim(a0),d0
bsr.s Obj32_SetCharacterOffBlock
lea (Sidekick).w,a1 ; a1=character
move.b breakableblock_sidekick_anim(a0),d0
bsr.s Obj32_SetCharacterOffBlock
bra.w Obj32_Destroy
; ===========================================================================
; loc_235EA:
Obj32_SupportingOnePlayerOnly:
move.b d0,d1
andi.b #p1_standing,d1 ; is the main character standing on the object?
beq.s Obj32_SupportingSidekick ; if not, branch
cmpi.b #AniIDSonAni_Roll,breakableblock_mainchar_anim(a0)
bne.s BranchTo2_JmpTo9_MarkObjGone
lea (MainCharacter).w,a1 ; a1=character
bsr.s Obj32_BouncePlayer
bra.s Obj32_Destroy
; ===========================================================================
; loc_23602:
Obj32_SetCharacterOffBlock:
cmpi.b #AniIDSonAni_Roll,d0
bne.s +
; loc_23608:
Obj32_BouncePlayer:
bset #2,status(a1)
move.b #$E,y_radius(a1)
move.b #7,x_radius(a1)
move.b #AniIDSonAni_Roll,anim(a1)
move.w #-$300,y_vel(a1)
+
bset #1,status(a1)
bclr #3,status(a1)
move.b #2,routine(a1)
rts
; ===========================================================================
; loc_2363A:
Obj32_SupportingSidekick:
andi.b #p2_standing,d0 ; is the sidekick standing on the object? (at this point, it should...)
beq.w BranchTo2_JmpTo9_MarkObjGone ; if, by miracle, he's not, branch
cmpi.b #2,breakableblock_sidekick_anim(a0)
bne.w BranchTo2_JmpTo9_MarkObjGone
lea (Sidekick).w,a1 ; a1=character
bsr.s Obj32_BouncePlayer
; loc_23652:
Obj32_Destroy:
move.w objoff_38(a0),(Chain_Bonus_counter).w
andi.b #~standing_mask,status(a0)
movea.l objoff_3C(a0),a4
jsrto (BreakObjectToPieces).l, JmpTo_BreakObjectToPieces
bsr.w SmashableObject_LoadPoints
; loc_2366A:
Obj32_Fragment:
jsrto (ObjectMove).l, JmpTo8_ObjectMove
addi.w #$18,y_vel(a0)
tst.b render_flags(a0)
bpl.w JmpTo22_DeleteObject
jmpto (DisplaySprite).l, JmpTo12_DisplaySprite
; ===========================================================================
; velocity array for smashed bits, two words for each fragment
; byte_23680:
Obj32_VelArray1:
; x_vel y_vel
dc.w -$200,-$200
dc.w 0,-$280
dc.w $200,-$200
dc.w -$1C0,-$1C0
dc.w 0,-$200
dc.w $1C0,-$1C0
;byte_23698:
Obj32_VelArray2:
; x_vel y_vel
dc.w -$100,-$200
dc.w $100,-$200
dc.w -$C0,-$1C0
dc.w $C0,-$1C0
; ===========================================================================
; loc_236A8:
SmashableObject_LoadPoints:
jsrto (SingleObjLoad).l, JmpTo3_SingleObjLoad
bne.s +++ ; rts
_move.b #ObjID_Points,id(a1) ; load obj29
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w (Chain_Bonus_counter).w,d2
addq.w #2,(Chain_Bonus_counter).w
cmpi.w #6,d2
blo.s +
moveq #6,d2
+
moveq #0,d0
move.w SmashableObject_ScoreBonus(pc,d2.w),d0
cmpi.w #$20,(Chain_Bonus_counter).w
blo.s +
move.w #1000,d0
moveq #$A,d2
+
jsr (AddPoints).l
lsr.w #1,d2
move.b d2,mapping_frame(a1)
+
rts
; ===========================================================================
; word_236F2:
SmashableObject_ScoreBonus:
dc.w 10
dc.w 20 ; 1
dc.w 50 ; 2
dc.w 100 ; 3
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj2F_MapUnc_236FA: BINCLUDE "mappings/sprite/obj2F.bin"
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj32_MapUnc_23852: BINCLUDE "mappings/sprite/obj32_a.bin"
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj32_MapUnc_23886: BINCLUDE "mappings/sprite/obj32_b.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo12_DisplaySprite
jmp (DisplaySprite).l
JmpTo22_DeleteObject
jmp (DeleteObject).l
JmpTo3_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo9_MarkObjGone
jmp (MarkObjGone).l
JmpTo18_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo_BreakObjectToPieces
jmp (BreakObjectToPieces).l
JmpTo3_SolidObject
jmp (SolidObject).l
; loc_238D6:
JmpTo8_ObjectMove
jmp (ObjectMove).l
align 4
else
JmpTo22_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 30 - Large rising lava during earthquake in HTZ
; ----------------------------------------------------------------------------
; Sprite_238DC:
Obj30:
moveq #0,d0
move.b routine(a0),d0
move.w Obj30_Index(pc,d0.w),d1
jmp Obj30_Index(pc,d1.w)
; ===========================================================================
; off_238EA:
Obj30_Index: offsetTable
offsetTableEntry.w Obj30_Init ; 0
offsetTableEntry.w Obj30_Main ; 2
; ===========================================================================
; byte_238EE:
Obj30_Widths:
dc.b $C0
dc.b 0 ; 1
dc.b $C0 ; 2
dc.b 0 ; 3
dc.b $C0 ; 4
dc.b 0 ; 5
dc.b $E0 ; 6
dc.b 0 ; 7
dc.b $C0 ; 8
dc.b 0 ; 9
; ===========================================================================
; loc_238F8:
Obj30_Init:
addq.b #2,routine(a0)
move.w y_pos(a0),objoff_32(a0)
move.w x_pos(a0),objoff_30(a0)
moveq #0,d0
move.b subtype(a0),d0
move.b Obj30_Widths(pc,d0.w),width_pixels(a0)
cmpi.b #6,d0
blo.s Obj30_Main
bne.s +
cmpi.w #$380,(Camera_Y_pos).w
bhs.s Obj30_Main
bra.s ++
; ===========================================================================
+
cmpi.w #$380,(Camera_Y_pos).w
blo.s Obj30_Main
+
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s +
bclr #7,2(a2,d0.w)
+
jmpto (DeleteObject).l, JmpTo23_DeleteObject
; ===========================================================================
; loc_23944:
Obj30_Main:
move.w objoff_32(a0),d0
add.w (Camera_BG_Y_offset).w,d0
move.w d0,y_pos(a0)
moveq #0,d0
move.b subtype(a0),d0
move.w Obj30_Modes(pc,d0.w),d1
jsr Obj30_Modes(pc,d1.w)
tst.b (Screen_Shaking_Flag_HTZ).w
beq.w JmpTo2_MarkObjGone3
rts
; ===========================================================================
; off_23968:
Obj30_Modes: offsetTable
offsetTableEntry.w loc_23972 ; 0
offsetTableEntry.w loc_23972 ; 2
offsetTableEntry.w loc_2398A ; 4
offsetTableEntry.w loc_239D0 ; 6
offsetTableEntry.w loc_239EA ; 8
; ===========================================================================
loc_23972:
move.w #$CB,d1
move.w #$80,d2
move.w #$81,d3
move.w x_pos(a0),d4
jsrto (SolidObject_Always).l, JmpTo_SolidObject_Always
jmpto (DropOnFloor).l, JmpTo_DropOnFloor
; ===========================================================================
loc_2398A:
move.w #$CB,d1
move.w #$78,d2
move.w #$79,d3
move.w x_pos(a0),d4
jsrto (SolidObject_Always).l, JmpTo_SolidObject_Always
jsrto (DropOnFloor).l, JmpTo_DropOnFloor
; loc_239A2:
Obj30_HurtSupportedPlayers:
btst #p1_standing_bit,status(a0)
beq.s +
move.l a0,-(sp)
movea.l a0,a1
lea (MainCharacter).w,a0 ; a0=character
jsrto (Touch_ChkHurt).l, JmpTo_Touch_ChkHurt
movea.l (sp)+,a0 ; load 0bj address
+
btst #p2_standing_bit,status(a0)
beq.s +
move.l a0,-(sp)
movea.l a0,a1
lea (Sidekick).w,a0 ; a0=character
jsrto (Touch_ChkHurt).l, JmpTo_Touch_ChkHurt
movea.l (sp)+,a0 ; load 0bj address
+
rts
; ===========================================================================
loc_239D0:
move.w #$EB,d1
move.w #$78,d2
move.w #$79,d3
move.w x_pos(a0),d4
jsrto (SolidObject_Always).l, JmpTo_SolidObject_Always
jsrto (DropOnFloor).l, JmpTo_DropOnFloor
bra.s Obj30_HurtSupportedPlayers
; ===========================================================================
loc_239EA:
move.w #$CB,d1
move.w #$2E,d2
move.w x_pos(a0),d4
lea (Obj30_SlopeData).l,a2
jsrto (SlopedSolid).l, JmpTo_SlopedSolid
jmpto (DropOnFloor).l, JmpTo_DropOnFloor
; ===========================================================================
;byte_23A04:
Obj30_SlopeData:
dc.b $30,$30,$30,$30,$30,$30,$30,$30,$2F,$2F,$2E,$2E,$2D,$2D,$2C,$2C
dc.b $2B,$2B,$2A,$2A,$29,$29,$28,$28,$27,$27,$26,$26,$25,$25,$24,$24; 16
dc.b $23,$23,$22,$22,$21,$21,$20,$20,$1F,$1F,$1E,$1E,$1D,$1D,$1C,$1C; 32
dc.b $1B,$1B,$1A,$1A,$19,$19,$18,$18,$17,$17,$16,$16,$15,$15,$14,$14; 48
dc.b $13,$13,$12,$12,$11,$11,$10,$10, $F, $F, $E, $E, $D, $D, $C, $C; 64
dc.b $B, $B, $A, $A, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4; 80
dc.b 3, 3, 2, 2, 1, 1, 0, 0,$FF,$FF,$FE,$FE,$FD,$FD,$FC,$FC; 96
dc.b $FB,$FB,$FA,$FA,$F9,$F9,$F8,$F8,$F7,$F7,$F6,$F6,$F5,$F5,$F4,$F4; 112
dc.b $F3,$F3,$F2,$F2,$F1,$F1,$F0,$F0,$EF,$EF,$EE,$EE,$ED,$ED,$EC,$EC; 128
dc.b $EB,$EB,$EA,$EA,$E9,$E9,$E8,$E8,$E7,$E7,$E6,$E6,$E5,$E5,$E4,$E4; 144
dc.b $E3,$E3,$E2,$E2,$E1,$E1,$E0,$E0,$DF,$DF,$DE,$DE,$DD,$DD,$DC,$DC; 160
dc.b $DB,$DB,$DA,$DA,$D9,$D9,$D8,$D8,$D7,$D7,$D6,$D6,$D5,$D5,$D4,$D4; 176
dc.b $D3,$D3,$D2,$D2,$D1,$D1,$D0,$D0,$D0,$D0,$D0,$D0; 192
; ===========================================================================
if ~~removeJmpTos
JmpTo23_DeleteObject
jmp (DeleteObject).l
JmpTo_Touch_ChkHurt
jmp (Touch_ChkHurt).l
JmpTo2_MarkObjGone3
jmp (MarkObjGone3).l
JmpTo_DropOnFloor
jmp (DropOnFloor).l
JmpTo_SolidObject_Always
jmp (SolidObject_Always).l
JmpTo_SlopedSolid
jmp (SlopedSolid).l
align 4
else
JmpTo2_MarkObjGone3
jmp (MarkObjGone3).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 33 - Green platform from OOZ
; ----------------------------------------------------------------------------
; Sprite_23AF4:
Obj33:
moveq #0,d0
move.b routine(a0),d0
move.w Obj33_Index(pc,d0.w),d1
jmp Obj33_Index(pc,d1.w)
; ===========================================================================
; off_23B02:
Obj33_Index: offsetTable
offsetTableEntry.w Obj33_Init ; 0
offsetTableEntry.w Obj33_Main ; 2
offsetTableEntry.w Obj33_Flame ; 4
; ===========================================================================
; loc_23B08:
Obj33_Init:
addq.b #2,routine(a0)
move.l #Obj33_MapUnc_23DDC,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_BurnerLid,3,0),art_tile(a0)
move.b #4,render_flags(a0)
move.b #3,priority(a0)
move.b #$18,width_pixels(a0)
move.w y_pos(a0),objoff_30(a0)
addq.b #2,routine_secondary(a0)
move.w #$78,objoff_36(a0)
tst.b subtype(a0)
beq.s +
move.b #4,routine_secondary(a0)
+
jsrto (SingleObjLoad2).l, JmpTo7_SingleObjLoad2
bne.s Obj33_Main
_move.b id(a0),id(a1) ; load obj33
move.b #4,routine(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
subi.w #$10,y_pos(a1)
move.l #Obj33_MapUnc_23DF0,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_OOZBurn,3,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #4,priority(a1)
move.b #$10,width_pixels(a1)
move.l a0,objoff_3C(a1)
; loc_23B90:
Obj33_Main:
move.w x_pos(a0),-(sp)
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj33_Modes(pc,d0.w),d1
jsr Obj33_Modes(pc,d1.w)
move.w (sp)+,d4
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #8,d2
move.w d2,d3
addq.w #1,d3
jsrto (SolidObject).l, JmpTo4_SolidObject
jmpto (MarkObjGone).l, JmpTo10_MarkObjGone
; ===========================================================================
; off_23BBC:
Obj33_Modes: offsetTable
offsetTableEntry.w loc_23BC6 ; 0
offsetTableEntry.w loc_23BEA ; 2
offsetTableEntry.w loc_23C26 ; 4
offsetTableEntry.w loc_23D20 ; 6
offsetTableEntry.w return_23D98 ; 8
; ===========================================================================
loc_23BC6:
subq.w #1,objoff_36(a0)
bpl.s + ; rts
move.w #$78,objoff_36(a0)
move.l #-$96800,objoff_32(a0)
addq.b #2,routine_secondary(a0)
move.w #SndID_OOZLidPop,d0
jsr (PlaySoundLocal).l
+
rts
; ===========================================================================
loc_23BEA:
move.l y_pos(a0),d1
add.l objoff_32(a0),d1
move.l d1,y_pos(a0)
addi.l #$3800,objoff_32(a0)
swap d1
cmp.w objoff_30(a0),d1
blo.s ++ ; rts
move.l objoff_32(a0),d0
cmpi.l #$10000,d0
bhs.s +
subq.b #2,routine_secondary(a0)
+
lsr.l #2,d0
neg.l d0
move.l d0,objoff_32(a0)
move.w objoff_30(a0),y_pos(a0)
+
rts
; ===========================================================================
loc_23C26:
move.w x_pos(a0),d2
move.w d2,d3
subi.w #$10,d2
addi.w #$10,d3
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s ++ ; rts
cmpi.b #standing_mask,d0
beq.s loc_23CA0
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
bsr.s +
lea (Sidekick).w,a1 ; a1=character
addq.b #1,d6
+
btst d6,status(a0)
beq.s + ; rts
move.w x_pos(a1),d0
cmp.w d2,d0
blo.s + ; rts
cmp.w d3,d0
bhs.s + ; rts
move.b #1,obj_control(a1)
move.w #0,inertia(a1)
move.w #0,x_vel(a1)
move.w #0,y_vel(a1)
bclr #5,status(a1)
bclr #high_priority_bit,art_tile(a1)
move.l #-$96800,objoff_32(a0)
addq.b #2,routine_secondary(a0)
move.w #SndID_OOZLidPop,d0
jsr (PlaySoundLocal).l
+
rts
; ===========================================================================
loc_23CA0:
lea (MainCharacter).w,a1 ; a1=character
move.w x_pos(a1),d0
cmp.w d2,d0
blo.s + ; rts
cmp.w d3,d0
bhs.s + ; rts
lea (Sidekick).w,a2 ; a2=character
move.w x_pos(a2),d0
cmp.w d2,d0
blo.s + ; rts
cmp.w d3,d0
bhs.s + ; rts
move.b #1,obj_control(a1)
move.w #0,inertia(a1)
move.w #0,x_vel(a1)
move.w #0,y_vel(a1)
bclr #5,status(a1)
bclr #high_priority_bit,art_tile(a1)
move.b #1,obj_control(a2)
move.w #0,inertia(a2)
move.w #0,x_vel(a2)
move.w #0,y_vel(a2)
bclr #5,status(a2)
bclr #high_priority_bit,art_tile(a2)
move.l #-$96800,objoff_32(a0)
addq.b #2,routine_secondary(a0)
move.w #SndID_OOZLidPop,d0
jsr (PlaySoundLocal).l
+
rts
; ===========================================================================
loc_23D20:
move.l y_pos(a0),d1
add.l objoff_32(a0),d1
move.l d1,y_pos(a0)
addi.l #$3800,objoff_32(a0)
swap d1
move.w objoff_30(a0),d0
subi.w #$7D,d0
cmp.w d0,d1
bne.s + ; rts
addq.b #2,routine_secondary(a0)
lea (MainCharacter).w,a1 ; a1=character
move.b status(a0),d0
andi.b #p1_standing,d0
bsr.s loc_23D60
lea (Sidekick).w,a1 ; a1=character
move.b status(a0),d0
andi.b #p2_standing,d0
loc_23D60:
beq.s + ; rts
move.w x_pos(a0),x_pos(a1)
move.b #AniIDSonAni_Roll,anim(a1)
move.w #$800,inertia(a1)
bset #1,status(a1)
move.w #-$1000,y_vel(a1)
bclr #3,status(a1)
move.b #0,obj_control(a1)
move.w #SndID_Spring,d0
jsr (PlaySoundLocal).l
+
rts
; ===========================================================================
return_23D98:
rts
; ===========================================================================
; loc_23D9A:
Obj33_Flame:
movea.l objoff_3C(a0),a1 ; a1=object
move.w y_pos(a0),d0
sub.w y_pos(a1),d0
cmpi.w #$14,d0
blt.s Obj33_FlameOff
move.b #$9B,collision_flags(a0)
lea (Ani_obj33).l,a1
jsr (AnimateSprite).l
jmpto (MarkObjGone).l, JmpTo10_MarkObjGone
; ===========================================================================
; loc_23DC2:
Obj33_FlameOff:
move.b #0,collision_flags(a0)
move.b #0,anim_frame(a0)
rts
; ===========================================================================
; animation script
; off_23DD0:
Ani_obj33: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 2, 2, 0, 2, 0, 2, 0, 1,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj33_MapUnc_23DDC: BINCLUDE "mappings/sprite/obj33_a.bin"
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj33_MapUnc_23DF0: BINCLUDE "mappings/sprite/obj33_b.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo10_MarkObjGone
jmp (MarkObjGone).l
JmpTo7_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo4_SolidObject
jmp (SolidObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 43 - Sliding spike obstacle thing from OOZ
; ----------------------------------------------------------------------------
; Sprite_23E40:
Obj43:
moveq #0,d0
move.b routine(a0),d0
move.w Obj43_Index(pc,d0.w),d1
jmp Obj43_Index(pc,d1.w)
; ===========================================================================
; off_23E4E:
Obj43_Index: offsetTable
offsetTableEntry.w Obj43_Init ; 0
offsetTableEntry.w loc_23F0A ; 2
offsetTableEntry.w loc_23F5C ; 4
; ---------------------------------------------------------------------------
byte_23E54:
dc.b 0
dc.b $68 ; 1
dc.b 0 ; 2
dc.b 0 ; 3
dc.b 0 ; 4
dc.b 0 ; 5
dc.b 1 ; 6
dc.b $E8 ; 7
dc.b $FF ; 8
dc.b $E8 ; 9
dc.b 0 ; 10
dc.b $18 ; 11
dc.b 1 ; 12
dc.b $A8 ; 13
dc.b $FF ; 14
dc.b $A8 ; 15
dc.b $FF ; 16
dc.b $D8 ; 17
; ===========================================================================
; loc_23E66:
Obj43_Init:
addq.b #2,routine(a0)
move.w #make_art_tile(ArtTile_ArtNem_SpikyThing,2,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo19_Adjust2PArtPointer
moveq #0,d1
move.b subtype(a0),d1
lea byte_23E54(pc,d1.w),a2
move.b (a2)+,d1
movea.l a0,a1
bra.s loc_23EA8
; ===========================================================================
loc_23E84:
jsrto (SingleObjLoad2).l, JmpTo8_SingleObjLoad2
bne.s loc_23ED4
_move.b id(a0),id(a1) ; load obj43
move.b #4,routine(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.b #1,objoff_36(a1)
loc_23EA8:
move.l #Obj43_MapUnc_23FE0,mappings(a1)
move.w art_tile(a0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #4,priority(a1)
move.b #$18,width_pixels(a1)
move.b #$A5,collision_flags(a1)
move.w x_pos(a1),objoff_30(a1)
loc_23ED4:
dbf d1,loc_23E84
move.l a0,objoff_3C(a1)
move.l a1,objoff_3C(a0)
moveq #0,d1
move.b (a2)+,d1
move.w objoff_30(a0),d0
sub.w d1,d0
move.w d0,objoff_32(a0)
move.w d0,objoff_32(a1)
add.w d1,d0
add.w d1,d0
move.w d0,objoff_34(a0)
move.w d0,objoff_34(a1)
move.w (a2)+,d0
add.w d0,x_pos(a0)
move.w (a2)+,d0
add.w d0,x_pos(a1)
loc_23F0A:
bsr.s loc_23F66
move.w objoff_32(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bls.s JmpTo13_DisplaySprite
move.w objoff_34(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.s loc_23F36
JmpTo13_DisplaySprite
jmp (DisplaySprite).l
; ===========================================================================
loc_23F36:
movea.l objoff_3C(a0),a1 ; a1=object
cmpa.l a0,a1
beq.s loc_23F44
jsr (DeleteObject2).l
loc_23F44:
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s JmpTo24_DeleteObject
bclr #7,2(a2,d0.w)
JmpTo24_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
loc_23F5C:
bsr.s loc_23F66
bsr.s loc_23FB0
jmp (DisplaySprite).l
; ===========================================================================
loc_23F66:
tst.b objoff_36(a0)
bne.s loc_23F8E
move.w x_pos(a0),d1
subq.w #1,d1
cmp.w objoff_32(a0),d1
bne.s loc_23F88
move.b #1,objoff_36(a0)
move.w #SndID_SlidingSpike,d0
jsr (PlaySoundLocal).l
loc_23F88:
move.w d1,x_pos(a0)
rts
; ===========================================================================
loc_23F8E:
move.w x_pos(a0),d1
addq.w #1,d1
cmp.w objoff_34(a0),d1
bne.s loc_23FAA
move.b #0,objoff_36(a0)
move.w #SndID_SlidingSpike,d0
jsr (PlaySoundLocal).l
loc_23FAA:
move.w d1,x_pos(a0)
rts
; ===========================================================================
loc_23FB0:
movea.l objoff_3C(a0),a1 ; a1=object
move.w x_pos(a0),d0
subi.w #$18,d0
move.w x_pos(a1),d2
addi.w #$18,d2
cmp.w d0,d2
bne.s return_23FDE
eori.b #1,objoff_36(a0)
eori.b #1,objoff_36(a1)
move.w #SndID_SlidingSpike,d0
jsr (PlaySoundLocal).l
return_23FDE:
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj43_MapUnc_23FE0: BINCLUDE "mappings/sprite/obj43.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo8_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo19_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 07 - Oil Ocean in OOZ
; ----------------------------------------------------------------------------
; OST:
oil_char1submersion = objoff_38 ; $38(a0)
oil_char2submersion = objoff_3A ; $3A(a0)
; ----------------------------------------------------------------------------
; Sprite_24020:
Obj07:
moveq #0,d0
move.b routine(a0),d0
move.w Obj07_Index(pc,d0.w),d1
jmp Obj07_Index(pc,d1.w)
; ===========================================================================
; off_2402E: Obj07_States:
Obj07_Index: offsetTable
offsetTableEntry.w Obj07_Init ; 0
offsetTableEntry.w Obj07_Main ; 2
; ===========================================================================
; loc_24032:
Obj07_Init:
addq.b #2,routine(a0) ; => Obj07_Main
move.w #$758,y_pos(a0)
move.b #$20,width_pixels(a0)
move.w y_pos(a0),objoff_30(a0)
move.b #$30,oil_char1submersion(a0)
bset #7,status(a0)
; loc_24054:
Obj07_Main:
; check player 1
tst.w (Debug_placement_mode).w
bne.w Obj07_End
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing,d1
move.b status(a0),d0
and.b d1,d0
bne.s Obj07_CheckKillChar1
cmpi.b #$30,oil_char1submersion(a0)
beq.s Obj07_CheckSupportChar1
addq.b #1,oil_char1submersion(a0)
bra.s Obj07_CheckSupportChar1
; ---------------------------------------------------------------------------
; loc_24078:
Obj07_CheckKillChar1:
tst.b oil_char1submersion(a0)
beq.s Obj07_SuffocateCharacter
subq.b #1,oil_char1submersion(a0)
; loc_24082:
Obj07_CheckSupportChar1:
moveq #$20,d1
moveq #0,d3
move.b oil_char1submersion(a0),d3
moveq #p1_standing_bit,d6
move.w x_pos(a1),d4
move.w d4,x_pos(a0)
jsrto (PlatformObject_SingleCharacter).l, JmpTo_PlatformObject_SingleCharacter ; stop the character from falling past the oil
; check player 2
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing,d1
move.b status(a0),d0
and.b d1,d0
bne.s Obj07_CheckKillChar2
cmpi.b #$30,oil_char2submersion(a0)
beq.s Obj07_CheckSupportChar2
addq.b #1,oil_char2submersion(a0)
bra.s Obj07_CheckSupportChar2
; ---------------------------------------------------------------------------
; loc_240B4:
Obj07_CheckKillChar2:
tst.b oil_char2submersion(a0)
beq.s Obj07_SuffocateCharacter
subq.b #1,oil_char2submersion(a0)
; loc_240BE:
Obj07_CheckSupportChar2:
moveq #$20,d1
moveq #0,d3
move.b oil_char2submersion(a0),d3
moveq #p2_standing_bit,d6
move.w x_pos(a1),d4
move.w d4,x_pos(a0)
jsrto (PlatformObject_SingleCharacter).l, JmpTo_PlatformObject_SingleCharacter ; stop the character from falling past the oil
rts
; ---------------------------------------------------------------------------
; loc_240D6:
Obj07_SuffocateCharacter:
not.b d1
and.b d1,status(a0)
move.l a0,-(sp)
movea.l a0,a2
movea.l a1,a0
jsrto (KillCharacter).l, JmpTo3_KillCharacter
movea.l (sp)+,a0 ; load 0bj address
Obj07_End:
rts
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo3_KillCharacter
jmp (KillCharacter).l
JmpTo_PlatformObject_SingleCharacter
jmp (PlatformObject_SingleCharacter).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 45 - Pressure spring from OOZ
; ----------------------------------------------------------------------------
; Sprite_240F8:
Obj45:
moveq #0,d0
move.b routine(a0),d0
move.w Obj45_Index(pc,d0.w),d1
jsr Obj45_Index(pc,d1.w)
jmpto (MarkObjGone).l, JmpTo11_MarkObjGone
; ===========================================================================
; off_2410A:
Obj45_Index: offsetTable
offsetTableEntry.w Obj45_Init ; 0
offsetTableEntry.w loc_24186 ; 2
offsetTableEntry.w loc_2427A ; 4
; ===========================================================================
; loc_24110:
Obj45_Init:
addq.b #2,routine(a0)
move.l #Obj45_MapUnc_2451A,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_PushSpring,2,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #4,priority(a0)
move.b subtype(a0),d0
lsr.w #3,d0
andi.w #$E,d0
move.w Obj45_InitRoutines(pc,d0.w),d0
jmp Obj45_InitRoutines(pc,d0.w)
; ===========================================================================
; off_24146:
Obj45_InitRoutines: offsetTable
offsetTableEntry.w loc_2416E ; 0
offsetTableEntry.w loc_2414A ; 2
; ===========================================================================
loc_2414A:
move.b #4,routine(a0)
move.b #1,anim(a0)
move.b #$A,mapping_frame(a0)
move.w #make_art_tile(ArtTile_ArtNem_PushSpring,2,0),art_tile(a0)
move.b #$14,width_pixels(a0)
move.w x_pos(a0),objoff_34(a0)
loc_2416E:
move.b subtype(a0),d0
andi.w #2,d0
move.w word_24182(pc,d0.w),objoff_30(a0)
jsrto (Adjust2PArtPointer).l, JmpTo20_Adjust2PArtPointer
rts
; ===========================================================================
word_24182:
dc.w $F000
dc.w $F600 ; 1
; ===========================================================================
loc_24186:
move.b status(a0),d0
andi.b #standing_mask,d0
bne.s loc_2419C
tst.b objoff_32(a0)
beq.s loc_241A8
subq.b #1,objoff_32(a0)
bra.s loc_241A8
; ===========================================================================
loc_2419C:
cmpi.b #9,objoff_32(a0)
beq.s loc_241C6
addq.b #1,objoff_32(a0)
loc_241A8:
moveq #0,d3
move.b objoff_32(a0),d3
move.b d3,mapping_frame(a0)
add.w d3,d3
move.w #$1B,d1
move.w #$14,d2
move.w x_pos(a0),d4
jsrto (SolidObject45).l, JmpTo_SolidObject45
rts
; ===========================================================================
loc_241C6:
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
bsr.s loc_241D4
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
loc_241D4:
bclr d6,status(a0)
beq.w return_24278
move.w objoff_30(a0),y_vel(a1)
bset #1,status(a1)
bclr #3,status(a1)
move.b #AniIDSonAni_Spring,anim(a1)
move.b #2,routine(a1)
move.b subtype(a0),d0
bpl.s loc_24206
move.w #0,x_vel(a1)
loc_24206:
btst #0,d0
beq.s loc_24246
move.w #1,inertia(a1)
move.b #1,flip_angle(a1)
move.b #AniIDSonAni_Walk,anim(a1)
move.b #0,flips_remaining(a1)
move.b #4,flip_speed(a1)
btst #1,d0
bne.s loc_24236
move.b #1,flips_remaining(a1)
loc_24236:
btst #0,status(a1)
beq.s loc_24246
neg.b flip_angle(a1)
neg.w inertia(a1)
loc_24246:
andi.b #$C,d0
cmpi.b #4,d0
bne.s loc_2425C
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
loc_2425C:
cmpi.b #8,d0
bne.s loc_2426E
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
loc_2426E:
move.w #SndID_Spring,d0
jmp (PlaySound).l
; ===========================================================================
return_24278:
rts
; ===========================================================================
loc_2427A:
move.b #0,objoff_36(a0)
move.w #$1F,d1
move.w #$C,d2
move.w #$D,d3
move.w x_pos(a0),d4
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
jsrto (SolidObject_Always_SingleCharacter).l, JmpTo_SolidObject_Always_SingleCharacter
cmpi.w #1,d4
bne.s loc_242C0
move.b status(a0),d1
move.w x_pos(a0),d2
sub.w x_pos(a1),d2
bcs.s loc_242B6
eori.b #1,d1
loc_242B6:
andi.b #1,d1
bne.s loc_242C0
bsr.w loc_2433C
loc_242C0:
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
jsrto (SolidObject_Always_SingleCharacter).l, JmpTo_SolidObject_Always_SingleCharacter
cmpi.w #1,d4
bne.s loc_242EE
move.b status(a0),d1
move.w x_pos(a0),d2
sub.w x_pos(a1),d2
bcs.s loc_242E6
eori.b #1,d1
loc_242E6:
andi.b #1,d1
bne.s loc_242EE
bsr.s loc_2433C
loc_242EE:
tst.b objoff_36(a0)
bne.s return_2433A
move.w objoff_34(a0),d0
cmp.w x_pos(a0),d0
beq.s return_2433A
bhs.s loc_2431C
subq.b #4,mapping_frame(a0)
subq.w #4,x_pos(a0)
cmp.w x_pos(a0),d0
blo.s loc_24336
move.b #$A,mapping_frame(a0)
move.w objoff_34(a0),x_pos(a0)
bra.s loc_24336
; ===========================================================================
loc_2431C:
subq.b #4,mapping_frame(a0)
addq.w #4,x_pos(a0)
cmp.w x_pos(a0),d0
bhs.s loc_24336
move.b #$A,mapping_frame(a0)
move.w objoff_34(a0),x_pos(a0)
loc_24336:
bsr.w loc_243D0
return_2433A:
rts
; ===========================================================================
loc_2433C:
btst #0,status(a0)
beq.s loc_24378
btst #0,status(a1)
bne.w return_243CE
tst.w d0
bne.w loc_2435E
tst.w inertia(a1)
beq.s return_243CE
bpl.s loc_243C8
bra.s return_243CE
; ===========================================================================
loc_2435E:
move.w objoff_34(a0),d0
addi.w #$12,d0
cmp.w x_pos(a0),d0
beq.s loc_243C8
addq.w #1,x_pos(a0)
moveq #1,d0
move.w #$40,d1
bra.s loc_243A6
; ===========================================================================
loc_24378:
btst #0,status(a1)
beq.s return_243CE
tst.w d0
bne.w loc_2438E
tst.w inertia(a1)
bmi.s loc_243C8
bra.s return_243CE
; ===========================================================================
loc_2438E:
move.w objoff_34(a0),d0
subi.w #$12,d0
cmp.w x_pos(a0),d0
beq.s loc_243C8
subq.w #1,x_pos(a0)
moveq #-1,d0
move.w #-$40,d1
loc_243A6:
add.w d0,x_pos(a1)
move.w d1,inertia(a1)
move.w #0,x_vel(a1)
move.w objoff_34(a0),d0
sub.w x_pos(a0),d0
bcc.s loc_243C0
neg.w d0
loc_243C0:
addi.w #$A,d0
move.b d0,mapping_frame(a0)
loc_243C8:
move.b #1,objoff_36(a0)
return_243CE:
rts
; ===========================================================================
loc_243D0:
move.b status(a0),d0
andi.b #pushing_mask,d0
beq.w return_244D0
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_pushing_bit,d6
bsr.s loc_243EA
lea (Sidekick).w,a1 ; a1=character
moveq #p2_pushing_bit,d6
loc_243EA:
bclr d6,status(a0)
beq.w return_244D0
move.w objoff_34(a0),d0
sub.w x_pos(a0),d0
bcc.s loc_243FE
neg.w d0
loc_243FE:
addi.w #$A,d0
lsl.w #7,d0
neg.w d0
move.w d0,x_vel(a1)
subq.w #4,x_pos(a1)
bset #0,status(a1)
btst #0,status(a0)
bne.s loc_2442C
bclr #0,status(a1)
addi_.w #8,x_pos(a1)
neg.w x_vel(a1)
loc_2442C:
move.w #$F,move_lock(a1)
move.w x_vel(a1),inertia(a1)
btst #2,status(a1)
bne.s loc_24446
move.b #AniIDSonAni_Walk,anim(a1)
loc_24446:
move.b subtype(a0),d0
bpl.s loc_24452
move.w #0,y_vel(a1)
loc_24452:
btst #0,d0
beq.s loc_24492
move.w #1,inertia(a1)
move.b #1,flip_angle(a1)
move.b #AniIDSonAni_Walk,anim(a1)
move.b #1,flips_remaining(a1)
move.b #8,flip_speed(a1)
btst #1,d0
bne.s loc_24482
move.b #3,flips_remaining(a1)
loc_24482:
btst #0,status(a1)
beq.s loc_24492
neg.b flip_angle(a1)
neg.w inertia(a1)
loc_24492:
andi.b #$C,d0
cmpi.b #4,d0
bne.s loc_244A8
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
loc_244A8:
cmpi.b #8,d0
bne.s loc_244BA
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
loc_244BA:
bclr #5,status(a1)
move.b #AniIDSonAni_Run,next_anim(a1)
move.w #SndID_Spring,d0 ; play spring bounce sound
jmp (PlaySound).l
; ===========================================================================
return_244D0:
rts
; ===========================================================================
; off_244D2:
; Unused animation script
Ani_obj45: offsetTable
offsetTableEntry.w byte_244D6 ; 0
offsetTableEntry.w byte_244F8 ; 1
byte_244D6:
dc.b 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9
dc.b 9, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0; 16
dc.b 0,$FF ; 32
byte_244F8:
dc.b 0, $A, $B, $C, $D, $E, $F,$10,$11,$12,$13,$13,$13,$13,$13,$13
dc.b $13,$13,$12,$11,$10, $F, $E, $D, $C, $B, $A, $A, $A, $A, $A, $A; 16
dc.b $A,$FF ; 32
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj45_MapUnc_2451A: BINCLUDE "mappings/sprite/obj45.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 46 - Ball from OOZ (unused, beta leftover)
; ----------------------------------------------------------------------------
; Sprite_24A16:
Obj46:
moveq #0,d0
move.b routine(a0),d0
move.w Obj46_Index(pc,d0.w),d1
jmp Obj46_Index(pc,d1.w)
; ===========================================================================
; off_24A24:
Obj46_Index: offsetTable
offsetTableEntry.w Obj46_Init ; 0 - Init
offsetTableEntry.w Obj46_Inactive ; 2 - Ball inactive
offsetTableEntry.w Obj46_Moving ; 4 - Ball moving
offsetTableEntry.w Obj46_PressureSpring ; 6 - Pressure Spring
; ===========================================================================
; loc_24A2C:
Obj46_Init:
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s +
bclr #7,2(a2,d0.w)
bset #0,2(a2,d0.w)
bne.w JmpTo25_DeleteObject
+
; loads the ball itself
addq.b #2,routine(a0)
move.b #$F,y_radius(a0)
move.b #$F,x_radius(a0)
move.l #Obj46_MapUnc_24C52,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_BallThing,3,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo20_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #3,priority(a0)
move.w x_pos(a0),objoff_34(a0)
move.w y_pos(a0),objoff_36(a0)
move.b #$10,width_pixels(a0)
move.b #0,mapping_frame(a0)
move.w #0,objoff_14(a0)
move.b #1,objoff_1F(a0)
; Obj46_InitPressureSpring: ; loads the spring under the ball
jsrto (SingleObjLoad).l, JmpTo4_SingleObjLoad
bne.s +
_move.b #ObjID_OOZBall,id(a1) ; load obj46
addq.b #6,routine(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
addi.w #$12,y_pos(a1)
move.l #Obj45_MapUnc_2451A,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_PushSpring,2,0),art_tile(a1)
ori.b #4,render_flags(a1)
move.b #$10,width_pixels(a1)
move.b #4,priority(a1)
move.b #9,mapping_frame(a1)
move.l a0,objoff_3C(a1)
+
move.l a1,objoff_3C(a0)
; loc_24AEA:
Obj46_Inactive:
btst #button_A,(Ctrl_2_Press).w
bne.s +
lea (ButtonVine_Trigger).w,a2
moveq #0,d0
move.b subtype(a0),d0
lsr.w #4,d0
tst.b (a2,d0.w)
beq.s ++
+
addq.b #2,routine(a0)
bset #1,status(a0)
move.w #-$300,y_vel(a0)
move.w #$100,objoff_14(a0)
movea.l objoff_3C(a0),a1 ; a1=object
move.b #1,objoff_30(a1)
btst #0,status(a0)
beq.s +
neg.w objoff_14(a0)
+
bsr.w loc_24BF0
jmpto (MarkObjGone).l, JmpTo11_MarkObjGone
; ===========================================================================
; loc_24B38:
Obj46_Moving:
move.w x_pos(a0),-(sp)
jsrto (ObjectMove).l, JmpTo9_ObjectMove
btst #1,status(a0)
beq.s loc_24B8C
addi.w #$18,y_vel(a0)
bmi.s +
move.w (Camera_Max_Y_pos_now).w,d0
addi.w #$E0,d0
cmp.w y_pos(a0),d0
blo.s loc_24BC4
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.w +
add.w d1,y_pos(a0)
clr.w y_vel(a0)
bclr #1,status(a0)
move.w #$100,x_vel(a0)
btst #0,status(a0)
beq.s +
neg.w x_vel(a0)
+
bra.s loc_24BA4
; ===========================================================================
loc_24B8C:
jsr (ObjCheckFloorDist).l
cmpi.w #8,d1
blt.s loc_24BA0
bset #1,status(a0)
bra.s loc_24BA4
; ===========================================================================
loc_24BA0:
add.w d1,y_pos(a0)
loc_24BA4:
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
move.w #$10,d2
move.w #$11,d3
move.w (sp)+,d4
jsrto (SolidObject).l, JmpTo5_SolidObject
bsr.w loc_24BF0
jmpto (MarkObjGone).l, JmpTo11_MarkObjGone
; ===========================================================================
loc_24BC4:
move.w (sp)+,d4
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s BranchTo_JmpTo25_DeleteObject
bclr #7,2(a2,d0.w)
if removeJmpTos
JmpTo25_DeleteObject
endif
BranchTo_JmpTo25_DeleteObject
jmpto (DeleteObject).l, JmpTo25_DeleteObject
; ===========================================================================
; loc_24BDC:
Obj46_PressureSpring:
tst.b objoff_30(a0)
beq.s +
subq.b #1,mapping_frame(a0)
bne.s +
clr.b objoff_30(a0)
+
jmpto (MarkObjGone).l, JmpTo11_MarkObjGone
; ===========================================================================
loc_24BF0:
tst.b mapping_frame(a0)
beq.s +
move.b #0,mapping_frame(a0)
rts
; ===========================================================================
+
move.b objoff_14(a0),d0
beq.s loc_24C2A
bmi.s loc_24C32
subq.b #1,anim_frame_duration(a0)
bpl.s loc_24C2A
neg.b d0
addq.b #8,d0
bcs.s +
moveq #0,d0
+
move.b d0,anim_frame_duration(a0)
move.b objoff_1F(a0),d0
addq.b #1,d0
cmpi.b #4,d0
bne.s +
moveq #1,d0
+
move.b d0,objoff_1F(a0)
loc_24C2A:
move.b objoff_1F(a0),mapping_frame(a0)
rts
; ===========================================================================
loc_24C32:
subq.b #1,anim_frame_duration(a0)
bpl.s loc_24C2A
addq.b #8,d0
bcs.s +
moveq #0,d0
+
move.b d0,anim_frame_duration(a0)
move.b objoff_1F(a0),d0
subq.b #1,d0
bne.s +
moveq #3,d0
+
move.b d0,objoff_1F(a0)
bra.s loc_24C2A
; ===========================================================================
; ----------------------------------------------------------------------------
; Unused sprite mappings
; ----------------------------------------------------------------------------
Obj46_MapUnc_24C52: BINCLUDE "mappings/sprite/obj46.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo25_DeleteObject
jmp (DeleteObject).l
JmpTo4_SingleObjLoad
jmp (SingleObjLoad).l
; some of these are still used, for some reason:
JmpTo11_MarkObjGone
jmp (MarkObjGone).l
JmpTo20_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo5_SolidObject
jmp (SolidObject).l
JmpTo_SolidObject_Always_SingleCharacter
jmp (SolidObject_Always_SingleCharacter).l
JmpTo_SolidObject45
jmp (SolidObject45).l
; loc_24CEE:
JmpTo9_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 47 - Button
; ----------------------------------------------------------------------------
; Sprite_24CF4:
Obj47:
moveq #0,d0
move.b routine(a0),d0
move.w Obj47_Index(pc,d0.w),d1
jmp Obj47_Index(pc,d1.w)
; ===========================================================================
; off_24D02:
Obj47_Index: offsetTable
offsetTableEntry.w Obj47_Init ; 0
offsetTableEntry.w Obj47_Main ; 2
; ===========================================================================
; loc_24D06:
Obj47_Init:
addq.b #2,routine(a0)
move.l #Obj47_MapUnc_24D96,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Button,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo21_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #4,priority(a0)
addq.w #4,y_pos(a0)
; loc_24D32:
Obj47_Main:
tst.b render_flags(a0)
bpl.s BranchTo_JmpTo12_MarkObjGone
move.w #$1B,d1
move.w #4,d2
move.w #5,d3
move.w x_pos(a0),d4
jsrto (SolidObject).l, JmpTo6_SolidObject
move.b #0,mapping_frame(a0)
move.b subtype(a0),d0
andi.w #$F,d0
lea (ButtonVine_Trigger).w,a3
lea (a3,d0.w),a3
moveq #0,d3
btst #6,subtype(a0)
beq.s +
moveq #7,d3
+
move.b status(a0),d0
andi.b #standing_mask,d0
bne.s +
bclr d3,(a3)
bra.s BranchTo_JmpTo12_MarkObjGone
; ===========================================================================
+
tst.b (a3)
bne.s +
move.w #SndID_Blip,d0
jsr (PlaySound).l
+
bset d3,(a3)
move.b #1,mapping_frame(a0)
BranchTo_JmpTo12_MarkObjGone
jmpto (MarkObjGone).l, JmpTo12_MarkObjGone
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj47_MapUnc_24D96: BINCLUDE "mappings/sprite/obj47.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo12_MarkObjGone
jmp (MarkObjGone).l
JmpTo21_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo6_SolidObject
jmp (SolidObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 3D - Block thingy in OOZ that launches you into the round ball things
; ----------------------------------------------------------------------------
; Sprite_24DD0:
Obj3D:
moveq #0,d0
move.b routine(a0),d0
move.w Obj3D_Index(pc,d0.w),d1
jmp Obj3D_Index(pc,d1.w)
; ===========================================================================
; off_24DDE:
Obj3D_Index: offsetTable
offsetTableEntry.w Obj3D_Init ; 0
offsetTableEntry.w Obj3D_Main ; 2
offsetTableEntry.w Obj3D_Fragment ; 4
offsetTableEntry.w Obj3D_InvisibleLauncher ; 6
; ===========================================================================
; loc_24DE6:
Obj3D_Init:
addq.b #2,routine(a0)
move.l #Obj3D_MapUnc_250BA,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_StripedBlocksVert,3,0),art_tile(a0)
tst.b subtype(a0)
beq.s +
move.w #make_art_tile(ArtTile_ArtNem_StripedBlocksHoriz,3,0),art_tile(a0)
move.b #2,mapping_frame(a0)
+
jsrto (Adjust2PArtPointer).l, JmpTo22_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
bset #7,status(a0)
move.b #4,priority(a0)
; loc_24E26:
Obj3D_Main:
move.b (MainCharacter+anim).w,objoff_32(a0)
move.b (Sidekick+anim).w,objoff_33(a0)
move.w (MainCharacter+y_vel).w,objoff_34(a0)
move.w (Sidekick+y_vel).w,objoff_36(a0)
move.w #$1B,d1
move.w #$10,d2
move.w #$11,d3
move.w x_pos(a0),d4
jsrto (SolidObject).l, JmpTo7_SolidObject
move.b status(a0),d0
andi.b #standing_mask,d0
bne.s loc_24E60
BranchTo_JmpTo13_MarkObjGone
jmpto (MarkObjGone).l, JmpTo13_MarkObjGone
; ===========================================================================
loc_24E60:
cmpi.b #standing_mask,d0
bne.s loc_24E96
cmpi.b #AniIDSonAni_Roll,objoff_32(a0)
beq.s loc_24E76
cmpi.b #AniIDSonAni_Roll,objoff_33(a0)
bne.s BranchTo_JmpTo13_MarkObjGone
loc_24E76:
lea (MainCharacter).w,a1 ; a1=character
move.b objoff_32(a0),d0
move.w objoff_34(a0),d1
bsr.s loc_24EB2
lea (Sidekick).w,a1 ; a1=character
move.b objoff_33(a0),d0
move.w objoff_36(a0),d1
bsr.s loc_24EB2
bra.w loc_24F04
; ===========================================================================
loc_24E96:
move.b d0,d1
andi.b #p1_standing,d1
beq.s loc_24EE8
cmpi.b #AniIDSonAni_Roll,objoff_32(a0)
bne.s BranchTo_JmpTo13_MarkObjGone
lea (MainCharacter).w,a1 ; a1=character
move.w objoff_34(a0),d1
bsr.s loc_24EB8
bra.s loc_24F04
; ===========================================================================
loc_24EB2:
cmpi.b #AniIDSonAni_Roll,d0
bne.s loc_24ED4
loc_24EB8:
bset #2,status(a1)
move.b #$E,y_radius(a1)
move.b #7,x_radius(a1)
move.b #AniIDSonAni_Roll,anim(a1)
move.w d1,y_vel(a1)
loc_24ED4:
bset #1,status(a1)
bclr #3,status(a1)
move.b #2,routine(a1)
rts
; ===========================================================================
loc_24EE8:
andi.b #p2_standing,d0
beq.w BranchTo_JmpTo13_MarkObjGone
cmpi.b #AniIDSonAni_Roll,objoff_33(a0)
bne.w BranchTo_JmpTo13_MarkObjGone
lea (Sidekick).w,a1 ; a1=character
move.w objoff_36(a0),d1
bsr.s loc_24EB8
loc_24F04:
andi.b #~standing_mask,status(a0)
jsrto (SingleObjLoad2).l, JmpTo9_SingleObjLoad2
bne.s loc_24F28
moveq #0,d0
move.w #$A,d1
loc_24F16:
move.l (a0,d0.w),(a1,d0.w)
addq.w #4,d0
dbf d1,loc_24F16
move.b #6,routine(a1)
loc_24F28:
lea (word_2507A).l,a4
addq.b #1,mapping_frame(a0)
moveq #$F,d1
move.w #$18,d2
jsrto (BreakObjectToPieces).l, JmpTo2_BreakObjectToPieces
; loc_24F3C:
Obj3D_Fragment:
jsrto (ObjectMove).l, JmpTo10_ObjectMove
addi.w #$18,y_vel(a0)
tst.b render_flags(a0)
bpl.w JmpTo26_DeleteObject
jmpto (DisplaySprite).l, JmpTo14_DisplaySprite
; ===========================================================================
; loc_24F52:
Obj3D_InvisibleLauncher:
lea (MainCharacter).w,a1 ; a1=character
lea objoff_2C(a0),a4
bsr.s loc_24F74
lea (Sidekick).w,a1 ; a1=character
lea objoff_36(a0),a4
bsr.s loc_24F74
move.b objoff_2C(a0),d0
add.b objoff_36(a0),d0
beq.w JmpTo3_MarkObjGone3
rts
; ===========================================================================
loc_24F74:
moveq #0,d0
move.b (a4),d0
move.w off_24F80(pc,d0.w),d0
jmp off_24F80(pc,d0.w)
; ===========================================================================
off_24F80: offsetTable
offsetTableEntry.w loc_24F84 ; 0
offsetTableEntry.w loc_25036 ; 2
; ===========================================================================
loc_24F84:
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
addi.w #$10,d0
cmpi.w #$20,d0
bhs.w return_25034
move.w y_pos(a1),d1
sub.w y_pos(a0),d1
tst.b subtype(a0)
beq.s loc_24FAA
addi.w #$10,d1
loc_24FAA:
cmpi.w #$10,d1
bhs.w return_25034
cmpa.w #Sidekick,a1
bne.s loc_24FC2
cmpi.w #4,(Tails_CPU_routine).w ; TailsCPU_Flying
beq.w return_25034
loc_24FC2:
addq.b #2,(a4)
move.b #$81,obj_control(a1)
move.b #AniIDSonAni_Roll,anim(a1)
move.w #$800,inertia(a1)
tst.b subtype(a0)
beq.s loc_24FF0
move.w x_pos(a0),x_pos(a1)
move.w #0,x_vel(a1)
move.w #-$800,y_vel(a1)
bra.s loc_25002
; ===========================================================================
loc_24FF0:
move.w y_pos(a0),y_pos(a1)
move.w #$800,x_vel(a1)
move.w #0,y_vel(a1)
loc_25002:
bclr #5,status(a0)
bclr #5,status(a1)
bset #1,status(a1)
bset #3,status(a1)
move.w a0,d0
subi.w #Object_RAM,d0
if object_size=$40
lsr.w #6,d0
else
divu.w #object_size,d0
endif
andi.w #$7F,d0
move.b d0,interact(a1)
move.w #SndID_Roll,d0
jsr (PlaySound).l
return_25034:
rts
; ===========================================================================
loc_25036:
tst.b render_flags(a1)
bmi.s Obj3D_MoveCharacter
move.b #0,obj_control(a1)
bset #1,status(a1)
bclr #3,status(a1)
move.b #0,(a4)
rts
; ===========================================================================
; update the position of Sonic/Tails from the block thing to the launcher
; loc_25054:
Obj3D_MoveCharacter:
move.l x_pos(a1),d2
move.l y_pos(a1),d3
move.w x_vel(a1),d0
ext.l d0
asl.l #8,d0
add.l d0,d2
move.w y_vel(a1),d0
ext.l d0
asl.l #8,d0
add.l d0,d3
move.l d2,x_pos(a1)
move.l d3,y_pos(a1)
rts
; ===========================================================================
word_2507A:
dc.w -$400,-$400 ; 0
dc.w -$200,-$400 ; 2
dc.w $200,-$400 ; 4
dc.w $400,-$400 ; 6
dc.w -$3C0,-$200 ; 8
dc.w -$1C0,-$200 ; 10
dc.w $1C0,-$200 ; 12
dc.w $3C0,-$200 ; 14
dc.w -$380, $200 ; 16
dc.w -$180, $200 ; 18
dc.w $180, $200 ; 20
dc.w $380, $200 ; 22
dc.w -$340, $400 ; 24
dc.w -$140, $400 ; 26
dc.w $140, $400 ; 28
dc.w $340, $400 ; 30
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj3D_MapUnc_250BA: BINCLUDE "mappings/sprite/obj3D.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo14_DisplaySprite
jmp (DisplaySprite).l
JmpTo26_DeleteObject
jmp (DeleteObject).l
JmpTo13_MarkObjGone
jmp (MarkObjGone).l
JmpTo9_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo3_MarkObjGone3
jmp (MarkObjGone3).l
JmpTo22_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo2_BreakObjectToPieces
jmp (BreakObjectToPieces).l
JmpTo7_SolidObject
jmp (SolidObject).l
; loc_2523C:
JmpTo10_ObjectMove
jmp (ObjectMove).l
align 4
else
JmpTo3_MarkObjGone3
jmp (MarkObjGone3).l
JmpTo26_DeleteObject
jmp (DeleteObject).l
; Unused
;JmpTo13_MarkObjGone
jmp (MarkObjGone).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 48 - Round ball thing from OOZ that fires you off in a different direction (sphere)
; ----------------------------------------------------------------------------
; Sprite_25244:
Obj48:
moveq #0,d0
move.b routine(a0),d0
move.w Obj48_Index(pc,d0.w),d1
jsr Obj48_Index(pc,d1.w)
move.b objoff_2C(a0),d0
add.b objoff_36(a0),d0
beq.w JmpTo14_MarkObjGone
jmpto (DisplaySprite).l, JmpTo15_DisplaySprite
if removeJmpTos
JmpTo14_MarkObjGone
jmp (MarkObjGone).l
endif
; ===========================================================================
; off_25262:
Obj48_Index: offsetTable
offsetTableEntry.w Obj48_Init ; 0
offsetTableEntry.w Obj48_Main ; 2
; ===========================================================================
; byte_25266:
Obj48_Properties:
; render_flags
; objoff_3F
dc.b 4, 0 ; 0
dc.b 6, 7 ; 2
dc.b 7, 0 ; 4
dc.b 5, 7 ; 6
dc.b 5, 0 ; 8
dc.b 4, 7 ; 10
dc.b 6, 0 ; 12
dc.b 7, 7 ; 14
; ===========================================================================
; loc_25276:
Obj48_Init:
addq.b #2,routine(a0)
move.l #Obj48_MapUnc_254FE,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_LaunchBall,3,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo23_Adjust2PArtPointer
move.b subtype(a0),d0
andi.w #$F,d0
btst #0,status(a0)
beq.s +
addq.w #4,d0
+
add.w d0,d0
move.b Obj48_Properties(pc,d0.w),render_flags(a0)
move.b Obj48_Properties+1(pc,d0.w),objoff_3F(a0)
beq.s +
move.b #1,objoff_3E(a0)
+
move.b objoff_3F(a0),mapping_frame(a0)
move.b #$28,width_pixels(a0)
move.b #1,priority(a0)
; loc_252C6:
Obj48_Main:
lea (MainCharacter).w,a1 ; a1=character
lea objoff_2C(a0),a4
moveq #objoff_2C,d2
bsr.s loc_252DC
lea (Sidekick).w,a1 ; a1=character
lea objoff_36(a0),a4
moveq #objoff_36,d2
loc_252DC:
moveq #0,d0
move.b (a4),d0
move.w Obj48_Modes(pc,d0.w),d0
jmp Obj48_Modes(pc,d0.w)
; ===========================================================================
; off_252E8:
Obj48_Modes: offsetTable
offsetTableEntry.w loc_252F0 ; 0
offsetTableEntry.w loc_253C6 ; 2
offsetTableEntry.w loc_25474 ; 4
offsetTableEntry.w loc_254F2 ; 6
; ===========================================================================
loc_252F0:
tst.w (Debug_placement_mode).w
bne.w return_253C4
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
addi.w #$10,d0
cmpi.w #$20,d0
bhs.w return_253C4
move.w y_pos(a1),d1
sub.w y_pos(a0),d1
addi.w #$10,d1
cmpi.w #$20,d1
bhs.w return_253C4
cmpa.w #Sidekick,a1
bne.s +
cmpi.w #4,(Tails_CPU_routine).w ; TailsCPU_Flying
beq.w return_253C4
+
cmpi.b #6,routine(a1)
bhs.w return_253C4
tst.w (Debug_placement_mode).w
bne.w return_253C4
btst #3,status(a1)
beq.s +
moveq #0,d0
move.b interact(a1),d0
if object_size=$40
lsl.w #6,d0
else
mulu.w #object_size,d0
endif
addi.l #Object_RAM,d0
movea.l d0,a3 ; a3=object
move.b #0,(a3,d2.w)
+
move.w a0,d0
subi.w #Object_RAM,d0
if object_size=$40
lsr.w #6,d0
else
divu.w #object_size,d0
endif
andi.w #$7F,d0
move.b d0,interact(a1)
addq.b #2,(a4)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.b #$81,obj_control(a1)
move.b #2,anim(a1)
move.w #$1000,inertia(a1)
move.w #0,x_vel(a1)
move.w #0,y_vel(a1)
bclr #5,status(a0)
bclr #5,status(a1)
bset #1,status(a1)
bset #3,status(a1)
move.b objoff_3F(a0),mapping_frame(a0)
move.w #SndID_Roll,d0
jsr (PlaySound).l
return_253C4:
rts
; ===========================================================================
loc_253C6:
tst.b objoff_3E(a0)
bne.s loc_253EE
cmpi.b #7,mapping_frame(a0)
beq.s loc_25408
subq.w #1,anim_frame_duration(a0)
bpl.s return_253EC
move.w #7,anim_frame_duration(a0)
addq.b #1,mapping_frame(a0)
cmpi.b #7,mapping_frame(a0)
beq.s loc_25408
return_253EC:
rts
; ===========================================================================
loc_253EE:
tst.b mapping_frame(a0)
beq.s loc_25408
subq.w #1,anim_frame_duration(a0)
bpl.s return_253EC
move.w #7,anim_frame_duration(a0)
subq.b #1,mapping_frame(a0)
beq.s loc_25408
rts
; ===========================================================================
loc_25408:
addq.b #2,(a4)
move.b subtype(a0),d0
addq.b #1,d0
btst #0,status(a0)
beq.s +
subq.b #2,d0
+
andi.w #3,d0
add.w d0,d0
add.w d0,d0
move.w word_25464(pc,d0.w),x_vel(a1)
move.w word_25464+2(pc,d0.w),y_vel(a1)
move.w #3,anim_frame_duration(a0)
tst.b subtype(a0)
bpl.s return_25462
move.b #0,obj_control(a1)
bset #1,status(a1)
bclr #3,status(a1)
move.b #0,jumping(a1)
move.b #2,routine(a1)
move.b #6,(a4)
move.w #7,objoff_3C(a0)
return_25462:
rts
; ===========================================================================
word_25464:
dc.w 0,-$1000
dc.w $1000, 0 ; 2
dc.w 0, $1000 ; 4
dc.w -$1000, 0 ; 6
; ===========================================================================
loc_25474:
tst.b render_flags(a1)
bmi.s loc_25492
move.b #0,obj_control(a1)
bset #1,status(a1)
bclr #3,status(a1)
move.b #0,(a4)
rts
; ===========================================================================
loc_25492:
cmpi.b #2,objoff_2C(a0)
beq.s Obj48_MoveCharacter
cmpi.b #2,objoff_36(a0)
beq.s Obj48_MoveCharacter
subq.w #1,anim_frame_duration(a0)
bpl.s Obj48_MoveCharacter
move.w #1,anim_frame_duration(a0)
tst.b objoff_3E(a0)
beq.s loc_254C2
cmpi.b #7,mapping_frame(a0)
beq.s Obj48_MoveCharacter
addq.b #1,mapping_frame(a0)
bra.s Obj48_MoveCharacter
; ===========================================================================
loc_254C2:
tst.b mapping_frame(a0)
beq.s Obj48_MoveCharacter
subq.b #1,mapping_frame(a0)
; update the position of Sonic/Tails between launchers
; loc_254CC:
Obj48_MoveCharacter:
move.l x_pos(a1),d2
move.l y_pos(a1),d3
move.w x_vel(a1),d0
ext.l d0
asl.l #8,d0
add.l d0,d2
move.w y_vel(a1),d0
ext.l d0
asl.l #8,d0
add.l d0,d3
move.l d2,x_pos(a1)
move.l d3,y_pos(a1)
rts
; ===========================================================================
loc_254F2:
subq.w #1,objoff_3C(a0)
bpl.s + ; rts
move.b #0,(a4)
+
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj48_MapUnc_254FE: BINCLUDE "mappings/sprite/obj48.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo15_DisplaySprite
jmp (DisplaySprite).l
JmpTo14_MarkObjGone
jmp (MarkObjGone).l
JmpTo23_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 22 - Arrow shooter from ARZ
; ----------------------------------------------------------------------------
; Sprite_25694:
Obj22:
moveq #0,d0
move.b routine(a0),d0
move.w Obj22_Index(pc,d0.w),d1
jmp Obj22_Index(pc,d1.w)
; ===========================================================================
; off_256A2:
Obj22_Index: offsetTable
offsetTableEntry.w Obj22_Init ; 0
offsetTableEntry.w Obj22_Main ; 2
offsetTableEntry.w Obj22_ShootArrow ; 4
offsetTableEntry.w Obj22_Arrow_Init ; 6
offsetTableEntry.w Obj22_Arrow ; 8
; ===========================================================================
; loc_256AC:
Obj22_Init:
addq.b #2,routine(a0)
move.l #Obj22_MapUnc_25804,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_ArrowAndShooter,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo24_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #3,priority(a0)
move.b #$10,width_pixels(a0)
move.b #1,mapping_frame(a0)
andi.b #$F,subtype(a0)
; loc_256E0:
Obj22_Main:
cmpi.b #2,anim(a0)
beq.s Obj22_Animate
moveq #0,d2
lea (MainCharacter).w,a1 ; a1=character
bsr.s Obj22_DetectPlayer
lea (Sidekick).w,a1 ; a1=character
bsr.s Obj22_DetectPlayer
tst.b d2
bne.s +
tst.b anim(a0)
beq.s +
moveq #2,d2
+
move.b d2,anim(a0)
; loc_25706:
Obj22_Animate:
lea (Ani_obj22).l,a1
jsrto (AnimateSprite).l, JmpTo5_AnimateSprite
jmpto (MarkObjGone).l, JmpTo15_MarkObjGone
; ===========================================================================
; loc_25714:
Obj22_DetectPlayer:
move.w x_pos(a0),d0
sub.w x_pos(a1),d0 ; is the player on the left of the shooter?
bcc.s + ; if yes, branch
neg.w d0
+
cmpi.w #$40,d0 ; is the player within $40 pixels of the shooter?
bhs.s + ; if not, branch
moveq #1,d2 ; change the shooter's animation
+
rts
; ===========================================================================
; loc_2572A:
Obj22_ShootArrow:
jsrto (SingleObjLoad).l, JmpTo5_SingleObjLoad
bne.s +
_move.b id(a0),id(a1) ; load obj22
addq.b #6,routine(a1)
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.b render_flags(a0),render_flags(a1)
move.b status(a0),status(a1)
move.w #SndID_PreArrowFiring,d0
jsr (PlaySound).l
+
subq.b #2,routine(a0)
lea (Ani_obj22).l,a1
jsrto (AnimateSprite).l, JmpTo5_AnimateSprite
jmpto (MarkObjGone).l, JmpTo15_MarkObjGone
; ===========================================================================
; loc_2577A:
Obj22_Arrow_Init:
addq.b #2,routine(a0)
move.b #8,y_radius(a0)
move.b #$10,x_radius(a0)
move.b #4,priority(a0)
move.b #$9B,collision_flags(a0)
move.b #8,width_pixels(a0)
move.b #0,mapping_frame(a0)
move.w #$400,x_vel(a0)
btst #0,status(a0)
beq.s +
neg.w x_vel(a0)
+
move.w #SndID_ArrowFiring,d0
jsr (PlaySound).l
; loc_257BE:
Obj22_Arrow:
jsrto (ObjectMove).l, JmpTo11_ObjectMove
btst #0,status(a0)
bne.s loc_257DE
moveq #-8,d3
bsr.w ObjCheckLeftWallDist
tst.w d1
bmi.w BranchTo_JmpTo27_DeleteObject
jmpto (MarkObjGone).l, JmpTo15_MarkObjGone
; ===========================================================================
BranchTo_JmpTo27_DeleteObject
jmpto (DeleteObject).l, JmpTo27_DeleteObject
; ===========================================================================
loc_257DE:
moveq #8,d3
bsr.w ObjCheckRightWallDist
tst.w d1
bmi.w BranchTo_JmpTo27_DeleteObject
jmpto (MarkObjGone).l, JmpTo15_MarkObjGone
; ===========================================================================
; animation script
; off_257EE:
Ani_obj22: offsetTable
offsetTableEntry.w byte_257F4 ; 0
offsetTableEntry.w byte_257F7 ; 1
offsetTableEntry.w byte_257FB ; 2
byte_257F4: dc.b $1F, 1,$FF
rev02even
byte_257F7: dc.b 3, 1, 2,$FF
rev02even
byte_257FB: dc.b 7, 3, 4,$FC, 4, 3, 1,$FD, 0
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj22_MapUnc_25804: BINCLUDE "mappings/sprite/obj22.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo27_DeleteObject
jmp (DeleteObject).l
JmpTo5_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo15_MarkObjGone
jmp (MarkObjGone).l
JmpTo5_AnimateSprite
jmp (AnimateSprite).l
JmpTo24_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
; loc_25886:
JmpTo11_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 23 - Pillar that drops its lower part from ARZ
; ----------------------------------------------------------------------------
; Sprite_2588C:
Obj23:
moveq #0,d0
move.b routine(a0),d0
move.w Obj23_Index(pc,d0.w),d1
jmp Obj23_Index(pc,d1.w)
; ===========================================================================
; off_2589A:
Obj23_Index: offsetTable
offsetTableEntry.w Obj23_Init ; 0
offsetTableEntry.w Obj23_Main ; 2
; ===========================================================================
; loc_2589E:
Obj23_Init:
addq.b #2,routine(a0)
move.l #Obj23_MapUnc_259E6,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,1,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo25_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #$20,y_radius(a0)
move.b #4,priority(a0)
jsrto (SingleObjLoad2).l, JmpTo10_SingleObjLoad2
bne.s Obj23_Main
_move.b id(a0),id(a1) ; load obj23
addq.b #2,routine(a1)
addq.b #2,routine_secondary(a1)
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
move.w x_pos(a0),x_pos(a1)
move.w x_pos(a0),objoff_30(a1)
move.w y_pos(a0),y_pos(a1)
addi.w #$30,y_pos(a1)
move.b render_flags(a0),render_flags(a1)
move.b #$10,width_pixels(a1)
move.b #$10,y_radius(a1)
move.b #4,priority(a1)
move.b #1,mapping_frame(a1)
; loc_25922:
Obj23_Main:
move.w x_pos(a0),-(sp)
bsr.w loc_25948
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
move.w (sp)+,d4
jsrto (SolidObject).l, JmpTo8_SolidObject
jmpto (MarkObjGone).l, JmpTo16_MarkObjGone
; ===========================================================================
loc_25948:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj23_Modes(pc,d0.w),d1
jmp Obj23_Modes(pc,d1.w)
; ===========================================================================
; off_25956:
Obj23_Modes: offsetTable
offsetTableEntry.w return_2598C ; 0
offsetTableEntry.w loc_2595E ; 2
offsetTableEntry.w loc_2598E ; 4
offsetTableEntry.w loc_259B8 ; 6
; ===========================================================================
loc_2595E:
tst.w (Debug_placement_mode).w
bne.s return_2598C
lea (MainCharacter).w,a1 ; a1=character
bsr.s loc_2596E
lea (Sidekick).w,a1 ; a1=character
loc_2596E:
move.w x_pos(a0),d0
sub.w x_pos(a1),d0
bcc.s +
neg.w d0
+
cmpi.w #$80,d0
bhs.s return_2598C
move.b #4,routine_secondary(a0)
move.w #8,objoff_34(a0)
return_2598C:
rts
; ===========================================================================
loc_2598E:
move.w objoff_34(a0),d0
subq.w #1,d0
bcc.s loc_2599C
addq.b #2,routine_secondary(a0)
rts
; ===========================================================================
loc_2599C:
move.w d0,objoff_34(a0)
move.b byte_259B0(pc,d0.w),d0
ext.w d0
add.w objoff_30(a0),d0
move.w d0,x_pos(a0)
rts
; ===========================================================================
byte_259B0:
dc.b 0 ; 0
dc.b 1 ; 1
dc.b -1 ; 2
dc.b 1 ; 3
dc.b 0 ; 4
dc.b -1 ; 5
dc.b 0 ; 6
dc.b 1 ; 7
; ===========================================================================
loc_259B8:
jsrto (ObjectMove).l, JmpTo12_ObjectMove
addi.w #$38,y_vel(a0)
bsr.w ObjCheckFloorDist
tst.w d1
bpl.w +
add.w d1,y_pos(a0)
clr.w y_vel(a0)
move.w y_pos(a0),objoff_32(a0)
move.b #2,mapping_frame(a0)
clr.b routine_secondary(a0)
+
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj23_MapUnc_259E6: BINCLUDE "mappings/sprite/obj23.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 2B - Rising pillar from ARZ
; ----------------------------------------------------------------------------
; Sprite_25A5A:
Obj2B:
moveq #0,d0
move.b routine(a0),d0
move.w Obj2B_Index(pc,d0.w),d1
jmp Obj2B_Index(pc,d1.w)
; ===========================================================================
; off_25A68:
Obj2B_Index: offsetTable
offsetTableEntry.w Obj2B_Init ; 0
offsetTableEntry.w Obj2B_Main ; 2
offsetTableEntry.w loc_25B8E ; 4
; ===========================================================================
; loc_25A6E:
Obj2B_Init:
addq.b #2,routine(a0)
move.l #Obj2B_MapUnc_25C6E,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,1,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo25_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #$18,y_radius(a0)
move.b #4,priority(a0)
; loc_25A9C:
Obj2B_Main:
move.w x_pos(a0),-(sp)
bsr.w loc_25B28
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
move.w (sp)+,d4
jsrto (SolidObject).l, JmpTo8_SolidObject
move.b status(a0),d0
andi.b #standing_mask,d0
bne.w loc_25ACE
jmpto (MarkObjGone).l, JmpTo16_MarkObjGone
; ===========================================================================
loc_25ACE:
lea (word_25BBE).l,a4
lea (byte_25BB0).l,a2
addq.b #7,mapping_frame(a0)
bsr.w loc_25BF6
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
bsr.s loc_25AF6
lea (Sidekick).w,a1 ; a1=character
addq.b #1,d6
bsr.s loc_25AF6
bra.w loc_25B8E
; ===========================================================================
loc_25AF6:
bclr d6,status(a0)
beq.s return_25B26
bset #2,status(a1)
move.b #$E,y_radius(a1)
move.b #7,x_radius(a1)
move.b #AniIDSonAni_Roll,anim(a1)
bset #1,status(a1)
bclr #3,status(a1)
move.b #2,routine(a1)
return_25B26:
rts
; ===========================================================================
loc_25B28:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_25B36(pc,d0.w),d1
jmp off_25B36(pc,d1.w)
; ===========================================================================
off_25B36: offsetTable
offsetTableEntry.w loc_25B3C ; 0
offsetTableEntry.w loc_25B66 ; 2
offsetTableEntry.w return_25B64 ; 4
; ===========================================================================
loc_25B3C:
tst.w (Debug_placement_mode).w
bne.s return_25B64
lea (MainCharacter).w,a1 ; a1=character
bsr.s loc_25B4C
lea (Sidekick).w,a1 ; a1=character
loc_25B4C:
move.w x_pos(a0),d0
sub.w x_pos(a1),d0
bcc.s loc_25B58
neg.w d0
loc_25B58:
cmpi.w #$40,d0
bhs.s return_25B64
move.b #2,routine_secondary(a0)
return_25B64:
rts
; ===========================================================================
loc_25B66:
subq.w #1,objoff_34(a0)
bcc.s return_25B8C
move.w #3,objoff_34(a0)
subq.w #4,y_pos(a0)
addq.b #4,y_radius(a0)
addq.b #1,mapping_frame(a0)
cmpi.b #6,mapping_frame(a0)
bne.s return_25B8C
move.b #4,routine_secondary(a0)
return_25B8C:
rts
; ===========================================================================
loc_25B8E:
tst.b objoff_3F(a0)
beq.s loc_25B9A
subq.b #1,objoff_3F(a0)
bra.s loc_25BA4
; ===========================================================================
loc_25B9A:
jsrto (ObjectMove).l, JmpTo12_ObjectMove
addi.w #$18,y_vel(a0)
loc_25BA4:
tst.b render_flags(a0)
bpl.w JmpTo28_DeleteObject
jmpto (DisplaySprite).l, JmpTo16_DisplaySprite
; ===========================================================================
byte_25BB0:
dc.b 0
dc.b 0 ; 1
dc.b 0 ; 2
dc.b 0 ; 3
dc.b 4 ; 4
dc.b 4 ; 5
dc.b 8 ; 6
dc.b 8 ; 7
dc.b $C ; 8
dc.b $C ; 9
dc.b $10 ; 10
dc.b $10 ; 11
dc.b $14 ; 12
dc.b $14 ; 13
word_25BBE:
dc.w -$200,-$200,$200,-$200 ; 0
dc.w -$1C0,-$1C0,$1C0,-$1C0 ; 4
dc.w -$180,-$180,$180,-$180 ; 8
dc.w -$140,-$140,$140,-$140 ; 12
dc.w -$100,-$100,$100,-$100 ; 16
dc.w -$C0, -$C0, $C0, -$C0 ; 20
dc.w -$80, -$80, $80, -$80 ; 24
; ===========================================================================
loc_25BF6:
moveq #0,d0
move.b mapping_frame(a0),d0
add.w d0,d0
movea.l mappings(a0),a3
adda.w (a3,d0.w),a3
move.w (a3)+,d1
subq.w #1,d1
bset #5,render_flags(a0)
_move.b id(a0),d4
move.b render_flags(a0),d5
movea.l a0,a1
bra.s loc_25C24
; ===========================================================================
loc_25C1C:
jsrto (SingleObjLoad2).l, JmpTo10_SingleObjLoad2
bne.s loc_25C64
addq.w #8,a3
loc_25C24:
move.b #4,routine(a1)
_move.b d4,id(a1) ; load obj2B?
move.l a3,mappings(a1)
move.b d5,render_flags(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w art_tile(a0),art_tile(a1)
move.b priority(a0),priority(a1)
move.b width_pixels(a0),width_pixels(a1)
move.w (a4)+,x_vel(a1)
move.w (a4)+,y_vel(a1)
move.b (a2)+,objoff_3F(a1)
dbf d1,loc_25C1C
loc_25C64:
move.w #SndID_SlowSmash,d0
jmp (PlaySound).l
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj2B_MapUnc_25C6E: BINCLUDE "mappings/sprite/obj2B.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo16_DisplaySprite
jmp (DisplaySprite).l
JmpTo28_DeleteObject
jmp (DeleteObject).l
JmpTo16_MarkObjGone
jmp (MarkObjGone).l
JmpTo10_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo25_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo8_SolidObject
jmp (SolidObject).l
; loc_260FC:
JmpTo12_ObjectMove
jmp (ObjectMove).l
align 4
else
JmpTo28_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 2C - Sprite that makes leaves fly off when you hit it from ARZ
; ----------------------------------------------------------------------------
; Sprite_26104:
Obj2C:
moveq #0,d0
move.b routine(a0),d0
move.w Obj2C_Index(pc,d0.w),d1
jmp Obj2C_Index(pc,d1.w)
; ===========================================================================
; off_26112:
Obj2C_Index: offsetTable
offsetTableEntry.w Obj2C_Init ; 0
offsetTableEntry.w Obj2C_Main ; 2
offsetTableEntry.w loc_26296 ; 4
; ===========================================================================
; byte_26118:
Obj2C_CollisionFlags:
dc.b $D6
dc.b $D4 ; 1
dc.b $D5 ; 2
dc.b 0 ; 3
; ===========================================================================
; loc_2611C:
Obj2C_Init:
addq.b #2,routine(a0)
moveq #0,d0
move.b subtype(a0),d0
move.b Obj2C_CollisionFlags(pc,d0.w),collision_flags(a0)
move.l #Obj31_MapUnc_20E74,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Powerups,0,1),art_tile(a0)
move.b #$84,render_flags(a0)
move.b #$80,width_pixels(a0)
move.b #4,priority(a0)
move.b subtype(a0),mapping_frame(a0)
; loc_26152:
Obj2C_Main:
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w JmpTo29_DeleteObject
move.b collision_property(a0),d0
beq.s loc_261C2
move.w objoff_2E(a0),d0
beq.s +
add.b (Timer_frames+1).w,d0
andi.w #$F,d0
bne.s loc_26198
+
lea (MainCharacter).w,a2 ; a2=character
bclr #0,collision_property(a0)
beq.s Obj2C_RemoveCollision
bsr.s loc_261C8
tst.w objoff_2E(a0)
bne.s Obj2C_RemoveCollision
move.w (Timer_frames).w,objoff_2E(a0)
bra.s Obj2C_RemoveCollision
; ===========================================================================
loc_26198:
addi_.w #8,d0
andi.w #$F,d0
bne.s Obj2C_RemoveCollision
lea (Sidekick).w,a2 ; a2=character
bclr #1,collision_property(a0)
beq.s Obj2C_RemoveCollision
bsr.s loc_261C8
tst.w objoff_2E(a0)
bne.s Obj2C_RemoveCollision
move.w (Timer_frames).w,objoff_2E(a0)
; loc_261BC:
Obj2C_RemoveCollision:
clr.b collision_property(a0)
rts
; ===========================================================================
loc_261C2:
clr.w objoff_2E(a0)
rts
; ===========================================================================
loc_261C8:
mvabs.w x_vel(a2),d0
cmpi.w #$200,d0
bhs.s loc_261E4
mvabs.w y_vel(a2),d0
cmpi.w #$200,d0
blo.s loc_261C2
loc_261E4:
lea (Obj2C_Speeds).l,a3
moveq #3,d6
loc_261EC:
jsrto (SingleObjLoad).l, JmpTo6_SingleObjLoad
bne.w loc_26278
_move.b #ObjID_LeavesGenerator,id(a1) ; load obj2C
move.b #4,routine(a1)
move.w x_pos(a2),x_pos(a1)
move.w y_pos(a2),y_pos(a1)
jsrto (RandomNumber).l, JmpTo2_RandomNumber
andi.w #$F,d0
subq.w #8,d0
add.w d0,x_pos(a1)
swap d0
andi.w #$F,d0
subq.w #8,d0
add.w d0,y_pos(a1)
move.w (a3)+,x_vel(a1)
move.w (a3)+,y_vel(a1)
btst #0,status(a2)
beq.s +
neg.w x_vel(a1)
+
move.w x_pos(a1),objoff_30(a1)
move.w y_pos(a1),objoff_34(a1)
andi.b #1,d0
move.b d0,mapping_frame(a1)
move.l #Obj2C_MapUnc_2631E,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_Leaves,3,1),art_tile(a1)
move.b #$84,render_flags(a1)
move.b #8,width_pixels(a1)
move.b #1,priority(a1)
move.b #4,objoff_38(a1)
move.b d1,angle(a0)
loc_26278:
dbf d6,loc_261EC
move.w #SndID_Leaves,d0
jmp (PlaySound).l
; ===========================================================================
; byte_26286: word_26286:
Obj2C_Speeds:
dc.w -$80,-$80 ; 0
dc.w $C0,-$40 ; 1
dc.w -$C0, $40 ; 2
dc.w $80, $80 ; 3
; ===========================================================================
loc_26296:
move.b objoff_38(a0),d0
add.b d0,angle(a0)
add.b (Vint_runcount+3).w,d0
andi.w #$1F,d0
bne.s +
add.b d7,d0
andi.b #1,d0
beq.s +
neg.b objoff_38(a0)
+
move.l objoff_30(a0),d2
move.l objoff_34(a0),d3
move.w x_vel(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d2
move.w y_vel(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d3
move.l d2,objoff_30(a0)
move.l d3,objoff_34(a0)
swap d2
andi.w #3,d3
addq.w #4,d3
add.w d3,y_vel(a0)
move.b angle(a0),d0
jsrto (CalcSine).l, JmpTo7_CalcSine
asr.w #6,d0
add.w objoff_30(a0),d0
move.w d0,x_pos(a0)
asr.w #6,d1
add.w objoff_34(a0),d1
move.w d1,y_pos(a0)
subq.b #1,anim_frame_duration(a0)
bpl.s +
move.b #$B,anim_frame_duration(a0)
bchg #1,mapping_frame(a0)
+
tst.b render_flags(a0)
bpl.w JmpTo29_DeleteObject
jmpto (DisplaySprite).l, JmpTo17_DisplaySprite
if removeJmpTos
JmpTo29_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj2C_MapUnc_2631E: BINCLUDE "mappings/sprite/obj2C.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo17_DisplaySprite
jmp (DisplaySprite).l
JmpTo29_DeleteObject
jmp (DeleteObject).l
JmpTo6_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo2_RandomNumber
jmp (RandomNumber).l
JmpTo7_CalcSine
jmp (CalcSine).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 40 - Pressure spring from CPZ, ARZ, and MCZ (the red "diving board" springboard)
; ----------------------------------------------------------------------------
; Sprite_26370:
Obj40:
moveq #0,d0
move.b routine(a0),d0
move.w Obj40_Index(pc,d0.w),d1
jsr Obj40_Index(pc,d1.w)
jmpto (MarkObjGone).l, JmpTo17_MarkObjGone
; ===========================================================================
; off_26382:
Obj40_Index: offsetTable
offsetTableEntry.w Obj40_Init ; 0
offsetTableEntry.w Obj40_Main ; 2
; ---------------------------------------------------------------------------
; it seems this object's strength was once controlled by subtype
; these would be applied to the player's y_vel
; word_26386:
Obj40_Strengths:
dc.w -$400 ; 0
dc.w -$A00 ; 2
; inaccessible
dc.w -$800 ; 4
; ===========================================================================
; loc_2638C:
Obj40_Init:
addq.b #2,routine(a0)
move.l #Obj40_MapUnc_265F4,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_LeverSpring,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo26_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$1C,width_pixels(a0)
move.b #4,priority(a0)
bset #7,status(a0)
move.b subtype(a0),d0
andi.w #2,d0 ; there is enough data for this to be capped at 4
move.w Obj40_Strengths(pc,d0.w),objoff_30(a0) ; this is never read
; loc_263C8:
Obj40_Main:
lea (Ani_obj40).l,a1
jsrto (AnimateSprite).l, JmpTo6_AnimateSprite
move.w #$27,d1
move.w #8,d2
move.w x_pos(a0),d4
lea Obj40_SlopeData_DiagUp(pc),a2
tst.b mapping_frame(a0)
beq.s +
lea Obj40_SlopeData_Straight(pc),a2
+
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
jsrto (SlopedSolid_SingleCharacter).l, JmpTo_SlopedSolid_SingleCharacter
btst #p1_standing_bit,status(a0)
beq.s +
bsr.s loc_2641E
+
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
jsrto (SlopedSolid_SingleCharacter).l, JmpTo_SlopedSolid_SingleCharacter
btst #p2_standing_bit,status(a0)
beq.s + ; rts
bsr.s loc_2641E
+
rts
; ===========================================================================
loc_2641E:
btst #0,status(a0)
bne.s loc_26436
move.w x_pos(a0),d0
subi.w #$10,d0
cmp.w x_pos(a1),d0
blo.s loc_26446
rts
; ===========================================================================
loc_26436:
move.w x_pos(a0),d0
addi.w #$10,d0
cmp.w x_pos(a1),d0
bhs.s loc_26446
rts
; ===========================================================================
loc_26446:
cmpi.b #1,anim(a0)
beq.s loc_26456
move.w #$100,anim(a0)
rts
; ===========================================================================
loc_26456:
tst.b mapping_frame(a0)
beq.s loc_2645E
rts
; ===========================================================================
loc_2645E:
move.w x_pos(a0),d0
subi.w #$1C,d0
sub.w x_pos(a1),d0
neg.w d0
btst #0,status(a0)
beq.s loc_2647A
not.w d0
addi.w #$27,d0
loc_2647A:
tst.w d0
bpl.s loc_26480
moveq #0,d0
loc_26480:
lea (byte_26550).l,a3
move.b (a3,d0.w),d0
move.w #-$400,y_vel(a1)
sub.b d0,y_vel(a1)
bset #0,status(a1)
btst #0,status(a0)
bne.s loc_264AA
bclr #0,status(a1)
neg.b d0
loc_264AA:
mvabs.w x_vel(a1),d1
cmpi.w #$400,d1
blo.s loc_264BC
sub.b d0,x_vel(a1)
loc_264BC:
bset #1,status(a1)
bclr #3,status(a1)
move.b #AniIDSonAni_Spring,anim(a1)
move.b #2,routine(a1)
move.b #0,spindash_flag(a1)
move.b subtype(a0),d0
btst #0,d0
beq.s loc_2651E
move.w #1,inertia(a1)
move.b #1,flip_angle(a1)
move.b #AniIDSonAni_Walk,anim(a1)
move.b #1,flips_remaining(a1)
move.b #8,flip_speed(a1)
btst #1,d0
bne.s loc_2650E
move.b #3,flips_remaining(a1)
loc_2650E:
btst #0,status(a1)
beq.s loc_2651E
neg.b flip_angle(a1)
neg.w inertia(a1)
loc_2651E:
andi.b #$C,d0
cmpi.b #4,d0
bne.s loc_26534
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
loc_26534:
cmpi.b #8,d0
bne.s loc_26546
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
loc_26546:
move.w #SndID_Spring,d0
jmp (PlaySound).l
; ===========================================================================
byte_26550:
dc.b 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
dc.b 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1; 16
dc.b 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2; 32
dc.b 3, 3, 3, 3, 3, 3, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0; 48
dc.b 0, 0, 0, 0, 0, 0, 0, 0; 64
;byte_26598:
Obj40_SlopeData_DiagUp:
dc.b 8, 8, 8, 8, 8, 8, 8, 9, $A, $B, $C, $D, $E, $F,$10,$10
dc.b $11,$12,$13,$14,$14,$15,$15,$16,$17,$18,$18,$18,$18,$18,$18,$18; 16
dc.b $18,$18,$18,$18,$18,$18,$18,$18; 32
;byte_265C0:
Obj40_SlopeData_Straight:
dc.b 8, 8, 8, 8, 8, 8, 8, 9, $A, $B, $C, $C, $C, $C, $D, $D
dc.b $D, $D, $D, $D, $E, $E, $F, $F,$10,$10,$10,$10, $F, $F, $E, $E; 16
dc.b $D, $D, $D, $D, $D, $D, $D, $D; 32
; animation script
; off_265E8:
Ani_obj40: offsetTable
offsetTableEntry.w byte_265EC ; 0
offsetTableEntry.w byte_265EF ; 1
byte_265EC: dc.b $F, 0,$FF
rev02even
byte_265EF: dc.b 3, 1, 0,$FD, 0
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj40_MapUnc_265F4: BINCLUDE "mappings/sprite/obj40.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo17_MarkObjGone
jmp (MarkObjGone).l
JmpTo6_AnimateSprite
jmp (AnimateSprite).l
JmpTo26_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo_SlopedSolid_SingleCharacter
jmp (SlopedSolid_SingleCharacter).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 42 - Steam Spring from MTZ
; ----------------------------------------------------------------------------
; Sprite_26634:
Obj42:
moveq #0,d0
move.b routine(a0),d0
move.w Obj42_Index(pc,d0.w),d1
jmp Obj42_Index(pc,d1.w)
; ===========================================================================
; off_26642:
Obj42_Index: offsetTable
offsetTableEntry.w Obj42_Init ; 0
offsetTableEntry.w loc_26688 ; 2
offsetTableEntry.w loc_2683A ; 4
; ===========================================================================
; loc_26648:
Obj42_Init:
addq.b #2,routine(a0)
move.l #Obj42_MapUnc_2686C,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,3,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #4,priority(a0)
jsrto (Adjust2PArtPointer).l, JmpTo27_Adjust2PArtPointer
move.b #7,mapping_frame(a0)
move.w y_pos(a0),objoff_34(a0)
move.w #$10,objoff_36(a0)
addi.w #$10,y_pos(a0)
loc_26688:
move.w #$1B,d1
move.w #$10,d2
move.w #$10,d3
move.w x_pos(a0),d4
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
jsrto (SolidObject_Always_SingleCharacter).l, JmpTo2_SolidObject_Always_SingleCharacter
btst #p1_standing_bit,status(a0)
beq.s +
bsr.w loc_2678E
+
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
jsrto (SolidObject_Always_SingleCharacter).l, JmpTo2_SolidObject_Always_SingleCharacter
btst #p2_standing_bit,status(a0)
beq.s +
bsr.w loc_2678E
+
move.b routine_secondary(a0),d0
bne.s loc_266E4
subq.w #1,objoff_32(a0)
bpl.s BranchTo_JmpTo18_MarkObjGone
move.w #$3B,objoff_32(a0)
addq.b #2,routine_secondary(a0)
bra.s BranchTo_JmpTo18_MarkObjGone
; ===========================================================================
loc_266E4:
subq.b #2,d0
bne.s loc_26716
subq.w #8,objoff_36(a0)
bne.s loc_26708
addq.b #2,routine_secondary(a0)
bsr.s loc_2674C
addi.w #$28,x_pos(a1)
bsr.s loc_2674C
subi.w #$28,x_pos(a1)
bset #0,render_flags(a1)
loc_26708:
move.w objoff_36(a0),d0
add.w objoff_34(a0),d0
move.w d0,y_pos(a0)
bra.s BranchTo_JmpTo18_MarkObjGone
; ===========================================================================
loc_26716:
subq.b #2,d0
bne.s loc_2672C
subq.w #1,objoff_32(a0)
bpl.s BranchTo_JmpTo18_MarkObjGone
move.w #$3B,objoff_32(a0)
addq.b #2,routine_secondary(a0)
bra.s BranchTo_JmpTo18_MarkObjGone
; ===========================================================================
loc_2672C:
addq.w #8,objoff_36(a0)
cmpi.w #$10,objoff_36(a0)
bne.s loc_2673C
clr.b routine_secondary(a0)
loc_2673C:
move.w objoff_36(a0),d0
add.w objoff_34(a0),d0
move.w d0,y_pos(a0)
BranchTo_JmpTo18_MarkObjGone
jmpto (MarkObjGone).l, JmpTo18_MarkObjGone
; ===========================================================================
loc_2674C:
jsrto (SingleObjLoad).l, JmpTo7_SingleObjLoad
bne.s +
_move.b id(a0),id(a1) ; load obj42
addq.b #4,routine(a1)
move.w x_pos(a0),x_pos(a1)
move.w objoff_34(a0),y_pos(a1)
move.b #7,anim_frame_duration(a1)
move.l mappings(a0),mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_MtzSteam,1,0),art_tile(a1)
ori.b #4,render_flags(a1)
move.b #$18,width_pixels(a1)
move.b #4,priority(a1)
+
rts
; ===========================================================================
loc_2678E:
cmpi.b #2,routine_secondary(a0)
beq.s loc_26798
rts
; ===========================================================================
loc_26798:
move.w #-$A00,y_vel(a1)
bset #1,status(a1)
bclr #3,status(a1)
move.b #AniIDSonAni_Spring,anim(a1)
move.b #2,routine(a1)
move.b #0,spindash_flag(a1)
move.b subtype(a0),d0
bpl.s +
move.w #0,x_vel(a1)
+
btst #0,d0
beq.s loc_26808
move.w #1,inertia(a1)
move.b #1,flip_angle(a1)
move.b #AniIDSonAni_Walk,anim(a1)
move.b #0,flips_remaining(a1)
move.b #4,flip_speed(a1)
btst #1,d0
bne.s +
move.b #1,flips_remaining(a1)
+
btst #0,status(a1)
beq.s loc_26808
neg.b flip_angle(a1)
neg.w inertia(a1)
loc_26808:
andi.b #$C,d0
cmpi.b #4,d0
bne.s +
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
+
cmpi.b #8,d0
bne.s +
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
+
move.w #SndID_Spring,d0
jmp (PlaySound).l
; ===========================================================================
loc_2683A:
subq.b #1,anim_frame_duration(a0)
bpl.s ++
move.b #7,anim_frame_duration(a0)
move.b #0,collision_flags(a0)
addq.b #1,mapping_frame(a0)
cmpi.b #3,mapping_frame(a0)
bne.s +
move.b #$A6,collision_flags(a0)
+
cmpi.b #7,mapping_frame(a0)
beq.w JmpTo30_DeleteObject
+
jmpto (DisplaySprite).l, JmpTo18_DisplaySprite
if removeJmpTos
JmpTo30_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj42_MapUnc_2686C: BINCLUDE "mappings/sprite/obj42.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo18_DisplaySprite
jmp (DisplaySprite).l
JmpTo30_DeleteObject
jmp (DeleteObject).l
JmpTo7_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo18_MarkObjGone
jmp (MarkObjGone).l
JmpTo27_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo2_SolidObject_Always_SingleCharacter
jmp (SolidObject_Always_SingleCharacter).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 64 - Twin stompers from MTZ
; ----------------------------------------------------------------------------
; Sprite_26920:
Obj64:
moveq #0,d0
move.b routine(a0),d0
move.w Obj64_Index(pc,d0.w),d1
jmp Obj64_Index(pc,d1.w)
; ===========================================================================
; off_2692E:
Obj64_Index: offsetTable
offsetTableEntry.w Obj64_Init ; 0
offsetTableEntry.w Obj64_Main ; 2
; ===========================================================================
; byte_26932:
Obj64_Properties:
; width_pixels
; objoff_2E
dc.b $40, $C
dc.b $40, 1 ; 2
dc.b $10,$20 ; 4
dc.b $40, 1 ; 6
; ===========================================================================
; loc_2693A:
Obj64_Init:
addq.b #2,routine(a0)
moveq #0,d0
move.b subtype(a0),d0
lsr.w #2,d0
andi.w #$1C,d0
lea Obj64_Properties(pc,d0.w),a3
move.b (a3)+,width_pixels(a0)
move.b (a3)+,objoff_2E(a0)
lsr.w #2,d0
move.b d0,mapping_frame(a0)
bne.s +
move.b #$6C,y_radius(a0)
bset #4,render_flags(a0)
+
move.l #Obj64_MapUnc_26A5C,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,1,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo28_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #4,priority(a0)
move.w x_pos(a0),objoff_34(a0)
move.w y_pos(a0),objoff_30(a0)
moveq #0,d0
move.b (a3)+,d0
move.w d0,objoff_3C(a0)
andi.b #$F,subtype(a0)
; loc_269A2:
Obj64_Main:
move.w x_pos(a0),-(sp)
moveq #0,d0
move.b subtype(a0),d0
add.w d0,d0
move.w Obj64_Modes(pc,d0.w),d1
jsr Obj64_Modes(pc,d1.w)
move.w (sp)+,d4
tst.b render_flags(a0)
bpl.s +
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b objoff_2E(a0),d2
move.w d2,d3
addq.w #1,d3
jsrto (SolidObject).l, JmpTo9_SolidObject
+
move.w objoff_34(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.s JmpTo31_DeleteObject
jmp (DisplaySprite).l
; ===========================================================================
JmpTo31_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
; off_269F4:
Obj64_Modes: offsetTable
offsetTableEntry.w return_269F8 ; 0
offsetTableEntry.w loc_269FA ; 2
; ===========================================================================
return_269F8:
rts
; ===========================================================================
loc_269FA:
tst.b objoff_38(a0)
bne.s loc_26A1E
tst.w objoff_3A(a0)
beq.s loc_26A0C
subq.w #8,objoff_3A(a0)
bra.s loc_26A3E
; ===========================================================================
loc_26A0C:
subq.w #1,objoff_36(a0)
bpl.s loc_26A3E
move.w #$5A,objoff_36(a0)
move.b #1,objoff_38(a0)
loc_26A1E:
move.w objoff_3A(a0),d0
cmp.w objoff_3C(a0),d0
beq.s loc_26A2E
addq.w #8,objoff_3A(a0)
bra.s loc_26A3E
; ===========================================================================
loc_26A2E:
subq.w #1,objoff_36(a0)
bpl.s loc_26A3E
move.w #$5A,objoff_36(a0)
clr.b objoff_38(a0)
loc_26A3E:
move.w objoff_3A(a0),d0
btst #0,status(a0)
beq.s loc_26A50
neg.w d0
addi.w #$40,d0
loc_26A50:
move.w objoff_30(a0),d1
add.w d0,d1
move.w d1,y_pos(a0)
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj64_MapUnc_26A5C: BINCLUDE "mappings/sprite/obj64.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo28_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo9_SolidObject
jmp (SolidObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 65 - Long moving platform from MTZ
; ----------------------------------------------------------------------------
; Sprite_26AE0:
Obj65:
moveq #0,d0
move.b routine(a0),d0
move.w Obj65_Index(pc,d0.w),d1
jmp Obj65_Index(pc,d1.w)
; ===========================================================================
; off_26AEE:
Obj65_Index: offsetTable
offsetTableEntry.w Obj65_Init ; 0
offsetTableEntry.w loc_26C1C ; 2
offsetTableEntry.w loc_26EA4 ; 4
offsetTableEntry.w loc_26EC2 ; 6
; ---------------------------------------------------------------------------
; byte_26AF6:
Obj65_Properties:
; width_pixels
; radius
dc.b $40, $C
dc.b $80, 1 ; 2
dc.b $20, $C ; 4
dc.b $40, 3 ; 6
dc.b $10,$10 ; 8
dc.b $20, 0 ; 10
dc.b $40, $C ; 12
dc.b $80, 7 ; 14
; ===========================================================================
; loc_26B06:
Obj65_Init:
addq.b #2,routine(a0)
move.l #Obj65_Obj6A_Obj6B_MapUnc_26EC8,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,3,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo29_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #4,priority(a0)
moveq #0,d0
move.b subtype(a0),d0
lsr.w #2,d0
andi.w #$1C,d0
lea Obj65_Properties(pc,d0.w),a3
move.b (a3)+,width_pixels(a0)
move.b (a3)+,y_radius(a0)
lsr.w #2,d0
move.b d0,mapping_frame(a0)
cmpi.b #1,d0
bne.s +
bset #7,status(a0)
+
cmpi.b #2,d0
bne.s loc_26B6E
addq.b #4,routine(a0)
move.l #Obj65_MapUnc_26F04,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_MtzCog,3,0),art_tile(a0)
bra.w loc_26EC2
; ===========================================================================
loc_26B6E:
move.w x_pos(a0),objoff_34(a0)
move.w y_pos(a0),objoff_30(a0)
moveq #0,d0
move.b (a3)+,d0
move.w d0,objoff_3C(a0)
moveq #0,d0
move.b subtype(a0),d0
bpl.w loc_26C16
andi.b #$F,d0
move.b d0,objoff_3E(a0)
move.b (a3),subtype(a0)
cmpi.b #7,(a3)
bne.s +
move.w objoff_3C(a0),objoff_3A(a0)
+
jsrto (SingleObjLoad2).l, JmpTo11_SingleObjLoad2
bne.s loc_26C04
_move.b id(a0),id(a1) ; load obj65
addq.b #4,routine(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
addi.w #-$4C,x_pos(a1)
addi.w #$14,y_pos(a1)
btst #0,status(a0)
bne.s +
subi.w #-$18,x_pos(a1)
bset #0,render_flags(a1)
+
move.l #Obj65_MapUnc_26F04,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_MtzCog,3,0),art_tile(a1)
ori.b #4,render_flags(a1)
move.b #$10,width_pixels(a1)
move.b #4,priority(a1)
move.l a0,objoff_3C(a1)
loc_26C04:
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s loc_26C16
bclr #7,2(a2,d0.w)
loc_26C16:
andi.b #$F,subtype(a0)
loc_26C1C:
move.w x_pos(a0),objoff_2E(a0)
moveq #0,d0
move.b subtype(a0),d0
add.w d0,d0
move.w off_26C7E(pc,d0.w),d1
jsr off_26C7E(pc,d1.w)
move.w objoff_2E(a0),d4
moveq #0,d1
move.b width_pixels(a0),d1
addi_.w #5,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
jsrto (SolidObject).l, JmpTo10_SolidObject
move.w objoff_34(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.s loc_26C66
jmp (DisplaySprite).l
; ===========================================================================
loc_26C66:
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s +
bclr #7,2(a2,d0.w)
+
jmp (DeleteObject).l
; ===========================================================================
off_26C7E: offsetTable
offsetTableEntry.w return_26C8E ; 0
offsetTableEntry.w loc_26CA4 ; 1
offsetTableEntry.w loc_26D34 ; 2
offsetTableEntry.w loc_26D94 ; 3
offsetTableEntry.w loc_26E3C ; 4
offsetTableEntry.w loc_26E4A ; 5
offsetTableEntry.w loc_26C90 ; 6
offsetTableEntry.w loc_26D14 ; 7
; ===========================================================================
return_26C8E:
rts
; ===========================================================================
loc_26C90:
tst.b objoff_38(a0)
bne.s BranchTo_loc_26CC2
subq.w #1,objoff_36(a0)
bne.s loc_26CD0
move.b #1,objoff_38(a0)
BranchTo_loc_26CC2
bra.s loc_26CC2
; ===========================================================================
loc_26CA4:
tst.b objoff_38(a0)
bne.s loc_26CC2
lea (ButtonVine_Trigger).w,a2
moveq #0,d0
move.b objoff_3E(a0),d0
btst #0,(a2,d0.w)
beq.s loc_26CD0
move.b #1,objoff_38(a0)
loc_26CC2:
move.w objoff_3C(a0),d0
cmp.w objoff_3A(a0),d0
beq.s loc_26CF2
addq.w #2,objoff_3A(a0)
loc_26CD0:
move.w objoff_3A(a0),d0
btst #0,status(a0)
beq.s +
neg.w d0
addi.w #$80,d0
+
move.w objoff_34(a0),d1
sub.w d0,d1
move.w d1,x_pos(a0)
move.w d1,objoff_2E(a0)
rts
; ===========================================================================
loc_26CF2:
addq.b #1,subtype(a0)
move.w #$B4,objoff_36(a0)
clr.b objoff_38(a0)
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s loc_26CD0
bset #0,2(a2,d0.w)
bra.s loc_26CD0
; ===========================================================================
loc_26D14:
tst.b objoff_38(a0)
bne.s +
lea (ButtonVine_Trigger).w,a2
moveq #0,d0
move.b objoff_3E(a0),d0
btst #0,(a2,d0.w)
beq.s loc_26D50
move.b #1,objoff_38(a0)
+
bra.s loc_26D46
; ===========================================================================
loc_26D34:
tst.b objoff_38(a0)
bne.s loc_26D46
subq.w #1,objoff_36(a0)
bne.s loc_26D50
move.b #1,objoff_38(a0)
loc_26D46:
tst.w objoff_3A(a0)
beq.s loc_26D72
subq.w #2,objoff_3A(a0)
loc_26D50:
move.w objoff_3A(a0),d0
btst #0,status(a0)
beq.s +
neg.w d0
addi.w #$80,d0
+
move.w objoff_34(a0),d1
sub.w d0,d1
move.w d1,x_pos(a0)
move.w d1,objoff_2E(a0)
rts
; ===========================================================================
loc_26D72:
subq.b #1,subtype(a0)
move.w #$B4,objoff_36(a0)
clr.b objoff_38(a0)
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s loc_26D50
bclr #0,2(a2,d0.w)
bra.s loc_26D50
; ===========================================================================
loc_26D94:
move.w objoff_34(a0),d4
move.w d4,d5
btst #0,status(a0)
bne.s loc_26DAC
subi.w #$20,d4
addi.w #$60,d5
bra.s loc_26DB4
; ===========================================================================
loc_26DAC:
subi.w #$A0,d4
subi.w #$20,d5
loc_26DB4:
move.w y_pos(a0),d2
move.w d2,d3
subi.w #$10,d2
addi.w #$40,d3
moveq #0,d1
move.w (MainCharacter+x_pos).w,d0
cmp.w d4,d0
blo.s +
cmp.w d5,d0
bhs.s +
move.w (MainCharacter+y_pos).w,d0
cmp.w d2,d0
blo.s +
cmp.w d3,d0
bhs.s +
moveq #1,d1
+
move.w (Sidekick+x_pos).w,d0
cmp.w d4,d0
blo.s +
cmp.w d5,d0
bhs.s +
move.w (Sidekick+y_pos).w,d0
cmp.w d2,d0
blo.s +
cmp.w d3,d0
bhs.s +
moveq #1,d1
+
tst.b d1
beq.s loc_26E0E
move.w objoff_3C(a0),d0
cmp.w objoff_3A(a0),d0
beq.s return_26E3A
addi.w #$10,objoff_3A(a0)
bra.s loc_26E1A
; ===========================================================================
loc_26E0E:
tst.w objoff_3A(a0)
beq.s loc_26E1A
subi.w #$10,objoff_3A(a0)
loc_26E1A:
move.w objoff_3A(a0),d0
btst #0,status(a0)
beq.s +
neg.w d0
addi.w #$40,d0
+
move.w objoff_34(a0),d1
sub.w d0,d1
move.w d1,x_pos(a0)
move.w d1,objoff_2E(a0)
return_26E3A:
rts
; ===========================================================================
loc_26E3C:
btst #p1_standing_bit,status(a0)
beq.s +
addq.b #1,subtype(a0)
+
rts
; ===========================================================================
loc_26E4A:
tst.b objoff_38(a0)
bne.s loc_26E84
addq.w #2,x_pos(a0)
cmpi.b #metropolis_zone_2,(Current_Zone).w
bne.s loc_26E74
cmpi.w #$1CC0,x_pos(a0)
beq.s loc_26E6C
cmpi.w #$2940,x_pos(a0)
bne.s loc_26E96
loc_26E6C:
move.b #0,subtype(a0)
bra.s loc_26E96
; ===========================================================================
loc_26E74:
cmpi.w #$1BC0,x_pos(a0)
bne.s loc_26E96
move.b #1,objoff_38(a0)
bra.s loc_26E96
; ===========================================================================
loc_26E84:
subq.w #2,x_pos(a0)
cmpi.w #$1880,x_pos(a0)
bne.s loc_26E96
move.b #0,objoff_38(a0)
loc_26E96:
move.w x_pos(a0),objoff_34(a0)
move.w x_pos(a0),(MTZ_Platform_Cog_X).w
rts
; ===========================================================================
loc_26EA4:
movea.l objoff_3C(a0),a1 ; a1=object
move.w objoff_3A(a1),d0
loc_26EAC:
andi.w #7,d0
move.b byte_26EBA(pc,d0.w),mapping_frame(a0)
jmpto (MarkObjGone).l, JmpTo19_MarkObjGone
; ===========================================================================
byte_26EBA:
dc.b 0
dc.b 0 ; 1
dc.b 2 ; 2
dc.b 2 ; 3
dc.b 2 ; 4
dc.b 1 ; 5
dc.b 1 ; 6
dc.b 1 ; 7
; ===========================================================================
loc_26EC2:
move.w (MTZ_Platform_Cog_X).w,d0
bra.s loc_26EAC
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj65_Obj6A_Obj6B_MapUnc_26EC8: BINCLUDE "mappings/sprite/obj65_a.bin"
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj65_MapUnc_26F04: BINCLUDE "mappings/sprite/obj65_b.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo19_MarkObjGone
jmp (MarkObjGone).l
JmpTo11_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo29_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo10_SolidObject
jmp (SolidObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 66 - Yellow spring walls from MTZ
; ----------------------------------------------------------------------------
; Sprite_26F58:
Obj66:
moveq #0,d0
move.b routine(a0),d0
move.w Obj66_Index(pc,d0.w),d1
jmp Obj66_Index(pc,d1.w)
; ===========================================================================
; off_26F66:
Obj66_Index: offsetTable
offsetTableEntry.w Obj66_Init ; 0
offsetTableEntry.w Obj66_Main ; 2
; ===========================================================================
; loc_26F6A:
Obj66_Init:
addq.b #2,routine(a0)
move.l #Obj66_MapUnc_27120,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Powerups,0,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo30_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #8,width_pixels(a0)
move.b #4,priority(a0)
move.b #$40,y_radius(a0)
move.b subtype(a0),d0
lsr.b #4,d0
andi.b #7,d0
move.b d0,mapping_frame(a0)
beq.s Obj66_Main
move.b #$80,y_radius(a0)
; loc_26FAE:
Obj66_Main:
move.w #$13,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
move.w x_pos(a0),d4
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
jsrto (SolidObject_Always_SingleCharacter).l, JmpTo3_SolidObject_Always_SingleCharacter
cmpi.b #1,d4
bne.s loc_26FF6
btst #1,status(a1)
beq.s loc_26FF6
move.b status(a0),d1
move.w x_pos(a0),d0
sub.w x_pos(a1),d0
bcs.s +
eori.b #1,d1
+
andi.b #1,d1
bne.s loc_26FF6
bsr.s loc_27042
loc_26FF6:
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
jsrto (SolidObject_Always_SingleCharacter).l, JmpTo3_SolidObject_Always_SingleCharacter
cmpi.b #1,d4
bne.s loc_2702C
btst #1,status(a1)
beq.s loc_2702C
move.b status(a0),d1
move.w x_pos(a0),d0
sub.w x_pos(a1),d0
bcs.s +
eori.b #1,d1
+
andi.b #1,d1
bne.s loc_2702C
bsr.s loc_27042
loc_2702C:
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w JmpTo33_DeleteObject
if gameRevision=0
; this object was visible with debug mode in REV00
tst.w (Debug_placement_mode).w
beq.s + ; rts
jsrto (DisplaySprite).l, JmpTo47_DisplaySprite
+
endif
rts
if removeJmpTos
JmpTo33_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
loc_27042:
if gameRevision>0
; REV00 didn't prevent the player from bouncing if they were hurt or dead
cmpi.b #4,routine(a1)
blo.s loc_2704C
rts
endif
; ===========================================================================
loc_2704C:
move.w objoff_30(a0),x_vel(a1)
move.w #-$800,x_vel(a1)
move.w #-$800,y_vel(a1)
bset #0,status(a1)
btst #0,status(a0)
bne.s +
bclr #0,status(a1)
neg.w x_vel(a1)
+
move.w #$F,move_lock(a1)
move.w x_vel(a1),inertia(a1)
btst #2,status(a1)
bne.s +
move.b #AniIDSonAni_Walk,anim(a1)
+
move.b subtype(a0),d0
bpl.s +
move.w #0,y_vel(a1)
+
btst #0,d0
beq.s loc_270DC
move.w #1,inertia(a1)
move.b #1,flip_angle(a1)
move.b #AniIDSonAni_Walk,anim(a1)
move.b #1,flips_remaining(a1)
move.b #8,flip_speed(a1)
btst #1,d0
bne.s +
move.b #3,flips_remaining(a1)
+
btst #0,status(a1)
beq.s loc_270DC
neg.b flip_angle(a1)
neg.w inertia(a1)
loc_270DC:
andi.b #$C,d0
cmpi.b #4,d0
bne.s +
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
+
cmpi.b #8,d0
bne.s +
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
+
bclr #p1_pushing_bit,status(a0)
bclr #p2_pushing_bit,status(a0)
bclr #5,status(a1)
move.w #SndID_Spring,d0
jmp (PlaySound).l
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj66_MapUnc_27120: BINCLUDE "mappings/sprite/obj66.bin"
; ===========================================================================
if ~~removeJmpTos
if gameRevision=0
JmpTo47_DisplaySprite
jmp (DisplaySprite).l
endif
JmpTo33_DeleteObject
jmp (DeleteObject).l
JmpTo30_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo3_SolidObject_Always_SingleCharacter
jmp (SolidObject_Always_SingleCharacter).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 67 - Spin tube from MTZ
; ----------------------------------------------------------------------------
; Sprite_2715C:
Obj67:
moveq #0,d0
move.b routine(a0),d0
move.w Obj67_Index(pc,d0.w),d1
jsr Obj67_Index(pc,d1.w)
move.b objoff_2C(a0),d0
add.b objoff_36(a0),d0
beq.w JmpTo4_MarkObjGone3
lea (Ani_obj67).l,a1
jsrto (AnimateSprite).l, JmpTo7_AnimateSprite
jmpto (DisplaySprite).l, JmpTo19_DisplaySprite
; ===========================================================================
; off_27184:
Obj67_Index: offsetTable
offsetTableEntry.w Obj67_Init ; 0
offsetTableEntry.w Obj67_Main ; 2
; ===========================================================================
; loc_27188:
Obj67_Init:
addq.b #2,routine(a0)
move.l #Obj67_MapUnc_27548,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_MtzSpinTubeFlash,3,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #5,priority(a0)
; loc_271AC:
Obj67_Main:
lea (MainCharacter).w,a1 ; a1=character
lea objoff_2C(a0),a4
bsr.s loc_271BE
lea (Sidekick).w,a1 ; a1=character
lea objoff_36(a0),a4
loc_271BE:
moveq #0,d0
move.b (a4),d0
move.w off_271CA(pc,d0.w),d0
jmp off_271CA(pc,d0.w)
; ===========================================================================
off_271CA: offsetTable
offsetTableEntry.w loc_271D0 ; 0
offsetTableEntry.w loc_27260 ; 2
offsetTableEntry.w loc_27294 ; 4
; ===========================================================================
loc_271D0:
tst.w (Debug_placement_mode).w
bne.w return_2725E
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
addq.w #3,d0
btst #0,status(a0)
beq.s +
addi.w #$A,d0
+
cmpi.w #$10,d0
bhs.s return_2725E
move.w y_pos(a1),d1
sub.w y_pos(a0),d1
addi.w #$20,d1
cmpi.w #$40,d1
bhs.s return_2725E
tst.b obj_control(a1)
bne.s return_2725E
addq.b #2,(a4)
move.b #$81,obj_control(a1)
move.b #AniIDSonAni_Roll,anim(a1)
move.w #$800,inertia(a1)
move.w #0,x_vel(a1)
move.w #0,y_vel(a1)
bclr #5,status(a0)
bclr #5,status(a1)
bset #1,status(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
clr.b 1(a4)
move.w #SndID_Roll,d0
jsr (PlaySound).l
move.w #$100,anim(a0)
return_2725E:
rts
; ===========================================================================
loc_27260:
move.b 1(a4),d0
addq.b #2,1(a4)
jsr (CalcSine).l
asr.w #5,d0
move.w y_pos(a0),d2
sub.w d0,d2
move.w d2,y_pos(a1)
cmpi.b #$80,1(a4)
bne.s +
bsr.w loc_27310
addq.b #2,(a4)
move.w #SndID_SpindashRelease,d0
jsr (PlaySound).l
+
rts
; ===========================================================================
loc_27294:
subq.b #1,2(a4)
bpl.s Obj67_MoveCharacter
movea.l 6(a4),a2
move.w (a2)+,d4
move.w d4,x_pos(a1)
move.w (a2)+,d5
move.w d5,y_pos(a1)
tst.b subtype(a0)
bpl.s +
subq.w #8,a2
+
move.l a2,6(a4)
subq.w #4,4(a4)
beq.s loc_272EE
move.w (a2)+,d4
move.w (a2)+,d5
move.w #$1000,d2
bra.w loc_27374
; ===========================================================================
; update the position of Sonic/Tails in the MTZ tube
; loc_272C8:
Obj67_MoveCharacter:
move.l x_pos(a1),d2
move.l y_pos(a1),d3
move.w x_vel(a1),d0
ext.l d0
asl.l #8,d0
add.l d0,d2
move.w y_vel(a1),d0
ext.l d0
asl.l #8,d0
add.l d0,d3
move.l d2,x_pos(a1)
move.l d3,y_pos(a1)
rts
; ===========================================================================
loc_272EE:
andi.w #$7FF,y_pos(a1)
clr.b (a4)
clr.b obj_control(a1)
btst #4,subtype(a0)
bne.s +
move.w #0,x_vel(a1)
move.w #0,y_vel(a1)
+
rts
; ===========================================================================
loc_27310:
move.b subtype(a0),d0
bpl.s loc_27344
neg.b d0
andi.w #$F,d0
add.w d0,d0
lea (off_273F2).l,a2
adda.w (a2,d0.w),a2
move.w (a2)+,d0
subq.w #4,d0
move.w d0,4(a4)
lea (a2,d0.w),a2
move.w (a2)+,d4
move.w d4,x_pos(a1)
move.w (a2)+,d5
move.w d5,y_pos(a1)
subq.w #8,a2
bra.s loc_27368
; ===========================================================================
loc_27344:
andi.w #$F,d0
add.w d0,d0
lea (off_273F2).l,a2
adda.w (a2,d0.w),a2
move.w (a2)+,4(a4)
subq.w #4,4(a4)
move.w (a2)+,d4
move.w d4,x_pos(a1)
move.w (a2)+,d5
move.w d5,y_pos(a1)
loc_27368:
move.l a2,6(a4)
move.w (a2)+,d4
move.w (a2)+,d5
move.w #$1000,d2
loc_27374:
moveq #0,d0
move.w d2,d3
move.w d4,d0
sub.w x_pos(a1),d0
bge.s loc_27384
neg.w d0
neg.w d2
loc_27384:
moveq #0,d1
move.w d5,d1
sub.w y_pos(a1),d1
bge.s loc_27392
neg.w d1
neg.w d3
loc_27392:
cmp.w d0,d1
blo.s loc_273C4
moveq #0,d1
move.w d5,d1
sub.w y_pos(a1),d1
swap d1
divs.w d3,d1
moveq #0,d0
move.w d4,d0
sub.w x_pos(a1),d0
beq.s loc_273B0
swap d0
divs.w d1,d0
loc_273B0:
move.w d0,x_vel(a1)
move.w d3,y_vel(a1)
abs.w d1
move.w d1,2(a4)
rts
; ===========================================================================
loc_273C4:
moveq #0,d0
move.w d4,d0
sub.w x_pos(a1),d0
swap d0
divs.w d2,d0
moveq #0,d1
move.w d5,d1
sub.w y_pos(a1),d1
beq.s loc_273DE
swap d1
divs.w d0,d1
loc_273DE:
move.w d1,y_vel(a1)
move.w d2,x_vel(a1)
abs.w d0
move.w d0,2(a4)
rts
; ===========================================================================
; MTZ tube position data
; off_273F2:
include "misc/obj67.asm"
; animation script
; byte_2752E:
Ani_obj67: offsetTable
offsetTableEntry.w byte_27532 ; 0
offsetTableEntry.w byte_27535 ; 1
byte_27532:
dc.b $1F, 0,$FF
rev02even
byte_27535:
dc.b 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0,$FE, 2
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj67_MapUnc_27548: BINCLUDE "mappings/sprite/obj67.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo19_DisplaySprite
jmp (DisplaySprite).l
JmpTo7_AnimateSprite
jmp (AnimateSprite).l
JmpTo4_MarkObjGone3
jmp (MarkObjGone3).l
align 4
else
JmpTo4_MarkObjGone3
jmp (MarkObjGone3).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 68 - Block with a spike that comes out of each side sequentially from MTZ
; ----------------------------------------------------------------------------
spikearoundblock_initial_x_pos = objoff_30
spikearoundblock_initial_y_pos = objoff_32
spikearoundblock_offset = objoff_34 ; offset from the center
spikearoundblock_position = objoff_36 ; 0 = retracted or expanding, 1 = expanded or retracting
spikearoundblock_waiting = objoff_38 ; 0 = moving, 1 = waiting
; Sprite_27594:
Obj68:
moveq #0,d0
move.b routine(a0),d0
move.w Obj68_Index(pc,d0.w),d1
jmp Obj68_Index(pc,d1.w)
; ===========================================================================
; off_275A2:
Obj68_Index: offsetTable
offsetTableEntry.w Obj68_Init ; 0
offsetTableEntry.w Obj68_Block ; 2
offsetTableEntry.w Obj68_Spike ; 4
; ===========================================================================
; loc_275A8:
Obj68_Init:
addq.b #2,routine(a0)
move.l #Obj68_Obj6D_MapUnc_27750,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_MtzSpikeBlock,3,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo31_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #4,priority(a0)
jsrto (SingleObjLoad2).l, JmpTo12_SingleObjLoad2
bne.s +
_move.b id(a0),id(a1) ; load obj68
addq.b #4,routine(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w x_pos(a1),spikearoundblock_initial_x_pos(a1)
move.w y_pos(a1),spikearoundblock_initial_y_pos(a1)
move.l mappings(a0),mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_MtzSpike,1,0),art_tile(a1)
ori.b #4,render_flags(a1)
move.b #$10,width_pixels(a1)
move.b #4,priority(a1)
move.w (Timer_frames).w,d0
lsr.w #6,d0
move.w d0,d1
andi.w #1,d0
move.w d0,spikearoundblock_position(a1)
lsr.w #1,d1
add.b subtype(a0),d1
andi.w #3,d1
move.b d1,routine_secondary(a1)
move.b d1,mapping_frame(a1)
lea (Obj68_CollisionFlags).l,a2
move.b (a2,d1.w),collision_flags(a1)
+
move.b #4,mapping_frame(a0)
; loc_2764A:
Obj68_Block:
move.w #$1B,d1
move.w #$10,d2
move.w #$11,d3
move.w x_pos(a0),d4
jsrto (SolidObject).l, JmpTo11_SolidObject
jmpto (MarkObjGone).l, JmpTo20_MarkObjGone
; ===========================================================================
; loc_27662:
Obj68_Spike:
bsr.w Obj68_Spike_Action
moveq #0,d0
move.b routine_secondary(a0),d0
add.w d0,d0
move.w Obj68_Spike_Directions(pc,d0.w),d1
jsr Obj68_Spike_Directions(pc,d1.w)
move.w spikearoundblock_initial_x_pos(a0),d0
jmpto (MarkObjGone2).l, JmpTo2_MarkObjGone2
; ===========================================================================
; off_2767E:
Obj68_Spike_Directions: offsetTable
offsetTableEntry.w Obj68_Spike_Up ; 0
offsetTableEntry.w Obj68_Spike_Right ; 1
offsetTableEntry.w Obj68_Spike_Down ; 2
offsetTableEntry.w Obj68_Spike_Left ; 3
; ===========================================================================
; These routines update the position of the spike.
; ===========================================================================
; loc_27686:
Obj68_Spike_Up:
moveq #0,d0
move.b spikearoundblock_offset(a0),d0
neg.w d0
add.w spikearoundblock_initial_y_pos(a0),d0
move.w d0,y_pos(a0)
rts
; ===========================================================================
; loc_27698:
Obj68_Spike_Right:
moveq #0,d0
move.b spikearoundblock_offset(a0),d0
add.w spikearoundblock_initial_x_pos(a0),d0
move.w d0,x_pos(a0)
rts
; ===========================================================================
; loc_276A8:
Obj68_Spike_Down:
moveq #0,d0
move.b spikearoundblock_offset(a0),d0
add.w spikearoundblock_initial_y_pos(a0),d0
move.w d0,y_pos(a0)
rts
; ===========================================================================
; loc_276B8:
Obj68_Spike_Left:
moveq #0,d0
move.b spikearoundblock_offset(a0),d0
neg.w d0
add.w spikearoundblock_initial_x_pos(a0),d0
move.w d0,x_pos(a0)
rts
; ===========================================================================
; loc_276CA:
Obj68_Spike_Action:
tst.w spikearoundblock_waiting(a0)
beq.s +
move.b (Timer_frames+1).w,d0
andi.b #$3F,d0
bne.s Obj68_Spike_Action_End
clr.w spikearoundblock_waiting(a0)
tst.b render_flags(a0) ; is the spike on the screen?
bpl.s + ; if not, branch
move.w #SndID_SpikesMove,d0
jsr (PlaySound).l
+
tst.w spikearoundblock_position(a0)
beq.s Obj68_Spike_Expanding
; Obj68_Spike_Retracting:
subi.w #$800,spikearoundblock_offset(a0) ; retract the spike
bcc.s Obj68_Spike_Action_End
move.w #0,spikearoundblock_offset(a0)
move.w #0,spikearoundblock_position(a0)
move.w #1,spikearoundblock_waiting(a0)
addq.b #1,routine_secondary(a0)
andi.b #3,routine_secondary(a0)
moveq #0,d0
move.b routine_secondary(a0),d0
move.b d0,mapping_frame(a0)
move.b Obj68_CollisionFlags(pc,d0.w),collision_flags(a0)
rts
; ===========================================================================
; loc_2772A:
Obj68_Spike_Expanding:
addi.w #$800,spikearoundblock_offset(a0) ; expand the spike
cmpi.w #$2000,spikearoundblock_offset(a0) ; did it reach full expansion?
blo.s Obj68_Spike_Action_End ; if not, return
move.w #$2000,spikearoundblock_offset(a0)
move.w #1,spikearoundblock_position(a0)
move.w #1,spikearoundblock_waiting(a0)
; return_2774A:
Obj68_Spike_Action_End:
rts
; ===========================================================================
; byte_2774C:
Obj68_CollisionFlags:
dc.b $84 ; 0
dc.b $A6 ; 1
dc.b $84 ; 2
dc.b $A6 ; 3
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj68_Obj6D_MapUnc_27750: BINCLUDE "mappings/sprite/obj68.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 6D - Floor spike from MTZ
; ----------------------------------------------------------------------------
floorspike_initial_x_pos = objoff_30
floorspike_initial_y_pos = objoff_32
floorspike_offset = objoff_34 ; on the y axis
floorspike_position = objoff_36 ; 0 = retracted or expanding, 1 = expanded or retracting
floorspike_waiting = objoff_38 ; 0 = moving, 1 = waiting
floorspike_delay = objoff_3A ; short delay before the spike retracts
; Sprite_27794:
Obj6D:
moveq #0,d0
move.b routine(a0),d0
move.w Obj6D_Index(pc,d0.w),d1
jmp Obj6D_Index(pc,d1.w)
; ===========================================================================
; off_277A2:
Obj6D_Index: offsetTable
offsetTableEntry.w Obj6D_Init ; 0
offsetTableEntry.w Obj6D_Main ; 2
; ===========================================================================
; loc_277A6:
Obj6D_Init:
addq.b #2,routine(a0)
move.l #Obj68_Obj6D_MapUnc_27750,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_MtzSpike,1,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo31_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #4,width_pixels(a0)
move.b #4,priority(a0)
move.w x_pos(a0),floorspike_initial_x_pos(a0)
move.w y_pos(a0),floorspike_initial_y_pos(a0)
move.b #$84,collision_flags(a0)
; loc_277E0:
Obj6D_Main:
bsr.w Obj6D_Action
moveq #0,d0
move.b floorspike_offset(a0),d0
neg.w d0
add.w floorspike_initial_y_pos(a0),d0
move.w d0,y_pos(a0)
move.w floorspike_initial_x_pos(a0),d0
jmpto (MarkObjGone2).l, JmpTo2_MarkObjGone2
; ===========================================================================
; loc_277FC:
Obj6D_Action:
tst.w floorspike_delay(a0)
beq.s +
subq.w #1,floorspike_delay(a0)
rts
; ---------------------------------------------------------------------------
+
tst.w floorspike_waiting(a0)
beq.s +
move.b (Timer_frames+1).w,d0
sub.b subtype(a0),d0
andi.b #$7F,d0
bne.s Obj6D_Action_End
clr.w floorspike_waiting(a0)
+
tst.w floorspike_position(a0)
beq.s Obj6D_Expanding
; Obj6D_Retracting:
subi.w #$400,floorspike_offset(a0)
bcc.s Obj6D_Action_End
move.w #0,floorspike_offset(a0)
move.w #0,floorspike_position(a0)
move.w #1,floorspike_waiting(a0)
rts
; ===========================================================================
; loc_27842:
Obj6D_Expanding:
addi.w #$400,floorspike_offset(a0)
cmpi.w #$2000,floorspike_offset(a0)
blo.s Obj6D_Action_End
move.w #$2000,floorspike_offset(a0)
move.w #1,floorspike_position(a0)
move.w #3,floorspike_delay(a0)
; return_27862:
Obj6D_Action_End:
rts
; ===========================================================================
if ~~removeJmpTos
JmpTo20_MarkObjGone
jmp (MarkObjGone).l
JmpTo12_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo31_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo11_SolidObject
jmp (SolidObject).l
JmpTo2_MarkObjGone2
jmp (MarkObjGone2).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 69 - Nut from MTZ
; ----------------------------------------------------------------------------
; Sprite_27884:
Obj69:
moveq #0,d0
move.b routine(a0),d0
move.w Obj69_Index(pc,d0.w),d1
jmp Obj69_Index(pc,d1.w)
; ===========================================================================
; off_27892:
Obj69_Index: offsetTable
offsetTableEntry.w Obj69_Init ; 0
offsetTableEntry.w Obj69_Main ; 2
offsetTableEntry.w loc_279FC ; 4
offsetTableEntry.w loc_278F4 ; 6
; ===========================================================================
; loc_2789A:
Obj69_Init:
addq.b #2,routine(a0)
move.l #Obj69_MapUnc_27A26,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_MtzAsstBlocks,1,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo32_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$20,width_pixels(a0)
move.b #$B,y_radius(a0)
move.b #4,priority(a0)
move.w y_pos(a0),objoff_32(a0)
move.b subtype(a0),d0
andi.w #$7F,d0
lsl.w #3,d0
move.w d0,objoff_36(a0)
; loc_278DC:
Obj69_Main:
lea (MainCharacter).w,a1 ; a1=character
lea objoff_38(a0),a4
moveq #p1_standing_bit,d6
bsr.s Obj69_Action
lea (Sidekick).w,a1 ; a1=character
lea objoff_3C(a0),a4
moveq #p2_standing_bit,d6
bsr.s Obj69_Action
loc_278F4:
andi.w #$7FF,y_pos(a0)
move.w #$2B,d1
move.w #$C,d2
move.w #$D,d3
move.w x_pos(a0),d4
jsrto (SolidObject).l, JmpTo12_SolidObject
jmpto (MarkObjGone).l, JmpTo21_MarkObjGone
; ===========================================================================
; loc_27912:
Obj69_Action:
btst d6,status(a0)
bne.s +
clr.b (a4)
+
moveq #0,d0
move.b (a4),d0
move.w Obj69_Modes(pc,d0.w),d0
jmp Obj69_Modes(pc,d0.w)
; ===========================================================================
; off_27926:
Obj69_Modes: offsetTable
offsetTableEntry.w loc_2792C ; 0
offsetTableEntry.w loc_2794C ; 2
offsetTableEntry.w loc_2796E ; 4
; ===========================================================================
loc_2792C:
btst d6,status(a0)
bne.s +
rts
; ===========================================================================
+
addq.b #2,(a4)
move.b #0,1(a4)
move.w x_pos(a0),d0
sub.w x_pos(a1),d0
bcc.s loc_2794C
move.b #1,1(a4)
loc_2794C:
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
tst.b 1(a4)
beq.s +
addi.w #$F,d0
+
cmpi.w #$10,d0
bhs.s + ; rts
move.w x_pos(a0),x_pos(a1)
addq.b #2,(a4)
+
rts
; ===========================================================================
loc_2796E:
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
bcc.s loc_279D4
add.w d0,objoff_34(a0)
move.w x_pos(a0),x_pos(a1)
move.w objoff_34(a0),d0
asr.w #3,d0
move.w d0,d1
asr.w #1,d0
andi.w #3,d0
move.b d0,mapping_frame(a0)
neg.w d1
add.w objoff_32(a0),d1
move.w d1,y_pos(a0)
sub.w objoff_32(a0),d1
move.w objoff_36(a0),d0
cmp.w d0,d1
blt.s return_279D2
move.w d0,d1
add.w objoff_32(a0),d1
move.w d1,y_pos(a0)
lsl.w #3,d0
neg.w d0
move.w d0,objoff_34(a0)
move.b #0,mapping_frame(a0)
tst.b subtype(a0)
bmi.s loc_279CC
clr.b (a4)
rts
; ===========================================================================
loc_279CC:
move.b #4,routine(a0)
return_279D2:
rts
; ===========================================================================
loc_279D4:
add.w d0,objoff_34(a0)
move.w x_pos(a0),x_pos(a1)
move.w objoff_34(a0),d0
asr.w #3,d0
move.w d0,d1
asr.w #1,d0
andi.w #3,d0
move.b d0,mapping_frame(a0)
neg.w d1
add.w objoff_32(a0),d1
move.w d1,y_pos(a0)
rts
; ===========================================================================
loc_279FC:
jsrto (ObjectMove).l, JmpTo13_ObjectMove
addi.w #$38,y_vel(a0)
jsrto (ObjCheckFloorDist).l, JmpTo_ObjCheckFloorDist
tst.w d1
bpl.w +
add.w d1,y_pos(a0)
andi.w #$7FF,y_pos(a0)
clr.w y_vel(a0)
addq.b #2,routine(a0)
+
bra.w loc_278F4
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj69_MapUnc_27A26: BINCLUDE "mappings/sprite/obj69.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo21_MarkObjGone
jmp (MarkObjGone).l
JmpTo_ObjCheckFloorDist
jmp (ObjCheckFloorDist).l
JmpTo32_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo12_SolidObject
jmp (SolidObject).l
; loc_27AA8:
JmpTo13_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 6A - Platform that moves when you walk off of it, from MTZ
; ----------------------------------------------------------------------------
; Sprite_27AB0:
Obj6A:
moveq #0,d0
move.b routine(a0),d0
move.w Obj6A_Index(pc,d0.w),d1
jmp Obj6A_Index(pc,d1.w)
; ===========================================================================
; off_27ABE:
Obj6A_Index: offsetTable
offsetTableEntry.w Obj6A_Init ; 0
offsetTableEntry.w loc_27BDE ; 2
offsetTableEntry.w loc_27C66 ; 4
; ===========================================================================
; loc_27AC4:
Obj6A_Init:
addq.b #2,routine(a0)
move.l #Obj65_Obj6A_Obj6B_MapUnc_26EC8,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,3,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #4,priority(a0)
move.b #$20,width_pixels(a0)
move.b #$C,y_radius(a0)
move.l #byte_27CDC,objoff_2C(a0)
move.b #1,mapping_frame(a0)
cmpi.b #mystic_cave_zone,(Current_Zone).w
bne.w loc_27BC4
addq.b #2,routine(a0)
move.l #Obj6A_MapUnc_27D30,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Crate,3,0),art_tile(a0)
move.b #$20,width_pixels(a0)
move.b #$20,y_radius(a0)
move.l #byte_27CF4,objoff_2C(a0)
btst #0,status(a0)
beq.s +
move.l #byte_27D12,objoff_2C(a0)
+
move.b #0,mapping_frame(a0)
cmpi.b #$18,subtype(a0)
bne.w loc_27BD0
jsrto (SingleObjLoad2).l, JmpTo13_SingleObjLoad2
bne.s ++
bsr.s Obj6A_InitSubObject
addi.w #$40,x_pos(a1)
addi.w #$40,y_pos(a1)
move.b #6,subtype(a1)
btst #0,status(a0)
beq.s +
move.b #$C,subtype(a1)
+
jsrto (SingleObjLoad2).l, JmpTo13_SingleObjLoad2
bne.s +
bsr.s Obj6A_InitSubObject
subi.w #$40,x_pos(a1)
addi.w #$40,y_pos(a1)
move.b #$C,subtype(a1)
btst #0,status(a0)
beq.s +
move.b #6,subtype(a1)
+
bra.s loc_27BC4
; ===========================================================================
; loc_27B9E:
Obj6A_InitSubObject:
_move.b id(a0),id(a1) ; load obj6A
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w x_pos(a0),objoff_32(a1)
move.w y_pos(a0),objoff_30(a1)
move.b status(a0),status(a1)
rts
; ===========================================================================
loc_27BC4:
move.w x_pos(a0),objoff_32(a0)
move.w y_pos(a0),objoff_30(a0)
loc_27BD0:
jsrto (Adjust2PArtPointer).l, JmpTo33_Adjust2PArtPointer
move.b subtype(a0),objoff_38(a0)
bra.w loc_27CA2
; ===========================================================================
loc_27BDE:
move.w x_pos(a0),-(sp)
tst.w objoff_36(a0)
bne.s loc_27C2E
move.b objoff_3C(a0),d1
move.b status(a0),d0
btst #p1_standing_bit,d0
bne.s loc_27C0A
btst #p1_standing_bit,d1
beq.s loc_27C0E
move.b #1,objoff_36(a0)
move.b #0,objoff_3C(a0)
bra.s loc_27C3E
; ===========================================================================
loc_27C0A:
move.b d0,objoff_3C(a0)
loc_27C0E:
btst #p2_standing_bit,d0
bne.s loc_27C28
btst #p2_standing_bit,d1
beq.s loc_27C3E
move.b #1,objoff_36(a0)
move.b #0,objoff_3C(a0)
bra.s loc_27C3E
; ===========================================================================
loc_27C28:
move.b d0,objoff_3C(a0)
bra.s loc_27C3E
; ===========================================================================
loc_27C2E:
jsr (ObjectMove).l
subq.w #1,objoff_34(a0)
bne.s loc_27C3E
bsr.w loc_27CA2
loc_27C3E:
move.w (sp)+,d4
tst.b render_flags(a0)
bpl.s loc_27C5E
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
jsrto (SolidObject).l, JmpTo13_SolidObject
loc_27C5E:
move.w objoff_32(a0),d0
jmpto (MarkObjGone2).l, JmpTo3_MarkObjGone2
; ===========================================================================
loc_27C66:
move.w x_pos(a0),-(sp)
jsr (ObjectMove).l
subq.w #1,objoff_34(a0)
bne.s loc_27C7A
bsr.w loc_27CA2
loc_27C7A:
move.w (sp)+,d4
tst.b render_flags(a0)
bpl.s loc_27C9A
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
jsrto (SolidObject).l, JmpTo13_SolidObject
loc_27C9A:
move.w objoff_32(a0),d0
jmpto (MarkObjGone2).l, JmpTo3_MarkObjGone2
; ===========================================================================
loc_27CA2:
moveq #0,d0
move.b objoff_38(a0),d0
movea.l objoff_2C(a0),a1 ; a1=object
lea (a1,d0.w),a1
move.w (a1)+,x_vel(a0)
move.w (a1)+,y_vel(a0)
move.w (a1)+,objoff_34(a0)
move.w #7,objoff_3A(a0)
move.b #0,objoff_36(a0)
addq.b #6,objoff_38(a0)
cmpi.b #$18,objoff_38(a0)
blo.s return_27CDA
move.b #0,objoff_38(a0)
return_27CDA:
rts
; ===========================================================================
byte_27CDC:
dc.b 0, 0, 4, 0, 0,$10, 4, 0,$FE, 0, 0,$20, 0, 0, 4, 0
dc.b 0,$10,$FC, 0,$FE, 0, 0,$20; 16
byte_27CF4:
dc.b 0, 0, 1, 0, 0,$40,$FF, 0, 0, 0, 0,$80, 0, 0,$FF, 0
dc.b 0,$40, 1, 0, 0, 0, 0,$80, 1, 0, 0, 0, 0,$40; 16
byte_27D12:
dc.b 0, 0, 1, 0, 0,$40, 1, 0, 0, 0, 0,$80, 0, 0,$FF, 0
dc.b 0,$40,$FF, 0, 0, 0, 0,$80,$FF, 0, 0, 0, 0,$40; 16
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj6A_MapUnc_27D30: BINCLUDE "mappings/sprite/obj6A.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo13_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo33_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo13_SolidObject
jmp (SolidObject).l
JmpTo3_MarkObjGone2
jmp (MarkObjGone2).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 6B - Immobile platform from MTZ
; ----------------------------------------------------------------------------
; Sprite_27D6C:
Obj6B:
moveq #0,d0
move.b routine(a0),d0
move.w Obj6B_Index(pc,d0.w),d1
jmp Obj6B_Index(pc,d1.w)
; ===========================================================================
; off_27D7A:
Obj6B_Index: offsetTable
offsetTableEntry.w Obj6B_Init ; 0
offsetTableEntry.w Obj6B_Main ; 2
; ===========================================================================
byte_27D7E:
dc.b $20
dc.b $C ; 1
dc.b 1 ; 2
dc.b 0 ; 3
dc.b $10 ; 4
dc.b $10 ; 5
dc.b 0 ; 6
dc.b 0 ; 7
; ===========================================================================
; loc_27D86:
Obj6B_Init:
addq.b #2,routine(a0)
move.l #Obj65_Obj6A_Obj6B_MapUnc_26EC8,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,3,0),art_tile(a0)
cmpi.b #chemical_plant_zone,(Current_Zone).w
bne.s +
move.l #Obj6B_MapUnc_2800E,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CPZStairBlock,3,0),art_tile(a0)
+
jsrto (Adjust2PArtPointer).l, JmpTo34_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #3,priority(a0)
moveq #0,d0
move.b subtype(a0),d0
lsr.w #2,d0
andi.w #$1C,d0
lea byte_27D7E(pc,d0.w),a2
move.b (a2)+,width_pixels(a0)
move.b (a2)+,y_radius(a0)
move.b (a2)+,mapping_frame(a0)
move.w x_pos(a0),objoff_34(a0)
move.w y_pos(a0),objoff_30(a0)
move.b status(a0),objoff_2E(a0)
moveq #0,d0
move.b subtype(a0),d0
andi.w #$F,d0
subq.w #8,d0
bcs.s Obj6B_Main
lsl.w #2,d0
lea (Oscillating_Data+$2A).w,a2
lea (a2,d0.w),a2
tst.w (a2)
bpl.s Obj6B_Main
bchg #0,objoff_2E(a0)
; loc_27E0E:
Obj6B_Main:
move.w x_pos(a0),-(sp)
moveq #0,d0
move.b subtype(a0),d0
andi.w #$F,d0
add.w d0,d0
move.w Obj6B_Types(pc,d0.w),d1
jsr Obj6B_Types(pc,d1.w)
move.w (sp)+,d4
tst.b render_flags(a0)
bpl.s +
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
jsrto (SolidObject).l, JmpTo14_SolidObject
+
move.w objoff_34(a0),d0
jmpto (MarkObjGone2).l, JmpTo4_MarkObjGone2
; ===========================================================================
; off_27E4E:
Obj6B_Types: offsetTable
offsetTableEntry.w Obj6B_Type_Immobile ; 0
offsetTableEntry.w loc_27E68 ; 1
offsetTableEntry.w loc_27E74 ; 2
offsetTableEntry.w loc_27E96 ; 3
offsetTableEntry.w loc_27EA2 ; 4
offsetTableEntry.w loc_27EC4 ; 5
offsetTableEntry.w loc_27EE2 ; 6
offsetTableEntry.w loc_27F10 ; 7
offsetTableEntry.w loc_27F4E ; 8
offsetTableEntry.w loc_27F60 ; 9
offsetTableEntry.w loc_27F70 ; $A
offsetTableEntry.w loc_27F80 ; $B
; ===========================================================================
; return_27E66:
Obj6B_Type_Immobile:
rts
; ===========================================================================
loc_27E68:
move.w #$40,d1
moveq #0,d0
move.b (Oscillating_Data+8).w,d0
bra.s +
; ===========================================================================
loc_27E74:
move.w #$80,d1
moveq #0,d0
move.b (Oscillating_Data+$1C).w,d0
+
btst #0,status(a0)
beq.s +
neg.w d0
add.w d1,d0
+
move.w objoff_34(a0),d1
sub.w d0,d1
move.w d1,x_pos(a0)
rts
; ===========================================================================
loc_27E96:
move.w #$40,d1
moveq #0,d0
move.b (Oscillating_Data+8).w,d0
bra.s loc_27EAC
; ===========================================================================
loc_27EA2:
move.w #$80,d1
moveq #0,d0
move.b (Oscillating_Data+$1C).w,d0
loc_27EAC:
btst #0,status(a0)
beq.s loc_27EB8
neg.w d0
add.w d1,d0
loc_27EB8:
move.w objoff_30(a0),d1
sub.w d0,d1
move.w d1,y_pos(a0)
rts
; ===========================================================================
loc_27EC4:
move.b (Oscillating_Data).w,d0
lsr.w #1,d0
add.w objoff_30(a0),d0
move.w d0,y_pos(a0)
move.b status(a0),d1
andi.b #standing_mask,d1
beq.s return_27EE0
addq.b #1,subtype(a0)
return_27EE0:
rts
; ===========================================================================
loc_27EE2:
move.l y_pos(a0),d3
move.w y_vel(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d3
move.l d3,y_pos(a0)
addi_.w #8,y_vel(a0)
move.w (Camera_Max_Y_pos_now).w,d0
addi.w #$E0,d0
cmp.w y_pos(a0),d0
bhs.s return_27F0E
move.b #0,subtype(a0)
return_27F0E:
rts
; ===========================================================================
loc_27F10:
tst.b objoff_38(a0)
bne.s loc_27F26
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s return_27F4C
move.b #8,objoff_38(a0)
loc_27F26:
jsrto (ObjectMove).l, JmpTo14_ObjectMove
andi.w #$7FF,y_pos(a0)
cmpi.w #$2A8,y_vel(a0)
bne.s loc_27F3C
neg.b objoff_38(a0)
loc_27F3C:
move.b objoff_38(a0),d1
ext.w d1
add.w d1,y_vel(a0)
bne.s return_27F4C
clr.b subtype(a0)
return_27F4C:
rts
; ===========================================================================
loc_27F4E:
move.w #$10,d1
moveq #0,d0
move.b (Oscillating_Data+$28).w,d0
lsr.w #1,d0
move.w (Oscillating_Data+$2A).w,d3
bra.s loc_27F8E
; ===========================================================================
loc_27F60:
move.w #$30,d1
moveq #0,d0
move.b (Oscillating_Data+$2C).w,d0
move.w (Oscillating_Data+$2E).w,d3
bra.s loc_27F8E
; ===========================================================================
loc_27F70:
move.w #$50,d1
moveq #0,d0
move.b (Oscillating_Data+$30).w,d0
move.w (Oscillating_Data+$32).w,d3
bra.s loc_27F8E
; ===========================================================================
loc_27F80:
move.w #$70,d1
moveq #0,d0
move.b (Oscillating_Data+$34).w,d0
move.w (Oscillating_Data+$36).w,d3
loc_27F8E:
tst.w d3
bne.s loc_27F9C
addq.b #1,objoff_2E(a0)
andi.b #3,objoff_2E(a0)
loc_27F9C:
move.b objoff_2E(a0),d2
andi.b #3,d2
bne.s loc_27FBC
sub.w d1,d0
add.w objoff_34(a0),d0
move.w d0,x_pos(a0)
neg.w d1
add.w objoff_30(a0),d1
move.w d1,y_pos(a0)
rts
; ===========================================================================
loc_27FBC:
subq.b #1,d2
bne.s loc_27FDA
subq.w #1,d1
sub.w d1,d0
neg.w d0
add.w objoff_30(a0),d0
move.w d0,y_pos(a0)
addq.w #1,d1
add.w objoff_34(a0),d1
move.w d1,x_pos(a0)
rts
; ===========================================================================
loc_27FDA:
subq.b #1,d2
bne.s loc_27FF8
subq.w #1,d1
sub.w d1,d0
neg.w d0
add.w objoff_34(a0),d0
move.w d0,x_pos(a0)
addq.w #1,d1
add.w objoff_30(a0),d1
move.w d1,y_pos(a0)
rts
; ===========================================================================
loc_27FF8:
sub.w d1,d0
add.w objoff_30(a0),d0
move.w d0,y_pos(a0)
neg.w d1
add.w objoff_34(a0),d1
move.w d1,x_pos(a0)
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj6B_MapUnc_2800E: BINCLUDE "mappings/sprite/obj6B.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo34_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo14_SolidObject
jmp (SolidObject).l
JmpTo4_MarkObjGone2
jmp (MarkObjGone2).l
; loc_2802E:
JmpTo14_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 6C - Small platform on pulleys (like at the start of MTZ2)
; ----------------------------------------------------------------------------
; Sprite_28034:
Obj6C:
moveq #0,d0
move.b routine(a0),d0
move.w Obj6C_Index(pc,d0.w),d1
jsr Obj6C_Index(pc,d1.w)
move.w objoff_30(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.s +
jmpto (DisplaySprite).l, JmpTo20_DisplaySprite
; ===========================================================================
+ jmpto (DeleteObject).l, JmpTo34_DeleteObject
; ===========================================================================
; off_2805C:
Obj6C_Index: offsetTable
offsetTableEntry.w Obj6C_Init ; 0
offsetTableEntry.w Obj6C_Main ; 2
; ===========================================================================
; loc_28060:
Obj6C_Init:
move.b subtype(a0),d0
bmi.w loc_28112
addq.b #2,routine(a0)
move.l #Obj6C_MapUnc_28372,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_LavaCup,3,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #4,priority(a0)
jsrto (Adjust2PArtPointer).l, JmpTo35_Adjust2PArtPointer
move.b #0,mapping_frame(a0)
moveq #0,d0
move.b subtype(a0),d0
move.w d0,d1
lsr.w #3,d0
andi.w #$1E,d0
lea off_28252(pc),a2
adda.w (a2,d0.w),a2
move.w (a2)+,objoff_38(a0)
move.l a2,objoff_3C(a0)
andi.w #$F,d1
lsl.w #2,d1
move.b d1,objoff_38(a0)
move.b #4,objoff_3A(a0)
btst #0,status(a0)
beq.s loc_280F2
neg.b objoff_3A(a0)
moveq #0,d1
move.b objoff_38(a0),d1
add.b objoff_3A(a0),d1
cmp.b objoff_39(a0),d1
blo.s loc_280EE
move.b d1,d0
moveq #0,d1
tst.b d0
bpl.s loc_280EE
move.b objoff_39(a0),d1
subq.b #4,d1
loc_280EE:
move.b d1,objoff_38(a0)
loc_280F2:
move.w (a2,d1.w),d0
add.w objoff_30(a0),d0
move.w d0,objoff_34(a0)
move.w 2(a2,d1.w),d0
add.w objoff_32(a0),d0
move.w d0,objoff_36(a0)
bsr.w loc_281DA
bra.w Obj6C_Main
; ===========================================================================
loc_28112:
andi.w #$7F,d0
add.w d0,d0
lea (off_282D6).l,a2
adda.w (a2,d0.w),a2
move.w (a2)+,d1
movea.l a0,a1
move.w x_pos(a0),d2
move.w y_pos(a0),d3
bra.s Obj6C_LoadSubObject
; ===========================================================================
; loc_28130:
Obj6C_SubObjectsLoop:
jsrto (SingleObjLoad).l, JmpTo8_SingleObjLoad
bne.s +
; loc_28136:
Obj6C_LoadSubObject:
_move.b #ObjID_Conveyor,id(a1) ; load obj6C
move.w (a2)+,d0
add.w d2,d0
move.w d0,x_pos(a1)
move.w (a2)+,d0
add.w d3,d0
move.w d0,y_pos(a1)
move.w d2,objoff_30(a1)
move.w d3,objoff_32(a1)
move.w (a2)+,d0
move.b d0,subtype(a1)
move.b status(a0),status(a1)
+
dbf d1,Obj6C_SubObjectsLoop
addq.l #4,sp
rts
; ===========================================================================
; loc_28168:
Obj6C_Main:
move.w x_pos(a0),-(sp)
bsr.w loc_2817E
moveq #0,d1
move.b width_pixels(a0),d1
moveq #8,d3
move.w (sp)+,d4
jmpto (PlatformObject).l, JmpTo5_PlatformObject
; ===========================================================================
loc_2817E:
move.w x_pos(a0),d0
cmp.w objoff_34(a0),d0
bne.s loc_281D4
move.w y_pos(a0),d0
cmp.w objoff_36(a0),d0
bne.s loc_281D4
moveq #0,d1
move.b objoff_38(a0),d1
add.b objoff_3A(a0),d1
cmp.b objoff_39(a0),d1
blo.s loc_281B0
move.b d1,d0
moveq #0,d1
tst.b d0
bpl.s loc_281B0
move.b objoff_39(a0),d1
subq.b #4,d1
loc_281B0:
move.b d1,objoff_38(a0)
movea.l objoff_3C(a0),a1 ; a1=object
move.w (a1,d1.w),d0
add.w objoff_30(a0),d0
move.w d0,objoff_34(a0)
move.w 2(a1,d1.w),d0
add.w objoff_32(a0),d0
move.w d0,objoff_36(a0)
bsr.w loc_281DA
loc_281D4:
jsrto (ObjectMove).l, JmpTo15_ObjectMove
rts
; ===========================================================================
loc_281DA:
moveq #0,d0
move.w #-$100,d2
move.w x_pos(a0),d0
sub.w objoff_34(a0),d0
bcc.s loc_281EE
neg.w d0
neg.w d2
loc_281EE:
moveq #0,d1
move.w #-$100,d3
move.w y_pos(a0),d1
sub.w objoff_36(a0),d1
bcc.s loc_28202
neg.w d1
neg.w d3
loc_28202:
cmp.w d0,d1
blo.s loc_2822C
move.w x_pos(a0),d0
sub.w objoff_34(a0),d0
beq.s loc_28218
ext.l d0
asl.l #8,d0
divs.w d1,d0
neg.w d0
loc_28218:
move.w d0,x_vel(a0)
move.w d3,y_vel(a0)
swap d0
move.w d0,x_sub(a0)
clr.w y_sub(a0)
rts
; ===========================================================================
loc_2822C:
move.w y_pos(a0),d1
sub.w objoff_36(a0),d1
beq.s loc_2823E
ext.l d1
asl.l #8,d1
divs.w d0,d1
neg.w d1
loc_2823E:
move.w d1,y_vel(a0)
move.w d2,x_vel(a0)
swap d1
move.w d1,y_sub(a0)
clr.w x_sub(a0)
rts
; ===========================================================================
off_28252: offsetTable
offsetTableEntry.w byte_28258 ; 0
offsetTableEntry.w byte_28282 ; 1
offsetTableEntry.w byte_282AC ; 2
byte_28258:
dc.b 0,$28, 0, 0, 0, 0,$FF,$EA, 0, $A,$FF,$E0, 0,$20,$FF,$E0
dc.b 0,$E0,$FF,$EA, 0,$F6, 0, 0, 1, 0, 0,$16, 0,$F6, 0,$20; 16
dc.b 0,$E0, 0,$20, 0,$20, 0,$16, 0, $A; 32
byte_28282:
dc.b 0,$28, 0, 0, 0, 0,$FF,$EA, 0, $A,$FF,$E0, 0,$20,$FF,$E0
dc.b 1,$60,$FF,$EA, 1,$76, 0, 0, 1,$80, 0,$16, 1,$76, 0,$20; 16
dc.b 1,$60, 0,$20, 0,$20, 0,$16, 0, $A; 32
byte_282AC:
dc.b 0,$28, 0, 0, 0, 0,$FF,$EA, 0, $A,$FF,$E0, 0,$20,$FF,$E0
dc.b 1,$E0,$FF,$EA, 1,$F6, 0, 0, 2, 0, 0,$16, 1,$F6, 0,$20; 16
dc.b 1,$E0, 0,$20, 0,$20, 0,$16, 0, $A; 32
; ---------------------------------------------------------------------------
off_282D6: offsetTable
offsetTableEntry.w byte_282DC ; 0
offsetTableEntry.w byte_2830E ; 1
offsetTableEntry.w byte_28340 ; 2
byte_282DC:
dc.b 0, 7, 0, 0, 0, 0, 0, 1,$FF,$E0, 0,$3A, 0, 3,$FF,$E0
dc.b 0,$80, 0, 3,$FF,$E0, 0,$C6, 0, 3, 0, 0, 1, 0, 0, 6; 16
dc.b 0,$20, 0,$C6, 0, 8, 0,$20, 0,$80, 0, 8, 0,$20, 0,$3A; 32
dc.b 0, 8 ; 48
byte_2830E:
dc.b 0, 7, 0, 0, 0, 0, 0,$11,$FF,$E0, 0,$5A, 0,$13,$FF,$E0
dc.b 0,$C0, 0,$13,$FF,$E0, 1,$26, 0,$13, 0, 0, 1,$80, 0,$16; 16
dc.b 0,$20, 1,$26, 0,$18, 0,$20, 0,$C0, 0,$18, 0,$20, 0,$5A; 32
dc.b 0,$18 ; 48
byte_28340:
dc.b 0, 7, 0, 0, 0, 0, 0,$21,$FF,$E0, 0,$7A, 0,$23,$FF,$E0
dc.b 1, 0, 0,$23,$FF,$E0, 1,$86, 0,$23, 0, 0, 2, 0, 0,$26; 16
dc.b 0,$20, 1,$86, 0,$28, 0,$20, 1, 0, 0,$28, 0,$20, 0,$7A; 32
dc.b 0,$28 ; 48
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj6C_MapUnc_28372: BINCLUDE "mappings/sprite/obj6C.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo20_DisplaySprite
jmp (DisplaySprite).l
JmpTo34_DeleteObject
jmp (DeleteObject).l
JmpTo8_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo35_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo5_PlatformObject
jmp (PlatformObject).l
; loc_283A6:
JmpTo15_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 6E - Platform moving in a circle (like at the start of MTZ3)
; ----------------------------------------------------------------------------
; Sprite_283AC:
Obj6E:
moveq #0,d0
move.b routine(a0),d0
move.w Obj6E_Index(pc,d0.w),d1
jmp Obj6E_Index(pc,d1.w)
; ===========================================================================
; off_283BA:
Obj6E_Index: offsetTable
offsetTableEntry.w Obj6E_Init ; 0
offsetTableEntry.w loc_28432 ; 2
offsetTableEntry.w loc_284BC ; 4
; ===========================================================================
byte_283C0:
; width_pixels
; radius
dc.b $10, $C
dc.b $28, 8 ; 2
dc.b $60,$18 ; 4
dc.b $C, $C ; 6
; ===========================================================================
; loc_283C8:
Obj6E_Init:
addq.b #2,routine(a0)
move.l #Obj6E_MapUnc_2852C,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,3,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo36_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #4,priority(a0)
moveq #0,d0
move.b subtype(a0),d0
lsr.w #3,d0
andi.w #$E,d0
lea byte_283C0(pc,d0.w),a3
move.b (a3)+,width_pixels(a0)
move.b (a3)+,y_radius(a0)
lsr.w #1,d0
move.b d0,mapping_frame(a0)
move.w x_pos(a0),objoff_34(a0)
move.w y_pos(a0),objoff_30(a0)
cmpi.b #3,d0
bne.s loc_28432
addq.b #2,routine(a0)
move.w #make_art_tile(ArtTile_ArtNem_MtzWheelIndent,3,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo36_Adjust2PArtPointer
move.b #5,priority(a0)
bra.w loc_284BC
; ===========================================================================
loc_28432:
move.w x_pos(a0),-(sp)
move.b (Oscillating_Data+$20).w,d1
subi.b #$38,d1
ext.w d1
move.b (Oscillating_Data+$24).w,d2
subi.b #$38,d2
ext.w d2
btst #0,subtype(a0)
beq.s +
neg.w d1
neg.w d2
+
btst #1,subtype(a0)
beq.s +
neg.w d1
exg d1,d2
+
add.w objoff_34(a0),d1
move.w d1,x_pos(a0)
add.w objoff_30(a0),d2
move.w d2,y_pos(a0)
move.w (sp)+,d4
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
jsrto (SolidObject).l, JmpTo15_SolidObject
move.w objoff_34(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.s +
jmp (DisplaySprite).l
; ===========================================================================
+
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s +
bclr #7,2(a2,d0.w)
+
jmp (DeleteObject).l
; ===========================================================================
loc_284BC:
move.b (Oscillating_Data+$20).w,d1
lsr.b #1,d1
subi.b #$1C,d1
ext.w d1
move.b (Oscillating_Data+$24).w,d2
lsr.b #1,d2
subi.b #$1C,d2
ext.w d2
btst #0,subtype(a0)
beq.s +
neg.w d1
neg.w d2
+
btst #1,subtype(a0)
beq.s +
neg.w d1
exg d1,d2
+
add.w objoff_34(a0),d1
move.w d1,x_pos(a0)
add.w objoff_30(a0),d2
move.w d2,y_pos(a0)
move.w objoff_34(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.s +
jmp (DisplaySprite).l
; ===========================================================================
+
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s +
bclr #7,2(a2,d0.w)
+
jmp (DeleteObject).l
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj6E_MapUnc_2852C: BINCLUDE "mappings/sprite/obj6E.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo36_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo15_SolidObject
jmp (SolidObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 70 - Giant rotating cog from MTZ
; ----------------------------------------------------------------------------
; Sprite_285C0:
Obj70:
moveq #0,d0
move.b routine(a0),d0
move.w Obj70_Index(pc,d0.w),d1
jmp Obj70_Index(pc,d1.w)
; ===========================================================================
; off_285CE:
Obj70_Index: offsetTable
offsetTableEntry.w Obj70_Init ; 0
offsetTableEntry.w Obj70_Main ; 2
; ===========================================================================
; loc_285D2:
Obj70_Init:
moveq #7,d1
moveq #0,d4
lea (Obj70_Positions).l,a2
movea.l a0,a1
move.w x_pos(a0),d2
move.w y_pos(a0),d3
bset #7,status(a0)
bra.s Obj70_LoadSubObject
; ===========================================================================
; loc_285EE:
Obj70_SubObjectLoop:
jsrto (SingleObjLoad2).l, JmpTo14_SingleObjLoad2
bne.s +
; loc_285F4:
Obj70_LoadSubObject:
_move.b id(a0),id(a1) ; load obj70
addq.b #2,routine(a1)
move.l #Obj70_MapUnc_28786,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_MtzWheel,3,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo4_Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #4,priority(a1)
move.b #$10,width_pixels(a1)
move.w d2,objoff_32(a1)
move.w d3,objoff_30(a1)
move.b (a2)+,d0
ext.w d0
add.w d2,d0
move.w d0,x_pos(a1)
move.b (a2)+,d0
ext.w d0
add.w d3,d0
move.w d0,y_pos(a1)
move.b (a2)+,mapping_frame(a1)
move.w d4,objoff_34(a1)
addq.w #3,d4
move.b status(a0),status(a1)
+
dbf d1,Obj70_SubObjectLoop
; loc_28652:
Obj70_Main:
move.w x_pos(a0),-(sp)
move.b (Timer_frames+1).w,d0
move.b d0,d1
andi.w #$F,d0
bne.s loc_286CA
move.w objoff_36(a0),d1
btst #0,status(a0)
beq.s loc_28684
subi.w #$18,d1
bcc.s loc_286A2
moveq #$48,d1
subq.w #3,objoff_34(a0)
bcc.s loc_286A2
move.w #$15,objoff_34(a0)
bra.s loc_286A2
; ===========================================================================
loc_28684:
addi.w #$18,d1
cmpi.w #$60,d1
blo.s loc_286A2
moveq #0,d1
addq.w #3,objoff_34(a0)
cmpi.w #$18,objoff_34(a0)
blo.s loc_286A2
move.w #0,objoff_34(a0)
loc_286A2:
move.w d1,objoff_36(a0)
add.w objoff_34(a0),d1
lea Obj70_Positions(pc,d1.w),a1
move.b (a1)+,d0
ext.w d0
add.w objoff_32(a0),d0
move.w d0,x_pos(a0)
move.b (a1)+,d0
ext.w d0
add.w objoff_30(a0),d0
move.w d0,y_pos(a0)
move.b (a1)+,mapping_frame(a0)
loc_286CA:
move.b mapping_frame(a0),d0
add.w d0,d0
andi.w #$1E,d0
moveq #0,d1
moveq #0,d2
move.b byte_28706(pc,d0.w),d1
move.b byte_28706+1(pc,d0.w),d2
move.w d2,d3
move.w (sp)+,d4
jsrto (SolidObject).l, JmpTo16_SolidObject
move.w objoff_32(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.s +
jmp (DisplaySprite).l
; ===========================================================================
+
jmp (DeleteObject).l
; ===========================================================================
byte_28706:
dc.b $10,$10 ; 0
dc.b $10,$10 ; 2
dc.b $10,$10 ; 4
dc.b $10,$10 ; 6
dc.b $10,$10 ; 8
dc.b $10,$10 ; 10
dc.b $10,$10 ; 12
dc.b $10, $C ; 14
dc.b $10, 8 ; 16
dc.b $10, $C ; 18
dc.b $10,$10 ; 20
dc.b $10,$10 ; 22
dc.b $10,$10 ; 24
dc.b $10,$10 ; 26
dc.b $10,$10 ; 28
dc.b $10,$10 ; 30
; byte_28726:
Obj70_Positions:
; initial positions
; x_pos, y_pos, mapping_frame
dc.b 0,$B8, 0
dc.b $32,$CE, 4
dc.b $48, 0, 8
dc.b $32,$32, $C
dc.b 0,$48,$10
dc.b $CE,$32,$14
dc.b $B8, 0,$18
dc.b $CE,$CE,$1C
dc.b $D,$B8, 1
dc.b $3F,$DA, 5
dc.b $48, $C, 9
dc.b $27,$3C, $D
dc.b $F3,$48,$11
dc.b $C1,$26,$15
dc.b $B8,$F4,$19
dc.b $D9,$C4,$1D
dc.b $19,$BC, 2
dc.b $46,$E9, 6
dc.b $46,$17, $A
dc.b $19,$44, $E
dc.b $E7,$44,$12
dc.b $BA,$17,$16
dc.b $BA,$E9,$1A
dc.b $E7,$BC,$1E
dc.b $27,$C4, 3
dc.b $48,$F4, 7
dc.b $3F,$26, $B
dc.b $D,$48, $F
dc.b $D9,$3C,$13
dc.b $B8, $C,$17
dc.b $C1,$DA,$1B
dc.b $F3,$B8,$1F
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj70_MapUnc_28786: BINCLUDE "mappings/sprite/obj70.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo14_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo4_Adjust2PArtPointer2
jmp (Adjust2PArtPointer2).l
JmpTo16_SolidObject
jmp (SolidObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 72 - Conveyor belt from CNZ
; ----------------------------------------------------------------------------
; Sprite_2893C:
Obj72:
moveq #0,d0
move.b routine(a0),d0
move.w Obj72_Index(pc,d0.w),d1
jmp Obj72_Index(pc,d1.w)
; ===========================================================================
; off_2894A:
Obj72_Index: offsetTable
offsetTableEntry.w Obj72_Init ; 0
offsetTableEntry.w Obj72_Main ; 2
; ===========================================================================
; loc_2894E:
Obj72_Init:
addq.b #2,routine(a0)
move.w #$30,objoff_3C(a0)
move.b subtype(a0),d0
bpl.s +
move.w #$70,objoff_3C(a0)
+
andi.b #$7F,d0
lsl.b #4,d0
move.b d0,objoff_38(a0)
move.w #2,objoff_36(a0)
btst #0,status(a0)
beq.s Obj72_Main
neg.w objoff_36(a0)
; loc_28980:
Obj72_Main:
lea (MainCharacter).w,a1 ; a1=character
bsr.s Obj72_Action
lea (Sidekick).w,a1 ; a1=character
bsr.s Obj72_Action
jmpto (MarkObjGone3).l, JmpTo5_MarkObjGone3
; ===========================================================================
; loc_28990:
Obj72_Action:
moveq #0,d2
move.b objoff_38(a0),d2
move.w d2,d3
add.w d3,d3
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
add.w d2,d0
cmp.w d3,d0
bhs.s + ; rts
move.w y_pos(a1),d1
sub.w y_pos(a0),d1
move.w objoff_3C(a0),d0
add.w d0,d1
cmp.w d0,d1
bhs.s + ; rts
btst #1,status(a1)
bne.s + ; rts
move.w objoff_36(a0),d0
add.w d0,x_pos(a1)
+
rts
; ===========================================================================
if ~~removeJmpTos
JmpTo5_MarkObjGone3
jmp (MarkObjGone3).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 73 - Solid rotating ring thing from Mystic Cave Zone
; (unused, but can be seen in debug mode)
; ----------------------------------------------------------------------------
; Sprite_289D4:
Obj73:
moveq #0,d0
move.b routine(a0),d0
move.w Obj73_Index(pc,d0.w),d1
jmp Obj73_Index(pc,d1.w)
; ===========================================================================
; off_289E2:
Obj73_Index: offsetTable
offsetTableEntry.w Obj73_Init ; 0
offsetTableEntry.w Obj73_Main ; 2
offsetTableEntry.w Obj73_SubObject ; 4
; ===========================================================================
; loc_289E8:
Obj73_Init:
addq.b #2,routine(a0)
move.l #Obj73_MapUnc_28B9C,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Ring,1,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo37_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #4,priority(a0)
move.b #8,width_pixels(a0)
move.w x_pos(a0),objoff_3A(a0)
move.w y_pos(a0),objoff_38(a0)
move.b #0,collision_flags(a0)
bset #7,status(a0)
move.b subtype(a0),d1
andi.b #$F0,d1
ext.w d1
asl.w #3,d1
move.w d1,objoff_3E(a0)
move.b status(a0),d0
ror.b #2,d0
andi.b #$C0,d0
move.b d0,angle(a0)
lea objoff_29(a0),a2
move.b subtype(a0),d1
andi.w #7,d1
move.b #0,(a2)+
move.w d1,d3
lsl.w #4,d3
move.b d3,objoff_3C(a0)
subq.w #1,d1
bcs.s Obj73_LoadSubObject_End
btst #3,subtype(a0)
beq.s Obj73_LoadSubObject
subq.w #1,d1
bcs.s Obj73_LoadSubObject_End
; loc_28A6E:
Obj73_LoadSubObject:
jsrto (SingleObjLoad).l, JmpTo9_SingleObjLoad
bne.s Obj73_LoadSubObject_End
addq.b #1,objoff_29(a0)
move.w a1,d5
subi.w #Object_RAM,d5
if object_size=$40
lsr.w #6,d5
else
divu.w #object_size,d5
endif
andi.w #$7F,d5
move.b d5,(a2)+
move.b #4,routine(a1)
_move.b id(a0),id(a1) ; load obj73
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
move.b render_flags(a0),render_flags(a1)
move.b priority(a0),priority(a1)
move.b width_pixels(a0),width_pixels(a1)
move.b collision_flags(a0),collision_flags(a1)
move.b status(a0),status(a1)
subi.b #$10,d3
move.b d3,objoff_3C(a1)
dbf d1,Obj73_LoadSubObject
; loc_28AC8:
Obj73_LoadSubObject_End:
move.w a0,d5
subi.w #Object_RAM,d5
if object_size=$40
lsr.w #6,d5
else
divu.w #object_size,d5
endif
andi.w #$7F,d5
move.b d5,(a2)+
; loc_28AD6:
Obj73_Main:
move.w x_pos(a0),-(sp)
bsr.w loc_28AF4
move.w #8,d1
move.w #8,d2
move.w d2,d3
addq.w #1,d3
move.w (sp)+,d4
jsrto (SolidObject).l, JmpTo17_SolidObject
bra.w loc_28B46
; ===========================================================================
loc_28AF4:
move.w objoff_3E(a0),d0
add.w d0,angle(a0)
move.b angle(a0),d0
jsr (CalcSine).l
move.w objoff_38(a0),d2
move.w objoff_3A(a0),d3
lea objoff_29(a0),a2
moveq #0,d6
move.b (a2)+,d6
loc_28B16:
moveq #0,d4
move.b (a2)+,d4
if object_size=$40
lsl.w #6,d4
else
mulu.w #object_size,d4
endif
addi.l #Object_RAM,d4
movea.l d4,a1 ; a1=object
moveq #0,d4
move.b objoff_3C(a1),d4
move.l d4,d5
muls.w d0,d4
asr.l #8,d4
muls.w d1,d5
asr.l #8,d5
add.w d2,d4
add.w d3,d5
move.w d4,y_pos(a1)
move.w d5,x_pos(a1)
dbf d6,loc_28B16
rts
; ===========================================================================
loc_28B46:
move.w objoff_3A(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w +
jmpto (DisplaySprite).l, JmpTo21_DisplaySprite
; ===========================================================================
+
moveq #0,d2
lea objoff_29(a0),a2
move.b (a2)+,d2
- moveq #0,d0
move.b (a2)+,d0
if object_size=$40
lsl.w #6,d0
else
mulu.w #object_size,d0
endif
addi.l #Object_RAM,d0
movea.l d0,a1 ; a1=object
jsrto (DeleteObject2).l, JmpTo_DeleteObject2
dbf d2,-
rts
; ===========================================================================
; loc_28B7E:
Obj73_SubObject:
move.w #8,d1
move.w #8,d2
move.w d2,d3
addq.w #1,d3
move.w objoff_36(a0),d4
jsrto (SolidObject).l, JmpTo17_SolidObject
move.w x_pos(a0),objoff_36(a0)
jmpto (DisplaySprite).l, JmpTo21_DisplaySprite
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj73_MapUnc_28B9C: BINCLUDE "mappings/sprite/obj73.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo21_DisplaySprite
jmp (DisplaySprite).l
JmpTo9_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo_DeleteObject2
jmp (DeleteObject2).l
JmpTo37_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo17_SolidObject
jmp (SolidObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 75 - Brick from MCZ
; ----------------------------------------------------------------------------
; Sprite_28BC8:
Obj75:
btst #6,render_flags(a0)
bne.w +
moveq #0,d0
move.b routine(a0),d0
move.w Obj75_Index(pc,d0.w),d1
jmp Obj75_Index(pc,d1.w)
; ===========================================================================
+
move.w #$280,d0
jmpto (DisplaySprite3).l, JmpTo_DisplaySprite3
; ===========================================================================
; off_28BE8:
Obj75_Index: offsetTable
offsetTableEntry.w Obj75_Init ; 0
offsetTableEntry.w Obj75_Main ; 2
offsetTableEntry.w loc_28D6C ; 4
; ===========================================================================
; loc_28BEE:
Obj75_Init:
addq.b #2,routine(a0)
move.l #Obj75_MapUnc_28D8A,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,1,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo38_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #5,priority(a0)
move.b #$10,width_pixels(a0)
move.w x_pos(a0),objoff_30(a0)
move.w y_pos(a0),objoff_32(a0)
move.b subtype(a0),d1
move.b d1,d0
andi.w #$F,d1
andi.b #$F0,d0
ext.w d0
asl.w #3,d0
move.w d0,objoff_34(a0)
move.b status(a0),d0
ror.b #2,d0
andi.b #$C0,d0
move.b d0,angle(a0)
cmpi.b #$F,d1
bne.s +
addq.b #2,routine(a0)
move.b #4,priority(a0)
move.b #2,mapping_frame(a0)
rts
; ===========================================================================
+
move.b #$9A,collision_flags(a0)
jsrto (SingleObjLoad2).l, JmpTo15_SingleObjLoad2
bne.s Obj75_Main
_move.b id(a0),id(a1) ; load obj75
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
move.b #4,render_flags(a1)
bset #6,render_flags(a1)
move.b #$40,mainspr_width(a1)
move.w x_pos(a0),d2
move.w y_pos(a0),d3
move.b d1,mainspr_childsprites(a1)
subq.w #1,d1
lea sub2_x_pos(a1),a2
- move.w d2,(a2)+ ; sub?_x_pos
move.w d3,(a2)+ ; sub?_y_pos
move.w #1,(a2)+ ; sub?_mapframe
dbf d1,-
move.w d2,x_pos(a1)
move.w d3,y_pos(a1)
move.b #0,mainspr_mapframe(a1)
move.l a1,objoff_3C(a0)
move.b #$40,mainspr_height(a1)
bset #4,render_flags(a1)
; loc_28CCA:
Obj75_Main:
moveq #0,d0
moveq #0,d1
move.w objoff_34(a0),d0
add.w d0,angle(a0)
move.b angle(a0),d0
jsrto (CalcSine).l, JmpTo8_CalcSine
move.w objoff_32(a0),d2
move.w objoff_30(a0),d3
moveq #0,d6
movea.l objoff_3C(a0),a1 ; a1=object
move.b mainspr_childsprites(a1),d6
subq.w #1,d6
bcs.s loc_28D3E
swap d0
swap d1
asr.l #4,d0
asr.l #4,d1
moveq #0,d4
moveq #0,d5
lea sub2_x_pos(a1),a2
- movem.l d4-d5,-(sp)
swap d4
swap d5
add.w d2,d4
add.w d3,d5
move.w d5,(a2)+ ; sub?_x_pos
move.w d4,(a2)+ ; sub?_y_pos
movem.l (sp)+,d4-d5
add.l d0,d4
add.l d1,d5
addq.w #next_subspr-4,a2
dbf d6,-
swap d4
swap d5
add.w d2,d4
add.w d3,d5
move.w d5,x_pos(a0)
move.w d4,y_pos(a0)
move.w sub6_x_pos(a1),x_pos(a1)
move.w sub6_y_pos(a1),y_pos(a1)
loc_28D3E:
tst.w (Two_player_mode).w
beq.s +
jmpto (DisplaySprite).l, JmpTo22_DisplaySprite
; ===========================================================================
+
move.w objoff_30(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w +
jmpto (DisplaySprite).l, JmpTo22_DisplaySprite
; ===========================================================================
+
movea.l objoff_3C(a0),a1 ; a1=object
jsrto (DeleteObject2).l, JmpTo2_DeleteObject2
jmpto (DeleteObject).l, JmpTo38_DeleteObject
; ===========================================================================
loc_28D6C:
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
move.w #$10,d2
move.w #$11,d3
move.w x_pos(a0),d4
jsrto (SolidObject).l, JmpTo18_SolidObject
jmpto (MarkObjGone).l, JmpTo22_MarkObjGone
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj75_MapUnc_28D8A: BINCLUDE "mappings/sprite/obj75.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo_DisplaySprite3
jmp (DisplaySprite3).l
JmpTo22_DisplaySprite
jmp (DisplaySprite).l
JmpTo38_DeleteObject
jmp (DeleteObject).l
JmpTo22_MarkObjGone
jmp (MarkObjGone).l
JmpTo2_DeleteObject2
jmp (DeleteObject2).l
JmpTo15_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo38_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo8_CalcSine
jmp (CalcSine).l
JmpTo18_SolidObject
jmp (SolidObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 76 - Spike block that slides out of the wall from MCZ
; ----------------------------------------------------------------------------
sliding_spikes_remaining_movement = objoff_36
; Sprite_28DF8:
Obj76:
moveq #0,d0
move.b routine(a0),d0
move.w Obj76_Index(pc,d0.w),d1
jmp Obj76_Index(pc,d1.w)
; ===========================================================================
; off_28E06:
Obj76_Index: offsetTable
offsetTableEntry.w Obj76_Init ; 0
offsetTableEntry.w Obj76_Main ; 2
; ===========================================================================
; byte_28E0A:
Obj76_InitData:
dc.b $40 ; width_pixels
dc.b $10 ; y_radius
dc.b 0 ; mapping_frame
even
; ===========================================================================
; loc_28E0E:
Obj76_Init:
addq.b #2,routine(a0)
move.l #Obj76_MapUnc_28F3A,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo39_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #4,priority(a0)
moveq #0,d0
move.b subtype(a0),d0 ; this is always 0 in the original layouts...
lsr.w #2,d0
andi.w #$1C,d0
lea Obj76_InitData(pc,d0.w),a2
move.b (a2)+,width_pixels(a0)
move.b (a2)+,y_radius(a0)
move.b (a2)+,mapping_frame(a0)
move.w x_pos(a0),objoff_34(a0)
move.w y_pos(a0),objoff_30(a0)
andi.w #$F,subtype(a0)
; loc_28E5E:
Obj76_Main:
move.w x_pos(a0),-(sp)
moveq #0,d0
move.b subtype(a0),d0
move.w Obj76_Modes(pc,d0.w),d1
jsr Obj76_Modes(pc,d1.w)
move.w (sp)+,d4
tst.b render_flags(a0)
bpl.s loc_28EC2
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
jsrto (SolidObject).l, JmpTo19_SolidObject
swap d6
andi.w #touch_side_mask,d6
beq.s loc_28EC2
move.b d6,d0
andi.b #p1_touch_side,d0
beq.s +
lea (MainCharacter).w,a1 ; a1=character
jsrto (Touch_ChkHurt2).l, JmpTo_Touch_ChkHurt2
bclr #p1_pushing_bit,status(a0)
+
andi.b #p2_touch_side,d6
beq.s loc_28EC2
lea (Sidekick).w,a1 ; a1=character
jsrto (Touch_ChkHurt2).l, JmpTo_Touch_ChkHurt2
bclr #p2_pushing_bit,status(a0)
loc_28EC2:
move.w objoff_34(a0),d0
jmpto (MarkObjGone2).l, JmpTo5_MarkObjGone2
; ===========================================================================
; off_28ECA:
Obj76_Modes: offsetTable
offsetTableEntry.w Obj76_CheckPlayers ; 0
offsetTableEntry.w Obj76_SlideOut ; 2
; ===========================================================================
; loc_28ECE:
Obj76_CheckPlayers:
lea (MainCharacter).w,a1 ; a1=character
bsr.s Obj76_CheckPlayer
lea (Sidekick).w,a1 ; a1=character
; loc_28ED8:
Obj76_CheckPlayer:
btst #1,status(a1)
bne.s ++ ; rts
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
addi.w #$C0,d0
btst #0,status(a0)
beq.s +
subi.w #$100,d0
+
cmpi.w #$80,d0
bhs.s + ; rts
move.w y_pos(a1),d0
sub.w y_pos(a0),d0
addi.w #$10,d0
cmpi.w #$20,d0
bhs.s + ; rts
move.b #2,subtype(a0)
move.w #$80,sliding_spikes_remaining_movement(a0)
+ rts
; ===========================================================================
; loc_28F1E:
Obj76_SlideOut:
tst.w sliding_spikes_remaining_movement(a0)
beq.s ++ ; rts
subq.w #1,sliding_spikes_remaining_movement(a0)
moveq #-1,d0
btst #0,status(a0)
beq.s +
neg.w d0
+ add.w d0,x_pos(a0)
+ rts
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj76_MapUnc_28F3A: BINCLUDE "mappings/sprite/obj76.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo_Touch_ChkHurt2
jmp (Touch_ChkHurt2).l
JmpTo39_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo19_SolidObject
jmp (SolidObject).l
JmpTo5_MarkObjGone2
jmp (MarkObjGone2).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 77 - Bridge from MCZ
; ----------------------------------------------------------------------------
; Sprite_28F88:
Obj77:
moveq #0,d0
move.b routine(a0),d0
move.w Obj77_Index(pc,d0.w),d1
jmp Obj77_Index(pc,d1.w)
; ===========================================================================
; off_28F96:
Obj77_Index: offsetTable
offsetTableEntry.w Obj77_Init ; 0
offsetTableEntry.w Obj77_Main ; 2
; ===========================================================================
; loc_28F9A:
Obj77_Init:
addq.b #2,routine(a0)
move.l #Obj77_MapUnc_29064,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_MCZGateLog,3,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo40_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$80,width_pixels(a0)
; loc_28FBC:
Obj77_Main:
tst.b objoff_34(a0)
bne.s +
lea (ButtonVine_Trigger).w,a2
moveq #0,d0
move.b subtype(a0),d0
btst #0,(a2,d0.w)
beq.s +
move.b #1,objoff_34(a0)
bchg #0,anim(a0)
tst.b render_flags(a0)
bpl.s +
move.w #SndID_DoorSlam,d0
jsr (PlaySound).l
+
lea (Ani_obj77).l,a1
jsr (AnimateSprite).l
tst.b mapping_frame(a0)
bne.s Obj77_DropCharacters
move.w #$4B,d1
move.w #8,d2
move.w d2,d3
addq.w #1,d3
move.w x_pos(a0),d4
jsrto (SolidObject).l, JmpTo20_SolidObject
jmpto (MarkObjGone).l, JmpTo23_MarkObjGone
; ===========================================================================
; Check if the characters are standing on it. If a character is standing on the
; bridge, the "standing on object" flag is cleared so that it falls.
; loc_2901A:
Obj77_DropCharacters:
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s +++
move.b d0,d1
andi.b #p1_standing,d0
beq.s +
lea (MainCharacter).w,a1 ; a1=character
bclr #3,status(a1)
+
andi.b #p2_standing,d1
beq.s +
lea (Sidekick).w,a1 ; a1=character
bclr #3,status(a1)
+
andi.b #~standing_mask,status(a0)
+
jmpto (MarkObjGone).l, JmpTo23_MarkObjGone
; ===========================================================================
; ----------------------------------------------------------------------------
; animation script
; ----------------------------------------------------------------------------
; off_29050:
Ani_obj77: offsetTable
offsetTableEntry.w Ani_obj77_Close ; 0
offsetTableEntry.w Ani_obj77_Open ; 1
; byte_29054:
Ani_obj77_Close:
dc.b 3, 4, 3, 2, 1, 0,$FE, 1
; byte_2905C:
Ani_obj77_Open:
dc.b 3, 0, 1, 2, 3, 4,$FE, 1
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj77_MapUnc_29064: BINCLUDE "mappings/sprite/obj77.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo23_MarkObjGone
jmp (MarkObjGone).l
JmpTo40_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo20_SolidObject
jmp (SolidObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 78 - Stairs from CPZ that move down to open the way
; ----------------------------------------------------------------------------
; Sprite_291CC:
Obj78:
moveq #0,d0
move.b routine(a0),d0
move.w Obj78_Index(pc,d0.w),d1
jsr Obj78_Index(pc,d1.w)
move.w objoff_30(a0),d0
jmpto (MarkObjGone2).l, JmpTo6_MarkObjGone2
; ===========================================================================
; off_291E2:
Obj78_Index: offsetTable
offsetTableEntry.w Obj78_Init ; 0
offsetTableEntry.w Obj78_Main ; 2
offsetTableEntry.w loc_29280 ; 4
; ===========================================================================
; loc_291E8:
Obj78_Init:
addq.b #2,routine(a0)
moveq #objoff_34,d3
moveq #2,d4
btst #0,status(a0)
beq.s +
moveq #objoff_3A,d3
moveq #-2,d4
+
move.w x_pos(a0),d2
movea.l a0,a1
moveq #3,d1
bra.s Obj78_LoadSubObject
; ===========================================================================
; loc_29206:
Obj78_SubObjectLoop:
jsrto (SingleObjLoad2).l, JmpTo16_SingleObjLoad2
bne.w Obj78_Main
move.b #4,routine(a1)
; loc_29214:
Obj78_LoadSubObject:
_move.b id(a0),id(a1) ; load obj78
move.l #Obj6B_MapUnc_2800E,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_CPZStairBlock,3,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo5_Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #3,priority(a1)
move.b #$10,width_pixels(a1)
move.b subtype(a0),subtype(a1)
move.w d2,x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w x_pos(a0),objoff_30(a1)
move.w y_pos(a1),objoff_32(a1)
addi.w #$20,d2
move.b d3,objoff_2F(a1)
move.l a0,objoff_3C(a1)
add.b d4,d3
dbf d1,Obj78_SubObjectLoop
; loc_2926C:
Obj78_Main:
moveq #0,d0
move.b subtype(a0),d0
andi.w #7,d0
add.w d0,d0
move.w Obj78_Types(pc,d0.w),d1
jsr Obj78_Types(pc,d1.w)
loc_29280:
movea.l objoff_3C(a0),a2 ; a2=object
moveq #0,d0
move.b objoff_2F(a0),d0
move.w (a2,d0.w),d0
add.w objoff_32(a0),d0
move.w d0,y_pos(a0)
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
move.w #$10,d2
move.w #$11,d3
move.w x_pos(a0),d4
jsrto (SolidObject).l, JmpTo21_SolidObject
swap d6
or.b d6,objoff_2E(a2)
rts
; ===========================================================================
; off_292B8:
Obj78_Types: offsetTable
offsetTableEntry.w loc_292C8 ; 0
offsetTableEntry.w loc_29334 ; 1
offsetTableEntry.w loc_292EC ; 2
offsetTableEntry.w loc_29334 ; 3
offsetTableEntry.w loc_292C8 ; 4
offsetTableEntry.w loc_2935E ; 5
offsetTableEntry.w loc_292EC ; 6
offsetTableEntry.w loc_2935E ; 7
; ===========================================================================
loc_292C8:
tst.w objoff_2C(a0)
bne.s loc_292E0
move.b objoff_2E(a0),d0
andi.b #touch_top_mask,d0
beq.s return_292DE
move.w #$1E,objoff_2C(a0)
return_292DE:
rts
; ===========================================================================
loc_292E0:
subq.w #1,objoff_2C(a0)
bne.s return_292DE
addq.b #1,subtype(a0)
rts
; ===========================================================================
loc_292EC:
tst.w objoff_2C(a0)
bne.s loc_29304
move.b objoff_2E(a0),d0
andi.b #touch_bottom_mask,d0
beq.s return_29302
move.w #$3C,objoff_2C(a0)
return_29302:
rts
; ===========================================================================
loc_29304:
subq.w #1,objoff_2C(a0)
bne.s loc_29310
addq.b #1,subtype(a0)
rts
; ===========================================================================
loc_29310:
lea objoff_34(a0),a1 ; a1=object
move.w objoff_2C(a0),d0
lsr.b #2,d0
andi.b #1,d0
move.w d0,(a1)+
eori.b #1,d0
move.w d0,(a1)+
eori.b #1,d0
move.w d0,(a1)+
eori.b #1,d0
move.w d0,(a1)+
rts
; ===========================================================================
loc_29334:
lea objoff_34(a0),a1 ; a1=object
cmpi.w #$80,(a1)
beq.s return_2935C
addq.w #1,(a1)
moveq #0,d1
move.w (a1)+,d1
swap d1
lsr.l #1,d1
move.l d1,d2
lsr.l #1,d1
move.l d1,d3
add.l d2,d3
swap d1
swap d2
swap d3
move.w d3,(a1)+
move.w d2,(a1)+
move.w d1,(a1)+
return_2935C:
rts
; ===========================================================================
loc_2935E:
lea objoff_34(a0),a1 ; a1=object
cmpi.w #-$80,(a1)
beq.s return_29386
subq.w #1,(a1)
moveq #0,d1
move.w (a1)+,d1
swap d1
asr.l #1,d1
move.l d1,d2
asr.l #1,d1
move.l d1,d3
add.l d2,d3
swap d1
swap d2
swap d3
move.w d3,(a1)+
move.w d2,(a1)+
move.w d1,(a1)+
return_29386:
rts
; ===========================================================================
if ~~removeJmpTos
JmpTo16_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo5_Adjust2PArtPointer2
jmp (Adjust2PArtPointer2).l
JmpTo21_SolidObject
jmp (SolidObject).l
JmpTo6_MarkObjGone2
jmp (MarkObjGone2).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 7A - Platform that moves back and forth on top of water in CPZ
; ----------------------------------------------------------------------------
; Sprite_293A0:
Obj7A:
moveq #0,d0
move.b routine(a0),d0
move.w Obj7A_Index(pc,d0.w),d1
jmp Obj7A_Index(pc,d1.w)
; ===========================================================================
; off_293AE:
Obj7A_Index: offsetTable
offsetTableEntry.w Obj7A_Init ; 0
offsetTableEntry.w Obj7A_Main ; 2
offsetTableEntry.w Obj7A_SubObject ; 4
; ===========================================================================
byte_293B4:
dc.b 0
dc.b $68 ; 1
dc.b $FF ; 2
dc.b $98 ; 3
dc.b 0 ; 4
dc.b 0 ; 5
dc.b 1 ; 6
dc.b $A8 ; 7
dc.b $FF ; 8
dc.b $50 ; 9
dc.b 0 ; 10
dc.b $40 ; 11
dc.b 1 ; 12
dc.b $E8 ; 13
dc.b $FF ; 14
dc.b $80 ; 15
dc.b 0 ; 16
dc.b $80 ; 17
dc.b 0 ; 18
dc.b $68 ; 19
dc.b 0 ; 20
dc.b $67 ; 21
dc.b 0 ; 22
dc.b 0 ; 23
; ===========================================================================
; loc_293CC:
Obj7A_Init:
addq.b #2,routine(a0)
move.l #Obj7A_MapUnc_29564,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CPZStairBlock,3,1),art_tile(a0)
cmpi.b #mystic_cave_zone,(Current_Zone).w
bne.s +
move.l #Obj15_Obj7A_MapUnc_10256,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0)
+
jsrto (Adjust2PArtPointer).l, JmpTo41_Adjust2PArtPointer
moveq #0,d1
move.b subtype(a0),d1
lea byte_293B4(pc,d1.w),a2
move.b (a2)+,d1
movea.l a0,a1
bra.s Obj7A_LoadSubObject
; ===========================================================================
; loc_29408:
Obj7A_SubObjectLoop:
jsrto (SingleObjLoad2).l, JmpTo17_SingleObjLoad2
bne.s Obj7A_SubObjectLoop_End
_move.b id(a0),id(a1) ; load obj7A
move.b #4,routine(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
; loc_29426:
Obj7A_LoadSubObject:
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #4,priority(a1)
move.b #$18,width_pixels(a1)
move.w x_pos(a1),objoff_30(a1)
; loc_2944A:
Obj7A_SubObjectLoop_End:
dbf d1,Obj7A_SubObjectLoop
move.l a0,objoff_3C(a1)
move.l a1,objoff_3C(a0)
cmpi.b #$C,subtype(a0)
bne.s +
move.b #1,objoff_36(a0)
+
moveq #0,d1
move.b (a2)+,d1
move.w objoff_30(a0),d0
sub.w d1,d0
move.w d0,objoff_32(a0)
move.w d0,objoff_32(a1)
add.w d1,d0
add.w d1,d0
move.w d0,objoff_34(a0)
move.w d0,objoff_34(a1)
move.w (a2)+,d0
add.w d0,x_pos(a0)
move.w (a2)+,d0
add.w d0,x_pos(a1)
; loc_2948E:
Obj7A_Main:
bsr.s loc_294F4
tst.w (Two_player_mode).w
beq.s + ; if 2P VS mode is off, branch
jmpto (DisplaySprite).l, JmpTo24_DisplaySprite
; ===========================================================================
+
move.w objoff_32(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bls.s +
move.w objoff_34(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.s loc_294C4
+
jmp (DisplaySprite).l
; ===========================================================================
loc_294C4:
movea.l objoff_3C(a0),a1 ; a1=object
cmpa.l a0,a1
beq.s +
jsr (DeleteObject2).l
+
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s JmpTo39_DeleteObject
bclr #7,2(a2,d0.w)
JmpTo39_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
; loc_294EA:
Obj7A_SubObject:
bsr.s loc_294F4
bsr.s loc_2953E
jmp (DisplaySprite).l
; ===========================================================================
loc_294F4:
move.w x_pos(a0),-(sp)
tst.b objoff_36(a0)
beq.s loc_29516
move.w x_pos(a0),d0
subq.w #1,d0
cmp.w objoff_32(a0),d0
bne.s +
move.b #0,objoff_36(a0)
+
move.w d0,x_pos(a0)
bra.s loc_2952C
; ===========================================================================
loc_29516:
move.w x_pos(a0),d0
addq.w #1,d0
cmp.w objoff_34(a0),d0
bne.s +
move.b #1,objoff_36(a0)
+
move.w d0,x_pos(a0)
loc_2952C:
moveq #0,d1
move.b width_pixels(a0),d1
move.w #8,d3
move.w (sp)+,d4
jsrto (PlatformObject).l, JmpTo6_PlatformObject
rts
; ===========================================================================
loc_2953E:
movea.l objoff_3C(a0),a1 ; a1=object
move.w x_pos(a0),d0
subi.w #$18,d0
move.w x_pos(a1),d2
addi.w #$18,d2
cmp.w d0,d2
bne.s + ; rts
eori.b #1,objoff_36(a0)
eori.b #1,objoff_36(a1)
+
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj7A_MapUnc_29564: BINCLUDE "mappings/sprite/obj7A.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo24_DisplaySprite
jmp (DisplaySprite).l
JmpTo17_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo41_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo6_PlatformObject
jmp (PlatformObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 7B - Warp pipe exit spring from CPZ
; ----------------------------------------------------------------------------
; Sprite_29590:
Obj7B:
moveq #0,d0
move.b routine(a0),d0
move.w Obj7B_Index(pc,d0.w),d1
jsr Obj7B_Index(pc,d1.w)
tst.w (Two_player_mode).w
beq.s +
jmpto (DisplaySprite).l, JmpTo25_DisplaySprite
; ===========================================================================
+
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w JmpTo40_DeleteObject
jmpto (DisplaySprite).l, JmpTo25_DisplaySprite
if removeJmpTos
JmpTo40_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
; off_295C0:
Obj7B_Index: offsetTable
offsetTableEntry.w Obj7B_Init ; 0
offsetTableEntry.w Obj7B_Main ; 2
; ===========================================================================
; byte_295C4:
Obj7B_Strengths:
; Speed applied on Sonic
dc.w -$1000
dc.w -$A80
; ===========================================================================
; loc_295C8:
Obj7B_Init:
addq.b #2,routine(a0)
move.l #Obj7B_MapUnc_29780,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CPZTubeSpring,0,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #1,priority(a0)
move.b subtype(a0),d0
andi.w #2,d0
move.w Obj7B_Strengths(pc,d0.w),objoff_30(a0)
jsrto (Adjust2PArtPointer).l, JmpTo42_Adjust2PArtPointer
; loc_295FE:
Obj7B_Main:
cmpi.b #1,mapping_frame(a0)
beq.s loc_29648
move.w #$1B,d1
move.w #8,d2
move.w #$10,d3
move.w x_pos(a0),d4
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
jsrto (SolidObject_Always_SingleCharacter).l, JmpTo4_SolidObject_Always_SingleCharacter
btst #p1_standing_bit,status(a0)
beq.s +
bsr.w loc_296C2
+
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
jsrto (SolidObject_Always_SingleCharacter).l, JmpTo4_SolidObject_Always_SingleCharacter
btst #p2_standing_bit,status(a0)
beq.s loc_29648
bsr.s loc_296C2
loc_29648:
move.w x_pos(a0),d4
move.w d4,d5
subi.w #$10,d4
addi.w #$10,d5
move.w y_pos(a0),d2
move.w d2,d3
addi.w #$30,d3
move.w (MainCharacter+x_pos).w,d0
cmp.w d4,d0
blo.s loc_29686
cmp.w d5,d0
bhs.s loc_29686
move.w (MainCharacter+y_pos).w,d0
cmp.w d2,d0
blo.s loc_29686
cmp.w d3,d0
bhs.s loc_29686
cmpi.b #2,next_anim(a0)
beq.s loc_29686
move.b #2,anim(a0)
loc_29686:
move.w (Sidekick+x_pos).w,d0
cmp.w d4,d0
blo.s loc_296B6
cmp.w d5,d0
bhs.s loc_296B6
move.w (Sidekick+y_pos).w,d0
cmp.w d2,d0
blo.s loc_296B6
cmp.w d3,d0
bhs.s loc_296B6
cmpi.w #4,(Tails_CPU_routine).w ; TailsCPU_Flying
beq.w loc_296B6
cmpi.b #3,next_anim(a0)
beq.s loc_296B6
move.b #3,anim(a0)
loc_296B6:
lea (Ani_obj7B).l,a1
jmpto (AnimateSprite).l, JmpTo8_AnimateSprite
; ===========================================================================
rts
; ===========================================================================
loc_296C2:
move.w #$100,anim(a0)
addq.w #4,y_pos(a1)
move.w objoff_30(a0),y_vel(a1)
bset #1,status(a1)
bclr #3,status(a1)
move.b #AniIDSonAni_Spring,anim(a1)
move.b #2,routine(a1)
move.b subtype(a0),d0
bpl.s +
move.w #0,x_vel(a1)
+
btst #0,d0
beq.s loc_29736
move.w #1,inertia(a1)
move.b #1,flip_angle(a1)
move.b #AniIDSonAni_Walk,anim(a1)
move.b #0,flips_remaining(a1)
move.b #4,flip_speed(a1)
btst #1,d0
bne.s +
move.b #1,flips_remaining(a1)
+
btst #0,status(a1)
beq.s loc_29736
neg.b flip_angle(a1)
neg.w inertia(a1)
loc_29736:
andi.b #$C,d0
cmpi.b #4,d0
bne.s +
move.b #$C,top_solid_bit(a1)
move.b #$D,lrb_solid_bit(a1)
+
cmpi.b #8,d0
bne.s +
move.b #$E,top_solid_bit(a1)
move.b #$F,lrb_solid_bit(a1)
+
move.w #SndID_Spring,d0
jmp (PlaySound).l
; ===========================================================================
; animation script
; off_29768:
Ani_obj7B: offsetTable
offsetTableEntry.w byte_29770 ; 0
offsetTableEntry.w byte_29773 ; 1
offsetTableEntry.w byte_29777 ; 2
offsetTableEntry.w byte_29777 ; 3
byte_29770: dc.b $F, 0,$FF
rev02even
byte_29773: dc.b 0, 3,$FD, 0
rev02even
byte_29777: dc.b 5, 1, 2, 2, 2, 4,$FD, 0
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj7B_MapUnc_29780: BINCLUDE "mappings/sprite/obj7B.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo25_DisplaySprite
jmp (DisplaySprite).l
JmpTo40_DeleteObject
jmp (DeleteObject).l
JmpTo8_AnimateSprite
jmp (AnimateSprite).l
JmpTo42_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo4_SolidObject_Always_SingleCharacter
jmp (SolidObject_Always_SingleCharacter).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 7F - Vine switch that you hang off in MCZ
; ----------------------------------------------------------------------------
; Sprite_297E4:
Obj7F:
moveq #0,d0
move.b routine(a0),d0
move.w Obj7F_Index(pc,d0.w),d1
jmp Obj7F_Index(pc,d1.w)
; ===========================================================================
; off_297F2:
Obj7F_Index: offsetTable
offsetTableEntry.w Obj7F_Init ; 0
offsetTableEntry.w Obj7F_Main ; 2
; ===========================================================================
; loc_297F6:
Obj7F_Init:
addq.b #2,routine(a0)
move.l #Obj7F_MapUnc_29938,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_VineSwitch,3,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo43_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #8,width_pixels(a0)
move.b #4,priority(a0)
; loc_2981E:
Obj7F_Main:
lea objoff_30(a0),a2
lea (MainCharacter).w,a1 ; a1=character
move.w (Ctrl_1).w,d0
bsr.s Obj7F_Action
lea (Sidekick).w,a1 ; a1=character
addq.w #1,a2
move.w (Ctrl_2).w,d0
bsr.s Obj7F_Action
jmpto (MarkObjGone).l, JmpTo24_MarkObjGone
; ===========================================================================
; loc_2983C:
Obj7F_Action:
tst.b (a2)
beq.s loc_29890
andi.b #button_B_mask|button_C_mask|button_A_mask,d0
beq.w return_29936
clr.b obj_control(a1)
clr.b (a2)
move.b #$12,2(a2)
andi.w #(button_up_mask|button_down_mask|button_left_mask|button_right_mask)<<8,d0
beq.s +
move.b #$3C,2(a2)
+
move.w #-$300,y_vel(a1)
move.b subtype(a0),d0
andi.w #$F,d0
lea (ButtonVine_Trigger).w,a3
lea (a3,d0.w),a3
bclr #0,(a3)
move.b #0,mapping_frame(a0)
tst.w objoff_30(a0)
beq.s +
move.b #1,mapping_frame(a0)
+
bra.w return_29936
; ===========================================================================
loc_29890:
tst.b 2(a2)
beq.s +
subq.b #1,2(a2)
bne.w return_29936
+
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
addi.w #$C,d0
cmpi.w #$18,d0
bhs.w return_29936
move.w y_pos(a1),d1
sub.w y_pos(a0),d1
subi.w #$28,d1
cmpi.w #$10,d1
bhs.w return_29936
tst.b obj_control(a1)
bmi.s return_29936
cmpi.b #4,routine(a1)
bhs.s return_29936
tst.w (Debug_placement_mode).w
bne.s return_29936
clr.w x_vel(a1)
clr.w y_vel(a1)
clr.w inertia(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
addi.w #$30,y_pos(a1)
move.b #AniIDSonAni_Hang2,anim(a1)
move.b #1,obj_control(a1)
move.b #1,(a2)
move.b subtype(a0),d0
andi.w #$F,d0
lea (ButtonVine_Trigger).w,a3
bset #0,(a3,d0.w)
move.w #SndID_Blip,d0
jsr (PlaySound).l
move.b #0,mapping_frame(a0)
tst.w objoff_30(a0)
beq.s return_29936
move.b #1,mapping_frame(a0)
return_29936:
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj7F_MapUnc_29938: BINCLUDE "mappings/sprite/obj7F.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo24_MarkObjGone
jmp (MarkObjGone).l
JmpTo43_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 80 - Vine that you hang off and it moves down from MCZ
; ----------------------------------------------------------------------------
; Sprite_2997C:
Obj80:
moveq #0,d0
move.b routine(a0),d0
move.w Obj80_Index(pc,d0.w),d1
jmp Obj80_Index(pc,d1.w)
; ===========================================================================
; off_2998A:
Obj80_Index: offsetTable
offsetTableEntry.w Obj80_Init ; 0 - Init
offsetTableEntry.w Obj80_MCZ_Main ; 2 - MCZ Vine
offsetTableEntry.w Obj80_WFZ_Main ; 4 - WFZ Hook
; ===========================================================================
; loc_29990:
Obj80_Init:
addq.b #2,routine(a0)
move.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #4,priority(a0)
move.b #$80,y_radius(a0)
bset #4,render_flags(a0)
move.w y_pos(a0),objoff_3C(a0)
cmpi.b #wing_fortress_zone,(Current_Zone).w
bne.s Obj80_MCZ_Init
addq.b #2,routine(a0)
move.l #Obj80_MapUnc_29DD0,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_WfzHook_Fudge,1,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo44_Adjust2PArtPointer
move.w #$A0,objoff_2E(a0)
move.b subtype(a0),d0
move.b d0,d1
andi.b #$F,d0
beq.s +
move.w #$60,objoff_2E(a0)
+
move.b subtype(a0),d0
move.w #2,objoff_3A(a0)
andi.b #$70,d1
beq.s +
move.w objoff_2E(a0),d0
move.w d0,objoff_38(a0)
move.b #1,objoff_36(a0)
add.w d0,y_pos(a0)
lsr.w #4,d0
addq.w #1,d0
move.b d0,mapping_frame(a0)
+
bra.w Obj80_WFZ_Main
; ===========================================================================
; loc_29A1C:
Obj80_MCZ_Init:
move.l #Obj80_MapUnc_29C64,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_VinePulley,3,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo44_Adjust2PArtPointer
move.w #$B0,objoff_2E(a0)
move.b subtype(a0),d0
bpl.s +
move.b #1,objoff_34(a0)
+
move.w #2,objoff_3A(a0)
andi.b #$70,d0
beq.s Obj80_MCZ_Main
move.w objoff_2E(a0),d0
move.w d0,objoff_38(a0)
move.b #1,objoff_36(a0)
add.w d0,y_pos(a0)
lsr.w #5,d0
addq.w #1,d0
move.b d0,mapping_frame(a0)
; loc_29A66:
Obj80_MCZ_Main:
tst.b objoff_36(a0)
beq.s loc_29A74
tst.w objoff_30(a0)
bne.s loc_29A8A
bra.s loc_29A7A
; ===========================================================================
loc_29A74:
tst.w objoff_30(a0)
beq.s loc_29A8A
loc_29A7A:
move.w objoff_38(a0),d2
cmp.w objoff_2E(a0),d2
beq.s loc_29AAE
add.w objoff_3A(a0),d2
bra.s loc_29A94
; ===========================================================================
loc_29A8A:
move.w objoff_38(a0),d2
beq.s loc_29AAE
sub.w objoff_3A(a0),d2
loc_29A94:
move.w d2,objoff_38(a0)
move.w objoff_3C(a0),d0
add.w d2,d0
move.w d0,y_pos(a0)
move.w d2,d0
beq.s +
lsr.w #5,d0
addq.w #1,d0
+
move.b d0,mapping_frame(a0)
loc_29AAE:
lea objoff_30(a0),a2
lea (MainCharacter).w,a1 ; a1=character
move.w (Ctrl_1).w,d0
bsr.s Obj80_Action
lea (Sidekick).w,a1 ; a1=character
addq.w #1,a2
move.w (Ctrl_2).w,d0
bsr.s Obj80_Action
jmpto (MarkObjGone).l, JmpTo25_MarkObjGone
; ===========================================================================
; loc_29ACC:
Obj80_Action:
tst.b (a2)
beq.w loc_29B5E
tst.b render_flags(a1)
bpl.s loc_29B42
cmpi.b #4,routine(a1)
bhs.s loc_29B42
andi.b #button_B_mask|button_C_mask|button_A_mask,d0
beq.w loc_29B50
clr.b obj_control(a1)
clr.b (a2)
move.b #$12,2(a2)
andi.w #(button_up_mask|button_down_mask|button_left_mask|button_right_mask)<<8,d0
beq.w +
move.b #$3C,2(a2)
+
btst #(button_left+8),d0
beq.s +
move.w #-$200,x_vel(a1)
+
btst #(button_right+8),d0
beq.s +
move.w #$200,x_vel(a1)
+
move.w #-$380,y_vel(a1)
bset #1,status(a1)
tst.b objoff_34(a0)
beq.s + ; rts
move.b subtype(a0),d0
andi.w #$F,d0
lea (ButtonVine_Trigger).w,a3
lea (a3,d0.w),a3
bclr #0,(a3)
+
rts
; ===========================================================================
loc_29B42:
clr.b obj_control(a1)
clr.b (a2)
move.b #$3C,2(a2)
rts
; ===========================================================================
loc_29B50:
move.w y_pos(a0),y_pos(a1)
addi.w #$94,y_pos(a1)
rts
; ===========================================================================
loc_29B5E:
tst.b 2(a2)
beq.s +
subq.b #1,2(a2)
bne.w return_29BF8
+
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
addi.w #$10,d0
cmpi.w #$20,d0
bhs.w return_29BF8
move.w y_pos(a1),d1
sub.w y_pos(a0),d1
subi.w #$88,d1
cmpi.w #$18,d1
bhs.w return_29BF8
tst.b obj_control(a1)
bmi.s return_29BF8
cmpi.b #4,routine(a1)
bhs.s return_29BF8
tst.w (Debug_placement_mode).w
bne.s return_29BF8
clr.w x_vel(a1)
clr.w y_vel(a1)
clr.w inertia(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
addi.w #$94,y_pos(a1)
move.b #AniIDSonAni_Hang2,anim(a1)
move.b #1,obj_control(a1)
move.b #1,(a2)
tst.b objoff_34(a0)
beq.s return_29BF8
move.b subtype(a0),d0
andi.w #$F,d0
lea (ButtonVine_Trigger).w,a3
bset #0,(a3,d0.w)
move.w #SndID_Blip,d0
jsr (PlaySound).l
return_29BF8:
rts
; ===========================================================================
; loc_29BFA:
Obj80_WFZ_Main:
tst.b objoff_36(a0)
beq.s loc_29C08
tst.w objoff_30(a0)
bne.s loc_29C1E
bra.s loc_29C0E
; ===========================================================================
loc_29C08:
tst.w objoff_30(a0)
beq.s loc_29C1E
loc_29C0E:
move.w objoff_38(a0),d2
cmp.w objoff_2E(a0),d2
beq.s loc_29C42
add.w objoff_3A(a0),d2
bra.s loc_29C28
; ===========================================================================
loc_29C1E:
move.w objoff_38(a0),d2
beq.s loc_29C42
sub.w objoff_3A(a0),d2
loc_29C28:
move.w d2,objoff_38(a0)
move.w objoff_3C(a0),d0
add.w d2,d0
move.w d0,y_pos(a0)
move.w d2,d0
beq.s +
lsr.w #4,d0
addq.w #1,d0
+
move.b d0,mapping_frame(a0)
loc_29C42:
lea objoff_30(a0),a2
lea (MainCharacter).w,a1 ; a1=character
move.w (Ctrl_1).w,d0
bsr.w Obj80_Action
lea (Sidekick).w,a1 ; a1=character
addq.w #1,a2
move.w (Ctrl_2).w,d0
bsr.w Obj80_Action
jmpto (MarkObjGone).l, JmpTo25_MarkObjGone
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj80_MapUnc_29C64: BINCLUDE "mappings/sprite/obj80_a.bin"
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj80_MapUnc_29DD0: BINCLUDE "mappings/sprite/obj80_b.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo25_MarkObjGone
jmp (MarkObjGone).l
JmpTo44_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 81 - Drawbridge (MCZ)
; ----------------------------------------------------------------------------
; Sprite_2A000:
Obj81:
btst #6,render_flags(a0)
bne.w +
moveq #0,d0
move.b routine(a0),d0
move.w Obj81_Index(pc,d0.w),d1
jmp Obj81_Index(pc,d1.w)
; ===========================================================================
+
move.w #$280,d0
jmpto (DisplaySprite3).l, JmpTo2_DisplaySprite3
; ===========================================================================
; off_2A020:
Obj81_Index: offsetTable
offsetTableEntry.w Obj81_Init ; 0
offsetTableEntry.w Obj81_BridgeUp ; 2
offsetTableEntry.w loc_2A18A ; 4
; ===========================================================================
; loc_2A026:
Obj81_Init:
addq.b #2,routine(a0)
move.l #Obj81_MapUnc_2A24E,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_MCZGateLog,3,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo45_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #5,priority(a0)
move.b #8,width_pixels(a0)
ori.b #$80,status(a0)
move.w x_pos(a0),objoff_30(a0)
move.w y_pos(a0),objoff_32(a0)
subi.w #$48,y_pos(a0)
move.b #-$40,angle(a0)
moveq #-$10,d4
btst #1,status(a0)
beq.s +
addi.w #$90,y_pos(a0)
move.b #$40,angle(a0)
neg.w d4
+
move.w #$100,d1
btst #0,status(a0)
beq.s +
neg.w d1
+
move.w d1,objoff_34(a0)
jsrto (SingleObjLoad2).l, JmpTo18_SingleObjLoad2
bne.s Obj81_BridgeUp
_move.b id(a0),id(a1) ; load obj81
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
move.b #4,render_flags(a1)
bset #6,render_flags(a1)
move.b #$40,mainspr_width(a1)
move.w objoff_30(a0),d2
move.w objoff_32(a0),d3
moveq #8,d1
move.b d1,mainspr_childsprites(a1)
subq.w #1,d1
lea sub2_x_pos(a1),a2
- add.w d4,d3
move.w d2,(a2)+ ; sub?_x_pos
move.w d3,(a2)+ ; sub?_y_pos
move.w #1,(a2)+ ; sub?_mapframe
dbf d1,-
move.w sub6_x_pos(a1),x_pos(a1)
move.w sub6_y_pos(a1),y_pos(a1)
move.l a1,objoff_3C(a0)
move.b #$40,mainspr_height(a1)
bset #4,render_flags(a1)
; loc_2A0FE:
Obj81_BridgeUp:
lea (ButtonVine_Trigger).w,a2
moveq #0,d0
move.b subtype(a0),d0
btst #0,(a2,d0.w)
beq.s +
tst.b objoff_36(a0)
bne.s +
move.b #1,objoff_36(a0)
move.w #SndID_DrawbridgeMove,d0
jsr (PlaySoundStereo).l
cmpi.b #$81,status(a0)
bne.s +
move.w objoff_30(a0),x_pos(a0)
subi.w #$48,x_pos(a0)
+
tst.b objoff_36(a0)
beq.s loc_2A188
move.w #$48,d1
tst.b angle(a0)
beq.s loc_2A154
cmpi.b #$80,angle(a0)
bne.s loc_2A180
neg.w d1
loc_2A154:
move.w objoff_32(a0),y_pos(a0)
move.w objoff_30(a0),x_pos(a0)
add.w d1,x_pos(a0)
move.b #$40,width_pixels(a0)
move.b #0,objoff_36(a0)
move.w #SndID_DrawbridgeDown,d0
jsr (PlaySound).l
addq.b #2,routine(a0)
bra.s loc_2A188
; ===========================================================================
loc_2A180:
move.w objoff_34(a0),d0
add.w d0,angle(a0)
loc_2A188:
bsr.s loc_2A1EA
loc_2A18A:
move.w #$13,d1
move.w #$40,d2
move.w #$41,d3
move.b angle(a0),d0
beq.s loc_2A1A8
cmpi.b #$40,d0
beq.s loc_2A1B4
cmpi.b #-$40,d0
bhs.s loc_2A1B4
loc_2A1A8:
move.w #$4B,d1
move.w #8,d2
move.w #9,d3
loc_2A1B4:
move.w x_pos(a0),d4
jsrto (SolidObject).l, JmpTo22_SolidObject
tst.w (Two_player_mode).w
beq.s +
jmpto (DisplaySprite).l, JmpTo26_DisplaySprite
; ---------------------------------------------------------------------------
+
move.w objoff_30(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w +
jmpto (DisplaySprite).l, JmpTo26_DisplaySprite
; ---------------------------------------------------------------------------
+
movea.l objoff_3C(a0),a1 ; a1=object
jsrto (DeleteObject2).l, JmpTo3_DeleteObject2
jmpto (DeleteObject).l, JmpTo41_DeleteObject
; ===========================================================================
loc_2A1EA:
tst.b objoff_36(a0)
beq.s return_2A24C
moveq #0,d0
moveq #0,d1
move.b angle(a0),d0
jsrto (CalcSine).l, JmpTo9_CalcSine
move.w objoff_32(a0),d2
move.w objoff_30(a0),d3
moveq #0,d6
movea.l objoff_3C(a0),a1 ; a1=object
move.b mainspr_childsprites(a1),d6
subq.w #1,d6
bcs.s return_2A24C
swap d0
swap d1
asr.l #4,d0
asr.l #4,d1
move.l d0,d4
move.l d1,d5
lea sub2_x_pos(a1),a2
- movem.l d4-d5,-(sp)
swap d4
swap d5
add.w d2,d4
add.w d3,d5
move.w d5,(a2)+ ; sub?_x_pos
move.w d4,(a2)+ ; sub?_y_pos
movem.l (sp)+,d4-d5
add.l d0,d4
add.l d1,d5
addq.w #next_subspr-4,a2
dbf d6,-
move.w sub6_x_pos(a1),x_pos(a1)
move.w sub6_y_pos(a1),y_pos(a1)
return_2A24C:
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj81_MapUnc_2A24E: BINCLUDE "mappings/sprite/obj81.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo2_DisplaySprite3
jmp (DisplaySprite3).l
JmpTo26_DisplaySprite
jmp (DisplaySprite).l
JmpTo41_DeleteObject
jmp (DeleteObject).l
JmpTo3_DeleteObject2
jmp (DeleteObject2).l
JmpTo18_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo45_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo9_CalcSine
jmp (CalcSine).l
JmpTo22_SolidObject
jmp (SolidObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 82 - Platform that is usually swinging, from ARZ
; ----------------------------------------------------------------------------
; Sprite_2A290:
Obj82:
moveq #0,d0
move.b routine(a0),d0
move.w Obj82_Index(pc,d0.w),d1
jmp Obj82_Index(pc,d1.w)
; ===========================================================================
; off_2A29E:
Obj82_Index: offsetTable
offsetTableEntry.w Obj82_Init ; 0
offsetTableEntry.w Obj82_Main ; 2
; ===========================================================================
; byte_2A2A2:
Obj82_Properties:
; width_pixels
; y_radius
dc.b $20, 8 ; 0
dc.b $1C,$30 ; 2
; Unused and broken; these don't have an associated frame, so using them crashes the game
dc.b $10,$10 ; 4
dc.b $10,$10 ; 6
; ===========================================================================
; loc_2A2AA:
Obj82_Init:
addq.b #2,routine(a0)
move.l #Obj82_MapUnc_2A476,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo46_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #3,priority(a0)
moveq #0,d0
move.b subtype(a0),d0
lsr.w #3,d0
andi.w #$E,d0
lea Obj82_Properties(pc,d0.w),a2
move.b (a2)+,width_pixels(a0)
move.b (a2),y_radius(a0)
lsr.w #1,d0
move.b d0,mapping_frame(a0)
move.w x_pos(a0),objoff_34(a0)
move.w y_pos(a0),objoff_30(a0)
move.b subtype(a0),d0
andi.b #$F,d0
beq.s +
cmpi.b #7,d0
beq.s +
move.b #1,objoff_38(a0)
+
andi.b #$F,subtype(a0)
; loc_2A312:
Obj82_Main:
move.w x_pos(a0),-(sp)
moveq #0,d0
move.b subtype(a0),d0
add.w d0,d0
move.w Obj82_Types(pc,d0.w),d1
jsr Obj82_Types(pc,d1.w)
move.w (sp)+,d4
tst.b render_flags(a0)
bpl.s +
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
moveq #0,d2
move.b y_radius(a0),d2
move.w d2,d3
addq.w #1,d3
jsrto (SolidObject).l, JmpTo23_SolidObject
swap d6
move.b d6,objoff_3F(a0)
bsr.w loc_2A432
+
move.w objoff_34(a0),d0
jmpto (MarkObjGone2).l, JmpTo7_MarkObjGone2
; ===========================================================================
; off_2A358:
Obj82_Types: offsetTable
offsetTableEntry.w return_2A368 ; 0
offsetTableEntry.w loc_2A36A ; 1
offsetTableEntry.w loc_2A392 ; 2
offsetTableEntry.w loc_2A36A ; 3
offsetTableEntry.w loc_2A3B6 ; 4
offsetTableEntry.w loc_2A3D8 ; 5
offsetTableEntry.w loc_2A392 ; 6
offsetTableEntry.w loc_2A3EC ; 7
; ===========================================================================
return_2A368:
rts
; ===========================================================================
loc_2A36A:
tst.w objoff_36(a0)
bne.s loc_2A382
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s return_2A380
move.w #$1E,objoff_36(a0)
return_2A380:
rts
; ===========================================================================
loc_2A382:
subq.w #1,objoff_36(a0)
bne.s return_2A380
addq.b #1,subtype(a0)
clr.b objoff_38(a0)
rts
; ===========================================================================
loc_2A392:
jsrto (ObjectMove).l, JmpTo16_ObjectMove
addi_.w #8,y_vel(a0)
jsrto (ObjCheckFloorDist).l, JmpTo2_ObjCheckFloorDist
tst.w d1
bpl.w return_2A3B4
addq.w #1,d1
add.w d1,y_pos(a0)
clr.w y_vel(a0)
clr.b subtype(a0)
return_2A3B4:
rts
; ===========================================================================
loc_2A3B6:
jsrto (ObjectMove).l, JmpTo16_ObjectMove
subi_.w #8,y_vel(a0)
jsrto (ObjCheckCeilingDist).l, JmpTo_ObjCheckCeilingDist
tst.w d1
bpl.w return_2A3D6
sub.w d1,y_pos(a0)
clr.w y_vel(a0)
clr.b subtype(a0)
return_2A3D6:
rts
; ===========================================================================
loc_2A3D8:
move.b objoff_3F(a0),d0
andi.b #3,d0
beq.s return_2A3EA
addq.b #1,subtype(a0)
clr.b objoff_38(a0)
return_2A3EA:
rts
; ===========================================================================
loc_2A3EC:
move.w (Water_Level_1).w,d0
sub.w y_pos(a0),d0
beq.s return_2A430
bcc.s loc_2A414
cmpi.w #-2,d0
bge.s loc_2A400
moveq #-2,d0
loc_2A400:
add.w d0,y_pos(a0)
jsrto (ObjCheckCeilingDist).l, JmpTo_ObjCheckCeilingDist
tst.w d1
bpl.w return_2A412
sub.w d1,y_pos(a0)
return_2A412:
rts
; ===========================================================================
loc_2A414:
cmpi.w #2,d0
ble.s loc_2A41C
moveq #2,d0
loc_2A41C:
add.w d0,y_pos(a0)
jsrto (ObjCheckFloorDist).l, JmpTo2_ObjCheckFloorDist
tst.w d1
bpl.w return_2A430
addq.w #1,d1
add.w d1,y_pos(a0)
return_2A430:
rts
; ===========================================================================
loc_2A432:
tst.b objoff_38(a0)
beq.s return_2A474
move.b status(a0),d0
andi.b #standing_mask,d0
bne.s loc_2A44E
tst.b objoff_3E(a0)
beq.s return_2A474
subq.b #4,objoff_3E(a0)
bra.s loc_2A45A
; ===========================================================================
loc_2A44E:
cmpi.b #$40,objoff_3E(a0)
beq.s return_2A474
addq.b #4,objoff_3E(a0)
loc_2A45A:
move.b objoff_3E(a0),d0
jsr (CalcSine).l
move.w #$400,d1
muls.w d1,d0
swap d0
add.w objoff_30(a0),d0
move.w d0,y_pos(a0)
return_2A474:
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj82_MapUnc_2A476: BINCLUDE "mappings/sprite/obj82.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo2_ObjCheckFloorDist
jmp (ObjCheckFloorDist).l
JmpTo46_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo_ObjCheckCeilingDist
jmp (ObjCheckCeilingDist).l
JmpTo23_SolidObject
jmp (SolidObject).l
JmpTo7_MarkObjGone2
jmp (MarkObjGone2).l
; loc_2A4F6:
JmpTo16_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 83 - 3 adjoined platforms from ARZ that rotate in a circle
; ----------------------------------------------------------------------------
; OST Variables:
Obj83_last_x_pos = objoff_2C ; word
Obj83_speed = objoff_2E ; word
Obj83_initial_x_pos = objoff_30 ; word
Obj83_initial_y_pos = objoff_32 ; word
; Child object RAM pointers
Obj83_childobjptr_chains = objoff_34 ; longword ; chain multisprite object
Obj83_childobjptr_platform2 = objoff_38 ; longword ; 2nd platform object (parent object is 1st platform)
Obj83_childobjptr_platform3 = objoff_3C ; longword ; 3rd platform object
; Sprite_2A4FC:
Obj83:
btst #6,render_flags(a0)
bne.w .isMultispriteObject
moveq #0,d0
move.b routine(a0),d0
move.w Obj83_Index(pc,d0.w),d1
jmp Obj83_Index(pc,d1.w)
; ===========================================================================
.isMultispriteObject:
move.w #$280,d0
jmpto (DisplaySprite3).l, JmpTo3_DisplaySprite3
; ===========================================================================
; off_2A51C:
Obj83_Index: offsetTable
offsetTableEntry.w Obj83_Init ; 0
offsetTableEntry.w Obj83_Main ; 2
offsetTableEntry.w Obj83_PlatformSubObject ; 4
; ===========================================================================
; loc_2A522:
Obj83_Init:
addq.b #2,routine(a0)
move.l #Obj15_Obj83_MapUnc_1021E,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo47_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #4,priority(a0)
move.b #$20,width_pixels(a0)
move.w x_pos(a0),Obj83_initial_x_pos(a0)
move.w y_pos(a0),Obj83_initial_y_pos(a0)
; Setup subtype variables (rotation speed and other unused variable)
move.b subtype(a0),d1
move.b d1,d0
andi.w #$F,d1 ; The lower 4 bits of subtype are unused, making these instructions useless
andi.b #$F0,d0
ext.w d0
asl.w #3,d0
move.w d0,Obj83_speed(a0)
; Set angle according to X-flip and Y-flip
move.b status(a0),d0
ror.b #2,d0
andi.b #$C0,d0
move.b d0,angle(a0)
; Create child object (chain multisprite)
jsrto (SingleObjLoad2).l, JmpTo19_SingleObjLoad2
bne.s .noRAMforChildObjects
_move.b id(a0),id(a1) ; load obj83
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
move.b #4,render_flags(a1)
bset #6,render_flags(a1)
move.b #$40,mainspr_width(a1)
moveq #8,d1
move.b d1,mainspr_childsprites(a1)
subq.w #1,d1
lea sub2_x_pos(a1),a2
.nextChildSprite:
addq.w #next_subspr-2,a2
move.w #1,(a2)+ ; sub?_mapframe
dbf d1,.nextChildSprite
move.b #1,mainspr_mapframe(a1)
move.b #$40,mainspr_height(a1)
bset #4,render_flags(a1)
move.l a1,Obj83_childobjptr_chains(a0)
; Create remaining child objects: platform 2 and 3
bsr.s Obj83_LoadSubObject
move.l a1,Obj83_childobjptr_platform2(a0)
bsr.s Obj83_LoadSubObject
move.l a1,Obj83_childobjptr_platform3(a0)
.noRAMforChildObjects:
bra.s Obj83_Main
; ===========================================================================
; loc_2A5DE:
Obj83_LoadSubObject:
jsrto (SingleObjLoad2).l, JmpTo19_SingleObjLoad2
bne.s .noRAMforChildObject ; rts
addq.b #4,routine(a1)
_move.b id(a0),id(a1) ; load obj
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #4,priority(a1)
move.b #$20,width_pixels(a1)
move.w x_pos(a0),Obj83_initial_x_pos(a1)
move.w y_pos(a0),Obj83_initial_y_pos(a1)
move.w x_pos(a0),Obj83_last_x_pos(a1)
.noRAMforChildObject:
rts
; ===========================================================================
; loc_2A620:
Obj83_Main:
move.w x_pos(a0),-(sp)
moveq #0,d0
moveq #0,d1
move.w Obj83_speed(a0),d0
add.w d0,angle(a0)
move.w Obj83_initial_y_pos(a0),d2
move.w Obj83_initial_x_pos(a0),d3
moveq #0,d6
movea.l Obj83_childobjptr_chains(a0),a1 ; a1=object
lea sub2_x_pos(a1),a2
; Update first row of chains
move.b angle(a0),d0
jsrto (CalcSine).l, JmpTo10_CalcSine
swap d0
swap d1
asr.l #4,d0
asr.l #4,d1
move.l d0,d4
move.l d1,d5
swap d4
swap d5
add.w d2,d4
add.w d3,d5
move.w d5,x_pos(a1) ; update chainlink mainsprite x_pos
move.w d4,y_pos(a1) ; update chainlink mainsprite y_pos
move.l d0,d4
move.l d1,d5
add.l d0,d4
add.l d1,d5
moveq #1,d6 ; Update 2 chainlink childsprites (the third chainlink is the mainsprite, which has already been updated)
bsr.w Obj83_UpdateChainSpritePosition
swap d4
swap d5
add.w d2,d4
add.w d3,d5
move.w d5,x_pos(a0)
move.w d4,y_pos(a0)
; Update second row of chains
move.b angle(a0),d0
addi.b #256/3,d0 ; 360 degrees = 256
jsrto (CalcSine).l, JmpTo10_CalcSine
swap d0
swap d1
asr.l #4,d0
asr.l #4,d1
move.l d0,d4
move.l d1,d5
moveq #2,d6 ; Update 3 chainlink childsprites
bsr.w Obj83_UpdateChainSpritePosition
swap d4
swap d5
add.w d2,d4
add.w d3,d5
movea.l Obj83_childobjptr_platform2(a0),a1 ; a1=object
move.w d5,x_pos(a1)
move.w d4,y_pos(a1)
; Update third row of chains
move.b angle(a0),d0
subi.b #256/3,d0 ; 360 degrees = 256
jsrto (CalcSine).l, JmpTo10_CalcSine
swap d0
swap d1
asr.l #4,d0
asr.l #4,d1
move.l d0,d4
move.l d1,d5
moveq #2,d6 ; Update 3 chainlink childsprites
bsr.w Obj83_UpdateChainSpritePosition
swap d4
swap d5
add.w d2,d4
add.w d3,d5
movea.l Obj83_childobjptr_platform3(a0),a1 ; a1=object
move.w d5,x_pos(a1)
move.w d4,y_pos(a1)
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
move.w #8,d2
move.w #9,d3
move.w (sp)+,d4
jsrto (PlatformObject).l, JmpTo7_PlatformObject
tst.w (Two_player_mode).w
beq.s .notTwoPlayerMode
jmpto (DisplaySprite).l, JmpTo27_DisplaySprite
; ===========================================================================
.notTwoPlayerMode:
move.w Obj83_initial_x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w .objectOffscreen
jmpto (DisplaySprite).l, JmpTo27_DisplaySprite
; ===========================================================================
.objectOffscreen:
movea.l Obj83_childobjptr_chains(a0),a1 ; a1=object
jsrto (DeleteObject2).l, JmpTo4_DeleteObject2
jmpto (DeleteObject).l, JmpTo42_DeleteObject
; ===========================================================================
; loc_2A72E:
Obj83_UpdateChainSpritePosition:
.nextChainSprite:
movem.l d4-d5,-(sp)
swap d4
swap d5
add.w d2,d4
add.w d3,d5
move.w d5,(a2)+ ; sub?_x_pos
move.w d4,(a2)+ ; sub?_y_pos
movem.l (sp)+,d4-d5
add.l d0,d4
add.l d1,d5
addq.w #next_subspr-4,a2
dbf d6,.nextChainSprite
rts
; ===========================================================================
; loc_2A74E: Obj83_SubObject:
Obj83_PlatformSubObject:
moveq #0,d1
move.b width_pixels(a0),d1
addi.w #$B,d1
move.w #8,d2
move.w #9,d3
move.w Obj83_last_x_pos(a0),d4
jsrto (PlatformObject).l, JmpTo7_PlatformObject
move.w x_pos(a0),Obj83_last_x_pos(a0)
move.w Obj83_initial_x_pos(a0),d0
jmpto (MarkObjGone2).l, JmpTo8_MarkObjGone2
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo3_DisplaySprite3
jmp (DisplaySprite3).l
JmpTo27_DisplaySprite
jmp (DisplaySprite).l
JmpTo42_DeleteObject
jmp (DeleteObject).l
JmpTo4_DeleteObject2
jmp (DeleteObject2).l
JmpTo19_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo47_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo10_CalcSine
jmp (CalcSine).l
JmpTo7_PlatformObject
jmp (PlatformObject).l
JmpTo8_MarkObjGone2
jmp (MarkObjGone2).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 3F - Fan from OOZ
; ----------------------------------------------------------------------------
; Sprite_2A7B0:
Obj3F:
moveq #0,d0
move.b routine(a0),d0
move.w Obj3F_Index(pc,d0.w),d1
jmp Obj3F_Index(pc,d1.w)
; ===========================================================================
; off_2A7BE:
Obj3F_Index: offsetTable
offsetTableEntry.w Obj3F_Init ; 0
offsetTableEntry.w Obj3F_Horizontal ; 2 - pushes horizontally
offsetTableEntry.w Obj3F_Vertical ; 4 - pushes vertically
; ===========================================================================
; loc_2A7C4:
Obj3F_Init:
addq.b #2,routine(a0)
move.l #Obj3F_MapUnc_2AA12,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_OOZFanHoriz,3,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo48_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #4,priority(a0)
tst.b subtype(a0)
bpl.s Obj3F_Horizontal
addq.b #2,routine(a0)
move.l #Obj3F_MapUnc_2AAC4,mappings(a0)
bra.w Obj3F_Vertical
; ===========================================================================
; loc_2A802:
Obj3F_Horizontal:
btst #1,subtype(a0)
bne.s loc_2A82A
subq.w #1,objoff_30(a0)
bpl.s loc_2A82A
move.w #0,objoff_34(a0)
move.w #$78,objoff_30(a0)
bchg #0,objoff_32(a0)
beq.s loc_2A82A
move.w #$B4,objoff_30(a0)
loc_2A82A:
tst.b objoff_32(a0)
beq.w loc_2A84E
subq.b #1,anim_frame_duration(a0)
bpl.s BranchTo_JmpTo26_MarkObjGone
cmpi.w #$400,objoff_34(a0)
bhs.s BranchTo_JmpTo26_MarkObjGone
addi.w #$2A,objoff_34(a0)
move.b objoff_34(a0),anim_frame_duration(a0)
bra.s loc_2A86A
; ===========================================================================
loc_2A84E:
lea (MainCharacter).w,a1 ; a1=character
bsr.w loc_2A894
lea (Sidekick).w,a1 ; a1=character
bsr.w loc_2A894
subq.b #1,anim_frame_duration(a0)
bpl.s BranchTo_JmpTo26_MarkObjGone
move.b #0,anim_frame_duration(a0)
loc_2A86A:
addq.b #1,anim_frame(a0)
cmpi.b #6,anim_frame(a0)
blo.s loc_2A87C
move.b #0,anim_frame(a0)
loc_2A87C:
moveq #0,d0
btst #0,subtype(a0)
beq.s loc_2A888
moveq #5,d0
loc_2A888:
add.b anim_frame(a0),d0
move.b d0,mapping_frame(a0)
BranchTo_JmpTo26_MarkObjGone
jmpto (MarkObjGone).l, JmpTo26_MarkObjGone
; ===========================================================================
loc_2A894:
cmpi.b #4,routine(a1)
bhs.s return_2A8FC
tst.b obj_control(a1)
bne.s return_2A8FC
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
btst #0,status(a0)
bne.s loc_2A8B4
neg.w d0
loc_2A8B4:
addi.w #$50,d0
cmpi.w #$F0,d0
bhs.s return_2A8FC
move.w y_pos(a1),d1
addi.w #$60,d1
sub.w y_pos(a0),d1
bcs.s return_2A8FC
cmpi.w #$70,d1
bhs.s return_2A8FC
subi.w #$50,d0
bcc.s loc_2A8DC
not.w d0
add.w d0,d0
loc_2A8DC:
addi.w #$60,d0
btst #0,status(a0)
bne.s loc_2A8EA
neg.w d0
loc_2A8EA:
neg.b d0
asr.w #4,d0
btst #0,subtype(a0)
beq.s loc_2A8F8
neg.w d0
loc_2A8F8:
add.w d0,x_pos(a1)
return_2A8FC:
rts
; ===========================================================================
; loc_2A8FE:
Obj3F_Vertical:
btst #1,subtype(a0)
bne.s loc_2A926
subq.w #1,objoff_30(a0)
bpl.s loc_2A926
move.w #0,objoff_34(a0)
move.w #$78,objoff_30(a0)
bchg #0,objoff_32(a0)
beq.s loc_2A926
move.w #$B4,objoff_30(a0)
loc_2A926:
tst.b objoff_32(a0)
beq.w loc_2A94A
subq.b #1,anim_frame_duration(a0)
bpl.s BranchTo2_JmpTo26_MarkObjGone
cmpi.w #$400,objoff_34(a0)
bhs.s BranchTo2_JmpTo26_MarkObjGone
addi.w #$2A,objoff_34(a0)
move.b objoff_34(a0),anim_frame_duration(a0)
bra.s loc_2A966
; ===========================================================================
loc_2A94A:
lea (MainCharacter).w,a1 ; a1=character
bsr.w loc_2A990
lea (Sidekick).w,a1 ; a1=character
bsr.w loc_2A990
subq.b #1,anim_frame_duration(a0)
bpl.s BranchTo2_JmpTo26_MarkObjGone
move.b #0,anim_frame_duration(a0)
loc_2A966:
addq.b #1,anim_frame(a0)
cmpi.b #6,anim_frame(a0)
blo.s +
move.b #0,anim_frame(a0)
+
moveq #0,d0
btst #0,subtype(a0)
beq.s +
moveq #5,d0
+
add.b anim_frame(a0),d0
move.b d0,mapping_frame(a0)
BranchTo2_JmpTo26_MarkObjGone
jmpto (MarkObjGone).l, JmpTo26_MarkObjGone
; ===========================================================================
loc_2A990:
cmpi.b #4,routine(a1)
bhs.s return_2AA10
tst.b obj_control(a1)
bne.s return_2AA10
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
addi.w #$40,d0
cmpi.w #$80,d0
bhs.s return_2AA10
moveq #0,d1
move.b (Oscillating_Data+$14).w,d1
add.w y_pos(a1),d1
addi.w #$60,d1
sub.w y_pos(a0),d1
bcs.s return_2AA10
cmpi.w #$90,d1
bhs.s return_2AA10
subi.w #$60,d1
bcs.s +
not.w d1
add.w d1,d1
+
addi.w #$60,d1
neg.w d1
asr.w #4,d1
add.w d1,y_pos(a1)
bset #1,status(a1)
move.w #0,y_vel(a1)
move.w #1,inertia(a1)
tst.b flip_angle(a1)
bne.s return_2AA10
move.b #1,flip_angle(a1)
move.b #AniIDSonAni_Walk,anim(a1)
move.b #$7F,flips_remaining(a1)
move.b #8,flip_speed(a1)
return_2AA10:
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
; sidefacing fan
Obj3F_MapUnc_2AA12: BINCLUDE "mappings/sprite/obj3F_a.bin"
; upfacing fan
Obj3F_MapUnc_2AAC4: BINCLUDE "mappings/sprite/obj3F_b.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo26_MarkObjGone
jmp (MarkObjGone).l
JmpTo48_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 85 - Spring from CNZ that you hold jump on to pull back further
; ----------------------------------------------------------------------------
; Sprite_2AB84:
Obj85:
moveq #0,d0
move.b routine(a0),d0
move.w Obj85_Index(pc,d0.w),d1
jsr Obj85_Index(pc,d1.w)
move.w #$200,d0
tst.w (Two_player_mode).w
beq.s +
jmpto (DisplaySprite3).l, JmpTo4_DisplaySprite3
; ===========================================================================
+
move.w x_pos(a0),d1
andi.w #$FF80,d1
sub.w (Camera_X_pos_coarse).w,d1
cmpi.w #$280,d1
bhi.w +
jmpto (DisplaySprite3).l, JmpTo4_DisplaySprite3
; ===========================================================================
+
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s BranchTo_JmpTo43_DeleteObject
bclr #7,2(a2,d0.w)
BranchTo_JmpTo43_DeleteObject
jmpto (DeleteObject).l, JmpTo43_DeleteObject
; ===========================================================================
; off_2ABCE:
Obj85_Index: offsetTable
offsetTableEntry.w Obj85_Init ; 0
offsetTableEntry.w Obj85_Up ; 2
offsetTableEntry.w Obj85_Diagonal ; 4
; ===========================================================================
; loc_2ABD4:
Obj85_Init:
addq.b #2,routine(a0)
move.l #Obj85_MapUnc_2B07E,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CNZVertPlunger,0,0),art_tile(a0)
tst.b subtype(a0)
beq.s +
move.l #Obj85_MapUnc_2B0EC,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CNZDiagPlunger,0,0),art_tile(a0)
+
jsrto (Adjust2PArtPointer).l, JmpTo49_Adjust2PArtPointer
move.b #4,render_flags(a0)
bset #6,render_flags(a0)
move.b #1,mainspr_mapframe(a0)
tst.b subtype(a0)
beq.s Obj85_Init_Up
addq.b #2,routine(a0)
move.b #$20,mainspr_width(a0)
move.b #$18,width_pixels(a0)
move.w x_pos(a0),objoff_2E(a0)
move.w y_pos(a0),objoff_34(a0)
move.w x_pos(a0),d2
move.w y_pos(a0),d3
addi.w #0,d3
move.b #1,mainspr_childsprites(a0)
lea sub2_x_pos(a0),a2
move.w d2,(a2)+ ; sub2_x_pos
move.w d3,(a2)+ ; sub2_y_pos
move.w #2,(a2)+ ; sub2_mapframe
bra.w Obj85_Diagonal
; ===========================================================================
; loc_2AC54:
Obj85_Init_Up:
move.b #$18,mainspr_width(a0)
move.b #$18,width_pixels(a0)
move.w y_pos(a0),objoff_34(a0)
move.w x_pos(a0),d2
move.w y_pos(a0),d3
addi.w #$20,d3
move.b #1,mainspr_childsprites(a0)
lea sub2_x_pos(a0),a2
move.w d2,(a2)+ ; sub2_x_pos
move.w d3,(a2)+ ; sub2_y_pos
move.w #2,(a2)+ ; sub2_mapframe
; loc_2AC84:
Obj85_Up:
move.b #0,objoff_3A(a0)
move.w objoff_34(a0),d0
add.w objoff_38(a0),d0
move.w d0,y_pos(a0)
move.b #2,sub2_mapframe(a0)
cmpi.w #$10,objoff_38(a0)
blo.s +
move.b #3,sub2_mapframe(a0)
+
move.w #$23,d1
move.w #$20,d2
move.w #$1D,d3
move.w x_pos(a0),d4
lea objoff_36(a0),a2
lea (MainCharacter).w,a1 ; a1=character
move.w (Ctrl_1_Logical).w,d5
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.s loc_2AD26
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
addq.w #1,a2
move.w (Ctrl_2).w,d5
moveq #p2_standing_bit,d6
bsr.s loc_2AD26
tst.w objoff_36(a0)
beq.s loc_2AD14
tst.w objoff_38(a0)
beq.s return_2AD24
moveq #0,d0
cmpi.b #1,objoff_36(a0)
bne.s +
or.w (Ctrl_1_Logical).w,d0
+
cmpi.b #1,objoff_37(a0)
bne.s +
or.w (Ctrl_2).w,d0
+
andi.w #(button_B_mask|button_C_mask|button_A_mask)<<8,d0
bne.s return_2AD24
move.w #$202,objoff_36(a0)
rts
; ===========================================================================
loc_2AD14:
move.b #1,mainspr_mapframe(a0)
subq.w #4,objoff_38(a0)
bcc.s return_2AD24
clr.w objoff_38(a0)
return_2AD24:
rts
; ===========================================================================
loc_2AD26:
move.b (a2),d0
bne.s loc_2AD7A
loc_2AD2A:
tst.w (Debug_placement_mode).w
bne.s return_2AD78
tst.w y_vel(a1)
bmi.s return_2AD78
jsrto (SolidObject_Always_SingleCharacter).l, JmpTo5_SolidObject_Always_SingleCharacter
btst d6,status(a0)
beq.s return_2AD78
move.b #$81,obj_control(a1)
move.w x_pos(a0),x_pos(a1)
move.w #0,x_vel(a1)
move.w #0,y_vel(a1)
move.w #0,inertia(a1)
bset #2,status(a1)
move.b #$E,y_radius(a1)
move.b #7,x_radius(a1)
move.b #AniIDSonAni_Roll,anim(a1)
addq.b #1,(a2)
return_2AD78:
rts
; ===========================================================================
loc_2AD7A:
if gameRevision>0
cmpi.b #4,routine(a1)
bhs.s return_2AD78
endif
subq.b #1,d0
bne.w loc_2AE0C
tst.b render_flags(a1)
bmi.s loc_2ADB0
bclr d6,status(a0)
bset #1,status(a1)
bclr #3,status(a1)
move.b #2,routine(a1)
move.b #0,obj_control(a1)
move.b #0,(a2)
rts
; ===========================================================================
loc_2ADB0:
andi.w #(button_B_mask|button_C_mask|button_A_mask)<<8,d5
beq.s loc_2ADFE
tst.b objoff_3A(a0)
bne.s loc_2ADFE
move.b #1,objoff_3A(a0)
subq.b #1,objoff_32(a0)
bpl.s loc_2ADDA
move.b #3,objoff_32(a0)
cmpi.w #$20,objoff_38(a0)
beq.s loc_2ADDA
addq.w #1,objoff_38(a0)
loc_2ADDA:
subq.b #1,objoff_33(a0)
bpl.s loc_2ADF8
move.w objoff_38(a0),d0
subi.w #$20,d0
neg.w d0
lsr.w #1,d0
move.b d0,objoff_33(a0)
bchg #2,mainspr_mapframe(a0)
bra.s loc_2ADFE
; ===========================================================================
loc_2ADF8:
move.b #1,mainspr_mapframe(a0)
loc_2ADFE:
move.w y_pos(a0),d0
subi.w #$2E,d0
move.w d0,y_pos(a1)
rts
; ===========================================================================
loc_2AE0C:
move.b #0,(a2)
bclr d6,status(a0)
beq.w loc_2AD2A
move.w objoff_38(a0),d0
addi.w #$10,d0
lsl.w #7,d0
neg.w d0
move.w d0,y_vel(a1)
move.w #0,x_vel(a1)
move.w #$800,inertia(a1)
bset #1,status(a1)
bclr #3,status(a1)
move.b #2,routine(a1)
move.b #0,obj_control(a1)
move.w #SndID_CNZLaunch,d0
jmp (PlaySound).l
; ===========================================================================
; loc_2AE56:
Obj85_Diagonal:
move.b #0,objoff_3A(a0)
move.w objoff_38(a0),d1
lsr.w #1,d1
move.w objoff_2E(a0),d0
sub.w d1,d0
move.w d0,x_pos(a0)
move.w objoff_34(a0),d0
add.w d1,d0
move.w d0,y_pos(a0)
move.b #2,sub2_mapframe(a0)
cmpi.w #$10,objoff_38(a0)
blo.s +
move.b #3,sub2_mapframe(a0)
+
move.w #$23,d1
move.w #8,d2
move.w #5,d3
move.w x_pos(a0),d4
lea objoff_36(a0),a2
lea (MainCharacter).w,a1 ; a1=character
move.w (Ctrl_1_Logical).w,d5
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.s loc_2AF06
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
addq.w #1,a2
move.w (Ctrl_2).w,d5
moveq #p2_standing_bit,d6
bsr.s loc_2AF06
tst.w objoff_36(a0)
beq.s loc_2AEF4
tst.w objoff_38(a0)
beq.s return_2AF04
moveq #0,d0
cmpi.b #1,objoff_36(a0)
bne.s +
or.w (Ctrl_1_Logical).w,d0
+
cmpi.b #1,objoff_37(a0)
bne.s +
or.w (Ctrl_2).w,d0
+
andi.w #(button_B_mask|button_C_mask|button_A_mask)<<8,d0
bne.s return_2AF04
move.w #$202,objoff_36(a0)
rts
; ===========================================================================
loc_2AEF4:
move.b #1,mainspr_mapframe(a0)
subq.w #4,objoff_38(a0)
bcc.s return_2AF04
clr.w objoff_38(a0)
return_2AF04:
rts
; ===========================================================================
loc_2AF06:
move.b (a2),d0
bne.s loc_2AF7A
tst.w (Debug_placement_mode).w
bne.s return_2AF78
tst.w y_vel(a1)
bmi.s return_2AF78
jsrto (SolidObject_Always_SingleCharacter).l, JmpTo5_SolidObject_Always_SingleCharacter
btst d6,status(a0)
bne.s loc_2AF2E
move.b d6,d0
addq.b #pushing_bit_delta,d0
btst d0,status(a0)
beq.s return_2AF78
bset d6,status(a0)
loc_2AF2E:
move.b #$81,obj_control(a1)
move.w x_pos(a0),x_pos(a1)
addi.w #$13,x_pos(a1)
move.w y_pos(a0),y_pos(a1)
subi.w #$13,y_pos(a1)
move.w #0,x_vel(a1)
move.w #0,y_vel(a1)
move.w #0,inertia(a1)
bset #2,status(a1)
move.b #$E,y_radius(a1)
move.b #7,x_radius(a1)
move.b #AniIDSonAni_Roll,anim(a1)
addq.b #1,(a2)
return_2AF78:
rts
; ===========================================================================
loc_2AF7A:
if gameRevision>0
cmpi.b #4,routine(a1)
bhs.s return_2AF78
endif
subq.b #1,d0
bne.w loc_2B018
tst.b render_flags(a1)
bmi.s loc_2AFB0
bclr d6,status(a0)
bset #1,status(a1)
bclr #3,status(a1)
move.b #2,routine(a1)
move.b #0,obj_control(a1)
move.b #0,(a2)
rts
; ===========================================================================
loc_2AFB0:
andi.w #(button_B_mask|button_C_mask|button_A_mask)<<8,d5
beq.s loc_2AFFE
tst.b objoff_3A(a0)
bne.s loc_2AFFE
move.b #1,objoff_3A(a0)
subq.b #1,objoff_32(a0)
bpl.s loc_2AFDA
move.b #3,objoff_32(a0)
cmpi.w #$1C,objoff_38(a0)
beq.s loc_2AFDA
addq.w #1,objoff_38(a0)
loc_2AFDA:
subq.b #1,objoff_33(a0)
bpl.s loc_2AFF8
move.w objoff_38(a0),d0
subi.w #$1C,d0
neg.w d0
lsr.w #1,d0
move.b d0,objoff_33(a0)
bchg #2,mainspr_mapframe(a0)
bra.s loc_2AFFE
; ===========================================================================
loc_2AFF8:
move.b #1,mainspr_mapframe(a0)
loc_2AFFE:
move.w x_pos(a0),d0
addi.w #$13,d0
move.w d0,x_pos(a1)
move.w y_pos(a0),d0
subi.w #$13,d0
move.w d0,y_pos(a1)
rts
; ===========================================================================
loc_2B018:
move.b #0,(a2)
bclr d6,status(a0)
beq.w return_2AF78
move.w objoff_38(a0),d0
addi_.w #4,d0
lsl.w #7,d0
move.w d0,x_vel(a1)
neg.w d0
move.w d0,y_vel(a1)
move.w #$800,inertia(a1)
bset #1,status(a1)
bclr #3,status(a1)
tst.b subtype(a0)
bpl.s loc_2B068
neg.w d0
move.w d0,inertia(a1)
bclr #0,status(a1)
bclr #1,status(a1)
move.b #-$20,angle(a1)
loc_2B068:
move.b #2,routine(a1)
move.b #0,obj_control(a1)
move.w #SndID_CNZLaunch,d0
jmp (PlaySound).l
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj85_MapUnc_2B07E: BINCLUDE "mappings/sprite/obj85_a.bin"
Obj85_MapUnc_2B0EC: BINCLUDE "mappings/sprite/obj85_b.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo4_DisplaySprite3
jmp (DisplaySprite3).l
JmpTo43_DeleteObject
jmp (DeleteObject).l
JmpTo49_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo5_SolidObject_Always_SingleCharacter
jmp (SolidObject_Always_SingleCharacter).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 86 - Flipper from CNZ
; ----------------------------------------------------------------------------
; Sprite_2B140:
Obj86:
moveq #0,d0
move.b routine(a0),d0
move.w Obj86_Index(pc,d0.w),d1
jsr Obj86_Index(pc,d1.w)
jmpto (MarkObjGone).l, JmpTo27_MarkObjGone
; ===========================================================================
; off_2B152:
Obj86_Index: offsetTable
offsetTableEntry.w Obj86_Init ; 0
offsetTableEntry.w Obj86_UpwardsType ; 2 - sends you upwards
offsetTableEntry.w Obj86_HorizontalType ; 4 - sends you leftward/rightward
; ===========================================================================
; loc_2B158:
Obj86_Init:
addq.b #2,routine(a0)
move.l #Obj86_MapUnc_2B45A,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CNZFlipper,2,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo50_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$18,width_pixels(a0)
move.b #4,priority(a0)
tst.b subtype(a0)
beq.s Obj86_UpwardsType
addq.b #2,routine(a0)
move.b #2,anim(a0)
bra.w Obj86_HorizontalType
; ===========================================================================
; loc_2B194:
Obj86_UpwardsType:
tst.w (Debug_placement_mode).w
bne.s return_2B208
lea (byte_2B3C6).l,a2
move.b mapping_frame(a0),d0
beq.s loc_2B1B6
lea (byte_2B3EA).l,a2
subq.b #1,d0
beq.s loc_2B1B6
lea (byte_2B40E).l,a2
loc_2B1B6:
move.w #$23,d1
move.w #6,d2
move.w x_pos(a0),d4
jsrto (SlopedSolid).l, JmpTo2_SlopedSolid
lea objoff_36(a0),a3
lea (MainCharacter).w,a1 ; a1=character
move.w (Ctrl_1_Logical).w,d5
moveq #p1_standing_bit,d6
bsr.s loc_2B20A
addq.w #1,a3
lea (Sidekick).w,a1 ; a1=character
move.w (Ctrl_2).w,d5
moveq #p2_standing_bit,d6
bsr.s loc_2B20A
tst.b objoff_38(a0)
beq.s loc_2B1FE
clr.b objoff_38(a0)
bsr.w loc_2B290
subq.w #1,a3
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
bsr.w loc_2B290
loc_2B1FE:
lea (Ani_obj86).l,a1
jmpto (AnimateSprite).l, JmpTo9_AnimateSprite
; ===========================================================================
return_2B208:
rts
; ===========================================================================
loc_2B20A:
move.b (a3),d0
bne.s loc_2B23C
btst d6,status(a0)
beq.s return_2B208
move.b #1,obj_control(a1)
move.b #$E,y_radius(a1)
move.b #7,x_radius(a1)
move.b #AniIDSonAni_Roll,anim(a1)
bset #2,status(a1)
bne.s loc_2B238
addq.w #5,y_pos(a1)
loc_2B238:
addq.b #1,(a3)
rts
; ===========================================================================
loc_2B23C:
andi.w #button_B_mask|button_C_mask|button_A_mask,d5
bne.s loc_2B288
btst d6,status(a0)
bne.s loc_2B254
move.b #0,obj_control(a1)
move.b #0,(a3)
rts
; ===========================================================================
loc_2B254:
moveq #0,d1
move.b mapping_frame(a0),d1
subq.w #1,d1
bset #0,status(a1)
btst #0,status(a0)
bne.s loc_2B272
neg.w d1
bclr #0,status(a1)
loc_2B272:
add.w d1,x_pos(a1)
lsl.w #8,d1
move.w d1,x_vel(a1)
move.w d1,inertia(a1)
move.w #0,y_vel(a1)
rts
; ===========================================================================
loc_2B288:
move.b #1,objoff_38(a0)
rts
; ===========================================================================
loc_2B290:
bclr d6,status(a0)
beq.w return_2B208
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
btst #0,status(a0)
beq.s loc_2B2AA
neg.w d0
loc_2B2AA:
addi.w #$23,d0
move.w d0,d2
cmpi.w #$40,d2
blo.s loc_2B2BA
move.w #$40,d2
loc_2B2BA:
lsl.w #5,d2
addi.w #$800,d2
neg.w d2
asr.w #2,d0
addi.w #$40,d0
jsrto (CalcSine).l, JmpTo11_CalcSine
muls.w d2,d0
muls.w d2,d1
asr.l #8,d0
asr.l #8,d1
move.w d0,y_vel(a1)
btst #0,status(a0)
beq.s loc_2B2E2
neg.w d1
loc_2B2E2:
move.w d1,x_vel(a1)
bset #1,status(a1)
bclr #3,status(a1)
move.b #2,routine(a1)
move.b #0,obj_control(a1)
move.b #1,anim(a0)
move.b #0,(a3)
move.w #SndID_Flipper,d0
jmp (PlaySound).l
; ===========================================================================
; loc_2B312:
Obj86_HorizontalType:
move.w #$13,d1
move.w #$18,d2
move.w #$19,d3
move.w x_pos(a0),d4
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
jsrto (SolidObject_Always_SingleCharacter).l, JmpTo6_SolidObject_Always_SingleCharacter
btst #p1_pushing_bit,status(a0)
beq.s loc_2B33A
bsr.s loc_2B35C
loc_2B33A:
movem.l (sp)+,d1-d4
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
jsrto (SolidObject_Always_SingleCharacter).l, JmpTo6_SolidObject_Always_SingleCharacter
btst #p2_pushing_bit,status(a0)
beq.s loc_2B352
bsr.s loc_2B35C
loc_2B352:
lea (Ani_obj86).l,a1
jmpto (AnimateSprite).l, JmpTo9_AnimateSprite
; ===========================================================================
loc_2B35C:
move.w #$300,anim(a0)
move.w #-$1000,x_vel(a1)
addq.w #8,x_pos(a1)
bset #0,status(a1)
move.w x_pos(a0),d0
sub.w x_pos(a1),d0
bcc.s loc_2B392
bclr #0,status(a1)
subi.w #$10,x_pos(a1)
neg.w x_vel(a1)
move.w #$400,anim(a0)
loc_2B392:
move.w #$F,move_lock(a1)
move.w x_vel(a1),inertia(a1)
move.b #$E,y_radius(a1)
move.b #7,x_radius(a1)
move.b #AniIDSonAni_Roll,anim(a1)
bset #2,status(a1)
bne.s loc_2B3BC
addq.w #5,y_pos(a1)
loc_2B3BC:
move.w #SndID_Flipper,d0
jmp (PlaySound).l
; ===========================================================================
byte_2B3C6:
dc.b 7, 7, 7, 7, 7, 7, 7, 8, 9, $A, $B, $A, 9, 8, 7, 6
dc.b 5, 4, 3, 2, 1, 0,$FF,$FE,$FD,$FC,$FB,$FA,$F9,$F8,$F7,$F6; 16
dc.b $F5,$F4,$F3,$F2 ; 32
byte_2B3EA:
dc.b 6, 6, 6, 6, 6, 6, 7, 8, 9, 9, 9, 9, 9, 9, 8, 8
dc.b 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 4, 4; 16
dc.b 4, 4, 4, 4 ; 32
byte_2B40E:
dc.b 5, 5, 5, 5, 5, 6, 7, 8, 9, $A, $B, $B, $C, $C, $D, $D
dc.b $E, $E, $F, $F,$10,$10,$11,$11,$12,$12,$11,$11,$10,$10,$10,$10; 16
dc.b $10,$10,$10,$10 ; 32
; animation script
; off_2B432:
Ani_obj86: offsetTable
offsetTableEntry.w byte_2B43C ; 0
offsetTableEntry.w byte_2B43F ; 1
offsetTableEntry.w byte_2B445 ; 2
offsetTableEntry.w byte_2B448 ; 3
offsetTableEntry.w byte_2B451 ; 4
byte_2B43C: dc.b $F, 0,$FF
rev02even
byte_2B43F: dc.b 3, 1, 2, 1,$FD, 0
rev02even
byte_2B445: dc.b $F, 4,$FF
rev02even
byte_2B448: dc.b 0, 5, 4, 3, 3, 3, 3,$FD, 2
rev02even
byte_2B451: dc.b 0, 3, 4, 5, 5, 5, 5,$FD, 2
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj86_MapUnc_2B45A: BINCLUDE "mappings/sprite/obj86.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo27_MarkObjGone
jmp (MarkObjGone).l
JmpTo9_AnimateSprite
jmp (AnimateSprite).l
JmpTo50_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo11_CalcSine
jmp (CalcSine).l
JmpTo6_SolidObject_Always_SingleCharacter
jmp (SolidObject_Always_SingleCharacter).l
JmpTo2_SlopedSolid
jmp (SlopedSolid).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object D2 - Flashing blocks that appear and disappear in a rectangular shape that you can walk across, from CNZ
; ----------------------------------------------------------------------------
; Sprite_2B528:
ObjD2:
moveq #0,d0
move.b routine(a0),d0
move.w ObjD2_Index(pc,d0.w),d1
jmp ObjD2_Index(pc,d1.w)
; ===========================================================================
; off_2B536:
ObjD2_Index: offsetTable
offsetTableEntry.w ObjD2_Init ; 0
offsetTableEntry.w ObjD2_Main ; 2
; ===========================================================================
; loc_2B53A:
ObjD2_Init:
addq.b #2,routine(a0)
move.l #ObjD2_MapUnc_2B694,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CNZSnake,2,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo51_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #8,width_pixels(a0)
move.b #4,priority(a0)
move.w x_pos(a0),objoff_30(a0)
move.w y_pos(a0),objoff_32(a0)
moveq #0,d0
move.b subtype(a0),d0
lsl.w #4,d0
move.w d0,objoff_38(a0)
bsr.w loc_2B60C
; loc_2B57E:
ObjD2_Main:
tst.w objoff_38(a0)
beq.s +
subq.w #1,objoff_38(a0)
jmpto (MarkObjGone3).l, JmpTo6_MarkObjGone3
; ===========================================================================
+
subq.w #1,objoff_3A(a0)
bpl.s loc_2B5EC
move.w #$F,objoff_3A(a0)
addq.b #1,mapping_frame(a0)
andi.b #$F,mapping_frame(a0)
bne.s loc_2B5EA
moveq #0,d0
move.b subtype(a0),d0
lsl.w #4,d0
move.w d0,objoff_38(a0)
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s loc_2B5E2
bclr #p1_standing_bit,status(a0)
beq.s +
bclr #3,(MainCharacter+status).w
bset #1,(MainCharacter+status).w
+
bclr #p2_standing_bit,status(a0)
beq.s loc_2B5E2
bclr #3,(Sidekick+status).w
bset #1,(Sidekick+status).w
loc_2B5E2:
move.w objoff_30(a0),x_pos(a0)
bra.s loc_2B60C
; ===========================================================================
loc_2B5EA:
bsr.s loc_2B60C
loc_2B5EC:
move.w objoff_34(a0),d1
addi.w #$B,d1
move.w objoff_36(a0),d2
move.w d2,d3
addq.w #1,d3
move.w x_pos(a0),d4
jsrto (SolidObject).l, JmpTo24_SolidObject
move.w objoff_30(a0),d0
jmpto (MarkObjGone2).l, JmpTo9_MarkObjGone2
; ===========================================================================
loc_2B60C:
moveq #0,d0
move.b mapping_frame(a0),d0
add.w d0,d0
add.w d0,d0
lea byte_2B654(pc,d0.w),a1
move.b (a1)+,d0
ext.w d0
btst #0,status(a0)
beq.s +
neg.w d0
+
add.w objoff_30(a0),d0
move.w d0,x_pos(a0)
move.b (a1)+,d0
ext.w d0
add.w objoff_32(a0),d0
move.w d0,y_pos(a0)
moveq #0,d1
moveq #0,d2
moveq #0,d3
move.b (a1)+,d1
move.b (a1)+,d2
move.w d1,objoff_34(a0)
move.b d1,width_pixels(a0)
move.w d2,objoff_36(a0)
rts
; ===========================================================================
byte_2B654:
dc.b $D8,$18, 8, 8,$D8,$10, 8,$10,$D8, 8, 8,$18,$D8, 0, 8,$20
dc.b $E0, 0,$10,$20,$E8,$F8,$18,$18,$F0,$F0,$20,$10,$F8,$E8,$28, 8; 16
dc.b 8,$E8,$28, 8,$10,$F0,$20,$10,$18,$F8,$18,$18,$20, 0,$10,$20; 32
dc.b $28, 0, 8,$20,$28, 8, 8,$18,$28,$10, 8,$10,$28,$18, 8, 8; 48
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjD2_MapUnc_2B694: BINCLUDE "mappings/sprite/objD2.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo6_MarkObjGone3
jmp (MarkObjGone3).l
JmpTo51_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo24_SolidObject
jmp (SolidObject).l
JmpTo9_MarkObjGone2
jmp (MarkObjGone2).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object D3 - Bomb prize from CNZ
; ----------------------------------------------------------------------------
; Note: see object DC (ring prize) for SST entries (casino_prize_*)
; Sprite_2B84C:
ObjD3:
moveq #0,d1
move.w casino_prize_machine_x_pos(a0),d1
swap d1
move.l casino_prize_x_pos(a0),d0
sub.l d1,d0
asr.l #4,d0
sub.l d0,casino_prize_x_pos(a0)
move.w casino_prize_x_pos(a0),x_pos(a0)
moveq #0,d1
move.w casino_prize_machine_y_pos(a0),d1
swap d1
move.l casino_prize_y_pos(a0),d0
sub.l d1,d0
asr.l #4,d0
sub.l d0,casino_prize_y_pos(a0)
move.w casino_prize_y_pos(a0),y_pos(a0)
subq.w #1,casino_prize_display_delay(a0)
bne.w JmpTo28_DisplaySprite
movea.l objoff_2A(a0),a1
subq.w #1,(a1)
cmpi.w #5,(Bonus_Countdown_3).w
blo.s +
clr.w (Bonus_Countdown_3).w
move.w #SndID_HurtBySpikes,d0
jsr (PlaySoundStereo).l
+
tst.b parent+1(a0)
beq.s ++
tst.w (Ring_count_2P).w
beq.s +
subq.w #1,(Ring_count_2P).w
ori.b #$81,(Update_HUD_rings_2P).w
+
tst.w (Two_player_mode).w
bne.s BranchTo_JmpTo44_DeleteObject
+
tst.w (Ring_count).w
beq.s BranchTo_JmpTo44_DeleteObject
subq.w #1,(Ring_count).w
ori.b #$81,(Update_HUD_rings).w
BranchTo_JmpTo44_DeleteObject
jmpto (DeleteObject).l, JmpTo44_DeleteObject
if removeJmpTos
JmpTo28_DisplaySprite
jmp (DisplaySprite).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjD3_MapUnc_2B8D4: BINCLUDE "mappings/sprite/objD6_a.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo28_DisplaySprite
jmp (DisplaySprite).l
JmpTo44_DeleteObject
jmp (DeleteObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object D4 - Big block from CNZ that moves back and forth
; ----------------------------------------------------------------------------
; Sprite_2B8EC:
ObjD4:
moveq #0,d0
move.b routine(a0),d0
move.w ObjD4_Index(pc,d0.w),d1
jmp ObjD4_Index(pc,d1.w)
; ===========================================================================
; off_2B8FA:
ObjD4_Index: offsetTable
offsetTableEntry.w ObjD4_Init ; 0
offsetTableEntry.w ObjD4_Main ; 2
; ===========================================================================
; loc_2B8FE:
ObjD4_Init:
addq.b #2,routine(a0)
move.l #ObjD4_MapUnc_2B9CA,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_BigMovingBlock,2,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo52_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$20,width_pixels(a0)
move.b #4,priority(a0)
move.w x_pos(a0),objoff_30(a0)
move.w y_pos(a0),objoff_32(a0)
move.w #$8000,x_sub(a0)
move.w #$8000,y_sub(a0)
tst.b subtype(a0)
bne.s loc_2B95A
subi.w #$60,x_pos(a0)
btst #0,status(a0)
beq.s ObjD4_Main
addi.w #$C0,x_pos(a0)
bra.s ObjD4_Main
; ===========================================================================
loc_2B95A:
subi.w #$60,y_pos(a0)
btst #1,status(a0)
beq.s ObjD4_Main
addi.w #$C0,y_pos(a0)
; loc_2B96E:
ObjD4_Main:
move.w x_pos(a0),-(sp)
moveq #0,d0
move.b subtype(a0),d0
move.w ObjD4_Types(pc,d0.w),d1
jsr ObjD4_Types(pc,d1.w)
jsrto (ObjectMove).l, JmpTo17_ObjectMove
move.w #$2B,d1
move.w #$20,d2
move.w #$21,d3
move.w (sp)+,d4
jsrto (SolidObject).l, JmpTo25_SolidObject
move.w objoff_30(a0),d0
jmpto (MarkObjGone2).l, JmpTo10_MarkObjGone2
; ===========================================================================
; off_2B99E:
ObjD4_Types: offsetTable
offsetTableEntry.w ObjD4_Horizontal ; 0
offsetTableEntry.w ObjD4_Vertical ; 2
; ===========================================================================
; loc_2B9A2:
ObjD4_Horizontal:
moveq #4,d1
move.w objoff_30(a0),d0
cmp.w x_pos(a0),d0
bhi.s +
neg.w d1
+
add.w d1,x_vel(a0)
rts
; ===========================================================================
; loc_2B9B6:
ObjD4_Vertical:
moveq #4,d1
move.w objoff_32(a0),d0
cmp.w y_pos(a0),d0
bhi.s +
neg.w d1
+
add.w d1,y_vel(a0)
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjD4_MapUnc_2B9CA: BINCLUDE "mappings/sprite/objD4.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo52_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo25_SolidObject
jmp (SolidObject).l
JmpTo10_MarkObjGone2
jmp (MarkObjGone2).l
; loc_2BA02:
JmpTo17_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object D5 - Elevator from CNZ
; ----------------------------------------------------------------------------
; Sprite_2BA08:
ObjD5:
moveq #0,d0
move.b routine(a0),d0
move.w ObjD5_Index(pc,d0.w),d1
jmp ObjD5_Index(pc,d1.w)
; ===========================================================================
; off_2BA16:
ObjD5_Index: offsetTable
offsetTableEntry.w ObjD5_Init ; 0
offsetTableEntry.w ObjD5_Main ; 2
; ===========================================================================
; loc_2BA1A:
ObjD5_Init:
addq.b #2,routine(a0)
move.l #ObjD5_MapUnc_2BB40,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CNZElevator,2,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo53_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #4,priority(a0)
move.w y_pos(a0),objoff_32(a0)
move.w #$8000,y_sub(a0)
moveq #0,d0
move.b subtype(a0),d0
lsl.w #2,d0
sub.w d0,y_pos(a0)
btst #0,status(a0)
beq.s ObjD5_Main
add.w d0,d0
add.w d0,y_pos(a0)
; loc_2BA68:
ObjD5_Main:
jsrto (ObjectMove).l, JmpTo18_ObjectMove
move.w objoff_34(a0),d0
move.w off_2BA94(pc,d0.w),d1
jsr off_2BA94(pc,d1.w)
cmpi.w #6,objoff_34(a0)
bhs.s +
move.w #$10,d1
move.w #9,d3
move.w x_pos(a0),d4
jsrto (PlatformObjectD5).l, JmpTo_PlatformObjectD5
+
jmpto (MarkObjGone).l, JmpTo28_MarkObjGone
; ===========================================================================
off_2BA94: offsetTable
offsetTableEntry.w loc_2BA9C ; 0
offsetTableEntry.w loc_2BAB6 ; 2
offsetTableEntry.w loc_2BAEE ; 4
offsetTableEntry.w loc_2BB08 ; 6
; ===========================================================================
loc_2BA9C:
move.b status(a0),d0
andi.w #standing_mask,d0
beq.s + ; rts
move.w #SndID_CNZElevator,d0
jsr (PlaySound).l
addq.w #2,objoff_34(a0)
+
rts
; ===========================================================================
loc_2BAB6:
moveq #8,d1
move.w objoff_32(a0),d0
cmp.w y_pos(a0),d0
bhs.s +
neg.w d1
+
add.w d1,y_vel(a0)
bne.s + ; rts
addq.w #2,objoff_34(a0)
move.w d0,y_pos(a0)
moveq #0,d0
move.b subtype(a0),d0
lsl.w #2,d0
sub.w d0,y_pos(a0)
btst #0,status(a0)
bne.s + ; rts
add.w d0,d0
add.w d0,y_pos(a0)
+
rts
; ===========================================================================
loc_2BAEE:
move.b status(a0),d0
andi.w #standing_mask,d0
bne.s + ; rts
move.w #SndID_CNZElevator,d0
jsr (PlaySound).l
addq.w #2,objoff_34(a0)
+
rts
; ===========================================================================
loc_2BB08:
moveq #8,d1
move.w objoff_32(a0),d0
cmp.w y_pos(a0),d0
bhs.s +
neg.w d1
+
add.w d1,y_vel(a0)
bne.s + ; rts
clr.w objoff_34(a0)
move.w d0,y_pos(a0)
moveq #0,d0
move.b subtype(a0),d0
lsl.w #2,d0
sub.w d0,y_pos(a0)
btst #0,status(a0)
beq.s + ; rts
add.w d0,d0
add.w d0,y_pos(a0)
+
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjD5_MapUnc_2BB40: BINCLUDE "mappings/sprite/objD5.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo28_MarkObjGone
jmp (MarkObjGone).l
JmpTo53_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo_PlatformObjectD5
jmp (PlatformObjectD5).l
; loc_2BB66:
JmpTo18_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object D6 - Pokey that gives out points from CNZ
; ----------------------------------------------------------------------------
; Sprite_2BB6C:
ObjD6:
moveq #0,d0
move.b routine(a0),d0
move.w ObjD6_Index(pc,d0.w),d1
jmp ObjD6_Index(pc,d1.w)
; ===========================================================================
; off_2BB7A:
ObjD6_Index: offsetTable
offsetTableEntry.w ObjD6_Init ; 0
offsetTableEntry.w ObjD6_Main ; 2
; ===========================================================================
; loc_2BB7E:
ObjD6_Init:
addq.b #2,routine(a0)
move.l #ObjD6_MapUnc_2BEBC,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CNZCage,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo54_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$18,width_pixels(a0)
move.b #1,priority(a0)
; loc_2BBA6:
ObjD6_Main:
move.w #$23,d1
move.w #$10,d2
move.w #$11,d3
move.w x_pos(a0),d4
lea objoff_30(a0),a2
lea (MainCharacter).w,a1 ; a1=character
moveq #p1_standing_bit,d6
movem.l d1-d4,-(sp)
bsr.w loc_2BBE8
movem.l (sp)+,d1-d4
lea objoff_34(a0),a2 ; a2=object
lea (Sidekick).w,a1 ; a1=character
moveq #p2_standing_bit,d6
bsr.w loc_2BBE8
lea (Ani_objD6).l,a1
jsrto (AnimateSprite).l, JmpTo10_AnimateSprite
jmpto (MarkObjGone).l, JmpTo29_MarkObjGone
; ===========================================================================
loc_2BBE8:
move.w (a2),d0
move.w off_2BBF2(pc,d0.w),d0
jmp off_2BBF2(pc,d0.w)
; ===========================================================================
off_2BBF2: offsetTable
offsetTableEntry.w loc_2BBF8 ; 0
offsetTableEntry.w loc_2BDF8 ; 2
offsetTableEntry.w loc_2BE9C ; 4
; ===========================================================================
loc_2BBF8:
tst.b obj_control(a1)
bne.w return_2BC84
tst.b subtype(a0)
beq.s loc_2BC0C
tst.w (SlotMachineInUse).w
bne.s return_2BC84
loc_2BC0C:
jsrto (SolidObject_Always_SingleCharacter).l, JmpTo7_SolidObject_Always_SingleCharacter
tst.w d4
bpl.s return_2BC84
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w #0,x_vel(a1)
move.w #0,y_vel(a1)
move.w #0,inertia(a1)
move.b #$81,obj_control(a1)
bset #2,status(a1)
move.b #$E,y_radius(a1)
move.b #7,x_radius(a1)
move.b #AniIDSonAni_Roll,anim(a1)
move.b #1,anim(a0)
addq.w #2,(a2)+
move.w #$78,(a2)
move.w a1,parent(a0)
tst.b subtype(a0)
beq.s return_2BC84
cmpi.b #$18,(SlotMachine_Routine).w ; Is it the null routine?
bne.s return_2BC84 ; Branch if not
move.b #8,(SlotMachine_Routine).w ; => SlotMachine_Routine3
clr.w objoff_2E(a0)
move.w #-1,(SlotMachineInUse).w
move.w #-1,objoff_2A(a0)
return_2BC84:
rts
; ===========================================================================
loc_2BC86:
move.w (SlotMachine_Reward).w,d0
bpl.w loc_2BD4E
tst.w objoff_2A(a0)
bpl.s +
move.w #$64,objoff_2A(a0)
+
tst.w objoff_2A(a0)
beq.w +
btst #0,(Timer_frames+1).w
beq.w loc_2BD48
cmpi.w #$10,objoff_2C(a0)
bhs.w loc_2BD48
jsrto (SingleObjLoad).l, JmpTo10_SingleObjLoad
bne.w loc_2BD48
_move.b #ObjID_BombPrize,id(a1) ; load objD3
move.l #ObjD3_MapUnc_2B8D4,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_CNZBonusSpike,0,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo6_Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #$10,width_pixels(a1)
move.b #4,priority(a1)
move.w #$1E,casino_prize_display_delay(a1)
move.w objoff_2E(a0),objoff_2E(a1)
addi.w #$90,objoff_2E(a0)
move.w x_pos(a0),casino_prize_machine_x_pos(a1)
move.w y_pos(a0),casino_prize_machine_y_pos(a1)
move.w objoff_2E(a1),d0
jsrto (CalcSine).l, JmpTo12_CalcSine
asr.w #1,d1
add.w casino_prize_machine_x_pos(a1),d1
move.w d1,casino_prize_x_pos(a1)
move.w d1,x_pos(a1)
asr.w #1,d0
add.w casino_prize_machine_y_pos(a1),d0
move.w d0,casino_prize_y_pos(a1)
move.w d0,y_pos(a1)
lea objoff_2C(a0),a2
move.l a2,objoff_2A(a1)
move.w parent(a0),parent(a1)
addq.w #1,objoff_2C(a0)
subq.w #1,objoff_2A(a0)
+
tst.w objoff_2C(a0)
beq.w loc_2BE2E
loc_2BD48:
addq.w #1,(Bonus_Countdown_3).w
rts
; ===========================================================================
loc_2BD4E:
beq.w +
btst #0,(Timer_frames+1).w
beq.w return_2BDF6
cmpi.w #$10,objoff_2C(a0)
bhs.w return_2BDF6
jsrto (SingleObjLoad).l, JmpTo10_SingleObjLoad
bne.w return_2BDF6
_move.b #ObjID_RingPrize,id(a1) ; load objDC
move.l #Obj25_MapUnc_12382,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_Ring,1,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo6_Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #3,priority(a1)
move.b #8,width_pixels(a1)
move.w #$1A,casino_prize_display_delay(a1)
move.w objoff_2E(a0),objoff_2E(a1)
addi.w #$89,objoff_2E(a0)
move.w x_pos(a0),casino_prize_machine_x_pos(a1)
move.w y_pos(a0),casino_prize_machine_y_pos(a1)
move.w objoff_2E(a1),d0
jsrto (CalcSine).l, JmpTo12_CalcSine
asr.w #1,d1
add.w casino_prize_machine_x_pos(a1),d1
move.w d1,casino_prize_x_pos(a1)
move.w d1,x_pos(a1)
asr.w #1,d0
add.w casino_prize_machine_y_pos(a1),d0
move.w d0,casino_prize_y_pos(a1)
move.w d0,y_pos(a1)
lea objoff_2C(a0),a2
move.l a2,objoff_2A(a1)
move.w parent(a0),parent(a1)
addq.w #1,objoff_2C(a0)
subq.w #1,(SlotMachine_Reward).w
+
tst.w objoff_2C(a0)
beq.s loc_2BE2E
return_2BDF6:
rts
; ===========================================================================
loc_2BDF8:
tst.b render_flags(a0)
bpl.s loc_2BE2E
tst.b subtype(a0)
beq.s loc_2BE28
move.w a1,objoff_3E(a0)
cmpi.b #$18,(SlotMachine_Routine).w ; Is it the null routine?
beq.w loc_2BC86 ; Branch if yes
move.b (Vint_runcount+3).w,d0
andi.w #$F,d0
bne.s + ; rts
move.w #SndID_CasinoBonus,d0
jsr (PlaySound).l
+
rts
; ===========================================================================
loc_2BE28:
subq.w #1,2(a2)
bpl.s loc_2BE5E
loc_2BE2E:
move.w #0,objoff_2C(a0)
move.b #0,anim(a0)
move.b #0,objoff_2A(a1)
bclr d6,status(a0)
bclr #3,status(a1)
bset #1,status(a1)
move.w #$400,y_vel(a1)
addq.w #2,(a2)+
move.w #$1E,(a2)
rts
; ===========================================================================
loc_2BE5E:
move.w 2(a2),d0
andi.w #$F,d0
bne.s + ; rts
move.w #SndID_CasinoBonus,d0
jsr (PlaySound).l
moveq #10,d0
movea.w a1,a3
jsr (AddPoints2).l
jsrto (SingleObjLoad).l, JmpTo10_SingleObjLoad
bne.s + ; rts
_move.b #ObjID_Points,id(a1) ; load obj29
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.b #0,mapping_frame(a1)
+
rts
; ===========================================================================
loc_2BE9C:
subq.w #1,2(a2)
bpl.s + ; rts
clr.w (a2)
tst.b subtype(a0)
beq.s + ; rts
clr.w (SlotMachineInUse).w
+
rts
; ===========================================================================
; animation script
; off_2BEB0:
Ani_objD6: offsetTable
offsetTableEntry.w byte_2BEB4 ; 0
offsetTableEntry.w byte_2BEB7 ; 1
byte_2BEB4: dc.b $F, 0,$FF
rev02even
byte_2BEB7: dc.b 1, 1, 0,$FF
even
; ------------------------------------------------------------------------------
; sprite mappings
; ------------------------------------------------------------------------------
ObjD6_MapUnc_2BEBC: BINCLUDE "mappings/sprite/objD6_b.bin"
; ===========================================================================
; ------------------------------------------------------------------------------
; runs the slot machines in CNZ
; ------------------------------------------------------------------------------
slot_rout = 0
slot_timer = 1
slot_index = 3
slots_targ = 4
slot1_targ = 4
slot23_targ = 5
slots_data = 6
slot1_index = slots_data
slot1_offset = slots_data+1
slot1_speed = slots_data+2
slot1_rout = slots_data+3
slot2_index = slots_data+4
slot2_offset = slots_data+5
slot2_speed = slots_data+6
slot2_rout = slots_data+7
slot3_index = slots_data+8
slot3_offset = slots_data+9
slot3_speed = slots_data+10
slot3_rout = slots_data+11
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_2BF24:
SlotMachine:
lea (SlotMachineVariables).w,a4
moveq #0,d0
_move.b slot_rout(a4),d0
jmp SlotMachine_JmpTable(pc,d0.w)
; ===========================================================================
; loc_2BF32:
SlotMachine_JmpTable: ;;
bra.w SlotMachine_Routine1 ; $00
bra.w SlotMachine_Routine2 ; $04
bra.w SlotMachine_Routine3 ; $08
bra.w SlotMachine_Routine4 ; $0C
bra.w SlotMachine_Routine5 ; $10
bra.w SlotMachine_Routine6 ; $14
rts ; $18
; ===========================================================================
; loc_2BF4C:
SlotMachine_Routine1:
movea.l a4,a1 ; Copy destination
moveq #8,d0 ; 18 bytes, in words
- clr.w (a1)+
dbf d0,-
move.b (Vint_runcount+3).w,d0 ; 'Random' seed
move.b d0,slot1_index(a4) ; Only last 3 bits matter
ror.b #3,d0 ; Remove last 3 bits
move.b d0,slot2_index(a4) ; Again, only last 3 bits matter
ror.b #3,d0 ; Remove 3 more bits (only have 2 bits now!)
move.b d0,slot3_index(a4) ; Only 3 bits matter, but we only have 2 anyway
move.b #8,slot1_offset(a4) ; This will set a draw from start of tile
move.b #8,slot2_offset(a4) ; This will set a draw from start of tile
move.b #8,slot3_offset(a4) ; This will set a draw from start of tile
move.b #8,slot1_speed(a4) ; Initial rolling speed
move.b #8,slot2_speed(a4) ; Initial rolling speed
move.b #8,slot3_speed(a4) ; Initial rolling speed
move.b #1,slot_timer(a4) ; Roll each slot once
_addq.b #4,slot_rout(a4) ; => SlotMachine_Routine2
rts
; ===========================================================================
; loc_2BF9A:
SlotMachine_Routine2:
bsr.w SlotMachine_DrawSlot ; Draw the slots
tst.b slot_timer(a4) ; Are we still rolling?
beq.s + ; Branch if not
rts
; ===========================================================================
+
_move.b #$18,slot_rout(a4) ; => null routine (rts)
clr.w slot1_speed(a4) ; Stop slot 1
clr.w slot2_speed(a4) ; Stop slot 2
clr.w slot3_speed(a4) ; Stop slot 3
rts
; ===========================================================================
; loc_2BFBA:
SlotMachine_Routine3:
move.b (Vint_runcount+3).w,d0 ; 'Random' seed
andi.b #7,d0 ; Only want last 3 bits
subq.b #4,d0 ; Subtract 4...
addi.b #$30,d0 ; ... then add $30 (why not just add $2C?)
move.b d0,slot1_speed(a4) ; This is our starting speed for slot 1
move.b (Vint_runcount+3).w,d0 ; 'Random' seed
rol.b #4,d0 ; Get top nibble...
andi.b #7,d0 ; ... but discard what was the sign bit
subq.b #4,d0 ; Subtract 4...
addi.b #$30,d0 ; ... then add $30 (why not just add $2C?)
move.b d0,slot2_speed(a4) ; This is our starting speed for slot 2
move.b (Vint_runcount+2).w,d0 ; 'Random' seed
andi.b #7,d0 ; Only want last 3 bits
subq.b #4,d0 ; Subtract 4...
addi.b #$30,d0 ; ... then add $30 (why not just add $2C?)
move.b d0,slot3_speed(a4) ; This is our starting speed for slot 3
move.b #2,slot_timer(a4) ; Roll each slot twice under these conditions
clr.b slot_index(a4) ; => SlotMachine_Subroutine1
clr.b slot1_rout(a4) ; => SlotMachine_Routine5_1
clr.b slot2_rout(a4) ; => SlotMachine_Routine5_1
clr.b slot3_rout(a4) ; => SlotMachine_Routine5_1
_addq.b #4,slot_rout(a4) ; => SlotMachine_Routine4
move.b (Vint_runcount+3).w,d0 ; 'Random' seed
ror.b #3,d0 ; Mess it around
lea (SlotTargetValues).l,a2
- sub.b (a2),d0 ; Subtract from random seed
bcs.s + ; Branch if result is less than zero
addq.w #3,a2 ; Advance 3 bytes
bra.s - ; Keep looping
; ===========================================================================
+
cmpi.b #-1,(a2) ; Is the previous value -1?
beq.s + ; Branch if yes (end of array)
move.b 1(a2),slot1_targ(a4) ; Target value for slot 1
move.b 2(a2),slot23_targ(a4) ; Target values for slots 2 and 3
rts
; ===========================================================================
+
move.b d0,d1 ; Copy our 'random' value
andi.w #7,d1 ; Want only last 3 bits
lea (SlotSequence1).l,a1 ; Slot sequence array for slot 1
move.b (a1,d0.w),slot1_targ(a4) ; Uhhh... use d0 as array index? This should have been d1! Anyway, set slot 1 target
ror.b #3,d0 ; Rotate it
move.b d0,d1 ; Copy it
andi.w #7,d1 ; Want only last 3 bits
lea (SlotSequence2).l,a1 ; Slot sequence array for slot 2
move.b (a1,d1.w),d2 ; Use as array index
lsl.b #4,d2 ; Move to high nibble
ror.b #3,d0 ; Rotate it again
andi.w #7,d0 ; Want only last 3 bits
lea (SlotSequence3).l,a1 ; Slot sequence array for slot 3
or.b (a1,d0.w),d2 ; Combine with earlier value
move.b d2,slot23_targ(a4) ; Target values for slots 2 and 3
rts
; ===========================================================================
; loc_2C070:
SlotMachine_Routine4:
bsr.w SlotMachine_DrawSlot
tst.b slot_timer(a4) ; Are slots still going?
beq.s + ; Branch if not
rts
; ===========================================================================
+
addi.b #$30,slot1_speed(a4) ; Increase slot 1 speed
addi.b #$30,slot2_speed(a4) ; Increase slot 2 speed
addi.b #$30,slot3_speed(a4) ; Increase slot 3 speed
move.b (Vint_runcount+3).w,d0 ; 'Random' seed
andi.b #$F,d0 ; Want only low nibble
addi.b #$C,d0 ; Increase by $C
move.b d0,slot_timer(a4) ; New value for slot timer
clr.b 2(a4) ; Clear otherwise unused variable
_addq.b #4,slot_rout(a4) ; => SlotMachine_Routine5
rts
; ===========================================================================
; loc_2C0A8:
SlotMachine_Routine5:
bsr.w SlotMachine_DrawSlot
cmpi.b #$C,slot1_rout(a4) ; Is slot done?
bne.s + ; Branch if not
cmpi.b #$C,slot2_rout(a4) ; Is slot done?
bne.s + ; Branch if not
cmpi.b #$C,slot3_rout(a4) ; Is slot done?
beq.w SlotMachine_Routine6 ; Branch if yes
+
moveq #0,d0 ; Clear d0
move.b slot_index(a4),d0 ; Get current slot index
lea slots_data(a4),a1 ; a1 = pointer to slots data
adda.w d0,a1 ; a1 = pointer to current slot data
lea (SlotSequence1).l,a3 ; Get pointer to slot sequences
add.w d0,d0 ; Turn into index
adda.w d0,a3 ; Get sequence for this slot
moveq #0,d0 ; Clear d0 again
move.b slot1_rout-slot1_index(a1),d0 ; Slot routine
jmp SlotMachine_Routine5_JmpTable(pc,d0.w)
; ===========================================================================
; loc_2C0E6
SlotMachine_Routine5_JmpTable: ;;
bra.w SlotMachine_Routine5_1 ; $00
bra.w SlotMachine_Routine5_2 ; $04
bra.w SlotMachine_Routine5_3 ; $08
bra.w SlotMachine_Routine5_4 ; $0C
; ===========================================================================
;loc_2C0F6
SlotMachine_GetTargetForSlot:
move.w slots_targ(a4),d1 ; Get target slot faces
move.b slot_index(a4),d0 ; Get current slot index
beq.s + ; Branch if zero
lsr.w d0,d1 ; Shift slot face into position
+
andi.w #7,d1 ; Only 8 slot faces
cmpi.b #5,d1 ; Is this above bar?
bgt.s + ; Branch if yes
rts
; ===========================================================================
+
subq.b #2,d1 ; Wrap back to ring/bar
rts
; ===========================================================================
;loc_2C112
SlotMachine_ChangeTarget:
move.w #$FFF0,d2 ; Kept faces mask
andi.w #$F,d1 ; New slot target
move.b slot_index(a4),d0 ; Get current slot
beq.s + ; Branch if it is slot 0
lsl.w d0,d1 ; Shift new slot target into position
rol.w d0,d2 ; Shift kept faces mask into position
+
and.w d2,slots_targ(a4) ; Mask off current slot
or.w d1,slots_targ(a4) ; Put in new value for it
andi.w #$777,slots_targ(a4) ; Slots are only 0-7
rts
; ===========================================================================
; loc_2C134:
SlotMachine_Routine5_1:
tst.b slot_index(a4) ; Is this slot 1?
bne.s + ; Branch if not
tst.b slot_timer(a4) ; Is timer positive or zero?
bmi.s ++ ; Branch if not
rts
; ===========================================================================
+
cmpi.b #8,slot1_rout-slot2_index(a1) ; Is previous slot in state SlotMachine_Routine5_3 or SlotMachine_Routine5_4?
bge.s + ; Branch if yes
rts
; ===========================================================================
+
bsr.s SlotMachine_GetTargetForSlot
move.w (a1),d0 ; Get current slot index/offset
subi.w #$A0,d0 ; Subtract 20 lines (2.5 tiles) from it
lsr.w #8,d0 ; Get effective slot index
andi.w #7,d0 ; Only want 3 bits
move.b (a3,d0.w),d0 ; Get face from sequence
cmp.b d1,d0 ; Are we close to target?
beq.s + ; Branch if yes
rts
; ===========================================================================
+
addq.b #4,slot1_rout-slot1_index(a1) ; => SlotMachine_Routine5_2
move.b #$60,slot1_speed-slot1_index(a1) ; Decrease slot speed
rts
; ===========================================================================
; loc_2C170:
SlotMachine_Routine5_2:
bsr.s SlotMachine_GetTargetForSlot
move.w (a1),d0 ; Get current slot index/offset
addi.w #$F0,d0 ; Add 30 lines (3.75 tiles) to it
andi.w #$700,d0 ; Limit to 8 faces
lsr.w #8,d0 ; Get effective slot index
move.b (a3,d0.w),d0 ; Get face from sequence
cmp.b d0,d1 ; Are we this close to target?
beq.s loc_2C1AE ; Branch if yes
cmpi.b #$20,slot1_speed-slot1_index(a1) ; Is slot speed more than $20?
bls.s + ; Branch if not
subi.b #$C,slot1_speed-slot1_index(a1) ; Reduce slot speed
+
cmpi.b #$18,slot1_speed-slot1_index(a1) ; Is slot speed $18 or less?
bgt.s + ; Branch if not
rts
; ===========================================================================
+
cmpi.b #$80,slot1_offset-slot1_index(a1) ; Is offset $80 or less?
bls.s + ; Branch if yes
rts
; ===========================================================================
+
subq.b #2,slot1_speed-slot1_index(a1) ; Reduce slot speed
rts
; ===========================================================================
loc_2C1AE:
move.w (a1),d0 ; Get current slot index/offset
addi.w #$80,d0 ; Subtract 16 lines (2 tiles) to it
move.w d0,d1 ; Copy to d1
andi.w #$700,d1 ; Limit to 8 faces
subi.w #$10,d1 ; Subtract 2 lines (1/4 tile) from it
move.w d1,(a1) ; Store new value for index/offset
lsr.w #8,d0 ; Convert to index
andi.w #7,d0 ; Limit to 8 faces
move.b (a3,d0.w),d1 ; Get face from sequence
bsr.w SlotMachine_ChangeTarget ; Set slot index to face number, indtead of sequence index
move.b #-8,slot1_speed-slot1_index(a1) ; Rotate slowly on the other direction
addq.b #4,slot1_rout-slot1_index(a1) ; => SlotMachine_Routine5_3
rts
; ===========================================================================
; loc_2C1DA:
SlotMachine_Routine5_3:
tst.b slot1_offset-slot1_index(a1) ; Is offset zero?
beq.s + ; Branch if yes
rts
; ===========================================================================
+
clr.b slot1_speed-slot1_index(a1) ; Stop slot
addq.b #4,slot1_rout-slot1_index(a1) ; => SlotMachine_Routine5_4
rts
; ===========================================================================
; return_2C1EC:
SlotMachine_Routine5_4:
rts
; ===========================================================================
; loc_2C1EE:
SlotMachine_Routine6:
clr.w slot1_speed(a4) ; Stop slot 1
clr.w slot2_speed(a4) ; Stop slot 2
clr.w slot3_speed(a4) ; Stop slot 3
clr.b slot_timer(a4) ; Stop drawing the slots
bsr.w SlotMachine_ChooseReward
_move.b #$18,slot_rout(a4) ; => null routine (rts)
rts
; ===========================================================================
; loc_2C20A
SlotMachine_DrawSlot:
moveq #0,d0 ; Clear d0
move.b slot_index(a4),d0 ; d0 = index of slot to draw
lea slots_data(a4),a1 ; a1 = pointer to slots data
adda.w d0,a1 ; a1 = pointer to current slot data
lea (SlotSequence1).l,a3 ; Get slot sequence
adda.w d0,a3 ; Add offset...
adda.w d0,a3 ; ... twice
jmp BranchTo_SlotMachine_Subroutine(pc,d0.w)
; ===========================================================================
BranchTo_SlotMachine_Subroutine
bra.w SlotMachine_Subroutine1 ; $00
bra.w SlotMachine_Subroutine2 ; $04
; bra.w SlotMachine_Subroutine3 ; $08
;SlotMachine_Subroutine3:
clr.b slot_index(a4) ; => SlotMachine_Subroutine1
subq.b #1,slot_timer(a4) ; Decrease timer
move.w #tiles_to_bytes(ArtTile_ArtUnc_CNZSlotPics_3),d2 ; DMA destination
bra.s +
; ===========================================================================
; loc_2C23A:
SlotMachine_Subroutine1:
addq.b #4,slot_index(a4) ; => SlotMachine_Subroutine2
move.w #tiles_to_bytes(ArtTile_ArtUnc_CNZSlotPics_1),d2 ; DMA destination
bra.w +
; ===========================================================================
; loc_2C246:
SlotMachine_Subroutine2:
addq.b #4,slot_index(a4) ; => SlotMachine_Subroutine3
move.w #tiles_to_bytes(ArtTile_ArtUnc_CNZSlotPics_2),d2 ; DMA destination
+
move.w (a1),d0 ; Get last pixel offset
move.b 2(a1),d1 ; Get slot rotation speed
ext.w d1 ; Extend to word
sub.w d1,(a1) ; Modify pixel offset
move.w (a1),d3 ; Get current pixel offset
andi.w #$7F8,d0 ; Get only desired bits of last pixel offset
andi.w #$7F8,d3 ; Get only desired bits of current pixel offset
cmp.w d0,d3 ; Are those equal?
bne.s + ; Branch if not (need new picture)
rts
; ---------------------------------------------------------------------------
+
bsr.w SlotMachine_GetPixelRow ; Get pointer to pixel row
lea (Block_Table+$1000).w,a1 ; Destination for pixel rows
move.w #4*8-1,d1 ; Slot picture is 4 tiles
- move.l $80(a2),$80(a1) ; Copy pixel row for second column
move.l $100(a2),$100(a1) ; Copy pixel row for third column
move.l $180(a2),$180(a1) ; Copy pixel row for fourth column
move.l (a2)+,(a1)+ ; Copy pixel row for first column, advance destination to next line
addq.b #8,d3 ; Increase offset by 8 (byte operation)
bne.s + ; If the result is not zero, branch
addi.w #$100,d3 ; Advance to next slot picture
andi.w #$700,d3 ; Limit the sequence to 8 pictures
bsr.w SlotMachine_GetPixelRow ; Need pointer to next pixel row
+
dbf d1,- ; Loop for aoo pixel rows
move.l #(Block_Table+$1000)&$FFFFFF,d1 ; Source
tst.w (Two_player_mode).w
beq.s +
addi.w #tiles_to_bytes(ArtTile_ArtUnc_CNZSlotPics_1_2p-ArtTile_ArtUnc_CNZSlotPics_1),d2
+
move.w #$100,d3 ; Number of bytes
jsr (QueueDMATransfer).l
rts
; ===========================================================================
; loc_2C2B8
SlotMachine_GetPixelRow:
move.w d3,d0 ; d0 = pixel offset into slot picture
lsr.w #8,d0 ; Convert offset into index
andi.w #7,d0 ; Limit each sequence to 8 pictures
move.b (a3,d0.w),d0 ; Get slot pic id
andi.w #7,d0 ; Get only lower 3 bits; leaves space for 2 more images
ror.w #7,d0 ; Equal to shifting left 9 places, or multiplying by 4*4 tiles, in bytes
lea (ArtUnc_CNZSlotPics).l,a2 ; Load slot pictures
adda.w d0,a2 ; a2 = pointer to first tile of slot picture
move.w d3,d0 ; d0 = d3
andi.w #$F8,d0 ; Strip high word (picture index)
lsr.w #1,d0 ; Convert into bytes
adda.w d0,a2 ; a2 = pointer to desired pixel row
rts
; ==========================================================================
; loc_2C2DE:
SlotMachine_ChooseReward:
move.b slot23_targ(a4),d2 ; Get slots 2 and 3
move.b d2,d3 ; Copy to d3
andi.w #$F0,d2 ; Strip off slot 3 nibble
lsr.w #4,d2 ; Shift slot 2 to position
andi.w #$F,d3 ; Strip off slot 2 nibble
moveq #0,d0 ; Clear d0
cmp.b slot1_targ(a4),d2 ; Are slots 1 and 2 equal?
bne.s + ; Branch if not
addq.w #4,d0
+
cmp.b slot1_targ(a4),d3 ; Are slots 1 and 3 equal?
bne.s + ; Branch if not
addq.w #8,d0
+
jmp SlotMachine_ChooseReward_JmpTable(pc,d0.w)
; ==========================================================================
; loc_2C304:
SlotMachine_ChooseReward_JmpTable: ;;
bra.w SlotMachine_Unmatched1 ; $00
bra.w SlotMachine_Match12 ; $04
bra.w SlotMachine_Match13 ; $08
; ==========================================================================
; SlotMachine_TripleMatch:
move.w d2,d0 ; d0 = reward index
bsr.w SlotMachine_GetReward
move.w d0,slots_targ(a4) ; Store reward
rts
; ===========================================================================
;loc_2C31C
SlotMachine_Match13:
cmpi.b #3,d3 ; is slot 3 a jackpot?
bne.s + ; Branch if not
move.w d2,d0 ; Slot 2 is reward index
bsr.w SlotMachine_GetReward
bsr.w SlotMachine_QuadrupleUp
move.w d0,slots_targ(a4) ; Store reward
rts
; ===========================================================================
+
cmpi.b #3,d2 ; Is slot 2 a jackpot?
bne.w SlotMachine_Unmatched1 ; Branch if not
move.w d3,d0 ; Slot 3 is reward index
bsr.w SlotMachine_GetReward
bsr.w SlotMachine_DoubleUp
move.w d0,slots_targ(a4) ; Store reward
rts
; ===========================================================================
;loc_2C34A
SlotMachine_Match12:
cmpi.b #3,d2 ; Is slot 2 a jackpot?
bne.s + ; Branch if not
move.w d3,d0 ; Slot 3 is reward index
bsr.s SlotMachine_GetReward
bsr.w SlotMachine_QuadrupleUp
move.w d0,slots_targ(a4) ; Store reward
rts
; ===========================================================================
+
cmpi.b #3,d3 ; Is slot 3 a jackpot?
bne.w SlotMachine_Unmatched1 ; Branch if not
move.w d2,d0 ; Slot 2 is reward index
bsr.s SlotMachine_GetReward
bsr.w SlotMachine_DoubleUp
move.w d0,slots_targ(a4) ; Store reward
rts
; ===========================================================================
;loc_2C374
SlotMachine_Unmatched1:
cmp.b d2,d3 ; Are slots 2 and 3 equal?
bne.s SlotMachine_CheckBars ; Branch if not
cmpi.b #3,slot1_targ(a4) ; Is slot 1 a jackpot?
bne.s + ; Branch if not
move.w d2,d0 ; Use slot 2 as reward index
bsr.s SlotMachine_GetReward
bsr.w SlotMachine_DoubleUp
move.w d0,slots_targ(a4) ; Store reward
rts
; ===========================================================================
+
cmpi.b #3,d2 ; Is slot 2 a jackpot?
bne.s SlotMachine_CheckBars ; Branch if not
move.b slot1_targ(a4),d0 ; Get slot 1 face
andi.w #$F,d0 ; Strip high nibble
bsr.s SlotMachine_GetReward
bsr.w SlotMachine_QuadrupleUp
move.w d0,slots_targ(a4) ; Store reward
rts
; ===========================================================================
;loc_2C3A8
SlotMachine_CheckBars:
moveq #2,d1 ; Number of rings per bar
moveq #0,d0 ; Start with zero
cmpi.b #5,slot1_targ(a4) ; Is slot 1 a bar?
bne.s + ; Branch if not
add.w d1,d0 ; Gain 2 rings
+
cmpi.b #5,d2 ; Is slot 2 a bar?
bne.s + ; Branch if not
add.w d1,d0 ; Gain 2 rings
+
cmpi.b #5,d3 ; Is slot 3 a bar?
bne.s + ; Branch if not
add.w d1,d0 ; Gain 2 rings
+
move.w d0,slots_targ(a4) ; Store reward
; For bars, the code past this line is useless. There should be an rts here.
;loc_2C3CA
SlotMachine_GetReward:
add.w d0,d0 ; Convert to index
lea (SlotRingRewards).l,a2 ; Ring reward array
move.w (a2,d0.w),d0 ; Get ring reward
rts
; ===========================================================================
;loc_2C3D8
SlotMachine_QuadrupleUp:
asl.w #2,d0 ; Quadruple reward
rts
; ===========================================================================
;loc_2C3DC
SlotMachine_DoubleUp:
add.w d0,d0 ; Double reward
rts
; ===========================================================================
; data for the slot machines
;byte_2C3E0
SlotRingRewards: dc.w 30, 25, -1, 150, 10, 20
rev02even
;byte_2C3EC
SlotTargetValues: dc.b 8, 3,$33, $12, 0,$00, $12, 1,$11 ,$24, 2,$22
dc.b $1E, 4,$44, $1E, 5,$55, $FF,$F,$FF
rev02even
;byte_2C401
SlotSequence1: dc.b 3, 0, 1, 4, 2, 5, 4, 1
rev02even
;byte_2C409
SlotSequence2: dc.b 3, 0, 1, 4, 2, 5, 0, 2
rev02even
;byte_2C411
SlotSequence3: dc.b 3, 0, 1, 4, 2, 5, 4, 1
even
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo10_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo29_MarkObjGone
jmp (MarkObjGone).l
JmpTo10_AnimateSprite
jmp (AnimateSprite).l
JmpTo6_Adjust2PArtPointer2
jmp (Adjust2PArtPointer2).l
JmpTo54_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo12_CalcSine
jmp (CalcSine).l
JmpTo7_SolidObject_Always_SingleCharacter
jmp (SolidObject_Always_SingleCharacter).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object D7 - Bumper from Casino Night Zone
; ----------------------------------------------------------------------------
; Sprite_2C448:
ObjD7:
moveq #0,d0
move.b routine(a0),d0
move.w ObjD7_Index(pc,d0.w),d1
jmp ObjD7_Index(pc,d1.w)
; ===========================================================================
; off_2C456:
ObjD7_Index: offsetTable
offsetTableEntry.w ObjD7_Init ; 0
offsetTableEntry.w ObjD7_Main ; 2
; ===========================================================================
; loc_2C45A:
ObjD7_Init:
addq.b #2,routine(a0)
move.l #ObjD7_MapUnc_2C626,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CNZHexBumper,2,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo55_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #1,priority(a0)
move.b #$CA,collision_flags(a0)
btst #0,status(a0)
beq.s +
move.b #1,objoff_34(a0)
+
move.w x_pos(a0),d0
move.w d0,d1
subi.w #$60,d0
move.w d0,objoff_30(a0)
addi.w #$60,d1
move.w d1,objoff_32(a0)
; loc_2C4AC:
ObjD7_Main:
move.b collision_property(a0),d0
beq.w ObjD7_MainContinued
lea (MainCharacter).w,a1 ; a1=character
bclr #0,collision_property(a0)
beq.s +
bsr.s ObjD7_BouncePlayerOff
+
lea (Sidekick).w,a1 ; a1=character
bclr #1,collision_property(a0)
beq.s +
bsr.s ObjD7_BouncePlayerOff
+
clr.b collision_property(a0)
bra.w ObjD7_MainContinued
; ===========================================================================
; loc_2C4D8:
ObjD7_BouncePlayerOff:
move.w x_pos(a0),d1
move.w y_pos(a0),d2
sub.w x_pos(a1),d1
sub.w y_pos(a1),d2
jsr (CalcAngle).l
addi.b #$20,d0
andi.w #$C0,d0
cmpi.w #$40,d0
beq.s ObjD7_BounceDown
cmpi.w #$80,d0
beq.s ObjD7_BounceRight
cmpi.w #$C0,d0
beq.s ObjD7_BounceUp
move.w #-$800,x_vel(a1)
move.b #2,anim(a0)
bra.s ObjD7_BounceEnd
; ===========================================================================
; loc_2C516:
ObjD7_BounceDown:
subi.w #$200,x_vel(a1)
tst.w d1
bpl.s +
addi.w #$400,x_vel(a1)
+
move.w #-$800,y_vel(a1)
move.b #1,anim(a0)
bra.s ObjD7_BounceEnd
; ===========================================================================
; loc_2C534:
ObjD7_BounceRight:
move.w #$800,x_vel(a1)
move.b #2,anim(a0)
bra.s ObjD7_BounceEnd
; ===========================================================================
; loc_2C542:
ObjD7_BounceUp:
subi.w #$200,x_vel(a1)
tst.w d1
bpl.s +
addi.w #$400,x_vel(a1)
+
move.w #$800,y_vel(a1)
move.b #1,anim(a0)
; loc_2C55E:
ObjD7_BounceEnd:
bset #1,status(a1)
bclr #4,status(a1)
bclr #5,status(a1)
clr.b jumping(a1)
move.w #SndID_Bumper,d0
jmp (PlaySound).l
; ===========================================================================
; loc_2C57E:
ObjD7_MainContinued:
lea (Ani_objD7).l,a1
jsrto (AnimateSprite).l, JmpTo11_AnimateSprite
tst.b subtype(a0)
beq.w JmpTo30_MarkObjGone
tst.b objoff_34(a0)
beq.s loc_2C5AE
move.w x_pos(a0),d0
subq.w #1,d0
cmp.w objoff_30(a0),d0
bne.s +
move.b #0,objoff_34(a0)
+
move.w d0,x_pos(a0)
bra.s loc_2C5C4
; ===========================================================================
loc_2C5AE:
move.w x_pos(a0),d0
addq.w #1,d0
cmp.w objoff_32(a0),d0
bne.s +
move.b #1,objoff_34(a0)
+
move.w d0,x_pos(a0)
loc_2C5C4:
tst.w (Two_player_mode).w
beq.s +
jmpto (DisplaySprite).l, JmpTo30_DisplaySprite
; ---------------------------------------------------------------------------
+
move.w objoff_30(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bls.s +
move.w objoff_32(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.s loc_2C5F8
+
jmp (DisplaySprite).l
; ===========================================================================
loc_2C5F8:
lea (Object_Respawn_Table).w,a2
moveq #0,d0
move.b respawn_index(a0),d0
beq.s +
bclr #7,2(a2,d0.w)
+
jmp (DeleteObject).l
if removeJmpTos
JmpTo30_MarkObjGone
jmp (MarkObjGone).l
endif
; ===========================================================================
; animation script
; off_2C610:
Ani_objD7: offsetTable
offsetTableEntry.w byte_2C616 ; 0
offsetTableEntry.w byte_2C619 ; 1
offsetTableEntry.w byte_2C61F ; 2
byte_2C616: dc.b $F, 0,$FF
rev02even
byte_2C619: dc.b 3, 1, 0, 1,$FD, 0
rev02even
byte_2C61F: dc.b 3, 2, 0, 2,$FD, 0
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjD7_MapUnc_2C626: BINCLUDE "mappings/sprite/objD7.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo30_DisplaySprite
jmp (DisplaySprite).l
JmpTo30_MarkObjGone
jmp (MarkObjGone).l
JmpTo11_AnimateSprite
jmp (AnimateSprite).l
JmpTo55_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object D8 - Block thingy from CNZ that disappears after 3 hits (UFO saucer-shaped)
; ----------------------------------------------------------------------------
; Sprite_2C6AC:
ObjD8:
moveq #0,d0
move.b routine(a0),d0
move.w ObjD8_Index(pc,d0.w),d1
jmp ObjD8_Index(pc,d1.w)
; ===========================================================================
; off_2C6BA:
ObjD8_Index: offsetTable
offsetTableEntry.w ObjD8_Init ; 0
offsetTableEntry.w loc_2C6FC ; 2
offsetTableEntry.w loc_2C884 ; 4
; ===========================================================================
; loc_2C6C0:
ObjD8_Init:
addq.b #2,routine(a0)
move.l #ObjD8_MapUnc_2C8C4,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CNZMiniBumper,2,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo56_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #$10,width_pixels(a0)
move.b #1,priority(a0)
move.b #$D7,collision_flags(a0)
move.b subtype(a0),d0
rol.b #2,d0
andi.b #3,d0
move.b d0,anim(a0)
loc_2C6FC:
move.b collision_property(a0),d0
bne.w loc_2C70A
tst.w objoff_30(a0)
beq.s loc_2C740
loc_2C70A:
lea objoff_30(a0),a4
tst.b (a4)
beq.s loc_2C716
subq.b #1,(a4)
bra.s loc_2C724
; ===========================================================================
loc_2C716:
lea (MainCharacter).w,a1 ; a1=character
bclr #0,collision_property(a0)
beq.s loc_2C724
bsr.s loc_2C74E
loc_2C724:
addq.w #1,a4
tst.b (a4)
beq.s loc_2C72E
subq.b #1,(a4)
bra.s loc_2C73C
; ===========================================================================
loc_2C72E:
lea (Sidekick).w,a1 ; a1=character
bclr #1,collision_property(a0)
beq.s loc_2C73C
bsr.s loc_2C74E
loc_2C73C:
clr.b collision_property(a0)
loc_2C740:
lea (Ani_objD8).l,a1
jsrto (AnimateSprite).l, JmpTo12_AnimateSprite
jmpto (MarkObjGone).l, JmpTo31_MarkObjGone
; ===========================================================================
loc_2C74E:
move.b mapping_frame(a0),d0
subq.b #3,d0
beq.s loc_2C75C
bcc.s loc_2C77A
addq.b #3,d0
bne.s loc_2C77A
loc_2C75C:
move.b #3,anim(a0)
move.w #-$700,y_vel(a1)
move.w y_pos(a0),d2
sub.w y_pos(a1),d2
bpl.s BranchTo_loc_2C806
neg.w y_vel(a1)
BranchTo_loc_2C806
bra.w loc_2C806
; ===========================================================================
loc_2C77A:
subq.b #1,d0
bne.s loc_2C7EC
move.b #4,anim(a0)
move.w #$20,d3
btst #0,status(a0)
bne.s loc_2C794
move.w #$60,d3
loc_2C794:
move.w x_vel(a1),d1
move.w y_vel(a1),d2
jsr (CalcAngle).l
sub.w d3,d0
mvabs.w d0,d1
neg.w d0
add.w d3,d0
cmpi.b #$40,d1
bhs.s loc_2C7BE
cmpi.b #$38,d1
blo.s loc_2C7D0
move.w d3,d0
bra.s loc_2C7D0
; ===========================================================================
loc_2C7BE:
subi.w #$80,d1
neg.w d1
cmpi.b #$38,d1
blo.s loc_2C7D0
move.w d3,d0
addi.w #$80,d0
loc_2C7D0:
jsr (CalcSine).l
muls.w #-$700,d1
asr.l #8,d1
move.w d1,x_vel(a1)
muls.w #-$700,d0
asr.l #8,d0
move.w d0,y_vel(a1)
bra.s loc_2C806
; ===========================================================================
loc_2C7EC:
move.b #5,anim(a0)
move.w #-$700,x_vel(a1)
move.w x_pos(a0),d2
sub.w x_pos(a1),d2
bpl.s loc_2C806
neg.w x_vel(a1)
loc_2C806:
bset #1,status(a1)
bclr #4,status(a1)
bclr #5,status(a1)
clr.b jumping(a1)
move.w #SndID_BonusBumper,d0
jsr (PlaySound).l
movea.w a1,a3
moveq #4,d3
moveq #1,d0
subi.w #palette_line_1,art_tile(a0)
bcc.s loc_2C85C
addi.w #palette_line_1,art_tile(a0)
move.b #4,routine(a0)
lea (CNZ_saucer_data).w,a1
move.b subtype(a0),d1
andi.w #$3F,d1 ; This means CNZ_saucer_data is only $40 bytes large
lea (a1,d1.w),a1
addq.b #1,(a1)
cmpi.b #3,(a1)
blo.s loc_2C85C
moveq #2,d3
moveq #50,d0
loc_2C85C:
jsr (AddPoints2).l
jsrto (SingleObjLoad).l, JmpTo11_SingleObjLoad
bne.s loc_2C87E
_move.b #ObjID_Points,id(a1) ; load obj29
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.b d3,mapping_frame(a1)
loc_2C87E:
move.b #4,(a4)
rts
; ===========================================================================
loc_2C884:
lea (Ani_objD8).l,a1
jsrto (AnimateSprite).l, JmpTo12_AnimateSprite
cmpi.b #3,anim(a0)
blo.w JmpTo46_DeleteObject
jmpto (MarkObjGone).l, JmpTo31_MarkObjGone
if removeJmpTos
JmpTo46_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
; animation script
; off_2C89C:
Ani_objD8: offsetTable
offsetTableEntry.w byte_2C8A8 ; 0
offsetTableEntry.w byte_2C8AB ; 1
offsetTableEntry.w byte_2C8AE ; 2
offsetTableEntry.w byte_2C8B1 ; 3
offsetTableEntry.w byte_2C8B7 ; 4
offsetTableEntry.w byte_2C8BD ; 5
byte_2C8A8: dc.b $F, 0,$FF
rev02even
byte_2C8AB: dc.b $F, 1,$FF
rev02even
byte_2C8AE: dc.b $F, 2,$FF
rev02even
byte_2C8B1: dc.b 3, 3, 0, 3,$FD, 0
rev02even
byte_2C8B7: dc.b 3, 4, 1, 4,$FD, 1
rev02even
byte_2C8BD: dc.b 3, 5, 2, 5,$FD, 2
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjD8_MapUnc_2C8C4: BINCLUDE "mappings/sprite/objD8.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo46_DeleteObject
jmp (DeleteObject).l
JmpTo11_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo31_MarkObjGone
jmp (MarkObjGone).l
JmpTo12_AnimateSprite
jmp (AnimateSprite).l
JmpTo56_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object D9 - Invisible sprite that you can hang on to, like the blocks in WFZ
; ----------------------------------------------------------------------------
; Sprite_2C92C:
ObjD9:
moveq #0,d0
move.b routine(a0),d0
move.w ObjD9_Index(pc,d0.w),d1
jmp ObjD9_Index(pc,d1.w)
; ===========================================================================
; off_2C93A:
ObjD9_Index: offsetTable
offsetTableEntry.w ObjD9_Init ; 0
offsetTableEntry.w ObjD9_Main ; 2
; ===========================================================================
; loc_2C93E:
ObjD9_Init:
addq.b #2,routine(a0)
move.b #4,render_flags(a0)
move.b #$18,width_pixels(a0)
move.b #4,priority(a0)
; loc_2C954:
ObjD9_Main:
lea objoff_30(a0),a2
lea (MainCharacter).w,a1 ; a1=character
move.w (Ctrl_1).w,d0
bsr.s ObjD9_CheckCharacter
lea (Sidekick).w,a1 ; a1=character
addq.w #1,a2
move.w (Ctrl_2).w,d0
bsr.s ObjD9_CheckCharacter
jmpto (MarkObjGone3).l, JmpTo7_MarkObjGone3
; ===========================================================================
; loc_2C972:
ObjD9_CheckCharacter:
tst.b (a2)
beq.s loc_2C9A0
andi.b #button_B_mask|button_C_mask|button_A_mask,d0
beq.w ObjD9_CheckCharacter_End
clr.b obj_control(a1)
clr.b (a2)
move.b #$12,2(a2)
andi.w #(button_up_mask|button_down_mask|button_left_mask|button_right_mask)<<8,d0
beq.s +
move.b #$3C,2(a2)
+
move.w #-$300,y_vel(a1)
bra.w ObjD9_CheckCharacter_End
; ===========================================================================
loc_2C9A0:
tst.b 2(a2)
beq.s +
subq.b #1,2(a2)
bne.w ObjD9_CheckCharacter_End
+
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
addi.w #$18,d0
cmpi.w #$30,d0
bhs.w ObjD9_CheckCharacter_End
move.w y_pos(a1),d1
sub.w y_pos(a0),d1
cmpi.w #$10,d1
bhs.w ObjD9_CheckCharacter_End
tst.b obj_control(a1)
bmi.s ObjD9_CheckCharacter_End
cmpi.b #6,routine(a1)
bhs.s ObjD9_CheckCharacter_End
tst.w (Debug_placement_mode).w
bne.s ObjD9_CheckCharacter_End
clr.w x_vel(a1)
clr.w y_vel(a1)
clr.w inertia(a1)
move.w y_pos(a0),y_pos(a1)
move.b #AniIDSonAni_Hang2,anim(a1)
move.b #1,obj_control(a1)
move.b #1,(a2)
; return_2CA08:
ObjD9_CheckCharacter_End:
rts
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo7_MarkObjGone3
jmp (MarkObjGone3).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 4A - Octus (octopus badnik) from OOZ
; ----------------------------------------------------------------------------
octus_start_position = objoff_2A
; Sprite_2CA14:
Obj4A:
moveq #0,d0
move.b routine(a0),d0
move.w Obj4A_Index(pc,d0.w),d1
jmp Obj4A_Index(pc,d1.w)
; ===========================================================================
; off_2CA22:
Obj4A_Index: offsetTable
offsetTableEntry.w Obj4A_Init ; 0
offsetTableEntry.w Obj4A_Main ; 2
offsetTableEntry.w Obj4A_Angry ; 4 - unused
offsetTableEntry.w Obj4A_Bullet ; 6
; ===========================================================================
; loc_2CA2A:
Obj4A_Bullet:
subi_.w #1,objoff_2C(a0)
bmi.s +
rts
; ---------------------------------------------------------------------------
+
jsrto (ObjectMove).l, JmpTo19_ObjectMove
lea (Ani_obj4A).l,a1
jsrto (AnimateSprite).l, JmpTo13_AnimateSprite
jmpto (MarkObjGone).l, JmpTo32_MarkObjGone
; ===========================================================================
; loc_2CA46:
Obj4A_Angry: ; Used by removed sub-object
subq.w #1,objoff_2C(a0)
beq.w JmpTo47_DeleteObject
jmpto (DisplaySprite).l, JmpTo31_DisplaySprite
if removeJmpTos
JmpTo47_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
; loc_2CA52:
Obj4A_Init:
move.l #Obj4A_MapUnc_2CBFE,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Octus,1,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #$A,collision_flags(a0)
move.b #4,priority(a0)
move.b #$10,width_pixels(a0)
move.b #$B,y_radius(a0)
move.b #8,x_radius(a0)
jsrto (ObjectMoveAndFall).l, JmpTo2_ObjectMoveAndFall
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.s +
add.w d1,y_pos(a0)
move.w #0,y_vel(a0)
addq.b #2,routine(a0)
move.w x_pos(a0),d0
sub.w (MainCharacter+x_pos).w,d0
bpl.s +
bchg #0,status(a0)
+
move.w y_pos(a0),octus_start_position(a0)
rts
; ===========================================================================
; loc_2CAB8:
Obj4A_Main:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj4A_Main_Index(pc,d0.w),d1
jsr Obj4A_Main_Index(pc,d1.w)
lea (Ani_obj4A).l,a1
jsrto (AnimateSprite).l, JmpTo13_AnimateSprite
jmpto (MarkObjGone).l, JmpTo32_MarkObjGone
; ===========================================================================
; off_2CAD4:
Obj4A_Main_Index: offsetTable
offsetTableEntry.w Obj4A_WaitForCharacter ; 0
offsetTableEntry.w Obj4A_DelayBeforeMoveUp ; 2
offsetTableEntry.w Obj4A_MoveUp ; 4
offsetTableEntry.w Obj4A_Hover ; 6
offsetTableEntry.w Obj4A_MoveDown ; 8
; ===========================================================================
; loc_2CADE:
Obj4A_WaitForCharacter:
move.w x_pos(a0),d0
sub.w (MainCharacter+x_pos).w,d0
cmpi.w #$80,d0
bgt.s + ; rts
cmpi.w #-$80,d0
blt.s + ; rts
addq.b #2,routine_secondary(a0)
move.b #3,anim(a0)
move.w #$20,objoff_2C(a0)
+
rts
; ===========================================================================
; loc_2CB04:
Obj4A_DelayBeforeMoveUp:
subq.w #1,objoff_2C(a0)
bmi.s +
rts
; ---------------------------------------------------------------------------
+
addq.b #2,routine_secondary(a0)
move.b #4,anim(a0)
move.w #-$200,y_vel(a0)
jmpto (ObjectMove).l, JmpTo19_ObjectMove
; ===========================================================================
; loc_2CB20:
Obj4A_MoveUp:
addi.w #$10,y_vel(a0)
bpl.s +
jmpto (ObjectMove).l, JmpTo19_ObjectMove
; ===========================================================================
+
addq.b #2,routine_secondary(a0)
move.w #$3C,objoff_2C(a0)
bra.w Obj4A_FireBullet
; ===========================================================================
; loc_2CB3A:
Obj4A_Hover:
subq.w #1,objoff_2C(a0)
bmi.s +
rts
; ---------------------------------------------------------------------------
+
addq.b #2,routine_secondary(a0)
rts
; ===========================================================================
; loc_2CB48:
Obj4A_MoveDown:
addi.w #$10,y_vel(a0)
move.w y_pos(a0),d0
cmp.w octus_start_position(a0),d0
bhs.s +
jmpto (ObjectMove).l, JmpTo19_ObjectMove
; ===========================================================================
+
clr.b routine_secondary(a0)
clr.b anim(a0)
clr.w y_vel(a0)
move.b #1,mapping_frame(a0)
rts
; ===========================================================================
; loc_2CB70:
Obj4A_FireBullet:
; In the Simon Wai beta, the object loads another object
; here, which makes it look angry as it fires.
; This object would have used Obj4A_Angry.
jsr (SingleObjLoad).l
bne.s + ; rts
_move.b #ObjID_Octus,id(a1) ; load obj4A
move.b #6,routine(a1)
move.l #Obj4A_MapUnc_2CBFE,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_Octus,1,0),art_tile(a1)
move.b #4,priority(a1)
move.b #$10,width_pixels(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w #$F,objoff_2C(a1)
move.b render_flags(a0),render_flags(a1)
move.b status(a0),status(a1)
move.b #2,anim(a1)
move.b #$98,collision_flags(a1)
move.w #-$200,x_vel(a1)
btst #0,render_flags(a1)
beq.s + ; rts
neg.w x_vel(a1)
+
rts
; ===========================================================================
; animation script
; off_2CBDC:
Ani_obj4A: offsetTable
offsetTableEntry.w byte_2CBE6 ; 0
offsetTableEntry.w byte_2CBEA ; 1
offsetTableEntry.w byte_2CBEF ; 2
offsetTableEntry.w byte_2CBF4 ; 3
offsetTableEntry.w byte_2CBF8 ; 4
byte_2CBE6: dc.b $F, 1, 0,$FF
rev02even
byte_2CBEA: dc.b 3, 1, 2, 3,$FF
rev02even
byte_2CBEF: dc.b 2, 5, 6,$FF
even
byte_2CBF4: dc.b $F, 4,$FF
even
byte_2CBF8: dc.b 7, 0, 1,$FD, 1
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj4A_MapUnc_2CBFE: BINCLUDE "mappings/sprite/obj4A.bin"
if ~~removeJmpTos
align 4
endif
; ===========================================================================
if ~~removeJmpTos
JmpTo31_DisplaySprite
jmp (DisplaySprite).l
JmpTo47_DeleteObject
jmp (DeleteObject).l
JmpTo32_MarkObjGone
jmp (MarkObjGone).l
JmpTo13_AnimateSprite
jmp (AnimateSprite).l
JmpTo2_ObjectMoveAndFall
jmp (ObjectMoveAndFall).l
; loc_2CCC2:
JmpTo19_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 50 - Aquis (seahorse badnik) from OOZ
; ----------------------------------------------------------------------------
; OST Variables:
Obj50_unkown1 = objoff_2A ; word
Obj50_shooting_flag = objoff_2D ; byte ; if set, shooting is disabled
Obj50_shots_remaining = objoff_2E ; word ; number of shots before retreating
Obj50_unkown2 = objoff_30 ; word
Obj50_unkown3 = objoff_32 ; word
Obj50_unkown4 = objoff_34 ; word
Obj50_child = objoff_36 ; long ; pointer to wing object (main)
Obj50_parent = objoff_36 ; long ; pointer to main object (wing)
Obj50_unkown5 = objoff_3A ; word
Obj50_timer = objoff_3C ; byte ; time spent following the player before shooting and time to wait before actually shooting
; Sprite_2CCC8:
Obj50:
moveq #0,d0
move.b routine(a0),d0
move.w Obj50_Index(pc,d0.w),d1
jmp Obj50_Index(pc,d1.w)
; ===========================================================================
; off_2CCD6:
Obj50_Index: offsetTable
offsetTableEntry.w Obj50_Init ; 0
offsetTableEntry.w Obj50_Main ; 2
offsetTableEntry.w Obj50_Wing ; 4
offsetTableEntry.w Obj50_Bullet ; 6
; ===========================================================================
; loc_2CCDE:
Obj50_Init:
addq.b #2,routine(a0)
move.l #Obj50_MapUnc_2CF94,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Aquis,1,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #$A,collision_flags(a0)
move.b #4,priority(a0)
move.b #$10,width_pixels(a0)
move.w #-$100,x_vel(a0)
move.b subtype(a0),d0
move.b d0,d1
andi.w #$F0,d1
lsl.w #4,d1
move.w d1,Obj50_shots_remaining(a0) ; looks like the number of shots could be set via subtype at one point
move.w d1,Obj50_unkown2(a0) ; unused
andi.w #$F,d0
lsl.w #4,d0
subq.w #1,d0
move.w d0,Obj50_unkown3(a0) ; unused
move.w d0,Obj50_unkown4(a0) ; unused
move.w y_pos(a0),Obj50_unkown1(a0) ; unused
move.w (Water_Level_1).w,Obj50_unkown5(a0)
move.b #3,Obj50_shots_remaining(a0) ; hardcoded to three shots
; creat wing child object
jsrto (SingleObjLoad).l, JmpTo12_SingleObjLoad
bne.s Obj50_Main
_move.b #ObjID_Aquis,id(a1) ; load obj50
move.b #4,routine(a1) ; => Obj50_Wing
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
addi.w #$A,x_pos(a1)
addi.w #-6,y_pos(a1)
move.l #Obj50_MapUnc_2CF94,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_Aquis,1,0),art_tile(a1)
ori.b #4,render_flags(a1)
move.b #3,priority(a1)
move.b status(a0),status(a1)
move.b #3,anim(a1)
move.l a1,Obj50_child(a0)
move.l a0,Obj50_parent(a1)
bset #6,status(a0) ; set compund sprite flag. This is useless, as the object doesn't define any child spites, nor does it set its child sprite count
; loc_2CDA2:
Obj50_Main:
lea (Ani_obj50).l,a1
jsrto (AnimateSprite).l, JmpTo14_AnimateSprite
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj50_Main_Index(pc,d0.w),d1
jsr Obj50_Main_Index(pc,d1.w)
bsr.w Obj50_ControlWing
jmpto (MarkObjGone).l, JmpTo33_MarkObjGone
; ===========================================================================
; off_2CDC2:
Obj50_Main_Index: offsetTable
offsetTableEntry.w Obj50_CheckIfOnScreen ; 0
offsetTableEntry.w Obj50_Chase ; 2
offsetTableEntry.w Obj50_Shooting ; 4
offsetTableEntry.w BranchTo_JmpTo20_ObjectMove ; 6
; ===========================================================================
; loc_2CDCA:
Obj50_Wing:
movea.l Obj50_parent(a0),a1 ; a1=object
tst.b id(a1) ; is parent object's slot empty?
beq.w JmpTo48_DeleteObject ; if yes, branch
cmpi.b #ObjID_Aquis,(a1) ; is parent object ObjID_Aquis?
bne.w JmpTo48_DeleteObject ; if not, branch
btst #7,status(a1) ; is parent object marked as destroyed?
bne.w JmpTo48_DeleteObject ; if yes, branch
lea (Ani_obj50).l,a1
jsrto (AnimateSprite).l, JmpTo14_AnimateSprite
jmpto (DisplaySprite).l, JmpTo32_DisplaySprite
; ===========================================================================
; loc_2CDF4:
Obj50_Bullet:
jsrto (ObjectMove).l, JmpTo20_ObjectMove
lea (Ani_obj50).l,a1
jsrto (AnimateSprite).l, JmpTo14_AnimateSprite
jmpto (MarkObjGone).l, JmpTo33_MarkObjGone
; ===========================================================================
; wait and do nothing until on screen
; loc_2CE06:
Obj50_CheckIfOnScreen:
tst.b render_flags(a0)
bmi.s +
rts
; ===========================================================================
+
addq.b #2,routine_secondary(a0) ; => Obj50_Chase
rts
; ===========================================================================
; loc_2CE14:
Obj50_Chase:
bsr.w Obj50_FollowPlayer
rts
; ===========================================================================
; loc_2CE1A:
Obj50_Shooting:
bsr.w Obj50_WaitForNextShot
bsr.w Obj50_ChkIfShoot
rts
; ===========================================================================
; loc_2CE24:
Obj50_ChkIfShoot:
tst.b Obj50_shooting_flag(a0) ; is object allowed to shoot?
bne.w return_2CEAC ; if not, branch
st Obj50_shooting_flag(a0) ; else, disallow shooting after this
jsrto (Obj_GetOrientationToPlayer).l, JmpTo_Obj_GetOrientationToPlayer
tst.w d1 ; is player above object?
beq.s return_2CEAC ; if yes, don't shoot
cmpi.w #$FFF0,d1 ; ? d1 should only be 0 or 2 here...
bhs.s return_2CEAC
; shoot bullet
jsrto (SingleObjLoad).l, JmpTo12_SingleObjLoad
bne.s return_2CEAC
_move.b #ObjID_Aquis,id(a1) ; load obj50
move.b #6,routine(a1) ; => Obj50_Bullet
move.w x_pos(a0),x_pos(a1) ; align with parent object
move.w y_pos(a0),y_pos(a1)
move.l #Obj50_MapUnc_2CF94,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_Aquis,1,0),art_tile(a1)
ori.b #4,render_flags(a1)
move.b #3,priority(a1)
move.b #$98,collision_flags(a1)
move.b #2,anim(a1)
move.w #$A,d0 ; set y offset
move.w #$10,d1 ; set x offset
move.w #-$300,d2 ; set x velocity
btst #0,status(a0) ; is object facing right?
beq.s + ; if yes, branch
neg.w d1 ; else, align bullet with other side of object...
neg.w d2 ; ... and move in the opposite direction
+
sub.w d0,y_pos(a1)
sub.w d1,x_pos(a1)
move.w d2,x_vel(a1)
move.w #$200,y_vel(a1)
return_2CEAC:
rts
; ===========================================================================
; follow player for a while; target is whichever character is the closest
; loc_2CEAE:
Obj50_FollowPlayer:
subq.b #1,Obj50_timer(a0)
bmi.s Obj50_DoneFollowing ; branch, if counter has expired
jsrto (Obj_GetOrientationToPlayer).l, JmpTo_Obj_GetOrientationToPlayer
bclr #0,status(a0) ; face right
tst.w d0
beq.s + ; branch, if player is right from object
bset #0,status(a0) ; otherwise, face left
+
; make object move towards player; d0 and d1 were set by the GetOrientationToPlayer routine
move.w Obj50_Speeds(pc,d0.w),d2
add.w d2,x_vel(a0)
move.w Obj50_Speeds(pc,d1.w),d2
add.w d2,y_vel(a0)
move.w #$100,d0 ; $100 is object's max x...
move.w d0,d1 ; ... and y velocity
jsrto (Obj_CapSpeed).l, JmpTo_Obj_CapSpeed
jmpto (ObjectMove).l, JmpTo20_ObjectMove
; ===========================================================================
; word_2CEE6:
Obj50_Speeds:
dc.w -$10 ; 0 - left/up
dc.w $10 ; 2 - right/down
; ===========================================================================
; loc_2CEEA:
Obj50_DoneFollowing:
addq.b #2,routine_secondary(a0) ; => Obj50_Shooting
move.b #$20,Obj50_timer(a0)
jmpto (Obj_MoveStop).l, JmpTo_Obj_MoveStop
; ===========================================================================
; loc_2CEF8:
Obj50_WaitForNextShot:
subq.b #1,Obj50_timer(a0) ; wait for a while
bmi.s + ; branch, if counter has expired
rts
; ===========================================================================
+ ; check if object is out of shots and flee if it is
subq.b #1,Obj50_shots_remaining(a0)
bmi.s Obj50_GoAway ; branch, if object is out of atttacks
; otherwise, shoot and return to chasing the player
subq.b #2,routine_secondary(a0) ; => Obj50_Chase
move.w #-$100,y_vel(a0)
move.b #$80,Obj50_timer(a0) ; reset timer
clr.b Obj50_shooting_flag(a0) ; reenbale shooting
rts
; ===========================================================================
; loc_2CF1C:
Obj50_GoAway:
move.b #6,routine_secondary(a0) ; => BranchTo_JmpTo20_ObjectMove
move.w #-$200,x_vel(a0) ; fly off to the left
clr.w y_vel(a0)
rts
; ===========================================================================
BranchTo_JmpTo20_ObjectMove
jmpto (ObjectMove).l, JmpTo20_ObjectMove
; ===========================================================================
; loc_2CF32:
Obj50_ControlWing:
moveq #$A,d0 ; x offset
moveq #-6,d1 ; y offset
movea.l Obj50_child(a0),a1 ; a1=object
move.w x_pos(a0),x_pos(a1) ; align child with parent object
move.w y_pos(a0),y_pos(a1)
move.b status(a0),status(a1)
move.b respawn_index(a0),respawn_index(a1)
move.b render_flags(a0),render_flags(a1)
btst #0,status(a1) ; is object facing right?
beq.s + ; if yes, branch
neg.w d0 ; else, align wing with other side of object
+
add.w d0,x_pos(a1)
add.w d1,y_pos(a1)
rts
; ===========================================================================
; animation script
; off_2CF6C:
Ani_obj50: offsetTable
offsetTableEntry.w Ani_obj50_Normal ; 0
offsetTableEntry.w byte_2CF7B ; 1
offsetTableEntry.w Ani_obj50_Bullet ; 2
offsetTableEntry.w Ani_obj50_Wing ; 3
offsetTableEntry.w byte_2CF8D ; 4
offsetTableEntry.w byte_2CF90 ; 5
Ani_obj50_Normal: dc.b $E, 0,$FF ; byte_2CF78
rev02even
byte_2CF7B: dc.b 5, 3, 4, 3, 4, 3, 4,$FF
rev02even
Ani_obj50_Bullet: dc.b 3, 5, 6, 7, 6,$FF ; byte_2CF83
rev02even
Ani_obj50_Wing: dc.b 3, 1, 2,$FF ; byte_2CF89
rev02even
byte_2CF8D: dc.b 1, 5,$FF
rev02even
byte_2CF90: dc.b $E, 8,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj50_MapUnc_2CF94: BINCLUDE "mappings/sprite/obj50.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo32_DisplaySprite
jmp (DisplaySprite).l
JmpTo48_DeleteObject
jmp (DeleteObject).l
JmpTo12_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo33_MarkObjGone
jmp (MarkObjGone).l
JmpTo14_AnimateSprite
jmp (AnimateSprite).l
JmpTo_Obj_GetOrientationToPlayer
jmp (Obj_GetOrientationToPlayer).l
JmpTo_Obj_CapSpeed
jmp (Obj_CapSpeed).l
JmpTo_Obj_MoveStop
jmp (Obj_MoveStop).l
; loc_2D060:
JmpTo20_ObjectMove
jmp (ObjectMove).l
align 4
else
JmpTo48_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 4B - Buzzer (Buzz bomber) from EHZ
; ----------------------------------------------------------------------------
; OST Variables:
Obj4B_parent = objoff_2A ; long
Obj4B_move_timer = objoff_2E ; word
Obj4B_turn_delay = objoff_30 ; word
Obj4B_shooting_flag = objoff_32 ; byte
Obj4B_shot_timer = objoff_34 ; word
; Sprite_2D068: ; Obj_Buzzer:
Obj4B:
moveq #0,d0
move.b routine(a0),d0
move.w Obj4B_Index(pc,d0.w),d1
jmp Obj4B_Index(pc,d1.w)
; ===========================================================================
; off_2D076:
Obj4B_Index: offsetTable
offsetTableEntry.w Obj4B_Init ; 0
offsetTableEntry.w Obj4B_Main ; 2
offsetTableEntry.w Obj4B_Flame ; 4
offsetTableEntry.w Obj4B_Projectile ; 6
; ===========================================================================
; loc_2D07E:
Obj4B_Projectile:
jsrto (ObjectMove).l, JmpTo21_ObjectMove
lea (Ani_obj4B).l,a1
jsrto (AnimateSprite).l, JmpTo15_AnimateSprite
jmpto (MarkObjGone_P1).l, JmpTo_MarkObjGone_P1
; ===========================================================================
; loc_2D090:
Obj4B_Flame:
movea.l Obj4B_parent(a0),a1 ; a1=object
tst.b id(a1)
beq.w JmpTo49_DeleteObject ; branch, if object slot is empty. This check is incomplete and very unreliable; check Obj50_Wing to see how it should be done
tst.w Obj4B_turn_delay(a1)
bmi.s + ; branch, if parent isn't currently turning around
rts
; ---------------------------------------------------------------------------
+ ; follow parent object
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
move.b status(a1),status(a0)
move.b render_flags(a1),render_flags(a0)
lea (Ani_obj4B).l,a1
jsrto (AnimateSprite).l, JmpTo15_AnimateSprite
jmpto (MarkObjGone_P1).l, JmpTo_MarkObjGone_P1
; ===========================================================================
; loc_2D0C8:
Obj4B_Init:
move.l #Obj4B_MapUnc_2D2EA,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Buzzer,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo57_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #$A,collision_flags(a0)
move.b #4,priority(a0)
move.b #$10,width_pixels(a0)
move.b #$10,y_radius(a0)
move.b #$18,x_radius(a0)
move.b #3,priority(a0)
addq.b #2,routine(a0) ; => Obj4B_Main
; load exhaust flame object
jsrto (SingleObjLoad2).l, JmpTo20_SingleObjLoad2
bne.s + ; rts
_move.b #ObjID_Buzzer,id(a1) ; load obj4B
move.b #4,routine(a1) ; => Obj4B_Flame
move.l #Obj4B_MapUnc_2D2EA,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_Buzzer,0,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo7_Adjust2PArtPointer2
move.b #4,priority(a1)
move.b #$10,width_pixels(a1)
move.b status(a0),status(a1)
move.b render_flags(a0),render_flags(a1)
move.b #1,anim(a1)
move.l a0,Obj4B_parent(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w #$100,Obj4B_move_timer(a0)
move.w #-$100,x_vel(a0)
btst #0,render_flags(a0)
beq.s + ; rts
neg.w x_vel(a0)
+
rts
; ===========================================================================
; loc_2D174:
Obj4B_Main:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj4B_Buzzer_States(pc,d0.w),d1
jsr Obj4B_Buzzer_States(pc,d1.w)
lea (Ani_obj4B).l,a1
jsrto (AnimateSprite).l, JmpTo15_AnimateSprite
jmpto (MarkObjGone_P1).l, JmpTo_MarkObjGone_P1
; ===========================================================================
; off_2D190:
Obj4B_Buzzer_States: offsetTable
offsetTableEntry.w Obj4B_Roaming ; 0
offsetTableEntry.w Obj4B_Shooting ; 2
; ===========================================================================
; loc_2D194:
Obj4B_Roaming:
bsr.w Obj4B_ChkPlayers
subq.w #1,Obj4B_turn_delay(a0)
move.w Obj4B_turn_delay(a0),d0
cmpi.w #$F,d0
beq.s Obj4B_TurnAround
tst.w d0
bpl.s return_2D1B8
subq.w #1,Obj4B_move_timer(a0)
bgt.w JmpTo21_ObjectMove
move.w #$1E,Obj4B_turn_delay(a0)
return_2D1B8:
rts
; ---------------------------------------------------------------------------
; loc_2D1BA:
Obj4B_TurnAround:
sf Obj4B_shooting_flag(a0) ; reenable shooting
neg.w x_vel(a0) ; reverse movement direction
bchg #0,render_flags(a0)
bchg #0,status(a0)
move.w #$100,Obj4B_move_timer(a0)
rts
; ===========================================================================
; Start of subroutine Obj4B_ChkPlayers
; sub_2D1D6:
Obj4B_ChkPlayers:
tst.b Obj4B_shooting_flag(a0)
bne.w return_2D232 ; branch, if shooting is disabled
move.w x_pos(a0),d0
lea (MainCharacter).w,a1 ; a1=character
btst #0,(Vint_runcount+3).w
beq.s + ; target Sidekick on uneven frames
lea (Sidekick).w,a1 ; a1=character
+
sub.w x_pos(a1),d0 ; get object's distance to player
move.w d0,d1 ; save value for later
bpl.s + ; branch, if it was positive
neg.w d0 ; get absolute value
+
; test if player is inside an 8 pixel wide strip
cmpi.w #$28,d0
blt.s return_2D232
cmpi.w #$30,d0
bgt.s return_2D232
tst.w d1 ; test sign of distance
bpl.s Obj4B_PlayerIsLeft ; branch, if player is left from object
btst #0,render_flags(a0)
beq.s return_2D232 ; branch, if object is facing right
bra.s Obj4B_ReadyToShoot
; ---------------------------------------------------------------------------
; loc_2D216:
Obj4B_PlayerIsLeft:
btst #0,render_flags(a0)
bne.s return_2D232 ; branch, if object is facing left
; loc_2D21E:
Obj4B_ReadyToShoot:
st Obj4B_shooting_flag(a0) ; disable shooting
addq.b #2,routine_secondary(a0) ; => Obj4B_Shooting
move.b #3,anim(a0) ; play shooting animation
move.w #$32,Obj4B_shot_timer(a0)
return_2D232:
rts
; End of subroutine Obj4B_ChkPlayers
; ===========================================================================
; loc_2D234:
Obj4B_Shooting:
move.w Obj4B_shot_timer(a0),d0 ; get timer value
subq.w #1,d0 ; decrement
blt.s Obj4B_DoneShooting ; branch, if timer has expired
move.w d0,Obj4B_shot_timer(a0) ; update timer value
cmpi.w #$14,d0 ; has timer reached a certain value?
beq.s Obj4B_ShootProjectile ; if yes, branch
rts
; ---------------------------------------------------------------------------
; loc_2D248:
Obj4B_DoneShooting:
subq.b #2,routine_secondary(a0) ; => Obj4B_Roaming
rts
; ---------------------------------------------------------------------------
; loc_2D24E
Obj4B_ShootProjectile:
jsr (SingleObjLoad2).l ; Find next open object space
bne.s +
_move.b #ObjID_Buzzer,id(a1) ; load obj4B
move.b #6,routine(a1) ; => Obj4B_Projectile
move.l #Obj4B_MapUnc_2D2EA,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_Buzzer,0,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo7_Adjust2PArtPointer2
move.b #4,priority(a1)
move.b #$98,collision_flags(a1)
move.b #$10,width_pixels(a1)
move.b status(a0),status(a1)
move.b render_flags(a0),render_flags(a1)
move.b #2,anim(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
addi.w #$18,y_pos(a1) ; align vertically with stinger
move.w #$D,d0 ; absolute horizontal offset for stinger
move.w #$180,y_vel(a1)
move.w #-$180,x_vel(a1)
btst #0,render_flags(a1) ; is object facing left?
beq.s + ; if not, branch
neg.w x_vel(a1) ; move in other direction
neg.w d0 ; make offset negative
+
add.w d0,x_pos(a1) ; align horizontally with stinger
rts
; ===========================================================================
; animation script
; off_2D2CE:
Ani_obj4B: offsetTable
offsetTableEntry.w byte_2D2D6 ; 0
offsetTableEntry.w byte_2D2D9 ; 1
offsetTableEntry.w byte_2D2DD ; 2
offsetTableEntry.w byte_2D2E1 ; 3
byte_2D2D6: dc.b $0F, $00, $FF
rev02even
byte_2D2D9: dc.b $02, $03, $04, $FF
rev02even
byte_2D2DD: dc.b $03, $05, $06, $FF
rev02even
byte_2D2E1: dc.b $09, $01, $01, $01, $01, $01, $FD, $00
even
; ----------------------------------------------------------------------------
; sprite mappings -- Buzz Bomber Sprite Table
; ----------------------------------------------------------------------------
; MapUnc_2D2EA: SprTbl_Buzzer:
Obj4B_MapUnc_2D2EA: BINCLUDE "mappings/sprite/obj4B.bin"
if ~~removeJmpTos
align 4
endif
; ===========================================================================
if ~~removeJmpTos
; loc_2D368:
JmpTo49_DeleteObject
jmp (DeleteObject).l
JmpTo20_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo15_AnimateSprite
jmp (AnimateSprite).l
JmpTo7_Adjust2PArtPointer2
jmp (Adjust2PArtPointer2).l
JmpTo_MarkObjGone_P1
jmp (MarkObjGone_P1).l
JmpTo57_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
; loc_2D38C:
JmpTo21_ObjectMove
jmp (ObjectMove).l
align 4
else
JmpTo49_DeleteObject
jmp (DeleteObject).l
; loc_2D38C:
JmpTo21_ObjectMove
jmp (ObjectMove).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 5C - Masher (jumping piranha fish badnik) from EHZ
; ----------------------------------------------------------------------------
; OST Variables:
Obj5C_initial_y_pos = objoff_30 ; word
; Sprite_2D394:
Obj5C:
moveq #0,d0
move.b routine(a0),d0
move.w Obj5C_Index(pc,d0.w),d1
jsr Obj5C_Index(pc,d1.w)
jmpto (MarkObjGone).l, JmpTo34_MarkObjGone
; ===========================================================================
; off_2D3A6:
Obj5C_Index: offsetTable
offsetTableEntry.w Obj5C_Init ; 0
offsetTableEntry.w Obj5C_Main ; 2
; ===========================================================================
; loc_2D3AA:
Obj5C_Init:
addq.b #2,routine(a0)
move.l #Obj5C_MapUnc_2D442,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Masher,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo58_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #4,priority(a0)
move.b #9,collision_flags(a0)
move.b #$10,width_pixels(a0)
move.w #-$400,y_vel(a0)
move.w y_pos(a0),Obj5C_initial_y_pos(a0) ; set initial (and lowest) y position
; loc_2D3E4:
Obj5C_Main:
lea (Ani_obj5C).l,a1
jsrto (AnimateSprite).l, JmpTo16_AnimateSprite
jsrto (ObjectMove).l, JmpTo22_ObjectMove
addi.w #$18,y_vel(a0) ; apply gravity
move.w Obj5C_initial_y_pos(a0),d0
cmp.w y_pos(a0),d0 ; has object reached its initial y position?
bhs.s + ; if not, branch
move.w d0,y_pos(a0)
move.w #-$500,y_vel(a0) ; jump
+
move.b #1,anim(a0)
subi.w #$C0,d0
cmp.w y_pos(a0),d0
bhs.s + ; rts
move.b #0,anim(a0)
tst.w y_vel(a0) ; is object falling?
bmi.s + ; rts ; if not, branch
move.b #2,anim(a0) ; use closed mouth animation
+
rts
; ===========================================================================
; animation script
; off_2D430:
Ani_obj5C: offsetTable
offsetTableEntry.w byte_2D436 ; 0
offsetTableEntry.w byte_2D43A ; 1
offsetTableEntry.w byte_2D43E ; 2
byte_2D436: dc.b 7, 0, 1,$FF
byte_2D43A: dc.b 3, 0, 1,$FF
byte_2D43E: dc.b 7, 0,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj5C_MapUnc_2D442: BINCLUDE "mappings/sprite/obj5C.bin"
if ~~removeJmpTos
align 4
endif
; ===========================================================================
if ~~removeJmpTos
JmpTo34_MarkObjGone
jmp (MarkObjGone).l
JmpTo16_AnimateSprite
jmp (AnimateSprite).l
JmpTo58_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
; loc_2D48E:
JmpTo22_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 58 - Boss explosion
; ----------------------------------------------------------------------------
; Sprite_2D494:
Obj58:
moveq #0,d0
move.b routine(a0),d0
move.w Obj58_Index(pc,d0.w),d1
jmp Obj58_Index(pc,d1.w)
; ===========================================================================
; off_2D4A2:
Obj58_Index: offsetTable
offsetTableEntry.w Obj58_Init ; 0
offsetTableEntry.w Obj58_Main ; 2
; ===========================================================================
; loc_2D4A6:
Obj58_Init:
addq.b #2,routine(a0)
move.l #Obj58_MapUnc_2D50A,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_FieryExplosion,0,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo59_Adjust2PArtPointer
move.b #4,render_flags(a0)
move.b #0,priority(a0)
move.b #0,collision_flags(a0)
move.b #$C,width_pixels(a0)
move.b #7,anim_frame_duration(a0)
move.b #0,mapping_frame(a0)
move.w #SndID_BossExplosion,d0
jmp (PlaySound).l
; ===========================================================================
rts
; ===========================================================================
; loc_2D4EC:
Obj58_Main:
subq.b #1,anim_frame_duration(a0)
bpl.s +
move.b #7,anim_frame_duration(a0)
addq.b #1,mapping_frame(a0)
cmpi.b #7,mapping_frame(a0)
beq.w JmpTo50_DeleteObject
+
jmpto (DisplaySprite).l, JmpTo33_DisplaySprite
if removeJmpTos
JmpTo50_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj58_MapUnc_2D50A: BINCLUDE "mappings/sprite/obj58.bin"
; ===========================================================================
; Unused - a little dead code here (until the next label)
;Boss_HoverPos:
move.b boss_sine_count(a0),d0 ; a0=object
jsr (CalcSine).l
asr.w #6,d0
add.w (Boss_Y_pos).w,d0
move.w d0,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
addq.b #2,boss_sine_count(a0)
;loc_2D57C
Boss_HandleHits:
cmpi.b #8,boss_routine(a0) ; is boss exploding or retreating?
bhs.s return_2D5C2 ; if yes, branch
tst.b boss_hitcount2(a0) ; has boss run out of hits?
beq.s Boss_Defeat ; if yes, branch
tst.b collision_flags(a0) ; are boss' collisions enabled?
bne.s return_2D5C2 ; if yes, branch
tst.b boss_invulnerable_time(a0) ; is boss invulnerable?
bne.s + ; if yes, branch
move.b #$20,boss_invulnerable_time(a0) ; make boss invulnerable
move.w #SndID_BossHit,d0 ; play "boss hit" sound
jsr (PlaySound).l
+
; do palette flashing effect
lea (Normal_palette_line2+2).w,a1
moveq #0,d0 ; 0000 = black
tst.w (a1) ; is current color black?
bne.s + ; if not, branch
move.w #$EEE,d0 ; 0EEE = white
+
move.w d0,(a1) ; set color to white or black
subq.b #1,boss_invulnerable_time(a0) ; decrease boss' invulnerable time
bne.s return_2D5C2 ; branch, if it hasn't run out
move.b #$F,collision_flags(a0) ; else, restore collisions
return_2D5C2:
rts
; ===========================================================================
; loc_2D5C4:
Boss_Defeat:
moveq #100,d0
jsrto (AddPoints).l, JmpTo_AddPoints
move.w #$B3,(Boss_Countdown).w
move.b #8,boss_routine(a0)
moveq #PLCID_Capsule,d0
jsrto (LoadPLC).l, JmpTo4_LoadPLC
rts
; ===========================================================================
;loc_2D5DE:
Boss_MoveObject:
move.l (Boss_X_pos).w,d2
move.l (Boss_Y_pos).w,d3
move.w (Boss_X_vel).w,d0
ext.l d0
asl.l #8,d0
add.l d0,d2
move.w (Boss_Y_vel).w,d0
ext.l d0
asl.l #8,d0
add.l d0,d3
move.l d2,(Boss_X_pos).w
move.l d3,(Boss_Y_pos).w
rts
; ===========================================================================
; a1 = animation script pointer
;AnimationArray: up to 8 2-byte entries:
; 4-bit: anim_ID (1)
; 4-bit: anim_ID (2) - the relevant one
; 4-bit: anim_frame
; 4-bit: anim_timer until next anim_frame
; if anim_ID (1) & (2) are not equal, new animation data is loaded
;loc_2D604:
AnimateBoss:
moveq #0,d6
movea.l a1,a4 ; address of animation script
lea (Boss_AnimationArray).w,a2
lea mainspr_mapframe(a0),a3 ; mapframe 1 (main object)
tst.b (a3)
bne.s +
addq.w #2,a2
bra.s ++
; ----------------------------------------------------------------------------
+
bsr.w AnimateBoss_Loop
+
moveq #0,d6
move.b mainspr_childsprites(a0),d6 ; number of child sprites
subq.w #1,d6 ; = amount of iterations to run the code from AnimateBoss_Loop
bmi.s return_2D690 ; if was 0, don't run
lea sub2_mapframe(a0),a3 ; mapframe 2
; ----------------------------------------------------------------------------
;loc_2D62A:
AnimateBoss_Loop: ; increases a2 (AnimationArray) by 2 each iteration
movea.l a4,a1
moveq #0,d0
moveq #0,d1
moveq #0,d2
moveq #0,d4
move.b (a2)+,d0
move.b d0,d1
lsr.b #4,d1 ; anim_ID (1)
andi.b #$F,d0 ; anim_ID (2)
move.b d0,d2
cmp.b d0,d1
beq.s +
st d4 ; anim_IDs not equal
+
move.b d0,d5
lsl.b #4,d5
or.b d0,d5 ; anim_ID (2) in both nybbles
move.b (a2)+,d0
move.b d0,d1
lsr.b #4,d1 ; anim_frame
tst.b d4 ; are the anim_IDs equal?
beq.s +
moveq #0,d0
moveq #0,d1 ; reset d0,d1 if anim_IDs not equal
+
andi.b #$F,d0 ; timer until next anim_frame
subi_.b #1,d0
bpl.s loc_2D67C ; timer not yet at 0, and anim_IDs are equal
add.w d2,d2 ; anim_ID (2)
adda.w (a1,d2.w),a1 ; address of animation data with this ID
move.b (a1),d0 ; animation speed
move.b 1(a1,d1.w),d2 ; mapping_frame of first/next anim_frame
bmi.s AnimateBoss_CmdParam ; if animation command parameter, branch
loc_2D672:
andi.b #$7F,d2
move.b d2,(a3) ; store mapping_frame to OST of object
addi_.b #1,d1 ; anim_frame
loc_2D67C:
lsl.b #4,d1
or.b d1,d0
move.b d0,-1(a2) ; (2nd byte) anim_frame and anim_timer
move.b d5,-2(a2) ; (1st byte) anim_ID (both nybbles)
adda_.w #6,a3 ; mapping_frame of next subobject
dbf d6,AnimateBoss_Loop
return_2D690:
rts
; ----------------------------------------------------------------------------
;loc_2D692:
AnimateBoss_CmdParam: ; parameter $FF - reset animation to first frame
addq.b #1,d2
bne.s +
move.b #0,d1
move.b 1(a1),d2
bra.s loc_2D672
; ----------------------------------------------------------------------------
+ ; parameter $FE - increase boss routine
addq.b #1,d2
bne.s +
addi_.b #2,angle(a0) ; boss routine
rts
; ----------------------------------------------------------------------------
+ ; parameter $FD - change anim_ID to byte after parameter
addq.b #1,d2
bne.s +
andi.b #$F0,d5 ; keep anim_ID (1)
or.b 2(a1,d1.w),d5 ; set anim_ID (2)
bra.s loc_2D67C
; ----------------------------------------------------------------------------
+ ; parameter $FC - jump back to anim_frame d1
addq.b #1,d2
bne.s + ; rts
moveq #0,d3
move.b 2(a1,d1.w),d1 ; anim_frame
move.b 1(a1,d1.w),d2 ; mapping_frame
bra.s loc_2D672
; ----------------------------------------------------------------------------
+ ; parameter $80-$FB
rts
; ===========================================================================
;loc_2D6CC:
Boss_LoadExplosion:
move.b (Vint_runcount+3).w,d0
andi.b #7,d0
bne.s + ; rts
jsr (SingleObjLoad).l
bne.s + ; rts
_move.b #ObjID_BossExplosion,id(a1) ; load obj58
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
jsr (RandomNumber).l
move.w d0,d1
moveq #0,d1
move.b d0,d1
lsr.b #2,d1
subi.w #$20,d1
add.w d1,x_pos(a1)
lsr.w #8,d0
lsr.b #2,d0
subi.w #$20,d0
add.w d0,y_pos(a1)
+
rts
; ===========================================================================
if ~~removeJmpTos
JmpTo33_DisplaySprite
jmp (DisplaySprite).l
JmpTo50_DeleteObject
jmp (DeleteObject).l
JmpTo4_LoadPLC
jmp (LoadPLC).l
JmpTo_AddPoints
jmp (AddPoints).l
JmpTo59_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 5D - CPZ boss
; ----------------------------------------------------------------------------
; OST Variables:
Obj5D_timer2 = objoff_2A
Obj5D_pipe_segments = objoff_2C
Obj5D_status = objoff_2D
Obj5D_status2 = objoff_2E
Obj5D_x_vel = objoff_2E ; and $2F
Obj5D_x_pos_next = objoff_30
Obj5D_timer = objoff_30
Obj5D_y_offset = objoff_31
Obj5D_timer3 = objoff_32
Obj5D_parent = objoff_34
Obj5D_y_pos_next = objoff_38
Obj5D_defeat_timer = objoff_3C
Obj5D_flag = objoff_3C
Obj5D_timer4 = objoff_3C
Obj5D_invulnerable_time = objoff_3E
Obj5D_hover_counter = objoff_3F
; Sprite_2D734:
Obj5D:
moveq #0,d0
move.b routine(a0),d0
move.w Obj5D_Index(pc,d0.w),d1
jmp Obj5D_Index(pc,d1.w)
; ===========================================================================
; off_2D742:
Obj5D_Index: offsetTable
offsetTableEntry.w Obj5D_Init ; 0
offsetTableEntry.w Obj5D_Main ; 2
offsetTableEntry.w Obj5D_Pipe ; 4
offsetTableEntry.w Obj5D_Pipe_Pump ; 6
offsetTableEntry.w Obj5D_Pipe_Retract ; 8
offsetTableEntry.w Obj5D_Dripper ; $A
offsetTableEntry.w Obj5D_Gunk ; $C
offsetTableEntry.w Obj5D_PipeSegment ; $E
offsetTableEntry.w Obj5D_Container ; $10
offsetTableEntry.w Obj5D_Pump ; $12
offsetTableEntry.w Obj5D_FallingParts ; $14
offsetTableEntry.w Obj5D_Robotnik ; $16
offsetTableEntry.w Obj5D_Flame ; $18
offsetTableEntry.w Obj5D_1A ; $1A
; ===========================================================================
; loc_2D75E:
Obj5D_Init:
; main vehicle
move.l #Obj5D_MapUnc_2ED8C,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Eggpod_3,1,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #$20,width_pixels(a0)
move.w #$2B80,x_pos(a0)
move.w #$4B0,y_pos(a0)
move.b #3,priority(a0)
move.b #$F,collision_flags(a0)
move.b #8,collision_property(a0)
addq.b #2,routine(a0) ; => Obj5D_Main
move.w x_pos(a0),Obj5D_x_pos_next(a0)
move.w y_pos(a0),Obj5D_y_pos_next(a0)
bclr #3,Obj5D_status(a0)
jsrto (Adjust2PArtPointer).l, JmpTo60_Adjust2PArtPointer
; robotnik sitting in his eggmobile
jsr (SingleObjLoad2).l
bne.w loc_2D8AC
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.l a0,Obj5D_parent(a1)
move.l a1,Obj5D_parent(a0)
move.l #Obj5D_MapUnc_2ED8C,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_Eggpod_3,0,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #3,priority(a1)
move.l x_pos(a0),x_pos(a1)
move.l y_pos(a0),y_pos(a1)
move.b #$16,routine(a1) ; => Obj5D_Robotnik
move.b #1,anim(a1)
move.b render_flags(a0),render_flags(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo8_Adjust2PArtPointer2
tst.b subtype(a0)
bmi.w loc_2D8AC
; eggmobile's exhaust flame
jsr (SingleObjLoad2).l
bne.w loc_2D8AC
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.l a0,Obj5D_parent(a1)
move.l #Obj5D_MapUnc_2EE88,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_EggpodJets_1,0,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo8_Adjust2PArtPointer2
move.b #1,anim_frame_duration(a0)
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #3,priority(a1)
move.l x_pos(a0),x_pos(a1)
move.l y_pos(a0),y_pos(a1)
move.b #$18,routine(a1) ; => Obj5D_Flame
move.b render_flags(a0),render_flags(a1)
; large pump mechanism on top of eggmobile
jsr (SingleObjLoad2).l
bne.s loc_2D8AC
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.l a0,Obj5D_parent(a1)
move.l #Obj5D_MapUnc_2EADC,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #2,priority(a1)
move.l x_pos(a0),x_pos(a1)
move.l y_pos(a0),y_pos(a1)
move.b #$12,routine(a1) ; => Obj5D_Pump
loc_2D8AC:
; glass container that dumps mega mack on player
jsr (SingleObjLoad2).l
bne.s loc_2D908
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.l a0,Obj5D_parent(a1)
move.l #Obj5D_MapUnc_2EADC,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #4,priority(a1)
move.l x_pos(a0),x_pos(a1)
move.l y_pos(a0),y_pos(a1)
subi.w #$38,y_pos(a1)
subi.w #$10,x_pos(a1)
move.w #-$10,Obj5D_x_vel(a1)
addi.b #$10,routine(a1) ; => Obj5D_Container
move.b #6,anim(a1)
loc_2D908:
; pipe used to suck mega mack from tube below
jsr (SingleObjLoad2).l
bne.s return_2D94C
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.l a0,Obj5D_parent(a1)
move.l #Obj5D_MapUnc_2EADC,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #4,priority(a1)
move.l x_pos(a0),x_pos(a1)
move.l y_pos(a0),y_pos(a1)
move.b #4,routine(a1) ; => Obj5D_Pipe
return_2D94C:
rts
; ===========================================================================
Obj5D_Main:
bsr.w Obj5D_LookAtChar
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj5D_Main_Index(pc,d0.w),d1
jsr Obj5D_Main_Index(pc,d1.w)
lea (Ani_obj5D_b).l,a1
jsr (AnimateSprite).l
move.b status(a0),d0
andi.b #3,d0
andi.b #$FC,render_flags(a0)
or.b d0,render_flags(a0)
jmp (DisplaySprite).l
; ===========================================================================
Obj5D_Main_Index: offsetTable
offsetTableEntry.w Obj5D_Main_0 ; 0
offsetTableEntry.w Obj5D_Main_2 ; 2
offsetTableEntry.w Obj5D_Main_4 ; 4
offsetTableEntry.w Obj5D_Main_6 ; 6
offsetTableEntry.w Obj5D_Main_8 ; 8
offsetTableEntry.w Obj5D_Main_A ; $A
offsetTableEntry.w Obj5D_Main_C ; $C
; ===========================================================================
; Makes the boss look in Sonic's direction under certain circumstances.
Obj5D_LookAtChar:
cmpi.b #8,routine_secondary(a0)
bge.s +
move.w (MainCharacter+x_pos).w,d0
sub.w x_pos(a0),d0
bgt.s ++
bclr #0,status(a0)
+
rts
; ---------------------------------------------------------------------------
+
bset #0,status(a0)
rts
; ===========================================================================
Obj5D_Main_8:
subq.w #1,Obj5D_defeat_timer(a0)
bpl.w Obj5D_Main_Explode
bset #0,status(a0)
bclr #7,status(a0)
clr.w x_vel(a0)
addq.b #2,routine_secondary(a0) ; => Obj5D_Main_A
move.w #-$26,Obj5D_defeat_timer(a0)
rts
; ===========================================================================
Obj5D_Main_A:
addq.w #1,Obj5D_defeat_timer(a0)
beq.s +
bpl.s ++
addi.w #$18,y_vel(a0)
bra.s Obj5D_Main_A_End
; ---------------------------------------------------------------------------
+
clr.w y_vel(a0)
bra.s Obj5D_Main_A_End
; ---------------------------------------------------------------------------
+
cmpi.w #$30,Obj5D_defeat_timer(a0)
blo.s +
beq.s ++
cmpi.w #$38,Obj5D_defeat_timer(a0)
blo.s Obj5D_Main_A_End
addq.b #2,routine_secondary(a0) ; => Obj5D_Main_C
bra.s Obj5D_Main_A_End
; ---------------------------------------------------------------------------
+
subi_.w #8,y_vel(a0)
bra.s Obj5D_Main_A_End
; ---------------------------------------------------------------------------
+
clr.w y_vel(a0)
jsrto (PlayLevelMusic).l, JmpTo_PlayLevelMusic
jsrto (LoadPLC_AnimalExplosion).l, JmpTo_LoadPLC_AnimalExplosion
Obj5D_Main_A_End:
bsr.w Obj5D_Main_Move
bra.w Obj5D_Main_Pos_and_Collision
; ===========================================================================
Obj5D_Main_C:
bset #6,Obj5D_status2(a0)
move.w #$400,x_vel(a0)
move.w #-$40,y_vel(a0)
cmpi.w #$2C30,(Camera_Max_X_pos).w
bhs.s +
addq.w #2,(Camera_Max_X_pos).w
bra.s Obj5D_Main_C_End
; ===========================================================================
+
tst.b render_flags(a0)
bpl.s Obj5D_Main_Delete
Obj5D_Main_C_End:
bsr.w Obj5D_Main_Move
bra.w Obj5D_Main_Pos_and_Collision
; ===========================================================================
Obj5D_Main_Delete:
addq.l #4,sp
movea.l Obj5D_parent(a0),a1 ; a1=object
jsr (DeleteObject2).l
if removeJmpTos
JmpTo51_DeleteObject
endif
jmp (DeleteObject).l
; ===========================================================================
Obj5D_Main_0:
move.w #$100,y_vel(a0)
bsr.w Obj5D_Main_Move
cmpi.w #$4C0,Obj5D_y_pos_next(a0)
bne.s Obj5D_Main_Pos_and_Collision
move.w #0,y_vel(a0)
addq.b #2,routine_secondary(a0) ; => Obj5D_Main_2
Obj5D_Main_Pos_and_Collision:
; do hovering motion using sine wave
move.b Obj5D_hover_counter(a0),d0
jsr (CalcSine).l
asr.w #6,d0
add.w Obj5D_y_pos_next(a0),d0 ; get y position for next frame, add sine value
move.w d0,y_pos(a0) ; set y and x positions
move.w Obj5D_x_pos_next(a0),x_pos(a0)
addq.b #2,Obj5D_hover_counter(a0)
cmpi.b #8,routine_secondary(a0) ; exploding or retreating?
bhs.s return_2DAE8 ; if yes, branch
tst.b status(a0)
bmi.s Obj5D_Defeated ; branch, if boss is defeated
tst.b collision_flags(a0)
bne.s return_2DAE8 ; branch, if collisions are not turned off
; if collisions are turned off, it means the boss was hit
tst.b Obj5D_invulnerable_time(a0)
bne.s + ; branch, if still invulnerable
move.b #$20,Obj5D_invulnerable_time(a0)
move.w #SndID_BossHit,d0
jsr (PlaySound).l
+
lea (Normal_palette_line2+2).w,a1
moveq #0,d0 ; color black
tst.w (a1) ; test palette entry
bne.s + ; branch, if it's not black
move.w #$EEE,d0 ; color white
+
move.w d0,(a1) ; set color for flashing effect
subq.b #1,Obj5D_invulnerable_time(a0)
bne.s return_2DAE8
move.b #$F,collision_flags(a0) ; restore collisions
bclr #1,Obj5D_status(a0)
return_2DAE8:
rts
; ===========================================================================
; called when status bit 7 is set (check Touch_Enemy_Part2)
Obj5D_Defeated:
moveq #100,d0
jsrto (AddPoints).l, JmpTo2_AddPoints
move.b #8,routine_secondary(a0) ; => Obj5D_Main_8
move.w #$B3,Obj5D_defeat_timer(a0)
movea.l Obj5D_parent(a0),a1 ; a1=object
move.b #4,anim(a1)
moveq #PLCID_Capsule,d0
jmpto (LoadPLC).l, JmpTo5_LoadPLC
; ===========================================================================
rts
; ===========================================================================
Obj5D_Main_Move:
move.l Obj5D_x_pos_next(a0),d2
move.l Obj5D_y_pos_next(a0),d3
move.w x_vel(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d2
move.w y_vel(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d3
move.l d2,Obj5D_x_pos_next(a0)
move.l d3,Obj5D_y_pos_next(a0)
rts
; ===========================================================================
; Creates an explosion every 8 frames at a random position relative to boss.
Obj5D_Main_Explode:
move.b (Vint_runcount+3).w,d0
andi.b #7,d0
bne.s + ; rts
jsr (SingleObjLoad).l
bne.s + ; rts
_move.b #ObjID_BossExplosion,id(a1) ; load obj58
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
jsr (RandomNumber).l
move.w d0,d1
moveq #0,d1
move.b d0,d1
lsr.b #2,d1
subi.w #$20,d1
add.w d1,x_pos(a1)
lsr.w #8,d0
lsr.b #2,d0
subi.w #$20,d0
add.w d0,y_pos(a1)
+
rts
; ===========================================================================
; Creates an explosion.
Obj5D_Main_Explode2:
jsr (SingleObjLoad).l
bne.s + ; rts
_move.b #ObjID_BossExplosion,id(a1) ; load obj58
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
+
rts
; ===========================================================================
Obj5D_Main_2:
btst #3,Obj5D_status(a0) ; is boss on the left side of the arena?
bne.s + ; if yes, branch
move.w #$2B30,d0 ; right side of arena
bra.s ++
; ---------------------------------------------------------------------------
+
move.w #$2A50,d0 ; left side of arena
+
move.w d0,d1
sub.w Obj5D_x_pos_next(a0),d0
bpl.s +
neg.w d0 ; get absolute value
+
cmpi.w #3,d0
ble.s Obj5D_Main_2_Stop ; branch, if boss is within 3 pixels to his target
cmp.w Obj5D_x_pos_next(a0),d1
bgt.s Obj5D_Main_2_MoveRight
;Obj5D_Main_2_MoveLeft:
move.w #-$300,x_vel(a0)
bra.s Obj5D_Main_2_End
; ---------------------------------------------------------------------------
Obj5D_Main_2_MoveRight:
move.w #$300,x_vel(a0)
Obj5D_Main_2_End:
bsr.w Obj5D_Main_Move
bra.w Obj5D_Main_Pos_and_Collision
; ===========================================================================
Obj5D_Main_2_Stop:
cmpi.w #$4C0,Obj5D_y_pos_next(a0)
bne.w Obj5D_Main_Pos_and_Collision
move.w #0,x_vel(a0)
move.w #0,y_vel(a0)
addq.b #2,routine_secondary(a0) ; => Obj5D_Main_4
bchg #3,Obj5D_status(a0) ; indicate boss is now at the other side
bset #0,Obj5D_status2(a0) ; action 0
bra.w Obj5D_Main_Pos_and_Collision
; ===========================================================================
; when status2 bit 0 set, wait for something
Obj5D_Main_4:
btst #0,Obj5D_status2(a0) ; action 0?
beq.s + ; if not, branch
bra.w Obj5D_Main_Pos_and_Collision
; ---------------------------------------------------------------------------
+
addq.b #2,routine_secondary(a0) ; => Obj5D_Main_6
bra.w Obj5D_Main_Pos_and_Collision
; ===========================================================================
Obj5D_Main_6:
move.w (MainCharacter+x_pos).w,d0
addi.w #$4C,d0
cmp.w Obj5D_x_pos_next(a0),d0
bgt.s Obj5D_Main_6_MoveRight
beq.w Obj5D_Main_Pos_and_Collision
;Obj5D_Main_6_MoveLeft:
subi.l #$10000,Obj5D_x_pos_next(a0) ; move left one pixel
; stop at left boundary
cmpi.w #$2A28,Obj5D_x_pos_next(a0)
bgt.w Obj5D_Main_Pos_and_Collision
move.w #$2A28,Obj5D_x_pos_next(a0)
bra.w Obj5D_Main_Pos_and_Collision
; ---------------------------------------------------------------------------
Obj5D_Main_6_MoveRight:
addi.l #$10000,Obj5D_x_pos_next(a0) ; move right one pixel
; stop at right boundary
cmpi.w #$2B70,Obj5D_x_pos_next(a0)
blt.w Obj5D_Main_Pos_and_Collision
move.w #$2B70,Obj5D_x_pos_next(a0)
bra.w Obj5D_Main_Pos_and_Collision
; ===========================================================================
Obj5D_FallingParts:
cmpi.b #-7,Obj5D_timer(a0)
beq.s +
subi_.b #1,Obj5D_timer(a0)
bgt.w JmpTo34_DisplaySprite
bsr.w Obj5D_Main_Explode2
move.b #-7,Obj5D_timer(a0)
move.w #$1E,Obj5D_timer2(a0)
+
subq.w #1,Obj5D_timer2(a0)
bpl.w JmpTo34_DisplaySprite
move.w x_vel(a0),d0
add.w d0,x_pos(a0)
move.l y_pos(a0),d3
move.w y_vel(a0),d0
addi.w #$38,y_vel(a0)
ext.l d0
asl.l #8,d0
add.l d0,d3
move.l d3,y_pos(a0)
cmpi.l #$5800000,d3
bhs.w JmpTo51_DeleteObject
jmpto (MarkObjGone).l, JmpTo35_MarkObjGone
; ===========================================================================
Obj5D_Pump:
btst #7,status(a0)
bne.s +
movea.l Obj5D_parent(a0),a1 ; a1=object
move.l x_pos(a1),x_pos(a0)
move.l y_pos(a1),y_pos(a0)
move.b render_flags(a1),render_flags(a0)
move.b status(a1),status(a0)
movea.l #Ani_Obj5D_Dripper,a1
jsr (AnimateSprite).l
jmp (DisplaySprite).l
; ---------------------------------------------------------------------------
+
moveq #$22,d3
move.b #$78,Obj5D_timer(a0)
movea.l Obj5D_parent(a0),a1 ; a1=object
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
move.b d3,mapping_frame(a0)
move.b #$14,routine(a0) ; => Obj5D_FallingParts
jsr (RandomNumber).l
asr.w #8,d0
asr.w #6,d0
move.w d0,x_vel(a0)
move.w #-$380,y_vel(a0)
moveq #1,d2
addq.w #1,d3
-
jsr (SingleObjLoad).l
bne.w JmpTo51_DeleteObject
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.l #Obj5D_MapUnc_2EADC,mappings(a1)
move.b d3,mapping_frame(a1)
move.b #$14,routine(a1) ; => Obj5D_FallingParts
move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #2,priority(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.b status(a0),status(a1)
move.b render_flags(a0),render_flags(a1)
jsr (RandomNumber).l
asr.w #8,d0
asr.w #6,d0
move.w d0,x_vel(a1)
move.w #-$380,y_vel(a1)
swap d0
addi.b #$1E,d0
andi.w #$7F,d0
move.b d0,Obj5D_timer(a1)
addq.w #1,d3
dbf d2,-
rts
; ===========================================================================
; Object to control the pipe's actions before pumping starts.
Obj5D_Pipe:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj5D_Pipe_Index(pc,d0.w),d1
jmp Obj5D_Pipe_Index(pc,d1.w)
; ===========================================================================
Obj5D_Pipe_Index: offsetTable
offsetTableEntry.w Obj5D_Pipe_0 ; 0
offsetTableEntry.w Obj5D_Pipe_2_Load ; 2
; ===========================================================================
; wait for main vehicle's action 0
Obj5D_Pipe_0:
movea.l Obj5D_parent(a0),a1 ; parent = main vehicle ; a1=object
btst #0,Obj5D_status2(a1) ; parent's action 0?
bne.s + ; if yes, branch
; else, do nothing
rts
; ---------------------------------------------------------------------------
+
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
addi.w #$18,y_pos(a0)
move.w #$C,Obj5D_pipe_segments(a0)
addq.b #2,routine_secondary(a0) ; => Obj5D_Pipe_2_Load
movea.l a0,a1
bra.s Obj5D_Pipe_2_Load_Part2 ; skip initial loading setup
; ===========================================================================
; load pipe segments, first object controls rest of pipe
; objects not loaded in a loop => one segment loaded per frame
; pipe extends gradually
Obj5D_Pipe_2_Load:
jsr (SingleObjLoad2).l
beq.s +
rts
; ---------------------------------------------------------------------------
+
move.l a0,Obj5D_parent(a1)
Obj5D_Pipe_2_Load_Part2:
subq.w #1,Obj5D_pipe_segments(a0) ; is pipe fully extended?
blt.s Obj5D_Pipe_2_Load_End ; if yes, branch
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.l #Obj5D_MapUnc_2EADC,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #5,priority(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
; calculate y position for current pipe segment
move.w Obj5D_pipe_segments(a0),d0
subi.w #$B,d0 ; $B = maximum number of pipe segments -1, result is always negative or zero
neg.w d0 ; positive value needed
lsl.w #3,d0 ; multiply with 8
move.w d0,Obj5D_y_pos_next(a1)
add.w d0,y_pos(a1)
move.b #1,anim(a1)
cmpi.b #2,routine_secondary(a1)
beq.w Obj5D_PipeSegment ; only true for the first object
move.b #$E,routine(a1) ; => Obj5D_PipeSegment
bra.w Obj5D_PipeSegment
; ===========================================================================
; once all pipe segments have been loaded, switch to pumping routine
Obj5D_Pipe_2_Load_End:
move.b #0,routine_secondary(a0)
move.b #6,routine(a0) ; => Obj5D_Pipe_Pump_0
bra.w Obj5D_PipeSegment
; ===========================================================================
; Object to control the pipe's actions while pumping.
Obj5D_Pipe_Pump:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj5D_Pipe_Pump_Index(pc,d0.w),d1
jmp Obj5D_Pipe_Pump_Index(pc,d1.w)
; ===========================================================================
Obj5D_Pipe_Pump_Index: offsetTable
offsetTableEntry.w Obj5D_Pipe_Pump_0 ; 0
offsetTableEntry.w Obj5D_Pipe_Pump_2 ; 2
offsetTableEntry.w Obj5D_Pipe_Pump_4 ; 4
; ===========================================================================
; prepares for pumping animation
Obj5D_Pipe_Pump_0:
jsr (SingleObjLoad2).l
bne.w Obj5D_PipeSegment
move.b #$E,routine(a0) ; => Obj5D_PipeSegment ; temporarily turn control object into a pipe segment
move.b #6,routine(a1)
move.b #2,routine_secondary(a1) ; => Obj5D_Pipe_Pump_2
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.l #Obj5D_MapUnc_2EADC,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #4,priority(a1)
move.b #2,Obj5D_timer3(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
; starting position for pumping animation
move.w #$B*8,d0
move.b d0,Obj5D_y_offset(a1)
add.w d0,y_pos(a1)
move.b #2,anim(a1)
move.l a0,Obj5D_parent(a1) ; address of control object
move.b #$12,Obj5D_timer(a1)
jsr (SingleObjLoad2).l
bne.s BranchTo_Obj5D_PipeSegment
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.b #$A,routine(a1) ; => Obj5D_Dripper
move.l Obj5D_parent(a0),Obj5D_parent(a1)
BranchTo_Obj5D_PipeSegment
bra.w Obj5D_PipeSegment
; ===========================================================================
; do pumping animation
Obj5D_Pipe_Pump_2:
movea.l Obj5D_parent(a0),a1 ; parent = pipe segment (control object) ; a1=object
movea.l Obj5D_parent(a1),a2 ; parent = main vehicle ; a2=object
btst #7,status(a2) ; has boss been defeated?
bne.w JmpTo51_DeleteObject ; if yes, branch
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
subi_.b #1,Obj5D_timer(a0) ; animation timer
bne.s Obj5D_Pipe_Pump_2_End
; when timer reaches zero
move.b #$12,Obj5D_timer(a0) ; reset animation timer
subi_.b #8,Obj5D_y_offset(a0) ; move one segment up
bgt.s Obj5D_Pipe_Pump_2_End
bmi.s + ; pumping sequence is over when y offset becomes negative
; one final delay when last segment is reached
move.b #3,anim(a0)
move.b #$C,Obj5D_timer(a0)
bra.s Obj5D_Pipe_Pump_2_End
; ---------------------------------------------------------------------------
+ ; when pumping sequence is over
move.b #6,Obj5D_timer(a0)
move.b #4,routine_secondary(a0) ; => Obj5D_Pipe_Pump_4
rts
; ---------------------------------------------------------------------------
Obj5D_Pipe_Pump_2_End:
; set y position based on y offset
moveq #0,d0
move.b Obj5D_y_offset(a0),d0
add.w d0,y_pos(a0)
lea (Ani_Obj5D_Dripper).l,a1
jsr (AnimateSprite).l
jmp (DisplaySprite).l
; ===========================================================================
Obj5D_Pipe_Pump_4:
subi_.b #1,Obj5D_timer(a0) ; wait a few frames
beq.s +
rts
; ---------------------------------------------------------------------------
+
subq.b #1,Obj5D_timer3(a0)
beq.s +
move.b #2,anim(a0)
move.b #$12,Obj5D_timer(a0)
move.b #2,routine_secondary(a0) ; => Obj5D_Pipe_Pump_2
move.b #$B*8,Obj5D_y_offset(a0)
+
; set control object's routine
movea.l Obj5D_parent(a0),a1 ; parent = pipe segment (control object) ; a1=object
move.b #8,routine(a1) ; => Obj5D_Pipe_Retract
move.b #$B*8,Obj5D_y_offset(a1)
bra.w JmpTo51_DeleteObject
; ===========================================================================
; Object to control the pipe's actions after pumping is finished.
Obj5D_Pipe_Retract:
tst.b Obj5D_flag(a0) ; is flag set?
bne.s loc_2DFEE ; if yes, branch
moveq #0,d0
move.b Obj5D_y_offset(a0),d0
add.w y_pos(a0),d0 ; get y pos of current pipe segment
lea (MainCharacter).w,a1 ; a1=object
moveq #(Dynamic_Object_RAM_End-Object_RAM)/object_size-1,d1
Obj5D_Pipe_Retract_Loop:
cmp.w y_pos(a1),d0 ; compare object's y position with current y offset
beq.s Obj5D_Pipe_Retract_ChkID ; if they match, branch
lea next_object(a1),a1 ; a1=object
dbf d1,Obj5D_Pipe_Retract_Loop ; continue as long as there are object slots left
bra.s Obj5D_PipeSegment
; ===========================================================================
loc_2DFD8:
st Obj5D_flag(a0)
bra.s Obj5D_PipeSegment
; ===========================================================================
Obj5D_Pipe_Retract_ChkID:
moveq #0,d7
move.b #ObjID_CPZBoss,d7
cmp.b id(a1),d7 ; is object a subtype of the CPZ Boss?
beq.s loc_2DFF0 ; if yes, branch
dbf d1,Obj5D_Pipe_Retract_Loop
bra.s Obj5D_PipeSegment
; ===========================================================================
loc_2DFEE:
movea.l a0,a1
loc_2DFF0:
bset #7,status(a1) ; mark segment for deletion
subi_.b #8,Obj5D_y_offset(a0) ; position of next segment up
beq.s loc_2DFD8
Obj5D_PipeSegment:
movea.l Obj5D_parent(a0),a1 ; a1=object
movea.l Obj5D_parent(a1),a2 ; a2=object
btst #7,status(a2) ; has boss been defeated?
bne.s Obj5D_PipeSegment_End ; if yes, branch
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
cmpi.b #4,routine_secondary(a0)
bne.s +
addi.w #$18,y_pos(a0)
+
btst #7,status(a0) ; is object marked for deletion?
bne.s BranchTo_JmpTo51_DeleteObject ; if yes, branch
move.w Obj5D_y_pos_next(a0),d0
add.w d0,y_pos(a0)
lea (Ani_Obj5D_Dripper).l,a1
jsr (AnimateSprite).l
jmp (DisplaySprite).l
; ===========================================================================
BranchTo_JmpTo51_DeleteObject
bra.w JmpTo51_DeleteObject
; ===========================================================================
Obj5D_PipeSegment_End:
move.b #$14,routine(a0)
jsr (RandomNumber).l
asr.w #8,d0
asr.w #6,d0
move.w d0,x_vel(a0)
move.w #-$380,y_vel(a0)
swap d0
addi.b #$1E,d0
andi.w #$7F,d0
move.b d0,Obj5D_timer(a0)
jmpto (DisplaySprite).l, JmpTo34_DisplaySprite
; ===========================================================================
Obj5D_Dripper:
btst #7,status(a0)
bne.w JmpTo51_DeleteObject
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj5D_Dripper_States(pc,d0.w),d1
jmp Obj5D_Dripper_States(pc,d1.w)
; ===========================================================================
Obj5D_Dripper_States: offsetTable
offsetTableEntry.w Obj5D_Dripper_0 ; 0
offsetTableEntry.w Obj5D_Dripper_2 ; 2
offsetTableEntry.w Obj5D_Dripper_4 ; 4
; ===========================================================================
Obj5D_Dripper_0:
addq.b #2,routine_secondary(a0) ; => Obj5D_Dripper_2
_move.b #ObjID_CPZBoss,id(a0) ; load 0bj5D
move.l #Obj5D_MapUnc_2EADC,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,3,0),art_tile(a0)
move.b #4,render_flags(a0)
move.b #$20,width_pixels(a0)
move.b #4,priority(a0)
movea.l Obj5D_parent(a0),a1 ; a1=object
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
move.b #$F,Obj5D_timer(a0)
move.b #4,anim(a0)
Obj5D_Dripper_2:
subq.b #1,Obj5D_timer(a0)
bne.s +
move.b #5,anim(a0)
move.b #4,Obj5D_timer(a0)
addq.b #2,routine_secondary(a0)
subi.w #$24,y_pos(a0)
subi_.w #2,x_pos(a0)
rts
; ---------------------------------------------------------------------------
+
movea.l Obj5D_parent(a0),a1 ; a1=object
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
move.b status(a1),status(a0)
move.b render_flags(a1),render_flags(a0)
lea (Ani_Obj5D_Dripper).l,a1
jsr (AnimateSprite).l
jmp (DisplaySprite).l
; ===========================================================================
Obj5D_Dripper_4:
subq.b #1,Obj5D_timer(a0)
bne.s +
move.b #0,routine_secondary(a0)
movea.l Obj5D_parent(a0),a1 ; a1=object
bset #1,Obj5D_status2(a1)
addq.b #1,Obj5D_timer4(a0)
cmpi.b #$C,Obj5D_timer4(a0)
bge.w JmpTo51_DeleteObject
rts
; ---------------------------------------------------------------------------
+
movea.l Obj5D_parent(a0),a1 ; a1=object
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
subi.w #$24,y_pos(a0)
subi_.w #2,x_pos(a0)
btst #0,render_flags(a0)
beq.s +
addi_.w #4,x_pos(a0)
+
lea (Ani_Obj5D_Dripper).l,a1
jsr (AnimateSprite).l
jmp (DisplaySprite).l
; ===========================================================================
Obj5D_Container:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj5D_Container_States(pc,d0.w),d1
jmp Obj5D_Container_States(pc,d1.w)
; ===========================================================================
Obj5D_Container_States: offsetTable
offsetTableEntry.w Obj5D_Container_Init ; 0
offsetTableEntry.w Obj5D_Container_Main ; 2
offsetTableEntry.w Obj5D_Container_Floor ; 4
offsetTableEntry.w Obj5D_Container_Extend ; 6
offsetTableEntry.w Obj5D_Container_Floor2 ; 8
offsetTableEntry.w Obj5D_Container_FallOff ; A
; ===========================================================================
Obj5D_Container_Init:
movea.l Obj5D_parent(a0),a1 ; a1=object
btst #7,Obj5D_status2(a1)
bne.s +
bset #7,Obj5D_status2(a1)
jsr (SingleObjLoad2).l
bne.s +
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.l a0,Obj5D_parent(a1)
move.l #Obj5D_MapUnc_2EADC,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #4,priority(a1)
move.l x_pos(a0),x_pos(a1)
move.l y_pos(a0),y_pos(a1)
move.b #$10,routine(a1)
move.b #4,routine_secondary(a1) ; => Obj5D_Container_Floor
move.b #9,anim(a1)
+
jsr (SingleObjLoad2).l
bne.s +
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.l a0,Obj5D_parent(a1)
move.l #Obj5D_MapUnc_2EADC,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,3,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #4,priority(a1)
move.l x_pos(a0),x_pos(a1)
move.l y_pos(a0),y_pos(a1)
addi.b #$10,routine(a1)
move.b #6,routine_secondary(a1) ; => Obj5D_Container_Extend
+
addq.b #2,routine_secondary(a0) ; => Obj5D_Container_Main
Obj5D_Container_Main:
movea.l Obj5D_parent(a0),a1 ; a1=object
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
subi.w #$38,y_pos(a0)
btst #7,status(a0)
bne.s loc_2E2E0
btst #2,Obj5D_status2(a1)
beq.s +
bsr.w loc_2E4CE
bsr.w loc_2E3F2
bra.s loc_2E2AC
; ---------------------------------------------------------------------------
+
btst #5,Obj5D_status2(a1)
beq.s loc_2E2AC
subq.w #1,Obj5D_timer2(a0)
bne.s loc_2E2AC
bclr #5,Obj5D_status2(a1)
bset #3,Obj5D_status2(a1)
bset #4,Obj5D_status2(a1)
loc_2E2AC:
movea.l Obj5D_parent(a0),a1 ; a1=object
move.b status(a1),status(a0)
move.b render_flags(a1),render_flags(a0)
move.w Obj5D_x_vel(a0),d0
btst #0,render_flags(a0)
beq.s +
neg.w d0
+
add.w d0,x_pos(a0)
lea (Ani_Obj5D_Dripper).l,a1
jsr (AnimateSprite).l
jmp (DisplaySprite).l
; ===========================================================================
loc_2E2E0:
move.b #$A,routine_secondary(a0)
bra.s loc_2E2AC
; ===========================================================================
Obj5D_Container_FallOff:
move.l d7,-(sp)
move.b #$1E,Obj5D_timer(a0)
movea.l Obj5D_parent(a0),a1 ; a1=object
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
subi.w #$38,y_pos(a0)
move.w Obj5D_x_vel(a0),d0
btst #0,render_flags(a0)
beq.s +
neg.w d0
+
add.w d0,x_pos(a0)
move.b #$20,mapping_frame(a0)
move.b #$14,routine(a0)
jsr (RandomNumber).l
asr.w #8,d0
asr.w #6,d0
move.w d0,x_vel(a0)
move.w #-$380,y_vel(a0)
moveq #0,d7
move.w Obj5D_x_vel(a0),d0
addi.w #$18,d0
bge.s loc_2E356
addi.w #$18,d0
bge.s loc_2E354
addi.w #$18,d0
bge.s loc_2E352
addq.w #1,d7
loc_2E352:
addq.w #1,d7
loc_2E354:
addq.w #1,d7
loc_2E356:
subq.w #1,d7
bmi.w loc_2E3E6
loc_2E35C:
jsr (SingleObjLoad).l
bne.w JmpTo51_DeleteObject
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.l #Obj5D_MapUnc_2EADC,mappings(a1)
move.b #$21,mapping_frame(a1)
move.b #$14,routine(a1)
move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1)
move.b render_flags(a0),render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #2,priority(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
addi_.w #8,y_pos(a1)
move.w d7,d2
add.w d2,d2
move.w word_2E3EC(pc,d2.w),d3
btst #0,render_flags(a0)
beq.s +
neg.w d3
+
add.w d3,x_pos(a1)
jsr (RandomNumber).l
asr.w #8,d0
asr.w #6,d0
move.w d0,x_vel(a1)
move.w #-$380,y_vel(a1)
swap d0
addi.b #$1E,d0
andi.w #$7F,d0
move.b d0,Obj5D_timer(a1)
dbf d7,loc_2E35C
loc_2E3E6:
move.l (sp)+,d7
if removeJmpTos
JmpTo34_DisplaySprite
endif
jmpto (DisplaySprite).l, JmpTo34_DisplaySprite
; ===========================================================================
word_2E3EC:
dc.w $18
dc.w $30 ; 1
dc.w $48 ; 2
; ===========================================================================
loc_2E3F2:
btst #3,Obj5D_status2(a1)
bne.w return_2E4CC
btst #4,Obj5D_status2(a1)
bne.w return_2E4CC
cmpi.w #-$14,Obj5D_x_vel(a0)
blt.s +
btst #1,Obj5D_status(a1)
beq.w return_2E4CC
bclr #1,Obj5D_status(a1)
bset #2,Obj5D_status(a1)
bra.s loc_2E464
; ---------------------------------------------------------------------------
+
cmpi.w #-$40,Obj5D_x_vel(a0)
bge.w return_2E4CC
move.w (MainCharacter+x_pos).w,d1
subi_.w #8,d1
btst #0,render_flags(a0)
beq.s +
add.w Obj5D_x_vel(a0),d1
sub.w x_pos(a0),d1
bgt.w return_2E4CC
cmpi.w #-$18,d1
bge.s loc_2E464
rts
; ---------------------------------------------------------------------------
+
sub.w Obj5D_x_vel(a0),d1
sub.w x_pos(a0),d1
blt.s return_2E4CC
cmpi.w #$18,d1
bgt.s return_2E4CC
loc_2E464:
bset #5,Obj5D_status2(a1)
bclr #2,Obj5D_status2(a1)
move.w #$12,Obj5D_timer2(a0)
jsr (SingleObjLoad2).l
bne.s return_2E4CC
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.l a0,Obj5D_parent(a1)
move.b #$10,routine(a1)
move.b #8,routine_secondary(a1)
move.l #Obj5D_MapUnc_2EADC,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #5,priority(a1)
move.l x_pos(a0),x_pos(a1)
move.l y_pos(a0),y_pos(a1)
move.b #$B,anim(a1)
move.w #$24,Obj5D_timer2(a1)
return_2E4CC:
rts
; ===========================================================================
loc_2E4CE:
moveq #1,d0
btst #4,Obj5D_status2(a1)
bne.s +
moveq #-1,d0
+
cmpi.w #-$10,Obj5D_x_vel(a0)
bne.s loc_2E552
bclr #4,Obj5D_status2(a1)
beq.s loc_2E552
bclr #2,Obj5D_status2(a1)
clr.b routine_secondary(a0)
movea.l a1,a2
jsr (SingleObjLoad2).l
bne.s return_2E550
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.l Obj5D_parent(a0),Obj5D_parent(a1)
move.l #Obj5D_MapUnc_2EADC,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,1,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #4,priority(a1)
move.l x_pos(a0),x_pos(a1)
move.l y_pos(a0),y_pos(a1)
move.b #4,routine(a1)
move.b #0,routine_secondary(a0)
bra.s return_2E550
; ===========================================================================
move.b #$A,routine(a1)
move.l Obj5D_parent(a0),Obj5D_parent(a1)
return_2E550:
rts
; ===========================================================================
loc_2E552:
move.w Obj5D_x_vel(a0),d1
cmpi.w #-$28,d1
bge.s loc_2E59C
cmpi.w #-$40,d1
bge.s loc_2E594
move.b #8,anim(a0)
cmpi.w #-$58,d1
blt.s loc_2E57E
bgt.s loc_2E578
btst #4,Obj5D_status2(a1)
beq.s return_2E57C
loc_2E578:
add.w d0,Obj5D_x_vel(a0)
return_2E57C:
rts
; ===========================================================================
loc_2E57E:
move.w #-$58,Obj5D_x_vel(a0)
btst #0,render_flags(a0)
beq.s loc_2E578
move.w #$58,Obj5D_x_vel(a0)
bra.s loc_2E578
; ===========================================================================
loc_2E594:
move.b #7,anim(a0)
bra.s loc_2E578
; ===========================================================================
loc_2E59C:
move.b #6,anim(a0)
bra.s loc_2E578
; ===========================================================================
Obj5D_Container_Extend:
btst #7,status(a0)
bne.w JmpTo51_DeleteObject
movea.l Obj5D_parent(a0),a1 ; a1=object
move.l Obj5D_parent(a1),d0
beq.w JmpTo51_DeleteObject
movea.l d0,a1 ; a1=object
bclr #3,Obj5D_status2(a1)
beq.s +
move.b #$C,routine(a0)
move.b #0,routine_secondary(a0)
move.b #$87,collision_flags(a0)
bra.s Obj5D_Container_Floor_End
; ----------------------------------------------------------------------------
+
bclr #1,Obj5D_status2(a1)
bne.s +
tst.b anim(a0)
bne.s Obj5D_Container_Floor_End
rts
; ---------------------------------------------------------------------------
+
tst.b anim(a0)
bne.s +
move.b #$B,anim(a0)
+
addi_.b #1,anim(a0)
cmpi.b #$17,anim(a0)
blt.s Obj5D_Container_Floor_End
bclr #0,Obj5D_status2(a1)
bset #2,Obj5D_status2(a1)
bra.s Obj5D_Container_Floor_End
; ===========================================================================
Obj5D_Container_Floor:
btst #7,status(a0)
bne.w JmpTo51_DeleteObject
movea.l Obj5D_parent(a0),a1 ; a1=object
movea.l Obj5D_parent(a1),a1
btst #5,Obj5D_status2(a1)
beq.s Obj5D_Container_Floor_End
cmpi.b #9,anim(a0)
bne.s Obj5D_Container_Floor_End
move.b #$A,anim(a0)
Obj5D_Container_Floor_End:
movea.l Obj5D_parent(a0),a1 ; a1=object
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
move.b render_flags(a1),render_flags(a0)
move.b status(a1),status(a0)
lea (Ani_Obj5D_Dripper).l,a1
jsr (AnimateSprite).l
jmp (DisplaySprite).l
; ===========================================================================
Obj5D_Container_Floor2:
btst #7,status(a0)
bne.w JmpTo51_DeleteObject
subq.w #1,Obj5D_timer2(a0)
beq.w JmpTo51_DeleteObject
bra.s Obj5D_Container_Floor_End
; ===========================================================================
Obj5D_Gunk:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj5D_Gunk_States(pc,d0.w),d1
jmp Obj5D_Gunk_States(pc,d1.w)
; ===========================================================================
Obj5D_Gunk_States: offsetTable
offsetTableEntry.w Obj5D_Gunk_Init ; 0
offsetTableEntry.w Obj5D_Gunk_Main ; 2
offsetTableEntry.w Obj5D_Gunk_Droplets ; 4
offsetTableEntry.w Obj5D_Gunk_6 ; 6
offsetTableEntry.w Obj5D_Gunk_8 ; 8
; ===========================================================================
Obj5D_Gunk_Init:
addq.b #2,routine_secondary(a0) ; => Obj5D_Gunk_Main
move.b #$20,y_radius(a0)
move.b #$19,anim(a0)
move.w #0,y_vel(a0)
movea.l Obj5D_parent(a0),a1 ; a1=object
movea.l Obj5D_parent(a1),a1
btst #2,Obj5D_status(a1)
beq.s Obj5D_Gunk_Main
bclr #2,Obj5D_status(a1)
move.b #6,routine_secondary(a0) ; => Obj5D_Gunk_6
move.w #9,Obj5D_timer2(a0)
Obj5D_Gunk_Main:
jsrto (ObjectMoveAndFall).l, JmpTo3_ObjectMoveAndFall
jsr (ObjCheckFloorDist).l
tst.w d1
bmi.s + ; branch, if hit the floor
cmpi.w #$518,y_pos(a0)
bge.s Obj5D_Gunk_OffScreen ; branch, if fallen off screen
lea (Ani_Obj5D_Dripper).l,a1
jsr (AnimateSprite).l
jmp (DisplaySprite).l
; ===========================================================================
+
add.w d1,y_pos(a0)
movea.l Obj5D_parent(a0),a1 ; a1=object
movea.l Obj5D_parent(a1),a1
bset #2,Obj5D_status2(a1)
bset #4,Obj5D_status2(a1)
move.b #2,routine_secondary(a1)
addq.b #2,routine_secondary(a0) ; => Obj5D_Gunk_Droplets
move.b #0,subtype(a0)
move.w #SndID_MegaMackDrop,d0
jsrto (PlaySound).l, JmpTo5_PlaySound
jmp (DisplaySprite).l
; ===========================================================================
Obj5D_Gunk_OffScreen:
movea.l Obj5D_parent(a0),a1 ; a1=object
movea.l Obj5D_parent(a1),a1
bset #2,Obj5D_status2(a1)
bset #4,Obj5D_status2(a1)
move.b #2,routine_secondary(a1)
bra.w JmpTo51_DeleteObject
; ===========================================================================
Obj5D_Gunk_6:
subi_.w #1,Obj5D_timer2(a0)
bpl.s +
move.b #2,priority(a0)
move.b #$25,mapping_frame(a0)
movea.l Obj5D_parent(a0),a1 ; a1=object
movea.l Obj5D_parent(a1),a1 ; a1=object
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
addq.b #2,routine_secondary(a0) ; => Obj5D_Gunk_8
move.b #8,anim_frame_duration(a0)
bra.s Obj5D_Gunk_8
; ===========================================================================
+
jsrto (ObjectMove).l, JmpTo23_ObjectMove
lea (Ani_Obj5D_Dripper).l,a1
jsr (AnimateSprite).l
jmp (DisplaySprite).l
; ===========================================================================
Obj5D_Gunk_8:
subi_.b #1,anim_frame_duration(a0)
bpl.s +
addi_.b #1,mapping_frame(a0)
move.b #8,anim_frame_duration(a0)
cmpi.b #$27,mapping_frame(a0)
bgt.w Obj5D_Gunk_OffScreen
blt.s +
addi.b #$C,anim_frame_duration(a0)
+
movea.l Obj5D_parent(a0),a1 ; a1=object
movea.l Obj5D_parent(a1),a1 ; a1=object
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
jmp (DisplaySprite).l
; ===========================================================================
Obj5D_Gunk_Droplets:
moveq #0,d0
move.b subtype(a0),d0
bne.w Obj5D_Gunk_Droplets_Move
addi.w #$18,y_pos(a0)
addi.w #$C,x_pos(a0)
btst #0,render_flags(a0)
beq.s +
subi.w #$18,x_pos(a0)
+
move.b #4,y_radius(a0)
move.b #4,x_radius(a0)
addq.b #1,subtype(a0)
move.b #9,mapping_frame(a0)
move.w y_vel(a0),d0
lsr.w #1,d0
neg.w d0
move.w d0,y_vel(a0)
jsr (RandomNumber).l
asr.w #6,d0
bmi.s +
addi.w #$200,d0
+
addi.w #-$100,d0
move.w d0,x_vel(a0)
move.b #0,collision_flags(a0)
moveq #3,d3
Obj5D_Gunk_Droplets_Loop:
jsr (SingleObjLoad2).l
bne.w BranchTo_JmpTo34_DisplaySprite
_move.b #ObjID_CPZBoss,id(a1) ; load obj5D
move.l a0,Obj5D_parent(a1)
move.l #Obj5D_MapUnc_2EADC,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_CPZBoss,3,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #2,priority(a1)
move.l x_pos(a0),x_pos(a1)
move.l y_pos(a0),y_pos(a1)
move.b #4,y_radius(a1)
move.b #4,x_radius(a1)
move.b #9,mapping_frame(a1)
move.b #$C,routine(a1)
move.b #4,routine_secondary(a1)
move.b #1,subtype(a1)
move.w y_vel(a0),y_vel(a1)
move.b collision_flags(a0),collision_flags(a1)
jsr (RandomNumber).l
asr.w #6,d0
bmi.s +
addi.w #$80,d0
+
addi.w #-$80,d0
move.w d0,x_vel(a1)
swap d0
andi.w #$3FF,d0
sub.w d0,y_vel(a1)
dbf d3,Obj5D_Gunk_Droplets_Loop
BranchTo_JmpTo34_DisplaySprite
jmpto (DisplaySprite).l, JmpTo34_DisplaySprite
; ===========================================================================
Obj5D_Gunk_Droplets_Move:
jsrto (ObjectMoveAndFall).l, JmpTo3_ObjectMoveAndFall
jsr (ObjCheckFloorDist).l
tst.w d1
bmi.s +
jmpto (MarkObjGone).l, JmpTo35_MarkObjGone
; ---------------------------------------------------------------------------
+
bra.w JmpTo51_DeleteObject
; ===========================================================================
; a bit of unused/dead code here
add.w d1,y_pos(a0) ; a0=object
move.w y_vel(a0),d0
lsr.w #1,d0
neg.w d0
move.w d0,y_vel(a0)
jmpto (DisplaySprite).l, JmpTo34_DisplaySprite
; ===========================================================================
Obj5D_Robotnik:
movea.l Obj5D_parent(a0),a1 ; a1=object
move.l x_pos(a1),x_pos(a0)
move.l y_pos(a1),y_pos(a0)
move.b status(a1),status(a0)
move.b render_flags(a1),render_flags(a0)
move.b Obj5D_invulnerable_time(a1),d0
cmpi.b #$1F,d0
bne.s +
move.b #2,anim(a0)
+
cmpi.b #4,(MainCharacter+routine).w
beq.s +
cmpi.b #4,(Sidekick+routine).w
bne.s Obj5D_Robotnik_End
+
move.b #3,anim(a0)
Obj5D_Robotnik_End:
lea (Ani_obj5D_b).l,a1
jsr (AnimateSprite).l
jmp (DisplaySprite).l
; ===========================================================================
byte_2E94A:
dc.b 0
dc.b $FF ; 1
dc.b 1 ; 2
dc.b 0 ; 3
; ===========================================================================
Obj5D_Flame:
btst #7,status(a0)
bne.s loc_2E9A8
movea.l Obj5D_parent(a0),a1 ; a1=object
move.l x_pos(a1),x_pos(a0)
move.l y_pos(a1),y_pos(a0)
move.b status(a1),status(a0)
move.b render_flags(a1),render_flags(a0)
subq.b #1,anim_frame_duration(a0)
bpl.s loc_2E996
move.b #1,anim_frame_duration(a0)
move.b Obj5D_timer2(a0),d0
addq.b #1,d0
cmpi.b #2,d0
ble.s +
moveq #0,d0
+
move.b byte_2E94A(pc,d0.w),mapping_frame(a0)
move.b d0,Obj5D_timer2(a0)
loc_2E996:
cmpi.b #-1,mapping_frame(a0)
bne.w JmpTo34_DisplaySprite
move.b #0,mapping_frame(a0)
rts
; ===========================================================================
loc_2E9A8:
movea.l Obj5D_parent(a0),a1 ; a1=object
btst #6,Obj5D_status2(a1)
bne.s +
rts
; ===========================================================================
+
addq.b #2,routine_secondary(a0)
move.l #Obj5D_MapUnc_2EEA0,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_EggpodJets_1,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo60_Adjust2PArtPointer
move.b #0,mapping_frame(a0)
move.b #5,anim_frame_duration(a0)
movea.l Obj5D_parent(a0),a1 ; a1=object
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
addi_.w #4,y_pos(a0)
subi.w #$28,x_pos(a0)
rts
; ===========================================================================
Obj5D_1A:
subq.b #1,anim_frame_duration(a0)
bpl.s BranchTo2_JmpTo34_DisplaySprite
move.b #5,anim_frame_duration(a0)
addq.b #1,mapping_frame(a0)
cmpi.b #4,mapping_frame(a0)
bne.w BranchTo2_JmpTo34_DisplaySprite
move.b #0,mapping_frame(a0)
movea.l Obj5D_parent(a0),a1 ; a1=object
move.b id(a1),d0
beq.w JmpTo51_DeleteObject ; branch, if parent object is gone
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
addi_.w #4,y_pos(a0)
subi.w #$28,x_pos(a0)
BranchTo2_JmpTo34_DisplaySprite
jmpto (DisplaySprite).l, JmpTo34_DisplaySprite
; ===========================================================================
; animation script
; off_2EA3C:
Ani_Obj5D_Dripper: offsetTable
offsetTableEntry.w byte_2EA72 ; 0
offsetTableEntry.w byte_2EA75 ; 1
offsetTableEntry.w byte_2EA78 ; 2
offsetTableEntry.w byte_2EA7D ; 3
offsetTableEntry.w byte_2EA81 ; 4
offsetTableEntry.w byte_2EA88 ; 5
offsetTableEntry.w byte_2EA8B ; 6
offsetTableEntry.w byte_2EA8E ; 7
offsetTableEntry.w byte_2EA91 ; 8
offsetTableEntry.w byte_2EA94 ; 9
offsetTableEntry.w byte_2EA97 ; $A
offsetTableEntry.w byte_2EAA3 ; $B
offsetTableEntry.w byte_2EAAE ; $C
offsetTableEntry.w byte_2EAB1 ; $D
offsetTableEntry.w byte_2EAB4 ; $E
offsetTableEntry.w byte_2EAB7 ; $F
offsetTableEntry.w byte_2EABA ; $10
offsetTableEntry.w byte_2EABD ; $11
offsetTableEntry.w byte_2EAC0 ; $12
offsetTableEntry.w byte_2EAC3 ; $13
offsetTableEntry.w byte_2EAC6 ; $14
offsetTableEntry.w byte_2EAC9 ; $15
offsetTableEntry.w byte_2EACC ; $16
offsetTableEntry.w byte_2EACF ; $17
offsetTableEntry.w byte_2EAD2 ; $18
offsetTableEntry.w byte_2EAD5 ; $19
offsetTableEntry.w byte_2EAD9 ; $1A
byte_2EA72: dc.b $F, 0,$FF
rev02even
byte_2EA75: dc.b $F, 1,$FF
rev02even
byte_2EA78: dc.b 5, 2, 3, 2,$FF
rev02even
byte_2EA7D: dc.b 5, 2, 3,$FF
rev02even
byte_2EA81: dc.b 2, 4, 5, 6, 7, 8,$FF
rev02even
byte_2EA88: dc.b 3, 9,$FF
rev02even
byte_2EA8B: dc.b $F, $A,$FF
rev02even
byte_2EA8E: dc.b $F,$1C,$FF
rev02even
byte_2EA91: dc.b $F,$1E,$FF
rev02even
byte_2EA94: dc.b $F, $B,$FF
rev02even
byte_2EA97: dc.b 3, $C, $C, $D, $D, $D, $D, $D, $C, $C,$FD, 9
rev02even
byte_2EAA3: dc.b 3, $E, $E, $F, $F, $F, $F, $F, $E, $E,$FF
rev02even
byte_2EAAE: dc.b $F,$10,$FF
rev02even
byte_2EAB1: dc.b $F,$11,$FF
rev02even
byte_2EAB4: dc.b $F,$12,$FF
rev02even
byte_2EAB7: dc.b $F,$13,$FF
rev02even
byte_2EABA: dc.b $F,$14,$FF
rev02even
byte_2EABD: dc.b $F,$15,$FF
rev02even
byte_2EAC0: dc.b $F,$16,$FF
rev02even
byte_2EAC3: dc.b $F,$17,$FF
rev02even
byte_2EAC6: dc.b $F,$18,$FF
rev02even
byte_2EAC9: dc.b $F,$19,$FF
rev02even
byte_2EACC: dc.b $F,$1A,$FF
rev02even
byte_2EACF: dc.b $F,$1B,$FF
rev02even
byte_2EAD2: dc.b $F,$1C,$FF
rev02even
byte_2EAD5: dc.b 1,$1D,$1F,$FF
rev02even
byte_2EAD9: dc.b $F,$1E,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings - uses ArtNem_CPZBoss
; ----------------------------------------------------------------------------
Obj5D_MapUnc_2EADC: BINCLUDE "mappings/sprite/obj5D_a.bin"
; animation script
; off_2ED5C:
Ani_obj5D_b: offsetTable
offsetTableEntry.w byte_2ED66 ; 0
offsetTableEntry.w byte_2ED69 ; 1
offsetTableEntry.w byte_2ED6D ; 2
offsetTableEntry.w byte_2ED76 ; 3
offsetTableEntry.w byte_2ED7F ; 4
byte_2ED66: dc.b $F, 0,$FF
rev02even
byte_2ED69: dc.b 7, 1, 2,$FF
rev02even
byte_2ED6D: dc.b 7, 5, 5, 5, 5, 5, 5,$FD, 1
rev02even
byte_2ED76: dc.b 7, 3, 4, 3, 4, 3, 4,$FD, 1
rev02even
byte_2ED7F: dc.b $F, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,$FD, 1
even
; ----------------------------------------------------------------------------
; sprite mappings - uses ArtNem_Eggpod
; ----------------------------------------------------------------------------
Obj5D_MapUnc_2ED8C: BINCLUDE "mappings/sprite/obj5D_b.bin"
; ----------------------------------------------------------------------------
; sprite mappings - uses ArtNem_EggpodJets
; ----------------------------------------------------------------------------
Obj5D_MapUnc_2EE88: BINCLUDE "mappings/sprite/obj5D_c.bin"
; ----------------------------------------------------------------------------
; sprite mappings - uses ArtNem_BossSmoke
; ----------------------------------------------------------------------------
Obj5D_MapUnc_2EEA0: BINCLUDE "mappings/sprite/obj5D_d.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo34_DisplaySprite
jmp (DisplaySprite).l
JmpTo51_DeleteObject
jmp (DeleteObject).l
JmpTo35_MarkObjGone
jmp (MarkObjGone).l
JmpTo5_PlaySound
jmp (PlaySound).l
JmpTo8_Adjust2PArtPointer2
jmp (Adjust2PArtPointer2).l
JmpTo5_LoadPLC
jmp (LoadPLC).l
JmpTo2_AddPoints
jmp (AddPoints).l
JmpTo60_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo_PlayLevelMusic
jmp (PlayLevelMusic).l
JmpTo_LoadPLC_AnimalExplosion
jmp (LoadPLC_AnimalExplosion).l
JmpTo3_ObjectMoveAndFall
jmp (ObjectMoveAndFall).l
; loc_2EF12:
JmpTo23_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 56 - EHZ boss
; the bottom part of the vehicle with the ability to fly is the parent object
; ----------------------------------------------------------------------------
; Sprite_2EF18:
Obj56:
moveq #0,d0
move.b routine(a0),d0
move.w Obj56_Index(pc,d0.w),d1
jmp Obj56_Index(pc,d1.w)
; ===========================================================================
; off_2EF26:
Obj56_Index: offsetTable
offsetTableEntry.w Obj56_Init ; 0 - Init
offsetTableEntry.w loc_2F262 ; 2 - Flying vehicle, bottom = main object
offsetTableEntry.w loc_2F54E ; 4 - Propeller normal
offsetTableEntry.w loc_2F5F6 ; 6 - Vehicle on ground
offsetTableEntry.w loc_2F664 ; 8 - Wheels
offsetTableEntry.w loc_2F7F4 ; A - Spike
offsetTableEntry.w loc_2F52A ; C - Propeller after defeat
offsetTableEntry.w loc_2F8DA ; E - Flying vehicle, top
; ===========================================================================
; #7,status(ax) set via collision response routine (Touch_Enemy_Part2)
; when after a hit collision_property(ax) = hitcount has reached zero
; objoff_2A(ax) used as timer (countdown)
; objoff_2C(ax) tertiary rountine counter
; #0,objoff_2D(ax) set when robotnik is on ground
; #1,objoff_2D(ax) set when robotnik is active (moving back & forth)
; #2,objoff_2D(ax) set when robotnik is flying off after being defeated
; #3,objoff_2D(ax) flag to separate spike from vehicle
; objoff_2E(ax) y_position of wheels
; objoff_34(ax) parent object
; objoff_3C(ax) timer after defeat
; loc_2EF36:
Obj56_Init:
move.l #Obj56_MapUnc_2FAF8,mappings(a0) ; main object
move.w #make_art_tile(ArtTile_ArtNem_Eggpod_1,1,0),art_tile(a0) ; vehicle with ability to fly, bottom part
ori.b #4,render_flags(a0)
move.b #$81,subtype(a0)
move.w #$29D0,x_pos(a0)
move.w #$426,y_pos(a0)
move.b #$20,width_pixels(a0)
move.b #$14,y_radius(a0)
move.b #4,priority(a0)
move.b #$F,collision_flags(a0)
move.b #8,collision_property(a0) ; hitcount
addq.b #2,routine(a0)
move.w x_pos(a0),objoff_30(a0)
move.w y_pos(a0),objoff_38(a0)
jsrto (Adjust2PArtPointer).l, JmpTo61_Adjust2PArtPointer
jsr (SingleObjLoad2).l ; vehicle with ability to fly, top part
bne.w +
_move.b #ObjID_EHZBoss,id(a1) ; load obj56
move.l a0,objoff_34(a1) ; link top and bottom to each other
move.l a1,objoff_34(a0) ; i.e. addresses for cross references
move.l #Obj56_MapUnc_2FAF8,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_Eggpod_1,0,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #4,priority(a1)
move.l x_pos(a0),x_pos(a1)
move.l y_pos(a0),y_pos(a1)
move.b #$E,routine(a1)
move.b #1,anim(a1) ; normal animation
move.b render_flags(a0),render_flags(a1)
+
jsr (SingleObjLoad2).l ; Vehicle on ground
bne.s +
_move.b #ObjID_EHZBoss,id(a1) ; load obj56
move.l a0,objoff_34(a1) ; linked to main object
move.l #Obj56_MapUnc_2FA58,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_EHZBoss,0,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo9_Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #$30,width_pixels(a1)
move.b #$10,y_radius(a1)
move.b #3,priority(a1)
move.w #$2AF0,x_pos(a1)
move.l y_pos(a0),y_pos(a1)
move.b #6,routine(a1)
+
bsr.w loc_2F098
subi_.w #8,objoff_38(a0)
move.w #$2AF0,x_pos(a0)
move.w #$2F8,y_pos(a0)
jsr (SingleObjLoad2).l ; propeller normal
bne.s + ; rts
_move.b #ObjID_EHZBoss,id(a1) ; load obj56
move.l a0,objoff_34(a1) ; linked to main object
move.l #Obj56_MapUnc_2F970,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_EggChoppers,1,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo9_Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #$40,width_pixels(a1)
move.b #3,priority(a1)
move.l x_pos(a0),x_pos(a1)
move.l y_pos(a0),y_pos(a1)
move.w #$1E,objoff_2A(a1)
move.b #4,routine(a1)
+
rts
; ---------------------------------------------------------------------------
loc_2F098:
jsr (SingleObjLoad2).l ; first foreground wheel
bne.s +
_move.b #ObjID_EHZBoss,id(a1) ; load obj56
move.l a0,objoff_34(a1) ; linked to main object
move.l #Obj56_MapUnc_2FA58,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_EHZBoss,1,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo9_Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #$10,width_pixels(a1)
move.b #2,priority(a1)
move.b #$10,y_radius(a1)
move.b #$10,x_radius(a1)
move.w #$2AF0,x_pos(a1)
move.l y_pos(a0),y_pos(a1)
addi.w #$1C,x_pos(a1)
addi.w #$C,y_pos(a1)
move.b #8,routine(a1)
move.b #4,mapping_frame(a1)
move.b #1,anim(a1)
move.w #$A,objoff_2A(a1)
move.b #0,subtype(a1)
+
jsr (SingleObjLoad2).l ; second foreground wheel
bne.s +
_move.b #ObjID_EHZBoss,id(a1) ; load obj56
move.l a0,objoff_34(a1) ; linked to main object
move.l #Obj56_MapUnc_2FA58,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_EHZBoss,1,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo9_Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #$10,width_pixels(a1)
move.b #2,priority(a1)
move.b #$10,y_radius(a1)
move.b #$10,x_radius(a1)
move.w #$2AF0,x_pos(a1)
move.l y_pos(a0),y_pos(a1)
addi.w #-$C,x_pos(a1)
addi.w #$C,y_pos(a1)
move.b #8,routine(a1)
move.b #4,mapping_frame(a1)
move.b #1,anim(a1)
move.w #$A,objoff_2A(a1)
move.b #1,subtype(a1)
+
jsr (SingleObjLoad2).l ; background wheel
bne.s +
_move.b #ObjID_EHZBoss,id(a1) ; load obj56
move.l a0,objoff_34(a1) ; linked to main object
move.l #Obj56_MapUnc_2FA58,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_EHZBoss,1,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo9_Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #$10,width_pixels(a1)
move.b #3,priority(a1)
move.b #$10,y_radius(a1)
move.b #$10,x_radius(a1)
move.w #$2AF0,x_pos(a1)
move.l y_pos(a0),y_pos(a1)
addi.w #-$2C,x_pos(a1)
addi.w #$C,y_pos(a1)
move.b #8,routine(a1)
move.b #6,mapping_frame(a1)
move.b #2,anim(a1)
move.w #$A,objoff_2A(a1)
move.b #2,subtype(a1)
+
jsr (SingleObjLoad2).l ; Spike
bne.s +
_move.b #ObjID_EHZBoss,id(a1) ; load obj56
move.l a0,objoff_34(a1) ; linked to main object
move.l #Obj56_MapUnc_2FA58,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_EHZBoss,1,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo9_Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #2,priority(a1)
move.w #$2AF0,x_pos(a1)
move.l y_pos(a0),y_pos(a1)
addi.w #-$36,x_pos(a1)
addi_.w #8,y_pos(a1)
move.b #$A,routine(a1)
move.b #1,mapping_frame(a1)
move.b #0,anim(a1)
+
rts
; ===========================================================================
loc_2F262: ; Obj56_VehicleMain:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_2F270(pc,d0.w),d1
jmp off_2F270(pc,d1.w)
; ---------------------------------------------------------------------------
off_2F270: offsetTable
offsetTableEntry.w loc_2F27C ; 0 - approaching diagonally
offsetTableEntry.w loc_2F2A8 ; 2 - final approaching stage (vertically/waiting)
offsetTableEntry.w loc_2F304 ; 4 - moving back and forth
offsetTableEntry.w loc_2F336 ; 6 - boss defeated, falling/lying on ground
offsetTableEntry.w loc_2F374 ; 8 - boss idle for $C frames
offsetTableEntry.w loc_2F38A ; A - flying off, moving camera
; ===========================================================================
loc_2F27C: ; Obj56_VehicleMain_Sub0:
move.b #0,collision_flags(a0)
cmpi.w #$29D0,x_pos(a0) ; reached the point to unite with bottom vehicle?
ble.s loc_2F29A
subi_.w #1,x_pos(a0)
addi_.w #1,y_pos(a0) ; move diagonally down
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F29A:
move.w #$29D0,x_pos(a0)
addq.b #2,routine_secondary(a0) ; next routine
bra.w JmpTo35_DisplaySprite
; ===========================================================================
loc_2F2A8: ; Obj56_VehicleMain_Sub2:
moveq #0,d0
move.b objoff_2C(a0),d0 ; tertiary routine
move.w off_2F2B6(pc,d0.w),d1
jmp off_2F2B6(pc,d1.w)
; ---------------------------------------------------------------------------
off_2F2B6: offsetTable
offsetTableEntry.w loc_2F2BA ; 0 - moving down to ground vehicle vertically
offsetTableEntry.w loc_2F2E0 ; 2 - not moving, delay until activation
; ---------------------------------------------------------------------------
loc_2F2BA: ; Obj56_VehicleMain_Sub2_0:
cmpi.w #$41E,y_pos(a0)
bge.s loc_2F2CC
addi_.w #1,y_pos(a0) ; move vertically (down)
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F2CC:
addq.b #2,objoff_2C(a0) ; tertiary routine
bset #0,objoff_2D(a0) ; robotnik on ground (relevant for propeller)
move.w #$3C,objoff_2A(a0) ; timer for standing still
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F2E0: ; Obj56_VehicleMain_Sub2_2:
subi_.w #1,objoff_2A(a0) ; timer
bpl.w JmpTo35_DisplaySprite
move.w #-$200,x_vel(a0)
addq.b #2,routine_secondary(a0)
move.b #$F,collision_flags(a0)
bset #1,objoff_2D(a0) ; boss now active and moving
bra.w JmpTo35_DisplaySprite
; ===========================================================================
loc_2F304: ; Obj56_VehicleMain_Sub4:
bsr.w loc_2F4A6 ; routine to handle hits
bsr.w loc_2F484 ; position check, sets direction
move.w objoff_2E(a0),d0 ; y_position of wheels
lsr.w #1,d0
subi.w #$14,d0
move.w d0,y_pos(a0) ; set y_pos depending on wheels
move.w #0,objoff_2E(a0)
move.l x_pos(a0),d2
move.w x_vel(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d2
move.l d2,x_pos(a0) ; set x_pos depening on velocity
bra.w JmpTo35_DisplaySprite
; ===========================================================================
loc_2F336: ; Obj56_VehicleMain_Sub6:
subq.w #1,objoff_3C(a0) ; timer set after defeat
bmi.s loc_2F35C ; if countdown finished
bsr.w Boss_LoadExplosion
jsrto (ObjectMoveAndFall).l, JmpTo4_ObjectMoveAndFall
jsrto (ObjCheckFloorDist).l, JmpTo3_ObjCheckFloorDist
tst.w d1
bpl.w JmpTo35_DisplaySprite
add.w d1,y_pos(a0)
move.w #0,y_vel(a0) ; set to ground and stand still
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F35C:
clr.w x_vel(a0)
addq.b #2,routine_secondary(a0)
move.w #-$26,objoff_3C(a0)
move.w #$C,objoff_2A(a0)
bra.w JmpTo35_DisplaySprite
; ===========================================================================
loc_2F374: ; Obj56_VehicleMain_Sub8:
subq.w #1,objoff_2A(a0) ; timer
bpl.w JmpTo35_DisplaySprite
addq.b #2,routine_secondary(a0)
move.b #0,objoff_2C(a0) ; tertiary routine
bra.w JmpTo35_DisplaySprite
; ===========================================================================
loc_2F38A: ; Obj56_VehicleMain_SubA:
moveq #0,d0
move.b objoff_2C(a0),d0 ; tertiary routine
move.w off_2F39C(pc,d0.w),d1
jsr off_2F39C(pc,d1.w)
bra.w JmpTo35_DisplaySprite
; ===========================================================================
off_2F39C: offsetTable
offsetTableEntry.w loc_2F3A2 ; 0 - initialize propellor
offsetTableEntry.w loc_2F424 ; 2 - waiting
offsetTableEntry.w loc_2F442 ; 4 - flying off
; ===========================================================================
loc_2F3A2: ; Obj56_VehicleMain_SubA_0:
bclr #0,objoff_2D(a0) ; robotnik off ground
jsrto (SingleObjLoad2).l, JmpTo21_SingleObjLoad2 ; reload propeller after defeat
bne.w + ; rts
_move.b #ObjID_EHZBoss,id(a1) ; load obj56
move.l a0,objoff_34(a1) ; linked to main object
move.l #Obj56_MapUnc_2F970,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_EggChoppers,1,0),art_tile(a1)
jsrto (Adjust2PArtPointer2).l, JmpTo9_Adjust2PArtPointer2
move.b #4,render_flags(a1)
move.b #$20,width_pixels(a1)
move.b #3,priority(a1)
move.l x_pos(a0),x_pos(a1)
move.l y_pos(a0),y_pos(a1)
addi.w #$C,y_pos(a1)
move.b status(a0),status(a1)
move.b render_flags(a0),render_flags(a1)
move.b #$C,routine(a1)
move.b #2,anim(a1)
move.w #$10,objoff_2A(a1) ; timer
move.w #$32,objoff_2A(a0) ; timer
addq.b #2,objoff_2C(a0) ; tertiary routine - increase
jsrto (PlayLevelMusic).l, JmpTo2_PlayLevelMusic ; play level Music
move.b #1,(Boss_defeated_flag).w
+
rts
; ===========================================================================
loc_2F424: ; Obj56_VehicleMain_SubA_2:
subi_.w #1,objoff_2A(a0) ; timer
bpl.s + ; rts
bset #2,objoff_2D(a0) ; robotnik flying off
move.w #$60,objoff_2A(a0) ; timer
addq.b #2,objoff_2C(a0) ; tertiary routine
jsrto (LoadPLC_AnimalExplosion).l, JmpTo2_LoadPLC_AnimalExplosion ; PLC_Explosion
+
rts
; ===========================================================================
loc_2F442: ; Obj56_VehicleMain_SubA_4:
subi_.w #1,objoff_2A(a0) ; timer
bpl.s loc_2F45C
bset #0,status(a0)
bset #0,render_flags(a0)
addq.w #6,x_pos(a0)
bra.s loc_2F460
; ===========================================================================
loc_2F45C:
subq.w #1,y_pos(a0)
loc_2F460:
cmpi.w #$2AB0,(Camera_Max_X_pos).w
bhs.s loc_2F46E
addq.w #2,(Camera_Max_X_pos).w
bra.s return_2F482
; ===========================================================================
loc_2F46E:
tst.b render_flags(a0)
bmi.s return_2F482
addq.w #4,sp
movea.l objoff_34(a0),a1 ; parent address (vehicle)
jsrto (DeleteObject2).l, JmpTo5_DeleteObject2
jmpto (DeleteObject).l, JmpTo52_DeleteObject
; ===========================================================================
return_2F482:
rts
; ===========================================================================
loc_2F484: ; shared routine, checks positions and sets direction
move.w x_pos(a0),d0
cmpi.w #$28A0,d0 ; beyond left boundary?
ble.s loc_2F494
cmpi.w #$2B08,d0
blt.s return_2F4A4 ; beyond right boundary?
loc_2F494: ; beyond boundary
bchg #0,status(a0) ; change direction
bchg #0,render_flags(a0) ; mirror sprite
neg.w x_vel(a0) ; change direction of velocity
return_2F4A4:
rts
; ===========================================================================
loc_2F4A6: ; routine to handle hits
cmpi.b #6,routine_secondary(a0) ; is only called when value is 4?
bhs.s return_2F4EC ; thus unnecessary? (return if greater or equal than 6)
tst.b status(a0)
bmi.s loc_2F4EE ; sonic has just defeated the boss (i.e. bit 7 set)
tst.b collision_flags(a0) ; set to 0 when boss was hit by Touch_Enemy_Part2
bne.s return_2F4EC ; not 0, i.e. boss not hit
tst.b objoff_3E(a0)
bne.s loc_2F4D0 ; boss already invincibile
move.b #$20,objoff_3E(a0) ; boss invincibility timer
move.w #SndID_BossHit,d0
jsr (PlaySound).l ; play boss hit sound
loc_2F4D0:
lea (Normal_palette_line2+2).w,a1
moveq #0,d0 ; black
tst.w (a1)
bne.s loc_2F4DE ; already not black (i.e. white)?
move.w #$EEE,d0 ; white
loc_2F4DE:
move.w d0,(a1) ; set respective color
subq.b #1,objoff_3E(a0) ; decrease boss invincibility timer
bne.s return_2F4EC
move.b #$F,collision_flags(a0) ; if invincibility ended, allow collision again
return_2F4EC:
rts
; ===========================================================================
loc_2F4EE: ; boss defeated
moveq #100,d0
jsrto (AddPoints).l, JmpTo3_AddPoints ; add 1000 points, reward for defeating boss
move.b #6,routine_secondary(a0)
move.w #0,x_vel(a0)
move.w #-$180,y_vel(a0)
move.w #$B3,objoff_3C(a0) ; timer
bset #3,objoff_2D(a0) ; flag to separate spike from vehicle
movea.l objoff_34(a0),a1 ; address top part
move.b #4,anim(a1) ; flying off animation
move.b #6,mapping_frame(a1)
moveq #PLCID_Capsule,d0
jmpto (LoadPLC).l, JmpTo6_LoadPLC ; load egg prison
; ===========================================================================
rts
; ===========================================================================
loc_2F52A: ; Obj56_PropellerReloaded: ; Propeller after defeat
subi_.w #1,y_pos(a0) ; move up
subi_.w #1,objoff_2A(a0) ; decrease timer
bpl.w JmpTo35_DisplaySprite
move.b #4,routine(a0) ; Propeller normal
lea (Ani_obj56_a).l,a1
jsrto (AnimateSprite).l, JmpTo17_AnimateSprite
bra.w JmpTo35_DisplaySprite
; ===========================================================================
loc_2F54E: ; Obj56_Propeller: ; Propeller normal
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_2F55C(pc,d0.w),d1
jmp off_2F55C(pc,d1.w)
; ---------------------------------------------------------------------------
off_2F55C: offsetTable
offsetTableEntry.w loc_2F560 ; 0 - robotnik in air
offsetTableEntry.w loc_2F5C6 ; 2 - robotnik on ground
; ---------------------------------------------------------------------------
loc_2F560: ; Obj56_Propeller_Sub0
movea.l objoff_34(a0),a1 ; parent address (vehicle)
cmpi.b #ObjID_EHZBoss,id(a1)
bne.w JmpTo52_DeleteObject ; if boss non-existant
btst #0,objoff_2D(a1) ; is robotnik on ground?
beq.s loc_2F58E ; if not, branch
move.b #1,anim(a0)
move.w #$18,objoff_2A(a0) ; timer until deletion
addq.b #2,routine_secondary(a0)
move.b #MusID_StopSFX,d0
jsrto (PlaySound).l, JmpTo6_PlaySound
bra.s loc_2F5A0
; ---------------------------------------------------------------------------
loc_2F58E: ; not on ground
move.b (Vint_runcount+3).w,d0
andi.b #$1F,d0
bne.s loc_2F5A0
move.b #SndID_Helicopter,d0
jsrto (PlaySound).l, JmpTo6_PlaySound
loc_2F5A0:
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
move.b status(a1),status(a0)
move.b render_flags(a1),render_flags(a0)
lea (Ani_obj56_a).l,a1
jsrto (AnimateSprite).l, JmpTo17_AnimateSprite
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F5C6: ; Obj56_Propeller_Sub2
subi_.w #1,objoff_2A(a0) ; timer
bpl.s loc_2F5E8
cmpi.w #-$10,objoff_2A(a0)
ble.w JmpTo52_DeleteObject
move.b #4,priority(a0)
addi_.w #1,y_pos(a0) ; move down
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F5E8:
lea (Ani_obj56_a).l,a1
jsrto (AnimateSprite).l, JmpTo17_AnimateSprite
bra.w JmpTo35_DisplaySprite
; ===========================================================================
loc_2F5F6: ; Obj56_GroundVehicle:
tst.b routine_secondary(a0)
bne.s loc_2F626
; Obj56_GroundVehicle_Sub0:
cmpi.w #$28F0,(Camera_Min_X_pos).w
blo.w JmpTo35_DisplaySprite
cmpi.w #$29D0,x_pos(a0)
ble.s loc_2F618
subi_.w #1,x_pos(a0)
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F618:
move.w #$29D0,x_pos(a0)
addq.b #2,routine_secondary(a0)
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F626: ; Obj56_GroundVehicle_Sub2:
movea.l objoff_34(a0),a1 ; parent address (vehicle)
btst #1,objoff_2D(a1)
beq.w JmpTo35_DisplaySprite ; boss not moving yet (inactive)
btst #2,objoff_2D(a1) ; robotnik flying off flag
bne.w JmpTo35_DisplaySprite
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
addi_.w #8,y_pos(a0)
move.b status(a1),status(a0)
bmi.w JmpTo35_DisplaySprite
move.b render_flags(a1),render_flags(a0)
bra.w JmpTo35_DisplaySprite
; ===========================================================================
loc_2F664: ; Obj56_Wheel:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_2F672(pc,d0.w),d1
jmp off_2F672(pc,d1.w)
; ---------------------------------------------------------------------------
off_2F672: offsetTable
offsetTableEntry.w loc_2F67C ; 0 - wheels moving towards start position
offsetTableEntry.w loc_2F714 ; 2 - standing still (boss inactive)
offsetTableEntry.w loc_2F746 ; 4 - normal mode (boss active)
offsetTableEntry.w loc_2F7A6 ; 6 - inactive while defeat
offsetTableEntry.w loc_2F7D2 ; 8 - wheels bouncing away after defeat
; ---------------------------------------------------------------------------
loc_2F67C: ; Obj56_Wheel_Sub0:
cmpi.w #$28F0,(Camera_Min_X_pos).w
blo.w JmpTo35_DisplaySprite
move.w #$100,y_vel(a0)
cmpi.b #1,subtype(a0) ; wheel number (0-2)
bgt.s loc_2F6B6 ; background wheel
beq.s loc_2F6A6 ; second foreground wheel
; ---------------------------------------------------------------------------
cmpi.w #$29EC,x_pos(a0) ; first foreground wheel
ble.s loc_2F6C6
subi_.w #1,x_pos(a0)
bra.s loc_2F6E8
loc_2F6A6: ; second foreground wheel
cmpi.w #$29C4,x_pos(a0)
ble.s loc_2F6D2
subi_.w #1,x_pos(a0)
bra.s loc_2F6E8
loc_2F6B6: ; background wheel
cmpi.w #$29A4,x_pos(a0)
ble.s loc_2F6DE
subi_.w #1,x_pos(a0)
bra.s loc_2F6E8
; ---------------------------------------------------------------------------
loc_2F6C6: ; first foreground wheel
move.w #$29EC,x_pos(a0)
addq.b #2,routine_secondary(a0)
bra.s loc_2F6E8
loc_2F6D2: ; second foreground wheel
move.w #$29C4,x_pos(a0)
addq.b #2,routine_secondary(a0)
bra.s loc_2F6E8
loc_2F6DE: ; background wheel
move.w #$29A4,x_pos(a0)
addq.b #2,routine_secondary(a0)
; ---------------------------------------------------------------------------
loc_2F6E8: ; routine for all wheels
jsrto (ObjectMoveAndFall).l, JmpTo4_ObjectMoveAndFall
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.s loc_2F6FA
add.w d1,y_pos(a0) ; reset on floor
loc_2F6FA:
tst.b routine_secondary(a0)
beq.s loc_2F706
move.w #-$200,x_vel(a0) ; if reached position, set velocity
loc_2F706:
lea (Ani_obj56_b).l,a1
jsrto (AnimateSprite).l, JmpTo17_AnimateSprite
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F714: ; Obj56_Wheel_Sub2:
movea.l objoff_34(a0),a1 ; parent address (vehicle)
cmpi.b #ObjID_EHZBoss,id(a1)
bne.w JmpTo52_DeleteObject ; if boss non-existant
btst #1,objoff_2D(a1)
beq.w JmpTo35_DisplaySprite ; boss not moving yet (inactive)
addq.b #2,routine_secondary(a0)
cmpi.b #2,priority(a0)
bne.s BranchTo_JmpTo35_DisplaySprite
move.w y_pos(a0),d0
movea.l objoff_34(a0),a1 ; parent address (vehicle)
add.w d0,objoff_2E(a1)
BranchTo_JmpTo35_DisplaySprite
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F746: ; Obj56_Wheel_Sub4:
movea.l objoff_34(a0),a1 ; parent address (vehicle)
cmpi.b #ObjID_EHZBoss,id(a1)
bne.w JmpTo52_DeleteObject ; if boss non-existant
move.b status(a1),status(a0)
move.b render_flags(a1),render_flags(a0)
tst.b status(a0)
bpl.s loc_2F768 ; has sonic just defeated the boss (i.e. bit7 set)?
addq.b #2,routine_secondary(a0) ; if yes, Sub6
loc_2F768:
bsr.w loc_2F484 ; position check, sets direction
jsrto (ObjectMoveAndFall).l, JmpTo4_ObjectMoveAndFall
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.s loc_2F77E
add.w d1,y_pos(a0) ; reset on floor
loc_2F77E:
move.w #$100,y_vel(a0)
cmpi.b #2,priority(a0)
bne.s loc_2F798
move.w y_pos(a0),d0
movea.l objoff_34(a0),a1 ; parent address (vehicle)
add.w d0,objoff_2E(a1)
loc_2F798:
lea (Ani_obj56_b).l,a1
jsrto (AnimateSprite).l, JmpTo17_AnimateSprite
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F7A6: ; Obj56_Wheel_Sub6:
subi_.w #1,objoff_2A(a0) ; timer, initially set to $A (first delay until wheels rolling off)
bpl.w JmpTo35_DisplaySprite
addq.b #2,routine_secondary(a0) ; Sub8
move.w #$A,objoff_2A(a0)
move.w #-$300,y_vel(a0) ; first bounce higher
cmpi.b #2,priority(a0)
beq.w JmpTo35_DisplaySprite
neg.w x_vel(a0) ; into other direction
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F7D2: ; Obj56_Wheel_Sub8:
subq.w #1,objoff_2A(a0) ; timer, initially set to $A (second delay until wheels rolling off)
bpl.w JmpTo35_DisplaySprite
jsrto (ObjectMoveAndFall).l, JmpTo4_ObjectMoveAndFall
jsrto (ObjCheckFloorDist).l, JmpTo3_ObjCheckFloorDist
tst.w d1
bpl.s BranchTo_JmpTo36_MarkObjGone
move.w #-$200,y_vel(a0) ; negative velocity to have bouncing effect
add.w d1,y_pos(a0) ; reset on floor
BranchTo_JmpTo36_MarkObjGone
jmpto (MarkObjGone).l, JmpTo36_MarkObjGone
; ===========================================================================
loc_2F7F4: ; Obj56_Spike:
tst.b routine_secondary(a0)
bne.s loc_2F824
; Obj56_Spike_Sub0:
cmpi.w #$28F0,(Camera_Min_X_pos).w
blo.w JmpTo35_DisplaySprite
cmpi.w #$299A,x_pos(a0)
ble.s loc_2F816
subi_.w #1,x_pos(a0)
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F816:
move.w #$299A,x_pos(a0)
addq.b #2,routine_secondary(a0)
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F824: ; Obj56_Spike_Sub2:
movea.l objoff_34(a0),a1 ; parent address (vehicle)
cmpi.b #ObjID_EHZBoss,id(a1)
bne.w JmpTo52_DeleteObject ; if boss non-existant
btst #3,objoff_2D(a1)
bne.s loc_2F88A ; spike separated from vehicle
bsr.w loc_2F8AA
btst #1,objoff_2D(a1)
beq.w JmpTo35_DisplaySprite ; boss not moving yet (inactive)
move.b #$8B,collision_flags(a0) ; spike still linked to vehicle
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
move.b status(a1),status(a0) ; transfer positions
move.b render_flags(a1),render_flags(a0)
addi.w #$10,y_pos(a0) ; vertical offset
move.w #-$36,d0
btst #0,status(a0)
beq.s loc_2F878
neg.w d0
loc_2F878:
add.w d0,x_pos(a0) ; horizontal offset
lea (Ani_obj56_b).l,a1
jsrto (AnimateSprite).l, JmpTo17_AnimateSprite
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F88A: ; spike separated from vehicle
move.w #-3,d0 ; velocity of spike in pixels/frame
btst #0,status(a0) ; check direction
beq.s loc_2F898
neg.w d0
loc_2F898:
add.w d0,x_pos(a0)
lea (Ani_obj56_b).l,a1
jsrto (AnimateSprite).l, JmpTo17_AnimateSprite
bra.w JmpTo35_DisplaySprite
; ---------------------------------------------------------------------------
loc_2F8AA:
cmpi.b #1,collision_property(a1) ; hit counter, only 1 life left?
beq.s loc_2F8B4
rts
; ---------------------------------------------------------------------------
loc_2F8B4:
move.w x_pos(a0),d0
sub.w (MainCharacter+x_pos).w,d0
bpl.s loc_2F8C8
btst #0,status(a1) ; sonic right from spike
bne.s loc_2F8D2 ; spike facing right
rts
; ---------------------------------------------------------------------------
loc_2F8C8:
btst #0,status(a1) ; sonic left from spike
beq.s loc_2F8D2 ; spike facing left
rts
; ---------------------------------------------------------------------------
loc_2F8D2:
bset #3,objoff_2D(a1) ; flag to separate spike from vehicle
rts
; ===========================================================================
loc_2F8DA: ; Obj56_VehicleTop:
movea.l objoff_34(a0),a1 ; parent address (vehicle)
move.l x_pos(a1),x_pos(a0)
move.l y_pos(a1),y_pos(a0)
move.b status(a1),status(a0) ; update position and status
move.b render_flags(a1),render_flags(a0)
move.b objoff_3E(a1),d0 ; boss invincibility timer
cmpi.b #$1F,d0 ; boss just got hit?
bne.s loc_2F906
move.b #2,anim(a0) ; robotnik animation when hit
loc_2F906:
cmpi.b #4,(MainCharacter+routine).w ; Sonic = ball
beq.s loc_2F916
cmpi.b #4,(Sidekick+routine).w ; Tails = ball
bne.s loc_2F924
loc_2F916:
cmpi.b #2,anim(a0) ; check eggman animation (when hit)
beq.s loc_2F924
move.b #3,anim(a0) ; eggman animation when hurting sonic
loc_2F924:
lea (Ani_obj56_c).l,a1 ; animation script
jsr (AnimateSprite).l
jmp (DisplaySprite).l
; ===========================================================================
; animation script
; off_2F936:
Ani_obj56_a: offsetTable
offsetTableEntry.w byte_2F93C ; 0
offsetTableEntry.w byte_2F940 ; 1
offsetTableEntry.w byte_2F956 ; 2
byte_2F93C:
dc.b 1, 5, 6,$FF
byte_2F940:
dc.b 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0
dc.b 0, 0, 0, 0, 0,$FF; 16
byte_2F956:
dc.b 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 3, 3, 3, 2
dc.b 2, 2, 1, 1, 1, 5, 6,$FE, 2
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj56_MapUnc_2F970: BINCLUDE "mappings/sprite/obj56_a.bin"
; propeller
; 7 frames
; animation script
; off_2FA44:
Ani_obj56_b: offsetTable
offsetTableEntry.w byte_2FA4A ; 0
offsetTableEntry.w byte_2FA4F ; 1
offsetTableEntry.w byte_2FA53 ; 2
byte_2FA4A:
dc.b 5, 1, 2, 3,$FF ; spike
rev02even
byte_2FA4F:
dc.b 1, 4, 5,$FF ; foreground wheel
rev02even
byte_2FA53:
dc.b 1, 6, 7,$FF ; background wheel
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj56_MapUnc_2FA58: BINCLUDE "mappings/sprite/obj56_b.bin"
; ground vehicle
; frame 0 = vehicle itself
; frame 1-3 = spike
; frame 4-5 = foreground wheel
; frame 6-7 = background wheel
; animation script
; off_2FAC8:
Ani_obj56_c: offsetTable
offsetTableEntry.w byte_2FAD2 ; 0
offsetTableEntry.w byte_2FAD5 ; 1
offsetTableEntry.w byte_2FAD9 ; 2
offsetTableEntry.w byte_2FAE2 ; 3
offsetTableEntry.w byte_2FAEB ; 4
byte_2FAD2: dc.b $F, 0,$FF ; bottom
rev02even
byte_2FAD5: dc.b 7, 1, 2,$FF ; top, normal
rev02even
byte_2FAD9: dc.b 7, 5, 5, 5, 5, 5, 5,$FD, 1 ; top, when hit
rev02even
byte_2FAE2: dc.b 7, 3, 4, 3, 4, 3, 4,$FD, 1 ; top, laughter (when hurting sonic)
rev02even
byte_2FAEB: dc.b $F, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,$FD, 1 ; top, when flying off
even ; for top part, after end of special animations always return to normal one ($FD->1)
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj56_MapUnc_2FAF8: BINCLUDE "mappings/sprite/obj56_c.bin"
; flying vehicle
; frame 0 = bottom
; frame 1-2 = top, normal
; frame 3-4 = top, laughter
; frame 5 = top, when hit
; frame 6 = top, when flying off
; ===========================================================================
if ~~removeJmpTos
JmpTo35_DisplaySprite
jmp (DisplaySprite).l
JmpTo52_DeleteObject
jmp (DeleteObject).l
JmpTo36_MarkObjGone
jmp (MarkObjGone).l
JmpTo5_DeleteObject2
jmp (DeleteObject2).l
JmpTo6_PlaySound
jmp (PlaySound).l
JmpTo21_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo17_AnimateSprite
jmp (AnimateSprite).l
JmpTo9_Adjust2PArtPointer2
jmp (Adjust2PArtPointer2).l
JmpTo3_ObjCheckFloorDist
jmp (ObjCheckFloorDist).l
JmpTo6_LoadPLC
jmp (LoadPLC).l
JmpTo3_AddPoints
jmp (AddPoints).l
JmpTo61_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo2_PlayLevelMusic ; play level Music
jmp (PlayLevelMusic).l
JmpTo2_LoadPLC_AnimalExplosion ; PLC_Explosion
jmp (LoadPLC_AnimalExplosion).l
JmpTo4_ObjectMoveAndFall
jmp (ObjectMoveAndFall).l
align 4
else
JmpTo52_DeleteObject
jmp (DeleteObject).l
JmpTo35_DisplaySprite
jmp (DisplaySprite).l
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 52 - HTZ boss
; ----------------------------------------------------------------------------
; Sprite_2FC50:
Obj52:
moveq #0,d0
move.b boss_subtype(a0),d0
move.w Obj52_Index(pc,d0.w),d1
jmp Obj52_Index(pc,d1.w)
; ===========================================================================
; off_2FC5E:
Obj52_Index: offsetTable
offsetTableEntry.w Obj52_Init ; 0
offsetTableEntry.w Obj52_Mobile ; 2
offsetTableEntry.w Obj52_FlameThrower ; 4
offsetTableEntry.w Obj52_LavaBall ; 6
offsetTableEntry.w loc_30210 ; 8
; ===========================================================================
; loc_2FC68:
Obj52_Init:
move.l #Obj52_MapUnc_302BC,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Eggpod_2,0,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #-$70,mainspr_width(a0)
move.b #-$70,mainspr_height(a0)
move.b #4,priority(a0)
move.w #$3040,x_pos(a0)
move.w #$580,y_pos(a0)
move.b #1,objoff_2C(a0)
move.b #1,mainspr_mapframe(a0)
addq.b #2,boss_subtype(a0)
bset #6,render_flags(a0)
move.b #$32,collision_flags(a0)
move.b #8,objoff_32(a0)
move.w #-$E0,(Boss_Y_vel).w
move.w x_pos(a0),(Boss_X_pos).w
move.w y_pos(a0),(Boss_Y_pos).w
clr.b objoff_14(a0)
move.w x_pos(a0),sub2_x_pos(a0)
move.w y_pos(a0),sub2_y_pos(a0)
move.b #2,sub2_mapframe(a0)
bsr.w loc_2FCEA
rts
; ===========================================================================
loc_2FCEA:
lea (Boss_AnimationArray).w,a2
move.b #6,(a2)+
move.b #0,(a2)+
move.b #$10,(a2)+
move.b #0,(a2)+
rts
; ===========================================================================
; loc_2FD00:
Obj52_Mobile:
moveq #0,d0
move.b angle(a0),d0
move.w off_2FD0E(pc,d0.w),d1
jmp off_2FD0E(pc,d1.w)
; ===========================================================================
off_2FD0E: offsetTable
offsetTableEntry.w Obj52_Mobile_Raise ; 0
offsetTableEntry.w Obj52_Mobile_Flamethrower ; 2
offsetTableEntry.w Obj52_Mobile_BeginLower ; 4
offsetTableEntry.w Obj52_Mobile_Lower ; 6
offsetTableEntry.w Obj52_Mobile_Defeated ; 8
; ===========================================================================
; loc_2FD18:
Obj52_Mobile_Raise:
move.b #0,(Boss_CollisionRoutine).w
bsr.w Boss_MoveObject
tst.b objoff_2C(a0)
bne.s loc_2FD32
cmpi.w #$518,(Boss_Y_pos).w
bgt.s loc_2FD50
bra.s loc_2FD3A
; ===========================================================================
loc_2FD32:
cmpi.w #$4FC,(Boss_Y_pos).w
bgt.s loc_2FD50
loc_2FD3A:
move.w #0,(Boss_Y_vel).w
move.b #4,mapping_frame(a0)
addq.b #2,angle(a0)
move.b #$3C,objoff_3E(a0)
loc_2FD50:
move.w (Boss_Y_pos).w,y_pos(a0)
bsr.w loc_300A4
if removeJmpTos
JmpTo36_DisplaySprite
endif
jmpto (DisplaySprite).l, JmpTo36_DisplaySprite
; ===========================================================================
; loc_2FD5E:
Obj52_Mobile_Flamethrower:
subi_.b #1,objoff_3E(a0)
bpl.s Obj52_Mobile_Hover
move.b #1,(Boss_CollisionRoutine).w
move.b #1,mainspr_childsprites(a0)
cmpi.b #-$18,objoff_3E(a0)
bne.s Obj52_Mobile_Hover
jsrto (SingleObjLoad).l, JmpTo13_SingleObjLoad
bne.s loc_2FDAA
_move.b #ObjID_HTZBoss,id(a1) ; load obj52
move.b #4,boss_subtype(a1)
move.b render_flags(a0),render_flags(a1)
andi.b #1,render_flags(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.b #$2F,objoff_3E(a0)
loc_2FDAA:
bsr.w loc_300A4
bsr.w loc_2FEDE
lea (Ani_obj52).l,a1
bsr.w AnimateBoss
jmpto (DisplaySprite).l, JmpTo36_DisplaySprite
; ===========================================================================
; loc_2FDC0:
Obj52_Mobile_Hover:
move.b mapping_frame(a0),d0
jsr (CalcSine).l
asr.w #7,d1
add.w (Boss_Y_pos).w,d1
move.w d1,y_pos(a0)
addq.b #4,mapping_frame(a0)
bra.s loc_2FDAA
; ===========================================================================
; loc_2FDDA:
Obj52_Mobile_BeginLower:
move.b #0,(Boss_CollisionRoutine).w
move.b #0,mainspr_childsprites(a0)
move.b #$10,(Boss_AnimationArray+2).w
move.b #0,(Boss_AnimationArray+3).w
subi_.b #1,objoff_3E(a0)
bne.w Obj52_Mobile_Hover
move.w #$E0,(Boss_Y_vel).w
addq.b #2,angle(a0)
bsr.w loc_2FEDE
jmpto (DisplaySprite).l, JmpTo36_DisplaySprite
; ===========================================================================
; loc_2FE0E:
Obj52_Mobile_Lower:
bsr.w Boss_MoveObject
tst.b objoff_2C(a0)
bne.s loc_2FE22
cmpi.w #$538,(Boss_Y_pos).w
blt.s loc_2FE58
bra.s Obj52_CreateLavaBall
; ===========================================================================
loc_2FE22:
cmpi.w #$548,(Boss_Y_pos).w
blt.s loc_2FE58
; loc_2FE2A
Obj52_CreateLavaBall:
tst.b objoff_38(a0)
bne.s loc_2FE58
st objoff_38(a0)
jsrto (SingleObjLoad).l, JmpTo13_SingleObjLoad
bne.s loc_2FE58
move.b #ObjID_HTZBoss,id(a1) ; load obj52
move.b #6,boss_subtype(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.b #SndID_LavaBall,d0
jsrto (PlaySound).l, JmpTo7_PlaySound
loc_2FE58:
tst.b objoff_2C(a0)
bne.s loc_2FE6E
cmpi.w #$5A0,(Boss_Y_pos).w
blt.s loc_2FED0
move.w #$5A0,(Boss_Y_pos).w
bra.s loc_2FE7C
; ===========================================================================
loc_2FE6E:
cmpi.w #$580,(Boss_Y_pos).w
blt.s loc_2FED0
move.w #$580,(Boss_Y_pos).w
loc_2FE7C:
move.w #-$E0,(Boss_Y_vel).w
move.b #0,angle(a0)
sf objoff_38(a0)
move.w (MainCharacter+x_pos).w,d0
subi.w #$2FC0,d0
bmi.s loc_2FEA8
move.w #$580,(Boss_Y_pos).w
move.w #$3040,x_pos(a0)
st objoff_2C(a0)
bra.s loc_2FEB8
; ===========================================================================
loc_2FEA8:
move.w #$2F40,x_pos(a0)
move.w #$5A0,(Boss_Y_pos).w
sf objoff_2C(a0)
loc_2FEB8:
move.w x_pos(a0),d0
cmp.w (MainCharacter+x_pos).w,d0
bgt.s loc_2FECA
bset #0,render_flags(a0)
bra.s loc_2FED0
; ===========================================================================
loc_2FECA:
bclr #0,render_flags(a0)
loc_2FED0:
move.w (Boss_Y_pos).w,y_pos(a0)
bsr.w loc_300A4
jmpto (DisplaySprite).l, JmpTo36_DisplaySprite
; ===========================================================================
loc_2FEDE:
move.w x_pos(a0),d0
move.w y_pos(a0),d1
move.w d0,sub2_x_pos(a0)
move.w d1,sub2_y_pos(a0)
rts
; ===========================================================================
; loc_2FEF0:
Obj52_FlameThrower:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_2FEFE(pc,d0.w),d1
jmp off_2FEFE(pc,d1.w)
; ===========================================================================
off_2FEFE: offsetTable
offsetTableEntry.w loc_2FF02 ; 0
offsetTableEntry.w loc_2FF50 ; 2
; ===========================================================================
loc_2FF02:
move.l #Obj52_MapUnc_302BC,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_HTZBoss,0,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #4,priority(a0)
addq.b #2,routine_secondary(a0)
move.b #5,anim(a0)
move.b #$98,collision_flags(a0)
subi.w #$1C,y_pos(a0)
move.w #-$70,d0
move.w #-4,d1
btst #0,render_flags(a0)
beq.s loc_2FF46
neg.w d0
neg.w d1
loc_2FF46:
add.w d0,x_pos(a0)
move.w d1,x_vel(a0)
rts
; ===========================================================================
loc_2FF50:
move.w x_vel(a0),d1
add.w d1,x_pos(a0)
lea (Ani_obj52).l,a1
jsrto (AnimateSprite).l, JmpTo18_AnimateSprite
jmpto (MarkObjGone).l, JmpTo37_MarkObjGone
; ===========================================================================
; loc_2FF66:
Obj52_LavaBall:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_2FF74(pc,d0.w),d1
jmp off_2FF74(pc,d1.w)
; ===========================================================================
off_2FF74: offsetTable
offsetTableEntry.w loc_2FF78 ; 0
offsetTableEntry.w loc_30008 ; 2
; ===========================================================================
loc_2FF78:
movea.l a0,a1
moveq #0,d2
moveq #1,d1
bra.s loc_2FF94
; ===========================================================================
loc_2FF80:
jsrto (SingleObjLoad).l, JmpTo13_SingleObjLoad
bne.w return_30006
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
loc_2FF94:
move.b #ObjID_HTZBoss,id(a1) ; load obj52
move.b #6,boss_subtype(a1)
move.l #Obj52_MapUnc_302BC,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_HTZBoss,0,0),art_tile(a1)
ori.b #4,render_flags(a1)
move.b #3,priority(a1)
addq.b #2,routine_secondary(a1)
move.b #7,anim(a1)
move.b #$8B,collision_flags(a1)
move.b d2,objoff_2E(a1)
move.b #8,y_radius(a1)
move.b #8,x_radius(a1)
move.w x_pos(a1),objoff_2A(a1)
move.w #$1C00,d0
tst.w d2
bne.s loc_2FFE8
neg.w d0
loc_2FFE8:
move.w d0,x_vel(a1)
move.w #-$5400,y_vel(a1)
cmpi.w #$2F40,x_pos(a1)
beq.s loc_30000
move.w #-$6400,y_vel(a1)
loc_30000:
addq.w #1,d2
dbf d1,loc_2FF80
return_30006:
rts
; ===========================================================================
loc_30008:
bsr.w Obj52_LavaBall_Move
jsrto (ObjCheckFloorDist).l, JmpTo4_ObjCheckFloorDist
tst.w d1
bpl.s loc_30064
add.w d1,y_pos(a0)
move.b #ObjID_LavaBubble,id(a0) ; load 0bj20
move.b #$A,routine(a0)
move.b #2,anim(a0)
move.b #4,mapping_frame(a0)
move.w #0,y_vel(a0)
move.l #Obj20_MapUnc_23294,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_Buzzer_Fireball_1,0,1),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo62_Adjust2PArtPointer
move.b #0,mapping_frame(a0)
move.w #9,objoff_32(a0)
move.b #3,objoff_36(a0)
move.b #SndID_FireBurn,d0
jsrto (PlaySound).l, JmpTo7_PlaySound
jmpto (Obj20).l, JmpTo_Obj20
; ===========================================================================
loc_30064:
lea (Ani_obj52).l,a1
jsrto (AnimateSprite).l, JmpTo18_AnimateSprite
jmpto (MarkObjGone).l, JmpTo37_MarkObjGone
; ===========================================================================
; loc_30072:
Obj52_LavaBall_Move:
move.l objoff_2A(a0),d2
move.l y_pos(a0),d3
move.w x_vel(a0),d0
ext.l d0
asl.l #4,d0
add.l d0,d2
move.w y_vel(a0),d0
addi.w #$380,y_vel(a0)
ext.l d0
asl.l #4,d0
add.l d0,d3
move.l d2,objoff_2A(a0)
move.l d3,y_pos(a0)
move.w objoff_2A(a0),x_pos(a0)
rts
; ===========================================================================
loc_300A4:
cmpi.b #8,angle(a0)
bhs.s return_300EA
tst.b objoff_32(a0)
beq.s Obj52_Defeat
tst.b collision_flags(a0)
bne.s return_300EA
tst.b objoff_14(a0)
bne.s loc_300CE
move.b #$20,objoff_14(a0)
move.w #SndID_BossHit,d0
jsr (PlaySound).l
loc_300CE:
lea (Normal_palette_line2+2).w,a1
moveq #0,d0
tst.w (a1)
bne.s loc_300DC
move.w #$EEE,d0
loc_300DC:
move.w d0,(a1)
subq.b #1,objoff_14(a0)
bne.s return_300EA
move.b #$32,collision_flags(a0)
return_300EA:
rts
; ===========================================================================
; loc_300EC:
Obj52_Defeat:
moveq #100,d0
jsrto (AddPoints).l, JmpTo4_AddPoints
move.w #$B3,(Boss_Countdown).w
move.b #8,angle(a0)
moveq #PLCID_Capsule,d0
jsrto (LoadPLC).l, JmpTo7_LoadPLC
rts
; ===========================================================================
; loc_30106:
Obj52_Mobile_Defeated:
move.b #0,mainspr_childsprites(a0)
subi_.w #1,(Boss_Countdown).w
bmi.s loc_30142
cmpi.w #$1E,(Boss_Countdown).w
bgt.s Obj52_Mobile_UpdateExplosion
move.b #$10,mainspr_mapframe(a0)
bsr.w Boss_LoadExplosion
move.b (Vint_runcount+3).w,d0
andi.b #$1F,d0
bne.w JmpTo36_DisplaySprite
bsr.w Obj52_CreateSmoke
jmpto (DisplaySprite).l, JmpTo36_DisplaySprite
; ===========================================================================
; loc_3013A:
Obj52_Mobile_UpdateExplosion:
bsr.w Boss_LoadExplosion
jmpto (DisplaySprite).l, JmpTo36_DisplaySprite
; ===========================================================================
loc_30142:
move.b (Vint_runcount+3).w,d0
andi.b #$1F,d0
bne.w Obj52_Mobile_Flee
bsr.w Obj52_CreateSmoke
; loc_30152:
Obj52_Mobile_Flee:
cmpi.w #-$3C,(Boss_Countdown).w
bgt.w JmpTo36_DisplaySprite
tst.b (Boss_defeated_flag).w
bne.s loc_30170
jsrto (PlayLevelMusic).l, JmpTo3_PlayLevelMusic
jsrto (LoadPLC_AnimalExplosion).l, JmpTo3_LoadPLC_AnimalExplosion
move.b #1,(Boss_defeated_flag).w
loc_30170:
addq.w #2,y_pos(a0)
cmpi.w #$3160,(Camera_Max_X_pos).w
bhs.s loc_30182
addq.w #2,(Camera_Max_X_pos).w
bra.s BranchTo_JmpTo36_DisplaySprite
; ===========================================================================
loc_30182:
tst.b render_flags(a0)
bpl.s loc_301AA
tst.b objoff_2C(a0)
bne.s loc_3019C
cmpi.w #$578,y_pos(a0)
bgt.w loc_301AA
jmpto (DisplaySprite).l, JmpTo36_DisplaySprite
; ===========================================================================
loc_3019C:
cmpi.w #$588,y_pos(a0)
bgt.w loc_301AA
BranchTo_JmpTo36_DisplaySprite
jmpto (DisplaySprite).l, JmpTo36_DisplaySprite
; ===========================================================================
loc_301AA:
move.w #$3160,(Camera_Max_X_pos).w
if removeJmpTos
JmpTo53_DeleteObject
endif
jmpto (DeleteObject).l, JmpTo53_DeleteObject
; ===========================================================================
; loc_301B4:
Obj52_CreateSmoke
jsrto (SingleObjLoad).l, JmpTo13_SingleObjLoad
bne.s return_3020E
move.b #ObjID_HTZBoss,id(a1) ; load obj52
move.b #8,boss_subtype(a1)
move.l #Obj52_MapUnc_30258,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_BossSmoke_2,0,0),art_tile(a1)
ori.b #4,render_flags(a1)
move.b #1,priority(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w x_pos(a0),objoff_2A(a1)
subi.w #$28,y_pos(a1)
move.w #-$60,x_vel(a1)
move.w #-$C0,y_vel(a1)
move.b #0,mapping_frame(a1)
move.b #$11,anim_frame_duration(a1)
return_3020E:
rts
; ===========================================================================
loc_30210:
subq.b #1,anim_frame_duration(a0)
bpl.s loc_3022A
move.b #$11,anim_frame_duration(a0)
addq.b #1,mapping_frame(a0)
cmpi.b #4,mapping_frame(a0)
beq.w JmpTo53_DeleteObject
loc_3022A:
move.l objoff_2A(a0),d2
move.l y_pos(a0),d3
move.w x_vel(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d2
move.w y_vel(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d3
move.l d2,objoff_2A(a0)
move.w objoff_2A(a0),x_pos(a0)
move.l d3,y_pos(a0)
jmpto (DisplaySprite).l, JmpTo36_DisplaySprite
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings - uses ArtNem_BossSmoke
; ----------------------------------------------------------------------------
Obj52_MapUnc_30258: BINCLUDE "mappings/sprite/obj52_a.bin"
; animation script
; off_30288:
Ani_obj52: offsetTable
offsetTableEntry.w byte_30298 ; 0
offsetTableEntry.w byte_3029D ; 1
offsetTableEntry.w byte_302A2 ; 2
offsetTableEntry.w byte_302A7 ; 3
offsetTableEntry.w byte_302AC ; 4
offsetTableEntry.w byte_302B0 ; 5
offsetTableEntry.w byte_302B4 ; 6
offsetTableEntry.w byte_302B7 ; 7
byte_30298: dc.b 1, 2, 3,$FD, 1
rev02even
byte_3029D: dc.b 2, 4, 5,$FD, 2
rev02even
byte_302A2: dc.b 3, 6, 7,$FD, 3
rev02even
byte_302A7: dc.b 4, 8, 9,$FD, 4
rev02even
byte_302AC: dc.b 5, $A, $B,$FE
rev02even
byte_302B0: dc.b 3, $C, $D,$FF
rev02even
byte_302B4: dc.b $F, 1,$FF
rev02even
byte_302B7: dc.b 3, $E, $F,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings - uses ArtNem_Eggpod + ?
; ----------------------------------------------------------------------------
Obj52_MapUnc_302BC: BINCLUDE "mappings/sprite/obj52_b.bin"
if ~~removeJmpTos
align 4
endif
; ===========================================================================
if ~~removeJmpTos
JmpTo36_DisplaySprite
jmp (DisplaySprite).l
JmpTo53_DeleteObject
jmp (DeleteObject).l
JmpTo13_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo37_MarkObjGone
jmp (MarkObjGone).l
JmpTo7_PlaySound
jmp (PlaySound).l
JmpTo18_AnimateSprite
jmp (AnimateSprite).l
JmpTo4_ObjCheckFloorDist
jmp (ObjCheckFloorDist).l
JmpTo7_LoadPLC
jmp (LoadPLC).l
JmpTo_Obj20
jmp (Obj20).l
JmpTo4_AddPoints
jmp (AddPoints).l
JmpTo62_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo3_PlayLevelMusic
jmp (PlayLevelMusic).l
JmpTo3_LoadPLC_AnimalExplosion
jmp (LoadPLC_AnimalExplosion).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 89 - ARZ boss
; ----------------------------------------------------------------------------
; OST Variables:
; Main Vehicle
obj89_hammer_y_vel = objoff_2E ; falling hammer's y velocity
obj89_target = objoff_38
obj89_hammer_y_pos = objoff_3A ; falling hammer's y position
obj89_hammer_flags = objoff_3E
; Pillars & Arrows
obj89_pillar_parent = objoff_2A ; address of main vehicle
obj89_pillar_shake_time = objoff_30
obj89_pillar_shaking = objoff_38
obj89_eyes_timer = objoff_30
obj89_arrow_routine = objoff_2A
obj89_arrow_timer = objoff_30
obj89_arrow_parent2 = objoff_34
obj89_arrow_parent = objoff_38 ; address of main vehicle
; Sprite_30480:
Obj89:
moveq #0,d0
move.b boss_subtype(a0),d0
move.w Obj89_Index(pc,d0.w),d1
jmp Obj89_Index(pc,d1.w)
; ===========================================================================
; off_3048E:
Obj89_Index: offsetTable
offsetTableEntry.w Obj89_Init ; 0 - Init
offsetTableEntry.w Obj89_Main ; 2 - Main Vehicle
offsetTableEntry.w Obj89_Pillar ; 4 - Pillars & Arrows
; ===========================================================================
; loc_30494:
Obj89_Init:
tst.l (Plc_Buffer).w ; is art finished loading?
beq.s + ; if yes, branch
rts
; ---------------------------------------------------------------------------
+
tst.w (Player_mode).w ; is player mode anything other than Sonic & Tails?
bne.s Obj89_Init_RaisePillars ; if yes, branch
move.w (MainCharacter+x_pos).w,d0
cmpi.w #$2A60,d0 ; is Sonic too close to the left edge?
blt.w Obj89_Init_Standard ; if yes, branch
cmpi.w #$2B60,d0 ; is Sonic too close to the right edge?
bgt.w Obj89_Init_Standard ; if yes, branch
cmpi.b #$81,(Sidekick+obj_control).w
beq.w Obj89_Init_RaisePillars ; branch, if Tails is flying
move.w (Sidekick+x_pos).w,d0
cmpi.w #$2A60,d0 ; is Tails too close to the left edge?
blt.w Obj89_Init_Standard ; if yes, branch
cmpi.w #$2B60,d0 ; is Tails too close to the right edge?
bgt.w Obj89_Init_Standard ; if yes, branch
; loc_304D4:
Obj89_Init_RaisePillars:
move.b #1,(Screen_Shaking_Flag).w ; make screen shake
move.w #make_art_tile(ArtTile_ArtNem_ARZBoss,0,0),art_tile(a0)
move.l #Obj89_MapUnc_30E04,mappings(a0)
ori.b #4,render_flags(a0)
move.b #$20,mainspr_width(a0)
move.b #2,priority(a0)
move.b #2,boss_subtype(a0) ; => Obj89_Main
move.w #$2AE0,x_pos(a0)
move.w #$388,y_pos(a0)
move.w #$2AE0,(Boss_X_pos).w
move.w #$388,(Boss_Y_pos).w
bset #6,render_flags(a0)
move.b #3,mainspr_childsprites(a0)
move.b #$F,collision_flags(a0)
move.b #8,boss_hitcount2(a0)
move.b #8,mainspr_mapframe(a0)
move.w #-$380,obj89_hammer_y_vel(a0)
clr.b (Boss_CollisionRoutine).w ; disable special collisions
move.w #$2AE0,sub2_x_pos(a0) ;
move.w #$488,sub2_y_pos(a0)
move.b #0,sub2_mapframe(a0)
move.w #$2AE0,sub3_x_pos(a0) ;
move.w #$488,sub3_y_pos(a0)
move.b #9,sub3_mapframe(a0)
move.w #$2AE0,sub4_x_pos(a0) ;
move.w #$488,sub4_y_pos(a0)
move.b #6,sub4_mapframe(a0)
move.w #$100,(Boss_Y_vel).w
; load first pillar object
jsrto (SingleObjLoad).l, JmpTo14_SingleObjLoad
bne.w Obj89_Init_Standard
move.b #ObjID_ARZBoss,id(a1) ; load obj89
move.l #Obj89_MapUnc_30D68,mappings(a1)
ori.b #4,render_flags(a1)
move.w #make_art_tile(ArtTile_ArtNem_ARZBoss,0,0),art_tile(a1)
move.b #$10,width_pixels(a1)
move.b #4,priority(a1)
move.w #$2A50,x_pos(a1)
move.w #$510,y_pos(a1)
addq.b #4,boss_subtype(a1) ; => Obj89_Pillar
move.l a0,obj89_pillar_parent(a1)
move.b #0,mapping_frame(a1)
move.b #2,priority(a1)
move.b #$20,y_radius(a1)
movea.l a1,a2 ; save first pillar's address
jsrto (SingleObjLoad2).l, JmpTo22_SingleObjLoad2
bne.s Obj89_Init_Standard
moveq #0,d0
move.w #bytesToLcnt(object_size),d1
; loc_305DC:
Obj89_Init_DuplicatePillar:
move.l (a2,d0.w),(a1,d0.w)
addq.w #4,d0
dbf d1,Obj89_Init_DuplicatePillar
if object_size&3
move.w (a2,d0.w),(a1,d0.w)
endif
bset #0,render_flags(a1)
move.w #$2B70,x_pos(a1) ; move pillar to other side of boss area
; loc_305F4:
Obj89_Init_Standard:
bsr.w Obj89_Init_AnimationArray
rts
; ===========================================================================
; loc_305FA:
Obj89_Init_AnimationArray:
lea (Boss_AnimationArray).w,a2
move.b #4,(a2)+ ; main vehicle
move.b #0,(a2)+
move.b #0,(a2)+ ; face
move.b #0,(a2)+
move.b #2,(a2)+ ; hammer
move.b #0,(a2)+
move.b #1,(a2)+ ; flames
move.b #0,(a2)+
rts
; ===========================================================================
; loc_30620:
Obj89_Main:
moveq #0,d0
move.b boss_routine(a0),d0
move.w Obj89_Main_Index(pc,d0.w),d1
jmp Obj89_Main_Index(pc,d1.w)
; ===========================================================================
; off_3062E:
Obj89_Main_Index: offsetTable ; main boss object
offsetTableEntry.w Obj89_Main_Sub0 ; 0 - moving down into arena
offsetTableEntry.w Obj89_Main_Sub2 ; 2 - moving left/right
offsetTableEntry.w Obj89_Main_Sub4 ; 4 - having reached pillar
offsetTableEntry.w Obj89_Main_Sub6 ; 6 - hit with hammer
offsetTableEntry.w Obj89_Main_Sub8 ; 8 - boss exploding
offsetTableEntry.w Obj89_Main_SubA ; A - move boss down and alter a little up again
offsetTableEntry.w Obj89_Main_SubC ; C - beaten boss moving away
; ===========================================================================
; loc_3063C:
Obj89_Main_Sub0:
bsr.w Boss_MoveObject
bsr.w Obj89_Main_HandleFace
bsr.w Obj89_Main_AlignParts
cmpi.w #$430,(Boss_Y_pos).w ; has boss reached its target?
blt.s Obj89_Main_Sub0_Standard ; if not, branch
move.w #$430,(Boss_Y_pos).w
addi_.b #2,boss_routine(a0) ; => Obj89_Main_Sub2
move.w #0,(Boss_Y_vel).w ; stop y movement
move.w #-$C8,(Boss_X_vel).w ; move leftward
st obj89_target(a0)
; loc_3066C:
Obj89_Main_Sub0_Standard:
lea (Ani_obj89_b).l,a1
bsr.w AnimateBoss
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
; loc_3067A:
Obj89_Main_Sub2:
bsr.w Boss_MoveObject
bsr.w Obj89_Main_HandleFace
bsr.w Obj89_Main_AlignParts
tst.b obj89_target(a0) ; is boss going left?
bne.s Obj89_Main_Sub2_GoingLeft ; if yes, branch
cmpi.w #$2B10,(Boss_X_pos).w ; is boss right in front of the right pillar?
blt.s Obj89_Main_Sub2_Standard ; branch, if still too far away
bra.s Obj89_Main_Sub2_AtTarget
; ===========================================================================
; loc_30696:
Obj89_Main_Sub2_GoingLeft:
cmpi.w #$2AB0,(Boss_X_pos).w ; is boss right in front of the left pillar?
bgt.s Obj89_Main_Sub2_Standard ; branch, if still too far away
; loc_3069E:
Obj89_Main_Sub2_AtTarget:
addi_.b #2,boss_routine(a0) ; => Obj89_Main_Sub4
move.w #0,(Boss_X_vel).w
; loc_306AA:
Obj89_Main_Sub2_Standard:
lea (Ani_obj89_b).l,a1
bsr.w AnimateBoss
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
; loc_306B8:
Obj89_Main_Sub4:
bsr.w Boss_MoveObject
bsr.w Obj89_Main_HandleFace
bsr.w Obj89_Main_AlignParts
cmpi.b #-$40,boss_sine_count(a0) ; has boss reached the right height in its hovering animation?
bne.s Obj89_Main_Sub4_Standard ; if not, branch
lea (Boss_AnimationArray).w,a1
andi.b #$F0,2*2(a1) ; reset hammer animation
ori.b #3,2*2(a1) ; reset hammer animation timer
addq.b #2,boss_routine(a0) ; => Obj89_Main_Sub6
btst #0,render_flags(a0)
sne obj89_target(a0) ; target opposite side
move.w #$1E,(Boss_Countdown).w
move.b #SndID_Hammer,d0
jsrto (PlaySound).l, JmpTo8_PlaySound
; loc_306F8:
Obj89_Main_Sub4_Standard:
lea (Ani_obj89_b).l,a1
bsr.w AnimateBoss
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
; loc_30706:
Obj89_Main_Sub6:
cmpi.w #$14,(Boss_Countdown).w ; has counter reached a specific value?
bne.s + ; if not, branch
bset #0,obj89_hammer_flags(a0) ; hammer just hit a pillar
move.b #1,(Boss_CollisionRoutine).w ; enable hammer collision
+
subi_.w #1,(Boss_Countdown).w ; decrement counter
bpl.s Obj89_Main_Sub6_Standard ; branch, if counter > 0
clr.b (Boss_CollisionRoutine).w ; disable hammer collision
move.b #2,boss_routine(a0) ; => Obj89_Main_Sub2
bchg #0,render_flags(a0) ; face opposite direction
beq.s Obj89_Main_Sub6_MoveRight ; branch, if new direction is right
move.w #-$C8,(Boss_X_vel).w ; move left
bra.s Obj89_Main_Sub6_Standard
; ===========================================================================
; loc_3073C:
Obj89_Main_Sub6_MoveRight:
move.w #$C8,(Boss_X_vel).w ; move right
; loc_30742:
Obj89_Main_Sub6_Standard:
bsr.w Boss_MoveObject
bsr.w Obj89_Main_HandleFace
bsr.w Obj89_Main_AlignParts
lea (Ani_obj89_b).l,a1
bsr.w AnimateBoss
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
; loc_3075C:
Obj89_Main_HandleFace:
bsr.w Obj89_Main_HandleHoveringAndHits
cmpi.b #4,(MainCharacter+routine).w ; is Sonic hurt?
beq.s Obj89_Main_Laugh ; if yes, branch
cmpi.b #4,(Sidekick+routine).w ; is Tails hurt?
bne.s Obj89_Main_ChkHurt ; if not, branch
; loc_30770:
Obj89_Main_Laugh:
lea (Boss_AnimationArray).w,a1
move.b #$31,1*2+1(a1) ; use laughing animation
; loc_3077A:
Obj89_Main_ChkHurt:
cmpi.b #$3F,boss_invulnerable_time(a0) ; was boss hurt?
bne.s return_3078C ; if not, branch
lea (Boss_AnimationArray).w,a1
move.b #-$40,1*2+1(a1) ; use hurt animation
return_3078C:
rts
; ===========================================================================
; loc_3078E:
Obj89_Main_HandleHoveringAndHits:
move.b boss_sine_count(a0),d0
jsr (CalcSine).l
asr.w #6,d0
add.w (Boss_Y_pos).w,d0
move.w d0,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
addq.b #2,boss_sine_count(a0)
cmpi.b #8,boss_routine(a0) ; has boss been defeated?
bhs.s return_307F2 ; if yes, branch
tst.b boss_hitcount2(a0) ; has boss run out of hits?
beq.s Obj89_Main_KillBoss ; if yes, branch
tst.b collision_flags(a0) ; are boss's collisions enabled?
bne.s return_307F2 ; if yes, branch
tst.b boss_invulnerable_time(a0) ; is boss invulnerable?
bne.s Obj89_Main_Flash ; if yes, branch
move.b #$40,boss_invulnerable_time(a0) ; make boss invulnerable
move.w #SndID_BossHit,d0 ; play "boss hit" sound
jsr (PlaySound).l
; loc_307D6:
Obj89_Main_Flash:
lea (Normal_palette_line2+2).w,a1
moveq #0,d0 ; 0000 = black
tst.w (a1) ; is current color black?
bne.s + ; if not, branch
move.w #$EEE,d0 ; 0EEE = white
+
move.w d0,(a1) ; set color
subq.b #1,boss_invulnerable_time(a0)
bne.s return_307F2 ; branch, if invulnerability hasn't run out
move.b #$F,collision_flags(a0) ; restore collisions
return_307F2:
rts
; ===========================================================================
; loc_307F4:
Obj89_Main_KillBoss:
moveq #100,d0
jsrto (AddPoints).l, JmpTo5_AddPoints
move.w #$B3,(Boss_Countdown).w ; set timer
move.b #8,boss_routine(a0) ; => Obj89_Main_Sub8
lea (Boss_AnimationArray).w,a1
move.b #5,1*2(a1) ; use defeated animation
move.b #0,1*2+1(a1) ; reset animation
moveq #PLCID_Capsule,d0
jsrto (LoadPLC).l, JmpTo8_LoadPLC
move.b #5,sub2_mapframe(a0)
rts
; ===========================================================================
; loc_30824:
Obj89_Main_AlignParts:
move.w x_pos(a0),d0
move.w y_pos(a0),d1
move.w d0,sub2_x_pos(a0)
move.w d1,sub2_y_pos(a0)
move.w d0,sub4_x_pos(a0)
move.w d1,sub4_y_pos(a0)
tst.b boss_defeated(a0)
bne.s Obj89_Main_DropHammer ; branch, if boss was defeated
move.w d0,sub3_x_pos(a0)
move.w d1,sub3_y_pos(a0)
move.w d1,obj89_hammer_y_pos(a0)
rts
; ===========================================================================
; loc_30850:
Obj89_Main_DropHammer:
cmpi.w #$78,(Boss_Countdown).w
bgt.s return_3088A ; wait until timer is below $78
subi_.w #1,sub3_x_pos(a0) ; make hammer move left
move.l obj89_hammer_y_pos(a0),d0
move.w obj89_hammer_y_vel(a0),d1
addi.w #$38,obj89_hammer_y_vel(a0) ; add gravity
ext.l d1
asl.l #8,d1
add.l d1,d0
move.l d0,obj89_hammer_y_pos(a0) ; update position
move.w obj89_hammer_y_pos(a0),sub3_y_pos(a0)
cmpi.w #$540,sub3_y_pos(a0) ; has the hammer reached the bottom?
blt.s return_3088A ; if not, branch
move.w #0,obj89_hammer_y_vel(a0) ; else, make hammer invisible
return_3088A:
rts
; ===========================================================================
; loc_3088C:
Obj89_Main_Sub8:
st boss_defeated(a0)
subq.w #1,(Boss_Countdown).w
bmi.s Obj89_Main_SetupEscapeAnim
bsr.w Boss_LoadExplosion
bra.s Obj89_Main_Sub8_Standard
; ===========================================================================
; loc_3089C:
Obj89_Main_SetupEscapeAnim:
move.b #3,mainspr_childsprites(a0)
lea (Boss_AnimationArray).w,a2
move.b #1,2*2(a2) ; hammer
move.b #0,2*2+1(a2)
move.b #0,1*2(a2) ; face
move.b #0,1*2+1(a2)
bset #0,render_flags(a0)
clr.w (Boss_X_vel).w ; stop movement
clr.w (Boss_Y_vel).w
addq.b #2,boss_routine(a0) ; => Obj89_Main_SubA
move.w #-$12,(Boss_Countdown).w
; loc_308D6:
Obj89_Main_Sub8_Standard:
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
lea (Ani_obj89_b).l,a1
bsr.w AnimateBoss
bsr.w Obj89_Main_AlignParts
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
; loc_308F4:
Obj89_Main_SubA:
addq.w #1,(Boss_Countdown).w ; note: countdown starts out as -$12
beq.s Obj89_Main_SubA_StopFall ; branch, if countdown reached 0
bpl.s Obj89_Main_SubA_Phase2 ; branch, if falling phase is over
addi.w #$18,(Boss_Y_vel).w ; else, make boss fall
bra.s Obj89_Main_SubA_Standard
; ===========================================================================
; loc_30904:
Obj89_Main_SubA_StopFall:
clr.w (Boss_Y_vel).w ; stop fall
bra.s Obj89_Main_SubA_Standard
; ===========================================================================
; loc_3090A:
Obj89_Main_SubA_Phase2:
cmpi.w #$18,(Boss_Countdown).w
blo.s Obj89_Main_SubA_Ascend
beq.s Obj89_Main_SubA_StopAscent
cmpi.w #$20,(Boss_Countdown).w
blo.s Obj89_Main_SubA_Standard
addq.b #2,boss_routine(a0) ; => Obj89_Main_SubC
bra.s Obj89_Main_SubA_Standard
; ===========================================================================
; loc_30922:
Obj89_Main_SubA_Ascend:
subi_.w #8,(Boss_Y_vel).w ; ascend slowly
bra.s Obj89_Main_SubA_Standard
; ===========================================================================
; loc_3092A:
Obj89_Main_SubA_StopAscent:
clr.w (Boss_Y_vel).w ; stop ascent
jsrto (PlayLevelMusic).l, JmpTo4_PlayLevelMusic
jsrto (LoadPLC_AnimalExplosion).l, JmpTo4_LoadPLC_AnimalExplosion
; loc_30936:
Obj89_Main_SubA_Standard:
bsr.w Boss_MoveObject
bsr.w Obj89_Main_HandleHoveringAndHits
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
lea (Ani_obj89_b).l,a1
bsr.w AnimateBoss
bsr.w Obj89_Main_AlignParts
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
; loc_3095C:
Obj89_Main_SubC:
move.w #$400,(Boss_X_vel).w
move.w #-$40,(Boss_Y_vel).w
cmpi.w #$2C00,(Camera_Max_X_pos).w ; has camera reached its target position?
bhs.s Obj89_Main_SubC_ChkDelete ; if yes, branch
addq.w #2,(Camera_Max_X_pos).w ; else, move camera
bra.s Obj89_Main_SubC_Standard
; ===========================================================================
; loc_30976:
Obj89_Main_SubC_ChkDelete:
tst.b render_flags(a0) ; is boss still visible?
bpl.s JmpTo54_DeleteObject ; if not, branch
; loc_3097C:
Obj89_Main_SubC_Standard:
bsr.w Boss_MoveObject
bsr.w Obj89_Main_HandleHoveringAndHits
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
lea (Ani_obj89_b).l,a1
bsr.w AnimateBoss
bsr.w Obj89_Main_AlignParts
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
JmpTo54_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
; loc_309A8:
Obj89_Pillar:
moveq #0,d0
movea.l obj89_pillar_parent(a0),a1 ; a1=object
cmpi.b #8,boss_routine(a1) ; has boss been defeated?
blt.s Obj89_Pillar_Normal ; if not, branch
move.b #4,routine_secondary(a0)
; loc_309BC:
Obj89_Pillar_Normal:
move.b routine_secondary(a0),d0
move.w Obj89_Pillar_Index(pc,d0.w),d1
jmp Obj89_Pillar_Index(pc,d1.w)
; ===========================================================================
; off_309C8:
Obj89_Pillar_Index: offsetTable ; pillar/arrow object
offsetTableEntry.w Obj89_Pillar_Sub0 ; 0 - raise pillars
offsetTableEntry.w Obj89_Pillar_Sub2 ; 2 - pillars shaking(?)
offsetTableEntry.w Obj89_Pillar_Sub4 ; 4 - move pillars down
offsetTableEntry.w Obj89_Arrow ; 6 - arrow
offsetTableEntry.w Obj89_Pillar_BulgingEyes ; 8 - pillar normal (standing)
; ===========================================================================
; loc_309D2:
Obj89_Pillar_Sub0:
bsr.w Obj89_Pillar_SolidObject
move.b (Vint_runcount+3).w,d0
andi.b #$1F,d0
bne.s +
move.w #SndID_Rumbling2,d0 ; play rumbling sound every 32 frames
jsrto (PlaySound).l, JmpTo8_PlaySound
+
subi_.w #1,y_pos(a0) ; raise pillar
cmpi.w #$488,y_pos(a0) ; has pillar reached its target height?
bgt.s BranchTo_JmpTo37_DisplaySprite ; if not, branch
addq.b #2,routine_secondary(a0) ; => Obj89_Pillar_Sub2
move.b #0,(Screen_Shaking_Flag).w ; stop screen shaking
BranchTo_JmpTo37_DisplaySprite
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
; loc_30A04:
Obj89_Pillar_Sub2:
; note: the boss switches targets before bit 0 of obj89_hammer_flags is set. In other
; words, it's always the pillar facing the new target that fires.
bsr.w Obj89_Pillar_SolidObject
movea.l obj89_pillar_parent(a0),a3 ; a3=object
btst #0,obj89_hammer_flags(a3)
beq.s Obj89_Pillar_Sub2_Standard ; branch, if hammer hasn't hit a pillar
tst.b obj89_target(a3) ; is boss targeting the right?
beq.s Obj89_Pillar_Sub2_RightPillar ; if yes, branch
btst #0,render_flags(a0) ; is pillar facing left?
beq.s Obj89_Pillar_Sub2_Standard ; if not, branch
bra.s loc_30A2C
; ===========================================================================
; loc_30A24:
Obj89_Pillar_Sub2_RightPillar:
btst #0,render_flags(a0) ; is pillar facing right?
bne.s Obj89_Pillar_Sub2_Standard ; if not, branch
loc_30A2C:
bclr #0,obj89_hammer_flags(a3) ; clear "hitting-pillar" flag
bsr.w Obj89_Pillar_Shoot ; shoot an arrow
st obj89_pillar_shaking(a0) ; make pillar shake
; loc_30A3A:
Obj89_Pillar_Sub2_Standard:
bsr.w Obj89_Pillar_ChkShake
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
; loc_30A42:
Obj89_Pillar_ChkShake:
tst.b obj89_pillar_shaking(a0) ; is pillar shaking?
beq.s return_30AAE ; if not, branch
tst.w obj89_pillar_shake_time(a0) ; has timer been set?
bgt.s + ; if yes, branch
move.w #$1F,obj89_pillar_shake_time(a0); else, initialize timer
+
subi_.w #1,obj89_pillar_shake_time(a0)
bgt.s Obj89_Pillar_Shake ; branch, if timer hasn't expired
sf obj89_pillar_shaking(a0) ; stop shaking
move.w #0,obj89_pillar_shake_time(a0) ; clear timer
tst.b obj89_target(a3) ; is boss targeting the left?
bne.s + ; if yes, branch
move.w #$2A50,x_pos(a0) ; reset x position of left pillar
bra.s Obj89_Pillar_Sub2_End
; ===========================================================================
+
move.w #$2B70,x_pos(a0) ; reset x position of right pillar
; loc_30A7A:
Obj89_Pillar_Sub2_End:
move.w #$488,y_pos(a0) ; reset y position
bra.s return_30AAE
; ===========================================================================
; loc_30A82:
Obj89_Pillar_Shake:
move.w #$2A50,d1 ; load left pillar's default x position
tst.b obj89_target(a3) ; is boss targeting the left
beq.s + ; if not, branch
move.w #$2B70,d1 ; load right pillar's default x position
+
move.b (Vint_runcount+3).w,d0
andi.w #1,d0
add.w d0,d0
add.w Obj89_Pillar_ShakeOffsets(pc,d0.w),d1
move.w d1,x_pos(a0) ; add offset to x position
move.w #$488,d1 ; load pillar's default y position
add.w Obj89_Pillar_ShakeOffsets(pc,d0.w),d1
move.w d1,y_pos(a0) ; add offset to y position
return_30AAE:
rts
; ===========================================================================
; word_30AB0:
Obj89_Pillar_ShakeOffsets:
dc.w 1 ; 0
dc.w -1 ; 1
; ===========================================================================
; loc_30AB4:
Obj89_Pillar_Shoot:
jsrto (SingleObjLoad).l, JmpTo14_SingleObjLoad
bne.w return_30B40
_move.b #ObjID_ARZBoss,id(a1) ; load obj89
move.b #4,boss_subtype(a1)
move.b #8,routine_secondary(a1) ; => Obj89_Pillar_BulgingEyes
move.l #Obj89_MapUnc_30D68,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_ARZBoss,0,0),art_tile(a1)
ori.b #4,render_flags(a1)
moveq #0,d6
move.b #2,mapping_frame(a1)
move.w #$2A6A,x_pos(a1) ; align with left pillar
tst.b obj89_target(a3) ; is boss targeting the right?
beq.s + ; if yes, branch
st d6
move.w #$2B56,x_pos(a1) ; align with right pillar
bset #0,render_flags(a1)
+
move.w #$28,obj89_eyes_timer(a1)
jsrto (RandomNumber).l, JmpTo3_RandomNumber
andi.w #3,d0
add.w d0,d0
move.w Obj89_Arrow_Offsets(pc,d0.w),y_pos(a1)
movea.l a1,a2
jsrto (SingleObjLoad).l, JmpTo14_SingleObjLoad
bne.s return_30B40
_move.b #ObjID_ARZBoss,id(a1) ; load obj89
move.b #4,boss_subtype(a1)
move.b #6,routine_secondary(a1) ; => Obj89_Arrow
move.l a2,obj89_arrow_parent2(a1)
move.b d6,subtype(a1)
move.l a3,obj89_arrow_parent(a1)
return_30B40:
rts
; ===========================================================================
; word_30B42:
Obj89_Arrow_Offsets:
dc.w $458
dc.w $478 ; 1
dc.w $498 ; 2
dc.w $4B8 ; 3
; ===========================================================================
; loc_30B4A:
Obj89_Pillar_Sub4:
move.b #1,(Screen_Shaking_Flag).w ; make screen shake
addi_.w #1,y_pos(a0) ; lower pillar
cmpi.w #$510,y_pos(a0) ; has pillar lowered into the ground?
blt.s BranchTo2_JmpTo37_DisplaySprite ; if not, branch
move.b #0,(Screen_Shaking_Flag).w ; else, stop shaking the screen
jmpto (DeleteObject).l, JmpTo55_DeleteObject
; ===========================================================================
BranchTo2_JmpTo37_DisplaySprite
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
; loc_30B6C:
Obj89_Pillar_BulgingEyes:
subi_.w #1,obj89_eyes_timer(a0)
beq.w JmpTo55_DeleteObject
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
; loc_30B7A:
Obj89_Pillar_SolidObject:
move.w #$23,d1
move.w #$44,d2
move.w #$45,d3
move.w x_pos(a0),d4
move.w y_pos(a0),-(sp)
addi_.w #4,y_pos(a0) ; assume a slightly lower y position
jsrto (SolidObject).l, JmpTo26_SolidObject
move.w (sp)+,y_pos(a0) ; restore y position
rts
; ===========================================================================
;loc_30B9E:
Obj89_Arrow:
moveq #0,d0
movea.l obj89_arrow_parent(a0),a1 ; a1=object
cmpi.b #8,boss_routine(a1) ; has boss been defeated?
blt.s Obj89_Arrow_Normal ; if not, branch
move.b #6,obj89_arrow_routine(a0) ; => Obj89_Arrow_Sub6
; loc_30BB2:
Obj89_Arrow_Normal:
move.b obj89_arrow_routine(a0),d0
move.w Obj89_Arrow_Index(pc,d0.w),d1
jmp Obj89_Arrow_Index(pc,d1.w)
; ===========================================================================
; off_30BBE:
Obj89_Arrow_Index: offsetTable
offsetTableEntry.w Obj89_Arrow_Init ; 0 - launch arrow (init)
offsetTableEntry.w Obj89_Arrow_Sub2 ; 2 - arrow in air
offsetTableEntry.w Obj89_Arrow_Sub4 ; 4 - arrow stuck
offsetTableEntry.w Obj89_Arrow_Sub6 ; 6 - falling down
offsetTableEntry.w BranchTo_JmpTo55_DeleteObject ; 8 - delete arrow
; ===========================================================================
; loc_30BC8:
Obj89_Arrow_Init:
move.l #Obj89_MapUnc_30D68,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_ARZBoss,0,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #-$70,mainspr_width(a0)
move.b #4,priority(a0)
addq.b #2,obj89_arrow_routine(a0) ; => Obj89_Arrow_Sub2
movea.l obj89_arrow_parent2(a0),a1 ; a1=object
move.w x_pos(a1),x_pos(a0) ; align with parent object
move.w y_pos(a1),y_pos(a0)
move.w #4,y_vel(a0)
move.b #4,mapping_frame(a0)
addi.w #9,y_pos(a0)
tst.b subtype(a0) ; was arrow fired from right pillar?
beq.s + ; if not, branch
bset #0,status(a0) ; make arrow face left
bset #0,render_flags(a0)
move.w #-3,x_vel(a0) ; move left
bra.s Obj89_Arrow_Init_End
; ===========================================================================
+
move.w #3,x_vel(a0) ; move right
; loc_30C2E:
Obj89_Arrow_Init_End:
move.b #$B0,collision_flags(a0)
rts
; ===========================================================================
; loc_30C36:
Obj89_Arrow_Sub2:
btst #7,status(a0)
beq.s +
move.b #8,obj89_arrow_routine(a0) ; => BranchTo_JmpTo55_DeleteObject
+
move.w x_pos(a0),d0 ; load x position...
add.w x_vel(a0),d0 ; ... and add x velocity
tst.w x_vel(a0) ; is arrow moving right?
bpl.s Obj89_Arrow_Sub2_GoingRight ; if yes, branch
cmpi.w #$2A77,d0
bgt.s Obj89_Arrow_Sub2_Move ; branch, if arrow hasn't reached left pillar
move.w #$2A77,d0 ; else, make arrow stick to left pillar
bra.s Obj89_Arrow_Sub2_Stop
; ===========================================================================
; loc_30C5E:
Obj89_Arrow_Sub2_GoingRight:
cmpi.w #$2B49,d0
blt.s Obj89_Arrow_Sub2_Move ; branch, if arrow hasn't reached right pillar
move.w #$2B49,d0 ; else, make arrow stick to right pillar
; loc_30C68:
Obj89_Arrow_Sub2_Stop:
addi_.b #2,obj89_arrow_routine(a0) ; => Obj89_Arrow_Sub4
move.w d0,x_pos(a0) ; update position
move.b #SndID_ArrowStick,d0
jsrto (PlaySound).l, JmpTo8_PlaySound
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
; loc_30C7E:
Obj89_Arrow_Sub2_Move:
move.w d0,x_pos(a0) ; update position
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
; loc_30C86:
Obj89_Arrow_Sub4:
move.b #0,collision_flags(a0) ; make arrow harmless
btst #7,status(a0)
beq.s +
addi_.b #2,obj89_arrow_routine(a0) ; => Obj89_Arrow_Sub6
+
bsr.w Obj89_Arrow_Platform
lea (Ani_obj89_a).l,a1
jsrto (AnimateSprite).l, JmpTo19_AnimateSprite
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
; loc_30CAC:
Obj89_Arrow_Sub6:
bsr.w Obj89_Arrow_ChkDropPlayers
move.w y_pos(a0),d0 ; load y position...
add.w y_vel(a0),d0 ; ... and add y velocity
cmpi.w #$4F0,d0 ; has arrow dropped to the ground?
bgt.w JmpTo55_DeleteObject ; if yes, branch
move.w d0,y_pos(a0) ; update y position
jmpto (DisplaySprite).l, JmpTo37_DisplaySprite
; ===========================================================================
if removeJmpTos
JmpTo55_DeleteObject
endif
BranchTo_JmpTo55_DeleteObject
jmpto (DeleteObject).l, JmpTo55_DeleteObject
; ===========================================================================
; loc_30CCC:
Obj89_Arrow_Platform:
tst.w obj89_arrow_timer(a0) ; is timer set?
bne.s Obj89_Arrow_Platform_Decay ; if yes, branch
move.w #$1B,d1
move.w #1,d2
move.w #2,d3
move.w x_pos(a0),d4
jsrto (PlatformObject).l, JmpTo8_PlatformObject
btst #3,status(a0) ; is Sonic standing on the arrow?
beq.s return_30D02 ; if not, branch
move.w #$1F,obj89_arrow_timer(a0) ; else, set timer
; loc_30CF4:
Obj89_Arrow_Platform_Decay:
subi_.w #1,obj89_arrow_timer(a0) ; decrement timer
bne.s return_30D02 ; branch, if timer hasn't expired
move.b #6,obj89_arrow_routine(a0) ; => Obj89_Arrow_Sub6
return_30D02:
rts
; ===========================================================================
; loc_30D04:
Obj89_Arrow_ChkDropPlayers:
bclr #p1_standing_bit,status(a0)
beq.s + ; branch, if Sonic wasn't standing on the arrow
lea (MainCharacter).w,a1 ; a1=character
bsr.s Obj89_Arrow_DropPlayer
+
bclr #p2_standing_bit,status(a0)
beq.s return_30D2A ; branch, if Tails wasn't standing on the arrow
lea (Sidekick).w,a1 ; a1=character
; loc_30D1E:
Obj89_Arrow_DropPlayer:
bset #1,status(a1)
bclr #3,status(a1)
return_30D2A:
rts
; ===========================================================================
; animation script
; off_30D2C:
Ani_obj89_a: offsetTable
offsetTableEntry.w byte_30D30 ; 0
offsetTableEntry.w byte_30D47 ; 1
byte_30D30: dc.b 1, 4, 6, 5, 4, 6, 4, 5, 4, 6, 4, 4, 6, 5, 4, 6
dc.b 4, 5, 4, 6, 4,$FD, 1; 16
rev02even
byte_30D47: dc.b $F, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
dc.b 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,$F9; 16
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj89_MapUnc_30D68: BINCLUDE "mappings/sprite/obj89_a.bin"
; animation script
; off_30DC8:
Ani_obj89_b: offsetTable
offsetTableEntry.w byte_30DD4 ; 0
offsetTableEntry.w byte_30DEA ; 2
offsetTableEntry.w byte_30DEE ; 4
offsetTableEntry.w byte_30DF1 ; 6
offsetTableEntry.w byte_30DFD ; 8
offsetTableEntry.w byte_30E00 ; $A
byte_30DD4: dc.b 7, 0, 1,$FF, 2, 3, 2, 3, 2, 3, 2, 3,$FF, 4, 4, 4
dc.b 4, 4, 4, 4, 4,$FF; 16
rev02even
byte_30DEA: dc.b 1, 6, 7,$FF
rev02even
byte_30DEE: dc.b $F, 9,$FF
rev02even
byte_30DF1: dc.b 2, $A, $A, $B, $B, $B, $B, $B, $A, $A,$FD, 2
rev02even
byte_30DFD: dc.b $F, 8,$FF
rev02even
byte_30E00: dc.b 7, 5,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj89_MapUnc_30E04: BINCLUDE "mappings/sprite/obj89_b.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo37_DisplaySprite
jmp (DisplaySprite).l
JmpTo55_DeleteObject
jmp (DeleteObject).l
JmpTo14_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo8_PlaySound
jmp (PlaySound).l
JmpTo22_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo19_AnimateSprite
jmp (AnimateSprite).l
JmpTo3_RandomNumber
jmp (RandomNumber).l
JmpTo8_LoadPLC
jmp (LoadPLC).l
JmpTo5_AddPoints
jmp (AddPoints).l
JmpTo4_PlayLevelMusic
jmp (PlayLevelMusic).l
JmpTo4_LoadPLC_AnimalExplosion
jmp (LoadPLC_AnimalExplosion).l
JmpTo8_PlatformObject
jmp (PlatformObject).l
JmpTo26_SolidObject
jmp (SolidObject).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 57 - MCZ boss
; ----------------------------------------------------------------------------
; OST: first $10 bytes for main sprite, 6 bytes for childsprites (5th byte unused)
obj57_sub5_y_vel = $2E ; word - y_vel of second digger when falling down
obj57_sub2_y_vel = $30 ; word - y_vel of first digger when falling down
obj57_sub2_y_pos2 = $34 ; longword - y_pos of first digger when falling down
obj57_sub5_y_pos2 = $3A ; longword - y_pos of second digger when falling down
; ----------------------------------------------------------------------------
; Sprite_30FA4:
Obj57:
moveq #0,d0
move.b boss_subtype(a0),d0
move.w Obj57_Index(pc,d0.w),d1
jmp Obj57_Index(pc,d1.w)
; ===========================================================================
;off_30FB2:
Obj57_Index: offsetTable
offsetTableEntry.w Obj57_Init ; 0 - Init
offsetTableEntry.w Obj57_Main ; 2 - Main Vehicle
offsetTableEntry.w Obj57_FallingStuff ; 4 - Spikes & Stones
; ===========================================================================
;loc_30FB8:
Obj57_Init:
move.l #Obj57_MapUnc_316EC,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_MCZBoss,0,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #3,priority(a0) ; gets overwritten
move.w #$21A0,x_pos(a0)
move.w #$560,y_pos(a0)
move.b #5,mainspr_mapframe(a0)
addq.b #2,boss_subtype(a0)
move.b #2,boss_routine(a0)
bset #6,render_flags(a0) ; use subobjects for rendering
move.b #4,mainspr_childsprites(a0)
move.b #$F,collision_flags(a0)
move.b #8,boss_hitcount2(a0)
move.w x_pos(a0),(Boss_X_pos).w
move.w y_pos(a0),(Boss_Y_pos).w
move.w #$C0,(Boss_Y_vel).w ; move down
move.b #0,(Boss_CollisionRoutine).w
move.b #1,(Screen_Shaking_Flag).w
move.b #$40,mainspr_width(a0)
move.w x_pos(a0),sub2_x_pos(a0)
move.w y_pos(a0),sub2_y_pos(a0)
move.b #2,sub2_mapframe(a0)
move.w x_pos(a0),sub3_x_pos(a0)
move.w y_pos(a0),sub3_y_pos(a0)
move.b #1,sub3_mapframe(a0)
move.w x_pos(a0),sub4_x_pos(a0)
move.w y_pos(a0),sub4_y_pos(a0)
move.b #$E,sub4_mapframe(a0)
move.w x_pos(a0),sub5_x_pos(a0)
move.w y_pos(a0),sub5_y_pos(a0)
move.b #2,sub5_mapframe(a0)
subi.w #$28,sub5_x_pos(a0)
move.w #$28,(Boss_Countdown).w
move.w #-$380,obj57_sub5_y_vel(a0)
move.w #-$380,obj57_sub2_y_vel(a0)
bsr.w Obj57_InitAnimationData
rts
; ===========================================================================
;loc_31090:
Obj57_InitAnimationData:
lea (Boss_AnimationArray).w,a2
move.b #2,(a2)+ ; hover thingies (fire on)
move.b #0,(a2)+
move.b #3,(a2)+ ; digger 1 (vertical)
move.b #0,(a2)+
move.b #$10,(a2)+ ; main vehicle
move.b #0,(a2)+
move.b #$D,(a2)+ ; main vehicle center (including robotnik's face)
move.b #0,(a2)+
move.b #3,(a2)+ ; digger 2 (vertical)
move.b #0,(a2)+
rts
; ===========================================================================
;loc_310BE:
Obj57_Main: ; Main Vehicle
moveq #0,d0
move.b boss_routine(a0),d0
move.w Obj57_Main_Index(pc,d0.w),d1
jmp Obj57_Main_Index(pc,d1.w)
; ===========================================================================
;off_310CC:
Obj57_Main_Index: offsetTable
offsetTableEntry.w Obj57_Main_Sub0 ; 0 - boss just moving up
offsetTableEntry.w Obj57_Main_Sub2 ; 2 - boss moving down, stuff falling down
offsetTableEntry.w Obj57_Main_Sub4 ; 4 - moving down, stop stuff falling down
offsetTableEntry.w Obj57_Main_Sub6 ; 6 - digger transition (rotation), moving back and forth
offsetTableEntry.w Obj57_Main_Sub8 ; 8 - boss defeated, standing still, exploding
offsetTableEntry.w Obj57_Main_SubA ; $A - slowly hovering down, no explosions
offsetTableEntry.w Obj57_Main_SubC ; $C - moving away fast
; ===========================================================================
;loc_310DA:
Obj57_Main_Sub0: ; boss just moving up
subi_.w #1,(Boss_Countdown).w ; countdown
bpl.s Obj57_Main_Sub0_Continue
move.b #0,(Boss_AnimationArray+5).w ; reset anim main vehicle
bsr.w Boss_MoveObject
cmpi.w #$560,(Boss_Y_pos).w ; a little above top screen boundary
bgt.s Obj57_Main_Sub0_Continue ; if below that, branch
move.w #$100,(Boss_Y_vel).w
move.w (MainCharacter+x_pos).w,d3
cmpi.w #$2190,d3
bhs.s +
move.w #$2200,d3
bra.s ++
; ===========================================================================
+
move.w #$2120,d3
+
move.w d3,(Boss_X_pos).w
addq.b #2,boss_routine(a0) ; stuff falling down
bclr #0,render_flags(a0)
move.w (MainCharacter+x_pos).w,d0
sub.w (Boss_X_pos).w,d0
bmi.s Obj57_Main_Sub0_Continue
bset #0,render_flags(a0)
;loc_3112C:
Obj57_Main_Sub0_Continue: ; if countdown finished or boss below $560
cmpi.w #$28,(Boss_Countdown).w
bne.s +
move.b #0,(Boss_CollisionRoutine).w
+
cmpi.w #$620,(Boss_Y_pos).w ; if above, screenshaking & stones
bge.s Obj57_Main_Sub0_Standard
move.b #1,(Screen_Shaking_Flag).w
bsr.w Obj57_SpawnStoneSpike
Obj57_Main_Sub0_Standard:
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
bsr.w Obj57_HandleHits
lea (Ani_obj57).l,a1
bsr.w AnimateBoss
bsr.w Obj57_TransferPositions
jmpto (DisplaySprite).l, JmpTo38_DisplaySprite
; ===========================================================================
;loc_3116E:
Obj57_Main_Sub2: ; boss moving down, stuff falling down
bsr.w Boss_MoveObject
bsr.w Obj57_SpawnStoneSpike
cmpi.w #$620,(Boss_Y_pos).w ; if below...
blt.s Obj57_Main_Sub2_Standard
addq.b #2,boss_routine(a0) ; ...next routine
move.b #0,(Screen_Shaking_Flag).w ; no screen shaking
Obj57_Main_Sub2_Standard:
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
bsr.w Obj57_HandleHits
lea (Ani_obj57).l,a1
bsr.w AnimateBoss
bsr.w Obj57_TransferPositions
jmpto (DisplaySprite).l, JmpTo38_DisplaySprite
; ===========================================================================
;loc_311AA:
Obj57_Main_Sub4: ; moving down, stop stuff falling down
bsr.w Boss_MoveObject
cmpi.w #$660,(Boss_Y_pos).w
blt.s Obj57_Main_Sub4_Standard ; if above, keep moving down
move.w #$660,(Boss_Y_pos).w ; if below, routine 6 + new anim
addq.b #2,boss_routine(a0)
lea (Boss_AnimationArray).w,a1
andi.b #$F0,2(a1)
ori.b #6,2(a1) ; (6) prepare for digger rotation to diag/hztl
andi.b #$F0,8(a1)
ori.b #6,8(a1) ; (6) prepare for digger rotation to diag/hztl
andi.b #$F0,6(a1)
ori.b #$D,6(a1) ; (D) robotnik face normal
move.b #$20,5(a1) ; main vehicle light on
move.w #$64,(Boss_Countdown).w
move.b #$30,1(a1) ; hover thingies fire off
bclr #0,render_flags(a0)
move.w (MainCharacter+x_pos).w,d0
sub.w (Boss_X_pos).w,d0
bmi.s +
bset #0,render_flags(a0)
+
move.w #-$200,(Boss_X_vel).w ; boss moving horizontally
move.w #0,(Boss_Y_vel).w
btst #0,render_flags(a0)
beq.s Obj57_Main_Sub4_Standard
neg.w (Boss_X_vel).w
Obj57_Main_Sub4_Standard:
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
bsr.w Obj57_HandleHits
lea (Ani_obj57).l,a1
bsr.w AnimateBoss
bsr.w Obj57_TransferPositions
jmpto (DisplaySprite).l, JmpTo38_DisplaySprite
; ===========================================================================
;loc_3124A:
Obj57_Main_Sub6: ; digger transition (rotation), moving back and forth
subi_.w #1,(Boss_Countdown).w
cmpi.w #$28,(Boss_Countdown).w
bgt.w Obj57_Main_Sub6_Standard
move.b #1,(Boss_CollisionRoutine).w
tst.w (Boss_Countdown).w
bpl.w Obj57_Main_Sub6_Standard
tst.b boss_hurt_sonic(a0) ; has sonic just been hurt?
beq.s +
sf boss_hurt_sonic(a0) ; if yes, clear this flag
bra.s Obj57_Main_Sub6_ReAscend1
; ===========================================================================
+
bsr.w Boss_MoveObject
cmpi.w #$2120,(Boss_X_pos).w
bgt.s +
move.w #$2120,(Boss_X_pos).w
bra.s Obj57_Main_Sub6_ReAscend2
; ===========================================================================
+
cmpi.w #$2200,(Boss_X_pos).w
blt.s Obj57_Main_Sub6_Standard
move.w #$2200,(Boss_X_pos).w
bra.s Obj57_Main_Sub6_ReAscend2
; ===========================================================================
;loc_31298:
Obj57_Main_Sub6_ReAscend1: ; that's a dumb name for a label
lea (Boss_AnimationArray).w,a1
move.b #$30,7(a1) ; face grin after hurting sonic
;loc_312A2:
Obj57_Main_Sub6_ReAscend2: ; set to routine 0 and make boss move up again
move.w #0,(Boss_X_vel).w
move.b #0,boss_routine(a0)
lea (Boss_AnimationArray).w,a1
andi.b #$F0,2(a1)
ori.b #$B,2(a1) ; (B) prepare for digger rotation to diag/vert
andi.b #$F0,8(a1)
ori.b #$B,8(a1) ; (B) prepare for digger rotation to diag/vert
move.b #0,1(a1) ; hover thingies fire on
andi.b #$F0,6(a1)
ori.b #$D,6(a1) ; (D) robotnik face normal
move.w #$64,(Boss_Countdown).w
move.w #-$C0,(Boss_Y_vel).w ; move up
Obj57_Main_Sub6_Standard:
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
bsr.w Obj57_HandleHits
lea (Ani_obj57).l,a1
bsr.w AnimateBoss
bsr.w Obj57_TransferPositions
jmpto (DisplaySprite).l, JmpTo38_DisplaySprite
; ===========================================================================
;loc_3130A:
Obj57_TransferPositions:
move.w x_pos(a0),d0
move.w y_pos(a0),d1
move.w d0,sub3_x_pos(a0)
move.w d1,sub3_y_pos(a0)
move.w d0,sub4_x_pos(a0)
move.w d1,sub4_y_pos(a0)
tst.b boss_defeated(a0)
bne.s Obj57_FallApart ; if boss defeated
move.w d0,sub5_x_pos(a0)
move.w d1,sub5_y_pos(a0)
move.w d0,sub2_x_pos(a0)
move.w d1,sub2_y_pos(a0)
move.w d1,obj57_sub5_y_pos2(a0)
move.w d1,obj57_sub2_y_pos2(a0)
btst #0,render_flags(a0)
beq.s +
addi.w #$28,sub5_x_pos(a0)
rts
; ===========================================================================
+
subi.w #$28,sub5_x_pos(a0)
rts
; ===========================================================================
;loc_31358:
Obj57_FallApart: ; make the digger thingies fall down
cmpi.w #$78,(Boss_Countdown).w
bgt.s return_313C4
subi_.w #1,sub5_x_pos(a0)
move.l obj57_sub5_y_pos2(a0),d0
move.w obj57_sub5_y_vel(a0),d1
addi.w #$38,obj57_sub5_y_vel(a0)
ext.l d1
asl.l #8,d1
add.l d1,d0
move.l d0,obj57_sub5_y_pos2(a0)
move.w obj57_sub5_y_pos2(a0),sub5_y_pos(a0)
cmpi.w #$6F0,sub5_y_pos(a0)
blt.s +
move.w #0,obj57_sub5_y_vel(a0)
+ ; second one
addi_.w #1,sub2_x_pos(a0)
move.l obj57_sub2_y_pos2(a0),d0
move.w obj57_sub2_y_vel(a0),d1
addi.w #$38,obj57_sub2_y_vel(a0)
ext.l d1
asl.l #8,d1
add.l d1,d0
move.l d0,obj57_sub2_y_pos2(a0)
move.w obj57_sub2_y_pos2(a0),sub2_y_pos(a0)
cmpi.w #$6F0,sub2_y_pos(a0)
blt.s return_313C4
move.w #0,obj57_sub2_y_vel(a0)
return_313C4:
rts
; ===========================================================================
;loc_313C6:
Obj57_SpawnStoneSpike: ; decide whether stone or spike
move.b (Vint_runcount+3).w,d1 ; not so random number?
sf d2
andi.b #$1F,d1
beq.s Obj57_LoadStoneSpike
andi.b #7,d1
bne.s return_31438
st d2
;loc_313DA:
Obj57_LoadStoneSpike:
jsrto (RandomNumber).l, JmpTo4_RandomNumber
swap d1
andi.w #$1FF,d1
addi.w #$20F0,d1
cmpi.w #$2230,d1
bgt.s Obj57_LoadStoneSpike
jsrto (SingleObjLoad).l, JmpTo15_SingleObjLoad
bne.s return_31438
move.b #ObjID_MCZBoss,id(a1) ; load obj57
move.b #4,boss_subtype(a1)
move.w d1,x_pos(a1)
move.w #$5F0,y_pos(a1)
move.l #Obj57_MapUnc_316EC,mappings(a1)
move.w #make_art_tile(ArtTile_ArtUnc_FallingRocks,0,0),art_tile(a1)
ori.b #4,render_flags(a1)
move.b #3,priority(a1)
move.b #$D,mapping_frame(a1)
tst.b d2
bne.s return_31438 ; stone
move.b #$14,mapping_frame(a1) ; spike
move.b #$B1,collision_flags(a1)
return_31438:
rts
; ===========================================================================
;loc_3143A:
Obj57_HandleHits:
bsr.w Obj57_HandleHits_Main
cmpi.b #$1F,boss_invulnerable_time(a0)
bne.s + ; rts
lea (Boss_AnimationArray).w,a1
move.b #$C0,7(a1) ; face grin when hit
+
rts
; ===========================================================================
;loc_31452:
Obj57_AddSinusOffset: ; called from routine $A and $C
move.b boss_sine_count(a0),d0 ; sinus offset something
jsr (CalcSine).l
asr.w #6,d0
add.w (Boss_Y_pos).w,d0
move.w d0,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
addq.b #2,boss_sine_count(a0) ; increment frame counter for sinus offset
;loc_31470:
Obj57_HandleHits_Main:
cmpi.b #8,boss_routine(a0)
bhs.s return_314B6 ; skip if boss already defeated
tst.b boss_hitcount2(a0)
beq.s Obj57_FinalDefeat
tst.b collision_flags(a0)
bne.s return_314B6
tst.b boss_invulnerable_time(a0)
bne.s +
move.b #$20,boss_invulnerable_time(a0) ; set invincibility timer
move.w #SndID_BossHit,d0
jsr (PlaySound).l
+
lea (Normal_palette_line2+2).w,a1
moveq #0,d0
tst.w (a1)
bne.s +
move.w #$EEE,d0
+
move.w d0,(a1)
subq.b #1,boss_invulnerable_time(a0)
bne.s return_314B6
move.b #$F,collision_flags(a0)
return_314B6:
rts
; ===========================================================================
;loc_314B8:
Obj57_FinalDefeat:
moveq #100,d0
jsrto (AddPoints).l, JmpTo6_AddPoints
move.w #$B3,(Boss_Countdown).w
move.b #8,boss_routine(a0) ; routine boss defeated
moveq #PLCID_Capsule,d0
jsrto (LoadPLC).l, JmpTo9_LoadPLC
rts
; ===========================================================================
;loc_314D2:
Obj57_Main_Sub8: ; boss defeated, standing still, exploding
st boss_defeated(a0)
move.b #0,(Screen_Shaking_Flag).w
subq.w #1,(Boss_Countdown).w ; countdown initially $B3
bmi.s + ; branch if countdown finished
move.b #$13,sub4_mapframe(a0) ; burnt face
move.b #7,mainspr_mapframe(a0)
bsr.w Boss_LoadExplosion
bra.s Obj57_Main_Sub8_Standard
; ===========================================================================
+
bset #0,render_flags(a0)
clr.w (Boss_X_vel).w
clr.w (Boss_Y_vel).w
addq.b #2,boss_routine(a0) ; next routine
move.b #$12,sub4_mapframe(a0) ; face grin when hit
move.w #-$12,(Boss_Countdown).w
Obj57_Main_Sub8_Standard:
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
bsr.w Obj57_TransferPositions
jmpto (DisplaySprite).l, JmpTo38_DisplaySprite
; ===========================================================================
;loc_31526:
Obj57_Main_SubA: ; slowly hovering down, no explosions
addq.w #1,(Boss_Countdown).w ; countdown initially -$12
beq.s ++ ; reset y_vel
bpl.s +++
cmpi.w #$620,(Boss_Y_pos).w
bhs.s +
subq.w #1,(Boss_Countdown).w
+
addi.w #$10,(Boss_Y_vel).w ; add gravity
bra.s Obj57_Main_SubA_Standard
; ===========================================================================
+
clr.w (Boss_Y_vel).w
bra.s Obj57_Main_SubA_Standard
; ===========================================================================
+
cmpi.w #$18,(Boss_Countdown).w
blo.s + ; accelerate boss upwards
beq.s ++ ; reset y_vel, PlayLevelMusic
cmpi.w #$20,(Boss_Countdown).w
blo.s Obj57_Main_SubA_Standard
lea (Boss_AnimationArray).w,a1
move.b #$D,7(a1) ; face grin when hit
_move.b #2,0(a2) ; There is a bug here. This should be a1 instead of a2. A random part of RAM gets written to instead.
move.b #0,1(a1) ; hover thingies fire off
addq.b #2,boss_routine(a0)
bra.s Obj57_Main_SubA_Standard
; ===========================================================================
+
subi_.w #8,(Boss_Y_vel).w
bra.s Obj57_Main_SubA_Standard
; ===========================================================================
+
clr.w (Boss_Y_vel).w
jsrto (PlayLevelMusic).l, JmpTo5_PlayLevelMusic
jsrto (LoadPLC_AnimalExplosion).l, JmpTo5_LoadPLC_AnimalExplosion
;loc_3158A:
Obj57_Main_SubA_Standard:
bsr.w Boss_MoveObject
bsr.w Obj57_AddSinusOffset
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
bsr.w Obj57_TransferPositions
jmpto (DisplaySprite).l, JmpTo38_DisplaySprite
; ===========================================================================
;loc_315A6:
Obj57_Main_SubC: ; moving away fast
move.w #$400,(Boss_X_vel).w
move.w #-$40,(Boss_Y_vel).w ; escape to the right
cmpi.w #$2240,(Camera_Max_X_pos).w
beq.s +
addq.w #2,(Camera_Max_X_pos).w
bra.s Obj57_Main_SubC_Standard
; ===========================================================================
+
tst.b render_flags(a0)
bpl.s JmpTo56_DeleteObject ; if off screen
;loc_315C6:
Obj57_Main_SubC_Standard:
bsr.w Boss_MoveObject
bsr.w Obj57_AddSinusOffset
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
lea (Ani_obj57).l,a1
bsr.w AnimateBoss
bsr.w Obj57_TransferPositions
jmpto (DisplaySprite).l, JmpTo38_DisplaySprite
; ===========================================================================
JmpTo56_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
;loc_315F2:
Obj57_FallingStuff: ; Spikes & Stones
jsrto (ObjectMoveAndFall).l, JmpTo5_ObjectMoveAndFall
subi.w #$28,sub2_y_pos(a0) ; decrease gravity
cmpi.w #$6F0,y_pos(a0) ; if below boundary, delete
if ~~removeJmpTos
bgt.w JmpTo57_DeleteObject
else
bgt.s JmpTo56_DeleteObject
endif
jmpto (DisplaySprite).l, JmpTo38_DisplaySprite
; ===========================================================================
; off_3160A: Obj57_AnimIndex:
Ani_obj57: offsetTable
offsetTableEntry.w byte_31628 ; 0 - main vehicle
offsetTableEntry.w byte_3162E ; 1 - digger diagonal
offsetTableEntry.w byte_31631 ; 2 - hover fire thingies to keep boss in air
offsetTableEntry.w byte_31638 ; 3 - digger vertical animated 1 -> (4)
offsetTableEntry.w byte_31649 ; 4 - digger vertical animated 2 -> (5)
offsetTableEntry.w byte_3165A ; 5 - digger vertical animated 3 (loop)
offsetTableEntry.w byte_31661 ; 6 - digger vertical animated 4 -> (7)
offsetTableEntry.w byte_31673 ; 7 - digger vertical + diagonal transition -> (8)
offsetTableEntry.w byte_31684 ; 8 - digger horizontal animated 1 -> (9)
offsetTableEntry.w byte_31695 ; 9 - digger horizontal animated 2 -> (A)
offsetTableEntry.w byte_316A6 ; A - digger horizontal animated 3 (loop)
offsetTableEntry.w byte_316AD ; B - digger horizontal animated 4 -> (C)
offsetTableEntry.w byte_316BF ; C - digger horizontal + diagonal transition -> (3)
offsetTableEntry.w byte_316D1 ; D - center vehicle, robotnik's face normal
offsetTableEntry.w byte_316E8 ; E - center vehicle, robotnik's face when hit
byte_31628: dc.b $F, 1,$FF ; light off
dc.b 0,$FC, 2 ; light on; (3) subanimation
rev02even
byte_3162E: dc.b 5, 8,$FF
rev02even
byte_31631: dc.b 1, 5, 6,$FF ; fire on
dc.b 7,$FC, 3 ; fire off; (4) subanimation
rev02even
byte_31638: dc.b 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4,$FD, 4
rev02even
byte_31649: dc.b 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 2, 2, 3, 3,$FD, 5
rev02even
byte_3165A: dc.b 1, 4, 2, 3, 4,$FC, 1
rev02even
byte_31661: dc.b 1, 2, 3, 4, 4, 2, 2, 3, 3, 3, 4, 4, 4, 2, 2, 2,$FD, 7
rev02even
byte_31673: dc.b 1, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 2, 8, 8, 8,$FD, 8
rev02even
byte_31684: dc.b 1, 9, 9, 9, 9, 9, $A, $A, $A, $A, $A, $B, $B, $B, $B,$FD, 9
rev02even
byte_31695: dc.b 1, 9, 9, 9, 9, $A, $A, $A, $B, $B, $B, 9, 9, $A, $A,$FD, $A
rev02even
byte_316A6: dc.b 1, $B, 9, $A, $B,$FC, 1
rev02even
byte_316AD: dc.b 1, 9, $A, $B, $B, 9, 9, $A, $A, $A, $B, $B, $B, 9, 9, 9,$FD, $C
rev02even
byte_316BF: dc.b 1, 9, $A, $A, $A, $A, $B, $B, $B, $B, $B, 9, 8, 8, 8, 8,$FD, 3
rev02even
byte_316D1: dc.b 7, $E, $F,$FF
dc.b $10,$11,$10,$11,$10,$11,$10,$11,$FF ; (4) subanimation (grin after hurting sonic)
dc.b $12,$12,$12,$12,$12,$12,$12,$12,$12,$FF ; (D) subanimation (grin when hit)
rev02even
byte_316E8: dc.b 7,$12,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj57_MapUnc_316EC: BINCLUDE "mappings/sprite/obj57.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo38_DisplaySprite
jmp (DisplaySprite).l
JmpTo57_DeleteObject
jmp (DeleteObject).l
JmpTo15_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo4_RandomNumber
jmp (RandomNumber).l
JmpTo9_LoadPLC
jmp (LoadPLC).l
JmpTo6_AddPoints
jmp (AddPoints).l
JmpTo5_PlayLevelMusic
jmp (PlayLevelMusic).l
JmpTo5_LoadPLC_AnimalExplosion
jmp (LoadPLC_AnimalExplosion).l
JmpTo5_ObjectMoveAndFall
jmp (ObjectMoveAndFall).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 51 - CNZ boss
; ----------------------------------------------------------------------------
; Sprite_318F0:
Obj51:
moveq #0,d0
move.b boss_subtype(a0),d0
move.w Obj51_Index(pc,d0.w),d1
jmp Obj51_Index(pc,d1.w)
; ===========================================================================
; off_318FE:
Obj51_Index: offsetTable
offsetTableEntry.w Obj51_Init ; 0
offsetTableEntry.w loc_31A04 ; 2
offsetTableEntry.w loc_31F24 ; 4
; ===========================================================================
; loc_31904:
Obj51_Init:
move.l #Obj51_MapUnc_320EA,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CNZBoss_Fudge,0,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #3,priority(a0)
move.w #$2A46,x_pos(a0)
move.w #$654,y_pos(a0)
move.b #0,mainspr_mapframe(a0)
move.b #$20,mainspr_width(a0)
move.b #$80,mainspr_height(a0)
addq.b #2,boss_subtype(a0)
move.b #0,angle(a0)
bset #6,render_flags(a0)
move.b #4,mainspr_childsprites(a0)
move.b #$F,collision_flags(a0)
move.b #8,objoff_32(a0)
move.w x_pos(a0),(Boss_X_pos).w
move.w y_pos(a0),(Boss_Y_pos).w
move.w x_pos(a0),sub2_x_pos(a0)
move.w y_pos(a0),sub2_y_pos(a0)
move.b #5,sub2_mapframe(a0)
move.w x_pos(a0),sub3_x_pos(a0)
move.w y_pos(a0),sub3_y_pos(a0)
move.b #1,sub3_mapframe(a0)
move.w x_pos(a0),sub4_x_pos(a0)
move.w y_pos(a0),sub4_y_pos(a0)
move.b #6,sub4_mapframe(a0)
move.w x_pos(a0),sub5_x_pos(a0)
move.w y_pos(a0),sub5_y_pos(a0)
move.b #2,sub5_mapframe(a0)
move.b #0,objoff_38(a0)
move.w #0,(Boss_Y_vel).w
move.w #-$180,(Boss_X_vel).w
move.b #0,objoff_2D(a0)
move.w #1,(Boss_Countdown).w
bsr.w loc_319D6
rts
; ===========================================================================
loc_319D6:
lea (Boss_AnimationArray).w,a2
move.b #8,(a2)+
move.b #0,(a2)+
move.b #1,(a2)+
move.b #0,(a2)+
move.b #$10,(a2)+
move.b #0,(a2)+
move.b #3,(a2)+
move.b #0,(a2)+
move.b #2,(a2)+
move.b #0,(a2)+
rts
; ===========================================================================
loc_31A04:
tst.b (Boss_CollisionRoutine).w
beq.s loc_31A1C
move.b (Vint_runcount+3).w,d0
andi.b #$1F,d0
bne.s loc_31A1C
move.b #SndID_CNZBossZap,d0
jsrto (PlaySound).l, JmpTo9_PlaySound
loc_31A1C:
moveq #0,d0
move.b angle(a0),d0
move.w off_31A2A(pc,d0.w),d1
jmp off_31A2A(pc,d1.w)
; ===========================================================================
off_31A2A: offsetTable
offsetTableEntry.w loc_31A36 ; 0
offsetTableEntry.w loc_31BA8 ; 2
offsetTableEntry.w loc_31C22 ; 4
offsetTableEntry.w loc_31D5C ; 6
offsetTableEntry.w loc_31DCC ; 8
offsetTableEntry.w loc_31E2A ; $A
; ===========================================================================
loc_31A36:
moveq #0,d0
move.b objoff_38(a0),d0
move.w off_31A44(pc,d0.w),d0
jmp off_31A44(pc,d0.w)
; ===========================================================================
off_31A44: offsetTable
offsetTableEntry.w loc_31A48 ; 0
offsetTableEntry.w loc_31A78 ; 2
; ===========================================================================
loc_31A48:
cmpi.w #$28C0,(Boss_X_pos).w
bgt.s BranchTo_loc_31AA4
move.w #$28C0,(Boss_X_pos).w
move.w #0,(Boss_Y_vel).w
move.w #$180,(Boss_X_vel).w
move.b #2,objoff_38(a0)
bset #0,render_flags(a0)
move.b #0,objoff_2D(a0)
BranchTo_loc_31AA4
bra.w loc_31AA4
; ===========================================================================
loc_31A78:
cmpi.w #$29C0,(Boss_X_pos).w
blt.s loc_31AA4
move.w #$29C0,(Boss_X_pos).w
move.w #0,(Boss_Y_vel).w
move.w #-$180,(Boss_X_vel).w
move.b #0,objoff_38(a0)
bclr #0,render_flags(a0)
move.b #0,objoff_2D(a0)
loc_31AA4:
bsr.w Boss_MoveObject
tst.b objoff_3F(a0)
beq.s loc_31AB6
subq.b #1,objoff_3F(a0)
bra.w loc_31B46
; ===========================================================================
loc_31AB6:
move.w (MainCharacter+x_pos).w,d0
sub.w x_pos(a0),d0
addi.w #$10,d0
cmpi.w #$20,d0
bhs.s loc_31B46
cmpi.w #$6B0,(MainCharacter+y_pos).w
blo.s loc_31B06
cmpi.b #3,objoff_2D(a0)
bhs.s loc_31B46
addq.b #1,objoff_2D(a0)
addq.b #2,angle(a0)
move.b #8,(Boss_AnimationArray).w
move.b #0,(Boss_AnimationArray+3).w
move.b #0,(Boss_AnimationArray+9).w
move.b #0,(Boss_CollisionRoutine).w
bsr.w loc_31BF2
move.w #$50,(Boss_Countdown).w
bra.w loc_31C08
; ===========================================================================
loc_31B06:
cmpi.w #$67C,(MainCharacter+y_pos).w
blo.s loc_31B46
move.b #$F,mainspr_mapframe(a0)
move.b #2,(Boss_CollisionRoutine).w
move.b #$20,(Boss_AnimationArray+3).w
move.b #$20,(Boss_AnimationArray+9).w
move.b #9,(Boss_AnimationArray).w
addq.b #4,angle(a0)
move.w #0,(Boss_X_vel).w
move.w #$180,(Boss_Y_vel).w
move.b #0,objoff_3E(a0)
bra.w loc_31C08
; ===========================================================================
loc_31B46:
bra.w +
+ addi_.w #1,(Boss_Countdown).w
move.w (Boss_Countdown).w,d0
andi.w #$3F,d0
bne.w loc_31C08
btst #6,(Boss_Countdown+1).w
beq.s loc_31B86
move.b #$F,mainspr_mapframe(a0)
move.b #2,(Boss_CollisionRoutine).w
move.b #$20,(Boss_AnimationArray+3).w
move.b #$20,(Boss_AnimationArray+9).w
move.b #9,(Boss_AnimationArray).w
bra.w loc_31C08
; ===========================================================================
loc_31B86:
move.b #$C,mainspr_mapframe(a0)
move.b #1,(Boss_CollisionRoutine).w
move.b #0,(Boss_AnimationArray+3).w
move.b #0,(Boss_AnimationArray+9).w
move.b #4,(Boss_AnimationArray).w
bra.w loc_31C08
; ===========================================================================
loc_31BA8:
move.b #0,(Boss_CollisionRoutine).w
subi_.w #1,(Boss_Countdown).w
bne.s loc_31BC6
move.b #$20,(Boss_AnimationArray+3).w
move.b #$20,(Boss_AnimationArray+9).w
bra.w loc_31C08
; ===========================================================================
loc_31BC6:
cmpi.w #-$14,(Boss_Countdown).w
bgt.w loc_31C08
move.b #0,(Boss_AnimationArray+3).w
move.b #0,(Boss_AnimationArray+9).w
move.b #0,angle(a0)
move.w #-1,(Boss_Countdown).w
move.b #$40,objoff_3F(a0)
bra.w loc_31C08
; ===========================================================================
loc_31BF2:
jsrto (SingleObjLoad).l, JmpTo16_SingleObjLoad
bne.s return_31C06
move.b #ObjID_CNZBoss,id(a1) ; load obj51
move.b #4,boss_subtype(a1)
move.l a0,objoff_34(a1)
return_31C06:
rts
; ===========================================================================
loc_31C08:
bsr.w loc_31CDC
bsr.w loc_31E76
bsr.w loc_31C92
lea (Ani_obj51).l,a1
bsr.w AnimateBoss
if removeJmpTos
JmpTo39_DisplaySprite
endif
jmpto (DisplaySprite).l, JmpTo39_DisplaySprite
; ===========================================================================
loc_31C22:
bsr.w Boss_MoveObject
tst.b objoff_3E(a0)
bne.s loc_31C60
cmpi.w #$680,y_pos(a0)
blo.s loc_31C08
move.w #0,(Boss_X_vel).w
move.w #-$180,(Boss_Y_vel).w
move.b #-1,objoff_3E(a0)
move.b #1,(Boss_CollisionRoutine).w
move.b #0,(Boss_AnimationArray+3).w
move.b #0,(Boss_AnimationArray+9).w
move.b #4,(Boss_AnimationArray).w
bra.s loc_31C08
; ===========================================================================
loc_31C60:
cmpi.w #$654,y_pos(a0)
bhs.s loc_31C08
move.b #0,angle(a0)
move.w #0,(Boss_Y_vel).w
move.w #-$180,(Boss_X_vel).w
btst #0,render_flags(a0)
beq.s BranchTo_loc_31C08
move.w #$180,(Boss_X_vel).w
move.b #$C,mainspr_mapframe(a0)
BranchTo_loc_31C08
bra.w loc_31C08
; ===========================================================================
loc_31C92:
cmpi.b #$2F,mainspr_height(a0)
bne.s loc_31CAC
lea (Boss_AnimationArray).w,a1
andi.b #$F0,6(a1)
ori.b #6,6(a1)
rts
; ===========================================================================
loc_31CAC:
cmpi.b #4,(MainCharacter+routine).w
beq.s loc_31CBC
cmpi.b #4,(Sidekick+routine).w
bne.s return_31CDA
loc_31CBC:
lea (Boss_AnimationArray).w,a1
move.b 6(a1),d0
andi.b #$F,d0
cmpi.b #6,d0
beq.s return_31CDA
andi.b #$F0,6(a1)
ori.b #5,6(a1)
return_31CDA:
rts
; ===========================================================================
loc_31CDC:
move.b mapping_frame(a0),d0
jsr (CalcSine).l
asr.w #6,d0
add.w (Boss_Y_pos).w,d0
move.w d0,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
addq.b #2,mapping_frame(a0)
cmpi.b #6,angle(a0)
bhs.s return_31D40
tst.b objoff_32(a0)
beq.s loc_31D42
tst.b collision_flags(a0)
bne.s return_31D40
tst.b mainspr_height(a0)
bne.s loc_31D24
move.b #$30,mainspr_height(a0)
move.w #SndID_BossHit,d0
jsr (PlaySound).l
loc_31D24:
lea (Normal_palette_line2+2).w,a1
moveq #0,d0
tst.w (a1)
bne.s loc_31D32
move.w #$EEE,d0
loc_31D32:
move.w d0,(a1)
subq.b #1,mainspr_height(a0)
bne.s return_31D40
move.b #$F,collision_flags(a0)
return_31D40:
rts
; ===========================================================================
loc_31D42:
moveq #100,d0
jsrto (AddPoints).l, JmpTo7_AddPoints
move.w #$B3,(Boss_Countdown).w
move.b #6,angle(a0)
moveq #PLCID_Capsule,d0
jsrto (LoadPLC).l, JmpTo10_LoadPLC
rts
; ===========================================================================
loc_31D5C:
st objoff_2C(a0)
subq.w #1,(Boss_Countdown).w
bmi.s loc_31D7E
move.b #0,(Boss_CollisionRoutine).w
move.b #0,mainspr_mapframe(a0)
move.b #$B,collision_property(a0)
bsr.w Boss_LoadExplosion
bra.s loc_31DB8
; ===========================================================================
loc_31D7E:
bset #0,render_flags(a0)
clr.w (Boss_X_vel).w
clr.w (Boss_Y_vel).w
addq.b #2,angle(a0)
lea (Boss_AnimationArray).w,a1
andi.b #$F0,6(a1)
ori.b #3,6(a1)
_move.b #8,0(a1)
move.b #$DD,(Level_Layout+$C54).w
move.b #1,(Screen_redraw_flag).w
move.w #-$12,(Boss_Countdown).w
loc_31DB8:
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
bsr.w loc_31E76
jmpto (DisplaySprite).l, JmpTo39_DisplaySprite
; ===========================================================================
loc_31DCC:
addq.w #1,(Boss_Countdown).w
beq.s loc_31DDC
bpl.s loc_31DE2
addi.w #$18,(Boss_Y_vel).w
bra.s loc_31E0E
; ===========================================================================
loc_31DDC:
clr.w (Boss_Y_vel).w
bra.s loc_31E0E
; ===========================================================================
loc_31DE2:
cmpi.w #$18,(Boss_Countdown).w
blo.s loc_31DFA
beq.s loc_31E02
cmpi.w #$20,(Boss_Countdown).w
blo.s loc_31E0E
addq.b #2,angle(a0)
bra.s loc_31E0E
; ===========================================================================
loc_31DFA:
subi_.w #8,(Boss_Y_vel).w
bra.s loc_31E0E
; ===========================================================================
loc_31E02:
clr.w (Boss_Y_vel).w
jsrto (PlayLevelMusic).l, JmpTo6_PlayLevelMusic
jsrto (LoadPLC_AnimalExplosion).l, JmpTo6_LoadPLC_AnimalExplosion
loc_31E0E:
bsr.w Boss_MoveObject
bsr.w loc_31CDC
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
bsr.w loc_31E76
jmpto (DisplaySprite).l, JmpTo39_DisplaySprite
; ===========================================================================
loc_31E2A:
move.w #$400,(Boss_X_vel).w
move.w #-$40,(Boss_Y_vel).w
cmpi.w #$2B20,(Camera_Max_X_pos).w
beq.s loc_31E44
addq.w #2,(Camera_Max_X_pos).w
bra.s loc_31E4A
; ===========================================================================
loc_31E44:
tst.b render_flags(a0)
bpl.s JmpTo58_DeleteObject
loc_31E4A:
bsr.w Boss_MoveObject
bsr.w loc_31CDC
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
bsr.w loc_31E76
lea (Ani_obj51).l,a1
bsr.w AnimateBoss
jmpto (DisplaySprite).l, JmpTo39_DisplaySprite
; ===========================================================================
if removeJmpTos
JmpTo59_DeleteObject
endif
JmpTo58_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
loc_31E76:
move.w x_pos(a0),d0
move.w y_pos(a0),d1
move.w d0,sub3_x_pos(a0)
move.w d1,sub3_y_pos(a0)
move.w d0,sub4_x_pos(a0)
move.w d1,sub4_y_pos(a0)
tst.b objoff_2C(a0)
bne.s loc_31EAE
move.w d0,sub5_x_pos(a0)
move.w d1,sub5_y_pos(a0)
move.w d0,sub2_x_pos(a0)
move.w d1,sub2_y_pos(a0)
move.w d1,objoff_3A(a0)
move.w d1,objoff_34(a0)
rts
; ===========================================================================
loc_31EAE:
cmpi.w #$78,(Boss_Countdown).w
bgt.s return_31F22
subi_.w #1,sub5_x_pos(a0)
move.l objoff_3A(a0),d0
move.w objoff_2E(a0),d1
addi.w #$38,objoff_2E(a0)
ext.l d1
asl.l #8,d1
add.l d1,d0
move.l d0,objoff_3A(a0)
move.w objoff_3A(a0),sub5_y_pos(a0)
cmpi.w #$6F0,sub5_y_pos(a0)
blt.s loc_31EE8
move.w #0,objoff_2E(a0)
loc_31EE8:
cmpi.w #$3C,(Boss_Countdown).w
bgt.s return_31F22
addi_.w #1,sub2_x_pos(a0)
move.l objoff_34(a0),d0
move.w objoff_30(a0),d1
addi.w #$38,objoff_30(a0)
ext.l d1
asl.l #8,d1
add.l d1,d0
move.l d0,objoff_34(a0)
move.w objoff_34(a0),sub2_y_pos(a0)
cmpi.w #$6F0,sub2_y_pos(a0)
blt.s return_31F22
move.w #0,objoff_30(a0)
return_31F22:
rts
; ===========================================================================
loc_31F24:
movea.l objoff_34(a0),a1 ; a1=object
cmpi.b #6,angle(a1)
bhs.w JmpTo59_DeleteObject
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_31F40(pc,d0.w),d1
jmp off_31F40(pc,d1.w)
; ===========================================================================
off_31F40: offsetTable
offsetTableEntry.w loc_31F48 ; 0
offsetTableEntry.w loc_31F96 ; 2
offsetTableEntry.w loc_31FDC ; 4
offsetTableEntry.w loc_32080 ; 6
; ===========================================================================
loc_31F48:
move.l #Obj51_MapUnc_320EA,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_CNZBoss_Fudge,0,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #7,priority(a0)
addq.b #2,routine_secondary(a0)
movea.l objoff_34(a0),a1 ; a1=object
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
addi.w #$30,y_pos(a0)
move.b #8,y_radius(a0)
move.b #8,x_radius(a0)
move.b #$12,mapping_frame(a0)
move.b #$98,collision_flags(a0)
rts
; ===========================================================================
loc_31F96:
movea.l objoff_34(a0),a1 ; a1=object
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
move.w objoff_28(a0),d0
add.w d0,y_pos(a0)
addi_.w #1,d0
cmpi.w #$2E,d0
blt.s +
move.w #$2E,d0
+
move.w d0,objoff_28(a0)
tst.w (Boss_Countdown).w
bne.w JmpTo39_DisplaySprite
addq.b #2,routine_secondary(a0)
move.w #0,x_vel(a0)
move.w #0,y_vel(a0)
jmpto (DisplaySprite).l, JmpTo39_DisplaySprite
; ===========================================================================
loc_31FDC:
bsr.w loc_31FF8
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.w JmpTo39_DisplaySprite
add.w d1,y_pos(a0)
bsr.w loc_32030
jmpto (DisplaySprite).l, JmpTo39_DisplaySprite
; ===========================================================================
loc_31FF8:
moveq #0,d2
move.w x_pos(a0),d2
swap d2
moveq #0,d3
move.w y_pos(a0),d3
swap d3
move.w x_vel(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d2
move.w y_vel(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d3
addi.w #$38,y_vel(a0)
swap d2
move.w d2,x_pos(a0)
swap d3
move.w d3,y_pos(a0)
rts
; ===========================================================================
loc_32030:
move.b #SndID_BossExplosion,d0
jsrto (PlaySound).l, JmpTo9_PlaySound
move.w #make_art_tile(ArtTile_ArtNem_CNZBoss_Fudge,0,0),art_tile(a0)
move.b #7,anim(a0)
move.w #-$300,y_vel(a0)
move.w #-$100,x_vel(a0)
move.b #4,boss_subtype(a0)
move.b #6,routine_secondary(a0)
move.b #$98,collision_flags(a0)
jsrto (SingleObjLoad2).l, JmpTo23_SingleObjLoad2
bne.s return_3207E
moveq #0,d0
move.w #bytesToLcnt(object_size),d1
loc_3206E:
move.l (a0,d0.w),(a1,d0.w)
addq.w #4,d0
dbf d1,loc_3206E
if object_size&3
move.w (a0,d0.w),(a1,d0.w)
endif
neg.w x_vel(a1)
return_3207E:
rts
; ===========================================================================
loc_32080:
bsr.w loc_31FF8
lea (Ani_obj51).l,a1
jsrto (AnimateSprite).l, JmpTo20_AnimateSprite
cmpi.w #$705,y_pos(a0)
blo.w JmpTo39_DisplaySprite
jmpto JmpTo59_DeleteObject, JmpTo59_DeleteObject
; ===========================================================================
; animation script
; off_3209C:
Ani_obj51: offsetTable
offsetTableEntry.w byte_320B0 ; 0
offsetTableEntry.w byte_320B3 ; 1
offsetTableEntry.w byte_320B9 ; 2
offsetTableEntry.w byte_320BF ; 3
offsetTableEntry.w byte_320C3 ; 4
offsetTableEntry.w byte_320C8 ; 5
offsetTableEntry.w byte_320D3 ; 6
offsetTableEntry.w byte_320DD ; 7
offsetTableEntry.w byte_320E1 ; 8
offsetTableEntry.w byte_320E4 ; 9
byte_320B0: dc.b $F, 1,$FF
rev02even
byte_320B3: dc.b $F, 4,$FF, 5,$FC, 2
rev02even
byte_320B9: dc.b $F, 2,$FF, 3,$FC, 2
rev02even
byte_320BF: dc.b 7, 6, 7,$FF
rev02even
byte_320C3: dc.b 1, $C, $D, $E,$FF
rev02even
byte_320C8: dc.b 7, 8, 9, 8, 9, 8, 9, 8, 9,$FD, 3
rev02even
byte_320D3: dc.b 7, $A, $A, $A, $A, $A, $A, $A,$FD, 3
rev02even
byte_320DD: dc.b 3,$13,$14,$FF
rev02even
byte_320E1: dc.b 1, 0,$FF
rev02even
byte_320E4: dc.b 1, $F,$10,$11,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj51_MapUnc_320EA: BINCLUDE "mappings/sprite/obj51.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo39_DisplaySprite
jmp (DisplaySprite).l
JmpTo59_DeleteObject
jmp (DeleteObject).l
JmpTo16_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo9_PlaySound
jmp (PlaySound).l
JmpTo23_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo20_AnimateSprite
jmp (AnimateSprite).l
JmpTo10_LoadPLC
jmp (LoadPLC).l
JmpTo7_AddPoints
jmp (AddPoints).l
JmpTo6_PlayLevelMusic
jmp (PlayLevelMusic).l
JmpTo6_LoadPLC_AnimalExplosion
jmp (LoadPLC_AnimalExplosion).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 54 - MTZ boss
; ----------------------------------------------------------------------------
; Sprite_32288:
Obj54:
moveq #0,d0
move.b boss_subtype(a0),d0
move.w Obj54_Index(pc,d0.w),d1
jmp Obj54_Index(pc,d1.w)
; ===========================================================================
; off_32296:
Obj54_Index: offsetTable
offsetTableEntry.w Obj54_Init ; 0
offsetTableEntry.w Obj54_Main ; 2
offsetTableEntry.w Obj54_Laser ; 4
offsetTableEntry.w Obj54_LaserShooter ; 6
; ===========================================================================
; loc_3229E:
Obj54_Init:
move.l #Obj54_MapUnc_32DC6,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_MTZBoss,0,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #3,priority(a0)
move.w #$2B50,x_pos(a0)
move.w #$380,y_pos(a0)
move.b #2,mainspr_mapframe(a0)
addq.b #2,boss_subtype(a0) ; => Obj54_Main
bset #6,render_flags(a0)
move.b #2,mainspr_childsprites(a0)
move.b #$F,collision_flags(a0)
move.b #8,boss_hitcount2(a0)
move.b #7,objoff_3E(a0)
move.w x_pos(a0),(Boss_X_pos).w
move.w y_pos(a0),(Boss_Y_pos).w
move.w #0,(Boss_X_vel).w
move.w #$100,(Boss_Y_vel).w
move.b #$20,mainspr_width(a0)
clr.b objoff_2B(a0)
clr.b objoff_2C(a0)
move.b #$40,mapping_frame(a0)
move.b #$27,objoff_33(a0)
move.b #$27,objoff_39(a0)
move.w x_pos(a0),sub2_x_pos(a0)
move.w y_pos(a0),sub2_y_pos(a0)
move.b #$C,sub2_mapframe(a0)
move.w x_pos(a0),sub3_x_pos(a0)
move.w y_pos(a0),sub3_y_pos(a0)
move.b #0,sub3_mapframe(a0)
jsrto (SingleObjLoad).l, JmpTo17_SingleObjLoad
bne.s +
move.b #ObjID_MTZBoss,id(a1) ; load obj54
move.b #6,boss_subtype(a1) ; => Obj54_LaserShooter
move.b #$13,mapping_frame(a1)
move.l #Obj54_MapUnc_32DC6,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_MTZBoss,0,0),art_tile(a1)
ori.b #4,render_flags(a1)
move.b #6,priority(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.l a0,objoff_34(a1)
move.b #$20,width_pixels(a1)
jsrto (SingleObjLoad).l, JmpTo17_SingleObjLoad
bne.s +
move.b #ObjID_MTZBossOrb,id(a1) ; load obj53
move.l a0,objoff_34(a1)
+
lea (Boss_AnimationArray).w,a2
move.b #$10,(a2)+
move.b #0,(a2)+
move.b #3,(a2)+
move.b #0,(a2)+
move.b #1,(a2)+
move.b #0,(a2)+
rts
; ===========================================================================
;loc_323BA
Obj54_Main:
moveq #0,d0
move.b angle(a0),d0
move.w Obj54_MainSubStates(pc,d0.w),d1
jmp Obj54_MainSubStates(pc,d1.w)
; ===========================================================================
Obj54_MainSubStates: offsetTable
offsetTableEntry.w Obj54_MainSub0 ; 0
offsetTableEntry.w Obj54_MainSub2 ; 2
offsetTableEntry.w Obj54_MainSub4 ; 4
offsetTableEntry.w Obj54_MainSub6 ; 6
offsetTableEntry.w Obj54_MainSub8 ; 8
offsetTableEntry.w Obj54_MainSubA ; $A
offsetTableEntry.w Obj54_MainSubC ; $C
offsetTableEntry.w Obj54_MainSubE ; $E
offsetTableEntry.w Obj54_MainSub10 ; $10
offsetTableEntry.w Obj54_MainSub12 ; $12
; ===========================================================================
;loc_323DC
Obj54_MainSub0:
bsr.w Boss_MoveObject
move.w (Boss_Y_pos).w,y_pos(a0)
cmpi.w #$4A0,(Boss_Y_pos).w
blo.s +
addq.b #2,angle(a0) ; => Obj54_MainSub2
move.w #0,(Boss_Y_vel).w
move.w #-$100,(Boss_X_vel).w
bclr #7,objoff_2B(a0)
bclr #0,render_flags(a0)
move.w (MainCharacter+x_pos).w,d0
cmp.w (Boss_X_pos).w,d0
blo.s +
move.w #$100,(Boss_X_vel).w
bset #7,objoff_2B(a0)
bset #0,render_flags(a0)
+
bsr.w Obj54_AnimateFace
lea (Ani_obj53).l,a1
bsr.w AnimateBoss
bsr.w Obj54_AlignSprites
jmpto (DisplaySprite).l, JmpTo40_DisplaySprite
; ===========================================================================
;loc_3243C
Obj54_Float:
move.b mapping_frame(a0),d0
jsr (CalcSine).l
asr.w #6,d0
add.w (Boss_Y_pos).w,d0
move.w d0,y_pos(a0)
addq.b #4,mapping_frame(a0)
rts
; ===========================================================================
;loc_32456
Obj54_MainSub2:
bsr.w Boss_MoveObject
btst #7,objoff_2B(a0)
bne.s +
cmpi.w #$2AD0,(Boss_X_pos).w
bhs.s Obj54_MoveAndShow
bchg #7,objoff_2B(a0)
move.w #$100,(Boss_X_vel).w
bset #0,render_flags(a0)
bset #6,objoff_2B(a0)
beq.s Obj54_MoveAndShow
addq.b #2,angle(a0) ; => Obj54_MainSub4
move.w #-$100,(Boss_Y_vel).w
bra.s Obj54_MoveAndShow
; ===========================================================================
+
cmpi.w #$2BD0,(Boss_X_pos).w
blo.s Obj54_MoveAndShow
bchg #7,objoff_2B(a0)
move.w #-$100,(Boss_X_vel).w
bclr #0,render_flags(a0)
bset #6,objoff_2B(a0)
beq.s Obj54_MoveAndShow
addq.b #2,angle(a0) ; => Obj54_MainSub4
move.w #-$100,(Boss_Y_vel).w
;loc_324BC
Obj54_MoveAndShow:
move.w (Boss_X_pos).w,x_pos(a0)
bsr.w Obj54_Float
;loc_324C6
Obj54_Display:
bsr.w Obj54_AnimateFace
lea (Ani_obj53).l,a1
bsr.w AnimateBoss
bsr.w Obj54_AlignSprites
jmpto (DisplaySprite).l, JmpTo40_DisplaySprite
; ===========================================================================
;loc_324DC
Obj54_MainSub4:
bsr.w Boss_MoveObject
cmpi.w #$470,(Boss_Y_pos).w
bhs.s +
move.w #0,(Boss_Y_vel).w
+
btst #7,objoff_2B(a0)
bne.s +
cmpi.w #$2B50,(Boss_X_pos).w
bhs.s ++
move.w #0,(Boss_X_vel).w
bra.s ++
; ===========================================================================
+
cmpi.w #$2B50,(Boss_X_pos).w
blo.s +
move.w #0,(Boss_X_vel).w
+
move.w (Boss_X_vel).w,d0
or.w (Boss_Y_vel).w,d0
bne.s BranchTo_Obj54_MoveAndShow
addq.b #2,angle(a0) ; => Obj54_MainSub6
BranchTo_Obj54_MoveAndShow
bra.s Obj54_MoveAndShow
; ===========================================================================
;loc_32524
Obj54_MainSub6:
cmpi.b #$68,objoff_33(a0)
bhs.s +
addq.b #1,objoff_33(a0)
addq.b #1,objoff_39(a0)
bra.s BranchTo2_Obj54_MoveAndShow
; ===========================================================================
+
subq.b #1,objoff_39(a0)
bne.s BranchTo2_Obj54_MoveAndShow
addq.b #2,angle(a0) ; => Obj54_MainSub8
BranchTo2_Obj54_MoveAndShow
bra.w Obj54_MoveAndShow
; ===========================================================================
;loc_32544
Obj54_MainSub8:
cmpi.b #$27,objoff_33(a0)
blo.s +
subq.b #1,objoff_33(a0)
bra.s BranchTo3_Obj54_MoveAndShow
; ===========================================================================
+
addq.b #1,objoff_39(a0)
cmpi.b #$27,objoff_39(a0)
blo.s BranchTo3_Obj54_MoveAndShow
move.w #$100,(Boss_Y_vel).w
move.b #0,angle(a0) ; => Obj54_MainSub0
bclr #6,objoff_2B(a0)
BranchTo3_Obj54_MoveAndShow
bra.w Obj54_MoveAndShow
; ===========================================================================
;loc_32574
Obj54_MainSubA:
tst.b objoff_39(a0)
beq.s +
subq.b #1,objoff_39(a0)
bra.s ++
; ===========================================================================
+
move.b #-1,objoff_3A(a0)
+
cmpi.b #$27,objoff_33(a0)
blo.s +
subq.b #1,objoff_33(a0)
+
bsr.w Boss_MoveObject
cmpi.w #$420,(Boss_Y_pos).w
bhs.s +
move.w #0,(Boss_Y_vel).w
+
tst.b objoff_2C(a0)
bne.s BranchTo4_Obj54_MoveAndShow
tst.b objoff_3A(a0)
beq.s +
move.b #$80,objoff_3A(a0)
+
addq.b #2,angle(a0) ; => Obj54_MainSubC
BranchTo4_Obj54_MoveAndShow
bra.w Obj54_MoveAndShow
; ===========================================================================
;loc_325BE
Obj54_MainSubC:
tst.b objoff_3E(a0)
beq.s ++
tst.b objoff_3A(a0)
bne.s BranchTo5_Obj54_MoveAndShow
cmpi.b #$27,objoff_39(a0)
bhs.s +
addq.b #1,objoff_39(a0)
bra.s BranchTo5_Obj54_MoveAndShow
; ===========================================================================
+
move.w #$100,(Boss_Y_vel).w
move.b #0,angle(a0) ; => Obj54_MainSub0
bclr #6,objoff_2B(a0)
bra.s BranchTo5_Obj54_MoveAndShow
; ===========================================================================
+
move.w #-$180,(Boss_Y_vel).w
move.w #-$100,(Boss_X_vel).w
bclr #0,render_flags(a0)
btst #7,objoff_2B(a0)
beq.s +
move.w #$100,(Boss_X_vel).w
bset #0,render_flags(a0)
+
move.b #$E,angle(a0) ; => Obj54_MainSubE
move.b #0,objoff_2E(a0)
bclr #6,objoff_2B(a0)
move.b #0,objoff_2F(a0)
BranchTo5_Obj54_MoveAndShow
bra.w Obj54_MoveAndShow
; ===========================================================================
;loc_3262E
Obj54_MainSubE:
tst.b objoff_2F(a0)
beq.s +
subq.b #1,objoff_2F(a0)
bra.w Obj54_Display
; ===========================================================================
+
moveq #0,d0
move.b objoff_2E(a0),d0
move.w off_3264A(pc,d0.w),d1
jmp off_3264A(pc,d1.w)
; ===========================================================================
off_3264A: offsetTable
offsetTableEntry.w loc_32650 ; 0
offsetTableEntry.w loc_326B8 ; 2
offsetTableEntry.w loc_32704 ; 4
; ===========================================================================
loc_32650:
bsr.w Boss_MoveObject
cmpi.w #$420,(Boss_Y_pos).w
bhs.s +
move.w #0,(Boss_Y_vel).w
+
btst #7,objoff_2B(a0)
bne.s +
cmpi.w #$2AF0,(Boss_X_pos).w
bhs.s BranchTo6_Obj54_MoveAndShow
addq.b #2,objoff_2E(a0)
move.w #$180,(Boss_Y_vel).w
move.b #3,objoff_2D(a0)
move.w #$1E,(Boss_Countdown).w
bset #0,render_flags(a0)
bra.s BranchTo6_Obj54_MoveAndShow
; ===========================================================================
+
cmpi.w #$2BB0,(Boss_X_pos).w
blo.s BranchTo6_Obj54_MoveAndShow
addq.b #2,objoff_2E(a0)
move.w #$180,(Boss_Y_vel).w
move.b #3,objoff_2D(a0)
move.w #$1E,(Boss_Countdown).w
bclr #0,render_flags(a0)
BranchTo6_Obj54_MoveAndShow
bra.w Obj54_MoveAndShow
; ===========================================================================
loc_326B8:
bsr.w Boss_MoveObject
cmpi.w #$4A0,(Boss_Y_pos).w
blo.s +
move.w #-$180,(Boss_Y_vel).w
addq.b #2,objoff_2E(a0)
bchg #7,objoff_2B(a0)
bra.s +++
; ===========================================================================
+
btst #7,objoff_2B(a0)
bne.s +
cmpi.w #$2AD0,(Boss_X_pos).w
bhs.s ++
move.w #0,(Boss_X_vel).w
bra.s ++
; ===========================================================================
+
cmpi.w #$2BD0,(Boss_X_pos).w
blo.s +
move.w #0,(Boss_X_vel).w
+
bsr.w Obj54_FireLaser
bra.w Obj54_MoveAndShow
; ===========================================================================
loc_32704:
bsr.w Boss_MoveObject
cmpi.w #$470,(Boss_Y_pos).w
bhs.s +
move.w #$100,(Boss_X_vel).w
btst #7,objoff_2B(a0)
bne.s +
move.w #-$100,(Boss_X_vel).w
+
cmpi.w #$420,(Boss_Y_pos).w
bhs.s +
move.w #0,(Boss_Y_vel).w
move.b #0,objoff_2E(a0)
+
bsr.w Obj54_FireLaser
bra.w Obj54_MoveAndShow
; ===========================================================================
;loc_32740
Obj54_FireLaser:
subi_.w #1,(Boss_Countdown).w
bne.s + ; rts
tst.b objoff_2D(a0)
beq.s + ; rts
subq.b #1,objoff_2D(a0)
jsrto (SingleObjLoad).l, JmpTo17_SingleObjLoad
bne.s + ; rts
move.b #ObjID_MTZBoss,id(a1) ; load obj54
move.b #4,boss_subtype(a1) ; => Obj54_Laser
move.l a0,objoff_34(a1)
move.w #$1E,(Boss_Countdown).w
move.b #$10,objoff_2F(a0)
+
rts
; ===========================================================================
;loc_32774
Obj54_AlignSprites:
move.w x_pos(a0),d0
move.w y_pos(a0),d1
move.w d0,sub2_x_pos(a0)
move.w d1,sub2_y_pos(a0)
move.w d0,sub3_x_pos(a0)
move.w d1,sub3_y_pos(a0)
rts
; ===========================================================================
;loc_3278E
Obj54_AnimateFace:
bsr.w Obj54_CheckHit
cmpi.b #$3F,boss_invulnerable_time(a0)
bne.s ++
st.b objoff_38(a0)
lea (Boss_AnimationArray).w,a1
andi.b #$F0,2(a1)
ori.b #5,2(a1)
tst.b objoff_3E(a0)
beq.s +
move.b #$A,angle(a0) ; => Obj54_MainSubA
move.w #-$180,(Boss_Y_vel).w
subq.b #1,objoff_3E(a0)
move.w #0,(Boss_X_vel).w
+
move.w #0,(Boss_X_vel).w
rts
; ===========================================================================
+
cmpi.b #4,(MainCharacter+routine).w
beq.s +
cmpi.b #4,(Sidekick+routine).w
bne.s ++ ; rts
+
lea (Boss_AnimationArray).w,a1
move.b 2(a1),d0
andi.b #$F,d0
cmpi.b #4,d0
beq.s + ; rts
andi.b #$F0,2(a1)
ori.b #4,2(a1)
+
rts
; ===========================================================================
;loc_32802
Obj54_MainSub10:
subq.w #1,(Boss_Countdown).w
cmpi.w #$3C,(Boss_Countdown).w
blo.s ++
bmi.s +
bsr.w Boss_LoadExplosion
lea (Boss_AnimationArray).w,a1
move.b #7,2(a1)
bra.s ++
; ===========================================================================
+
bset #0,render_flags(a0)
clr.w (Boss_X_vel).w
clr.w (Boss_Y_vel).w
addq.b #2,angle(a0) ; => Obj54_MainSub12
move.w #-$12,(Boss_Countdown).w
lea (Boss_AnimationArray).w,a1
move.b #3,2(a1)
jsrto (PlayLevelMusic).l, JmpTo7_PlayLevelMusic
+
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
lea (Ani_obj53).l,a1
bsr.w AnimateBoss
bsr.w Obj54_AlignSprites
jmpto (DisplaySprite).l, JmpTo40_DisplaySprite
; ===========================================================================
;loc_32864
Obj54_MainSub12:
move.w #$400,(Boss_X_vel).w
move.w #-$40,(Boss_Y_vel).w
cmpi.w #$2BF0,(Camera_Max_X_pos).w
bhs.s +
addq.w #2,(Camera_Max_X_pos).w
bra.s ++
; ===========================================================================
+
tst.b render_flags(a0)
bpl.s JmpTo60_DeleteObject
+
tst.b (Boss_defeated_flag).w
bne.s +
move.b #1,(Boss_defeated_flag).w
jsrto (LoadPLC_AnimalExplosion).l, JmpTo7_LoadPLC_AnimalExplosion
+
bsr.w Boss_MoveObject
bsr.w loc_328C0
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
lea (Ani_obj53).l,a1
bsr.w AnimateBoss
bsr.w Obj54_AlignSprites
jmpto (DisplaySprite).l, JmpTo40_DisplaySprite
; ===========================================================================
JmpTo60_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
loc_328C0:
move.b mapping_frame(a0),d0
jsr (CalcSine).l
asr.w #6,d0
add.w (Boss_Y_pos).w,d0
move.w d0,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
addq.b #2,mapping_frame(a0)
;loc_328DE
Obj54_CheckHit:
cmpi.b #$10,angle(a0)
bhs.s return_32924
tst.b boss_hitcount2(a0)
beq.s Obj54_Defeated
tst.b collision_flags(a0)
bne.s return_32924
tst.b boss_invulnerable_time(a0)
bne.s +
move.b #$40,boss_invulnerable_time(a0)
move.w #SndID_BossHit,d0
jsr (PlaySound).l
+
lea (Normal_palette_line2+2).w,a1
moveq #0,d0
tst.w (a1)
bne.s +
move.w #$EEE,d0
+
move.w d0,(a1)
subq.b #1,boss_invulnerable_time(a0)
bne.s return_32924
move.b #$F,collision_flags(a0)
return_32924:
rts
; ===========================================================================
;loc_32926
Obj54_Defeated:
moveq #100,d0
jsrto (AddPoints).l, JmpTo8_AddPoints
move.w #$EF,(Boss_Countdown).w
move.b #$10,angle(a0) ; => Obj54_MainSub10
moveq #PLCID_Capsule,d0
jsrto (LoadPLC).l, JmpTo11_LoadPLC
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 53 - Shield orbs that surround MTZ boss
; ----------------------------------------------------------------------------
; Sprite_32940:
Obj53:
moveq #0,d0
move.b routine(a0),d0
move.w Obj53_Index(pc,d0.w),d1
jmp Obj53_Index(pc,d1.w)
; ===========================================================================
; off_3294E:
Obj53_Index: offsetTable
offsetTableEntry.w Obj53_Init ; 0
offsetTableEntry.w Obj53_Main ; 2
offsetTableEntry.w Obj53_BreakAway ; 4
offsetTableEntry.w Obj53_BounceAround ; 6
offsetTableEntry.w Obj53_Burst ; 8
; ===========================================================================
; loc_32958:
Obj53_Init:
movea.l a0,a1
moveq #6,d3
moveq #0,d2
bra.s +
; ===========================================================================
- jsrto (SingleObjLoad).l, JmpTo17_SingleObjLoad
bne.s ++
+
move.b #$20,width_pixels(a1)
move.l objoff_34(a0),objoff_34(a1)
move.b #ObjID_MTZBossOrb,id(a1) ; load obj53
move.l #Obj54_MapUnc_32DC6,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_MTZBoss,0,0),art_tile(a1)
ori.b #4,render_flags(a1)
move.b #3,priority(a1)
addq.b #2,routine(a1) ; => Obj53_Main
move.b #5,mapping_frame(a1)
move.b byte_329CC(pc,d2.w),objoff_28(a1)
move.b byte_329CC(pc,d2.w),objoff_3B(a1)
move.b byte_329D3(pc,d2.w),objoff_3A(a1)
move.b #$40,objoff_29(a1)
move.b #$87,collision_flags(a1)
move.b #2,collision_property(a1)
move.b #0,objoff_3C(a1)
addq.w #1,d2
dbf d3,-
+
rts
; ===========================================================================
byte_329CC:
dc.b $24
dc.b $6C ; 1
dc.b $B4 ; 2
dc.b $FC ; 3
dc.b $48 ; 4
dc.b $90 ; 5
dc.b $D8 ; 6
rev02even
byte_329D3:
dc.b 0
dc.b 1 ; 1
dc.b 1 ; 2
dc.b 0 ; 3
dc.b 1 ; 4
dc.b 1 ; 5
dc.b 0 ; 6
even
; ===========================================================================
;loc_329DA
Obj53_Main:
movea.l objoff_34(a0),a1 ; a1=object
move.w y_pos(a1),objoff_2A(a0)
subi_.w #4,objoff_2A(a0)
move.w x_pos(a1),objoff_38(a0)
tst.b objoff_38(a1)
beq.s Obj53_ClearBossCollision
move.b #0,objoff_38(a1)
addi_.b #1,objoff_2C(a1)
addq.b #2,routine(a0) ; => Obj53_BreakAway
move.b #$3C,objoff_32(a0)
move.b #2,anim(a0)
move.w #-$400,y_vel(a0)
move.w #-$80,d1
move.w (MainCharacter+x_pos).w,d0
sub.w x_pos(a0),d0
bpl.s +
neg.w d1
+
cmpi.w #$2AF0,x_pos(a0)
bhs.s +
move.w #$80,d1
+
cmpi.w #$2BB0,x_pos(a0)
blo.s +
move.w #-$80,d1
+
bclr #0,render_flags(a0)
tst.w d1
bmi.s +
bset #0,render_flags(a0)
+
move.w d1,x_vel(a0)
bra.s +
; ===========================================================================
;loc_32A56
Obj53_ClearBossCollision:
cmpi.b #2,collision_property(a0)
beq.s +
move.b #0,collision_flags(a1)
+
bsr.w Obj53_OrbitBoss
bsr.w Obj53_SetAnimPriority
jmpto (DisplaySprite).l, JmpTo40_DisplaySprite
; ===========================================================================
;loc_32A70
Obj53_OrbitBoss:
move.b objoff_29(a0),d0
jsr (CalcSine).l
move.w d0,d3
moveq #0,d1
move.b objoff_33(a1),d1
muls.w d1,d0
move.w d0,d5
move.w d0,d4
move.b objoff_39(a1),d2
tst.b objoff_3A(a1)
beq.s +
move.w #$10,d2
+
muls.w d3,d2
move.w objoff_38(a0),d6
move.b objoff_28(a0),d0
jsr (CalcSine).l
muls.w d0,d5
swap d5
add.w d6,d5
move.w d5,x_pos(a0)
muls.w d1,d4
swap d4
move.w d4,objoff_30(a0)
move.w objoff_2A(a0),d6
move.b objoff_3B(a0),d0
tst.b objoff_3A(a1)
beq.s +
move.b objoff_3C(a0),d0
+
jsr (CalcSine).l
muls.w d0,d2
swap d2
add.w d6,d2
move.w d2,y_pos(a0)
addq.b #4,objoff_28(a0)
tst.b objoff_3A(a1)
bne.s +
addq.b #8,objoff_3B(a0)
rts
; ===========================================================================
+
cmpi.b #-1,objoff_3A(a1)
beq.s ++
cmpi.b #$80,objoff_3A(a1)
bne.s +
subq.b #2,objoff_3C(a0)
bpl.s return_32B18
clr.b objoff_3C(a0)
+
move.b #0,objoff_3A(a1)
rts
; ===========================================================================
+
cmpi.b #$40,objoff_3C(a0)
bhs.s return_32B18
addq.b #2,objoff_3C(a0)
return_32B18:
rts
; ===========================================================================
;loc_32B1A
Obj53_SetAnimPriority:
move.w objoff_30(a0),d0
bmi.s ++
cmpi.w #$C,d0
blt.s +
move.b #3,mapping_frame(a0)
move.b #1,priority(a0)
rts
; ===========================================================================
+
move.b #4,mapping_frame(a0)
move.b #2,priority(a0)
rts
; ===========================================================================
+
cmpi.w #-$C,d0
blt.s +
move.b #4,mapping_frame(a0)
move.b #6,priority(a0)
rts
; ===========================================================================
+
move.b #5,mapping_frame(a0)
move.b #7,priority(a0)
rts
; ===========================================================================
;loc_32B64
Obj53_BreakAway:
tst.b objoff_32(a0)
bmi.s +
subq.b #1,objoff_32(a0)
bpl.s +
move.b #$DA,collision_flags(a0)
+
jsrto (ObjectMoveAndFall).l, JmpTo6_ObjectMoveAndFall
subi.w #$20,y_vel(a0)
cmpi.w #$180,y_vel(a0)
blt.s +
move.w #$180,y_vel(a0)
+
cmpi.w #$4AC,y_pos(a0)
blo.s Obj53_Animate
move.w #$4AC,y_pos(a0)
move.w #$4AC,objoff_2E(a0)
move.b #1,objoff_2C(a0)
addq.b #2,routine(a0)
bsr.w Obj53_FaceLeader
;loc_32BB0
Obj53_Animate:
bsr.w +
lea (Ani_obj53).l,a1
jsrto (AnimateSprite).l, JmpTo21_AnimateSprite
jmpto (DisplaySprite).l, JmpTo40_DisplaySprite
; ===========================================================================
+
cmpi.b #-2,collision_property(a0)
bgt.s + ; rts
move.b #$14,mapping_frame(a0)
move.b #6,anim(a0)
addq.b #2,routine(a0)
+
rts
; ===========================================================================
;loc_32BDC
Obj53_BounceAround:
tst.b objoff_32(a0)
bmi.s +
subq.b #1,objoff_32(a0)
bpl.s +
move.b #$DA,collision_flags(a0)
+
bsr.w Obj53_CheckPlayerHit
cmpi.b #$B,mapping_frame(a0)
bne.s Obj53_Animate
move.b objoff_2C(a0),d0
jsr (CalcSine).l
neg.w d0
asr.w #2,d0
add.w objoff_2E(a0),d0
cmpi.w #$4AC,d0
bhs.s ++
move.w d0,y_pos(a0)
addq.b #1,objoff_2C(a0)
btst #0,objoff_2C(a0)
beq.w JmpTo40_DisplaySprite
moveq #-1,d0
btst #0,render_flags(a0)
beq.s +
neg.w d0
+
add.w d0,x_pos(a0)
jmpto (DisplaySprite).l, JmpTo40_DisplaySprite
; ===========================================================================
+
move.w #$4AC,y_pos(a0)
bsr.w Obj53_FaceLeader
move.b #1,objoff_2C(a0)
jmpto (DisplaySprite).l, JmpTo40_DisplaySprite
; ===========================================================================
;loc_32C4C
Obj53_FaceLeader:
move.w (MainCharacter+x_pos).w,d0
sub.w x_pos(a0),d0
bpl.s +
bclr #0,render_flags(a0)
rts
; ===========================================================================
+
bset #0,render_flags(a0)
rts
; ===========================================================================
;loc_32C66
Obj53_CheckPlayerHit:
cmpi.b #4,(MainCharacter+routine).w
beq.s +
cmpi.b #4,(Sidekick+routine).w
bne.s ++
+
move.b #$14,mapping_frame(a0)
move.b #6,anim(a0)
+
cmpi.b #-2,collision_property(a0)
bgt.s +
move.b #$14,mapping_frame(a0)
move.b #6,anim(a0)
+
rts
; ===========================================================================
;loc_32C98
Obj53_Burst:
move.b #SndID_BossExplosion,d0
jsrto (PlaySound).l, JmpTo10_PlaySound
movea.l objoff_34(a0),a1 ; a1=object
subi_.b #1,objoff_2C(a1)
if removeJmpTos
JmpTo61_DeleteObject
endif
jmpto (DeleteObject).l, JmpTo61_DeleteObject
; ===========================================================================
;loc_32CAE
Obj54_Laser:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_32CBC(pc,d0.w),d0
jmp off_32CBC(pc,d0.w)
; ===========================================================================
off_32CBC: offsetTable
offsetTableEntry.w Obj54_Laser_Init ; 0
offsetTableEntry.w Obj54_Laser_Main ; 2
; ===========================================================================
;loc_32CC0
Obj54_Laser_Init:
move.l #Obj54_MapUnc_32DC6,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_MTZBoss,0,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #5,priority(a0)
move.b #$12,mapping_frame(a0)
addq.b #2,routine_secondary(a0) ; => Obj54_Laser_Main
movea.l objoff_34(a0),a1 ; a1=object
move.b #$50,width_pixels(a0)
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
addi_.w #7,y_pos(a0)
subi_.w #4,x_pos(a0)
move.w #-$400,d0
btst #0,render_flags(a1)
beq.s +
neg.w d0
addi_.w #8,x_pos(a0)
+
move.w d0,x_vel(a0)
move.b #$99,collision_flags(a0)
move.b #SndID_LaserBurst,d0
jsrto (PlaySound).l, JmpTo10_PlaySound
;loc_32D2C
Obj54_Laser_Main:
jsrto (ObjectMove).l, JmpTo24_ObjectMove
cmpi.w #$2AB0,x_pos(a0)
blo.w JmpTo61_DeleteObject
cmpi.w #$2BF0,x_pos(a0)
bhs.w JmpTo61_DeleteObject
jmpto (DisplaySprite).l, JmpTo40_DisplaySprite
; ===========================================================================
;loc_32D48
Obj54_LaserShooter:
movea.l objoff_34(a0),a1 ; a1=object
cmpi.b #ObjID_MTZBoss,id(a1)
bne.w JmpTo61_DeleteObject
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
bclr #0,render_flags(a0)
btst #0,render_flags(a1)
beq.w JmpTo40_DisplaySprite
bset #0,render_flags(a0)
if removeJmpTos
JmpTo40_DisplaySprite
endif
jmpto (DisplaySprite).l, JmpTo40_DisplaySprite
; ===========================================================================
; animation script
; off_32D7A:
Ani_obj53: offsetTable
offsetTableEntry.w byte_32D8A ; 0
offsetTableEntry.w byte_32D8D ; 1
offsetTableEntry.w byte_32D91 ; 2
offsetTableEntry.w byte_32DA6 ; 3
offsetTableEntry.w byte_32DAA ; 4
offsetTableEntry.w byte_32DB5 ; 5
offsetTableEntry.w byte_32DC0 ; 6
offsetTableEntry.w byte_32DC3 ; 7
byte_32D8A: dc.b $F, 2,$FF
rev02even
byte_32D8D: dc.b 1, 0, 1,$FF
rev02even
byte_32D91: dc.b 3, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 6, 7, 6, 7, 8
dc.b 9, $A, $B,$FE, 1; 16
rev02even
byte_32DA6: dc.b 7, $C, $D,$FF
rev02even
byte_32DAA: dc.b 7, $E, $F, $E, $F, $E, $F, $E, $F,$FD, 3
rev02even
byte_32DB5: dc.b 7,$10,$10,$10,$10,$10,$10,$10,$10,$FD, 3
rev02even
byte_32DC0: dc.b 1,$14,$FC
rev02even
byte_32DC3: dc.b 7,$11,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj54_MapUnc_32DC6: BINCLUDE "mappings/sprite/obj54.bin"
if ~~removeJmpTos
align 4
endif
; ===========================================================================
if ~~removeJmpTos
JmpTo40_DisplaySprite
jmp (DisplaySprite).l
JmpTo61_DeleteObject
jmp (DeleteObject).l
JmpTo17_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo10_PlaySound
jmp (PlaySound).l
JmpTo21_AnimateSprite
jmp (AnimateSprite).l
JmpTo11_LoadPLC
jmp (LoadPLC).l
JmpTo8_AddPoints
jmp (AddPoints).l
JmpTo7_PlayLevelMusic
jmp (PlayLevelMusic).l
JmpTo7_LoadPLC_AnimalExplosion
jmp (LoadPLC_AnimalExplosion).l
JmpTo6_ObjectMoveAndFall
jmp (ObjectMoveAndFall).l
; loc_32F88:
JmpTo24_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 55 - OOZ boss
; ----------------------------------------------------------------------------
; OST Variables:
Obj55_status = objoff_2A ; bitfield
Obj55_anim_frame_duration = objoff_2C ; number of frames the laser shooter displays its shooting frame
Obj55_shot_count = objoff_38 ; number of lasers the shooter fires during its attack phase
Obj55_laser_pos = objoff_3E ; bitfield, each of the first four bits stands for one of the possible y positions a laser can be fired from
Obj55_Wave_delay = objoff_32 ; time before the next part of the wave is created
Obj55_Wave_parent = objoff_34 ; pointer to main vehicle
Obj55_Wave_count = objoff_36 ; number of waves to make
; Sprite_32F90:
Obj55:
moveq #0,d0
move.b boss_subtype(a0),d0
move.w Obj55_Index(pc,d0.w),d1
jmp Obj55_Index(pc,d1.w)
; ===========================================================================
; off_32F9E:
Obj55_Index: offsetTable
offsetTableEntry.w Obj55_Init ; 0 - Init
offsetTableEntry.w Obj55_Main ; 2 - Main Vehicle
offsetTableEntry.w Obj55_LaserShooter ; 4 - Laser Shooter
offsetTableEntry.w Obj55_SpikeChain ; 6 - Spiked Chain
offsetTableEntry.w Obj55_Laser ; 8 - Laser
; ===========================================================================
; loc_32FA8:
Obj55_Init:
move.l #Obj55_MapUnc_33756,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_OOZBoss,0,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #3,priority(a0)
bset #6,render_flags(a0) ; object consists of multiple sprites
move.b #0,mainspr_childsprites(a0)
addq.b #2,boss_subtype(a0) ; => Obj55_Main
move.b #$F,collision_flags(a0)
move.b #8,boss_hitcount2(a0)
move.b #$40,mainspr_width(a0)
rts
; ===========================================================================
; loc_32FE6:
Obj55_Main:
moveq #0,d0
move.b boss_routine(a0),d0
move.w Obj55_Main_Index(pc,d0.w),d1
jmp Obj55_Main_Index(pc,d1.w)
; ===========================================================================
; off_32FF4:
Obj55_Main_Index: offsetTable
offsetTableEntry.w Obj55_Main_Init ; 0 - boss' initial state
offsetTableEntry.w Obj55_Main_Surface ; 2 - moving up
offsetTableEntry.w Obj55_Main_Wait ; 4 - stay in place for a while
offsetTableEntry.w Obj55_Main_Dive ; 6 - moving down
offsetTableEntry.w Obj55_Main_Defeated ; 8 - boss defeated and escaping
; ===========================================================================
; loc_32FFE:
Obj55_Main_Init:
move.w #$2940,(Boss_X_pos).w
bclr #0,render_flags(a0) ; face right
move.w (MainCharacter+x_pos).w,d1
cmpi.w #$293A,d1 ; is player on the left side of the arena?
bhs.s + ; if not, branch
bchg #0,render_flags(a0) ; face left
+
move.w #$2D0,y_pos(a0)
move.w #$2D0,(Boss_Y_pos).w
move.b #8,mainspr_mapframe(a0)
move.b #1,mainspr_childsprites(a0)
addq.b #2,boss_routine(a0) ; => Obj55_Main_Surface
move.w #-$80,(Boss_Y_vel).w
move.b #$F,collision_flags(a0)
move.w x_pos(a0),sub2_x_pos(a0)
move.w y_pos(a0),sub2_y_pos(a0)
clr.b boss_sine_count(a0)
clr.b Obj55_status(a0)
move.b #8,sub2_mapframe(a0)
lea (Boss_AnimationArray).w,a2
move.b #5,(a2)+
move.b #0,(a2)+
move.b #1,(a2)+
move.b #0,(a2)
move.b #0,(Boss_CollisionRoutine).w
rts
; ===========================================================================
; loc_33078:
Obj55_Main_Surface:
bsr.w Boss_MoveObject
move.w (Boss_X_pos).w,x_pos(a0)
bsr.w Obj55_HoverPos
cmpi.w #$290,(Boss_Y_pos).w ; has boss reached its target position?
bhs.w Obj55_Main_End ; if not, branch
move.w #$290,(Boss_Y_pos).w
addq.b #2,boss_routine(a0) ; => Obj55_Main_Wait
move.w #$A8,(Boss_Countdown).w
btst #7,Obj55_status(a0) ; was boss hit?
bne.w Obj55_Main_End ; if yes, branch
lea (Boss_AnimationArray).w,a2
move.b #$10,(a2)+
move.b #0,(a2)
bra.w Obj55_Main_End
; ===========================================================================
; loc_330BA:
Obj55_Main_Wait:
btst #7,Obj55_status(a0) ; was boss hit?
bne.s + ; if yes, branch
bsr.w Obj55_HoverPos
subi_.w #1,(Boss_Countdown).w ; hover in place for a while
bpl.w Obj55_Main_End
lea (Boss_AnimationArray).w,a2
move.b #5,(a2)+
move.b #0,(a2)
+
addq.b #2,boss_routine(a0) ; => Obj55_Main_Dive
move.w #-$40,(Boss_Y_vel).w ; bob up a little before diving
bra.w Obj55_Main_End
; ===========================================================================
; does the hovering effect
; loc_330EA:
Obj55_HoverPos:
move.b boss_sine_count(a0),d0
jsr (CalcSine).l
asr.w #7,d1
add.w (Boss_Y_pos).w,d1
move.w d1,y_pos(a0)
addq.b #4,boss_sine_count(a0)
rts
; ===========================================================================
; loc_33104:
Obj55_Main_Dive:
bsr.w Boss_MoveObject
move.w (Boss_Y_pos).w,y_pos(a0)
move.w (Boss_X_pos).w,x_pos(a0)
btst #6,Obj55_status(a0) ; is boss done rising?
bne.s Obj55_Main_Dive_Part2 ; if yes, branch
cmpi.w #$28C,(Boss_Y_pos).w ; has boss reached initial destination (rising before diving)?
bhs.w Obj55_Main_End ; if not, branch
move.w #$28C,(Boss_Y_pos).w
move.w #$80,(Boss_Y_vel).w
ori.b #$40,Obj55_status(a0) ; set diving bit
bra.w Obj55_Main_End
; ===========================================================================
; loc_3313C:
Obj55_Main_Dive_Part2:
cmpi.w #$2D0,(Boss_Y_pos).w ; has boss reached its target position?
blo.s Obj55_Main_End ; if yes, branch
move.w #$2D0,(Boss_Y_pos).w
clr.b boss_routine(a0)
addq.b #2,boss_subtype(a0) ; => Obj55_LaserShooter
btst #7,Obj55_status(a0) ; was boss hit?
beq.s Obj55_Main_End ; if not, branch
addq.b #2,boss_subtype(a0) ; => Obj55_SpikeChain
; loc_3315E:
Obj55_Main_End:
bsr.w Obj55_HandleHits
lea (Ani_obj55).l,a1
bsr.w AnimateBoss
bsr.w Obj55_AlignSprites
jmpto (DisplaySprite).l, JmpTo41_DisplaySprite
; ===========================================================================
; loc_33174:
Obj55_HandleHits:
bsr.w Boss_HandleHits
cmpi.b #$1F,boss_invulnerable_time(a0)
bne.s return_33192
lea (Boss_AnimationArray).w,a1
andi.b #$F0,(a1)
ori.b #3,(a1)
ori.b #$80,Obj55_status(a0) ; set boss hit bit
return_33192:
rts
; ===========================================================================
; loc_33194:
Obj55_AlignSprites:
move.w x_pos(a0),d0
move.w y_pos(a0),d1
move.w d0,sub2_x_pos(a0)
move.w d1,sub2_y_pos(a0)
rts
; ===========================================================================
; loc_331A6:
Obj55_Main_Defeated:
clr.w (Normal_palette_line2+2).w ; set color to black
subq.w #1,(Boss_Countdown).w ; wait for a while
bmi.s Obj55_Main_Defeated_Part2 ; branch, if wait is over
cmpi.w #$1E,(Boss_Countdown).w ; has boss waited for a certain ammount of time?
bhs.s Obj55_Explode ; if not, branch
move.b #$B,mainspr_mapframe(a0) ; use defeated animation
jmpto (DisplaySprite).l, JmpTo41_DisplaySprite
; ===========================================================================
; loc_331C2:
Obj55_Explode:
bsr.w Boss_LoadExplosion
jmpto (DisplaySprite).l, JmpTo41_DisplaySprite
; ===========================================================================
; loc_331CA:
Obj55_Main_Defeated_Part2:
tst.b (Boss_defeated_flag).w ; has boss been defeated?
bne.s Obj55_ReleaseCamera ; if yes, branch
jsrto (PlayLevelMusic).l, JmpTo8_PlayLevelMusic
jsrto (LoadPLC_AnimalExplosion).l, JmpTo8_LoadPLC_AnimalExplosion
move.b #1,(Boss_defeated_flag).w
; loc_331DE:
Obj55_ReleaseCamera:
cmpi.w #$2A20,(Camera_Max_X_pos).w ; has camera reached its destination?
bhs.s Obj55_ChkDelete ; if yes, branch
addq.w #2,(Camera_Max_X_pos).w ; else, move camera some more
bra.s Obj55_Defeated_Sink
; ===========================================================================
; loc_331EC:
Obj55_ChkDelete:
move.w #$2A20,(Camera_Max_X_pos).w
cmpi.w #$2D0,y_pos(a0) ; has boss reached its target position?
bhs.s BranchTo_JmpTo62_DeleteObject ; if yes, branch
; loc_331FA:
Obj55_Defeated_Sink:
addi_.w #1,y_pos(a0)
bsr.s Obj55_AlignSprites
jmpto (DisplaySprite).l, JmpTo41_DisplaySprite
; ===========================================================================
if removeJmpTos
JmpTo62_DeleteObject
endif
BranchTo_JmpTo62_DeleteObject
jmpto (DeleteObject).l, JmpTo62_DeleteObject
; ===========================================================================
; loc_3320A:
Obj55_LaserShooter:
moveq #0,d0
move.b boss_routine(a0),d0
move.w Obj55_LaserShooter_Index(pc,d0.w),d1
jmp Obj55_LaserShooter_Index(pc,d1.w)
; ===========================================================================
; off_33218:
Obj55_LaserShooter_Index: offsetTable
offsetTableEntry.w Obj55_LaserShooter_Init ; 0 - laser shooter's initial state
offsetTableEntry.w Obj55_LaserShooter_Rise ; 2 - moving up
offsetTableEntry.w Obj55_LaserShooter_ChooseTarget ; 4 - stay in place for a while
offsetTableEntry.w Obj55_LaserShooter_Aim ; 6 - move towards target and shoot
offsetTableEntry.w Obj55_LaserShooter_Lower ; 8 - moving down
; ===========================================================================
; loc_33222:
Obj55_LaserShooter_Init:
clr.w (Normal_palette_line2+2).w ; reset palette flash
move.w #$2940,(Boss_X_pos).w
bclr #0,render_flags(a0)
move.w (MainCharacter+x_pos).w,d1
cmpi.w #$293A,d1 ; is player left from center?
blo.s + ; if yes, branch
bchg #0,render_flags(a0)
+
move.w #$2B0,(Boss_Y_pos).w
move.w #$2B0,y_pos(a0)
move.b #2,boss_routine(a0) ; => Obj55_LaserShooter_Rise
move.b #$8A,collision_flags(a0)
move.b #5,mainspr_mapframe(a0)
moveq #7,d0
moveq #7,d2
moveq #0,d4
move.w (Boss_Y_pos).w,d5
- ; initialize chain
addi.w #$F,d5
move.b d0,sub2_mapframe(a0,d4.w)
move.w d5,sub2_y_pos(a0,d4.w)
addq.w #next_subspr,d4
dbf d2,-
move.b #8,mainspr_childsprites(a0)
move.w #-$80,(Boss_Y_vel).w
move.b #0,Obj55_laser_pos(a0)
move.b #1,(Boss_CollisionRoutine).w
rts
; ===========================================================================
; loc_33296:
Obj55_LaserShooter_Rise:
bsr.w Boss_MoveObject
cmpi.w #$240,(Boss_Y_pos).w ; has laser shooter reached its destination?
bhs.w Obj55_LaserShooter_End ; if not, branch
move.w #$240,(Boss_Y_pos).w
move.w #0,(Boss_Y_vel).w
addi_.b #2,boss_routine(a0) ; => Obj55_LaserShooter_ChooseTarget
move.w #$80,(Boss_Countdown).w
move.b #3,Obj55_shot_count(a0) ; prepare to shoot 3 lasers
bra.w Obj55_LaserShooter_End
; ===========================================================================
; loc_332C6:
Obj55_LaserShooter_ChooseTarget:
subq.b #1,Obj55_anim_frame_duration(a0) ; is firing animation finished?
bne.s + ; if not, branch
move.b #5,mainspr_mapframe(a0) ; reset animation frame to not firing
+
subi_.w #1,(Boss_Countdown).w ; wait for a while
bne.w Obj55_LaserShooter_End ; branch, as long as wait isn't over
subi_.b #1,Obj55_shot_count(a0) ; decrement number of shots left
bmi.s Obj55_LaserShooter_DoneShooting ; branch, if no shots left
jsrto (RandomNumber).l, JmpTo5_RandomNumber
- ; find first valid firing position
addq.b #1,d0 ; next position
andi.w #3,d0 ; limit to 4 possible values
btst d0,Obj55_laser_pos(a0) ; was a laser already shot in this position?
bne.s - ; if yes, branch
bset d0,Obj55_laser_pos(a0) ; set posion as used
add.w d0,d0
move.w Obj55_LaserTargets(pc,d0.w),(Boss_Countdown).w ; set target positon
addq.b #2,boss_routine(a0) ; => Obj55_LaserShooter_Aim
bsr.w Obj55_MoveTowardTarget
bra.w Obj55_LaserShooter_End
; ===========================================================================
; loc_3330C:
Obj55_LaserShooter_DoneShooting:
move.w #$80,(Boss_Y_vel).w
move.b #8,boss_routine(a0) ; => Obj55_LaserShooter_Lower
bra.w Obj55_LaserShooter_End
; ===========================================================================
; word_3331C:
Obj55_LaserTargets:
dc.w $238 ; 0
dc.w $230 ; 2
dc.w $240 ; 4
dc.w $25F ; 6
; ===========================================================================
; loc_33324:
Obj55_LaserShooter_Aim:
bsr.w Boss_MoveObject
move.w (Boss_Countdown).w,d0
tst.w (Boss_Y_vel).w ; is laser shooter moving up?
bmi.s Obj55_LaserShooter_Aim_MovingUp ; if yes, branch
cmp.w (Boss_Y_pos).w,d0 ; has laser shooter reached its destination?
blo.s Obj55_LaserShooter_Fire ; if yes, branch
bra.w Obj55_LaserShooter_End
; ===========================================================================
; loc_3333C:
Obj55_LaserShooter_Aim_MovingUp:
cmp.w (Boss_Y_pos).w,d0 ; has laser shooter reached its destination?
blo.s Obj55_LaserShooter_End ; if not, branch
; loc_33342:
Obj55_LaserShooter_Fire:
move.w #0,(Boss_Y_vel).w
move.b #8,Obj55_anim_frame_duration(a0)
move.b #6,mainspr_mapframe(a0) ; use firing frame
jsrto (SingleObjLoad).l, JmpTo18_SingleObjLoad
bne.w Obj55_LaserShooter_End
move.b #ObjID_OOZBoss,id(a1) ; load obj55
move.b #8,boss_subtype(a1) ; => Obj55_Laser
move.l a0,Obj55_Wave_parent(a1)
move.b #SndID_LaserBurst,d0
jsrto (PlaySound).l, JmpTo11_PlaySound
move.b #4,boss_routine(a0) ; => Obj55_LaserShooter_ChooseTarget
move.w #$28,(Boss_Countdown).w
move.w #-$80,(Boss_Y_vel).w
bra.w Obj55_LaserShooter_End
; ===========================================================================
; loc_33388:
Obj55_LaserShooter_Lower:
subq.b #1,Obj55_anim_frame_duration(a0) ; is firing animation finished?
bne.s + ; if not, branch
move.b #5,mainspr_mapframe(a0) ; reset animation frame to not firing
+
bsr.w Boss_MoveObject
cmpi.w #$2B0,(Boss_Y_pos).w ; has laser shooter reached its destination?
blo.s Obj55_LaserShooter_End ; if not, branch
move.w #$2B0,(Boss_Y_pos).w
move.w #0,(Boss_Y_vel).w
move.b #0,boss_routine(a0)
move.b #2,boss_subtype(a0) ; => Obj55_Main_Init
rts
; ===========================================================================
; loc_333BA:
Obj55_LaserShooter_End:
bsr.w Obj55_LaserShooter_FacePlayer
bsr.w Obj55_LaserShooter_Wind
jmpto (DisplaySprite).l, JmpTo41_DisplaySprite
; ===========================================================================
; sets the laser shooter's y velocity so that it moves toward its target
; loc_333C6:
Obj55_MoveTowardTarget:
move.w (Boss_Countdown).w,d0
sub.w (Boss_Y_pos).w,d0
bpl.s Obj55_LaserShooter_MoveUp ; branch, if laser shooter is below target
move.w #-$80,(Boss_Y_vel).w
rts
; ===========================================================================
; loc_333D8:
Obj55_LaserShooter_MoveUp:
move.w #$80,(Boss_Y_vel).w
rts
; ===========================================================================
; loc_333E0:
Obj55_LaserShooter_FacePlayer:
move.w (MainCharacter+x_pos).w,d0
sub.w x_pos(a0),d0
blt.s Obj55_LaserShooter_FaceLeft ; branch, if player is to the left
subi_.w #8,d0 ; allow an 8 pixel margin
blt.s return_333F6
bset #0,render_flags(a0)
return_333F6:
rts
; ===========================================================================
; loc_333F8:
Obj55_LaserShooter_FaceLeft:
addi_.w #8,d0 ; allow an 8 pixel margin
bgt.s return_333F6
bclr #0,render_flags(a0)
rts
; ===========================================================================
; creates the twisting effect
; loc_33406:
Obj55_LaserShooter_Wind:
move.w (Boss_X_pos).w,d5
move.w (Boss_Y_pos).w,d6
move.b boss_sine_count(a0),d3
move.b d3,d0
bsr.w Obj55_LaserShooter_CalcSineRelative
move.w d1,x_pos(a0)
move.w d0,y_pos(a0)
addi_.b #2,boss_sine_count(a0)
moveq #7,d2
moveq #0,d4
- addi.w #$F,d6
subi.b #$10,d3
bsr.w Obj55_LaserShooter_CalcSineRelative
move.w d1,sub2_x_pos(a0,d4.w)
move.w d0,sub2_y_pos(a0,d4.w)
addq.w #next_subspr,d4
dbf d2,-
rts
; ===========================================================================
; loc_33446:
Obj55_LaserShooter_CalcSineRelative:
move.b d3,d0
jsrto (CalcSine).l, JmpTo13_CalcSine
asr.w #4,d1
add.w d5,d1
asr.w #6,d0
add.w d6,d0
rts
; ===========================================================================
; loc_33456:
Obj55_SpikeChain:
moveq #0,d0
move.b boss_routine(a0),d0
move.w Obj55_SpikeChain_Index(pc,d0.w),d1
jmp Obj55_SpikeChain_Index(pc,d1.w)
; ===========================================================================
; off_33464:
Obj55_SpikeChain_Index: offsetTable
offsetTableEntry.w Obj55_SpikeChain_Init ; 0 - spiked chain's initial state
offsetTableEntry.w Obj55_SpikeChain_Main ; 2 - spiked chain moving at an arc
; ===========================================================================
; loc_33468:
Obj55_SpikeChain_Init:
clr.w (Normal_palette_line2+2).w ; reset palette flash
move.w #$28C0,(Boss_X_pos).w
bclr #0,render_flags(a0)
move.w (MainCharacter+x_pos).w,d1
cmpi.w #$293A,d1 ; is player on the left side of the arena?
blo.s + ; if yes, branch
move.w #$29C0,(Boss_X_pos).w
bset #0,render_flags(a0)
+
move.w #$2A0,(Boss_Y_pos).w
move.b #2,mainspr_mapframe(a0)
move.b #$8A,collision_flags(a0)
addq.b #2,boss_routine(a0) ; => Obj55_SpikeChain_Main
move.b #$80,mainspr_width(a0)
clr.b boss_sine_count(a0)
moveq #7,d0
moveq #7,d1
moveq #0,d2
- move.b d1,sub2_mapframe(a0,d2.w)
addq.w #next_subspr,d2
dbf d0,-
move.b #8,mainspr_childsprites(a0)
move.b #2,(Boss_CollisionRoutine).w
rts
; ===========================================================================
; loc_334CC:
Obj55_SpikeChain_Main:
bsr.w Obj55_SpikeChain_Move
cmpi.b #$FE,boss_sine_count(a0) ; has chain reached a certain angle?
blo.s Obj55_SpikeChain_End ; if not, branch
move.b #0,boss_routine(a0)
move.b #4,boss_subtype(a0) ; => Obj55_LaserShooter_Init
rts
; ===========================================================================
; loc_334E6:
Obj55_SpikeChain_End:
bsr.w Obj55_SpikeChain_SetAnimFrame
jmpto (DisplaySprite).l, JmpTo41_DisplaySprite
; ===========================================================================
; loc_334EE:
Obj55_SpikeChain_Move:
move.b boss_sine_count(a0),d0
addi.b #$40,d0
move.b d0,d3
bsr.w Obj55_SpikeChain_Rotate
move.w d1,x_pos(a0)
move.w d0,y_pos(a0)
addi_.b #1,boss_sine_count(a0)
moveq #7,d2
moveq #0,d4
- subi_.b #6,d3
bsr.w Obj55_SpikeChain_Rotate
move.w d1,sub2_x_pos(a0,d4.w)
move.w d0,sub2_y_pos(a0,d4.w)
addq.w #next_subspr,d4
dbf d2,-
rts
; ===========================================================================
; loc_33526:
Obj55_SpikeChain_Rotate:
move.b d3,d0
jsrto (CalcSine).l, JmpTo13_CalcSine
muls.w #$68,d1
asr.l #8,d1
btst #0,render_flags(a0)
bne.s +
neg.w d1
+
add.w (Boss_X_pos).w,d1
muls.w #$68,d0
asr.l #8,d0
add.w (Boss_Y_pos).w,d0
rts
; ===========================================================================
; loc_3354C:
Obj55_SpikeChain_SetAnimFrame:
move.b boss_sine_count(a0),d0
moveq #$15,d1
cmpi.b #$52,d0
blo.s +
moveq #3,d1
cmpi.b #$6B,d0
blo.s +
moveq #2,d1
cmpi.b #-$6E,d0
blo.s +
moveq #4,d1
+
move.b d1,mainspr_mapframe(a0)
rts
; ===========================================================================
; loc_33570:
Obj55_Laser:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj55_Laser_Index(pc,d0.w),d0
jmp Obj55_Laser_Index(pc,d0.w)
; ===========================================================================
; off_3357E:
Obj55_Laser_Index: offsetTable
offsetTableEntry.w Obj55_Laser_Init ; 0 - Init
offsetTableEntry.w Obj55_Laser_Main ; 2 - Laser moving horizontally
offsetTableEntry.w Obj55_Wave ; 4 - Energy wave that moves along the ground
offsetTableEntry.w BranchTo2_JmpTo62_DeleteObject ; 6 - Delete (triggered by an animation)
; ===========================================================================
; loc_33586:
Obj55_Laser_Init:
addq.b #2,routine_secondary(a0) ; => Obj55_Laser_Main
move.l #Obj55_MapUnc_33756,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_OOZBoss,0,0),art_tile(a0)
ori.b #4,render_flags(a0)
move.b #4,priority(a0)
movea.l Obj55_Wave_parent(a0),a1 ; a1=object
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
move.b #$C,mapping_frame(a0)
move.w #-$20,d0
move.w #-$400,x_vel(a0)
btst #0,render_flags(a1)
beq.s +
neg.w d0
neg.w x_vel(a0)
+
add.w d0,x_pos(a0)
move.b #$AF,collision_flags(a0)
rts
; ===========================================================================
; loc_335DE:
Obj55_Laser_Main:
bsr.w Obj55_Laser_ChkGround
jsrto (ObjectMove).l, JmpTo25_ObjectMove
cmpi.w #$2870,x_pos(a0) ; has laser moved off screen going left?
blo.w JmpTo62_DeleteObject ; if yes, branch
cmpi.w #$2A10,x_pos(a0) ; has laser moved off screen going right?
bhs.w JmpTo62_DeleteObject ; if yes, branch
jmpto (DisplaySprite).l, JmpTo41_DisplaySprite
; ===========================================================================
; checks if laser hit the ground
; loc_335FE:
Obj55_Laser_ChkGround:
cmpi.w #$250,y_pos(a0) ; is laser on ground level?
blo.s return_33626 ; if not, branch
tst.w x_vel(a0) ; is laser moving left?
bmi.w Obj55_Laser_ChkGroundLeft ; if yes, branch
move.w x_pos(a0),d0
cmpi.w #$2980,d0
bhs.s return_33626
cmpi.w #$297C,d0
blo.w return_33626
move.w #$2988,d1 ; wave's start position
bra.s Obj55_Laser_CreateWave
; ===========================================================================
return_33626:
rts
; ===========================================================================
; loc_33628:
Obj55_Laser_ChkGroundLeft:
move.w x_pos(a0),d0
cmpi.w #$2900,d0
blo.s return_3363E
cmpi.w #$2904,d0
bhs.s return_3363E
move.w #$28F8,d1 ; wave's start position
bra.s Obj55_Laser_CreateWave
; ===========================================================================
return_3363E:
rts
; ===========================================================================
; loc_33640:
Obj55_Laser_CreateWave:
jsrto (SingleObjLoad).l, JmpTo18_SingleObjLoad
bne.s return_336B0
move.b #ObjID_OOZBoss,id(a1) ; load obj55
move.b #8,boss_subtype(a1)
move.b #4,routine_secondary(a1) ; => Obj55_Wave
move.b #$8B,collision_flags(a1)
move.b #2,anim(a1)
move.b #$D,mapping_frame(a1)
move.w #0,y_vel(a1)
move.l #Obj55_MapUnc_33756,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_OOZBoss,0,0),art_tile(a1)
jsrto (Adjust2PArtPointer).l, JmpTo63_Adjust2PArtPointer
ori.b #4,render_flags(a1)
move.b #2,priority(a1)
move.w #5,Obj55_Wave_delay(a1)
move.b #7,Obj55_Wave_count(a1)
move.w x_vel(a0),x_vel(a1)
move.w d1,x_pos(a1)
move.w #$250,y_pos(a1)
move.b #SndID_LaserFloor,d0
jsrto (PlaySound).l, JmpTo11_PlaySound
return_336B0:
rts
; ===========================================================================
; loc_336B2:
Obj55_Wave:
subq.w #1,Obj55_Wave_delay(a0)
bpl.s Obj55_Wave_End
move.w #$C7,Obj55_Wave_delay(a0)
subq.b #1,Obj55_Wave_count(a0)
bmi.s Obj55_Wave_End
jsrto (SingleObjLoad2).l, JmpTo24_SingleObjLoad2
bne.s Obj55_Wave_End
moveq #0,d0
move.w #bytesToLcnt(object_size),d1
- move.l (a0,d0.w),(a1,d0.w) ; make new object a copy of this one
addq.w #4,d0
dbf d1,-
if object_size&3
move.w (a0,d0.w),(a1,d0.w) ; make new object a copy of this one
endif
move.w #5,Obj55_Wave_delay(a1)
move.w #$200,anim(a1)
move.w #$10,d0 ; place new wave object 16 pixels next to current one
tst.w x_vel(a1) ; is object going left?
bpl.s + ; if not, branch
neg.w d0 ; flip offset
+
add.w d0,x_pos(a1) ; set position
move.b #SndID_LaserFloor,d0
jsrto (PlaySound).l, JmpTo11_PlaySound
Obj55_Wave_End:
lea (Ani_obj55).l,a1
jsrto (AnimateSprite).l, JmpTo22_AnimateSprite
jmpto (MarkObjGone).l, JmpTo38_MarkObjGone
; ===========================================================================
BranchTo2_JmpTo62_DeleteObject
bra.w JmpTo62_DeleteObject
; ===========================================================================
; animation script
; off_33712:
Ani_obj55: offsetTable
offsetTableEntry.w byte_3371E
offsetTableEntry.w byte_33738
offsetTableEntry.w byte_3373B
offsetTableEntry.w byte_3374D
offsetTableEntry.w byte_33750
offsetTableEntry.w byte_33753
byte_3371E:
dc.b 9, 8, 8, 8, 8, 9, 9, 9, 9, 8, 8, 8, 8, 9, 9, 9
dc.b 9, 8, 8, 8, 8, 9, 9, 9, 9,$FF; 16
rev02even
byte_33738:
dc.b $F, 1,$FF
rev02even
byte_3373B:
dc.b 1, $D,$11, $E,$12, $F,$13,$10,$14,$14,$10,$13, $F,$12, $E,$11
dc.b $D,$FA ; 16
rev02even
byte_3374D:
dc.b $F, $A,$FF
rev02even
byte_33750:
dc.b $F, $B,$FF
rev02even
byte_33753:
dc.b $F, 8,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj55_MapUnc_33756: BINCLUDE "mappings/sprite/obj55.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo41_DisplaySprite
jmp (DisplaySprite).l
JmpTo62_DeleteObject
jmp (DeleteObject).l
JmpTo18_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo38_MarkObjGone
jmp (MarkObjGone).l
JmpTo11_PlaySound
jmp (PlaySound).l
JmpTo24_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo22_AnimateSprite
jmp (AnimateSprite).l
JmpTo5_RandomNumber
jmp (RandomNumber).l
JmpTo63_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo13_CalcSine
jmp (CalcSine).l
JmpTo8_PlayLevelMusic
jmp (PlayLevelMusic).l
JmpTo8_LoadPLC_AnimalExplosion
jmp (LoadPLC_AnimalExplosion).l
; loc_338E4:
JmpTo25_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 09 - Sonic in Special Stage
; ----------------------------------------------------------------------------
; Sprite_338EC:
Obj09:
bsr.w loc_33908
moveq #0,d0
move.b routine(a0),d0
move.w Obj09_Index(pc,d0.w),d1
jmp Obj09_Index(pc,d1.w)
; ===========================================================================
; off_338FE:
Obj09_Index: offsetTable
offsetTableEntry.w Obj09_Init ; 0
offsetTableEntry.w Obj09_MdNormal ; 2
offsetTableEntry.w Obj09_MdJump ; 4
offsetTableEntry.w Obj09_Index ; 6 - invalid
offsetTableEntry.w Obj09_MdAir ; 8
; ===========================================================================
loc_33908:
lea (SS_Ctrl_Record_Buf_End).w,a1
moveq #(SS_Ctrl_Record_Buf_End-SS_Ctrl_Record_Buf)/2-2,d0
- move.w -4(a1),-(a1)
dbf d0,-
move.w (Ctrl_1_Logical).w,-(a1)
rts
; ===========================================================================
; loc_3391C:
Obj09_Init:
move.b #2,routine(a0)
moveq #0,d0
move.l d0,ss_x_pos(a0)
move.w #$80,d1
move.w d1,ss_y_pos(a0)
move.w d0,ss_y_sub(a0)
add.w (SS_Offset_X).w,d0
move.w d0,x_pos(a0)
add.w (SS_Offset_Y).w,d1
move.w d1,y_pos(a0)
move.b #$E,y_radius(a0)
move.b #7,x_radius(a0)
move.l #Obj09_MapUnc_34212,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_SpecialSonic,1,0),art_tile(a0)
move.b #4,render_flags(a0)
move.b #3,priority(a0)
move.w #$6E,ss_z_pos(a0)
clr.b (SS_Swap_Positions_Flag).w
move.w #$400,ss_init_flip_timer(a0)
move.b #$40,angle(a0)
move.b #1,(Sonic_LastLoadedDPLC).w
clr.b ss_slide_timer(a0)
bclr #6,status(a0)
clr.b collision_property(a0)
clr.b ss_dplc_timer(a0)
movea.l #SpecialStageShadow_Sonic,a1
move.b #ObjID_SSShadow,id(a1) ; load obj63 (shadow) at $FFFFB140
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
addi.w #$18,y_pos(a1)
move.l #Obj63_MapUnc_34492,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_SpecialFlatShadow,3,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #4,priority(a1)
move.l a0,ss_parent(a1)
bra.w LoadSSSonicDynPLC
; ===========================================================================
Obj09_MdNormal:
tst.b routine_secondary(a0)
bne.s Obj09_Hurt
lea (Ctrl_1_Held_Logical).w,a2
bsr.w SSPlayer_Move
bsr.w SSPlayer_Traction
bsr.w SSPlayerSwapPositions
bsr.w SSObjectMove
bsr.w SSAnglePos
bsr.w SSSonic_Jump
bsr.w SSPlayer_SetAnimation
lea (off_341E4).l,a1
bsr.w SSPlayer_Animate
bsr.w SSPlayer_Collision
bra.w LoadSSSonicDynPLC
; ===========================================================================
Obj09_Hurt:
bsr.w SSHurt_Animation
bsr.w SSPlayerSwapPositions
bsr.w SSObjectMove
bsr.w SSAnglePos
bra.w LoadSSSonicDynPLC
; ===========================================================================
SSHurt_Animation:
moveq #0,d0
move.b ss_hurt_timer(a0),d0
addi_.b #8,d0
move.b d0,ss_hurt_timer(a0)
bne.s +
move.b #0,routine_secondary(a0)
move.b #$1E,ss_dplc_timer(a0)
+
add.b angle(a0),d0
andi.b #$FC,render_flags(a0)
subi.b #$10,d0
lsr.b #5,d0
add.w d0,d0
move.b byte_33A92(pc,d0.w),mapping_frame(a0)
move.b byte_33A92+1(pc,d0.w),d0
or.b d0,render_flags(a0)
move.b ss_hurt_timer(a0),d0
subi_.b #8,d0
bne.s return_33A90
move.b d0,collision_property(a0)
cmpa.l #MainCharacter,a0
bne.s +
tst.w (Ring_count).w
beq.s return_33A90
bra.s ++
; ===========================================================================
+
tst.w (Ring_count_2P).w
beq.s return_33A90
+
jsrto (SSSingleObjLoad).l, JmpTo_SSSingleObjLoad
bne.s return_33A90
move.l a0,ss_parent(a1)
move.b #ObjID_SSRingSpill,id(a1) ; load obj5B
return_33A90:
rts
; ===========================================================================
byte_33A92:
dc.b 4, 1
dc.b 0, 0 ; 2
dc.b 4, 0 ; 4
dc.b $C, 0 ; 6
dc.b 4, 2 ; 8
dc.b 0, 2 ; 10
dc.b 4, 3 ; 12
dc.b $C, 1 ; 14
dword_33AA2:
dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($000) ; Sonic in upright position, $58 tiles
dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($058) ; Sonic in diagonal position, $CC tiles
dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($124) ; Sonic in horizontal position, $4D tiles
dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($171) ; Sonic in ball form, $12 tiles
; ===========================================================================
LoadSSSonicDynPLC:
move.b ss_dplc_timer(a0),d0
beq.s +
subq.b #1,d0
move.b d0,ss_dplc_timer(a0)
andi.b #1,d0
beq.s +
rts
; ===========================================================================
+
jsrto (DisplaySprite).l, JmpTo42_DisplaySprite
lea dword_33AA2(pc),a3
lea (Sonic_LastLoadedDPLC).w,a4
move.w #tiles_to_bytes(ArtTile_ArtNem_SpecialSonic),d4
moveq #0,d1
LoadSSPlayerDynPLC:
moveq #0,d0
move.b mapping_frame(a0),d0
cmp.b (a4),d0
beq.s return_33B3E
move.b d0,(a4)
moveq #0,d6
cmpi.b #4,d0
blt.s loc_33AFE
addq.w #4,d6
cmpi.b #$C,d0
blt.s loc_33AFE
addq.w #4,d6
cmpi.b #$10,d0
blt.s loc_33AFE
addq.b #4,d6
loc_33AFE:
move.l (a3,d6.w),d6
add.w d1,d0
add.w d0,d0
lea (Obj09_MapRUnc_345FA).l,a2
adda.w (a2,d0.w),a2
move.w (a2)+,d5
subq.w #1,d5
bmi.s return_33B3E
SSPLC_ReadEntry:
moveq #0,d1
move.w (a2)+,d1
move.w d1,d3
lsr.w #8,d3
andi.w #$F0,d3
addi.w #$10,d3
andi.w #$FFF,d1
lsl.w #1,d1
add.l d6,d1
move.w d4,d2
add.w d3,d4
add.w d3,d4
jsr (QueueDMATransfer).l
dbf d5,SSPLC_ReadEntry
return_33B3E:
rts
; ===========================================================================
SSSonic_Jump:
lea (Ctrl_1_Press_Logical).w,a2
SSPlayer_Jump:
move.b (a2),d0
andi.b #button_B_mask|button_C_mask|button_A_mask,d0
beq.w return_33BAC
move.w #$780,d2
moveq #0,d0
move.b angle(a0),d0
addi.b #$80,d0
jsr (CalcSine).l
muls.w d2,d1
asr.l #8,d1
add.w d1,x_vel(a0)
muls.w d2,d0
asr.l #7,d0
add.w d0,y_vel(a0)
bset #2,status(a0)
move.b #4,routine(a0)
move.b #3,anim(a0)
moveq #0,d0
move.b d0,anim_frame_duration(a0)
move.b d0,anim_frame(a0)
move.b d0,collision_property(a0)
tst.b (SS_2p_Flag).w
bne.s loc_33B9E
tst.w (Player_mode).w
bne.s loc_33BA2
loc_33B9E:
not.b (SS_Swap_Positions_Flag).w
loc_33BA2:
move.w #SndID_Jump,d0
jsr (PlaySound).l
return_33BAC:
rts
; ===========================================================================
Obj09_MdJump:
lea (Ctrl_1_Held_Logical).w,a2
bsr.w SSPlayer_ChgJumpDir
bsr.w SSObjectMoveAndFall
bsr.w SSPlayer_JumpAngle
bsr.w SSPlayer_DoLevelCollision
bsr.w SSPlayerSwapPositions
bsr.w SSAnglePos
lea (off_341E4).l,a1
bsr.w SSPlayer_Animate
bra.w LoadSSSonicDynPLC
; ===========================================================================
Obj09_MdAir:
lea (Ctrl_1_Held_Logical).w,a2
bsr.w SSPlayer_ChgJumpDir
bsr.w SSObjectMoveAndFall
bsr.w SSPlayer_JumpAngle
bsr.w SSPlayer_DoLevelCollision
bsr.w SSPlayerSwapPositions
bsr.w SSAnglePos
bsr.w SSPlayer_SetAnimation
lea (off_341E4).l,a1
bsr.w SSPlayer_Animate
bra.w LoadSSSonicDynPLC
; ===========================================================================
SSObjectMoveAndFall:
move.l ss_x_pos(a0),d2
move.l ss_y_pos(a0),d3
move.w x_vel(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d2
move.w y_vel(a0),d0
addi.w #$A8,y_vel(a0) ; Apply gravity
ext.l d0
asl.l #8,d0
add.l d0,d3
move.l d2,ss_x_pos(a0)
move.l d3,ss_y_pos(a0)
rts
; ===========================================================================
SSPlayer_ChgJumpDir:
move.b (a2),d0
btst #button_left,d0
bne.s +
btst #button_right,d0
bne.w ++
rts
; ===========================================================================
+
subi.w #$40,x_vel(a0)
rts
; ===========================================================================
+
addi.w #$40,x_vel(a0)
rts
; ===========================================================================
SSPlayer_JumpAngle:
moveq #0,d2
moveq #0,d3
move.w ss_y_pos(a0),d2
bmi.s SSPlayer_JumpAngle_above_screen
move.w ss_x_pos(a0),d3
bmi.s +++
cmp.w d2,d3
blo.s ++
bne.s +
tst.w d3
bne.s +
move.b #$40,angle(a0)
rts
; ===========================================================================
+
lsl.l #5,d2
divu.w d3,d2
move.b d2,angle(a0)
rts
; ===========================================================================
+
lsl.l #5,d3
divu.w d2,d3
subi.w #$40,d3
neg.w d3
move.b d3,angle(a0)
rts
; ===========================================================================
+
neg.w d3
cmp.w d2,d3
bhs.s +
lsl.l #5,d3
divu.w d2,d3
addi.w #$40,d3
move.b d3,angle(a0)
rts
; ===========================================================================
+
lsl.l #5,d2
divu.w d3,d2
subi.w #$80,d2
neg.w d2
move.b d2,angle(a0)
rts
; ===========================================================================
SSPlayer_JumpAngle_above_screen:
neg.w d2
move.w ss_x_pos(a0),d3
bpl.s ++
neg.w d3
cmp.w d2,d3
blo.s +
lsl.l #5,d2
divu.w d3,d2
addi.w #$80,d2
move.b d2,angle(a0)
rts
; ===========================================================================
+
lsl.l #5,d3
divu.w d2,d3
subi.w #$C0,d3
neg.w d3
move.b d3,angle(a0)
rts
; ===========================================================================
+
cmp.w d2,d3
bhs.s +
lsl.l #5,d3
divu.w d2,d3
addi.w #$C0,d3
move.b d3,angle(a0)
rts
; ===========================================================================
+
lsl.l #5,d2
divu.w d3,d2
subi.w #$100,d2
neg.w d2
move.b d2,angle(a0)
rts
; ===========================================================================
loc_33D02:
moveq #0,d6
moveq #0,d0
move.w ss_x_pos(a1),d0
bpl.s loc_33D10
st d6
neg.w d0
loc_33D10:
lsl.l #7,d0
divu.w ss_z_pos(a1),d0
move.b byte_33D32(pc,d0.w),d0
tst.b d6
bne.s loc_33D24
subi.b #$80,d0
neg.b d0
loc_33D24:
tst.w ss_y_pos(a1)
bpl.s loc_33D2C
neg.b d0
loc_33D2C:
move.b d0,angle(a0)
rts
; ===========================================================================
byte_33D32:
dc.b $40,$40,$40,$40,$41,$41,$41,$42,$42,$42,$43,$43,$43,$44,$44,$44
dc.b $45,$45,$45,$46,$46,$46,$47,$47,$47,$48,$48,$48,$48,$49,$49,$49; 16
dc.b $4A,$4A,$4A,$4B,$4B,$4B,$4C,$4C,$4C,$4D,$4D,$4D,$4E,$4E,$4E,$4F; 32
dc.b $4F,$50,$50,$50,$51,$51,$51,$52,$52,$52,$53,$53,$53,$54,$54,$54; 48
dc.b $55,$55,$56,$56,$56,$57,$57,$57,$58,$58,$59,$59,$59,$5A,$5A,$5B; 64
dc.b $5B,$5B,$5C,$5C,$5D,$5D,$5E,$5E,$5E,$5F,$5F,$60,$60,$61,$61,$62; 80
dc.b $62,$63,$63,$64,$64,$65,$65,$66,$66,$67,$67,$68,$68,$69,$6A,$6A; 96
dc.b $6B,$6C,$6C,$6D,$6E,$6E,$6F,$70,$71,$72,$73,$74,$75,$77,$78,$7A; 112
dc.b $80, 0 ; 128
; ===========================================================================
SSPlayer_DoLevelCollision:
move.w ss_y_pos(a0),d0
ble.s +
muls.w d0,d0
move.w ss_x_pos(a0),d1
muls.w d1,d1
add.w d1,d0
move.w ss_z_pos(a0),d1
mulu.w d1,d1
cmp.l d1,d0
blo.s +
move.b #2,routine(a0)
bclr #2,status(a0)
moveq #0,d0
move.w d0,x_vel(a0)
move.w d0,y_vel(a0)
move.w d0,inertia(a0) ; This makes player stop on ground
move.b d0,ss_slide_timer(a0)
bset #6,status(a0)
bsr.w SSObjectMove
bsr.w SSAnglePos
+
rts
; ===========================================================================
SSPlayer_Collision:
tst.b collision_property(a0)
beq.s return_33E42
clr.b collision_property(a0)
tst.b ss_dplc_timer(a0)
bne.s return_33E42
clr.b inertia(a0) ; clears only high byte, leaving a bit of speed
cmpa.l #MainCharacter,a0
bne.s +
st.b (SS_Swap_Positions_Flag).w
tst.w (Ring_count).w
beq.s loc_33E38
bra.s ++
; ===========================================================================
+
clr.b (SS_Swap_Positions_Flag).w
tst.w (Ring_count_2P).w
beq.s loc_33E38
+
move.w #SndID_RingSpill,d0
jsr (PlaySound).l
loc_33E38:
move.b #2,routine_secondary(a0) ; hurt state
clr.b ss_hurt_timer(a0)
return_33E42:
rts
; ===========================================================================
SSPlayerSwapPositions:
tst.w (Player_mode).w
bne.s return_33E8E
move.w ss_z_pos(a0),d0
cmpa.l #MainCharacter,a0
bne.s loc_33E5E
tst.b (SS_Swap_Positions_Flag).w
beq.s loc_33E6E
bra.s loc_33E64
; ===========================================================================
loc_33E5E:
tst.b (SS_Swap_Positions_Flag).w
bne.s loc_33E6E
loc_33E64:
cmpi.w #$80,d0
beq.s return_33E8E
addq.w #1,d0
bra.s loc_33E76
; ===========================================================================
loc_33E6E:
cmpi.w #$6E,d0
beq.s return_33E8E
subq.w #1,d0
loc_33E76:
move.w d0,ss_z_pos(a0)
cmpi.w #$77,d0
bhs.s loc_33E88
move.b #3,priority(a0)
rts
; ===========================================================================
loc_33E88:
move.b #2,priority(a0)
return_33E8E:
rts
; ===========================================================================
byte_33E90:
dc.b 1, 1
dc.b 0, 0 ; 2
dc.b 1, 0 ; 4
dc.b 2, 0 ; 6
dc.b 1, 2 ; 8
dc.b 0, 2 ; 10
dc.b 1, 3 ; 12
dc.b 2, 1 ; 14
; ===========================================================================
SSPlayer_SetAnimation:
btst #2,status(a0)
beq.s +
move.b #3,anim(a0)
andi.b #$FC,status(a0)
rts
; ===========================================================================
+
moveq #0,d0
move.b angle(a0),d0
subi.b #$10,d0
lsr.b #5,d0
move.b d0,d1
add.w d0,d0
move.b byte_33E90(pc,d0.w),d2
cmp.b anim(a0),d2
bne.s +
cmp.b ss_last_angle_index(a0),d1
beq.s return_33EFE
+
move.b d1,ss_last_angle_index(a0)
move.b d2,anim(a0)
move.b byte_33E90+1(pc,d0.w),d0
andi.b #$FC,status(a0)
or.b d0,status(a0)
cmpi.b #1,d1
beq.s loc_33EF8
cmpi.b #5,d1
bne.s return_33EFE
loc_33EF8:
move.w #$400,ss_init_flip_timer(a0)
return_33EFE:
rts
; ===========================================================================
SSPlayer_Animate:
moveq #0,d0
move.b anim(a0),d0
cmp.b next_anim(a0),d0
beq.s SSAnim_Do
move.b #0,anim_frame(a0)
move.b d0,next_anim(a0)
move.b #0,anim_frame_duration(a0)
SSAnim_Do:
subq.b #1,anim_frame_duration(a0)
bpl.s SSAnim_Delay
add.w d0,d0
adda.w (a1,d0.w),a1
move.b (SS_player_anim_frame_timer).w,d0
lsr.b #1,d0
move.b d0,anim_frame_duration(a0)
cmpi.b #0,anim(a0)
bne.s +
subi_.b #1,ss_flip_timer(a0)
bgt.s +
bchg #0,status(a0)
bchg #0,render_flags(a0)
move.b ss_init_flip_timer(a0),ss_flip_timer(a0)
+
moveq #0,d1
move.b anim_frame(a0),d1
move.b 1(a1,d1.w),d0
bpl.s +
move.b #0,anim_frame(a0)
move.b 1(a1),d0
+
andi.b #$7F,d0
move.b d0,mapping_frame(a0)
move.b status(a0),d1
andi.b #3,d1
andi.b #$FC,render_flags(a0)
or.b d1,render_flags(a0)
addq.b #1,anim_frame(a0)
SSAnim_Delay:
rts
; ===========================================================================
SSPlayer_Move:
move.w inertia(a0),d2
move.b (a2),d0
btst #button_left,d0
bne.s SSPlayer_MoveLeft
btst #button_right,d0
bne.w SSPlayer_MoveRight
bset #6,status(a0)
bne.s +
move.b #$1E,ss_slide_timer(a0)
+
move.b angle(a0),d0
bmi.s +
subi.b #$38,d0
cmpi.b #$10,d0
bhs.s +
move.w d2,d1
asr.w #3,d1
sub.w d1,d2
bra.s ++
; ===========================================================================
+
move.w d2,d1
asr.w #3,d1
sub.w d1,d2
+
move.w d2,inertia(a0)
move.b ss_slide_timer(a0),d0
beq.s +
subq.b #1,d0
move.b d0,ss_slide_timer(a0)
+
rts
; ===========================================================================
SSPlayer_MoveLeft:
addi.w #$60,d2
cmpi.w #$600,d2
ble.s +
move.w #$600,d2
bra.s +
; ===========================================================================
SSPlayer_MoveRight:
subi.w #$60,d2
cmpi.w #-$600,d2
bge.s +
move.w #-$600,d2
+
move.w d2,inertia(a0)
bclr #6,status(a0)
clr.b ss_slide_timer(a0)
rts
; ===========================================================================
SSPlayer_Traction:
tst.b ss_slide_timer(a0)
bne.s +
move.b angle(a0),d0
jsr (CalcSine).l
muls.w #$50,d1
asr.l #8,d1
add.w d1,inertia(a0)
+
move.b angle(a0),d0
bpl.s return_34048
addi_.b #4,d0
cmpi.b #-$78,d0
blo.s return_34048
mvabs.w inertia(a0),d0
cmpi.w #$100,d0
bhs.s return_34048
move.b #8,routine(a0)
return_34048:
rts
; ===========================================================================
SSObjectMove:
moveq #0,d0
moveq #0,d1
move.w inertia(a0),d2
bpl.s +
neg.w d2
lsr.w #8,d2
sub.b d2,angle(a0)
bra.s ++
; ===========================================================================
+
lsr.w #8,d2
add.b d2,angle(a0)
+
move.b angle(a0),d0
jsr (CalcSine).l
muls.w ss_z_pos(a0),d1
asr.l #8,d1
move.w d1,ss_x_pos(a0)
muls.w ss_z_pos(a0),d0
asr.l #8,d0
move.w d0,ss_y_pos(a0)
rts
; ===========================================================================
SSAnglePos:
move.w ss_x_pos(a0),d0
muls.w #$CC,d0
asr.l #8,d0
add.w (SS_Offset_X).w,d0
move.w d0,x_pos(a0)
move.w ss_y_pos(a0),d0
add.w (SS_Offset_Y).w,d0
move.w d0,y_pos(a0)
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 63 - Character shadow from Special Stage
; ----------------------------------------------------------------------------
; Sprite_340A4:
Obj63:
movea.l ss_parent(a0),a1 ; a1=object
cmpa.l #MainCharacter,a1
bne.s loc_340BC
movea.l #MainCharacter,a1 ; a1=character
bsr.s loc_340CC
jmpto (DisplaySprite).l, JmpTo42_DisplaySprite
; ===========================================================================
loc_340BC:
movea.l #Sidekick,a1 ; a1=object
bsr.s loc_340CC
bsr.w loc_341BA
jmpto (DisplaySprite).l, JmpTo42_DisplaySprite
; ===========================================================================
loc_340CC:
cmpi.b #2,routine(a1)
beq.w loc_34108
bsr.w loc_33D02
move.b angle(a0),d0
jsr (CalcSine).l
muls.w ss_z_pos(a1),d1
muls.w #$CC,d1
swap d1
add.w (SS_Offset_X).w,d1
move.w d1,x_pos(a0)
muls.w ss_z_pos(a1),d0
asr.l #8,d0
add.w (SS_Offset_Y).w,d0
move.w d0,y_pos(a0)
bra.w loc_3411A
; ===========================================================================
loc_34108:
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
move.b angle(a1),angle(a0)
loc_3411A:
moveq #0,d0
move.b angle(a0),d0
subi.b #$10,d0
lsr.b #5,d0
move.b d0,d1
lsl.w #3,d0
lea word_3417A(pc),a2
adda.w d0,a2
move.w (a2)+,art_tile(a0)
move.w (a2)+,d0
add.w d0,x_pos(a0)
move.w (a2)+,d0
add.w d0,y_pos(a0)
move.b (a2)+,mapping_frame(a0)
move.b render_flags(a0),d0
andi.b #$FC,d0
or.b (a2)+,d0
move.b d0,render_flags(a0)
tst.b angle(a0)
bpl.s return_34178
cmpi.b #3,d1
beq.s loc_34164
cmpi.b #7,d1
bne.s loc_3416A
loc_34164:
addi_.b #3,mapping_frame(a0)
loc_3416A:
move.w (SS_Offset_Y).w,d1
sub.w y_pos(a0),d1
add.w d1,d1
add.w d1,y_pos(a0)
return_34178:
rts
; ===========================================================================
word_3417A:
dc.w make_art_tile(ArtTile_ArtNem_SpecialDiagShadow,3,0), $14, $14, $101
dc.w make_art_tile(ArtTile_ArtNem_SpecialFlatShadow,3,0), 0, $18, 0; 4
dc.w make_art_tile(ArtTile_ArtNem_SpecialDiagShadow,3,0),$FFEC, $14, $100; 8
dc.w make_art_tile(ArtTile_ArtNem_SpecialSideShadow,3,0),$FFEC, 0, $200; 12
dc.w make_art_tile(ArtTile_ArtNem_SpecialDiagShadow,3,0),$FFEC,$FFEC, $700; 16
dc.w make_art_tile(ArtTile_ArtNem_SpecialFlatShadow,3,0), 0,$FFE8, $900; 20
dc.w make_art_tile(ArtTile_ArtNem_SpecialDiagShadow,3,0), $14,$FFEC, $701; 24
dc.w make_art_tile(ArtTile_ArtNem_SpecialSideShadow,3,0), $14, 0, $201; 28
; ===========================================================================
loc_341BA:
cmpi.b #1,anim(a1)
bne.s return_341E0
move.b status(a1),d1
andi.w #3,d1
cmpi.b #2,d1
bhs.s return_341E0
move.b byte_341E2(pc,d1.w),d0
ext.w d0
add.w d0,x_pos(a0)
subi_.w #4,y_pos(a0)
return_341E0:
rts
; ===========================================================================
; animation script
byte_341E2: dc.b 4, -4
off_341E4: offsetTable
offsetTableEntry.w byte_341EE ; 0
offsetTableEntry.w byte_341F4 ; 1
offsetTableEntry.w byte_341FE ; 2
offsetTableEntry.w byte_34204 ; 3
offsetTableEntry.w byte_34208 ; 4
byte_341EE:
dc.b 3, 0, 1, 2, 3,$FF
byte_341F4:
dc.b 3, 4, 5, 6, 7, 8, 9, $A, $B,$FF
byte_341FE:
dc.b 3, $C, $D, $E, $F,$FF
byte_34204:
dc.b 1,$10,$11,$FF
byte_34208:
dc.b 3, 0, 4, $C, 4, 0, 4, $C, 4,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings - uses ArtNem_SpecialSonicAndTails
; ----------------------------------------------------------------------------
Obj09_MapUnc_34212: BINCLUDE "mappings/sprite/obj09.bin"
; ----------------------------------------------------------------------------
; sprite mappings for special stage shadows
; ----------------------------------------------------------------------------
Obj63_MapUnc_34492: BINCLUDE "mappings/sprite/obj63.bin"
; ----------------------------------------------------------------------------
; custom dynamic pattern loading cues for special stage Sonic, Tails and
; Tails' tails
; The first $12 frames are for Sonic, and the next $12 frames are for Tails.
; The last $15 frames are for Tails' tails.
; The first $24 frames are almost normal dplcs -- the only difference being
; that the art tile to load is pre-shifted left by 4 bits.
; The same applies to the last $15 frames, but they have yet another difference:
; a small space optimization. These frames only have one dplc per frame ever,
; hence the two-byte dplc count is removed from each frame.
; ----------------------------------------------------------------------------
Obj09_MapRUnc_345FA: BINCLUDE "mappings/spriteDPLC/obj09.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo42_DisplaySprite
jmp (DisplaySprite).l
JmpTo_SSSingleObjLoad
jmp (SSSingleObjLoad).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 10 - Tails in Special Stage
; ----------------------------------------------------------------------------
; Sprite_347EC:
Obj10:
moveq #0,d0
move.b routine(a0),d0
move.w Obj10_Index(pc,d0.w),d1
jmp Obj10_Index(pc,d1.w)
; ===========================================================================
; off_347FA:
Obj10_Index: offsetTable
offsetTableEntry.w Obj10_Init ; 0
offsetTableEntry.w Obj10_MdNormal ; 1
offsetTableEntry.w Obj10_MdJump ; 2
offsetTableEntry.w Obj10_Index ; 3 - invalid
offsetTableEntry.w Obj10_MdAir ; 4
; ===========================================================================
; loc_34804:
Obj10_Init:
addq.b #2,routine(a0)
moveq #0,d0
move.w d0,ss_x_pos(a0)
move.w #$80,d1
move.w d1,ss_y_pos(a0)
add.w (SS_Offset_X).w,d0
move.w d0,x_pos(a0)
add.w (SS_Offset_Y).w,d1
move.w d1,y_pos(a0)
move.b #$E,y_radius(a0)
move.b #7,x_radius(a0)
move.l #Obj10_MapUnc_34B3E,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_SpecialTails,2,0),art_tile(a0)
move.b #4,render_flags(a0)
move.b #2,priority(a0)
move.w #$80,ss_z_pos(a0)
tst.w (Player_mode).w
beq.s loc_34864
move.b #3,priority(a0)
move.w #$6E,ss_z_pos(a0)
loc_34864:
move.w #$400,ss_init_flip_timer(a0)
move.b #$40,angle(a0)
move.b #1,(Tails_LastLoadedDPLC).w
clr.b collision_property(a0)
clr.b ss_dplc_timer(a0)
bsr.w LoadSSTailsDynPLC
movea.l #SpecialStageShadow_Tails,a1
move.b #ObjID_SSShadow,id(a1) ; load obj63 (shadow) at $FFFFB180
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
addi.w #$18,y_pos(a1)
move.l #Obj63_MapUnc_34492,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_SpecialFlatShadow,3,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #4,priority(a1)
move.l a0,ss_parent(a1)
movea.l #SpecialStageTails_Tails,a1
move.b #ObjID_SSTailsTails,id(a1) ; load obj88
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.l #Obj88_MapUnc_34DA8,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_SpecialTails_Tails,2,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b priority(a0),priority(a1)
subi_.b #1,priority(a1)
move.l a0,ss_parent(a1)
movea.l a1,a0
move.b #1,(TailsTails_LastLoadedDPLC).w
clr.b ss_dplc_timer(a0)
movea.l ss_parent(a0),a0 ; load 0bj address
rts
; ===========================================================================
Obj10_MdNormal:
tst.b routine_secondary(a0)
bne.s Obj10_Hurt
bsr.w SSTailsCPU_Control
lea (Ctrl_2_Held_Logical).w,a2
tst.w (Player_mode).w
beq.s +
lea (Ctrl_1_Held_Logical).w,a2
+
bsr.w SSPlayer_Move
bsr.w SSPlayer_Traction
moveq #1,d0
bsr.w SSPlayerSwapPositions
bsr.w SSObjectMove
bsr.w SSAnglePos
lea (Ctrl_2_Press_Logical).w,a2
tst.w (Player_mode).w
beq.s +
lea (Ctrl_1_Press_Logical).w,a2
+
bsr.w SSPlayer_Jump
bsr.w SSPlayer_SetAnimation
lea (off_34B1C).l,a1
bsr.w SSPlayer_Animate
bsr.w SSPlayer_Collision
bra.w LoadSSTailsDynPLC
; ===========================================================================
Obj10_Hurt:
bsr.w SSHurt_Animation
bsr.w SSPlayerSwapPositions
bsr.w SSObjectMove
bsr.w SSAnglePos
bra.w LoadSSTailsDynPLC
; ===========================================================================
SSTailsCPU_Control:
tst.b (SS_2p_Flag).w
bne.s +
tst.w (Player_mode).w
beq.s ++
+
rts
; ===========================================================================
+
move.b (Ctrl_2_Held_Logical).w,d0
andi.b #button_up_mask|button_down_mask|button_left_mask|button_right_mask|button_B_mask|button_C_mask|button_A_mask,d0
beq.s +
moveq #0,d0
moveq #3,d1
lea (SS_Ctrl_Record_Buf).w,a1
-
move.l d0,(a1)
move.l d0,(a1)
dbf d1,-
move.w #$B4,(Tails_control_counter).w
rts
; ===========================================================================
+
tst.w (Tails_control_counter).w
beq.s +
subq.w #1,(Tails_control_counter).w
rts
; ===========================================================================
+
lea (SS_Last_Ctrl_Record).w,a1
move.w (a1),(Ctrl_2_Logical).w
rts
; ===========================================================================
dword_349B8:
dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($183) ; Tails in upright position, $3D tiles
dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($1C0) ; Tails in diagonal position, $A4 tiles
dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($264) ; Tails in horizontal position, $3A tiles
dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($29E) ; Tails in ball form, $10 tiles
; ===========================================================================
LoadSSTailsDynPLC:
move.b ss_dplc_timer(a0),d0
beq.s +
subq.b #1,d0
move.b d0,ss_dplc_timer(a0)
andi.b #1,d0
beq.s +
rts
; ===========================================================================
+
jsrto (DisplaySprite).l, JmpTo43_DisplaySprite
lea dword_349B8(pc),a3
lea (Tails_LastLoadedDPLC).w,a4
move.w #tiles_to_bytes(ArtTile_ArtNem_SpecialTails),d4
moveq #$12,d1
bra.w LoadSSPlayerDynPLC
; ===========================================================================
Obj10_MdJump:
lea (Ctrl_2_Held_Logical).w,a2
tst.w (Player_mode).w
beq.s +
lea (Ctrl_1_Held_Logical).w,a2
+
bsr.w SSPlayer_ChgJumpDir
bsr.w SSObjectMoveAndFall
bsr.w SSPlayer_DoLevelCollision
bsr.w SSPlayerSwapPositions
bsr.w SSAnglePos
bsr.w SSPlayer_JumpAngle
lea (off_34B1C).l,a1
bsr.w SSPlayer_Animate
bra.s LoadSSTailsDynPLC
; ===========================================================================
Obj10_MdAir:
lea (Ctrl_2_Held_Logical).w,a2
tst.w (Player_mode).w
beq.s +
lea (Ctrl_1_Held_Logical).w,a2
+
bsr.w SSPlayer_ChgJumpDir
bsr.w SSObjectMoveAndFall
bsr.w SSPlayer_JumpAngle
bsr.w SSPlayer_DoLevelCollision
bsr.w SSPlayerSwapPositions
bsr.w SSAnglePos
bsr.w SSPlayer_SetAnimation
lea (off_34B1C).l,a1
bsr.w SSPlayer_Animate
bra.w LoadSSTailsDynPLC
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 88 - Tails' tails in Special Stage
; ----------------------------------------------------------------------------
; Sprite_34A5C:
Obj88:
movea.l ss_parent(a0),a1 ; load obj address of Tails
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
move.b render_flags(a1),render_flags(a0)
move.b status(a1),status(a0)
move.b anim(a1),anim(a0)
move.b priority(a1),d0
subq.b #1,d0
move.b d0,priority(a0)
cmpi.b #3,anim(a0)
bhs.s return_34A9E
lea (Ani_obj88).l,a1
jsrto (AnimateSprite).l, JmpTo23_AnimateSprite
bra.w LoadSSTailsTailsDynPLC
; ===========================================================================
return_34A9E:
rts
; ===========================================================================
dword_34AA0:
dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($2AE) ; Tails' tails when he is in upright position, $35 tiles
dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($2E3) ; Tails' tails when he is in diagonal position, $3B tiles
dc.l (SSRAM_ArtNem_SpecialSonicAndTails & $FFFFFF) + tiles_to_bytes($31E) ; Tails' tails when he is in horizontal position, $35 tiles
; ===========================================================================
LoadSSTailsTailsDynPLC:
movea.l ss_parent(a0),a1 ; load obj address of Tails
move.b ss_dplc_timer(a1),d0
beq.s +
andi.b #1,d0
beq.s +
rts
; ===========================================================================
+
jsrto (DisplaySprite).l, JmpTo43_DisplaySprite
moveq #0,d0
move.b mapping_frame(a0),d0
cmp.b (TailsTails_LastLoadedDPLC).w,d0
beq.s return_34B1A
move.b d0,(TailsTails_LastLoadedDPLC).w
moveq #0,d6
cmpi.b #7,d0
blt.s loc_34AE4
addq.w #4,d6
cmpi.b #$E,d0
blt.s loc_34AE4
addq.w #4,d6
loc_34AE4:
move.l dword_34AA0(pc,d6.w),d6
addi.w #$24,d0
add.w d0,d0
lea (Obj09_MapRUnc_345FA).l,a2
adda.w (a2,d0.w),a2
move.w #tiles_to_bytes(ArtTile_ArtNem_SpecialTails_Tails),d2
moveq #0,d1
move.w (a2)+,d1
move.w d1,d3
lsr.w #8,d3
andi.w #$F0,d3
addi.w #$10,d3
andi.w #$FFF,d1
lsl.w #1,d1
add.l d6,d1
jsr (QueueDMATransfer).l
return_34B1A:
rts
; ===========================================================================
off_34B1C: offsetTable
offsetTableEntry.w byte_34B24 ; 0
offsetTableEntry.w byte_34B2A ; 1
offsetTableEntry.w byte_34B34 ; 2
offsetTableEntry.w byte_34B3A ; 3
byte_34B24:
dc.b 3, 0, 1, 2, 3,$FF
byte_34B2A:
dc.b 3, 4, 5, 6, 7, 8, 9, $A, $B,$FF
byte_34B34:
dc.b 3, $C, $D, $E, $F,$FF
byte_34B3A:
dc.b 1,$10,$11,$FF
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj10_MapUnc_34B3E: BINCLUDE "mappings/sprite/obj10.bin"
; animation script
; off_34D86:
Ani_obj88: offsetTable
offsetTableEntry.w byte_34D8C ; 0
offsetTableEntry.w byte_34D95 ; 1
offsetTableEntry.w byte_34D9E ; 2
byte_34D8C: dc.b 3, 0, 1, 2, 3, 4, 5, 6,$FF
rev02even
byte_34D95: dc.b 3, 7, 8, 9, $A, $B, $C, $D,$FF
rev02even
byte_34D9E: dc.b 3, $E, $F,$10,$11,$12,$13,$14,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings for Tails' tails in special stage
; ----------------------------------------------------------------------------
Obj88_MapUnc_34DA8: BINCLUDE "mappings/sprite/obj88.bin"
; ===========================================================================
if ~~removeJmpTos
JmpTo43_DisplaySprite
jmp (DisplaySprite).l
JmpTo23_AnimateSprite
jmp (AnimateSprite).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 61 - Bombs from Special Stage
; ----------------------------------------------------------------------------
; Sprite_34EB0:
Obj61:
moveq #0,d0
move.b routine(a0),d0
move.w Obj61_Index(pc,d0.w),d1
jmp Obj61_Index(pc,d1.w)
; ===========================================================================
; off_34EBE:
Obj61_Index: offsetTable
offsetTableEntry.w Obj61_Init ; 0
offsetTableEntry.w loc_34F06 ; 2
offsetTableEntry.w loc_3533A ; 4
offsetTableEntry.w loc_34F6A ; 6
; ===========================================================================
; loc_34EC6:
Obj61_Init:
addq.b #2,routine(a0)
move.w #$7F,x_pos(a0)
move.w #$58,y_pos(a0)
move.l #Obj61_MapUnc_36508,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_SpecialBomb,1,0),art_tile(a0)
move.b #4,render_flags(a0)
move.b #3,priority(a0)
move.b #2,collision_flags(a0)
move.b #-1,(SS_unk_DB4D).w
tst.b angle(a0)
bmi.s loc_34F06
bsr.w loc_3529C
loc_34F06:
bsr.w loc_3512A
bsr.w loc_351A0
lea (Ani_obj61).l,a1
bsr.w loc_3539E
tst.b render_flags(a0)
bpl.s return_34F26
bsr.w loc_34F28
bra.w JmpTo44_DisplaySprite
; ===========================================================================
return_34F26:
rts
; ===========================================================================
loc_34F28:
move.w #8,d6
bsr.w loc_350A0
bcc.s return_34F68
move.b #1,collision_property(a1)
move.w #SndID_SlowSmash,d0
jsr (PlaySoundStereo).l
move.b #6,routine(a0)
move.b #0,anim_frame(a0)
move.b #0,anim_frame_duration(a0)
move.l objoff_34(a0),d0
beq.s return_34F68
move.l #0,objoff_34(a0)
movea.l d0,a1 ; a1=object
st objoff_2A(a1)
return_34F68:
rts
; ===========================================================================
loc_34F6A:
move.b #$A,anim(a0)
move.w #make_art_tile(ArtTile_ArtNem_SpecialExplosion,2,0),art_tile(a0)
bsr.w loc_34F90
bsr.w loc_3512A
bsr.w loc_351A0
lea (Ani_obj61).l,a1
jsrto (AnimateSprite).l, JmpTo24_AnimateSprite
bra.w JmpTo44_DisplaySprite
; ===========================================================================
loc_34F90:
cmpi.w #4,objoff_30(a0)
bhs.s return_34F9E
move.b #1,priority(a0)
return_34F9E:
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 60 - Rings from Special Stage
; ----------------------------------------------------------------------------
; Sprite_34FA0:
Obj60:
moveq #0,d0
move.b routine(a0),d0
move.w Obj60_Index(pc,d0.w),d1
jmp Obj60_Index(pc,d1.w)
; ===========================================================================
; off_34FAE:
Obj60_Index: offsetTable
offsetTableEntry.w Obj60_Init ; 0
offsetTableEntry.w loc_34FF0 ; 1
offsetTableEntry.w loc_3533A ; 2
offsetTableEntry.w loc_35010 ; 3
; ===========================================================================
; loc_34FB6:
Obj60_Init:
addq.b #2,routine(a0)
move.w #$7F,x_pos(a0)
move.w #$58,y_pos(a0)
move.l #Obj5A_Obj5B_Obj60_MapUnc_3632A,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_SpecialRings,3,0),art_tile(a0)
move.b #4,render_flags(a0)
move.b #3,priority(a0)
move.b #1,collision_flags(a0)
tst.b angle(a0)
bmi.s loc_34FF0
bsr.w loc_3529C
loc_34FF0:
bsr.w loc_3512A
bsr.w loc_351A0
bsr.w loc_35036
lea (Ani_obj5B_obj60).l,a1
bsr.w loc_3539E
tst.b render_flags(a0)
bmi.w JmpTo44_DisplaySprite
rts
; ===========================================================================
loc_35010:
move.b #$A,anim(a0)
move.w #make_art_tile(ArtTile_ArtNem_SpecialStars,2,0),art_tile(a0)
bsr.w loc_34F90
bsr.w loc_3512A
bsr.w loc_351A0
lea (Ani_obj5B_obj60).l,a1
jsrto (AnimateSprite).l, JmpTo24_AnimateSprite
bra.w JmpTo44_DisplaySprite
; ===========================================================================
loc_35036:
move.w #$A,d6
bsr.w loc_350A0
bcc.s return_3509E
cmpa.l #MainCharacter,a1
bne.s loc_3504E
addq.w #1,(Ring_count).w
bra.s loc_35052
; ===========================================================================
loc_3504E:
addq.w #1,(Ring_count_2P).w
loc_35052:
addq.b #1,ss_rings_units(a1)
cmpi.b #$A,ss_rings_units(a1)
blt.s loc_3507A
addq.b #1,ss_rings_tens(a1)
move.b #0,ss_rings_units(a1)
cmpi.b #$A,ss_rings_tens(a1)
blt.s loc_3507A
addq.b #1,ss_rings_hundreds(a1)
move.b #0,ss_rings_tens(a1)
loc_3507A:
move.b #6,routine(a0)
move.l objoff_34(a0),d0
beq.s loc_35094
move.l #0,objoff_34(a0)
movea.l d0,a1 ; a1=object
st objoff_2A(a1)
loc_35094:
move.w #SndID_Ring,d0
jsr (PlaySoundStereo).l
return_3509E:
rts
; ===========================================================================
loc_350A0:
cmpi.b #8,anim(a0)
bne.s loc_350DC
tst.b collision_flags(a0)
beq.s loc_350DC
lea (MainCharacter).w,a2 ; a2=object (special stage sonic)
lea (Sidekick).w,a3 ; a3=object (special stage tails)
move.w objoff_34(a2),d0
cmp.w objoff_34(a3),d0
blo.s loc_350CE
movea.l a3,a1
bsr.w loc_350E2
bcs.s return_350E0
movea.l a2,a1
bra.w loc_350E2
; ===========================================================================
loc_350CE:
movea.l a2,a1
bsr.w loc_350E2
bcs.s return_350E0
movea.l a3,a1
bra.w loc_350E2
; ===========================================================================
loc_350DC:
move #0,ccr
return_350E0:
rts
; ===========================================================================
loc_350E2:
tst.b (a1)
beq.s loc_3511A
cmpi.b #2,routine(a1)
bne.s loc_3511A
tst.b routine_secondary(a1)
bne.s loc_3511A
move.b angle(a1),d0
move.b angle(a0),d1
move.b d1,d2
add.b d6,d1
bcs.s loc_35110
sub.b d6,d2
bcs.s loc_35112
cmp.b d1,d0
bhs.s loc_3511A
cmp.b d2,d0
bhs.s loc_35120
bra.s loc_3511A
; ===========================================================================
loc_35110:
sub.b d6,d2
loc_35112:
cmp.b d1,d0
blo.s loc_35120
cmp.b d2,d0
bhs.s loc_35120
loc_3511A:
move #0,ccr
rts
; ===========================================================================
loc_35120:
clr.b collision_flags(a0)
move #1,ccr
rts
; ===========================================================================
loc_3512A:
btst #7,status(a0)
bne.s loc_3516C
cmpi.b #4,(SSTrack_drawing_index).w
bne.s loc_35146
subi.l #$CCCC,objoff_30(a0)
ble.s loc_3516C
bra.s loc_35150
; ===========================================================================
loc_35146:
subi.l #$CCCD,objoff_30(a0)
ble.s loc_3516C
loc_35150:
cmpi.b #$A,anim(a0)
beq.s return_3516A
move.w objoff_30(a0),d0
cmpi.w #$1D,d0
ble.s loc_35164
moveq #$1E,d0
loc_35164:
move.b byte_35180(pc,d0.w),anim(a0)
return_3516A:
rts
; ===========================================================================
loc_3516C:
move.l (sp)+,d0
move.l objoff_34(a0),d0
beq.w JmpTo63_DeleteObject
movea.l d0,a1 ; a1=object
st objoff_2A(a1)
if removeJmpTos
JmpTo63_DeleteObject
endif
jmpto (DeleteObject).l, JmpTo63_DeleteObject
; ===========================================================================
byte_35180:
dc.b 9, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 3
dc.b 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0; 16
; ===========================================================================
loc_351A0:
move.w d7,-(sp)
moveq #0,d2
moveq #0,d3
moveq #0,d4
moveq #0,d5
moveq #0,d6
moveq #0,d7
movea.l (SS_CurrentPerspective).w,a1
move.w objoff_30(a0),d0
beq.w loc_35258
cmp.w (a1)+,d0
bgt.w loc_35258
subq.w #1,d0
add.w d0,d0
move.w d0,d1
add.w d0,d0
add.w d1,d0
tst.b (SSTrack_Orientation).w
bne.w loc_35260
move.b 4(a1,d0.w),d6
move.b 5(a1,d0.w),d7
beq.s loc_351E8
move.b angle(a0),d1
cmp.b d6,d1
blo.s loc_351E8
cmp.b d7,d1
blo.s loc_35258
loc_351E8:
move.b (a1,d0.w),d2
move.b 2(a1,d0.w),d4
move.b 3(a1,d0.w),d5
move.b 1(a1,d0.w),d3
loc_351F8:
bpl.s loc_35202
cmpi.b #$48,d3
blo.s loc_35202
ext.w d3
loc_35202:
move.b angle(a0),d0
jsrto (CalcSine).l, JmpTo14_CalcSine
muls.w d4,d1
muls.w d5,d0
asr.l #8,d0
asr.l #8,d1
add.w d2,d1
add.w d3,d0
move.w d1,x_pos(a0)
move.w d0,y_pos(a0)
move.l objoff_34(a0),d0
beq.s loc_3524E
movea.l d0,a1 ; a1=object
move.b angle(a0),d0
jsrto (CalcSine).l, JmpTo14_CalcSine
move.w d4,d7
lsr.w #2,d7
add.w d7,d4
muls.w d4,d1
move.w d5,d7
asr.w #2,d7
add.w d7,d5
muls.w d5,d0
asr.l #8,d0
asr.l #8,d1
add.w d2,d1
add.w d3,d0
move.w d1,x_pos(a1)
move.w d0,y_pos(a1)
loc_3524E:
ori.b #$80,render_flags(a0)
loc_35254:
move.w (sp)+,d7
rts
; ===========================================================================
loc_35258:
andi.b #$7F,render_flags(a0)
bra.s loc_35254
; ===========================================================================
loc_35260:
move.b #$80,d1
move.b 4(a1,d0.w),d6
move.b 5(a1,d0.w),d7
beq.s loc_35282
sub.w d1,d6
sub.w d1,d7
neg.w d6
neg.w d7
move.b angle(a0),d1
cmp.b d7,d1
blo.s loc_35282
cmp.b d6,d1
blo.s loc_35258
loc_35282:
move.b (a1,d0.w),d2
move.b 2(a1,d0.w),d4
move.b 3(a1,d0.w),d5
subi.w #$100,d2
neg.w d2
move.b 1(a1,d0.w),d3
bra.w loc_351F8
; ===========================================================================
loc_3529C:
jsrto (SSSingleObjLoad2).l, JmpTo_SSSingleObjLoad2
bne.w return_3532C
move.l a0,objoff_34(a1)
move.b (a0),(a1)
move.b #4,routine(a1)
move.l #Obj63_MapUnc_34492,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_SpecialFlatShadow,3,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #5,priority(a1)
move.b angle(a0),d0
cmpi.b #$10,d0
bgt.s loc_352E6
bset #0,render_flags(a1)
move.b #2,objoff_2B(a1)
move.l a1,objoff_34(a0)
rts
; ===========================================================================
loc_352E6:
cmpi.b #$30,d0
bgt.s loc_352FE
bset #0,render_flags(a1)
move.b #1,objoff_2B(a1)
move.l a1,objoff_34(a0)
rts
; ===========================================================================
loc_352FE:
cmpi.b #$50,d0
bgt.s loc_35310
move.b #0,objoff_2B(a1)
move.l a1,objoff_34(a0)
rts
; ===========================================================================
loc_35310:
cmpi.b #$70,d0
bgt.s loc_35322
move.b #1,objoff_2B(a1)
move.l a1,objoff_34(a0)
rts
; ===========================================================================
loc_35322:
move.b #2,objoff_2B(a1)
move.l a1,objoff_34(a0)
return_3532C:
rts
; ===========================================================================
dc.b 0
dc.b 0 ; 1
dc.b 0 ; 2
dc.b $18 ; 3
dc.b 0 ; 4
dc.b $14 ; 5
dc.b 0 ; 6
dc.b $14 ; 7
dc.b 0 ; 8
dc.b $14 ; 9
dc.b 0 ; 10
dc.b 0 ; 11
; ===========================================================================
loc_3533A:
tst.b objoff_2A(a0)
bne.w BranchTo_JmpTo63_DeleteObject
movea.l objoff_34(a0),a1 ; a1=object
tst.b render_flags(a1)
bmi.s loc_3534E
rts
; ===========================================================================
loc_3534E:
moveq #9,d0
sub.b anim(a1),d0
addi_.b #1,d0
cmpi.b #$A,d0
bne.s loc_35362
move.w #9,d0
loc_35362:
move.w d0,d1
add.w d0,d0
add.w d1,d0
moveq #0,d1
move.b objoff_2B(a0),d1
beq.s loc_3538A
cmpi.b #1,d1
beq.s loc_35380
add.w d1,d0
move.w #make_art_tile(ArtTile_ArtNem_SpecialSideShadow,3,0),art_tile(a0)
bra.s loc_35392
; ===========================================================================
loc_35380:
add.w d1,d0
move.w #make_art_tile(ArtTile_ArtNem_SpecialDiagShadow,3,0),art_tile(a0)
bra.s loc_35392
; ===========================================================================
loc_3538A:
add.w d1,d0
move.w #make_art_tile(ArtTile_ArtNem_SpecialFlatShadow,3,0),art_tile(a0)
loc_35392:
move.b d0,mapping_frame(a0)
bra.w JmpTo44_DisplaySprite
; ===========================================================================
BranchTo_JmpTo63_DeleteObject
jmpto (DeleteObject).l, JmpTo63_DeleteObject
; ===========================================================================
loc_3539E:
subq.b #1,anim_frame_duration(a0)
bpl.s return_353E8
moveq #0,d0
move.b anim(a0),d0
add.w d0,d0
adda.w (a1,d0.w),a1
move.b (a1),anim_frame_duration(a0)
moveq #0,d1
move.b anim_frame(a0),d1
move.b 1(a1,d1.w),d0
bpl.s loc_353CA
move.b #0,anim_frame(a0)
move.b 1(a1),d0
loc_353CA:
andi.b #$7F,d0
move.b d0,mapping_frame(a0)
move.b status(a0),d1
andi.b #3,d1
andi.b #$FC,render_flags(a0)
or.b d1,render_flags(a0)
addq.b #1,anim_frame(a0)
return_353E8:
rts
; ===========================================================================
byte_353EA:
dc.b $38
dc.b $48 ; 1
dc.b $2A ; 2
dc.b $56 ; 3
dc.b $1C ; 4
dc.b $64 ; 5
dc.b $E ; 6
dc.b $72 ; 7
dc.b 0 ; 8
dc.b $80 ; 9
byte_353F4:
dc.b $40
dc.b $30 ; 1
dc.b $50 ; 2
dc.b $20 ; 3
dc.b $60 ; 4
dc.b $10 ; 5
dc.b $70 ; 6
dc.b 0 ; 7
dc.b $80 ; 8
dc.b 0 ; 9
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 5B - Ring spray/spill in Special Stage
; ----------------------------------------------------------------------------
; Sprite_353FE:
Obj5B:
moveq #0,d0
move.b routine(a0),d0
move.w Obj5B_Index(pc,d0.w),d1
jmp Obj5B_Index(pc,d1.w)
; ===========================================================================
; off_3540C:
Obj5B_Index: offsetTable
offsetTableEntry.w Obj5B_Init ; 0
offsetTableEntry.w Obj5B_Main ; 2
; ===========================================================================
; loc_35410:
Obj5B_Init:
movea.l ss_parent(a0),a3
moveq #0,d1
move.b ss_rings_tens(a3),d1
beq.s loc_35428
subi_.b #1,ss_rings_tens(a3)
move.w #$A,d1
bra.s loc_35458
; ===========================================================================
loc_35428:
move.b ss_rings_hundreds(a3),d1
beq.s loc_35440
subi_.b #1,ss_rings_hundreds(a3)
move.b #9,ss_rings_tens(a3)
move.w #$A,d1
bra.s loc_35458
; ===========================================================================
loc_35440:
move.b ss_rings_units(a3),d1
beq.s loc_3545C
move.b #0,ss_rings_units(a3)
btst #0,d1
beq.s loc_35458
lea_ byte_353F4,a2
bra.s loc_3545C
; ===========================================================================
loc_35458:
lea_ byte_353EA,a2
loc_3545C:
cmpi.b #ObjID_SonicSS,(a3)
bne.s loc_35468
sub.w d1,(Ring_count).w
bra.s loc_3546C
; ===========================================================================
loc_35468:
sub.w d1,(Ring_count_2P).w
loc_3546C:
move.w d1,d2
subq.w #1,d2
bmi.w JmpTo63_DeleteObject
movea.l a0,a1
bra.s loc_3547E
; ===========================================================================
loc_35478:
jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad
bne.s loc_354DE
loc_3547E:
move.b #ObjID_SSRingSpill,id(a1) ; load obj5B
move.b #2,routine(a1)
move.l #Obj5A_Obj5B_Obj60_MapUnc_3632A,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_SpecialRings,3,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #5,priority(a1)
move.b #0,collision_flags(a1)
move.b #8,anim(a1)
move.w x_pos(a3),x_pos(a1)
move.w y_pos(a3),y_pos(a1)
move.b angle(a3),d0
addi.b #$40,d0
add.b (a2)+,d0
jsr (CalcSine).l
muls.w #$400,d1
asr.l #8,d1
move.w d1,x_vel(a1)
muls.w #$1000,d0
asr.l #8,d0
move.w d0,y_vel(a1)
loc_354DE:
dbf d2,loc_35478
rts
; ===========================================================================
; loc_354E4:
Obj5B_Main:
jsrto (ObjectMoveAndFall).l, JmpTo7_ObjectMoveAndFall
addi.w #$80,y_vel(a0)
bsr.w loc_3551C
tst.w x_pos(a0)
bmi.w JmpTo63_DeleteObject
cmpi.w #$100,x_pos(a0)
bhs.w JmpTo63_DeleteObject
cmpi.w #$E0,y_pos(a0)
bgt.w JmpTo63_DeleteObject
lea (Ani_obj5B_obj60).l,a1
jsrto (AnimateSprite).l, JmpTo24_AnimateSprite
bra.w JmpTo44_DisplaySprite
; ===========================================================================
loc_3551C:
tst.w y_vel(a0)
bmi.w +
move.b #0,priority(a0)
move.b #9,anim(a0)
+
rts
; ===========================================================================
rts
; ===========================================================================
SSRainbowPaletteColors:
move.w word_35548(pc,d0.w),(Normal_palette_line4+$16).w
move.w word_35548+2(pc,d0.w),(Normal_palette_line4+$18).w
move.w word_35548+4(pc,d0.w),(Normal_palette_line4+$1A).w
rts
; ===========================================================================
word_35548:
dc.w $EE, $88, $44
dc.w $EE, $CC, $88 ; 3
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 5A - Messages/checkpoint from Special Stage
; ----------------------------------------------------------------------------
; Sprite_35554:
Obj5A:
moveq #0,d0
move.b routine(a0),d0
move.w Obj5A_Index(pc,d0.w),d1
jmp Obj5A_Index(pc,d1.w)
; ===========================================================================
; off_35562:
Obj5A_Index: offsetTable
offsetTableEntry.w Obj5A_Init ; 0
offsetTableEntry.w Obj5A_CheckpointRainbow ; 2
offsetTableEntry.w Obj5A_TextFlyoutInit ; 4
offsetTableEntry.w Obj5A_Handshake ; 6
offsetTableEntry.w Obj5A_TextFlyout ; 8
offsetTableEntry.w Obj5A_MostRingsWin ; $A
offsetTableEntry.w Obj5A_RingCheckTrigger ; $C
offsetTableEntry.w Obj5A_RingsNeeded ; $E
offsetTableEntry.w Obj5A_FlashMessage ; $10
offsetTableEntry.w Obj5A_MoveAndFlash ; $12
offsetTableEntry.w Obj5A_FlashOnly ; $14
; ===========================================================================
; loc_35578:
Obj5A_Init:
tst.b (SS_NoCheckpoint_flag).w
bne.s Obj5A_RingsMessageInit
movea.l (SSTrack_last_mappings_copy).w,a1
cmpa.l #MapSpec_Straight4,a1
blt.s ++ ; rts
cmpa.l #MapSpec_Drop1,a1
bge.s ++ ; rts
moveq #6,d0
bsr.s SSRainbowPaletteColors
st.b (SS_Checkpoint_Rainbow_flag).w
moveq #6,d0
-
jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad
bne.s +
move.b #ObjID_SSMessage,id(a1) ; load obj5A
move.b #2,routine(a1) ; => Obj5A_CheckpointRainbow
move.l #Obj5A_Obj5B_Obj60_MapUnc_3632A,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_SpecialRings,3,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #5,priority(a1)
move.b d0,objoff_2A(a1)
move.w #0,objoff_30(a1)
move.b #-1,mapping_frame(a1)
+ dbf d0,-
bra.w JmpTo63_DeleteObject
; ===========================================================================
+
rts
; ===========================================================================
;loc_355E0
Obj5A_RingsMessageInit:
sf.b (SS_NoCheckpoint_flag).w
tst.b (SS_2p_Flag).w
bne.w JmpTo63_DeleteObject
sf.b (SS_HideRingsToGo).w
sf.b (SS_TriggerRingsToGo).w
move.w #0,(SS_NoRingsTogoLifetime).w
move.b #0,objoff_3A(a0)
bra.w JmpTo63_DeleteObject
; ===========================================================================
; temporarily remap characters to title card letter format
; Characters are encoded as Aa, Bb, Cc, etc. through a macro
charset 'a','z','A' ; Convert to uppercase
charset 'A',"\xD\x11\7\x11\1\x11"
charset 'G',0 ; can't have an embedded 0 in a string
charset 'H',"\xB\4\x11\x11\9\xF\5\8\xC\x11\3\6\2\xA\x11\x10\x11\xE\x11"
charset '!',"\x11"
charset '.',"\x12"
specialText macro letters
dc.b letters
dc.b $FF ; output string terminator
endm
Obj5A_RingsToGoText:
specialText "RING"
specialText "!OGOT"
specialText "S"
even
Obj5A_ToGoOffsets:
dc.w $C0 ; 0
dc.w $B8 ; 1
dc.w $B0 ; 2
dc.w $A0 ; 3
dc.w $98 ; 4
dc.w $88 ; 5
charset ; revert character set
; ===========================================================================
;loc_3561E
Obj5A_CreateRingsToGoText:
st.b (SS_TriggerRingsToGo).w
jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad
bne.w return_356E4
move.l #Obj5F_MapUnc_72D2,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_SpecialHUD,2,0),art_tile(a1)
move.b #ObjID_SSMessage,id(a1) ; load obj5A
move.b #4,render_flags(a1)
move.b #1,priority(a1)
bset #6,render_flags(a1)
move.b #0,mainspr_childsprites(a1)
move.b #$E,routine(a1) ; => Obj5A_RingsNeeded
lea sub2_x_pos(a1),a2
move.w #$5A,d1
move.w #$38,d2
moveq #0,d0
moveq #2,d3
- move.w d1,(a2)+ ; sub?_x_pos
move.w d2,(a2)+ ; sub?_y_pos
move.w d0,(a2)+ ; sub?_mapframe
subq.w #8,d1
dbf d3,-
lea Obj5A_RingsToGoText(pc),a3
move.w #$68,d1
move.w #$38,d2
- move.b (a3)+,d0
bmi.s +
jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad
bne.s return_356E4
bsr.s Init_Obj5A
move.b #$10,routine(a1)
move.w d1,x_pos(a1)
move.w d2,y_pos(a1)
move.b d0,mapping_frame(a1)
addq.w #8,d1
bra.s -
; ===========================================================================
+
lea Obj5A_ToGoOffsets(pc),a2
- move.b (a3)+,d0
bmi.s +
jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad
bne.s return_356E4
bsr.s Init_Obj5A
move.b #$12,routine(a1) ; => Obj5A_MoveAndFlash
move.w (a2)+,objoff_2A(a1)
move.w d2,y_pos(a1)
move.b d0,mapping_frame(a1)
bra.s -
; ===========================================================================
+
move.b (a3)+,d0
jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad
bne.s return_356E4
bsr.s Init_Obj5A
move.b #$14,routine(a1) ; => Obj5A_FlashOnly
move.w (a2)+,x_pos(a1)
move.w d2,y_pos(a1)
move.b d0,mapping_frame(a1)
return_356E4:
rts
; ===========================================================================
;loc_356E6
Init_Obj5A:
move.b #ObjID_SSMessage,id(a1) ; load obj5A
move.l #Obj5A_MapUnc_35E1E,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_SpecialMessages,2,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #1,priority(a1)
rts
; ===========================================================================
;loc_35706
Obj5A_RingsNeeded:
move.b (SS_TriggerRingsToGo).w,(SS_HideRingsToGo).w
bne.s +
bsr.s ++
bra.w Obj5A_FlashMessage
; ===========================================================================
+
rts
; ===========================================================================
+
move.w (Ring_count).w,d0
cmpi.w #1,(Player_mode).w
blt.s +
beq.s ++
move.w (Ring_count_2P).w,d0
bra.s ++
; ===========================================================================
+
add.w (Ring_count_2P).w,d0
+
sub.w (SS_Ring_Requirement).w,d0
neg.w d0
bgt.s +
moveq #0,d0
moveq #1,d2
addi_.w #1,(SS_NoRingsTogoLifetime).w
cmpi.w #$C,(SS_NoRingsTogoLifetime).w
blo.s loc_3577A
st.b (SS_HideRingsToGo).w
bra.s loc_3577A
; ===========================================================================
+
; This code converts the remaining rings into binary coded decimal format.
moveq #0,d1
move.w d0,d1
moveq #0,d0
cmpi.w #100,d1
blt.s +
- addi.w #$100,d0
subi.w #100,d1
bgt.s -
+
divu.w #$A,d1
lsl.w #4,d1
or.b d1,d0
swap d1
or.b d1,d0
move.w #0,(SS_NoRingsTogoLifetime).w
sf.b (SS_HideRingsToGo).w
loc_3577A:
moveq #1,d2
lea sub2_x_pos(a0),a1
move.w d0,(SS_RingsToGoBCD).w
move.w d0,d1
andi.w #$F,d1
move.b d1,sub2_mapframe-sub2_x_pos(a1)
lsr.w #4,d0
beq.s +
addq.w #1,d2
move.w d0,d1
andi.w #$F,d1
move.b d1,sub3_mapframe-sub2_x_pos(a1)
lsr.w #4,d0
beq.s +
addq.w #1,d2
andi.w #$F,d0
move.b d0,sub4_mapframe-sub2_x_pos(a1)
+
move.b d2,mainspr_childsprites(a0)
rts
; ===========================================================================
;loc_357B2
Obj5A_FlashMessage:
tst.b (SS_NoCheckpointMsg_flag).w
bne.w + ; rts
tst.b (SS_HideRingsToGo).w
bne.s + ; rts
move.b (Vint_runcount+3).w,d0
andi.b #7,d0
cmpi.b #6,d0
blo.w JmpTo44_DisplaySprite
+
rts
; ===========================================================================
;loc_357D2
Obj5A_MoveAndFlash:
moveq #0,d0
cmpi.w #2,(SS_RingsToGoBCD).w
bhs.s +
moveq #-8,d0
+
add.w objoff_2A(a0),d0
move.w d0,x_pos(a0)
bra.s Obj5A_FlashMessage
; ===========================================================================
;loc_357E8
Obj5A_FlashOnly:
moveq #0,d0
cmpi.w #2,(SS_RingsToGoBCD).w
bhs.s Obj5A_FlashMessage
rts
; ===========================================================================
Obj5A_Rainbow_Frames:
dc.b 0
dc.b 1 ; 1
dc.b 1 ; 2
dc.b 1 ; 3
dc.b 2 ; 4
dc.b 4 ; 5
dc.b 6 ; 6
dc.b 8 ; 7
dc.b 9 ; 8
dc.b $FF ; 9
; ===========================================================================
;loc_357FE
Obj5A_CheckpointRainbow:
cmpi.b #4,(SSTrack_drawing_index).w
bne.s +
move.w objoff_2C(a0),d0
move.b Obj5A_Rainbow_Frames(pc,d0.w),mapping_frame(a0)
bmi.w ++
addi_.w #1,objoff_2C(a0)
moveq #0,d0
move.b objoff_2A(a0),d0
add.w d0,d0
add.w objoff_30(a0),d0
move.b Obj5A_Rainbow_Positions(pc,d0.w),1+x_pos(a0)
move.b Obj5A_Rainbow_Positions+1(pc,d0.w),1+y_pos(a0)
addi.w #$E,objoff_30(a0)
bra.w JmpTo44_DisplaySprite
; ===========================================================================
+
tst.b mapping_frame(a0)
bpl.w JmpTo44_DisplaySprite
rts
; ===========================================================================
Obj5A_Rainbow_Positions:
; x, y
dc.b $F6,$F6
dc.b $70,$5E ; 2
dc.b $76,$58 ; 4
dc.b $7E,$56 ; 6
dc.b $88,$58 ; 8
dc.b $8E,$5E ; 10
dc.b $F6,$F6 ; 12
dc.b $F6,$F6 ; 14
dc.b $6D,$5A ; 16
dc.b $74,$54 ; 18
dc.b $7E,$50 ; 20
dc.b $8A,$54 ; 22
dc.b $92,$5A ; 24
dc.b $F6,$F6 ; 26
dc.b $F6,$F6 ; 28
dc.b $6A,$58 ; 30
dc.b $72,$50 ; 32
dc.b $7E,$4C ; 34
dc.b $8C,$50 ; 36
dc.b $94,$58 ; 38
dc.b $F6,$F6 ; 40
dc.b $F6,$F6 ; 42
dc.b $68,$56 ; 44
dc.b $70,$4C ; 46
dc.b $7E,$48 ; 48
dc.b $8E,$4C ; 50
dc.b $96,$56 ; 52
dc.b $F6,$F6 ; 54
dc.b $62,$5E ; 56
dc.b $66,$50 ; 58
dc.b $70,$46 ; 60
dc.b $7E,$42 ; 62
dc.b $8E,$46 ; 64
dc.b $98,$50 ; 66
dc.b $9C,$5E ; 68
dc.b $5C,$5A ; 70
dc.b $62,$4A ; 72
dc.b $70,$3E ; 74
dc.b $7E,$38 ; 76
dc.b $8E,$3E ; 78
dc.b $9C,$4A ; 80
dc.b $A2,$5A ; 82
dc.b $54,$54 ; 84
dc.b $5A,$3E ; 86
dc.b $6A,$30 ; 88
dc.b $7E,$2A ; 90
dc.b $94,$30 ; 92
dc.b $A4,$3E ; 94
dc.b $AA,$54 ; 96
dc.b $42,$4A ; 98
dc.b $4C,$28 ; 100
dc.b $62,$12 ; 102
dc.b $7E, $A ; 104
dc.b $9C,$12 ; 106
dc.b $B2,$28 ; 108
dc.b $BC,$4A ; 110
dc.b $16,$26 ; 112
dc.b $28,$FC ; 114
dc.b $EC,$EC ; 116
dc.b $EC,$EC ; 118
dc.b $EC,$EC ; 120
dc.b $D6,$FC ; 122
dc.b $E8,$26 ; 124
; ===========================================================================
+
cmpi.w #$E8,x_pos(a0)
bne.w JmpTo63_DeleteObject
moveq #0,d0
bsr.w SSRainbowPaletteColors
sf.b (SS_Checkpoint_Rainbow_flag).w
st.b (SS_NoCheckpointMsg_flag).w
tst.b (SS_2p_Flag).w ; Is it VS mode?
beq.w loc_35978 ; Branch if not
move.w #SndID_Checkpoint,d0
jsr (PlaySound).l
addi.b #$10,(SS_2P_BCD_Score).w
moveq #0,d6
addi_.b #1,(Current_Special_Act).w
move.w #$C,d0
move.w (Ring_count).w,d2
cmp.w (Ring_count_2P).w,d2
bgt.s ++
beq.s +++
subi.b #$10,(SS_2P_BCD_Score).w
addi_.b #1,(SS_2P_BCD_Score).w
move.w #$E,d0
tst.b (Graphics_Flags).w
bpl.s +
move.w #$14,d0
+
move.w #palette_line_1,d6
+
move.w #$80,d3
bsr.w Obj5A_CreateCheckpointWingedHand
add.w d6,art_tile(a1)
add.w d6,2(a2)
bsr.w Obj5A_PrintPhrase
bra.w JmpTo63_DeleteObject
; ===========================================================================
+
subi.b #$10,(SS_2P_BCD_Score).w
move.w #$10,d0
bsr.w Obj5A_PrintPhrase
cmpi.b #3,(Current_Special_Act).w
beq.s +
move.w #$46,objoff_2A(a0)
move.b #$A,routine(a0)
rts
; ===========================================================================
+
bsr.w Obj5A_VSReset
move.w #$46,objoff_2A(a0)
move.b #$C,routine(a0)
rts
; ===========================================================================
loc_35978:
move.w #6,d1
move.w #SndID_Error,d0
move.w (Ring_count).w,d2
add.w (Ring_count_2P).w,d2
cmp.w (SS_Ring_Requirement).w,d2
blt.s +
move.w #4,d1
move.w #SndID_Checkpoint,d0
+
jsr (PlaySound).l
move.w d1,d0
bsr.w Obj5A_PrintCheckpointMessage
bra.w JmpTo63_DeleteObject
; ===========================================================================
;loc_359A6
Obj5A_MostRingsWin:
subi_.w #1,objoff_2A(a0)
beq.s +
rts
; ===========================================================================
+
move.w #$A,d0 ; MOST RINGS WINS
bsr.w Obj5A_PrintPhrase
bra.w JmpTo63_DeleteObject
; ===========================================================================
;loc_359BC
Obj5A_RingCheckTrigger:
subi_.w #1,objoff_2A(a0)
beq.s +
rts
; ===========================================================================
+
st.b (SS_Check_Rings_flag).w
bra.w SSClearObjs
; ===========================================================================
;loc_359CE
Obj5A_Handshake:
cmpi.b #$15,mapping_frame(a0) ; Is this the hand?
bne.s ++ ; if not, branch
move.w objoff_30(a0),d0 ; Target y position for handshake
tst.b objoff_2E(a0)
bne.s +
subi_.w #1,y_pos(a0)
subi_.w #4,d0
cmp.w y_pos(a0),d0
blt.s ++
addi_.w #1,d0
move.w d0,y_pos(a0)
st.b objoff_2E(a0)
bra.s ++
; ===========================================================================
+
addi_.w #1,y_pos(a0)
addi_.w #4,d0
cmp.w y_pos(a0),d0
bgt.s +
subi_.w #1,d0
move.w d0,y_pos(a0)
sf.b objoff_2E(a0)
+
subi_.w #1,objoff_2A(a0)
bne.w JmpTo44_DisplaySprite
tst.b objoff_2F(a0)
beq.s +
-
move.w #MusID_FadeOut,d0
jsr (PlayMusic).l
move.w #$30,objoff_2A(a0)
move.b #$C,routine(a0) ; => Obj5A_RingCheckTrigger
rts
; ===========================================================================
+
cmpi.b #$15,mapping_frame(a0) ; Is this the hand?
bne.w JmpTo63_DeleteObject ; Branch if not
tst.w objoff_30(a0)
beq.w JmpTo63_DeleteObject
tst.b (SS_2p_Flag).w ; Is this VS mode?
beq.s + ; Branch if not
bsr.w Obj5A_VSReset
cmpi.b #3,(Current_Special_Act).w
beq.s -
move.w #$A,d0
bsr.w Obj5A_PrintPhrase
bra.w JmpTo63_DeleteObject
; ===========================================================================
+
bsr.w Obj5A_CreateRingReqMessage
bra.w JmpTo63_DeleteObject
; ===========================================================================
;loc_35A7A
Obj5A_VSReset:
lea (SS2p_RingBuffer).w,a3
moveq #0,d0
move.b (Current_Special_Act).w,d0
subq.w #1,d0
add.w d0,d0
add.w d0,d0
move.w (Ring_count).w,(a3,d0.w)
move.w (Ring_count_2P).w,2(a3,d0.w)
move.w #0,(Ring_count).w
move.w #0,(Ring_count_2P).w
moveq #0,d0
move.w d0,(MainCharacter+ss_rings_base).w
move.b d0,(MainCharacter+ss_rings_units).w
move.w d0,(Sidekick+ss_rings_base).w
move.b d0,(Sidekick+ss_rings_units).w
rts
; ===========================================================================
;loc_35AB6
Obj5A_CreateCheckpointWingedHand:
move.w #$48,d4
tst.b (SS_2p_Flag).w ; Is this VS mode?
beq.s + ; Branch if not
move.w #$1C,d4
+
jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad
bne.w + ; rts
move.b #ObjID_SSMessage,id(a1) ; load obj5A
move.b #6,routine(a1) ; => Obj5A_Handshake
move.l #Obj5A_MapUnc_35E1E,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_SpecialMessages,1,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #1,priority(a1)
move.w d3,x_pos(a1)
move.w d4,y_pos(a1)
move.w #$46,objoff_2A(a1)
move.b #$14,mapping_frame(a1) ; Checkpoint wings
movea.l a1,a2
jsrto (SSSingleObjLoad).l, JmpTo2_SSSingleObjLoad
bne.s + ; rts
move.b #ObjID_SSMessage,id(a1) ; load obj5A
move.b #6,routine(a1) ; => Obj5A_Handshake
move.l #Obj5A_MapUnc_35E1E,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_SpecialMessages,1,0),art_tile(a1)
move.b #4,render_flags(a1)
move.b #0,priority(a1)
move.w d3,x_pos(a1)
move.w d4,y_pos(a1)
move.w d4,objoff_30(a1) ; Target y position for handshake
move.w #$46,objoff_2A(a1)
move.b #$15,mapping_frame(a1) ; Checkpoint hand
cmpi.w #6,d0 ; Does player have enough rings?
bne.s + ; If yes, return
st.b objoff_2F(a1) ; Flag for failed checkpoint
bset #1,render_flags(a1) ; Point thumb down
+
rts
; ===========================================================================
;loc_35B5A
Obj5A_TextFlyoutInit:
subi_.w #1,objoff_2A(a0)
bne.w JmpTo44_DisplaySprite
cmpi.b #$13,mapping_frame(a0) ; Is this the hand or wings?
bgt.w JmpTo63_DeleteObject ; If yes, branch
move.b #8,routine(a0) ; Obj5A_TextFlyout
move.w #8,objoff_14(a0)
move.w x_pos(a0),d1
subi.w #$80,d1
move.w y_pos(a0),d2
subi.w #$70,d2
jsrto (CalcAngle).l, JmpTo_CalcAngle
move.b d0,angle(a0)
bra.w JmpTo44_DisplaySprite
; ===========================================================================
; this makes special stage messages like "most rings wins!" fly off the screen
;loc_35B96
Obj5A_TextFlyout:
moveq #0,d0
move.b angle(a0),d0
jsrto (CalcSine).l, JmpTo14_CalcSine
muls.w objoff_14(a0),d0
muls.w objoff_14(a0),d1
asr.w #8,d0
asr.w #8,d1
add.w d1,x_pos(a0)
add.w d0,y_pos(a0)
cmpi.w #0,x_pos(a0)
blt.w JmpTo63_DeleteObject
cmpi.w #$100,x_pos(a0)
bgt.w JmpTo63_DeleteObject
cmpi.w #0,y_pos(a0)
blt.w JmpTo63_DeleteObject
bra.w JmpTo44_DisplaySprite
; ===========================================================================
;loc_35BD6
Obj5A_PrintNumber:
jsrto (SSSingleObjLoad2).l, JmpTo_SSSingleObjLoad2
bne.s + ; rts
move.b d0,mapping_frame(a1)
move.l #Obj5F_MapUnc_72D2,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_SpecialHUD,2,0),art_tile(a1)
move.b #ObjID_SSMessage,id(a1) ; load obj5A
move.b #4,routine(a1) ; Obj5A_TextFlyoutInit
move.b #4,render_flags(a1)
move.b #1,priority(a1)
move.w d1,x_pos(a1)
move.w d2,y_pos(a1)
move.w #$46,objoff_2A(a1)
+
rts
; ===========================================================================
; Subroutine to draw checkpoint or message text
; d0 = text ID
; d1 = x position of first letter
; d2 = y position
;loc_35C14
Obj5A_PrintWord:
lea SSMessage_TextFrames(pc),a3
adda.w (a3,d0.w),a3
- move.b (a3)+,d0
bmi.s + ; rts
jsrto (SSSingleObjLoad2).l, JmpTo_SSSingleObjLoad2
bne.s + ; rts
move.b d0,mapping_frame(a1)
move.l #Obj5A_MapUnc_35E1E,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_SpecialMessages,2,0),art_tile(a1)
move.b #ObjID_SSMessage,id(a1) ; load obj5A
move.b #4,routine(a1) ; Obj5A_TextFlyoutInit
move.b #4,render_flags(a1)
move.b #1,priority(a1)
move.w d1,x_pos(a1)
move.w d2,y_pos(a1)
move.w #$46,objoff_2A(a1)
addq.w #8,d1
bra.s -
; ===========================================================================
+
rts
; ===========================================================================
; temporarily remap characters to title card letter format
; Characters are encoded as Aa, Bb, Cc, etc. through a macro
charset 'a','z','A' ; Convert to uppercase
charset 'A',"\xD\x11\7\x11\1\x11"
charset 'G',0 ; can't have an embedded 0 in a string
charset 'H',"\xB\4\x11\x11\9\xF\5\8\xC\x11\3\6\2\xA\x11\x10\x11\xE\x11"
charset '!',"\x11"
charset '.',"\x12"
; Text words
;off_35C62
SSMessage_TextFrames: offsetTable
offsetTableEntry.w byte_35C86 ; 0
offsetTableEntry.w byte_35C8A ; 2
offsetTableEntry.w byte_35C90 ; 4
offsetTableEntry.w byte_35C96 ; 6
offsetTableEntry.w byte_35C9A ; 8
offsetTableEntry.w byte_35CA1 ; $A
offsetTableEntry.w byte_35CA8 ; $C
offsetTableEntry.w byte_35CAD ; $E
offsetTableEntry.w byte_35CB3 ;$10
offsetTableEntry.w byte_35CB9 ;$12
offsetTableEntry.w byte_35CBF ;$14
offsetTableEntry.w byte_35CC4 ;$16
offsetTableEntry.w byte_35CC8 ;$18
offsetTableEntry.w byte_35CCE ;$1A
offsetTableEntry.w byte_35CD3 ;$1C
offsetTableEntry.w byte_35CD5 ;$1E
offsetTableEntry.w byte_35CD9 ;$20
offsetTableEntry.w byte_35CDB ;$22
byte_35C86: specialText "GET"
rev02even
byte_35C8A: specialText "RINGS"
rev02even
byte_35C90: specialText "COOL!"
rev02even
byte_35C96: specialText "NOT"
rev02even
byte_35C9A: specialText "ENOUGH"
rev02even
byte_35CA1: specialText "PLAYER"
rev02even
byte_35CA8: specialText "MOST"
rev02even
byte_35CAD: specialText "WINS!"
rev02even
byte_35CB3: specialText "SONIC"
rev02even
byte_35CB9: specialText "MILES"
rev02even
byte_35CBF: specialText "TIE!"
rev02even
byte_35CC4: specialText "WIN"
rev02even
byte_35CC8: specialText "TWICE"
rev02even
byte_35CCE: specialText "ALL!"
rev02even
byte_35CD3: specialText "!"
rev02even
byte_35CD5: specialText "..."
rev02even
byte_35CD9: dc.b $13,$FF ; VS
rev02even
byte_35CDB: specialText "TAILS"
even
charset ; revert character set
; ===========================================================================
;loc_35CE2
Obj5A_CreateRingReqMessage:
moveq #0,d0 ; GET
move.w #$54,d1 ; x
move.w #$6C,d2 ; y
bsr.w Obj5A_PrintWord
jsrto (SSStartNewAct).l, JmpTo_SSStartNewAct
move.w d1,d4 ; Binary coded decimal ring requirements
move.w d2,d5 ; Digit count - 1 (minumum 2 digits)
movea.w d2,a3 ; Copy of above, but in a3.
move.w #$80,d1 ; x position of least digit
cmpi.w #2,d2 ; Do we need hundreds digit?
beq.s + ; if yes, branch
subi_.w #8,d1 ; Otherwise, move digits to the left
+ move.w #$6C,d2 ; y position of digits
- move.w d4,d6 ; Copy BCD reuirements
lsr.w #4,d4 ; Next BCD digit
andi.w #$F,d6 ; Extract least digit
move.b d6,d0
swap d5
bsr.w Obj5A_PrintNumber
subi_.w #8,d1 ; Set position for next digit
swap d5
dbf d5,-
moveq #2,d0 ; RINGS!
lea (SSMessage_TextPhrases).l,a2
adda.w (a2,d0.w),a2
move.w #$6C,d2 ; y
move.w #$84,d1 ; x
cmpa.w #2,a3 ; Do we need space for hundreds digit?
bne.s + ; Branch if not
addi_.w #8,d1 ; Move digits to right
/ moveq #0,d0
move.b (a2)+,d0
bmi.s +
bsr.w Obj5A_PrintWord
bra.s -
; ===========================================================================
+
rts
; ===========================================================================
;loc_35D52
Obj5A_PrintCheckpointMessage:
move.w #$80,d3 ; x
bsr.w Obj5A_CreateCheckpointWingedHand
cmpi.w #1,(Player_mode).w
ble.s loc_35D6E
addi.w #palette_line_1,art_tile(a1)
addi.w #palette_line_1,art_tile(a2)
loc_35D6E:
move.w #$74,d1 ; x
move.w #$68,d2 ; y
lea (SSMessage_TextPhrases).l,a2
adda.w (a2,d0.w),a2 ; Fetch phrase
cmpi.b #4,d0 ; Is it 'COOL!'?
beq.s + ; Branch if yes
move.w #$5E,d1 ; Move text otherwise
/ moveq #0,d0
move.b (a2)+,d0
bmi.s ++ ; rts
cmpi.b #2,d0
bne.s +
move.w #$5E,d1 ; x
move.w #$7E,d2 ; y
+
bsr.w Obj5A_PrintWord
addi_.w #8,d1
bra.s -
; ===========================================================================
+
rts
; ===========================================================================
;loc_35DAA
Obj5A_PrintPhrase:
move.w d0,d3
subq.w #8,d3
lsr.w #1,d3
moveq #0,d1
move.b byte_35DD6(pc,d3.w),d1
move.w #$48,d2
lea (SSMessage_TextPhrases).l,a2
adda.w (a2,d0.w),a2
- moveq #0,d0
move.b (a2)+,d0
bmi.s + ; rts
bsr.w Obj5A_PrintWord
addi_.w #8,d1
bra.s -
; ===========================================================================
+
rts
; ===========================================================================
byte_35DD6:
dc.b $48
dc.b $44 ; 1
dc.b $58 ; 2
dc.b $58 ; 3
dc.b $74 ; 4
dc.b $3C ; 5
dc.b $58 ; 6
dc.b 0 ; 7
; Text phrases
;off_35DDE
SSMessage_TextPhrases: offsetTable
offsetTableEntry.w byte_35DF6 ; 0
offsetTableEntry.w byte_35DF7 ; 2
offsetTableEntry.w byte_35DFA ; 4
offsetTableEntry.w byte_35DFC ; 6
offsetTableEntry.w byte_35E01 ; 8
offsetTableEntry.w byte_35E05 ; $A
offsetTableEntry.w byte_35E09 ; $C
offsetTableEntry.w byte_35E0C ; $E
offsetTableEntry.w byte_35E0F ;$10
offsetTableEntry.w byte_35E11 ;$12
offsetTableEntry.w byte_35E16 ;$14
offsetTableEntry.w byte_35E19 ;$16
byte_35DF6: dc.b $FF ; (empty)
byte_35DF7: dc.b 2,$1C,$FF ; RINGS!
byte_35DFA: dc.b 4,$FF ; COOL!
byte_35DFC: dc.b 6, 8, 2,$1E,$FF ; NOT ENOUGH RINGS...
byte_35E01: dc.b $A,$20, $A,$FF ; PLAYER VS PLAYER
byte_35E05: dc.b $C, 2, $E,$FF ; MOST RINGS WINS
byte_35E09: dc.b $10, $E,$FF ; SONIC WINS
byte_35E0C: dc.b $12, $E,$FF ; MILES WINS
byte_35E0F: dc.b $14,$FF ; TIE!
byte_35E11: dc.b $16,$18,$16,$1A,$FF ; WIN TWICE WIN ALL!
byte_35E16: dc.b $22, $E,$FF ; TAILS WINS
byte_35E19: dc.b 2,$24,$26,$1C,$FF ; RINGS ?? ?? !
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj5A_MapUnc_35E1E: BINCLUDE "mappings/sprite/obj5A.bin"
; ===========================================================================
loc_35F76:
add.w d0,d0
move.w d0,d1
add.w d0,d0
add.w d1,d0
move.w word_35F92(pc,d0.w),(Normal_palette_line4+$16).w
move.w word_35F92+2(pc,d0.w),(Normal_palette_line4+$18).w
move.w word_35F92+4(pc,d0.w),(Normal_palette_line4+$1A).w
rts
; ===========================================================================
; Special Stage Chaos Emerald palette
word_35F92: BINCLUDE "art/palettes/SS Emerald.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 59 - Emerald from Special Stage
; ----------------------------------------------------------------------------
; Sprite_35FBC:
Obj59:
moveq #0,d0
move.b routine(a0),d0
move.w Obj59_Index(pc,d0.w),d1
jmp Obj59_Index(pc,d1.w)
; ===========================================================================
; off_35FCA:
Obj59_Index: offsetTable
offsetTableEntry.w Obj59_Init ; 0
offsetTableEntry.w loc_36022 ; 2
offsetTableEntry.w loc_3533A ; 4
offsetTableEntry.w loc_36160 ; 6
offsetTableEntry.w loc_36172 ; 8
; ===========================================================================
; loc_35FD4:
Obj59_Init:
st.b (SS_NoCheckpointMsg_flag).w
st.b (SS_Pause_Only_flag).w
subi_.w #1,objoff_2A(a0)
cmpi.w #-$3C,objoff_2A(a0)
beq.s +
rts
; ---------------------------------------------------------------------------
+
moveq #0,d0
move.b (Current_Special_Stage).w,d0
bsr.s loc_35F76
addq.b #2,routine(a0)
move.l #Obj59_MapUnc_3625A,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_SpecialEmerald,3,0),art_tile(a0)
move.b #4,render_flags(a0)
move.b #4,priority(a0)
move.w #$36,objoff_30(a0)
move.b #$40,angle(a0)
bsr.w loc_3529C
loc_36022:
bsr.w loc_360F0
bsr.w loc_3512A
bsr.w loc_3603C
lea (off_36228).l,a1
bsr.w loc_3539E
bra.w JmpTo44_DisplaySprite
; ===========================================================================
loc_3603C:
move.w d7,-(sp)
moveq #0,d2
moveq #0,d3
moveq #0,d4
moveq #0,d5
moveq #0,d6
moveq #0,d7
movea.l (SS_CurrentPerspective).w,a1
adda_.l #2,a1
move.w objoff_30(a0),d0
subq.w #1,d0
add.w d0,d0
move.w d0,d1
add.w d0,d0
add.w d1,d0
move.b (a1,d0.w),d2
move.b 1(a1,d0.w),d3
move.b 2(a1,d0.w),d4
move.b 3(a1,d0.w),d5
move.w d5,d6
swap d5
move.w d6,d5
move.w d4,d6
swap d4
move.w d6,d4
bpl.s loc_36088
cmpi.b #$48,d3
blo.s loc_36088
ext.w d3
loc_36088:
move.w d4,d6
add.w d4,d4
add.w d6,d4
lsr.w #2,d4
move.w d5,d6
add.w d5,d5
add.w d6,d5
lsr.w #2,d5
move.b angle(a0),d0
jsrto (CalcSine).l, JmpTo14_CalcSine
muls.w d4,d1
muls.w d5,d0
asr.l #8,d0
asr.l #8,d1
add.w d2,d1
add.w d3,d0
move.w d1,x_pos(a0)
move.w d0,y_pos(a0)
move.b d1,objoff_3A(a0)
move.b d0,objoff_3B(a0)
swap d4
swap d5
movea.l objoff_34(a0),a1 ; a1=object
move.b angle(a0),d0
jsrto (CalcSine).l, JmpTo14_CalcSine
move.w d4,d6
lsr.w #2,d6
add.w d6,d4
muls.w d4,d1
move.w d5,d6
asr.w #2,d6
add.w d6,d5
muls.w d5,d0
asr.l #8,d0
asr.l #8,d1
add.w d2,d1
add.w d3,d0
move.w d1,x_pos(a1)
move.w d0,y_pos(a1)
move.w (sp)+,d7
rts
; ===========================================================================
loc_360F0:
cmpi.b #3,anim(a0)
blo.s return_36140
tst.b objoff_3E(a0)
bne.s loc_3610C
move.w #MusID_FadeOut,d0
jsr (PlayMusic).l
st objoff_3E(a0)
loc_3610C:
cmpi.b #6,anim(a0)
blo.s return_36140
move.w (Ring_count).w,d2
add.w (Ring_count_2P).w,d2
cmp.w (SS_Ring_Requirement).w,d2
blt.s loc_36142
cmpi.b #9,anim(a0)
blo.s return_36140
move.w #$63,objoff_2A(a0)
move.b #8,routine(a0)
move.w #MusID_Emerald,d0
jsr (PlayMusic).l
return_36140:
rts
; ===========================================================================
loc_36142:
move.l #0,(SS_New_Speed_Factor).w
move.b #6,routine(a0)
move.w #$4F,objoff_2A(a0)
move.w #6,d0
bsr.w loc_35D6E
rts
; ===========================================================================
loc_36160:
subi_.w #1,objoff_2A(a0)
bpl.w JmpTo44_DisplaySprite
st.b (SS_Check_Rings_flag).w
bra.w SSClearObjs
; ===========================================================================
loc_36172:
subi_.w #1,objoff_2A(a0)
bpl.s loc_361A4
moveq #0,d0
move.b (Current_Special_Stage).w,d0
lea (Got_Emeralds_array).w,a0
st (a0,d0.w)
st (Got_Emerald).w
addi_.b #1,(Current_Special_Stage).w
addi_.b #1,(Emerald_count).w
st.b (SS_Check_Rings_flag).w
bsr.w SSClearObjs
move.l (sp)+,d0
rts
; ===========================================================================
loc_361A4:
addi_.b #1,objoff_3C(a0)
moveq #0,d0
moveq #0,d2
move.b objoff_3B(a0),d2
move.b objoff_3C(a0),d0
lsr.w #2,d0
andi.w #3,d0
add.b byte_361C8(pc,d0.w),d2
move.w d2,y_pos(a0)
bra.w JmpTo44_DisplaySprite
; ===========================================================================
byte_361C8:
dc.b $FF
dc.b 0 ; 1
dc.b 1 ; 2
dc.b 0 ; 3
; ===========================================================================
;loc_361CC
SSClearObjs:
movea.l #(SS_Object_RAM&$FFFFFF),a1
move.w #(SS_Object_RAM_End-SS_Object_RAM)/$10-1,d0
moveq #0,d1
loc_361D8:
rept $10/4
move.l d1,(a1)+
endm
dbf d0,loc_361D8
.c := ((SS_Object_RAM_End-SS_Object_RAM)#$10)/4
if .c
rept .c
move.l d1,(a1)+
endm
endif
.c := ((SS_Object_RAM_End-SS_Object_RAM)#$10)&2
if .c
rept .c
move.w d1,(a1)+
endm
endif
; Bug: The '+4' shouldn't be here; clearRAM accidentally clears an additional 4 bytes
clearRAM SS_Sprite_Table,SS_Sprite_Table_End+4
rts
; ===========================================================================
; unused/dead code ; a0=object
cmpi.b #$B,(SSTrack_drawing_index).w
blo.s loc_36208
subi.l #$4445,objoff_30(a0)
bra.s loc_36210
; ---------------------------------------------------------------------------
loc_36208:
subi.l #$4444,objoff_30(a0)
loc_36210:
move.w objoff_30(a0),d0
cmpi.w #$1D,d0
ble.s +
moveq #$1E,d0
+
lea_ byte_35180,a1
move.b (a1,d0.w),anim(a0)
rts
; end of unused code
; ===========================================================================
; animation script for object 59
off_36228: offsetTable
offsetTableEntry.w byte_3623C ; 0
offsetTableEntry.w byte_3623F ; 1
offsetTableEntry.w byte_36242 ; 2
offsetTableEntry.w byte_36245 ; 3
offsetTableEntry.w byte_36248 ; 4
offsetTableEntry.w byte_3624B ; 5
offsetTableEntry.w byte_3624E ; 6
offsetTableEntry.w byte_36251 ; 7
offsetTableEntry.w byte_36254 ; 8
offsetTableEntry.w byte_36257 ; 9
byte_3623C:
dc.b $B, 0,$FF
rev02even
byte_3623F:
dc.b $B, 1,$FF
rev02even
byte_36242:
dc.b $B, 2,$FF
rev02even
byte_36245:
dc.b $B, 3,$FF
rev02even
byte_36248:
dc.b $B, 4,$FF
rev02even
byte_3624B:
dc.b $B, 5,$FF
rev02even
byte_3624E:
dc.b $B, 6,$FF
rev02even
byte_36251:
dc.b $B, 7,$FF
rev02even
byte_36254:
dc.b $B, 8,$FF
rev02even
byte_36257:
dc.b $B, 9,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj59_MapUnc_3625A: BINCLUDE "mappings/sprite/obj59.bin"
; animation script:
; off_362D2:
Ani_obj5B_obj60:offsetTable
offsetTableEntry.w byte_362E8 ; 0
offsetTableEntry.w byte_362EE ; 1
offsetTableEntry.w byte_362F4 ; 2
offsetTableEntry.w byte_362FA ; 3
offsetTableEntry.w byte_36300 ; 4
offsetTableEntry.w byte_36306 ; 5
offsetTableEntry.w byte_3630C ; 6
offsetTableEntry.w byte_36312 ; 7
offsetTableEntry.w byte_36318 ; 8
offsetTableEntry.w byte_3631E ; 9
offsetTableEntry.w byte_36324 ; $A
byte_362E8: dc.b 5, 0, $A,$14, $A,$FF
rev02even
byte_362EE: dc.b 5, 1, $B,$15, $B,$FF
rev02even
byte_362F4: dc.b 5, 2, $C,$16, $C,$FF
rev02even
byte_362FA: dc.b 5, 3, $D,$17, $D,$FF
rev02even
byte_36300: dc.b 5, 4, $E,$18, $E,$FF
rev02even
byte_36306: dc.b 5, 5, $F,$19, $F,$FF
rev02even
byte_3630C: dc.b 5, 6,$10,$1A,$10,$FF
rev02even
byte_36312: dc.b 5, 7,$11,$1B,$11,$FF
rev02even
byte_36318: dc.b 5, 8,$12,$1C,$12,$FF
rev02even
byte_3631E: dc.b 5, 9,$13,$1D,$13,$FF
rev02even
byte_36324: dc.b 1,$1E,$1F,$20,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj5A_Obj5B_Obj60_MapUnc_3632A: BINCLUDE "mappings/sprite/obj5A_5B_60.bin"
; animation script:
; off_364CE:
Ani_obj61: offsetTable
offsetTableEntry.w byte_364E4 ; 0
offsetTableEntry.w byte_364E7 ; 1
offsetTableEntry.w byte_364EA ; 2
offsetTableEntry.w byte_364ED ; 3
offsetTableEntry.w byte_364F0 ; 4
offsetTableEntry.w byte_364F3 ; 5
offsetTableEntry.w byte_364F6 ; 6
offsetTableEntry.w byte_364F9 ; 7
offsetTableEntry.w byte_364FC ; 8
offsetTableEntry.w byte_364FF ; 9
offsetTableEntry.w byte_36502 ; $A
byte_364E4: dc.b $B, 0,$FF
rev02even
byte_364E7: dc.b $B, 1,$FF
rev02even
byte_364EA: dc.b $B, 2,$FF
rev02even
byte_364ED: dc.b $B, 3,$FF
rev02even
byte_364F0: dc.b $B, 4,$FF
rev02even
byte_364F3: dc.b $B, 5,$FF
rev02even
byte_364F6: dc.b $B, 6,$FF
rev02even
byte_364F9: dc.b $B, 7,$FF
rev02even
byte_364FC: dc.b $B, 8,$FF
rev02even
byte_364FF: dc.b $B, 9,$FF
rev02even
byte_36502: dc.b 2, $A, $B, $C,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj61_MapUnc_36508: BINCLUDE "mappings/sprite/obj61.bin"
; ===========================================================================
JmpTo44_DisplaySprite
jmp (DisplaySprite).l
; ===========================================================================
if ~~removeJmpTos
JmpTo63_DeleteObject
jmp (DeleteObject).l
JmpTo24_AnimateSprite
jmp (AnimateSprite).l
JmpTo_SSStartNewAct
jmp (SSStartNewAct).l
JmpTo_CalcAngle
jmp (CalcAngle).l
JmpTo14_CalcSine
jmp (CalcSine).l
JmpTo7_ObjectMoveAndFall
jmp (ObjectMoveAndFall).l
JmpTo_SSSingleObjLoad2
jmp (SSSingleObjLoad2).l
JmpTo2_SSSingleObjLoad
jmp (SSSingleObjLoad).l
align 4
endif
; ===========================================================================
; ---------------------------------------------------------------------------
; LoadSubObject
; loads information from a sub-object into this object a0
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_365F4:
LoadSubObject:
moveq #0,d0
move.b subtype(a0),d0
; loc_365FA:
LoadSubObject_Part2:
move.w SubObjData_Index(pc,d0.w),d0
lea SubObjData_Index(pc,d0.w),a1
; loc_36602:
LoadSubObject_Part3:
move.l (a1)+,mappings(a0)
move.w (a1)+,art_tile(a0)
jsr (Adjust2PArtPointer).l
move.b (a1)+,d0
or.b d0,render_flags(a0)
move.b (a1)+,priority(a0)
move.b (a1)+,width_pixels(a0)
move.b (a1),collision_flags(a0)
addq.b #2,routine(a0)
rts
; ===========================================================================
; table that maps from the subtype ID to which address to load the data from
; the format of the data there is
; dc.l Pointer_To_Sprite_Mappings
; dc.w VRAM_Location
; dc.b render_flags, priority, width_pixels, collision_flags
;
; for whatever reason, only Obj8C and later have entries in this table
; off_36628:
SubObjData_Index: offsetTable
offsetTableEntry.w Obj8C_SubObjData ; $0
offsetTableEntry.w Obj8D_SubObjData ; $2
offsetTableEntry.w Obj90_SubObjData ; $4
offsetTableEntry.w Obj90_SubObjData2 ; $6
offsetTableEntry.w Obj91_SubObjData ; $8
offsetTableEntry.w Obj92_SubObjData ; $A
offsetTableEntry.w Invalid_SubObjData ; $C
offsetTableEntry.w Obj94_SubObjData ; $E
offsetTableEntry.w Obj94_SubObjData2 ; $10
offsetTableEntry.w Obj99_SubObjData2 ; $12
offsetTableEntry.w Obj99_SubObjData ; $14
offsetTableEntry.w Obj9A_SubObjData ; $16
offsetTableEntry.w Obj9B_SubObjData ; $18
offsetTableEntry.w Obj9C_SubObjData ; $1A
offsetTableEntry.w Obj9A_SubObjData2 ; $1C
offsetTableEntry.w Obj9D_SubObjData ; $1E
offsetTableEntry.w Obj9D_SubObjData2 ; $20
offsetTableEntry.w Obj9E_SubObjData ; $22
offsetTableEntry.w Obj9F_SubObjData ; $24
offsetTableEntry.w ObjA0_SubObjData ; $26
offsetTableEntry.w ObjA1_SubObjData ; $28
offsetTableEntry.w ObjA2_SubObjData ; $2A
offsetTableEntry.w ObjA3_SubObjData ; $2C
offsetTableEntry.w ObjA4_SubObjData ; $2E
offsetTableEntry.w ObjA4_SubObjData2 ; $30
offsetTableEntry.w ObjA5_SubObjData ; $32
offsetTableEntry.w ObjA6_SubObjData ; $34
offsetTableEntry.w ObjA7_SubObjData ; $36
offsetTableEntry.w ObjA7_SubObjData2 ; $38
offsetTableEntry.w ObjA8_SubObjData ; $3A
offsetTableEntry.w ObjA8_SubObjData2 ; $3C
offsetTableEntry.w ObjA7_SubObjData3 ; $3E
offsetTableEntry.w ObjAC_SubObjData ; $40
offsetTableEntry.w ObjAD_SubObjData ; $42
offsetTableEntry.w ObjAD_SubObjData2 ; $44
offsetTableEntry.w ObjAD_SubObjData3 ; $46
offsetTableEntry.w ObjAF_SubObjData2 ; $48
offsetTableEntry.w ObjAF_SubObjData ; $4A
offsetTableEntry.w ObjB0_SubObjData ; $4C
offsetTableEntry.w ObjB1_SubObjData ; $4E
offsetTableEntry.w ObjB2_SubObjData ; $50
offsetTableEntry.w ObjB2_SubObjData ; $52
offsetTableEntry.w ObjB2_SubObjData ; $54
offsetTableEntry.w ObjBC_SubObjData2 ; $56
offsetTableEntry.w ObjBC_SubObjData2 ; $58
offsetTableEntry.w ObjB3_SubObjData ; $5A
offsetTableEntry.w ObjB2_SubObjData2 ; $5C
offsetTableEntry.w ObjB3_SubObjData ; $5E
offsetTableEntry.w ObjB3_SubObjData ; $60
offsetTableEntry.w ObjB3_SubObjData ; $62
offsetTableEntry.w ObjB4_SubObjData ; $64
offsetTableEntry.w ObjB5_SubObjData ; $66
offsetTableEntry.w ObjB5_SubObjData ; $68
offsetTableEntry.w ObjB6_SubObjData ; $6A
offsetTableEntry.w ObjB6_SubObjData ; $6C
offsetTableEntry.w ObjB6_SubObjData ; $6E
offsetTableEntry.w ObjB6_SubObjData ; $70
offsetTableEntry.w ObjB7_SubObjData ; $72
offsetTableEntry.w ObjB8_SubObjData ; $74
offsetTableEntry.w ObjB9_SubObjData ; $76
offsetTableEntry.w ObjBA_SubObjData ; $78
offsetTableEntry.w ObjBB_SubObjData ; $7A
offsetTableEntry.w ObjBC_SubObjData2 ; $7C
offsetTableEntry.w ObjBD_SubObjData ; $7E
offsetTableEntry.w ObjBD_SubObjData ; $80
offsetTableEntry.w ObjBE_SubObjData ; $82
offsetTableEntry.w ObjBE_SubObjData2 ; $84
offsetTableEntry.w ObjC0_SubObjData ; $86
offsetTableEntry.w ObjC1_SubObjData ; $88
offsetTableEntry.w ObjC2_SubObjData ; $8A
offsetTableEntry.w Invalid_SubObjData2 ; $8C
offsetTableEntry.w ObjB8_SubObjData2 ; $8E
offsetTableEntry.w ObjC3_SubObjData ; $90
offsetTableEntry.w ObjC5_SubObjData ; $92
offsetTableEntry.w ObjC5_SubObjData2 ; $94
offsetTableEntry.w ObjC5_SubObjData3 ; $96
offsetTableEntry.w ObjC5_SubObjData3 ; $98
offsetTableEntry.w ObjC5_SubObjData3 ; $9A
offsetTableEntry.w ObjC5_SubObjData3 ; $9C
offsetTableEntry.w ObjC5_SubObjData3 ; $9E
offsetTableEntry.w ObjC6_SubObjData2 ; $A0
offsetTableEntry.w ObjC5_SubObjData4 ; $A2
offsetTableEntry.w ObjAF_SubObjData3 ; $A4
offsetTableEntry.w ObjC6_SubObjData3 ; $A6
offsetTableEntry.w ObjC6_SubObjData4 ; $A8
offsetTableEntry.w ObjC6_SubObjData ; $AA
offsetTableEntry.w ObjC8_SubObjData ; $AC
; ===========================================================================
; ---------------------------------------------------------------------------
; Get Orientation To Player
; Returns the horizontal and vertical distances of the closest player object.
;
; input variables:
; a0 = object
;
; returns:
; a1 = address of closest player character
; d0 = 0 if player is left from object, 2 if right
; d1 = 0 if player is above object, 2 if below
; d2 = closest character's horizontal distance to object
; d3 = closest character's vertical distance to object
;
; writes:
; d0, d1, d2, d3, d4, d5
; a1
; a2 = sidekick
; ---------------------------------------------------------------------------
;loc_366D6:
Obj_GetOrientationToPlayer:
moveq #0,d0
moveq #0,d1
lea (MainCharacter).w,a1 ; a1=character
move.w x_pos(a0),d2
sub.w x_pos(a1),d2
mvabs.w d2,d4 ; absolute horizontal distance to main character
lea (Sidekick).w,a2 ; a2=character
move.w x_pos(a0),d3
sub.w x_pos(a2),d3
mvabs.w d3,d5 ; absolute horizontal distance to sidekick
cmp.w d5,d4 ; get shorter distance
bls.s + ; branch, if main character is closer
; if sidekick is closer
movea.l a2,a1
move.w d3,d2
+
tst.w d2 ; is player to enemy's left?
bpl.s + ; if not, branch
addq.w #2,d0
+
move.w y_pos(a0),d3
sub.w y_pos(a1),d3 ; vertical distance to closest character
bhs.s + ; branch, if enemy is under
addq.w #2,d1
+
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Cap Object Speed
; Prevents an object from going over a specified speed value.
;
; input variables:
; d0 = max x velocity
; d1 = max y velocity
;
; a0 = object
;
; writes:
; d0, d1, d2, d3
; ---------------------------------------------------------------------------
; loc_3671A:
Obj_CapSpeed:
move.w x_vel(a0),d2
bpl.s + ; branch, if object is moving right
; going left
neg.w d0 ; set opposite direction
cmp.w d0,d2 ; is object's current x velocity lower than max?
bhs.s ++ ; if yes, branch
move.w d0,d2 ; else, cap speed
bra.w ++
; ===========================================================================
+ ; going right
cmp.w d0,d2 ; is object's current x velocity lower than max?
bls.s + ; if yes, branch
move.w d0,d2 ; else, cap speed
+
move.w y_vel(a0),d3
bpl.s + ; branch, if object is moving down
; going up
neg.w d1 ; set opposite direction
cmp.w d1,d3 ; is object's current y velocity lower than max?
bhs.s ++ ; if yes, branch
move.w d1,d3 ; else, cap speed
bra.w ++
; ===========================================================================
+ ; going down
cmp.w d1,d3 ; is object's current y velocity lower than max?
bls.s + ; if yes, branch
move.w d1,d3 ; else, cap speed
+ ; update speed
move.w d2,x_vel(a0)
move.w d3,y_vel(a0)
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Movement Stop
; Stops an object's movement.
;
; input variables:
; a0 = object
;
; writes:
; d0 = 0
; ---------------------------------------------------------------------------
;loc_36754:
Obj_MoveStop:
moveq #0,d0
move.w d0,x_vel(a0)
move.w d0,y_vel(a0)
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Align Child XY
; Moves a referenced object to the position of the current object with
; variable x and y offset.
;
; input variables:
; d0 = x offset
; d1 = y offset
;
; a0 = parent object
; a1 = child object
;
; writes:
; d2 = new x position
; d3 = new y position
; ---------------------------------------------------------------------------
;loc_36760:
Obj_AlignChildXY:
move.w x_pos(a0),d2
add.w d0,d2
move.w d2,x_pos(a1)
move.w y_pos(a0),d3
add.w d1,d3
move.w d3,y_pos(a1)
rts
; ===========================================================================
loc_36776:
move.w (Tornado_Velocity_X).w,d0
add.w d0,x_pos(a0)
move.w (Tornado_Velocity_Y).w,d0
add.w d0,y_pos(a0)
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Delete If Behind Screen
; deletes an object if it scrolls off the left side of the screen
;
; input variables:
; a0 = object
;
; writes:
; d0
; ---------------------------------------------------------------------------
;loc_36788:
Obj_DeleteBehindScreen:
tst.w (Two_player_mode).w
beq.s +
jmp (DisplaySprite).l
+
; when not in two player mode
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
bmi.w JmpTo64_DeleteObject
jmp (DisplaySprite).l
; ===========================================================================
loc_367AA:
move.b render_flags(a0),d0
if gameRevision<2
andi.b #$FC,d0
move.b status(a0),d2
andi.b #$FC,d2
move.b render_flags(a1),d1
andi.b #3,d1
else
; now causes a bug where some sprites are displayed backwards (Silver Sonic's sparks and Grabber's legs)
andi.b #$FD,d0
move.b status(a0),d2
andi.b #$FD,d2
move.b render_flags(a1),d1
andi.b #2,d1
endif
or.b d1,d0
or.b d1,d2
move.b d0,render_flags(a0)
move.b d2,status(a0)
rts
; ===========================================================================
;loc_367D0:
LoadChildObject:
jsr (SingleObjLoad2).l
bne.s + ; rts
move.w (a2)+,d0
move.w a1,(a0,d0.w) ; store pointer to child in parent's SST
_move.b (a2)+,id(a1) ; load obj
move.b (a2)+,subtype(a1)
move.w a0,objoff_2C(a1) ; store pointer to parent in child's SST
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
+
rts
; ===========================================================================
; unused/dead code ; a0=object
bsr.w Obj_GetOrientationToPlayer
bclr #0,render_flags(a0)
bclr #0,status(a0)
tst.w d0
beq.s return_36818
bset #0,render_flags(a0)
bset #0,status(a0)
return_36818:
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Create Projectiles
; Creates a specified number of generic moving projectiles.
;
; input variables:
; d2 = subtype, used for object initialization (refer to LoadSubObject)
; d6 = number of projectiles to create -1
;
; a2 = projectile stat list
; format:
; dc.b x_offset, y_offset, x_vel, y_vel, mapping_frame, render_flags
;
; writes:
; d0
; d1 = index in list
; d6 = num objects
;
; a1 = addres of new projectile
; a3 = movement type (ObjectMove)
; ---------------------------------------------------------------------------
;loc_3681A:
Obj_CreateProjectiles:
moveq #0,d1
; loop creates d6+1 projectiles
-
jsr (SingleObjLoad2).l
bne.s return_3686E
_move.b #ObjID_Projectile,id(a1) ; load obj98
move.b d2,subtype(a1) ; used for object initialization
move.w x_pos(a0),x_pos(a1) ; align objects
move.w y_pos(a0),y_pos(a1)
lea (ObjectMove).l,a3 ; set movement type
move.l a3,objoff_2A(a1)
lea (a2,d1.w),a3 ; get address in list
move.b (a3)+,d0 ; get x offset
ext.w d0
add.w d0,x_pos(a1)
move.b (a3)+,d0 ; get y offset
ext.w d0
add.w d0,y_pos(a1)
move.b (a3)+,x_vel(a1) ; set movement values
move.b (a3)+,y_vel(a1)
move.b (a3)+,mapping_frame(a1) ; set map frame
move.b (a3)+,render_flags(a1) ; set render flags
addq.w #6,d1
dbf d6,-
return_3686E:
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to animate a sprite using an animation script
; Works like AnimateSprite, except for:
; * this function does not change render flags to match orientation given by
; the status byte;
; * the function returns 0 on d0 if it changed the mapping frame, or 1 if an
; end-of-animation flag was found ($FC to $FF);
; * it is only used by Mecha Sonic;
; * some of the end-of-animation flags work differently.
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_36870:
AnimateSprite_Checked:
moveq #0,d0
move.b anim(a0),d0 ; move animation number to d0
cmp.b next_anim(a0),d0 ; is animation set to change?
beq.s AnimChk_Run ; if not, branch
move.b d0,next_anim(a0) ; set next anim to current current
move.b #0,anim_frame(a0) ; reset animation
move.b #0,anim_frame_duration(a0) ; reset frame duration
AnimChk_Run:
subq.b #1,anim_frame_duration(a0) ; subtract 1 from frame duration
bpl.s AnimChk_Wait ; if time remains, branch
add.w d0,d0
adda.w (a1,d0.w),a1 ; calculate address of appropriate animation script
move.b (a1),anim_frame_duration(a0) ; load frame duration
moveq #0,d1
move.b anim_frame(a0),d1 ; load current frame number
move.b 1(a1,d1.w),d0 ; read sprite number from script
bmi.s AnimChk_End_FF ; if animation is complete, branch
;loc_368A8
AnimChk_Next:
move.b d0,mapping_frame(a0) ; load sprite number
addq.b #1,anim_frame(a0) ; next frame number
;loc_368B0
AnimChk_Wait:
moveq #0,d0 ; Return 0
rts
; ---------------------------------------------------------------------------
;loc_368B4
AnimChk_End_FF:
addq.b #1,d0 ; is the end flag = $FF ?
bne.s AnimChk_End_FE ; if not, branch
move.b #0,anim_frame(a0) ; restart the animation
move.b 1(a1),d0 ; read sprite number
bsr.s AnimChk_Next
moveq #1,d0 ; Return 1
rts
; ---------------------------------------------------------------------------
;loc_368C8
AnimChk_End_FE:
addq.b #1,d0 ; is the end flag = $FE ?
bne.s AnimChk_End_FD ; if not, branch
addq.b #2,routine(a0) ; jump to next routine
move.b #0,anim_frame_duration(a0)
addq.b #1,anim_frame(a0)
moveq #1,d0 ; Return 1
rts
; ---------------------------------------------------------------------------
;loc_368DE
AnimChk_End_FD:
addq.b #1,d0 ; is the end flag = $FD ?
bne.s AnimChk_End_FC ; if not, branch
addq.b #2,routine_secondary(a0) ; jump to next routine
moveq #1,d0 ; Return 1
rts
; ---------------------------------------------------------------------------
;loc_368EA
AnimChk_End_FC:
addq.b #1,d0 ; is the end flag = $FC ?
bne.s AnimChk_End ; if not, branch
move.b #1,anim_frame_duration(a0) ; Force frame duration to 1
moveq #1,d0 ; Return 1
AnimChk_End:
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Delete If Off-Screen
; deletes an object if it is too far away from the screen
;
; input variables:
; a0 = object
;
; writes:
; d0
; ---------------------------------------------------------------------------
;loc_368F8:
Obj_DeleteOffScreen:
tst.w (Two_player_mode).w
beq.s +
jmp (DisplaySprite).l
+
; when not in two player mode
move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w JmpTo64_DeleteObject
jmp (DisplaySprite).l
; ===========================================================================
if removeJmpTos
JmpTo65_DeleteObject
endif
JmpTo64_DeleteObject
jmp (DeleteObject).l
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 8C - Whisp (blowfly badnik) from ARZ
; ----------------------------------------------------------------------------
; Sprite_36924:
Obj8C:
moveq #0,d0
move.b routine(a0),d0
move.w Obj8C_Index(pc,d0.w),d1
jmp Obj8C_Index(pc,d1.w)
; ===========================================================================
; off_36932: Obj8C_States:
Obj8C_Index: offsetTable
offsetTableEntry.w Obj8C_Init ; 0
offsetTableEntry.w loc_3694E ; 1
offsetTableEntry.w loc_369A8 ; 2
offsetTableEntry.w loc_36958 ; 3
offsetTableEntry.w loc_36A26 ; 4
; ===========================================================================
; loc_3693C:
Obj8C_Init:
bsr.w LoadSubObject
move.b #$10,objoff_2A(a0)
move.b #4,objoff_2B(a0)
rts
; ===========================================================================
loc_3694E:
tst.b render_flags(a0)
bmi.s loc_36970
bra.w Obj8C_Animate
; ===========================================================================
loc_36958:
subq.b #1,objoff_2A(a0)
bmi.s loc_36970
; loc_3695E:
Obj8C_Animate:
lea (Ani_obj8C).l,a1
jsr (AnimateSprite).l
jmp (MarkObjGone).l
; ===========================================================================
loc_36970:
subq.b #1,objoff_2B(a0)
bpl.s loc_36996
move.b #8,routine(a0)
bclr #0,status(a0)
clr.w y_vel(a0)
move.w #-$200,x_vel(a0)
move.w #-$200,y_vel(a0)
bra.w loc_36A26
; ===========================================================================
loc_36996:
move.b #4,routine(a0)
move.w #-$100,y_vel(a0)
move.b #$60,objoff_2A(a0)
loc_369A8:
subq.b #1,objoff_2A(a0)
bmi.s loc_369F8
bsr.w Obj_GetOrientationToPlayer
bclr #0,status(a0)
tst.w d0
beq.s loc_369C2
bset #0,status(a0)
loc_369C2:
move.w word_369F4(pc,d0.w),d2
add.w d2,x_vel(a0)
move.w word_369F4(pc,d1.w),d2
add.w d2,y_vel(a0)
move.w #$200,d0
move.w d0,d1
bsr.w Obj_CapSpeed
jsr (ObjectMove).l
lea (Ani_obj8C).l,a1
jsr (AnimateSprite).l
jmp (MarkObjGone).l
; ===========================================================================
word_369F4:
dc.w -$10
dc.w $10
; ===========================================================================
loc_369F8:
move.b #6,routine(a0)
jsr (RandomNumber).l
move.l (RNG_seed).w,d0
andi.b #$1F,d0
move.b d0,objoff_2A(a0)
bsr.w Obj_MoveStop
lea (Ani_obj8C).l,a1
jsr (AnimateSprite).l
jmp (MarkObjGone).l
; ===========================================================================
loc_36A26:
jsr (ObjectMove).l
lea (Ani_obj8C).l,a1
jsr (AnimateSprite).l
jmp (MarkObjGone).l
; ===========================================================================
; off_36A3E:
Obj8C_SubObjData:
subObjData Obj8C_MapUnc_36A4E,make_art_tile(ArtTile_ArtNem_Whisp,1,1),4,4,$C,$B
; animation script
; off_36A48:
Ani_obj8C: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 1, 0, 1,$FF
even
; ------------------------------------------------------------------------
; sprite mappings
; ------------------------------------------------------------------------
Obj8C_MapUnc_36A4E: BINCLUDE "mappings/sprite/obj8C.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 8D - Grounder in wall, from ARZ
; ----------------------------------------------------------------------------
; Sprite_36A76:
Obj8D:
moveq #0,d0
move.b routine(a0),d0
move.w Obj8D_Index(pc,d0.w),d1
jmp Obj8D_Index(pc,d1.w)
; ===========================================================================
; off_36A84:
Obj8D_Index: offsetTable
offsetTableEntry.w Obj8D_Init ; 0
offsetTableEntry.w loc_36ADC ; 2
offsetTableEntry.w Obj8D_Animate ; 4
offsetTableEntry.w loc_36B0E ; 6
offsetTableEntry.w loc_36B34 ; 8
offsetTableEntry.w loc_36B6A ; $A
; ===========================================================================
; loc_36A90:
Obj8D_Init:
bsr.w LoadSubObject
bclr #1,render_flags(a0)
beq.s +
bclr #1,status(a0)
andi.w #drawing_mask,art_tile(a0)
+
move.b #$14,y_radius(a0)
move.b #$10,x_radius(a0)
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.s +
add.w d1,y_pos(a0)
move.w #0,y_vel(a0)
+
_move.b id(a0),d0
subi.b #ObjID_GrounderInWall,d0
beq.w loc_36C64
move.b #6,routine(a0)
rts
; ===========================================================================
loc_36ADC:
bsr.w Obj_GetOrientationToPlayer
abs.w d2
cmpi.w #$60,d2
bls.s +
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
+
addq.b #2,routine(a0)
st objoff_2B(a0)
bsr.w loc_36C2C
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_36B00:
Obj8D_Animate:
lea (Ani_obj8D_b).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_36B0E:
addq.b #2,routine(a0)
bsr.w Obj_GetOrientationToPlayer
move.w Obj8D_Directions(pc,d0.w),x_vel(a0)
bclr #0,status(a0)
tst.w d0
beq.s +
bset #0,status(a0)
+
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; word_36B30:
Obj8D_Directions:
dc.w -$100
dc.w $100 ; 1
; ===========================================================================
loc_36B34:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jsr (ObjCheckFloorDist).l
cmpi.w #-1,d1
blt.s loc_36B5C
cmpi.w #$C,d1
bge.s loc_36B5C
add.w d1,y_pos(a0)
lea (Ani_obj8D_a).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_36B5C:
addq.b #2,routine(a0)
move.b #$3B,objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_36B6A:
subq.b #1,objoff_2A(a0)
bmi.s loc_36B74
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_36B74:
move.b #8,routine(a0)
neg.w x_vel(a0)
bchg #0,status(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 8F - Wall behind which Grounder hides, from ARZ
; ----------------------------------------------------------------------------
; Sprite_36B88:
Obj8F:
moveq #0,d0
move.b routine(a0),d0
move.w Obj8F_Index(pc,d0.w),d1
jmp Obj8F_Index(pc,d1.w)
; ===========================================================================
; off_36B96:
Obj8F_Index: offsetTable
offsetTableEntry.w Obj8F_Init ; 0
offsetTableEntry.w loc_36BA6 ; 2
offsetTableEntry.w Obj8F_Move ; 4
; ===========================================================================
; loc_36B9C:
Obj8F_Init:
bsr.w LoadSubObject
clr.w art_tile(a0)
rts
; ===========================================================================
loc_36BA6:
movea.w objoff_2C(a0),a1 ; a1=object
tst.b objoff_2B(a1)
bne.s +
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
+
addq.b #2,routine(a0)
move.w objoff_2E(a0),d0
move.b Obj8F_Directions(pc,d0.w),x_vel(a0)
move.b Obj8F_Directions+1(pc,d0.w),y_vel(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; byte_36BCC:
Obj8F_Directions:
dc.b 1,-2 ; 0
dc.b 1,-1 ; 2
dc.b -1,-2 ; 4
dc.b -1,-1 ; 6
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 90 - Rocks thrown by Grounder behind wall, from ARZ
; ----------------------------------------------------------------------------
; Sprite_36BD4:
Obj90:
moveq #0,d0
move.b routine(a0),d0
move.w Obj90_Index(pc,d0.w),d1
jmp Obj90_Index(pc,d1.w)
; ===========================================================================
; off_36BE2:
Obj90_Index: offsetTable
offsetTableEntry.w Obj90_Init ; 0
offsetTableEntry.w Obj90_Move ; 2
; ===========================================================================
; loc_36BE6:
Obj90_Init:
bsr.w LoadSubObject
move.w #make_art_tile(ArtTile_ArtNem_Grounder,2,0),art_tile(a0)
move.w objoff_2E(a0),d0
move.b Obj90_Directions(pc,d0.w),x_vel(a0)
move.b Obj90_Directions+1(pc,d0.w),y_vel(a0)
lsr.w #1,d0
move.b Obj90_Frames(pc,d0.w),mapping_frame(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; byte_36C0C:
Obj90_Frames:
dc.b 0
dc.b 2 ; 1
dc.b 0 ; 2
dc.b 1 ; 3
dc.b 0 ; 4
dc.b 0 ; 5
; ===========================================================================
; byte_36C12:
Obj90_Directions:
dc.b -1, -4
dc.b 4, -3 ; 2
dc.b 2, 0 ; 4
dc.b -3, -1 ; 6
dc.b -3, -3 ; 8
; ===========================================================================
; loc_36C1C:
Obj8F_Move:
Obj90_Move:
tst.b render_flags(a0)
bpl.w JmpTo65_DeleteObject
jsrto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_36C2C:
moveq #0,d1
moveq #4,d6
- jsrto (SingleObjLoad).l, JmpTo19_SingleObjLoad
bne.s + ; rts
bsr.w loc_36C40
dbf d6,-
+
rts
; ===========================================================================
loc_36C40:
_move.b #ObjID_GrounderRocks,id(a1) ; load obj90
move.b #6,subtype(a1) ; <== Obj90_SubObjData2
move.w a0,objoff_2C(a1)
move.w d1,objoff_2E(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
addq.w #2,d1
rts
; ===========================================================================
loc_36C64:
moveq #0,d1
moveq #3,d6
- jsrto (SingleObjLoad).l, JmpTo19_SingleObjLoad
bne.s + ; rts
bsr.w loc_36C78
dbf d6,-
+
rts
; ===========================================================================
loc_36C78:
_move.b #ObjID_GrounderWall,id(a1) ; load obj8F
move.b #4,subtype(a1) ; <== Obj90_SubObjData
move.w a0,objoff_2C(a1)
move.w d1,objoff_2E(a1)
move.l x_pos(a0),d0
swap d0
moveq #0,d2
move.b byte_36CBC(pc,d1.w),d2
ext.w d2
add.w d2,d0
swap d0
move.l d0,x_pos(a1)
move.l y_pos(a0),d0
swap d0
moveq #0,d2
move.b byte_36CBC+1(pc,d1.w),d2
ext.w d2
add.w d2,d0
swap d0
move.l d0,y_pos(a1)
addq.w #2,d1
rts
; ===========================================================================
byte_36CBC:
dc.b 0,-$14
dc.b $10, -4 ; 2
dc.b 0, $C ; 4
dc.b -$10, -4 ; 6
; off_36CC4:
Obj8D_SubObjData:
subObjData Obj8D_MapUnc_36CF0,make_art_tile(ArtTile_ArtNem_Grounder,1,1),4,5,$10,2
; off_36CCE:
Obj90_SubObjData:
subObjData Obj90_MapUnc_36D00,make_art_tile(ArtTile_ArtKos_LevelArt,0,0),$84,4,$10,0
; off_36CD8:
Obj90_SubObjData2:
subObjData Obj90_MapUnc_36CFA,make_art_tile(ArtTile_ArtNem_Grounder,1,1),$84,4,8,0
; animation script
Ani_obj8D_a: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 3, 2, 3, 4,$FF
even
; animation script
; off_36CEA:
Ani_obj8D_b: offsetTable
offsetTableEntry.w +
+ dc.b 7, 0, 1,$FC
even
; -----------------------------------------------------------------------------
; sprite mappings (obj8D)
; -----------------------------------------------------------------------------
Obj8D_MapUnc_36CF0: offsetTable
offsetTableEntry.w word_36D02 ; 0
offsetTableEntry.w word_36D24 ; 2
offsetTableEntry.w word_36D46 ; 4
offsetTableEntry.w word_36D58 ; 6
offsetTableEntry.w word_36D6A ; 8
; -----------------------------------------------------------------------------
; sprite mappings (obj90)
; -----------------------------------------------------------------------------
Obj90_MapUnc_36CFA: offsetTable
offsetTableEntry.w word_36D7C ; 0
offsetTableEntry.w word_36D86 ; 2
offsetTableEntry.w word_36D90 ; 4
; -----------------------------------------------------------------------------
; sprite mappings (obj90)
; -----------------------------------------------------------------------------
Obj90_MapUnc_36D00: offsetTable
offsetTableEntry.w word_36D9A ; 0
word_36D02:
dc.w 4
dc.w $F400, 0, 0,$FFF8
dc.w $FC06, 1, 0,$FFF0 ; 4
dc.w $F400, $800, $800, 0 ; 8
dc.w $FC06, $801, $800, 0 ; 12
word_36D24:
dc.w 4
dc.w $EC00, 7, 3,$FFF8
dc.w $F407, 8, 4,$FFF0 ; 4
dc.w $EC00, $807, $803, 0 ; 8
dc.w $F407, $808, $804, 0 ; 12
word_36D46:
dc.w 2
dc.w $EC0F, $10, 8,$FFF0
dc.w $C0C, $20, $10,$FFF0 ; 4
word_36D58:
dc.w 2
dc.w $EC0F, $10, 8,$FFF0
dc.w $C0C, $24, $12,$FFF0 ; 4
word_36D6A:
dc.w 2
dc.w $EC0F, $10, 8,$FFF0
dc.w $C0C, $28, $14,$FFF0 ; 4
word_36D7C:
dc.w 1
dc.w $F805, $2C, $16,$FFF8
word_36D86:
dc.w 1
dc.w $FC00, $30, $18,$FFFC
word_36D90:
dc.w 1
dc.w $FC00, $31, $18,$FFFC
word_36D9A:
dc.w 2
dc.w $F805,$4093,$4049,$FFF0
dc.w $F805,$4097,$404B, 0 ; 4
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 91 - Chop Chop (piranha/shark badnik) from ARZ
; ----------------------------------------------------------------------------
; OST Variables:
Obj91_move_timer = objoff_2A ; time to wait before turning around
Obj91_bubble_timer = objoff_2C ; time to wait before producing a bubble
; Sprite_36DAC:
Obj91:
moveq #0,d0
move.b routine(a0),d0
move.w Obj91_Index(pc,d0.w),d1
jmp Obj91_Index(pc,d1.w)
; ===========================================================================
; off_36DBA:
Obj91_Index: offsetTable
offsetTableEntry.w Obj91_Init ; 0 - Initialize object variables
offsetTableEntry.w Obj91_Main ; 2 - Moving back and forth until Sonic or Tails approach
offsetTableEntry.w Obj91_Waiting ; 4 - Stopped, opening and closing mouth
offsetTableEntry.w Obj91_Charge ; 6 - Charging at Sonic or Tails
; ===========================================================================
; loc_36DC2:
Obj91_Init:
bsr.w LoadSubObject
move.w #$200,Obj91_move_timer(a0)
move.w #$50,Obj91_bubble_timer(a0)
moveq #$40,d0 ; enemy speed
btst #0,status(a0) ; is enemy facing left?
bne.s + ; if not, branch
neg.w d0 ; else reverse movement direction
+
move.w d0,x_vel(a0) ; set speed
rts
; ===========================================================================
; loc_36DE4:
Obj91_Main:
subq.b #1,Obj91_bubble_timer(a0)
bne.s + ; branch, if timer isn't done counting down
bsr.w Obj91_MakeBubble
+
subq.w #1,Obj91_move_timer(a0)
bpl.s + ; branch, if timer isn't done counting down
move.w #$200,Obj91_move_timer(a0) ; else, reset timer...
bchg #0,status(a0) ; ... change direction...
bchg #0,render_flags(a0)
neg.w x_vel(a0) ; ... and reverse movement
+
jsrto (ObjectMove).l, JmpTo26_ObjectMove
bsr.w Obj_GetOrientationToPlayer
move.w d2,d4
move.w d3,d5
bsr.w Obj91_TestCharacterPos ; are Sonic or Tails close enough to attack?
bne.s Obj91_PrepareCharge ; if yes, prepare to charge at them
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_36E20
Obj91_PrepareCharge:
addq.b #2,routine(a0) ; => Obj91_Waiting
move.b #$10,Obj91_move_timer(a0) ; time to wait before charging at the player
clr.w x_vel(a0) ; stop movement
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_36E32:
Obj91_Waiting:
subq.b #1,Obj91_move_timer(a0)
bmi.s Obj91_MoveTowardsPlayer ; branch, if wait time is over
bra.w Obj91_Animate
; ===========================================================================
; loc_36E3C:
Obj91_MoveTowardsPlayer:
addq.b #2,routine(a0) ; => Obj91_Charge
bsr.w Obj_GetOrientationToPlayer
lsr.w #1,d0 ; set speed based on closest character
move.b Obj91_HorizontalSpeeds(pc,d0.w),x_vel(a0) ; horizontal
addi.w #$10,d3
cmpi.w #$20,d3 ; is closest character withing $10 pixels above or $F pixels below?
blo.s + ; if not, branch
lsr.w #1,d1 ; set speed based on closest character
move.b Obj91_VerticalSpeeds(pc,d1.w),1+y_vel(a0) ; vertical
+
bra.w Obj91_Animate
; ===========================================================================
; byte_36E62:
Obj91_HorizontalSpeeds:
dc.b -2 ; 0 - player is left from object -> move left
dc.b 2 ; 1 - player is right from object -> move right
; byte_36E64:
Obj91_VerticalSpeeds:
dc.b $80 ; 0 - player is above object -> ... move down?
dc.b $80 ; 1 - player is below object -> move down
; ===========================================================================
; loc_36E66:
Obj91_Charge:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
; loc_36E6A:
Obj91_Animate:
lea (Ani_obj91).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_36E78:
Obj91_MakeBubble:
move.w #$50,Obj91_bubble_timer(a0) ; reset timer
jsrto (SingleObjLoad).l, JmpTo19_SingleObjLoad
bne.s return_36EB0
_move.b #ObjID_SmallBubbles,id(a1) ; load obj
move.b #6,subtype(a1) ; <== Obj90_SubObjData2
move.w x_pos(a0),x_pos(a1) ; align objects horizontally
moveq #$14,d0 ; load x-offset
btst #0,render_flags(a0) ; is object facing left?
beq.s + ; if not, branch
neg.w d0 ; else mirror offset
+
add.w d0,x_pos(a1) ; add horizontal offset
move.w y_pos(a0),y_pos(a1) ; align objects vertically
addq.w #6,y_pos(a1) ; move object 6 pixels down
return_36EB0:
rts
; ===========================================================================
; loc_36EB2:
Obj91_TestCharacterPos:
addi.w #$20,d3
cmpi.w #$40,d3 ; is character too low?
bhs.s Obj91_DoNotCharge ; if yes, branch
tst.w d2 ; is character to the left?
bmi.s Obj91_TestPosLeft ; if yes, branch
tst.w x_vel(a0) ; is object moving left, towards character?
bpl.s Obj91_DoNotCharge ; if not, branch
bra.w Obj91_TestHorizontalDist
; ===========================================================================
; loc_36ECA:
Obj91_TestPosLeft:
tst.w x_vel(a0) ; is object moving right, towards character?
bmi.s Obj91_DoNotCharge ; if not, branch
neg.w d2 ; get absolute value
; loc_36ED2:
Obj91_TestHorizontalDist:
cmpi.w #$20,d2 ; is distance less than $20?
blo.s Obj91_DoNotCharge ; if yes, don't attack
cmpi.w #$A0,d2 ; is distance less than $A0?
blo.s Obj91_PlayerInRange ; if yes, attack
; loc_36EDE:
Obj91_DoNotCharge:
moveq #0,d2 ; -> don't charge at player
rts
; ===========================================================================
; loc_36EE2:
Obj91_PlayerInRange:
moveq #1,d2 ; -> charge at player
rts
; ===========================================================================
; off_36EE6:
Obj91_SubObjData:
subObjData Obj91_MapUnc_36EF6,make_art_tile(ArtTile_ArtNem_ChopChop,1,0),4,4,$10,2
; animation script
; off_36EF0:
Ani_obj91: offsetTable
offsetTableEntry.w +
+ dc.b 4, 0, 1,$FF ; 0
even
; --------------------------------------------------------------------------
; sprite mappings
; --------------------------------------------------------------------------
Obj91_MapUnc_36EF6: BINCLUDE "mappings/sprite/obj91.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 92 - Spiker (drill badnik) from HTZ
; ----------------------------------------------------------------------------
; Sprite_36F0E:
Obj92:
moveq #0,d0
move.b routine(a0),d0
move.w Obj92_Index(pc,d0.w),d1
jmp Obj92_Index(pc,d1.w)
; ===========================================================================
; off_36F1C:
Obj92_Index: offsetTable
offsetTableEntry.w Obj92_Init ; 0
offsetTableEntry.w loc_36F3C ; 2
offsetTableEntry.w loc_36F68 ; 4
offsetTableEntry.w loc_36F90 ; 6
; ===========================================================================
; loc_36F24:
Obj92_Init:
bsr.w LoadSubObject
move.b #$40,objoff_2A(a0)
move.w #$80,x_vel(a0)
bchg #0,status(a0)
rts
; ===========================================================================
loc_36F3C:
bsr.w loc_3703E
bne.s loc_36F48
subq.b #1,objoff_2A(a0)
bmi.s loc_36F5A
loc_36F48:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (Ani_obj92).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_36F5A:
addq.b #2,routine(a0)
move.b #$10,objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_36F68:
bsr.w loc_3703E
bne.s +
subq.b #1,objoff_2A(a0)
bmi.s loc_36F78
+
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_36F78:
subq.b #2,routine(a0)
move.b #$40,objoff_2A(a0)
neg.w x_vel(a0)
bchg #0,status(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_36F90:
move.b objoff_2E(a0),d0
cmpi.b #8,d0
beq.s loc_36FA4
subq.b #1,d0
move.b d0,objoff_2E(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_36FA4:
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s loc_36FDC
st objoff_2B(a0)
_move.b #ObjID_SpikerDrill,id(a1) ; load obj93
move.b subtype(a0),subtype(a1)
move.w a0,objoff_2C(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.b #4,mapping_frame(a1)
move.b #2,mapping_frame(a0)
move.b #1,anim(a0)
loc_36FDC:
move.b objoff_2F(a0),routine(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 93 - Drill thrown by Spiker from HTZ
; ----------------------------------------------------------------------------
; Sprite_36FE6:
Obj93:
moveq #0,d0
move.b routine(a0),d0
move.w Obj93_Index(pc,d0.w),d1
jmp Obj93_Index(pc,d1.w)
; ===========================================================================
; off_36FF4:
Obj93_Index: offsetTable
offsetTableEntry.w Obj93_Init ; 0
offsetTableEntry.w loc_37028 ; 2
; ===========================================================================
; loc_36FF8:
Obj93_Init:
bsr.w LoadSubObject
ori.b #$80,render_flags(a0)
ori.b #$80,collision_flags(a0)
movea.w objoff_2C(a0),a1 ; a1=object
move.b render_flags(a1),d0
andi.b #3,d0
or.b d0,render_flags(a0)
moveq #2,d1
btst #1,d0
bne.s +
neg.w d1
+
move.b d1,y_vel(a0)
rts
; ===========================================================================
loc_37028:
tst.b render_flags(a0)
bpl.w JmpTo65_DeleteObject
bchg #0,render_flags(a0)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3703E:
tst.b objoff_2B(a0)
bne.s loc_37062
tst.b render_flags(a0)
bpl.s loc_37062
bsr.w Obj_GetOrientationToPlayer
addi.w #$20,d2
cmpi.w #$40,d2
bhs.s loc_37062
addi.w #$80,d3
cmpi.w #$100,d3
blo.s loc_37066
loc_37062:
moveq #0,d0
rts
; ===========================================================================
loc_37066:
move.b routine(a0),objoff_2F(a0)
move.b #6,routine(a0)
move.b #$10,objoff_2E(a0)
moveq #1,d0
rts
; ===========================================================================
; off_3707C:
Obj92_SubObjData:
subObjData Obj92_Obj93_MapUnc_37092,make_art_tile(ArtTile_ArtKos_LevelArt,0,0),4,4,$10,$12
; animation script
; off_37086:
Ani_obj92: offsetTable
offsetTableEntry.w byte_3708A ; 0
offsetTableEntry.w byte_3708E ; 2
byte_3708A: dc.b 9, 0, 1,$FF
byte_3708E: dc.b 9, 2, 3,$FF
even
; ---------------------------------------------------------------------------
; sprite mappings
; ---------------------------------------------------------------------------
Obj92_Obj93_MapUnc_37092: BINCLUDE "mappings/sprite/obj93.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 95 - Sol (fireball-throwing orbit badnik) from HTZ
; ----------------------------------------------------------------------------
; Sprite_370FE:
Obj95:
moveq #0,d0
move.b routine(a0),d0
move.w Obj95_Index(pc,d0.w),d1
jmp Obj95_Index(pc,d1.w)
; ===========================================================================
; off_3710C:
Obj95_Index: offsetTable
offsetTableEntry.w Obj95_Init ; 0
offsetTableEntry.w Obj95_WaitForPlayer ; 2
offsetTableEntry.w loc_37224 ; 4
offsetTableEntry.w Obj95_FireballUpdate ; 6
offsetTableEntry.w loc_372B8 ; 8
; ===========================================================================
; loc_37116:
Obj95_Init:
move.l #Obj95_MapUnc_372E6,mappings(a0)
move.w #make_art_tile(ArtTile_ArtKos_LevelArt,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo64_Adjust2PArtPointer
ori.b #4,render_flags(a0)
move.b #4,priority(a0)
move.b #$B,collision_flags(a0)
move.b #$C,width_pixels(a0)
move.w #-$40,x_vel(a0)
moveq #0,d2
lea objoff_37(a0),a2
movea.l a2,a3
addq.w #1,a2
moveq #3,d1
; loc_37152:
Obj95_NextFireball:
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s loc_371AE
addq.b #1,(a3)
move.w a1,d5
subi.w #MainCharacter,d5
if object_size=$40
lsr.w #6,d5
else
divu.w #object_size,d5
endif
andi.w #$7F,d5
move.b d5,(a2)+
_move.b id(a0),id(a1) ; load obj95
move.b #6,routine(a1)
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
ori.b #4,render_flags(a1)
move.b #4,priority(a1)
move.b #8,width_pixels(a1)
move.b #3,mapping_frame(a1)
move.b #$98,collision_flags(a1)
move.b d2,angle(a1)
addi.b #$40,d2
move.l a0,objoff_3C(a1)
dbf d1,Obj95_NextFireball
loc_371AE:
moveq #1,d0
btst #0,status(a0)
beq.s loc_371BA
neg.w d0
loc_371BA:
move.b d0,objoff_36(a0)
move.b subtype(a0),routine(a0)
addq.b #2,routine(a0)
move.w #-$40,x_vel(a0)
btst #0,status(a0)
beq.s return_371DA
neg.w x_vel(a0)
return_371DA:
rts
; ===========================================================================
; loc_371DC:
Obj95_WaitForPlayer:
move.w (MainCharacter+x_pos).w,d0
sub.w x_pos(a0),d0
bcc.s loc_371E8
neg.w d0
loc_371E8:
cmpi.w #$A0,d0
bhs.s loc_3720C
move.w (MainCharacter+y_pos).w,d0
sub.w y_pos(a0),d0
bcc.s loc_371FA
neg.w d0
loc_371FA:
cmpi.w #$50,d0
bhs.s loc_3720C
tst.w (Debug_placement_mode).w
bne.s loc_3720C
move.b #1,anim(a0)
loc_3720C:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (Ani_obj95_a).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
andi.b #3,mapping_frame(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_37224:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (Ani_obj95_b).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
andi.b #3,mapping_frame(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_3723C:
Obj95_FireballUpdate:
lea (Ani_obj95_b).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
movea.l objoff_3C(a0),a1 ; a1=object
_cmpi.b #ObjID_Sol,id(a1) ; check if parent object is still alive
bne.w JmpTo65_DeleteObject
cmpi.b #2,mapping_frame(a1)
bne.s Obj95_FireballOrbit
cmpi.b #$40,angle(a0)
bne.s Obj95_FireballOrbit
addq.b #2,routine(a0)
move.b #0,anim(a0)
subq.b #1,objoff_37(a1)
bne.s loc_37278
addq.b #2,routine(a1)
loc_37278:
move.w #-$200,x_vel(a0)
btst #0,status(a1)
beq.s +
neg.w x_vel(a0)
+
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; loc_3728E:
Obj95_FireballOrbit:
move.b angle(a0),d0
jsr (CalcSine).l
asr.w #4,d1
add.w x_pos(a1),d1
move.w d1,x_pos(a0)
asr.w #4,d0
add.w y_pos(a1),d0
move.w d0,y_pos(a0)
move.b objoff_36(a1),d0
add.b d0,angle(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_372B8:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
tst.b render_flags(a0)
bpl.w JmpTo65_DeleteObject
lea (Ani_obj95_b).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; animation script
; off_372D2:
Ani_obj95_a: offsetTable
offsetTableEntry.w byte_372D6 ; 0
offsetTableEntry.w byte_372DA ; 1
byte_372D6: dc.b $F, 0,$FF, 0
byte_372DA: dc.b $F, 1, 2,$FE, 1
even
; animation script
; off_372E0:
Ani_obj95_b: offsetTable
offsetTableEntry.w +
+ dc.b 5, 3, 4,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj95_MapUnc_372E6: BINCLUDE "mappings/sprite/obj95.bin"
Invalid_SubObjData:
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 94,96 - Rexon (lava snake badnik), from HTZ
; ----------------------------------------------------------------------------
; Sprite_37322:
Obj94:
moveq #0,d0
move.b routine(a0),d0
move.w Obj94_Index(pc,d0.w),d1
jmp Obj94_Index(pc,d1.w)
; ===========================================================================
; off_37330:
Obj94_Index: offsetTable
offsetTableEntry.w Obj94_Init ; 0
offsetTableEntry.w Obj94_WaitForPlayer ; 2
offsetTableEntry.w Obj94_ReadyToCreateHead ; 4
offsetTableEntry.w Obj94_PostCreateHead ; 6
; ===========================================================================
; loc_37338:
Obj94_Init:
bsr.w LoadSubObject
move.b #2,mapping_frame(a0)
move.w #-$20,x_vel(a0)
move.b #$80,objoff_2A(a0)
rts
; ===========================================================================
; loc_37350:
Obj94_WaitForPlayer:
bsr.w Obj_GetOrientationToPlayer
addi.w #$60,d2
cmpi.w #$100,d2
bhs.s loc_37362
bsr.w Obj94_CreateHead
loc_37362:
move.w x_pos(a0),-(sp)
bsr.w Obj94_CheckTurnAround
move.w #$1B,d1
move.w #8,d2
move.w #$11,d3
move.w (sp)+,d4
jsrto (SolidObject).l, JmpTo27_SolidObject
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_37380:
Obj94_CheckTurnAround:
subq.b #1,objoff_2A(a0)
bpl.s loc_37396
move.b #$80,objoff_2A(a0)
neg.w x_vel(a0)
bchg #0,render_flags(a0)
loc_37396:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
rts
; ===========================================================================
; loc_3739C:
Obj94_ReadyToCreateHead:
bsr.w Obj_GetOrientationToPlayer
addi.w #$60,d2
cmpi.w #$100,d2
bhs.s loc_373AE
bsr.w Obj94_CreateHead
loc_373AE:
bsr.w Obj94_SolidCollision
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_373B6:
Obj94_SolidCollision:
move.w #$1B,d1
move.w #8,d2
move.w #8,d3
move.w x_pos(a0),d4
jmpto (SolidObject).l, JmpTo27_SolidObject
; ===========================================================================
; loc_373CA:
Obj94_PostCreateHead:
bsr.s Obj94_SolidCollision
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 97 - Rexon's head, from HTZ
; ----------------------------------------------------------------------------
; Sprite_373D0:
Obj97:
moveq #0,d0
move.b routine(a0),d0
move.w Obj97_Index(pc,d0.w),d1
jmp Obj97_Index(pc,d1.w)
; ===========================================================================
; off_373DE:
Obj97_Index: offsetTable
offsetTableEntry.w Obj97_Init ; 0
offsetTableEntry.w Obj97_InitialWait ; 2
offsetTableEntry.w Obj97_RaiseHead ; 4
offsetTableEntry.w Obj97_Normal ; 6
offsetTableEntry.w Obj97_DeathDrop ; 8
; ===========================================================================
; loc_373E8:
Obj97_Init:
bsr.w LoadSubObject
move.b #8,width_pixels(a0)
moveq #$28,d0
btst #0,render_flags(a0)
bne.s +
moveq #-$18,d0
+
add.w d0,x_pos(a0)
addi.w #$10,y_pos(a0)
move.b #1,objoff_38(a0)
movea.w objoff_2C(a0),a1 ; a1=object
lea objoff_2E(a1),a1
move.b #$B,collision_flags(a0)
moveq #0,d0
move.w objoff_2E(a0),d0
cmpi.w #8,d0
beq.s +
move.b #1,mapping_frame(a0)
move.b #$8B,collision_flags(a0)
move.w (a1,d0.w),objoff_30(a0)
+
move.w 6(a1),objoff_32(a0)
lsr.w #1,d0
move.b byte_3744E(pc,d0.w),objoff_2A(a0)
move.b d0,objoff_39(a0)
rts
; ===========================================================================
byte_3744E:
dc.b $1E
dc.b $18 ; 1
dc.b $12 ; 2
dc.b $C ; 3
dc.b 6 ; 4
dc.b 0 ; 5
; ===========================================================================
; loc_37454:
Obj97_InitialWait:
if gameRevision<2
bsr.w Obj97_CheckHeadIsAlive
subq.b #1,objoff_2A(a0)
bmi.s Obj97_StartRaise
else
; fixes an occational crash when defeated
subq.b #1,objoff_2A(a0)
bmi.s Obj97_StartRaise
bsr.w Obj97_CheckHeadIsAlive
endif
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_37462:
Obj97_StartRaise:
addq.b #2,routine(a0)
move.w #-$120,x_vel(a0)
move.w #-$200,y_vel(a0)
move.w objoff_2E(a0),d0
subi_.w #8,d0
neg.w d0
lsr.w #1,d0
move.b byte_3744E(pc,d0.w),objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_37488:
Obj97_RaiseHead:
if gameRevision<2
bsr.w Obj97_CheckHeadIsAlive
moveq #$10,d0
add.w d0,x_vel(a0)
subq.b #1,objoff_2A(a0)
bmi.s Obj97_StartNormalState
else
; fixes an occational crash when defeated
moveq #$10,d0
add.w d0,x_vel(a0)
subq.b #1,objoff_2A(a0)
bmi.s Obj97_StartNormalState
bsr.w Obj97_CheckHeadIsAlive
endif
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_374A0:
Obj97_StartNormalState:
addq.b #2,routine(a0)
bsr.w Obj_MoveStop
move.b #$20,objoff_2A(a0)
move.w objoff_2E(a0),d0
lsr.w #1,d0
move.b byte_374BE(pc,d0.w),objoff_2B(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
byte_374BE:
dc.b $24
dc.b $20 ; 1
dc.b $1C ; 2
dc.b $1A ; 3
; ===========================================================================
; loc_374C2:
Obj97_Normal:
bsr.w Obj97_CheckHeadIsAlive
cmpi.w #8,objoff_2E(a0)
bne.s loc_374D8
subq.b #1,objoff_2A(a0)
bpl.s loc_374D8
bsr.w Obj97_FireProjectile
loc_374D8:
move.b objoff_39(a0),d0
addq.b #1,d0
move.b d0,objoff_39(a0)
andi.b #3,d0
bne.s +
bsr.w loc_3758A
bsr.w Obj97_Oscillate
+
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_374F4:
Obj97_DeathDrop:
move.w (Camera_Max_Y_pos_now).w,d0
addi.w #$E0,d0
cmp.w y_pos(a0),d0
blo.w JmpTo65_DeleteObject
jsrto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_3750C:
Obj97_CheckHeadIsAlive:
movea.w objoff_32(a0),a1 ; a1=object
cmpi.b #ObjID_RexonHead,(a1)
beq.s + ; rts
move.b #8,routine(a0)
move.w objoff_2E(a0),d0
move.w word_37528(pc,d0.w),x_vel(a0)
+
rts
; ===========================================================================
word_37528:
dc.w $80
dc.w -$100 ; 1
dc.w $100 ; 2
dc.w -$80 ; 3
dc.w $80 ; 4
; ===========================================================================
; loc_37532:
Obj97_FireProjectile:
move.b #$7F,objoff_2A(a0)
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s ++ ; rts
_move.b #ObjID_Projectile,id(a1) ; load obj98
move.b #3,mapping_frame(a1)
move.b #$10,subtype(a1) ; <== Obj94_SubObjData2
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
lea (ObjectMove).l,a2
move.l a2,objoff_2A(a1)
moveq #1,d0
moveq #$10,d1
btst #0,render_flags(a0)
bne.s +
neg.w d0
neg.w d1
+
move.b d0,x_vel(a1)
add.w d1,x_pos(a1)
addq.w #4,y_pos(a1)
move.b #$80,1+y_vel(a1)
+
rts
; ===========================================================================
loc_3758A:
move.b objoff_2B(a0),d0
move.b objoff_38(a0),d1
add.b d1,d0
move.b d0,objoff_2B(a0)
subi.b #$18,d0
beq.s +
bcs.s +
cmpi.b #$10,d0
blo.s ++ ; rts
+
neg.b objoff_38(a0)
+
rts
; ===========================================================================
; loc_375AC:
Obj94_CreateHead:
move.b #6,routine(a0)
bclr #0,render_flags(a0)
tst.w d0
beq.s +
bset #0,render_flags(a0)
+
bsr.w Obj_MoveStop
lea objoff_2C(a0),a2
moveq #0,d1
moveq #4,d6
loc_375CE:
jsrto (SingleObjLoad).l, JmpTo19_SingleObjLoad
bne.s + ; rts
_move.b #ObjID_RexonHead,id(a1) ; load obj97
move.b render_flags(a0),render_flags(a1)
move.b subtype(a0),subtype(a1)
move.w a0,objoff_2C(a1)
move.w a1,(a2)+
move.w d1,objoff_2E(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
addq.w #2,d1
dbf d6,loc_375CE
+
rts
; ===========================================================================
; loc_37604:
Obj97_Oscillate:
move.w objoff_30(a0),d0
beq.s + ; rts
movea.w d0,a1 ; a1=object
lea byte_376A8(pc),a2
moveq #0,d0
move.b objoff_2B(a0),d0
andi.b #$7F,d0
move.w d0,d1
andi.w #$1F,d0
add.w d0,d0
move.b (a2,d0.w),d2
ext.w d2
move.b 1(a2,d0.w),d3
ext.w d3
lsr.w #4,d1
andi.w #6,d1
move.w off_37652(pc,d1.w),d1
jsr off_37652(pc,d1.w)
move.w x_pos(a0),d4
add.w d2,d4
move.w d4,x_pos(a1)
move.b 1+y_pos(a0),d5
add.b d3,d5
move.b d5,1+y_pos(a1)
+
rts
; ===========================================================================
off_37652: offsetTable
offsetTableEntry.w return_3765A ; 0
offsetTableEntry.w loc_3765C ; $20
offsetTableEntry.w loc_37662 ; $40
offsetTableEntry.w loc_37668 ; $60
; ===========================================================================
return_3765A:
rts
; ===========================================================================
loc_3765C:
exg d2,d3
neg.w d3
rts
; ===========================================================================
loc_37662:
neg.w d2
neg.w d3
rts
; ===========================================================================
loc_37668:
exg d2,d3
neg.w d2
rts
; ===========================================================================
; off_3766E:
Obj94_SubObjData:
subObjData Obj94_Obj98_MapUnc_37678,make_art_tile(ArtTile_ArtNem_Rexon,3,0),4,4,$10,0
; ------------------------------------------------------------------------
; sprite mappings
; ------------------------------------------------------------------------
Obj94_Obj98_MapUnc_37678: BINCLUDE "mappings/sprite/obj97.bin"
; seems to be a lookup table for oscillating horizontal position offset
byte_376A8:
dc.b $F, 0
dc.b $F,$FF ; 1
dc.b $F,$FF ; 2
dc.b $F,$FE ; 3
dc.b $F,$FD ; 4
dc.b $F,$FC ; 5
dc.b $E,$FC ; 6
dc.b $E,$FB ; 7
dc.b $E,$FA ; 8
dc.b $E,$FA ; 9
dc.b $D,$F9 ; 10
dc.b $D,$F8 ; 11
dc.b $C,$F8 ; 12
dc.b $C,$F7 ; 13
dc.b $C,$F6 ; 14
dc.b $B,$F6 ; 15
dc.b $B,$F5 ; 16
dc.b $A,$F5 ; 17
dc.b $A,$F4 ; 18
dc.b 9,$F4 ; 19
dc.b 8,$F4 ; 20
dc.b 8,$F3 ; 21
dc.b 7,$F3 ; 22
dc.b 6,$F2 ; 23
dc.b 6,$F2 ; 24
dc.b 5,$F2 ; 25
dc.b 4,$F2 ; 26
dc.b 4,$F1 ; 27
dc.b 3,$F1 ; 28
dc.b 2,$F1 ; 29
dc.b 1,$F1 ; 30
dc.b 1,$F1 ; 31
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 98 - Projectile with optional gravity (EHZ coconut, CPZ spiny, etc.)
; ----------------------------------------------------------------------------
; Sprite_376E8:
Obj98:
moveq #0,d0
move.b routine(a0),d0
move.w Obj98_Index(pc,d0.w),d1
jmp Obj98_Index(pc,d1.w)
; ===========================================================================
; off_376F6: Obj98_States:
Obj98_Index: offsetTable
offsetTableEntry.w Obj98_Init ; 0
offsetTableEntry.w Obj98_Main ; 2
; ===========================================================================
; loc_376FA:
Obj98_Init: ;;
bra.w LoadSubObject
; ===========================================================================
; loc_376FE:
Obj98_Main:
tst.b render_flags(a0)
bpl.w JmpTo65_DeleteObject
movea.l objoff_2A(a0),a1
jsr (a1) ; dynamic call! to Obj98_NebulaBombFall, Obj98_TurtloidShotMove, Obj98_CoconutFall, Obj98_CluckerShotMove, Obj98_SpinyShotFall, or Obj98_WallTurretShotMove, assuming the code hasn't been changed
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; for obj99
; loc_37710:
Obj98_NebulaBombFall:
bchg #palette_bit_0,art_tile(a0) ; bypass the animation system and make it blink
jmpto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall
; ===========================================================================
; for obj9A
; loc_3771A:
Obj98_TurtloidShotMove:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (Ani_TurtloidShot).l,a1
jmpto (AnimateSprite).l, JmpTo25_AnimateSprite
; ===========================================================================
; for obj9D
; loc_37728:
Obj98_CoconutFall:
addi.w #$20,y_vel(a0) ; apply gravity (less than normal)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
rts
; ===========================================================================
; for objAE
; loc_37734:
Obj98_CluckerShotMove:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (Ani_CluckerShot).l,a1
jmpto (AnimateSprite).l, JmpTo25_AnimateSprite
; ===========================================================================
; for objA6
; loc_37742:
Obj98_SpinyShotFall:
addi.w #$20,y_vel(a0) ; apply gravity (less than normal)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (Ani_SpinyShot).l,a1
jmpto (AnimateSprite).l, JmpTo25_AnimateSprite
; ===========================================================================
; for objB8
; loc_37756:
Obj98_WallTurretShotMove:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (Ani_WallTurretShot).l,a1
jmpto (AnimateSprite).l, JmpTo25_AnimateSprite
; ===========================================================================
; off_37764:
Obj94_SubObjData2:
subObjData Obj94_Obj98_MapUnc_37678,make_art_tile(ArtTile_ArtNem_Rexon,1,0),$84,4,4,$98
; off_3776E:
Obj99_SubObjData:
subObjData Obj99_Obj98_MapUnc_3789A,make_art_tile(ArtTile_ArtNem_Nebula,1,1),$84,4,8,$8B
; off_37778:
Obj9A_SubObjData2:
subObjData Obj9A_Obj98_MapUnc_37B62,make_art_tile(ArtTile_ArtNem_Turtloid,0,0),$84,4,4,$98
; off_37782:
Obj9D_SubObjData2:
subObjData Obj9D_Obj98_MapUnc_37D96,make_art_tile(ArtTile_ArtNem_Coconuts,0,0),$84,4,8,$8B
; off_3778C:
ObjA4_SubObjData2:
subObjData ObjA4_Obj98_MapUnc_38A96,make_art_tile(ArtTile_ArtNem_MtzSupernova,0,1),$84,5,4,$98
; off_37796:
ObjA6_SubObjData:
subObjData ObjA5_ObjA6_Obj98_MapUnc_38CCA,make_art_tile(ArtTile_ArtNem_Spiny,1,0),$84,5,4,$98
; off_377A0:
ObjA7_SubObjData3:
subObjData ObjA7_ObjA8_ObjA9_Obj98_MapUnc_3921A,make_art_tile(ArtTile_ArtNem_Grabber,1,1),$84,4,4,$98
; off_377AA:
ObjAD_SubObjData3:
subObjData ObjAD_Obj98_MapUnc_395B4,make_art_tile(ArtTile_ArtNem_WfzScratch,0,0),$84,5,4,$98
; off_377B4:
ObjAF_SubObjData:
subObjData ObjAF_Obj98_MapUnc_39E68,make_art_tile(ArtTile_ArtNem_CNZBonusSpike,1,0),$84,5,4,$98
; off_377BE:
ObjB8_SubObjData2:
subObjData ObjB8_Obj98_MapUnc_3BA46,make_art_tile(ArtTile_ArtNem_WfzWallTurret,0,0),$84,3,4,$98
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 99 - Nebula (bomber badnik) from SCZ
; ----------------------------------------------------------------------------
; Sprite_377C8:
Obj99:
moveq #0,d0
move.b routine(a0),d0
move.w Obj99_Index(pc,d0.w),d1
jmp Obj99_Index(pc,d1.w)
; ===========================================================================
; off_377D6:
Obj99_Index: offsetTable
offsetTableEntry.w Obj99_Init
offsetTableEntry.w loc_377E8
offsetTableEntry.w loc_3781C
; ===========================================================================
; loc_377DC:
Obj99_Init:
bsr.w LoadSubObject
move.w #-$C0,x_vel(a0)
rts
; ===========================================================================
loc_377E8:
bsr.w Obj_GetOrientationToPlayer
tst.w d0
bne.s loc_377FA
cmpi.w #$80,d2
bhs.s loc_377FA
bsr.w loc_37810
loc_377FA:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
bsr.w loc_36776
lea (Ani_obj99).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
bra.w Obj_DeleteBehindScreen
; ===========================================================================
loc_37810:
addq.b #2,routine(a0)
move.w #-$A0,y_vel(a0)
rts
; ===========================================================================
loc_3781C:
tst.b objoff_2A(a0)
bne.s loc_37834
bsr.w Obj_GetOrientationToPlayer
addi_.w #8,d2
cmpi.w #$10,d2
bhs.s loc_37834
bsr.w loc_37850
loc_37834:
addi_.w #1,y_vel(a0)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
bsr.w loc_36776
lea (Ani_obj99).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
bra.w Obj_DeleteBehindScreen
; ===========================================================================
loc_37850:
st objoff_2A(a0)
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s return_37886
_move.b #ObjID_Projectile,id(a1) ; load obj98
move.b #4,mapping_frame(a1)
move.b #$14,subtype(a1) ; <== Obj99_SubObjData
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
addi.w #$18,y_pos(a1)
lea_ Obj98_NebulaBombFall,a2
move.l a2,objoff_2A(a1)
return_37886:
rts
; ===========================================================================
; off_37888:
Obj99_SubObjData2:
subObjData Obj99_Obj98_MapUnc_3789A,make_art_tile(ArtTile_ArtNem_Nebula,1,1),4,4,$10,6
; animation script
; off_37892:
Ani_obj99: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 3, 0, 1, 2, 3,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj99_Obj98_MapUnc_3789A: BINCLUDE "mappings/sprite/obj99.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 9A - Turtloid (turtle badnik) from Sky Chase Zone
; ----------------------------------------------------------------------------
; Sprite_37936:
Obj9A:
moveq #0,d0
move.b routine(a0),d0
move.w Obj9A_Index(pc,d0.w),d1
jmp Obj9A_Index(pc,d1.w)
; ===========================================================================
; off_37944:
Obj9A_Index: offsetTable
offsetTableEntry.w Obj9A_Init ; 0
offsetTableEntry.w Obj9A_Main ; 2
; ===========================================================================
; loc_37948:
Obj9A_Init:
bsr.w LoadSubObject
move.w #-$80,x_vel(a0)
bsr.w loc_37A4A
lea (Ani_obj9A).l,a1
move.l a1,objoff_2E(a0)
bra.w loc_37ABE
; ===========================================================================
; loc_37964:
Obj9A_Main:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3797A(pc,d0.w),d1
jsr off_3797A(pc,d1.w)
bsr.w loc_37982
bra.w Obj_DeleteBehindScreen
; ===========================================================================
off_3797A: offsetTable
offsetTableEntry.w loc_379A0 ; 0
offsetTableEntry.w loc_379CA ; 2
offsetTableEntry.w loc_379EA ; 4
offsetTableEntry.w return_37A04 ; 6
; ===========================================================================
loc_37982:
move.w x_pos(a0),-(sp)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
bsr.w loc_36776
move.w #$18,d1
move.w #8,d2
move.w #$E,d3
move.w (sp)+,d4
jmpto (PlatformObject).l, JmpTo9_PlatformObject
; ===========================================================================
loc_379A0:
bsr.w Obj_GetOrientationToPlayer
tst.w d0
bmi.w return_37A48
cmpi.w #$80,d2
bhs.w return_37A48
addq.b #2,routine_secondary(a0)
move.w #0,x_vel(a0)
move.b #4,objoff_2A(a0)
move.b #1,mapping_frame(a0)
rts
; ===========================================================================
loc_379CA:
subq.b #1,objoff_2A(a0)
bpl.w return_37A48
addq.b #2,routine_secondary(a0)
move.b #8,objoff_2A(a0)
movea.w objoff_2C(a0),a1 ; a1=object
move.b #3,mapping_frame(a1)
bra.w loc_37AF2
; ===========================================================================
loc_379EA:
subq.b #1,objoff_2A(a0)
bpl.s return_37A02
addq.b #2,routine_secondary(a0)
move.w #-$80,x_vel(a0)
clr.b mapping_frame(a0)
movea.w objoff_2C(a0),a1 ; a1=object
return_37A02:
rts
; ===========================================================================
return_37A04:
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 9B - Turtloid rider from Sky Chase Zone
; ----------------------------------------------------------------------------
; Sprite_37A06:
Obj9B:
moveq #0,d0
move.b routine(a0),d0
move.w Obj9B_Index(pc,d0.w),d1
jmp Obj9B_Index(pc,d1.w)
; ===========================================================================
; off_37A14:
Obj9B_Index: offsetTable
offsetTableEntry.w Obj9B_Init ; 0
offsetTableEntry.w Obj9B_Main ; 2
; ===========================================================================
; BranchTo_LoadSubObject
Obj9B_Init:
bra.w LoadSubObject
; ===========================================================================
; loc_37A1C:
Obj9B_Main:
movea.w objoff_2C(a0),a1 ; a1=object
lea word_37A2C(pc),a2
bsr.w loc_37A30
bra.w Obj_DeleteBehindScreen
; ===========================================================================
word_37A2C:
dc.w 4 ; 0
dc.w -$18 ; 1
; ===========================================================================
loc_37A30:
move.l x_pos(a1),x_pos(a0)
move.l y_pos(a1),y_pos(a0)
move.w (a2)+,d0
add.w d0,x_pos(a0)
move.w (a2)+,d0
add.w d0,y_pos(a0)
return_37A48:
rts
; ===========================================================================
loc_37A4A:
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s return_37A80
_move.b #ObjID_TurtloidRider,id(a1) ; load obj9B
move.b #2,mapping_frame(a1)
move.b #$18,subtype(a1) ; <== Obj9B_SubObjData
move.w a0,objoff_2C(a1)
move.w a1,objoff_2C(a0)
move.w x_pos(a0),x_pos(a1)
addq.w #4,x_pos(a1)
move.w y_pos(a0),y_pos(a1)
subi.w #$18,y_pos(a1)
return_37A80:
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 9C - Balkiry's jet from Sky Chase Zone
; ----------------------------------------------------------------------------
; Sprite_37A82:
Obj9C:
moveq #0,d0
move.b routine(a0),d0
move.w Obj9C_Index(pc,d0.w),d1
jmp Obj9C_Index(pc,d1.w)
; ===========================================================================
; off_37A90:
Obj9C_Index: offsetTable
offsetTableEntry.w Obj9C_Init
offsetTableEntry.w Obj9C_Main
; ===========================================================================
; BranchTo2_LoadSubObject
Obj9C_Init:
bra.w LoadSubObject
; ===========================================================================
; loc_37A98:
Obj9C_Main:
movea.w objoff_2C(a0),a1 ; a1=object
move.b objoff_32(a0),d0
cmp.b (a1),d0
bne.w JmpTo65_DeleteObject
move.l x_pos(a1),x_pos(a0)
move.l y_pos(a1),y_pos(a0)
movea.l objoff_2E(a0),a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
bra.w Obj_DeleteBehindScreen
; ===========================================================================
loc_37ABE:
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s + ; rts
_move.b #ObjID_BalkiryJet,id(a1) ; load obj9C
move.b #6,mapping_frame(a1)
move.b #$1A,subtype(a1) ; <== Obj9C_SubObjData
move.w a0,objoff_2C(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.l objoff_2E(a0),objoff_2E(a1)
move.b (a0),objoff_32(a1)
+
rts
; ===========================================================================
; this code is for Obj9A
loc_37AF2:
jsrto (SingleObjLoad).l, JmpTo19_SingleObjLoad
bne.s + ; rts
_move.b #ObjID_Projectile,id(a1) ; load obj98
move.b #6,mapping_frame(a1)
move.b #$1C,subtype(a1) ; <== Obj9A_SubObjData2
move.w x_pos(a0),x_pos(a1)
subi.w #$14,x_pos(a1)
move.w y_pos(a0),y_pos(a1)
addi.w #$A,y_pos(a1)
move.w #-$100,x_vel(a1)
lea_ Obj98_TurtloidShotMove,a2
move.l a2,objoff_2A(a1)
+
rts
; ===========================================================================
; off_37B32:
Obj9A_SubObjData:
subObjData Obj9A_Obj98_MapUnc_37B62,make_art_tile(ArtTile_ArtNem_Turtloid,0,0),4,5,$18,0
; off_37B3C:
Obj9B_SubObjData:
subObjData Obj9A_Obj98_MapUnc_37B62,make_art_tile(ArtTile_ArtNem_Turtloid,0,0),4,4,$C,$1A
; off_37B46:
Obj9C_SubObjData:
subObjData Obj9A_Obj98_MapUnc_37B62,make_art_tile(ArtTile_ArtNem_Turtloid,0,0),4,5,8,0
; animation script
; off_37B50: TurtloidShotAniData:
Ani_TurtloidShot: offsetTable
offsetTableEntry.w +
+ dc.b 1, 4, 5,$FF
even
; animation script
; off_37B56:
Ani_obj9A: offsetTable
offsetTableEntry.w +
+ dc.b 1, 6, 7,$FF
even
; animation script
; off_37B5C:
Ani_obj9C: offsetTable
offsetTableEntry.w +
+ dc.b 1, 8, 9,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj9A_Obj98_MapUnc_37B62: BINCLUDE "mappings/sprite/obj9C.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 9D - Coconuts (monkey badnik) from EHZ
; ----------------------------------------------------------------------------
; OST Variables:
Obj9D_timer = objoff_2A ; byte
Obj9D_climb_table_index = objoff_2C ; word
Obj9D_attack_timer = objoff_2E ; byte ; time player needs to spend close to object before it attacks
; Sprite_37BFA:
Obj9D:
moveq #0,d0
move.b routine(a0),d0
move.w Obj9D_Index(pc,d0.w),d1
jmp Obj9D_Index(pc,d1.w)
; ===========================================================================
; off_37C08:
Obj9D_Index: offsetTable
offsetTableEntry.w Obj9D_Init ; 0
offsetTableEntry.w Obj9D_Idle ; 2
offsetTableEntry.w Obj9D_Climbing ; 4
offsetTableEntry.w Obj9D_Throwing ; 6
; ===========================================================================
; loc_37C10:
Obj9D_Init:
bsr.w LoadSubObject
move.b #$10,Obj9D_timer(a0)
rts
; ===========================================================================
; loc_37C1C: Obj9D_Main:
Obj9D_Idle:
bsr.w Obj_GetOrientationToPlayer
bclr #0,render_flags(a0) ; face right
bclr #0,status(a0)
tst.w d0 ; is player to object's left?
beq.s + ; if not, branch
bset #0,render_flags(a0) ; face left
bset #0,status(a0)
+
addi.w #$60,d2
cmpi.w #$C0,d2
bcc.s + ; branch, if distance to player is greater than 60 in either direction
tst.b Obj9D_attack_timer(a0) ; wait for a bit before attacking
beq.s Obj9D_StartThrowing ; branch, when done waiting
subq.b #1,Obj9D_attack_timer(a0)
+
subq.b #1,Obj9D_timer(a0) ; wait for a bit...
bmi.s Obj9D_StartClimbing ; branch, when done waiting
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ---------------------------------------------------------------------------
Obj9D_StartClimbing:
addq.b #2,routine(a0) ; => Obj9D_Climbing
bsr.w Obj9D_SetClimbingDirection
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ---------------------------------------------------------------------------
; loc_37C66:
Obj9D_StartThrowing:
move.b #6,routine(a0) ; => Obj9D_Throwing
move.b #1,mapping_frame(a0) ; display first throwing frame
move.b #8,Obj9D_timer(a0) ; set time to display frame
move.b #$20,Obj9D_attack_timer(a0) ; reset timer
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ---------------------------------------------------------------------------
; loc_37C82:
Obj9D_SetClimbingDirection:
move.w Obj9D_climb_table_index(a0),d0
cmpi.w #$C,d0
blo.s + ; branch, if index is less than $C
moveq #0,d0 ; otherwise, reset to 0
+
lea Obj9D_ClimbData(pc,d0.w),a1
addq.w #2,d0
move.w d0,Obj9D_climb_table_index(a0)
move.b (a1)+,y_vel(a0) ; climbing speed
move.b (a1)+,Obj9D_timer(a0) ; time to spend moving at this speed
rts
; ===========================================================================
; byte_37CA2:
Obj9D_ClimbData:
dc.b -1,$20
dc.b 1,$18 ; 2
dc.b -1,$10 ; 4
dc.b 1,$28 ; 6
dc.b -1,$20 ; 8
dc.b 1,$10 ; 10
; ===========================================================================
; loc_37CAE: Obj09_Climbing:
Obj9D_Climbing:
subq.b #1,Obj9D_timer(a0)
beq.s Obj9D_StopClimbing ; branch, if done moving
jsrto (ObjectMove).l, JmpTo26_ObjectMove ; else, keep moving
lea (Ani_obj09).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_37CC6:
Obj9D_StopClimbing:
subq.b #2,routine(a0) ; => Obj9D_Idle
move.b #$10,Obj9D_timer(a0) ; time to remain idle
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_37CD4: Obj09_Throwing:
Obj9D_Throwing:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w Obj9D_ThrowingStates(pc,d0.w),d1
jsr Obj9D_ThrowingStates(pc,d1.w)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; off_37CE6:
Obj9D_ThrowingStates: offsetTable
offsetTableEntry.w Obj9D_ThrowingHandRaised ; 0
offsetTableEntry.w Obj9D_ThrowingHandLowered ; 2
; ===========================================================================
; loc_37CEA:
Obj9D_ThrowingHandRaised:
subq.b #1,Obj9D_timer(a0) ; wait for a bit...
bmi.s +
rts
; ---------------------------------------------------------------------------
+ addq.b #2,routine_secondary(a0) ; => Obj9D_ThrowingHandLowered
move.b #8,Obj9D_timer(a0)
move.b #2,mapping_frame(a0) ; display second throwing frame
bra.w Obj9D_CreateCoconut
; ===========================================================================
; loc_37D06:
Obj9D_ThrowingHandLowered:
subq.b #1,Obj9D_timer(a0) ; wait for a bit...
bmi.s +
rts
; ---------------------------------------------------------------------------
+ clr.b routine_secondary(a0) ; reset routine counter for next time
move.b #4,routine(a0) ; => Obj9D_Climbing
move.b #8,Obj9D_timer(a0) ; this gets overwrittten by the next subroutine...
bra.w Obj9D_SetClimbingDirection
; ===========================================================================
; loc_37D22:
Obj9D_CreateCoconut:
jsrto (SingleObjLoad).l, JmpTo19_SingleObjLoad
bne.s return_37D74 ; branch, if no free slots
_move.b #ObjID_Projectile,id(a1) ; load obj98
move.b #3,mapping_frame(a1)
move.b #$20,subtype(a1) ; <== Obj9D_SubObjData2
move.w x_pos(a0),x_pos(a1) ; align with parent object
move.w y_pos(a0),y_pos(a1)
addi.w #-$D,y_pos(a1) ; offset slightly upward
moveq #0,d0 ; use rightfacing data
btst #0,render_flags(a0) ; is object facing left?
bne.s + ; if yes, branch
moveq #4,d0 ; use leftfacing data
+
lea Obj9D_ThrowData(pc,d0.w),a2
move.w (a2)+,d0
add.w d0,x_pos(a1) ; offset slightly left or right depending on object's direction
move.w (a2)+,x_vel(a1) ; set projectile speed
move.w #-$100,y_vel(a1)
lea_ Obj98_CoconutFall,a2 ; set the routine used to move the projectile
move.l a2,objoff_2A(a1)
return_37D74:
rts
; ===========================================================================
; word_37D76:
Obj9D_ThrowData:
dc.w -$B, $100 ; 0
dc.w $B, -$100 ; 4
; off_37D7E:
Obj9D_SubObjData:
subObjData Obj9D_Obj98_MapUnc_37D96,make_art_tile(ArtTile_ArtNem_Coconuts,0,0),4,5,$C,9
; animation script
; off_37D88:
Ani_obj09: offsetTable
offsetTableEntry.w byte_37D8C ; 0
offsetTableEntry.w byte_37D90 ; 1
byte_37D8C: dc.b 5, 0, 1,$FF
byte_37D90: dc.b 9, 1, 2, 1,$FF
even
; ------------------------------------------------------------------------
; sprite mappings
; ------------------------------------------------------------------------
Obj9D_Obj98_MapUnc_37D96: BINCLUDE "mappings/sprite/obj9D.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 9E - Crawlton (snake badnik) from MCZ
; ----------------------------------------------------------------------------
; Sprite_37E16:
Obj9E:
moveq #0,d0
move.b objoff_3B(a0),d0
move.w Obj9E_Index(pc,d0.w),d1
jmp Obj9E_Index(pc,d1.w)
; ===========================================================================
; off_37E24:
Obj9E_Index: offsetTable
offsetTableEntry.w Obj9E_Init ; 0
offsetTableEntry.w loc_37E42 ; 2
offsetTableEntry.w loc_37E98 ; 4
offsetTableEntry.w loc_37EB6 ; 6
offsetTableEntry.w loc_37ED4 ; 8
offsetTableEntry.w loc_37EFC ; $A
; ===========================================================================
; loc_37E30:
Obj9E_Init:
bsr.w LoadSubObject
move.b #$80,y_radius(a0)
addq.b #2,objoff_3B(a0)
bra.w loc_37F74
; ===========================================================================
loc_37E42:
bsr.w Obj_GetOrientationToPlayer
move.w d2,d4
move.w d3,d5
addi.w #$80,d2
cmpi.w #$100,d2
bhs.s +
addi.w #$80,d3
cmpi.w #$100,d3
blo.s loc_37E62
+
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_37E62:
addq.b #2,objoff_3B(a0)
move.b #$10,objoff_3A(a0)
bclr #0,render_flags(a0)
tst.w d0
beq.s +
bset #0,render_flags(a0)
+
neg.w d4
lsl.w #3,d4
andi.w #$FF00,d4
move.w d4,x_vel(a0)
neg.w d5
lsl.w #3,d5
andi.w #$FF00,d5
move.w d5,y_vel(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_37E98:
subq.b #1,objoff_3A(a0)
bmi.s +
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ---------------------------------------------------------------------------
+
addq.b #2,objoff_3B(a0)
move.b #8,objoff_39(a0)
move.b #$1C,objoff_3A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_37EB6:
subq.b #1,objoff_3A(a0)
beq.s +
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ---------------------------------------------------------------------------
+
move.b objoff_39(a0),objoff_3B(a0)
move.b #$20,objoff_3A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_37ED4:
subq.b #1,objoff_3A(a0)
beq.s +
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ---------------------------------------------------------------------------
+
move.b #6,objoff_3B(a0)
move.b #2,objoff_39(a0)
move.b #$1C,objoff_3A(a0)
neg.w x_vel(a0)
neg.w y_vel(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_37EFC:
movea.w parent(a0),a1 ; a1=object
cmpi.b #ObjID_Crawlton,id(a1)
bne.w JmpTo65_DeleteObject
bclr #0,render_flags(a0)
btst #0,render_flags(a1)
beq.s +
bset #0,render_flags(a0)
+
move.b #$80,objoff_14(a0)
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
cmpi.b #6,objoff_3B(a1)
bne.s loc_37F6C
move.w x_vel(a1),d2
asr.w #8,d2
move.w y_vel(a1),d3
asr.w #8,d3
lea sub2_x_pos(a0),a2
move.b objoff_3A(a1),d0
moveq #$18,d1
moveq #6,d6
- move.w (a2),d4 ; sub?_x_pos
move.w 2(a2),d5 ; sub?_y_pos
cmp.b d1,d0
bhs.s +
add.w d2,d4
add.w d3,d5
+
move.w d4,(a2)+ ; sub?_x_pos
move.w d5,(a2)+ ; sub?_y_pos
subi_.b #4,d1
bcs.s loc_37F6C
addq.w #next_subspr-4,a2
dbf d6,-
loc_37F6C:
move.w #$280,d0
jmpto (DisplaySprite3).l, JmpTo5_DisplaySprite3
; ===========================================================================
loc_37F74:
jsrto (SingleObjLoad).l, JmpTo19_SingleObjLoad
bne.s + ; rts
_move.b #ObjID_Crawlton,id(a1) ; load obj9E
move.b render_flags(a0),render_flags(a1)
bset #6,render_flags(a1)
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
move.b #$A,objoff_3B(a1)
move.b #0,mainspr_mapframe(a1)
move.b #$80,mainspr_width(a1)
move.b #7,mainspr_childsprites(a1)
move.w a0,parent(a1)
move.w x_pos(a0),d2
move.w d2,x_pos(a1)
move.w y_pos(a0),d3
move.w d3,y_pos(a1)
move.b #$80,objoff_14(a1)
bset #4,render_flags(a1)
lea sub2_x_pos(a1),a2
moveq #6,d6
- move.w d2,(a2)+ ; sub?_x_pos
move.w d3,(a2)+ ; sub?_y_pos
move.w #2,(a2)+ ; sub?_mapframe
addi.w #$10,d1
dbf d6,-
+
rts
; ===========================================================================
; off_37FE8:
Obj9E_SubObjData:
subObjData Obj9E_MapUnc_37FF2,make_art_tile(ArtTile_ArtNem_Crawlton,1,0),4,4,$80,$B
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
Obj9E_MapUnc_37FF2: BINCLUDE "mappings/sprite/obj9E.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 9F - Shellcraker (crab badnik) from MTZ
; ----------------------------------------------------------------------------
; Sprite_3800C:
Obj9F:
moveq #0,d0
move.b routine(a0),d0
move.w Obj9F_Index(pc,d0.w),d1
jmp Obj9F_Index(pc,d1.w)
; ===========================================================================
; off_3801A:
Obj9F_Index: offsetTable
offsetTableEntry.w Obj9F_Init ; 0
offsetTableEntry.w loc_3804E ; 2
offsetTableEntry.w loc_380C4 ; 4
offsetTableEntry.w loc_380FC ; 6
; ===========================================================================
; loc_38022:
Obj9F_Init:
bsr.w LoadSubObject
btst #0,render_flags(a0)
beq.s +
bset #0,status(a0)
+
move.w #-$40,x_vel(a0)
move.b #$C,y_radius(a0)
move.b #$18,x_radius(a0)
move.w #$140,objoff_2A(a0)
rts
; ===========================================================================
loc_3804E:
bsr.w Obj_GetOrientationToPlayer
tst.w d0
beq.s loc_3805E
btst #0,render_flags(a0)
beq.s loc_38068
loc_3805E:
addi.w #$60,d2
cmpi.w #$C0,d2
blo.s loc_380AE
loc_38068:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jsr (ObjCheckFloorDist).l
cmpi.w #-8,d1
blt.s loc_38096
cmpi.w #$C,d1
bge.s loc_38096
add.w d1,y_pos(a0)
subq.w #1,objoff_2A(a0)
bmi.s loc_3809A
lea (Ani_obj9F).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38096:
neg.w x_vel(a0)
loc_3809A:
addq.b #2,routine(a0)
move.b #0,mapping_frame(a0)
move.w #$3B,objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_380AE:
move.b #6,routine(a0)
move.b #0,mapping_frame(a0)
move.w #8,objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_380C4:
tst.b render_flags(a0)
bpl.s loc_380E4
bsr.w Obj_GetOrientationToPlayer
tst.w d0
beq.s loc_380DA
btst #0,render_flags(a0)
beq.s loc_380E4
loc_380DA:
addi.w #$60,d2
cmpi.w #$C0,d2
blo.s loc_380AE
loc_380E4:
subq.w #1,objoff_2A(a0)
bmi.s loc_380EE
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_380EE:
subq.b #2,routine(a0)
move.w #$140,objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_380FC:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3810E(pc,d0.w),d1
jsr off_3810E(pc,d1.w)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
off_3810E: offsetTable
offsetTableEntry.w loc_38114 ; 0
offsetTableEntry.w loc_3812A ; 2
offsetTableEntry.w loc_3813E ; 4
; ===========================================================================
loc_38114:
subq.w #1,objoff_2A(a0)
bmi.s loc_3811C
rts
; ===========================================================================
loc_3811C:
addq.b #2,routine_secondary(a0)
move.b #3,mapping_frame(a0)
bra.w loc_38292
; ===========================================================================
loc_3812A:
tst.b objoff_2C(a0)
bne.s loc_38132
rts
; ===========================================================================
loc_38132:
addq.b #2,routine_secondary(a0)
move.w #$20,objoff_2A(a0)
rts
; ===========================================================================
loc_3813E:
subq.w #1,objoff_2A(a0)
bmi.s loc_38146
rts
; ===========================================================================
loc_38146:
clr.b routine_secondary(a0)
clr.b objoff_2C(a0)
move.b #2,routine(a0)
move.w #$140,objoff_2A(a0)
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; Object A0 - Shellcracker's claw from MTZ
; ----------------------------------------------------------------------------
; Sprite_3815C:
ObjA0:
moveq #0,d0
move.b routine(a0),d0
move.w ObjA0_Index(pc,d0.w),d1
jmp ObjA0_Index(pc,d1.w)
; ===========================================================================
; off_3816A:
ObjA0_Index: offsetTable
offsetTableEntry.w ObjA0_Init ; 0
offsetTableEntry.w loc_381AC ; 2
offsetTableEntry.w loc_38280 ; 4
; ===========================================================================
; loc_38170:
ObjA0_Init:
bsr.w LoadSubObject
movea.w objoff_2C(a0),a1 ; a1=object
move.b render_flags(a1),d0
andi.b #1,d0
or.b d0,render_flags(a0)
move.w objoff_2E(a0),d0
beq.s loc_38198
move.b #4,mapping_frame(a0)
addq.w #6,x_pos(a0)
addq.w #6,y_pos(a0)
loc_38198:
lsr.w #1,d0
move.b byte_381A4(pc,d0.w),objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
byte_381A4:
dc.b 0 ; 0
dc.b 3 ; 1
dc.b 5 ; 2
dc.b 7 ; 3
dc.b 9 ; 4
dc.b $B ; 5
dc.b $D ; 6
dc.b $F ; 7
; ===========================================================================
loc_381AC:
movea.w objoff_2C(a0),a1 ; a1=object
cmpi.b #ObjID_Shellcracker,id(a1)
bne.s loc_381D0
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_381C8(pc,d0.w),d1
jsr off_381C8(pc,d1.w)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
off_381C8: offsetTable
offsetTableEntry.w loc_381E0 ; 0
offsetTableEntry.w loc_3822A ; 2
offsetTableEntry.w loc_38244 ; 4
offsetTableEntry.w loc_38258 ; 6
; ===========================================================================
loc_381D0:
move.b #4,routine(a0)
move.w #$40,objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_381E0:
subq.b #1,objoff_2A(a0)
beq.s loc_381EA
bmi.s loc_381EA
rts
; ===========================================================================
loc_381EA:
addq.b #2,routine_secondary(a0)
move.w objoff_2E(a0),d0
cmpi.w #$E,d0
bhs.s loc_3821A
move.w #-$400,d2
btst #0,render_flags(a0)
beq.s loc_38206
neg.w d2
loc_38206:
move.w d2,x_vel(a0)
lsr.w #1,d0
move.b byte_38222(pc,d0.w),d1
move.b d1,objoff_2A(a0)
move.b d1,objoff_2B(a0)
rts
; ===========================================================================
loc_3821A:
move.w #$B,objoff_2A(a0)
rts
; ===========================================================================
byte_38222:
dc.b $D ; 0
dc.b $C ; 1
dc.b $A ; 2
dc.b 8 ; 3
dc.b 6 ; 4
dc.b 4 ; 5
dc.b 2 ; 6
dc.b 0 ; 7
; ===========================================================================
loc_3822A:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
subq.b #1,objoff_2A(a0)
beq.s loc_38238
bmi.s loc_38238
rts
; ===========================================================================
loc_38238:
addq.b #2,routine_secondary(a0)
move.b #8,objoff_2A(a0)
rts
; ===========================================================================
loc_38244:
subq.b #1,objoff_2A(a0)
beq.s loc_3824E
bmi.s loc_3824E
rts
; ===========================================================================
loc_3824E:
addq.b #2,routine_secondary(a0)
neg.w x_vel(a0)
rts
; ===========================================================================
loc_38258:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
subq.b #1,objoff_2B(a0)
beq.s loc_38266
bmi.s loc_38266
rts
; ===========================================================================
loc_38266:
tst.w objoff_2E(a0)
bne.s loc_3827A
movea.w objoff_2C(a0),a1 ; a1=object
move.b #0,mapping_frame(a1)
st objoff_2C(a1)
loc_3827A:
addq.w #4,sp
bra.w JmpTo65_DeleteObject
; ===========================================================================
loc_38280:
jsrto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall
subi_.w #1,objoff_2A(a0)
bmi.w JmpTo65_DeleteObject
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38292:
moveq #0,d1
moveq #7,d6
loc_38296:
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s return_382EE
_move.b #ObjID_ShellcrackerClaw,id(a1) ; load objA0
move.b #$26,subtype(a1) ; <== ObjA0_SubObjData
move.b #5,mapping_frame(a1)
move.b #4,priority(a1)
move.w a0,objoff_2C(a1)
move.w d1,objoff_2E(a1)
move.w x_pos(a0),x_pos(a1)
move.w #-$14,d2
btst #0,render_flags(a0)
beq.s loc_382D8
neg.w d2
tst.w d1
beq.s loc_382D8
subi.w #$C,d2
loc_382D8:
add.w d2,x_pos(a1)
move.w y_pos(a0),y_pos(a1)
subi_.w #8,y_pos(a1)
addq.w #2,d1
dbf d6,loc_38296
return_382EE:
rts
; ===========================================================================
; off_382F0:
Obj9F_SubObjData:
subObjData Obj9F_MapUnc_38314,make_art_tile(ArtTile_ArtNem_Crabmeat,0,0),4,5,$18,$A
; off_382FA:
ObjA0_SubObjData:
subObjData Obj9F_MapUnc_38314,make_art_tile(ArtTile_ArtNem_Crabmeat,0,0),4,4,$C,$9A
; animation script
; off_38304:
Ani_obj9F: offsetTable
offsetTableEntry.w byte_38308 ; 0
offsetTableEntry.w byte_3830E ; 1
byte_38308: dc.b $E, 0, 1, 2,$FF, 0
byte_3830E: dc.b $E, 0, 2, 1,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj9F_MapUnc_38314: BINCLUDE "mappings/sprite/objA0.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object A1 - Slicer (praying mantis dude) from MTZ
; ----------------------------------------------------------------------------
; Sprite_383B4:
ObjA1:
moveq #0,d0
move.b routine(a0),d0
move.w ObjA1_Index(pc,d0.w),d1
jmp ObjA1_Index(pc,d1.w)
; ===========================================================================
; off_383C2:
ObjA1_Index: offsetTable
offsetTableEntry.w ObjA1_Init ; 0
offsetTableEntry.w ObjA1_Main ; 2
offsetTableEntry.w loc_38466 ; 4
offsetTableEntry.w loc_38482 ; 6
offsetTableEntry.w BranchTo5_JmpTo39_MarkObjGone ; 8
; ===========================================================================
; loc_383CC:
ObjA1_Init:
bsr.w LoadSubObject
move.w #-$40,d0
btst #0,render_flags(a0)
beq.s loc_383DE
neg.w d0
loc_383DE:
move.w d0,x_vel(a0)
move.b #$10,y_radius(a0)
move.b #$10,x_radius(a0)
rts
; ===========================================================================
ObjA1_Main:
tst.b render_flags(a0)
bpl.s loc_3841C
bsr.w Obj_GetOrientationToPlayer
btst #0,render_flags(a0)
beq.s loc_38404
subq.w #2,d0
loc_38404:
tst.w d0
bne.s loc_3841C
addi.w #$80,d2
cmpi.w #$100,d2
bhs.s loc_3841C
addi.w #$40,d3
cmpi.w #$80,d3
blo.s loc_38452
loc_3841C:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jsr (ObjCheckFloorDist).l
cmpi.w #-8,d1
blt.s loc_38444
cmpi.w #$C,d1
bge.s loc_38444
add.w d1,y_pos(a0)
lea (Ani_objA1).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38444:
addq.b #2,routine(a0)
move.b #$3B,objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38452:
addq.b #4,routine(a0)
move.b #3,mapping_frame(a0)
move.b #8,objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38466:
subq.b #1,objoff_2A(a0)
bmi.s loc_38470
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38470:
subq.b #2,routine(a0)
neg.w x_vel(a0)
bchg #0,status(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38482:
subq.b #1,objoff_2A(a0)
bmi.s loc_3848C
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3848C:
addq.b #2,routine(a0)
move.b #4,mapping_frame(a0)
bsr.w ObjA1_LoadPincers
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
BranchTo5_JmpTo39_MarkObjGone
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; ----------------------------------------------------------------------------
; Object A2 - Slicer's pincers from MTZ
; ----------------------------------------------------------------------------
; Sprite_384A2:
ObjA2:
moveq #0,d0
move.b routine(a0),d0
move.w ObjA2_Index(pc,d0.w),d1
jmp ObjA2_Index(pc,d1.w)
; ===========================================================================
; off_384B0:
ObjA2_Index: offsetTable
offsetTableEntry.w ObjA2_Init ; 0
offsetTableEntry.w ObjA2_Main ; 2
offsetTableEntry.w ObjA2_Main2 ; 4
; ===========================================================================
; loc_384B6:
ObjA2_Init:
bsr.w LoadSubObject
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
ObjA2_Main:
tst.b render_flags(a0)
bpl.w JmpTo65_DeleteObject
subq.w #1,objoff_2A(a0)
bmi.s loc_3851A
movea.w objoff_2C(a0),a1 ; a1=object
cmpi.b #ObjID_Slicer,(a1)
bne.s loc_3851A
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_384F6(pc,d0.w),d1
jsr off_384F6(pc,d1.w)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (Ani_objA2).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
off_384F6: offsetTable
offsetTableEntry.w +
; ===========================================================================
+
bsr.w Obj_GetOrientationToPlayer
move.w ObjA2_acceleration(pc,d0.w),d2
add.w d2,x_vel(a0)
move.w ObjA2_acceleration(pc,d1.w),d2
add.w d2,y_vel(a0)
move.w #$200,d0
move.w d0,d1
bra.w Obj_CapSpeed
; ===========================================================================
ObjA2_acceleration: dc.w -$10, $10
; ===========================================================================
loc_3851A:
addq.b #2,routine(a0)
move.w #$60,objoff_2A(a0)
ObjA2_Main2:
subq.w #1,objoff_2A(a0)
bmi.w JmpTo65_DeleteObject
jsrto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall
lea (Ani_objA2).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
ObjA1_LoadPincers:
lea objoff_3C(a0),a2 ; a2=object
moveq #0,d1
moveq #1,d6
loc_38546:
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s return_385BA
_move.b #ObjID_SlicerPincers,id(a1) ; load objA2
move.b #$2A,subtype(a1) ; <== ObjA2_SubObjData
move.b render_flags(a0),render_flags(a1)
move.b #5,mapping_frame(a1)
move.b #4,priority(a1)
move.w #$78,objoff_2A(a1)
move.w a0,objoff_2C(a1)
move.w a1,(a2)+
move.w #-$200,d0
btst #0,render_flags(a1)
beq.s loc_3858A
neg.w d0
bset #0,status(a1)
loc_3858A:
move.w d0,x_vel(a1)
lea ObjA1_Pincer_Offsets(pc,d1.w),a3
move.b (a3)+,d0
ext.w d0
btst #0,render_flags(a1)
beq.s loc_385A0
neg.w d0
loc_385A0:
add.w x_pos(a0),d0
move.w d0,x_pos(a1)
move.b (a3)+,d0
ext.w d0
add.w y_pos(a0),d0
move.w d0,y_pos(a1)
addq.w #2,d1
dbf d6,loc_38546
return_385BA:
rts
; ===========================================================================
ObjA1_Pincer_Offsets:
dc.b 6, 0 ; 0
dc.b -$10, 0 ; 3
; off_385C0
ObjA1_SubObjData:
subObjData ObjA1_MapUnc_385E2,make_art_tile(ArtTile_ArtNem_MtzMantis,1,0),4,5,$10,6
; off_385CA:
ObjA2_SubObjData:
subObjData ObjA1_MapUnc_385E2,make_art_tile(ArtTile_ArtNem_MtzMantis,1,0),4,4,$10,$9A
; animation script
; off_385D4:
Ani_objA1: offsetTable
offsetTableEntry.w + ; 0
+ dc.b $13, 0, 2,$FF
even
; animation script
; off_385DA:
Ani_objA2: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 3, 5, 6, 7, 8,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjA1_MapUnc_385E2: BINCLUDE "mappings/sprite/objA2.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object A3 - Flasher (firefly/glowbug badnik) from MCZ
; ----------------------------------------------------------------------------
; Sprite_3873E:
ObjA3:
moveq #0,d0
move.b routine(a0),d0
move.w ObjA3_Index(pc,d0.w),d1
jmp ObjA3_Index(pc,d1.w)
; ===========================================================================
; off_3874C:
ObjA3_Index: offsetTable
offsetTableEntry.w loc_3875A ; 0
offsetTableEntry.w loc_38766 ; 2
offsetTableEntry.w loc_38794 ; 4
offsetTableEntry.w loc_38832 ; 6
offsetTableEntry.w loc_3885C ; 8
offsetTableEntry.w loc_38880 ; $A
offsetTableEntry.w loc_3888E ; $C
; ===========================================================================
loc_3875A:
bsr.w LoadSubObject
move.w #$40,objoff_2A(a0)
rts
; ===========================================================================
loc_38766:
subq.w #1,objoff_2A(a0)
bmi.s loc_38770
jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1
; ===========================================================================
loc_38770:
addq.b #2,routine(a0)
move.w #-$100,x_vel(a0)
move.w #$40,y_vel(a0)
move.w #2,objoff_2E(a0)
clr.w objoff_2A(a0)
move.w #$80,objoff_30(a0)
jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1
; ===========================================================================
loc_38794:
subq.w #1,objoff_30(a0)
bmi.s loc_387FC
move.w objoff_2A(a0),d0
bmi.w JmpTo65_DeleteObject
bclr #0,render_flags(a0)
bclr #0,status(a0)
tst.w x_vel(a0)
bmi.s loc_387C0
bset #0,render_flags(a0)
bset #0,status(a0)
loc_387C0:
addq.w #1,d0
move.w d0,objoff_2A(a0)
move.w objoff_2C(a0),d1
move.w word_38810(pc,d1.w),d2
cmp.w d2,d0
blo.s loc_387EC
addq.w #2,d1
move.w d1,objoff_2C(a0)
lea byte_38820(pc,d1.w),a1
tst.b (a1)+
beq.s loc_387E4
neg.w objoff_2E(a0)
loc_387E4:
tst.b (a1)+
beq.s loc_387EC
neg.w y_vel(a0)
loc_387EC:
move.w objoff_2E(a0),d0
add.w d0,x_vel(a0)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1
; ===========================================================================
loc_387FC:
addq.b #2,routine(a0)
move.w #$80,objoff_30(a0)
ori.b #$80,collision_flags(a0)
jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1
; ===========================================================================
word_38810:
dc.w $100
dc.w $1A0 ; 1
dc.w $208 ; 2
dc.w $285 ; 3
dc.w $300 ; 4
dc.w $340 ; 5
dc.w $390 ; 6
dc.w $440 ; 7
byte_38820:
dc.b $F0
dc.b 0 ; 1
dc.b 1 ; 2
dc.b 1 ; 3
dc.b 0 ; 4
dc.b 1 ; 5
dc.b 1 ; 6
dc.b 1 ; 7
dc.b 0 ; 8
dc.b 1 ; 9
dc.b 0 ; 10
dc.b 1 ; 11
dc.b 1 ; 12
dc.b 0 ; 13
dc.b 0 ; 14
dc.b 1 ; 15
dc.b 0 ; 16
dc.b 1 ; 17
; ===========================================================================
loc_38832:
move.b routine(a0),d2
lea (Ani_objA3_a).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
cmp.b routine(a0),d2
bne.s loc_3884A
jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1
; ===========================================================================
loc_3884A:
clr.l mapping_frame(a0)
clr.w anim_frame_duration(a0)
move.b #3,mapping_frame(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3885C:
subq.w #1,objoff_30(a0)
bmi.s loc_38870
lea (Ani_objA3_b).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1
; ===========================================================================
loc_38870:
addq.b #2,routine(a0)
clr.l mapping_frame(a0)
clr.w anim_frame_duration(a0)
jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1
; ===========================================================================
loc_38880:
lea (Ani_objA3_c).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1
; ===========================================================================
loc_3888E:
move.b #4,routine(a0)
move.w #$80,objoff_30(a0)
andi.b #$7F,collision_flags(a0)
clr.l mapping_frame(a0)
clr.w anim_frame_duration(a0)
jmpto (MarkObjGone_P1).l, JmpTo2_MarkObjGone_P1
; ===========================================================================
; off_388AC:
ObjA3_SubObjData:
subObjData ObjA3_MapUnc_388F0,make_art_tile(ArtTile_ArtNem_Flasher,0,1),4,4,$10,6
; animation script
; off_388B6:
Ani_objA3_a: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1
dc.b 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 2, 3, 4, $FC
even
; animation script
; off_388DA:
Ani_objA3_b: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 0, 2, 0, 3, 0, 4, 0, 3, 0,$FF
even
; animation script
; off_388E6:
Ani_objA3_c: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 3, 4, 3, 2, 1, 0,$FC
even
; -------------------------------------------------------------------------------
; sprite mappings
; -------------------------------------------------------------------------------
ObjA3_MapUnc_388F0: BINCLUDE "mappings/sprite/objA3.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object A4 - Asteron (exploding starfish badnik) from MTZ
; ----------------------------------------------------------------------------
; Sprite_3899C:
ObjA4:
moveq #0,d0
move.b routine(a0),d0
move.w ObjA4_Index(pc,d0.w),d1
jmp ObjA4_Index(pc,d1.w)
; ===========================================================================
; off_389AA:
ObjA4_Index: offsetTable
offsetTableEntry.w ObjA4_Init ; 0
offsetTableEntry.w loc_389B6 ; 2
offsetTableEntry.w loc_389DA ; 4
offsetTableEntry.w loc_38A2C ; 6
; ===========================================================================
; BranchTo3_LoadSubObject
ObjA4_Init:
bra.w LoadSubObject
; ===========================================================================
loc_389B6:
bsr.w Obj_GetOrientationToPlayer
addi.w #$60,d2
cmpi.w #$C0,d2
bhs.s BranchTo6_JmpTo39_MarkObjGone
addi.w #$40,d3
cmpi.w #$80,d3
blo.s loc_389D2
BranchTo6_JmpTo39_MarkObjGone
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_389D2:
addq.b #2,routine(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_389DA:
bsr.w Obj_GetOrientationToPlayer
abs.w d2
cmpi.w #$10,d2
blo.s loc_389FA
cmpi.w #$60,d2
bhs.s loc_389FA
move.w word_38A1A(pc,d0.w),x_vel(a0)
bsr.w loc_38A1E
loc_389FA:
abs.w d3
cmpi.w #$10,d3
blo.s BranchTo7_JmpTo39_MarkObjGone
cmpi.w #$60,d3
bhs.s BranchTo7_JmpTo39_MarkObjGone
move.w word_38A1A(pc,d1.w),y_vel(a0)
bsr.w loc_38A1E
BranchTo7_JmpTo39_MarkObjGone
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
word_38A1A:
dc.w -$40 ; 0
dc.w $40 ; 1
; ===========================================================================
loc_38A1E:
move.b #6,routine(a0)
move.b #$40,objoff_2A(a0)
rts
; ===========================================================================
loc_38A2C:
subq.b #1,objoff_2A(a0)
bmi.s loc_38A44
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (Ani_objA4).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38A44:
_move.b #ObjID_Explosion,id(a0) ; load 0bj27
move.b #2,routine(a0)
bsr.w loc_38A58
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38A58:
move.b #$30,d2
moveq #4,d6
lea (word_38A68).l,a2
bra.w Obj_CreateProjectiles
; ===========================================================================
word_38A68:
dc.w $F8
dc.w $FC
dc.w $200
dc.w $8FC
dc.w $3FF
dc.w $301
dc.w $808
dc.w $303
dc.w $401
dc.w $F808
dc.w $FD03
dc.w $400
dc.w $F8FC
dc.w $FDFF
dc.w $300
; off_38A86:
ObjA4_SubObjData:
subObjData ObjA4_Obj98_MapUnc_38A96,make_art_tile(ArtTile_ArtNem_MtzSupernova,0,1),4,4,$10,$B
; animation script
; off_38A90:
Ani_objA4: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 1, 0, 1,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjA4_Obj98_MapUnc_38A96: BINCLUDE "mappings/sprite/objA4.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object A5 - Spiny (crawling badnik) from CPZ
; ----------------------------------------------------------------------------
; Sprite_38AEA:
ObjA5:
moveq #0,d0
move.b routine(a0),d0
move.w ObjA5_Index(pc,d0.w),d1
jmp ObjA5_Index(pc,d1.w)
; ===========================================================================
; off_38AF8:
ObjA5_Index: offsetTable
offsetTableEntry.w ObjA5_Init ; 0
offsetTableEntry.w loc_38B10 ; 2
offsetTableEntry.w loc_38B62 ; 4
; ===========================================================================
; loc_38AFE:
ObjA5_Init:
bsr.w LoadSubObject
move.w #-$40,x_vel(a0)
move.w #$80,objoff_2A(a0)
rts
; ===========================================================================
loc_38B10:
tst.b objoff_2B(a0)
beq.s loc_38B1E
subq.b #1,objoff_2B(a0)
bra.w loc_38B2C
; ===========================================================================
loc_38B1E:
bsr.w Obj_GetOrientationToPlayer
addi.w #$60,d2
cmpi.w #$C0,d2
blo.s loc_38B4E
loc_38B2C:
subq.b #1,objoff_2A(a0)
bne.s loc_38B3C
move.w #$80,objoff_2A(a0)
neg.w x_vel(a0)
loc_38B3C:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (Ani_objA5).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38B4E:
addq.b #2,routine(a0)
move.b #$28,objoff_2B(a0)
move.b #2,mapping_frame(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38B62:
subq.b #1,objoff_2B(a0)
bmi.s loc_38B78
cmpi.b #$14,objoff_2B(a0)
bne.s +
bsr.w loc_38C22
+
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38B78:
subq.b #2,routine(a0)
move.b #$40,objoff_2B(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; ----------------------------------------------------------------------------
; Object A6 - Spiny (on wall) from CPZ
; ----------------------------------------------------------------------------
; Sprite_38B86:
ObjA6:
moveq #0,d0
move.b routine(a0),d0
move.w ObjA6_Index(pc,d0.w),d1
jmp ObjA6_Index(pc,d1.w)
; ===========================================================================
; off_38B94:
ObjA6_Index: offsetTable
offsetTableEntry.w ObjA6_Init ; 0
offsetTableEntry.w loc_38BAC ; 2
offsetTableEntry.w loc_38BFE ; 4
; ===========================================================================
; loc_38B9A:
ObjA6_Init:
bsr.w LoadSubObject
move.w #-$40,y_vel(a0)
move.w #$80,objoff_2A(a0)
rts
; ===========================================================================
loc_38BAC:
tst.b objoff_2B(a0)
beq.s loc_38BBA
subq.b #1,objoff_2B(a0)
bra.w loc_38BC8
; ===========================================================================
loc_38BBA:
bsr.w Obj_GetOrientationToPlayer
addi.w #$60,d2
cmpi.w #$C0,d2
blo.s loc_38BEA
loc_38BC8:
subq.b #1,objoff_2A(a0)
bne.s +
move.w #$80,objoff_2A(a0)
neg.w y_vel(a0)
+
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (Ani_objA6).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38BEA:
addq.b #2,routine(a0)
move.b #$28,objoff_2B(a0)
move.b #5,mapping_frame(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38BFE:
subq.b #1,objoff_2B(a0)
bmi.s loc_38C14
cmpi.b #$14,objoff_2B(a0)
bne.s +
bsr.w loc_38C6E
+
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38C14:
subq.b #2,routine(a0)
move.b #$40,objoff_2B(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_38C22:
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s ++ ; rts
_move.b #ObjID_Projectile,id(a1) ; load obj98
move.b #6,mapping_frame(a1)
move.b #$34,subtype(a1) ; <== ObjA6_SubObjData
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w #-$300,y_vel(a1)
move.w #$100,d1
lea (MainCharacter).w,a2 ; a2=character
move.w x_pos(a0),d0
cmp.w x_pos(a2),d0
blo.s +
neg.w d1
+
move.w d1,x_vel(a1)
lea_ Obj98_SpinyShotFall,a2
move.l a2,objoff_2A(a1)
+
rts
; ===========================================================================
loc_38C6E:
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s ++ ; rts
_move.b #ObjID_Projectile,id(a1) ; load obj98
move.b #6,mapping_frame(a1)
move.b #$34,subtype(a1) ; <== ObjA6_SubObjData
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w #$300,d1
btst #0,render_flags(a0)
beq.s +
neg.w d1
+
move.w d1,x_vel(a1)
lea_ Obj98_SpinyShotFall,a2
move.l a2,objoff_2A(a1)
+
rts
; ===========================================================================
; off_38CAE:
ObjA5_SubObjData:
subObjData ObjA5_ObjA6_Obj98_MapUnc_38CCA,make_art_tile(ArtTile_ArtNem_Spiny,1,0),4,4,8,$B
; animation scripts
; off_38CB8
Ani_objA5: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 9, 0, 1,$FF
even
; off_38CBE
Ani_objA6: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 9, 3, 4,$FF
even
; off_38CC4
Ani_SpinyShot: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 3, 6, 7,$FF
even
; ------------------------------------------------------------------------------
; sprite mappings
; ------------------------------------------------------------------------------
ObjA5_ObjA6_Obj98_MapUnc_38CCA: BINCLUDE "mappings/sprite/objA6.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object A7 - Grabber (spider badnik) from CPZ
; ----------------------------------------------------------------------------
; Sprite_38DBA:
ObjA7:
moveq #0,d0
move.b routine(a0),d0
move.w ObjA7_Index(pc,d0.w),d1
jmp ObjA7_Index(pc,d1.w)
; ===========================================================================
; off_38DC8:
ObjA7_Index: offsetTable
offsetTableEntry.w ObjA7_Init ; 0
offsetTableEntry.w ObjA7_Main ; 2
; ===========================================================================
; loc_38DCC:
ObjA7_Init:
bsr.w LoadSubObject
move.w #-$40,d0
btst #0,render_flags(a0)
beq.s +
neg.w d0
+
move.w d0,x_vel(a0)
move.w #$FF,objoff_2A(a0)
move.b #2,objoff_2D(a0)
lea (word_391E0).l,a2
bsr.w LoadChildObject
lea (word_391E4).l,a2
bsr.w LoadChildObject
lea (word_391E8).l,a2
bra.w LoadChildObject
; ===========================================================================
; loc_38E0C:
ObjA7_Main:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_38E46(pc,d0.w),d1
jsr off_38E46(pc,d1.w)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
moveq #0,d0
moveq #$10,d1
movea.w objoff_3C(a0),a1 ; a1=object
bsr.w Obj_AlignChildXY
movea.w parent(a0),a1 ; a1=object
move.w x_pos(a0),x_pos(a1)
movea.w objoff_3A(a0),a1 ; a1=object
move.w x_pos(a0),x_pos(a1)
lea objoff_3A(a0),a2 ; a2=object
bra.w loc_39182
; ===========================================================================
off_38E46: offsetTable
offsetTableEntry.w loc_38E52 ; 0
offsetTableEntry.w loc_38E9A ; 2
offsetTableEntry.w loc_38EB4 ; 4
offsetTableEntry.w loc_38F3E ; 6
offsetTableEntry.w loc_38F58 ; 8
offsetTableEntry.w BranchTo_ObjA7_CheckExplode ; $A
; ===========================================================================
loc_38E52:
bsr.w Obj_GetOrientationToPlayer
addi.w #$40,d2
cmpi.w #$80,d2
bhs.s loc_38E66
cmpi.w #-$80,d3
bhi.s loc_38E84
loc_38E66:
subq.w #1,objoff_2A(a0)
bpl.s return_38E82
move.w #$FF,objoff_2A(a0)
neg.w x_vel(a0)
bchg #0,render_flags(a0)
bchg #0,status(a0)
return_38E82:
rts
; ===========================================================================
loc_38E84:
addq.b #2,routine_secondary(a0)
move.w x_vel(a0),objoff_2E(a0)
clr.w x_vel(a0)
move.b #$10,objoff_2C(a0)
rts
; ===========================================================================
loc_38E9A:
subq.b #1,objoff_2C(a0)
bmi.s loc_38EA2
rts
; ===========================================================================
loc_38EA2:
addq.b #2,routine_secondary(a0)
move.w #$200,y_vel(a0)
move.b #$40,objoff_2C(a0)
rts
; ===========================================================================
loc_38EB4:
tst.b objoff_30(a0)
bne.s ObjA7_GrabCharacter
subq.b #1,objoff_2C(a0)
beq.s loc_38ED6
cmpi.b #$20,objoff_2C(a0)
bne.s loc_38ECC
neg.w y_vel(a0)
loc_38ECC:
lea (Ani_objA7).l,a1
jmpto (AnimateSprite).l, JmpTo25_AnimateSprite
; ===========================================================================
loc_38ED6:
move.b #0,routine_secondary(a0)
clr.w y_vel(a0)
move.w objoff_2E(a0),x_vel(a0)
move.b #0,mapping_frame(a0)
rts
; ===========================================================================
;loc_38EEE:
ObjA7_GrabCharacter:
addq.b #2,routine_secondary(a0)
movea.w objoff_32(a0),a1
move.b #$81,obj_control(a1)
clr.w x_vel(a1)
clr.w y_vel(a1)
move.b #AniIDSonAni_Float,anim(a1)
move.b #1,mapping_frame(a0)
tst.w y_vel(a0)
bmi.s loc_38F2A
neg.w y_vel(a0)
move.b objoff_2C(a0),d0
subi.b #$40,d0
neg.w d0
addq.b #1,d0
move.b d0,objoff_2C(a0)
loc_38F2A:
move.b #1,objoff_2A(a0)
move.b #$10,objoff_2B(a0)
move.b #$20,objoff_37(a0)
rts
; ===========================================================================
loc_38F3E:
bsr.w ObjA7_CheckExplode
bsr.w loc_390BC
subq.b #1,objoff_2C(a0)
beq.s loc_38F4E
rts
; ===========================================================================
loc_38F4E:
addq.b #2,routine_secondary(a0)
clr.w y_vel(a0)
rts
; ===========================================================================
loc_38F58:
bsr.w ObjA7_CheckExplode
bra.w loc_390BC
; ===========================================================================
rts
; ===========================================================================
BranchTo_ObjA7_CheckExplode
bra.w ObjA7_CheckExplode
; ===========================================================================
; ----------------------------------------------------------------------------
; Object A8 - Grabber's legs from CPZ
; ----------------------------------------------------------------------------
; Sprite_38F66:
ObjA8:
moveq #0,d0
move.b routine(a0),d0
move.w ObjA8_Index(pc,d0.w),d1
jmp ObjA8_Index(pc,d1.w)
; ===========================================================================
; off_38F74:
ObjA8_Index: offsetTable
offsetTableEntry.w ObjA8_Init ; 0
offsetTableEntry.w loc_38F88 ; 2
offsetTableEntry.w loc_38FE8 ; 4
offsetTableEntry.w loc_39022 ; 6
; ===========================================================================
; loc_38F7C:
ObjA8_Init:
bsr.w LoadSubObject
move.b #3,mapping_frame(a0)
rts
; ===========================================================================
loc_38F88:
movea.w objoff_2C(a0),a1 ; a1=object
cmpi.b #ObjID_Grabber,id(a1)
bne.w JmpTo65_DeleteObject
bsr.w loc_367AA
movea.w objoff_2C(a0),a1 ; a1=object
move.b mapping_frame(a1),d0
addq.b #3,d0
move.b d0,mapping_frame(a0)
move.b collision_property(a0),d0
beq.s BranchTo2_JmpTo45_DisplaySprite
clr.b collision_property(a0)
cmpi.b #4,routine_secondary(a1)
bne.s BranchTo2_JmpTo45_DisplaySprite
andi.b #3,d0
beq.s BranchTo2_JmpTo45_DisplaySprite
clr.b collision_flags(a0)
addq.b #2,routine(a0)
add.w d0,d0
st objoff_30(a1)
move.w word_38FE0-6(pc,d0.w),objoff_32(a1)
move.w word_38FE0(pc,d0.w),objoff_34(a1)
BranchTo2_JmpTo45_DisplaySprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
dc.w MainCharacter ; -2
dc.w Sidekick ; -1
word_38FE0: dc.w MainCharacter ; 0
dc.w Ctrl_1_Held ; 1
dc.w Ctrl_2_Held ; 2
dc.w Ctrl_1_Held ; 3
; ===========================================================================
loc_38FE8:
movea.w objoff_2C(a0),a1 ; a1=object
move.w objoff_32(a1),d0
beq.s loc_3901A
movea.w d0,a2 ; a2=object
cmpi.b #ObjID_Grabber,id(a1)
bne.s loc_3900A
move.w x_pos(a0),x_pos(a2)
move.w y_pos(a0),y_pos(a2)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3900A:
move.b #0,obj_control(a2)
bset #1,status(a2)
bra.w JmpTo65_DeleteObject
; ===========================================================================
loc_3901A:
addq.b #2,routine(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_39022:
movea.w objoff_2C(a0),a1 ; a1=object
cmpi.b #ObjID_Grabber,id(a1) ; compare to objA7
bne.w JmpTo65_DeleteObject
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; ----------------------------------------------------------------------------
; Object A9 - The little hanger box thing a Grabber's string comes out of
; ----------------------------------------------------------------------------
; Sprite_39032:
ObjA9:
moveq #0,d0
move.b routine(a0),d0
move.w ObjA9_Index(pc,d0.w),d1
jmp ObjA9_Index(pc,d1.w)
; ===========================================================================
; off_39040:
ObjA9_Index: offsetTable
offsetTableEntry.w ObjA9_Init ; 0
offsetTableEntry.w ObjA9_Main ; 2
; ===========================================================================
; loc_39044:
ObjA9_Init:
bsr.w LoadSubObject
move.b #2,mapping_frame(a0)
subi.w #$C,y_pos(a0)
rts
; ===========================================================================
; loc_39056:
ObjA9_Main:
movea.w objoff_2C(a0),a1 ; a1=object
cmpi.b #ObjID_Grabber,id(a1) ; compare to objA7 (grabber badnik)
bne.w JmpTo65_DeleteObject
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; ----------------------------------------------------------------------------
; Object AA - The thin white string a Grabber hangs from
; ----------------------------------------------------------------------------
; Sprite_39066:
ObjAA:
moveq #0,d0
move.b routine(a0),d0
move.w ObjAA_Index(pc,d0.w),d1
jmp ObjAA_Index(pc,d1.w)
; ===========================================================================
; off_39074:
ObjAA_Index: offsetTable
offsetTableEntry.w ObjAA_Init ; 0
offsetTableEntry.w ObjAA_Main ; 2
; ===========================================================================
; loc_39078:
ObjAA_Init:
bsr.w LoadSubObject
subq.w #8,y_pos(a0)
rts
; ===========================================================================
; loc_39082:
ObjAA_Main:
movea.w objoff_2C(a0),a1 ; a1=object
cmpi.b #ObjID_Grabber,id(a1) ; compare to objA7 (grabber badnik)
bne.w JmpTo65_DeleteObject
move.w y_pos(a1),d0
sub.w y_pos(a0),d0
bmi.s +
lsr.w #4,d0
move.b d0,mapping_frame(a0)
+
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; ----------------------------------------------------------------------------
; Object AB - Removed object (unknown, unused)
; ----------------------------------------------------------------------------
; Sprite_390A2:
ObjAB:
moveq #0,d0
move.b routine(a0),d0
move.w ObjAB_Index(pc,d0.w),d1
jmp ObjAB_Index(pc,d1.w)
; ===========================================================================
; off_390B0:
ObjAB_Index: offsetTable
offsetTableEntry.w ObjAB_Init
offsetTableEntry.w ObjAB_Main
; ===========================================================================
; BranchTo4_LoadSubObject
ObjAB_Init:
bra.w LoadSubObject
; ===========================================================================
; BranchTo10_JmpTo39_MarkObjGone
ObjAB_Main:
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; END OF OBJECT AB
; ---------------------------------------------------------------------------
; Some subroutine for the Grabber badnik
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
loc_390BC:
movea.w objoff_34(a0),a1 ; a1=object
move.w (a1),d0
tst.b objoff_31(a0)
beq.s loc_390E6
subq.b #1,objoff_37(a0)
beq.s loc_390FA
move.b objoff_36(a0),d1
andi.b #$C,d0
beq.s return_390E4
cmp.b d1,d0
beq.s return_390E4
move.b d0,objoff_36(a0)
addq.b #1,objoff_38(a0)
return_390E4:
rts
; ---------------------------------------------------------------------------
loc_390E6:
andi.b #$C,d0
beq.s return_390E4
nop
st objoff_31(a0)
move.b d0,objoff_36(a0)
nop
rts
; ---------------------------------------------------------------------------
loc_390FA:
cmpi.b #4,objoff_38(a0)
blo.s +
move.b #$A,routine_secondary(a0)
clr.w y_vel(a0)
clr.b collision_flags(a0)
movea.w objoff_32(a0),a2 ; a2=object
move.b #0,obj_control(a2)
bset #1,status(a2)
move.b #AniIDSonAni_Walk,anim(a2)
clr.w objoff_32(a0)
+
move.b #$20,objoff_37(a0)
clr.b objoff_31(a0)
clr.b objoff_38(a0)
rts
; End of subroutine loc_390BC
; ---------------------------------------------------------------------------
; Grabber death check subroutine
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_3913A:
ObjA7_CheckExplode:
subq.b #1,objoff_2A(a0)
bne.s +
move.b objoff_2B(a0),objoff_2A(a0)
subq.b #1,objoff_2B(a0)
beq.s ObjA7_Poof
bchg #palette_bit_0,art_tile(a0)
+
rts
; ---------------------------------------------------------------------------
; loc_39154:
ObjA7_Poof:
_move.b #ObjID_Explosion,id(a0) ; load 0bj27 (transform into explosion)
move.b #2,routine(a0)
bset #palette_bit_0,art_tile(a0)
move.w objoff_32(a0),d0
beq.s +
movea.w d0,a2 ; a2=object
move.b #0,objoff_2A(a2)
bset #1,status(a2)
move.b #$B,collision_flags(a0)
+
rts
; End of subroutine ObjA7_CheckExplode
; ===========================================================================
; ---------------------------------------------------------------------------
; Yet another subroutine for the Grabber badnik
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
loc_39182:
tst.w (Two_player_mode).w
beq.s +
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ---------------------------------------------------------------------------
+ move.w x_pos(a0),d0
andi.w #$FF80,d0
sub.w (Camera_X_pos_coarse).w,d0
cmpi.w #$280,d0
bhi.w +
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ---------------------------------------------------------------------------
+ lea (Object_Respawn_Table).w,a3
moveq #0,d0
move.b respawn_index(a0),d0
beq.s +
bclr #7,2(a3,d0.w)
+
tst.b objoff_30(a0)
beq.s +
movea.w objoff_32(a0),a3
move.b #0,$2A(a3)
bset #1,$22(a3)
+
moveq #0,d6
move.b objoff_2D(a0),d6
- movea.w (a2)+,a1
jsrto (DeleteObject2).l, JmpTo6_DeleteObject2
dbf d6,-
bra.w JmpTo65_DeleteObject
; End of subroutine loc_39182
; ===========================================================================
word_391E0:
dc.w objoff_3E
dc.b ObjID_GrabberBox
dc.b $3A
word_391E4:
dc.w objoff_3C
dc.b ObjID_GrabberLegs
dc.b $38
word_391E8:
dc.w objoff_3A
dc.b ObjID_GrabberString
dc.b $3C
; off_391EC:
ObjA7_SubObjData:
subObjData ObjA7_ObjA8_ObjA9_Obj98_MapUnc_3921A,make_art_tile(ArtTile_ArtNem_Grabber,1,1),4,4,$10,$B
; off_391F6:
ObjA7_SubObjData2:
subObjData ObjA7_ObjA8_ObjA9_Obj98_MapUnc_3921A,make_art_tile(ArtTile_ArtNem_Grabber,1,1),4,1,$10,$D7
; off_39200:
ObjA8_SubObjData:
subObjData ObjA7_ObjA8_ObjA9_Obj98_MapUnc_3921A,make_art_tile(ArtTile_ArtNem_Grabber,1,1),4,4,4,0
; off_3920A:
ObjA8_SubObjData2:
subObjData ObjAA_MapUnc_39228,make_art_tile(ArtTile_ArtNem_Grabber,1,1),4,5,4,0
; animation script
; off_39214:
Ani_objA7: offsetTable
offsetTableEntry.w byte_39216 ; 0
byte_39216:
dc.b 7, 0, 1,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings - objA7,objA8,objA9
; ----------------------------------------------------------------------------
ObjA7_ObjA8_ObjA9_Obj98_MapUnc_3921A: offsetTable
offsetTableEntry.w word_3923A ; 0
offsetTableEntry.w word_39254 ; 1
offsetTableEntry.w word_3926E ; 2
offsetTableEntry.w word_39278 ; 3
offsetTableEntry.w word_39282 ; 4
offsetTableEntry.w word_3928C ; 5
offsetTableEntry.w word_39296 ; 6
; -------------------------------------------------------------------------------
; sprite mappings - objAA (string of various lengths)
; -------------------------------------------------------------------------------
ObjAA_MapUnc_39228: offsetTable
offsetTableEntry.w word_392A0 ; 0
offsetTableEntry.w word_392AA ; 1
offsetTableEntry.w word_392B4 ; 2
offsetTableEntry.w word_392C6 ; 3
offsetTableEntry.w word_392D8 ; 4
; Unused - The spider badnik never goes down enough for these to appear
offsetTableEntry.w word_3930C ; 5 ; This is in the wrong place - this should be frame 6
offsetTableEntry.w word_392F2 ; 6 ; This is in the wrong place - this should be frame 5
offsetTableEntry.w word_3932E ; 7
offsetTableEntry.w word_3932E ; 8 ; This should point to word_39350
word_3923A:
dc.w 3
dc.w $F801, 0, 0,$FFE5
dc.w $F80D, 2, 1,$FFED; 4
dc.w $809, $1D, $E,$FFF1; 8
word_39254:
dc.w 3
dc.w $F801, 0, 0,$FFE5
dc.w $F80D, 2, 1,$FFED; 4
dc.w $80D, $23, $11,$FFF1; 8
word_3926E:
dc.w 1
dc.w $FC00, $A, 5,$FFFC
word_39278:
dc.w 1
dc.w $F809, $F, 7,$FFF9
word_39282:
dc.w 1
dc.w $F80D, $15, $A,$FFF9
word_3928C:
dc.w 1
dc.w $FC00, $2B, $15,$FFFC
word_39296:
dc.w 1
dc.w $FC00, $2C, $16,$FFFC
word_392A0:
dc.w 1
dc.w 1, $B, 5,$FFFC
word_392AA:
dc.w 1
dc.w 3, $B, 5,$FFFC
word_392B4:
dc.w 2
dc.w 1, $B, 5,$FFFC
dc.w $1003, $B, 5,$FFFC; 4
word_392C6:
dc.w 2
dc.w 3, $B, 5,$FFFC
dc.w $2003, $B, 5,$FFFC; 4
word_392D8:
dc.w 3
dc.w 1, $B, 5,$FFFC
dc.w $1003, $B, 5,$FFFC; 4
dc.w $3003, $B, 5,$FFFC; 8
word_392F2:
dc.w 3
dc.w 3, $B, 5,$FFFC
dc.w $2003, $B, 5,$FFFC; 4
dc.w $4003, $B, 5,$FFFC; 8
word_3930C:
dc.w 4
dc.w 1, $B, 5,$FFFC
dc.w $1003, $B, 5,$FFFC; 4
dc.w $3003, $B, 5,$FFFC; 8
dc.w $5003, $B, 5,$FFFC; 12
word_3932E:
dc.w 4
dc.w 3, $B, 5,$FFFC
dc.w $2003, $B, 5,$FFFC; 4
dc.w $4003, $B, 5,$FFFC; 8
dc.w $6003, $B, 5,$FFFC; 12
; Unused frame
;word_39350:
dc.w 5
dc.w 1, $B, 5,$FFFC
dc.w $1003, $B, 5,$FFFC; 4
dc.w $3003, $B, 5,$FFFC; 8
dc.w $5003, $B, 5,$FFFC; 12
dc.w $7003, $B, 5,$FFFC; 16
; ===========================================================================
; ----------------------------------------------------------------------------
; Object AC - Balkiry (jet badnik) from SCZ
; ----------------------------------------------------------------------------
; Sprite_3937A:
ObjAC:
moveq #0,d0
move.b routine(a0),d0
move.w ObjAC_Index(pc,d0.w),d1
jmp ObjAC_Index(pc,d1.w)
; ===========================================================================
; off_39388:
ObjAC_Index: offsetTable
offsetTableEntry.w ObjAC_Init ; 0
offsetTableEntry.w ObjAC_Main ; 2
; ===========================================================================
; loc_3938C:
ObjAC_Init:
bsr.w LoadSubObject
move.b #1,mapping_frame(a0)
move.w #-$300,x_vel(a0)
bclr #1,render_flags(a0)
beq.s +
move.w #-$500,x_vel(a0)
+
lea_ Ani_obj9C,a1
move.l a1,objoff_2E(a0)
bra.w loc_37ABE
; ===========================================================================
; loc_393B6:
ObjAC_Main:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
bsr.w loc_36776
bra.w Obj_DeleteBehindScreen
; ===========================================================================
; off_393C2:
ObjAC_SubObjData:
subObjData ObjAC_MapUnc_393CC,make_art_tile(ArtTile_ArtNem_Balkrie,0,0),4,4,$20,8
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjAC_MapUnc_393CC: BINCLUDE "mappings/sprite/objAC.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object AD - Clucker's base from WFZ
; ----------------------------------------------------------------------------
; Sprite_3941C:
ObjAD:
moveq #0,d0
move.b routine(a0),d0
move.w ObjAD_Index(pc,d0.w),d1
jmp ObjAD_Index(pc,d1.w)
; ===========================================================================
; off_3942A:
ObjAD_Index: offsetTable
offsetTableEntry.w ObjAD_Init ; 0
offsetTableEntry.w ObjAD_Main ; 2
; ===========================================================================
; loc_3942E:
ObjAD_Init:
bsr.w LoadSubObject
move.b #$C,mapping_frame(a0)
rts
; ===========================================================================
; loc_3943A:
ObjAD_Main:
move.w #$1B,d1
move.w #8,d2
move.w #8,d3
move.w x_pos(a0),d4
jsrto (SolidObject).l, JmpTo27_SolidObject
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; ----------------------------------------------------------------------------
; Object AE - Clucker (chicken badnik) from WFZ
; ----------------------------------------------------------------------------
; Sprite_39452:
ObjAE:
moveq #0,d0
move.b routine(a0),d0
move.w ObjAE_Index(pc,d0.w),d1
jmp ObjAE_Index(pc,d1.w)
; ===========================================================================
; off_39460:
ObjAE_Index: offsetTable
offsetTableEntry.w ObjAE_Init ; 0
offsetTableEntry.w loc_39488 ; 2
offsetTableEntry.w loc_394A2 ; 4
offsetTableEntry.w loc_394D2 ; 6
offsetTableEntry.w loc_394E0 ; 8
offsetTableEntry.w loc_39508 ; $A
offsetTableEntry.w loc_39516 ; $C
; ===========================================================================
; loc_3946E:
ObjAE_Init:
bsr.w LoadSubObject
move.b #$15,mapping_frame(a0)
btst #0,render_flags(a0)
beq.s +
bset #0,status(a0)
+
rts
; ===========================================================================
loc_39488:
bsr.w Obj_GetOrientationToPlayer
addi.w #$80,d2
cmpi.w #$100,d2
blo.s +
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
+
addq.b #2,routine(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_394A2:
move.b routine(a0),d2
lea (Ani_objAE_a).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
cmp.b routine(a0),d2
bne.s +
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
+
lea mapping_frame(a0),a1
clr.l (a1)
clr.w anim_frame_duration-mapping_frame(a1)
move.b #8,(a1)
move.b #6,collision_flags(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_394D2:
lea (Ani_objAE_b).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_394E0:
tst.b objoff_2A(a0)
beq.s +
subq.b #1,objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
+
addq.b #2,routine(a0)
lea mapping_frame(a0),a1
clr.l (a1)
clr.w anim_frame_duration-mapping_frame(a1)
move.b #$B,(a1)
bsr.w loc_39526
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_39508:
lea (Ani_objAE_c).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_39516:
move.b #8,routine(a0)
move.b #$40,objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_39526:
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s ++ ; rts
_move.b #ObjID_Projectile,id(a1) ; load obj98
move.b #$D,mapping_frame(a1)
move.b #$46,subtype(a1) ; <== ObjAD_SubObjData3
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
addi.w #$B,y_pos(a1)
move.w #-$200,d0
move.w #-8,d1
btst #0,render_flags(a0)
beq.s +
neg.w d0
neg.w d1
+
move.w d0,x_vel(a1)
add.w d1,x_pos(a1)
lea_ Obj98_CluckerShotMove,a2
move.l a2,objoff_2A(a1)
+
rts
; ===========================================================================
ObjAD_SubObjData:
subObjData ObjAD_Obj98_MapUnc_395B4,make_art_tile(ArtTile_ArtNem_WfzScratch,0,0),4,4,$18,0
ObjAD_SubObjData2:
subObjData ObjAD_Obj98_MapUnc_395B4,make_art_tile(ArtTile_ArtNem_WfzScratch,0,0),4,5,$10,0
; animation script
; off_3958A
Ani_objAE_a: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 1, 0, 1, 2, 3, 4, 5, 6, 7,$FC
even
; animation script
; off_39596
Ani_objAE_b: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 1, 8, 9, $A, $B, $B, $B, $B,$FC
even
; animation script
; off_395A2
Ani_objAE_c: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 3, $A, $B,$FC
even
; animation script
; off_395A8
Ani_CluckerShot:offsetTable
offsetTableEntry.w + ; 0
+ dc.b 3, $D, $E, $F,$10,$11,$12,$13,$14,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjAD_Obj98_MapUnc_395B4: BINCLUDE "mappings/sprite/objAE.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object AF - Mecha Sonic / Silver Sonic from DEZ
; (also handles Eggman's remote-control window)
; ----------------------------------------------------------------------------
; Sprite_3972C:
ObjAF:
moveq #0,d0
move.b routine(a0),d0
move.w ObjAF_Index(pc,d0.w),d1
jmp ObjAF_Index(pc,d1.w)
; ===========================================================================
; off_3973A:
ObjAF_Index: offsetTable
offsetTableEntry.w ObjAF_Init ; 0
offsetTableEntry.w loc_397AC ; 2
offsetTableEntry.w loc_397E6 ; 4
offsetTableEntry.w loc_397FE ; 6
offsetTableEntry.w loc_3984A ; 8
offsetTableEntry.w loc_398C0 ; $A
offsetTableEntry.w loc_39B92 ; $C
offsetTableEntry.w loc_39BBA ; $E
offsetTableEntry.w loc_39BCC ; $10
offsetTableEntry.w loc_39BE2 ; $12
offsetTableEntry.w loc_39BEA ; $14
offsetTableEntry.w loc_39C02 ; $16
offsetTableEntry.w loc_39C0A ; $18
offsetTableEntry.w loc_39C12 ; $1A
offsetTableEntry.w loc_39C2A ; $1C
offsetTableEntry.w loc_39C42 ; $1E
offsetTableEntry.w loc_39C50 ; $20
offsetTableEntry.w loc_39CA0 ; $22
; ===========================================================================
; loc_3975E:
ObjAF_Init:
bsr.w LoadSubObject
move.b #$1B,y_radius(a0)
move.b #$10,x_radius(a0)
move.b #0,collision_flags(a0)
move.b #8,collision_property(a0)
lea (word_39DC2).l,a2
bsr.w LoadChildObject
move.b #$E,routine(a1)
lea (word_39DC6).l,a2
bsr.w LoadChildObject
move.b #$14,routine(a1)
lea (word_39DCA).l,a2
bsr.w LoadChildObject
move.b #$1A,routine(a1)
rts
; ===========================================================================
loc_397AC:
move.w (Camera_X_pos).w,d0
cmpi.w #$224,d0
bhs.s loc_397BA
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_397BA:
addq.b #2,routine(a0)
move.w #$3C,objoff_2A(a0)
move.w #$100,y_vel(a0)
move.w #$224,d0
move.w d0,(Camera_Min_X_pos).w
move.w d0,(Camera_Max_X_pos).w
move.b #9,(Current_Boss_ID).w
moveq #MusID_FadeOut,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_397E6:
subq.w #1,objoff_2A(a0)
bmi.s loc_397F0
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_397F0:
addq.b #2,routine(a0)
moveq #MusID_Boss,d0
jsrto (PlayMusic).l, JmpTo5_PlayMusic
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_397FE:
move.b (Vint_runcount+3).w,d0
andi.b #$1F,d0
bne.s loc_3980E
moveq #SndID_Fire,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
loc_3980E:
jsr (ObjCheckFloorDist).l
tst.w d1
bmi.s loc_39830
jsrto (ObjectMove).l, JmpTo26_ObjectMove
moveq #0,d0
moveq #0,d1
movea.w parent(a0),a1 ; a1=object
bsr.w Obj_AlignChildXY
bsr.w loc_39D4A
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_39830:
add.w d1,y_pos(a0)
move.w #0,y_vel(a0)
move.b #$1A,collision_flags(a0)
bset #1,status(a0)
bra.w loc_399D6
; ===========================================================================
loc_3984A:
bsr.w loc_39CAE
bsr.w loc_39D1C
subq.b #1,objoff_2A(a0)
beq.s loc_39886
cmpi.b #$32,objoff_2A(a0)
bne.s loc_3986A
moveq #SndID_MechaSonicBuzz,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
jsrto (DisplaySprite).l, JmpTo45_DisplaySprite
loc_3986A:
jsr (ObjCheckFloorDist).l
add.w d1,y_pos(a0)
lea (off_39DE2).l,a1
bsr.w AnimateSprite_Checked
bsr.w loc_39D4A
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_39886:
addq.b #2,routine(a0)
moveq #0,d0
move.b objoff_2F(a0),d0
andi.b #$F,d0
move.b byte_398B0(pc,d0.w),routine_secondary(a0)
addq.b #1,objoff_2F(a0)
clr.b objoff_2E(a0)
movea.w objoff_3C(a0),a1 ; a1=object
move.b #$16,routine(a1)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
byte_398B0:
dc.b 6
dc.b 0 ; 1
dc.b $10 ; 2
dc.b 6 ; 3
dc.b 6 ; 4
dc.b $1E ; 5
dc.b 0 ; 6
dc.b $10 ; 7
dc.b 6 ; 8
dc.b 6 ; 9
dc.b $10 ; 10
dc.b 6 ; 11
dc.b 0 ; 12
dc.b 6 ; 13
dc.b $10 ; 14
dc.b $1E ; 15
; ===========================================================================
loc_398C0:
bsr.w loc_39CAE
bsr.w loc_39D1C
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_398F2(pc,d0.w),d1
jsr off_398F2(pc,d1.w)
moveq #0,d0
moveq #0,d1
movea.w parent(a0),a1 ; a1=object
bsr.w Obj_AlignChildXY
bsr.w loc_39D4A
bsr.w Obj_AlignChildXY
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
off_398F2: offsetTable
offsetTableEntry.w loc_3991E ; 0
offsetTableEntry.w loc_39946 ; 2
offsetTableEntry.w loc_39976 ; 4
offsetTableEntry.w loc_39A0A ; 6
offsetTableEntry.w loc_39A1C ; 8
offsetTableEntry.w loc_39A44 ; $A
offsetTableEntry.w loc_39A68 ; $C
offsetTableEntry.w loc_39A96 ; $E
offsetTableEntry.w loc_39A0A ; $10
offsetTableEntry.w loc_39A1C ; $12
offsetTableEntry.w loc_39AAA ; $14
offsetTableEntry.w loc_39ACE ; $16
offsetTableEntry.w loc_39AF4 ; $18
offsetTableEntry.w loc_39B28 ; $1A
offsetTableEntry.w loc_39A96 ; $1C
offsetTableEntry.w loc_39A0A ; $1E
offsetTableEntry.w loc_39A1C ; $20
offsetTableEntry.w loc_39AAA ; $22
offsetTableEntry.w loc_39ACE ; $24
offsetTableEntry.w loc_39B44 ; $26
offsetTableEntry.w loc_39B28 ; $28
offsetTableEntry.w loc_39A96 ; $2A
; ===========================================================================
loc_3991E:
addq.b #2,routine_secondary(a0)
move.b #3,mapping_frame(a0)
move.b #2,objoff_2C(a0)
loc_3992E:
move.b #$20,objoff_2A(a0)
movea.w parent(a0),a1 ; a1=object
move.b #$10,routine(a1)
move.b #1,anim(a1)
rts
; ===========================================================================
loc_39946:
subq.b #1,objoff_2A(a0)
bmi.s loc_3994E
rts
; ===========================================================================
loc_3994E:
addq.b #2,routine_secondary(a0)
move.b #$40,objoff_2A(a0)
move.b #1,anim(a0)
move.w #$800,d0
bsr.w loc_39D60
movea.w parent(a0),a1 ; a1=object
move.b #2,anim(a1)
moveq #SndID_SpindashRelease,d0
jmpto (PlaySound).l, JmpTo12_PlaySound
; ===========================================================================
loc_39976:
subq.b #1,objoff_2A(a0)
bmi.s loc_399C2
cmpi.b #$20,objoff_2A(a0)
bne.s loc_39994
move.b #2,anim(a0)
movea.w parent(a0),a1 ; a1=object
move.b #$12,routine(a1)
loc_39994:
bsr.w loc_39D72
lea (off_39DE2).l,a1
bsr.w AnimateSprite_Checked
cmpi.b #2,anim(a0)
bne.s return_399C0
cmpi.b #2,anim_frame(a0)
bne.s return_399C0
cmpi.b #3,anim_frame_duration(a0)
bne.s return_399C0
bchg #0,render_flags(a0)
return_399C0:
rts
; ===========================================================================
loc_399C2:
subq.b #1,objoff_2C(a0)
beq.s loc_399D6
move.b #2,routine_secondary(a0)
clr.w x_vel(a0)
bra.w loc_3992E
; ===========================================================================
loc_399D6:
move.b #8,routine(a0)
move.b #0,anim(a0)
move.b #$64,objoff_2A(a0)
clr.w x_vel(a0)
movea.w parent(a0),a1 ; a1=object
move.b #$12,routine(a1)
movea.w objoff_3C(a0),a1 ; a1=object
move.b #$18,routine(a1)
moveq #SndID_MechaSonicBuzz,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_39A0A:
addq.b #2,routine_secondary(a0)
move.b #3,mapping_frame(a0)
move.b #3,anim(a0)
rts
; ===========================================================================
loc_39A1C:
lea (off_39DE2).l,a1
bsr.w AnimateSprite_Checked
bne.s loc_39A2A
rts
; ===========================================================================
loc_39A2A:
addq.b #2,routine_secondary(a0)
move.b #$20,objoff_2A(a0)
move.b #4,anim(a0)
moveq #SndID_LaserBeam,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_39A44:
subq.b #1,objoff_2A(a0)
bmi.s loc_39A56
lea (off_39DE2).l,a1
bsr.w AnimateSprite_Checked
rts
; ===========================================================================
loc_39A56:
addq.b #2,routine_secondary(a0)
move.b #$40,objoff_2A(a0)
move.w #$800,d0
bra.w loc_39D60
; ===========================================================================
loc_39A68:
subq.b #1,objoff_2A(a0)
bmi.s loc_39A7C
bsr.w loc_39D72
lea (off_39DE2).l,a1
bra.w AnimateSprite_Checked
; ===========================================================================
loc_39A7C:
addq.b #2,routine_secondary(a0)
move.b #5,anim(a0)
bchg #0,render_flags(a0)
clr.w x_vel(a0)
clr.w y_vel(a0)
rts
; ===========================================================================
loc_39A96:
lea (off_39DE2).l,a1
bsr.w AnimateSprite_Checked
bne.w BranchTo_loc_399D6
rts
; ===========================================================================
BranchTo_loc_399D6
bra.w loc_399D6
; ===========================================================================
loc_39AAA:
subq.b #1,objoff_2A(a0)
bmi.s loc_39ABC
lea (off_39DE2).l,a1
bsr.w AnimateSprite_Checked
rts
; ===========================================================================
loc_39ABC:
addq.b #2,routine_secondary(a0)
move.b #$40,objoff_2A(a0)
move.w #$400,d0
bra.w loc_39D60
; ===========================================================================
loc_39ACE:
subq.b #1,objoff_2A(a0)
cmpi.b #$3C,objoff_2A(a0)
bne.s loc_39ADE
bsr.w loc_39AE8
loc_39ADE:
lea (off_39DE2).l,a1
bra.w AnimateSprite_Checked
; ===========================================================================
loc_39AE8:
addq.b #2,routine_secondary(a0)
move.w #-$600,y_vel(a0)
rts
; ===========================================================================
loc_39AF4:
subq.b #1,objoff_2A(a0)
bmi.w loc_39A7C
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.s loc_39B0A
bsr.w loc_39B1A
loc_39B0A:
addi.w #$38,y_vel(a0)
lea (off_39DE2).l,a1
bra.w AnimateSprite_Checked
; ===========================================================================
loc_39B1A:
addq.b #2,routine_secondary(a0)
add.w d1,y_pos(a0)
clr.w y_vel(a0)
rts
; ===========================================================================
loc_39B28:
subq.b #1,objoff_2A(a0)
bmi.w loc_39A7C
jsr (ObjCheckFloorDist).l
add.w d1,y_pos(a0)
lea (off_39DE2).l,a1
bra.w AnimateSprite_Checked
; ===========================================================================
loc_39B44:
subq.b #1,objoff_2A(a0)
bmi.w loc_39A7C
tst.b objoff_2E(a0)
bne.s loc_39B66
tst.w y_vel(a0)
bmi.s loc_39B66
st objoff_2E(a0)
bsr.w loc_39D82
moveq #SndID_SpikeSwitch,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
loc_39B66:
jsr (ObjCheckFloorDist).l
tst.w d1
bpl.s loc_39B74
bsr.w loc_39B84
loc_39B74:
addi.w #$38,y_vel(a0)
lea (off_39DE2).l,a1
bra.w AnimateSprite_Checked
; ===========================================================================
loc_39B84:
addq.b #2,routine_secondary(a0)
add.w d1,y_pos(a0)
clr.w y_vel(a0)
rts
; ===========================================================================
loc_39B92:
clr.b collision_flags(a0)
subq.w #1,objoff_32(a0)
bmi.s loc_39BA4
jsrto (Boss_LoadExplosion).l, JmpTo_Boss_LoadExplosion
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_39BA4:
move.w #$1000,(Camera_Max_X_pos).w
addq.b #2,(Dynamic_Resize_Routine).w
move.b (Level_Music).w,d0
jsrto (PlayMusic).l, JmpTo5_PlayMusic
bra.w JmpTo65_DeleteObject
; ===========================================================================
loc_39BBA:
bsr.w LoadSubObject
move.b #8,width_pixels(a0)
move.b #0,collision_flags(a0)
rts
; ===========================================================================
loc_39BCC:
movea.w objoff_2C(a0),a1 ; a1=object
bsr.w loc_367AA
lea (off_39E30).l,a1
bsr.w AnimateSprite_Checked
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_39BE2:
andi.b #$7F,render_flags(a0)
rts
; ===========================================================================
loc_39BEA:
bsr.w LoadSubObject
move.b #8,width_pixels(a0)
move.b #$B,mapping_frame(a0)
move.b #3,priority(a0)
rts
; ===========================================================================
loc_39C02:
move.b #0,collision_flags(a0)
rts
; ===========================================================================
loc_39C0A:
move.b #$98,collision_flags(a0)
rts
; ===========================================================================
loc_39C12:
bsr.w LoadSubObject
move.b #4,mapping_frame(a0)
move.w #$2C0,x_pos(a0)
move.w #$139,y_pos(a0)
rts
; ===========================================================================
loc_39C2A:
movea.w objoff_2C(a0),a1 ; a1=object
bclr #1,status(a1)
bne.s loc_39C3A
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_39C3A:
addq.b #2,routine(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_39C42:
lea (Ani_objAF_c).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_39C50:
movea.w objoff_2C(a0),a1 ; a1=object
lea (MainCharacter).w,a2 ; a2=character
btst #2,status(a1)
bne.s loc_39C92
move.b #2,anim(a0)
cmpi.b #4,routine(a2)
bne.s loc_39C78
move.b #3,anim(a0)
bra.w loc_39C84
; ===========================================================================
loc_39C78:
tst.b collision_flags(a1)
bne.s loc_39C84
move.b #4,anim(a0)
loc_39C84:
lea (Ani_objAF_c).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_39C92:
addq.b #2,routine(a0)
move.b #1,anim(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_39CA0:
lea (Ani_objAF_c).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_39CAE:
tst.b collision_property(a0)
beq.s loc_39CF0
tst.b collision_flags(a0)
bne.s return_39CEE
tst.b objoff_30(a0)
bne.s loc_39CD0
move.b #$20,objoff_30(a0)
move.w #SndID_BossHit,d0
jsr (PlaySound).l
loc_39CD0:
lea (Normal_palette_line2+2).w,a1
moveq #0,d0
tst.w (a1)
bne.s loc_39CDE
move.w #$EEE,d0
loc_39CDE:
move.w d0,(a1)
subq.b #1,objoff_30(a0)
bne.s return_39CEE
clr.w (Normal_palette_line2+2).w
bsr.w loc_39D24
return_39CEE:
rts
; ===========================================================================
loc_39CF0:
moveq #100,d0
bsr.w AddPoints
move.w #$FF,objoff_32(a0)
move.b #$C,routine(a0)
clr.b collision_flags(a0)
bset #2,status(a0)
movea.w objoff_3C(a0),a1 ; a1=object
jsrto (DeleteObject2).l, JmpTo6_DeleteObject2
movea.w parent(a0),a1 ; a1=object
jmpto (DeleteObject2).l, JmpTo6_DeleteObject2
; ===========================================================================
loc_39D1C:
tst.b collision_flags(a0)
beq.w return_37A48
loc_39D24:
move.b mapping_frame(a0),d0
cmpi.b #6,d0
beq.s loc_39D42
cmpi.b #7,d0
beq.s loc_39D42
cmpi.b #8,d0
beq.s loc_39D42
move.b #$1A,collision_flags(a0)
rts
; ===========================================================================
loc_39D42:
move.b #$9A,collision_flags(a0)
rts
; ===========================================================================
loc_39D4A:
moveq #$C,d0
moveq #-$C,d1
btst #0,render_flags(a0)
beq.s loc_39D58
neg.w d0
loc_39D58:
movea.w objoff_3C(a0),a1 ; a1=object
bra.w Obj_AlignChildXY
; ===========================================================================
loc_39D60:
tst.b objoff_2D(a0)
bne.s loc_39D68
neg.w d0
loc_39D68:
not.b objoff_2D(a0)
move.w d0,x_vel(a0)
rts
; ===========================================================================
loc_39D72:
moveq #$20,d0
tst.w x_vel(a0)
bmi.s loc_39D7C
neg.w d0
loc_39D7C:
add.w d0,x_vel(a0)
rts
; ===========================================================================
loc_39D82:
move.b #$4A,d2
moveq #7,d6
lea (byte_39D92).l,a2
bra.w Obj_CreateProjectiles
; ===========================================================================
byte_39D92:
dc.b 0,$E8, 0,$FD, $F, 0,$F0,$F0,$FE,$FE,$10, 0,$E8, 0,$FD, 0
dc.b $11, 0,$F0,$10,$FE, 2,$12, 0, 0,$18, 0, 3,$13, 0,$10,$10; 16
dc.b 2, 2,$14, 0,$18, 0, 3, 0,$15, 0,$10,$F0, 2,$FE,$16, 0; 32
word_39DC2:
dc.w objoff_3E
dc.b ObjID_MechaSonic
dc.b $48
word_39DC6:
dc.w objoff_3C
dc.b ObjID_MechaSonic
dc.b $48
word_39DCA:
dc.w objoff_3A
dc.b ObjID_MechaSonic
dc.b $A4
; off_39DCE:
ObjAF_SubObjData2:
subObjData ObjAF_Obj98_MapUnc_39E68,make_art_tile(ArtTile_ArtNem_SilverSonic,1,0),4,4,$10,$1A
; off_39DD8:
ObjAF_SubObjData3:
subObjData ObjAF_MapUnc_3A08C,make_art_tile(ArtTile_ArtNem_DEZWindow,0,0),4,6,$10,0
; animation script
off_39DE2: offsetTable
offsetTableEntry.w byte_39DEE ; 0
offsetTableEntry.w byte_39DF4 ; 1
offsetTableEntry.w byte_39DF8 ; 2
offsetTableEntry.w byte_39DFE ; 3
offsetTableEntry.w byte_39E14 ; 4
offsetTableEntry.w byte_39E1A ; 5
byte_39DEE:
dc.b 2, 0, 1, 2,$FF, 0
byte_39DF4:
dc.b $45, 3,$FD, 0
byte_39DF8:
dc.b 3, 4, 5, 4, 3,$FC
byte_39DFE:
dc.b 3, 3, 3, 6, 6, 6, 7, 7, 7, 8, 8, 8, 6, 6, 7, 7
dc.b 8, 8, 6, 7, 8,$FC; 16
byte_39E14:
dc.b 2, 6, 7, 8,$FF, 0
byte_39E1A:
dc.b 3, 8, 7, 6, 8, 8, 7, 7, 6, 6, 8, 8, 8, 7, 7, 7
dc.b 6, 6, 6, 3, 3,$FC; 16
even
; animation script
off_39E30: offsetTable
offsetTableEntry.w byte_39E36 ; 0
offsetTableEntry.w byte_39E3A ; 1
offsetTableEntry.w byte_39E3E ; 2
byte_39E36:
dc.b 1, $B, $C,$FF
byte_39E3A:
dc.b 1, $D, $E,$FF
byte_39E3E:
dc.b 1, 9, $A,$FF
even
; animation script
; off_39E42:
Ani_objAF_c: offsetTable
offsetTableEntry.w byte_39E4C ; 0
offsetTableEntry.w byte_39E54 ; 1
offsetTableEntry.w byte_39E5C ; 2
offsetTableEntry.w byte_39E60 ; 3
offsetTableEntry.w byte_39E64 ; 4
byte_39E4C: dc.b 3, 4, 3, 2, 1, 0,$FC, 0
byte_39E54: dc.b 3, 0, 1, 2, 3, 4,$FA, 0
byte_39E5C: dc.b 3, 5, 5,$FF
byte_39E60: dc.b 3, 5, 6,$FF
byte_39E64: dc.b 3, 7, 7,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjAF_Obj98_MapUnc_39E68: BINCLUDE "mappings/sprite/objAF_a.bin"
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjAF_MapUnc_3A08C: BINCLUDE "mappings/sprite/objAF_b.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object B0 - Sonic on the Sega screen
; ----------------------------------------------------------------------------
; Sprite_3A1DC:
ObjB0:
moveq #0,d0
move.b routine(a0),d0
move.w ObjB0_Index(pc,d0.w),d1
jmp ObjB0_Index(pc,d1.w)
; ===========================================================================
; off_3A1EA:
ObjB0_Index: offsetTable
offsetTableEntry.w ObjB0_Init ; 0
offsetTableEntry.w ObjB0_RunLeft ; 2
offsetTableEntry.w ObjB0_MidWipe ; 4
offsetTableEntry.w ObjB0_RunRight ; 6
offsetTableEntry.w ObjB0_EndWipe ; 8
offsetTableEntry.w return_3A3F6 ; $A
; ===========================================================================
ObjB0_Init:
bsr.w LoadSubObject
move.w #$1E8,x_pixel(a0)
move.w #$F0,y_pixel(a0)
move.w #$B,objoff_2A(a0)
move.w #2,(SegaScr_VInt_Subrout).w
bset #0,render_flags(a0)
bset #0,status(a0)
; Initialize streak horizontal offsets for Sonic going left.
; 9 full lines (8 pixels) + 6 pixels, 2-byte interleaved entries for PNT A and PNT B
lea (Horiz_Scroll_Buf + 2 * 2 * (9 * 8 + 6)).w,a1
lea Streak_Horizontal_offsets(pc),a2
moveq #0,d0
moveq #$22,d6 ; Number of streaks-1
- move.b (a2)+,d0
add.w d0,(a1)
addq.w #2 * 2 * 2,a1 ; Advance to next streak 2 pixels down
dbf d6,-
lea off_3A294(pc),a1 ; pointers to mapping DPLC data
lea (ArtUnc_Sonic).l,a3
lea (Chunk_Table).l,a5
moveq #4-1,d5 ; there are 4 mapping frames to loop over
; this copies the tiles that we want to scale up from ROM to RAM
;loc_3A246:
;CopySpriteTilesToRAMForSegaScreen:
- movea.l (a1)+,a2
move.w (a2)+,d6 ; get the number of pieces in this mapping frame
subq.w #1,d6
- move.w (a2)+,d0
move.w d0,d1
; Depending on the exact location (and size) of the art being used,
; you may encounter an overflow in the original code which garbles
; the enlarged Sonic. The following code fixes this:
if 1==0
andi.l #$FFF,d0
lsl.l #5,d0
lea (a3,d0.l),a4 ; source ROM address of tiles to copy
else
andi.w #$FFF,d0
lsl.w #5,d0
lea (a3,d0.w),a4 ; source ROM address of tiles to copy
endif
andi.w #$F000,d1 ; abcd000000000000
rol.w #4,d1 ; (this calculation can be done smaller and faster
addq.w #1,d1 ; by doing rol.w #7,d1 addq.w #7,d1
lsl.w #3,d1 ; instead of these 4 lines)
subq.w #1,d1 ; 000000000abcd111 ; number of dwords to copy minus 1
- move.l (a4)+,(a5)+
dbf d1,- ; copy all of the pixels in this piece into the temp buffer
dbf d6,-- ; loop per piece in the frame
dbf d5,--- ; loop per mapping frame
; this scales up the tiles by 2
;ScaleUpSpriteTiles:
move.w d7,-(sp)
moveq #0,d0
moveq #0,d1
lea SonicRunningSpriteScaleData(pc),a6
moveq #4*2-1,d7 ; there are 4 sprite mapping frames with 2 pieces each
- movea.l (a6)+,a1 ; source in RAM of tile graphics to enlarge
movea.l (a6)+,a2 ; destination in RAM of enlarged graphics
move.b (a6)+,d0 ; width of the sprite piece to enlarge (minus 1)
move.b (a6)+,d1 ; height of the sprite piece to enlarge (minus 1)
bsr.w Scale_2x
dbf d7,- ; loop over each piece
move.w (sp)+,d7
rts
; ===========================================================================
; These next four things are pointers to Sonic's dereferenced
; DPLC entries of his "running animation" frames for the SEGA screen.
; I want that DPLC data split into a binary file for use with editors,
; but unfortunately there's no way to refer to BINCLUDE'd bytes
; from within AS, so I put an educated guess (default) here and
; run an external program (fixpointer.exe) to fix it later.
; WARNING: the build script needs editing if you rename this label
off_3A294:
dc.l (MapRUnc_Sonic+$33A) ;dc.l word_7181A
dc.l (MapRUnc_Sonic+$340) ;dc.l word_71820
dc.l (MapRUnc_Sonic+$346) ;dc.l word_71826
dc.l (MapRUnc_Sonic+$34C) ;dc.l word_7182C
map_piece macro width,height
dc.l copysrc,copydst
dc.b width-1,height-1
copysrc := copysrc + tiles_to_bytes(width * height)
copydst := copydst + tiles_to_bytes(width * height) * 2 * 2
endm
;word_3A2A4:
SonicRunningSpriteScaleData:
copysrc := Chunk_Table
copydst := Chunk_Table + $B00
SegaScreenScaledSpriteDataStart = copydst
rept 4 ; repeat 4 times since there are 4 frames to scale up
; piece 1 of each frame (the smaller top piece):
map_piece 3,2
; piece 2 of each frame (the larger bottom piece):
map_piece 4,4
endm
SegaScreenScaledSpriteDataEnd = copydst
if copysrc > SegaScreenScaledSpriteDataStart
fatal "Scale copy source overran allocated size. Try changing the initial value of copydst to Chunk_Table+$\{copysrc-Chunk_Table}"
endif
; ===========================================================================
ObjB0_RunLeft:
subi.w #$20,x_pos(a0)
subq.w #1,objoff_2A(a0)
bmi.s loc_3A312
bsr.w ObjB0_Move_Streaks_Left
lea (Ani_objB0).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3A312:
addq.b #2,routine(a0)
move.w #$C,objoff_2A(a0)
move.b #1,objoff_2C(a0)
move.b #-1,objoff_2D(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjB0_MidWipe:
tst.w objoff_2A(a0)
beq.s loc_3A33A
subq.w #1,objoff_2A(a0)
bsr.w ObjB0_Move_Streaks_Left
loc_3A33A:
lea word_3A49E(pc),a1
bsr.w loc_3A44E
bne.s loc_3A346
rts
; ===========================================================================
loc_3A346:
addq.b #2,routine(a0)
bchg #0,render_flags(a0)
move.w #$B,objoff_2A(a0)
move.w #4,(SegaScr_VInt_Subrout).w
subi.w #$28,x_pos(a0)
bchg #0,render_flags(a0)
bchg #0,status(a0)
; This clears a lot more than the horizontal scroll buffer, which is $400 bytes.
; This is because the loop counter is erroneously set to $400, instead of ($400/4)-1.
clearRAM Horiz_Scroll_Buf,Horiz_Scroll_Buf_End+$C04 ; Bug: That '+$C04' shouldn't be there; accidentally clears an additional $C04 bytes
; Initialize streak horizontal offsets for Sonic going right.
; 9 full lines (8 pixels) + 7 pixels, 2-byte interleaved entries for PNT A and PNT B
lea (Horiz_Scroll_Buf + 2 * 2 * (9 * 8 + 7)).w,a1
lea Streak_Horizontal_offsets(pc),a2
moveq #0,d0
moveq #$22,d6 ; Number of streaks-1
loc_3A38A:
move.b (a2)+,d0
sub.w d0,(a1)
addq.w #2 * 2 * 2,a1 ; Advance to next streak 2 pixels down
dbf d6,loc_3A38A
rts
; ===========================================================================
ObjB0_RunRight:
subq.w #1,objoff_2A(a0)
bmi.s loc_3A3B4
addi.w #$20,x_pos(a0)
bsr.w ObjB0_Move_Streaks_Right
lea (Ani_objB0).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3A3B4:
addq.b #2,routine(a0)
move.w #$C,objoff_2A(a0)
move.b #1,objoff_2C(a0)
move.b #-1,objoff_2D(a0)
rts
; ===========================================================================
ObjB0_EndWipe:
tst.w objoff_2A(a0)
beq.s loc_3A3DA
subq.w #1,objoff_2A(a0)
bsr.w ObjB0_Move_Streaks_Right
loc_3A3DA:
lea word_3A514(pc),a1
bsr.w loc_3A44E
bne.s loc_3A3E6
rts
; ===========================================================================
loc_3A3E6:
addq.b #2,routine(a0)
st (SegaScr_PalDone_Flag).w
move.b #SndID_SegaSound,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
return_3A3F6:
rts
; ===========================================================================
; ----------------------------------------------------------------------------
; Object B1 - Object that hides TM symbol on JP region
; ----------------------------------------------------------------------------
; Sprite_3A3F8:
ObjB1:
moveq #0,d0
move.b routine(a0),d0
move.w ObjB1_Index(pc,d0.w),d1
jmp ObjB1_Index(pc,d1.w)
; ===========================================================================
; off_3A406:
ObjB1_Index: offsetTable
offsetTableEntry.w ObjB1_Init ; 0
offsetTableEntry.w ObjB1_Main ; 2
; ===========================================================================
; loc_3A40A:
ObjB1_Init:
bsr.w LoadSubObject
move.b #4,mapping_frame(a0)
move.w #$174,x_pixel(a0)
move.w #$D8,y_pixel(a0)
rts
; ===========================================================================
; BranchTo4_JmpTo45_DisplaySprite
ObjB1_Main:
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjB0_Move_Streaks_Left:
; 9 full lines (8 pixels) + 6 pixels, 2-byte interleaved entries for PNT A and PNT B
lea (Horiz_Scroll_Buf + 2 * 2 * (9 * 8 + 6)).w,a1
move.w #$22,d6 ; Number of streaks-1
- subi.w #$20,(a1)
addq.w #2 * 2 * 2,a1 ; Advance to next streak 2 pixels down
dbf d6,-
rts
; ===========================================================================
ObjB0_Move_Streaks_Right:
; 9 full lines (8 pixels) + 7 pixels, 2-byte interleaved entries for PNT A and PNT B
lea (Horiz_Scroll_Buf + 2 * 2 * (9 * 8 + 7)).w,a1
move.w #$22,d6 ; Number of streaks-1
- addi.w #$20,(a1)
addq.w #2 * 2 * 2,a1 ; Advance to next streak 2 pixels down
dbf d6,-
rts
; ===========================================================================
loc_3A44E:
subq.b #1,objoff_2C(a0)
bne.s loc_3A496
moveq #0,d0
move.b objoff_2D(a0),d0
addq.b #1,d0
cmp.b 1(a1),d0
blo.s loc_3A468
tst.b 3(a1)
bne.s loc_3A49A
loc_3A468:
move.b d0,objoff_2D(a0)
_move.b 0(a1),objoff_2C(a0)
lea 6(a1),a2 ; This loads a palette: Sega Screen 2.bin or Sega Screen 3.bin
moveq #0,d1
move.b 2(a1),d1
move.w d1,d2
tst.w d0
beq.s loc_3A48C
loc_3A482:
subq.b #1,d0
beq.s loc_3A48A
add.w d2,d1
bra.s loc_3A482
; ===========================================================================
loc_3A48A:
adda.w d1,a2
loc_3A48C:
movea.w 4(a1),a3
loc_3A490:
move.w (a2)+,(a3)+
subq.w #2,d2
bne.s loc_3A490
loc_3A496:
moveq #0,d0
rts
; ===========================================================================
loc_3A49A:
moveq #1,d0
rts
; ===========================================================================
; probably some sort of description of how to use the following palette
word_3A49E:
dc.b 4 ; 0 ; How many frames before each iteration
dc.b 7 ; 1 ; How many iterations
dc.b $10 ; 2 ; Number of colors * 2 to skip each iteration
dc.b $FF ; 3 ; Some sort of flag
dc.w Normal_palette+$10 ; 4 ; First target palette entry
; Palette for the SEGA screen (background and pre-wipe foreground) (7 frames)
;pal_3A4A4:
BINCLUDE "art/palettes/Sega Screen 2.bin"
; probably some sort of description of how to use the following palette
word_3A514:
dc.b 4 ; 0 ; How many frames before each iteration
dc.b 7 ; 1 ; How many iterations
dc.b $10 ; 2 ; Number of colors * 2 to skip each iteration
dc.b $FF ; 3 ; Some sort of flag
dc.w Normal_palette ; 4 ; First target palette entry
; Palette for the SEGA screen (wiping and post-wipe foreground) (7 frames)
;pal_3A51A:
BINCLUDE "art/palettes/Sega Screen 3.bin"
; off_3A58A:
ObjB0_SubObjData:
subObjData ObjB1_MapUnc_3A5A6,make_art_tile(ArtTile_ArtUnc_Giant_Sonic,2,1),0,1,$10,0
; off_3A594:
ObjB1_SubObjData:
subObjData ObjB1_MapUnc_3A5A6,make_art_tile(ArtTile_ArtNem_Sega_Logo+2,0,0),0,2,8,0
; animation script
; off_3A59E:
Ani_objB0: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 0, 0, 1, 2, 3,$FF
even
; ------------------------------------------------------------------------------
; sprite mappings
; Gigantic Sonic (2x size) mappings for the SEGA screen
; also has the "trademark hider" mappings
; ------------------------------------------------------------------------------
ObjB1_MapUnc_3A5A6: BINCLUDE "mappings/sprite/objB1.bin"
; ===========================================================================
;loc_3A68A
SegaScr_VInt:
move.w (SegaScr_VInt_Subrout).w,d0
beq.w return_37A48
clr.w (SegaScr_VInt_Subrout).w
move.w off_3A69E-2(pc,d0.w),d0
jmp off_3A69E(pc,d0.w)
; ===========================================================================
off_3A69E: offsetTable
offsetTableEntry.w loc_3A6A2 ; 0
offsetTableEntry.w loc_3A6D4 ; 2
; ===========================================================================
loc_3A6A2:
dma68kToVDP SegaScreenScaledSpriteDataStart,tiles_to_bytes(ArtTile_ArtUnc_Giant_Sonic),\
SegaScreenScaledSpriteDataEnd-SegaScreenScaledSpriteDataStart,VRAM
lea ObjB1_Streak_fade_to_right(pc),a1
; 9 full lines ($100 bytes each) plus $28 8-pixel cells
move.l #vdpComm(VRAM_SegaScr_Plane_A_Name_Table + planeLocH80($28,9),VRAM,WRITE),d0 ; $49500003
bra.w loc_3A710
; ===========================================================================
loc_3A6D4:
dmaFillVRAM 0,VRAM_SegaScr_Plane_A_Name_Table,VRAM_SegaScr_Plane_Table_Size ; clear Plane A pattern name table
lea ObjB1_Streak_fade_to_left(pc),a1
; $49A00003; 9 full lines ($100 bytes each) plus $50 8-pixel cells
move.l #vdpComm(VRAM_SegaScr_Plane_A_Name_Table + planeLocH80($50,9),VRAM,WRITE),d0
bra.w loc_3A710
loc_3A710:
lea (VDP_data_port).l,a6
; This is the line delta; for each line, the code below
; writes $30 entries, leaving $50 untouched.
move.l #vdpCommDelta(planeLocH80(0,1)),d6 ; $1000000
moveq #7,d1 ; Inner loop: repeat 8 times
moveq #9,d2 ; Outer loop: repeat $A times
-
move.l d0,4(a6) ; Send command to VDP: set address to write to
move.w d1,d3 ; Reset inner loop counter
movea.l a1,a2 ; Reset data pointer
-
move.w (a2)+,d4 ; Read one pattern name table entry
bclr #$A,d4 ; Test bit $A and clear (flag for end of line)
beq.s + ; Branch if bit was clear
bsr.w loc_3A742 ; Fill rest of line with this set of pixels
+
move.w d4,(a6) ; Write PNT entry
dbf d3,-
add.l d6,d0 ; Point to the next VRAM area to be written to
dbf d2,--
rts
; ===========================================================================
loc_3A742:
moveq #$28,d5 ; Fill next $29 entries...
-
move.w d4,(a6) ; ... using the PNT entry that had bit $A set
dbf d5,-
rts
; ===========================================================================
; Pattern A name table entries, with special flag detailed below
; These are used for the streaks, and point to VRAM in the $1000-$10FF range
ObjB1_Streak_fade_to_right:
dc.w make_block_tile(ArtTile_ArtNem_Trails+0,0,0,1,1) ; 0
dc.w make_block_tile(ArtTile_ArtNem_Trails+1,0,0,1,1) ; 2
dc.w make_block_tile(ArtTile_ArtNem_Trails+2,0,0,1,1) ; 4
dc.w make_block_tile(ArtTile_ArtNem_Trails+3,0,0,1,1) ; 6
dc.w make_block_tile(ArtTile_ArtNem_Trails+4,0,0,1,1) ; 8
dc.w make_block_tile(ArtTile_ArtNem_Trails+5,0,0,1,1) ; 10
dc.w make_block_tile(ArtTile_ArtNem_Trails+6,0,0,1,1) ; 12
dc.w make_block_tile(ArtTile_ArtNem_Trails+7,0,0,1,1) | (1 << $A) ; 14 ; Bit $A is used as a flag to use this tile $29 times
ObjB1_Streak_fade_to_left:
dc.w make_block_tile(ArtTile_ArtNem_Trails+7,0,0,1,1) | (1 << $A) ; 0 ; Bit $A is used as a flag to use this tile $29 times
dc.w make_block_tile(ArtTile_ArtNem_Trails+6,0,0,1,1) ; 2
dc.w make_block_tile(ArtTile_ArtNem_Trails+5,0,0,1,1) ; 4
dc.w make_block_tile(ArtTile_ArtNem_Trails+4,0,0,1,1) ; 6
dc.w make_block_tile(ArtTile_ArtNem_Trails+3,0,0,1,1) ; 8
dc.w make_block_tile(ArtTile_ArtNem_Trails+2,0,0,1,1) ; 10
dc.w make_block_tile(ArtTile_ArtNem_Trails+1,0,0,1,1) ; 12
dc.w make_block_tile(ArtTile_ArtNem_Trails+0,0,0,1,1) ; 14
Streak_Horizontal_offsets:
dc.b $12
dc.b 4 ; 1
dc.b 4 ; 2
dc.b 2 ; 3
dc.b 2 ; 4
dc.b 2 ; 5
dc.b 2 ; 6
dc.b 0 ; 7
dc.b 0 ; 8
dc.b 0 ; 9
dc.b 0 ; 10
dc.b 0 ; 11
dc.b 0 ; 12
dc.b 0 ; 13
dc.b 0 ; 14
dc.b 4 ; 15
dc.b 4 ; 16
dc.b 6 ; 17
dc.b $A ; 18
dc.b 8 ; 19
dc.b 6 ; 20
dc.b 4 ; 21
dc.b 4 ; 22
dc.b 4 ; 23
dc.b 4 ; 24
dc.b 6 ; 25
dc.b 6 ; 26
dc.b 8 ; 27
dc.b 8 ; 28
dc.b $A ; 29
dc.b $A ; 30
dc.b $C ; 31
dc.b $E ; 32
dc.b $10 ; 33
dc.b $16 ; 34
dc.b 0 ; 35
; ===========================================================================
; ----------------------------------------------------------------------------
; Object B2 - The Tornado (Tails' plane)
; ----------------------------------------------------------------------------
; Sprite_3A790:
ObjB2:
moveq #0,d0
move.b routine(a0),d0
move.w ObjB2_Index(pc,d0.w),d1
jmp ObjB2_Index(pc,d1.w)
; ===========================================================================
; off_3A79E:
ObjB2_Index: offsetTable
offsetTableEntry.w ObjB2_Init ; 0
offsetTableEntry.w ObjB2_Main_SCZ ; 2
offsetTableEntry.w ObjB2_Main_WFZ_Start ; 4
offsetTableEntry.w ObjB2_Main_WFZ_End ; 6
offsetTableEntry.w ObjB2_Invisible_grabber ; 8
offsetTableEntry.w loc_3AD0C ; $A
offsetTableEntry.w loc_3AD2A ; $C
offsetTableEntry.w loc_3AD42 ; $E
; ===========================================================================
; loc_3A7AE:
ObjB2_Init:
bsr.w LoadSubObject
moveq #0,d0
move.b subtype(a0),d0
subi.b #$4E,d0
move.b d0,routine(a0)
cmpi.w #2,(Player_mode).w
bne.s +
cmpi.b #8,d0
bhs.s +
move.b #4,mapping_frame(a0)
move.b #1,anim(a0)
+ ; BranchTo5_JmpTo45_DisplaySprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; loc_3A7DE:
ObjB2_Main_SCZ:
bsr.w ObjB2_Animate_Pilot
tst.w (Debug_placement_mode).w
bne.w ObjB2_animate
lea (MainCharacter).w,a1 ; a1=character
move.w art_tile(a1),d0
andi.w #high_priority,d0
move.w art_tile(a0),d1
andi.w #drawing_mask,d1
or.w d0,d1
move.w d1,art_tile(a0)
move.w x_pos(a0),-(sp)
bsr.w ObjB2_Move_with_player
move.b status(a0),objoff_2E(a0)
move.w #$1B,d1
move.w #8,d2
move.w #9,d3
move.w (sp)+,d4
jsrto (SolidObject).l, JmpTo27_SolidObject
bsr.w ObjB2_Move_obbey_player
move.b objoff_2E(a0),d0
move.b status(a0),d1
if gameRevision<2
andi.b #p1_standing,d0 ; 'on object' bit
andi.b #p1_standing,d1 ; 'on object' bit
else
; 'fixes' the player being able to spin dash off the Tornado
andi.b #1,d0 ; 'in air' bit
andi.b #1,d1 ; 'in air' bit
endif
eor.b d0,d1
move.b d1,objoff_2E(a0)
lea (MainCharacter).w,a1 ; a1=character
move.w x_pos(a1),d1
move.w (Camera_X_pos).w,d0
move.w d0,(Camera_Min_X_pos).w
move.w d0,d2
addi.w #$11,d2
cmp.w d2,d1
bhi.s +
addq.w #1,d1
move.w d1,x_pos(a1)
+ ; loc_3A85E:
cmpi.w #$1400,d0
blo.s loc_3A878
cmpi.w #$1568,d1
bhs.s ObjB2_SCZ_Finished
st (Control_Locked).w
move.w #(button_right_mask<<8)|button_right_mask,(Ctrl_1_Logical).w
bra.w loc_3A87C
; ===========================================================================
loc_3A878:
subi.w #$40,d0
loc_3A87C:
move.w d0,(Camera_Max_X_pos).w
; loc_3A880:
ObjB2_animate:
lea (Ani_objB2_a).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; loc_3A88E:
ObjB2_SCZ_Finished:
bsr.w ObjB2_Deactivate_level
move.w #wing_fortress_zone_act_1,(Current_ZoneAndAct).w
bra.s ObjB2_animate
; ===========================================================================
; loc_3A89A:
ObjB2_Main_WFZ_Start:
bsr.w ObjB2_Animate_Pilot
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3A8BA(pc,d0.w),d1
jsr off_3A8BA(pc,d1.w)
lea (Ani_objB2_a).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (Obj_DeleteOffScreen).l, Obj_DeleteOffScreen
; ===========================================================================
off_3A8BA: offsetTable
offsetTableEntry.w ObjB2_Main_WFZ_Start_init ; 0
offsetTableEntry.w ObjB2_Main_WFZ_Start_main ; 2
offsetTableEntry.w ObjB2_Main_WFZ_Start_shot_down ; 4
offsetTableEntry.w ObjB2_Main_WFZ_Start_fall_down ; 6
; ===========================================================================
; loc_3A8C2:
ObjB2_Main_WFZ_Start_init:
addq.b #2,routine_secondary(a0)
move.w #$C0,objoff_32(a0)
move.w #$100,x_vel(a0)
rts
; ===========================================================================
; loc_3A8D4:
ObjB2_Main_WFZ_Start_main:
subq.w #1,objoff_32(a0)
bmi.s +
move.w x_pos(a0),-(sp)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
bsr.w loc_36776
move.w #$1B,d1
move.w #8,d2
move.w #9,d3
move.w (sp)+,d4
jsrto (SolidObject).l, JmpTo27_SolidObject
bra.w ObjB2_Horizontal_limit
; ===========================================================================
+ ; loc_3A8FC:
addq.b #2,routine_secondary(a0)
move.w #$60,objoff_2A(a0)
move.w #1,objoff_32(a0)
move.w #$100,x_vel(a0)
move.w #$100,y_vel(a0)
rts
; ===========================================================================
; loc_3A91A:
ObjB2_Main_WFZ_Start_shot_down:
move.b (Vint_runcount+3).w,d0
andi.b #$1F,d0
bne.s +
moveq #SndID_Scatter,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
+ ; loc_3A92A:
subq.w #1,objoff_2A(a0)
bmi.s +
- ; loc_3A930:
bsr.w ObjB2_Align_plane
subq.w #1,objoff_32(a0)
bne.w return_37A48
move.w #$E,objoff_32(a0)
bra.w ObjB2_Main_WFZ_Start_load_smoke
; ===========================================================================
+ ; loc_3A946:
addq.b #2,routine_secondary(a0)
bra.w loc_3B7BC
; ===========================================================================
; loc_3A94E:
ObjB2_Main_WFZ_Start_fall_down:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
bra.s -
; ===========================================================================
; loc_3A954:
ObjB2_Main_WFZ_End:
bsr.w ObjB2_Animate_Pilot
moveq #0,d0
move.b routine_secondary(a0),d0
move.w ObjB2_Main_WFZ_states(pc,d0.w),d1
jsr ObjB2_Main_WFZ_states(pc,d1.w)
lea (Ani_objB2_a).l,a1
jmpto (AnimateSprite).l, JmpTo25_AnimateSprite
; ===========================================================================
; off_3A970:
ObjB2_Main_WFZ_states: offsetTable
offsetTableEntry.w ObjB2_Wait_Leader_position ; 0
offsetTableEntry.w ObjB2_Move_Leader_edge ; 2
offsetTableEntry.w ObjB2_Wait_for_plane ; 4
offsetTableEntry.w ObjB2_Prepare_to_jump ; 6
offsetTableEntry.w ObjB2_Jump_to_plane ; 8
offsetTableEntry.w ObjB2_Landed_on_plane ; $A
offsetTableEntry.w ObjB2_Approaching_ship ; $C
offsetTableEntry.w ObjB2_Jump_to_ship ; $E
offsetTableEntry.w ObjB2_Dock_on_DEZ ; $10
; ===========================================================================
; loc_3A982:
ObjB2_Wait_Leader_position:
lea (MainCharacter).w,a1 ; a1=character
cmpi.w #$5EC,y_pos(a1)
blo.s + ; rts
clr.w (Ctrl_1_Logical).w
addq.w #1,objoff_2E(a0)
cmpi.w #$40,objoff_2E(a0)
bhs.s ++
+ ; return_3A99E:
rts
; ===========================================================================
+ ; loc_3A9A0:
addq.b #2,routine_secondary(a0)
move.w #$2E58,x_pos(a0)
move.w #$66C,y_pos(a0)
lea (MainCharacter).w,a1 ; a1=character
bsr.w ObjB2_Waiting_animation
lea (word_3AFBC).l,a2
bsr.w LoadChildObject
move.w #$3118,x_pos(a1)
move.w #$3F0,y_pos(a1)
lea (word_3AFB8).l,a2
bsr.w LoadChildObject
move.w #$3070,x_pos(a1)
move.w #$3B0,y_pos(a1)
lea (word_3AFB8).l,a2
bsr.w LoadChildObject
move.w #$3070,x_pos(a1)
move.w #$430,y_pos(a1)
lea (word_3AFC0).l,a2
bsr.w LoadChildObject
clr.w x_pos(a1)
clr.w y_pos(a1)
rts
; ===========================================================================
; loc_3AA0E: ObjB2_Move_Leader_egde:
ObjB2_Move_Leader_edge:
lea (MainCharacter).w,a1 ; a1=character
cmpi.w #$2E30,x_pos(a1)
bhs.s +
move.w #(button_right_mask<<8)|button_right_mask,(Ctrl_1_Logical).w
rts
; ===========================================================================
+ ; loc_3AA22:
addq.b #2,routine_secondary(a0)
clr.w (Ctrl_1_Logical).w
clr.w x_vel(a1)
clr.w y_vel(a1)
clr.w inertia(a1)
move.w #$600,(Sonic_top_speed).w
move.w #$C,(Sonic_acceleration).w
move.w #$80,(Sonic_deceleration).w
bra.w ObjB2_Waiting_animation
; ===========================================================================
; loc_3AA4C:
ObjB2_Wait_for_plane:
cmpi.w #$380,(Camera_BG_X_offset).w
bhs.s +
clr.w (Ctrl_1_Logical).w
bra.w ObjB2_Waiting_animation
; ===========================================================================
+ ; loc_3AA5C:
addq.b #2,routine_secondary(a0)
move.w #$100,x_vel(a0)
move.w #-$100,y_vel(a0)
clr.w objoff_2A(a0)
bra.w ObjB2_Waiting_animation
; ===========================================================================
; loc_3AA74:
ObjB2_Prepare_to_jump:
bsr.w ObjB2_Waiting_animation
addq.w #1,objoff_2A(a0)
cmpi.w #$30,objoff_2A(a0)
bne.s +
addq.b #2,routine_secondary(a0)
move.w #(button_A_mask<<8)|button_A_mask,(Ctrl_1_Logical).w
move.w #$38,objoff_2E(a0)
tst.b (Super_Sonic_flag).w
beq.s +
move.w #$28,objoff_2E(a0)
+ ; loc_3AAA0:
bsr.w ObjB2_Align_plane
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; loc_3AAA8:
ObjB2_Jump_to_plane:
clr.w (Ctrl_1_Logical).w
addq.w #1,objoff_2A(a0)
subq.w #1,objoff_2E(a0)
bmi.s +
move.w #((button_right_mask|button_A_mask)<<8)|button_right_mask|button_A_mask,(Ctrl_1_Logical).w
+ ; loc_3AABC:
bsr.w ObjB2_Align_plane
btst #p1_standing_bit,status(a0)
beq.s +
addq.b #2,routine_secondary(a0)
move.w #$20,objoff_2E(a0)
lea (Level_Layout+$0D2).w,a1
move.l #$501F0025,(a1)+
lea (Level_Layout+$1D2).w,a1
move.l #$25001F50,(a1)+
lea (Level_Layout+$BD6).w,a1
move.l #$501F0025,(a1)+
lea (Level_Layout+$CD6).w,a1
move.l #$25001F50,(a1)+
+ ; BranchTo6_JmpTo45_DisplaySprite:
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; loc_3AAFE:
ObjB2_Landed_on_plane:
addq.w #1,objoff_2A(a0)
cmpi.w #$100,objoff_2A(a0)
blo.s loc_3AB18
addq.b #2,routine_secondary(a0)
movea.w objoff_3A(a0),a1 ; a1=object ??
move.b #2,routine_secondary(a1)
loc_3AB18:
clr.w (Ctrl_1_Logical).w
lea (MainCharacter).w,a1 ; a1=character
move.w x_pos(a0),x_pos(a1)
clr.w x_vel(a1)
clr.w y_vel(a1)
clr.w inertia(a1)
bclr #1,status(a1)
bclr #2,status(a1)
move.l #$1000505,mapping_frame(a1)
move.w #$100,anim_frame_duration(a1)
move.b #$13,y_radius(a1)
cmpi.w #2,(Player_mode).w
bne.s +
move.b #$F,y_radius(a1)
+ ; loc_3AB60:
bsr.w ObjB2_Align_plane
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; loc_3AB68:
ObjB2_Approaching_ship:
clr.w (Ctrl_1_Logical).w
bsr.w ObjB2_Waiting_animation
cmpi.w #$437,objoff_2A(a0)
blo.s loc_3AB8A
addq.b #2,routine_secondary(a0)
; loc_3AB7C:
ObjB2_Jump_to_ship:
cmpi.w #$447,objoff_2A(a0)
bhs.s loc_3AB8A
move.w #(button_A_mask<<8)|button_A_mask,(Ctrl_1_Logical).w
loc_3AB8A:
cmpi.w #$460,objoff_2A(a0)
blo.s ObjB2_Dock_on_DEZ
move.b #6,(Dynamic_Resize_Routine).w ; => LevEvents_WFZ_Routine4
addq.b #2,routine_secondary(a0)
lea (word_3AFB8).l,a2
bsr.w LoadChildObject
move.w #$3090,x_pos(a1)
move.w #$3D0,y_pos(a1)
lea (word_3AFB8).l,a2
bsr.w LoadChildObject
move.w #$30C0,x_pos(a1)
move.w #$3F0,y_pos(a1)
lea (word_3AFB8).l,a2
bsr.w LoadChildObject
move.w #$3090,x_pos(a1)
move.w #$410,y_pos(a1)
; loc_3ABDE:
ObjB2_Dock_on_DEZ:
cmpi.w #$9C0,objoff_2A(a0)
bhs.s ObjB2_Start_DEZ
move.w objoff_2A(a0),d0
addq.w #1,d0
move.w d0,objoff_2A(a0)
move.w objoff_34(a0),d1
move.w word_3AC16(pc,d1.w),d2
cmp.w d2,d0
blo.s loc_3AC0E
addq.w #2,d1
move.w d1,objoff_34(a0)
lea byte_3AC2A(pc,d1.w),a1
move.b (a1)+,x_vel(a0)
move.b (a1)+,y_vel(a0)
loc_3AC0E:
bsr.w ObjB2_Align_plane
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
word_3AC16:
dc.w $1E0
dc.w $260 ; 1
dc.w $2A0 ; 2
dc.w $2C0 ; 3
dc.w $300 ; 4
dc.w $3A0 ; 5
dc.w $3F0 ; 6
dc.w $460 ; 7
dc.w $4A0 ; 8
dc.w $580 ; 9
byte_3AC2A:
dc.b $FF
dc.b $FF ; 1
dc.b 1 ; 2
dc.b 0 ; 3
dc.b 0 ; 4
dc.b 1 ; 5
dc.b 1 ; 6
dc.b $FF ; 7
dc.b 1 ; 8
dc.b 1 ; 9
dc.b 1 ; 10
dc.b $FF ; 11
dc.b $FF ; 12
dc.b 1 ; 13
dc.b $FF ; 14
dc.b $FF ; 15
dc.b $FF ; 16
dc.b 1 ; 17
dc.b $FE ; 18
dc.b 0 ; 19
dc.b 0 ; 20
dc.b 0 ; 21
; ===========================================================================
; loc_3AC40:
ObjB2_Start_DEZ:
move.w #death_egg_zone_act_1,(Current_ZoneAndAct).w
; loc_3AC46:
ObjB2_Deactivate_level:
move.w #1,(Level_Inactive_flag).w
clr.b (Last_star_pole_hit).w
clr.b (Last_star_pole_hit_2P).w
rts
; ===========================================================================
; loc_3AC56:
ObjB2_Waiting_animation:
lea (MainCharacter).w,a1 ; a1=character
move.l #$1000505,mapping_frame(a1)
move.w #$100,anim_frame_duration(a1)
rts
; ===========================================================================
; loc_3AC6A:
ObjB2_Invisible_grabber:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3AC78(pc,d0.w),d1
jmp off_3AC78(pc,d1.w)
; ===========================================================================
off_3AC78: offsetTable
offsetTableEntry.w loc_3AC7E ; 0
offsetTableEntry.w loc_3AC84 ; 2
offsetTableEntry.w loc_3ACF2 ; 4
; ===========================================================================
loc_3AC7E:
move.b #$C7,collision_flags(a0)
loc_3AC84:
tst.b collision_property(a0)
beq.s return_3ACF0
addq.b #2,routine_secondary(a0)
clr.b collision_flags(a0)
move.w #(224/2)+8,(Camera_Y_pos_bias).w
movea.w objoff_2C(a0),a1 ; a1=object
bset #6,status(a1)
lea (MainCharacter).w,a1 ; a1=character
clr.w x_vel(a1)
clr.w y_vel(a1)
move.w x_pos(a0),d0
subi.w #$10,d0
move.w d0,x_pos(a1)
cmpi.w #2,(Player_mode).w
bne.s loc_3ACC8
subi.w #$10,y_pos(a1)
loc_3ACC8:
bset #0,status(a1)
bclr #1,status(a1)
bclr #2,status(a1)
move.b #AniIDSonAni_Hang,anim(a1)
move.b #1,(MainCharacter+obj_control).w
move.b #1,(WindTunnel_holding_flag).w
clr.w (Ctrl_1_Logical).w
return_3ACF0:
rts
; ===========================================================================
loc_3ACF2:
lea (MainCharacter).w,a1 ; a1=character
clr.w x_vel(a1)
clr.w y_vel(a1)
move.w x_pos(a0),d0
subi.w #$10,d0
move.w d0,x_pos(a1)
rts
; ===========================================================================
loc_3AD0C:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3AD1A(pc,d0.w),d1
jmp off_3AD1A(pc,d1.w)
; ===========================================================================
off_3AD1A: offsetTable
offsetTableEntry.w + ; 0
; ===========================================================================
+ ; loc_3AD1C:
bchg #2,status(a0)
bne.w return_37A48
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3AD2A:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3AD38(pc,d0.w),d1
jmp off_3AD38(pc,d1.w)
; ===========================================================================
off_3AD38: offsetTable
offsetTableEntry.w + ; 0
; ===========================================================================
+ ; loc_3AD3A:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3AD42:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3AD50(pc,d0.w),d1
jmp off_3AD50(pc,d1.w)
; ===========================================================================
off_3AD50: offsetTable
offsetTableEntry.w loc_3AD54 ; 0
offsetTableEntry.w loc_3AD5C ; 2
; ===========================================================================
loc_3AD54:
bsr.w loc_3AD6E
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3AD5C:
bsr.w loc_3AD6E
lea (Ani_objB2_b).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3AD6E:
movea.w objoff_2C(a0),a1 ; a1=object
move.w x_pos(a1),d0
subi.w #$C,d0
move.w d0,x_pos(a0)
move.w y_pos(a1),d0
addi.w #$28,d0
move.w d0,y_pos(a0)
rts
; ===========================================================================
; loc_3AD8C:
ObjB2_Align_plane:
move.w x_pos(a0),-(sp)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
bsr.w loc_36776
move.w #$1B,d1
move.w #8,d2
move.w #9,d3
move.w (sp)+,d4
jmpto (SolidObject).l, JmpTo27_SolidObject
; ===========================================================================
; loc_3ADAA:
ObjB2_Move_with_player:
lea (MainCharacter).w,a1 ; a1=character
btst #3,status(a1)
beq.s ObjB2_Move_below_player
bsr.w ObjB2_Move_vert
bsr.w ObjB2_Vertical_limit
jsrto (ObjectMove).l, JmpTo26_ObjectMove
bra.w loc_36776
; ===========================================================================
; loc_3ADC6:
ObjB2_Move_below_player:
tst.b objoff_2E(a0)
beq.s loc_3ADD4
bsr.w Obj_GetOrientationToPlayer
move.w d2,objoff_38(a0)
loc_3ADD4:
move.w #1,d0
move.w objoff_38(a0),d3
beq.s loc_3ADE8
bmi.s loc_3ADE2
neg.w d0
loc_3ADE2:
add.w d0,d3
move.w d3,objoff_38(a0)
loc_3ADE8:
move.w x_pos(a1),d1
add.w d3,d1
move.w d1,x_pos(a0)
bra.w loc_36776
; ===========================================================================
; loc_3ADF6:
ObjB2_Move_vert:
tst.b objoff_2F(a0)
bne.s loc_3AE16
tst.b objoff_2E(a0)
beq.s return_3AE38
st objoff_2F(a0)
clr.b objoff_30(a0)
move.w #$200,y_vel(a0)
move.b #$14,objoff_31(a0)
loc_3AE16:
subq.b #1,objoff_31(a0)
bpl.s loc_3AE26
clr.b objoff_2F(a0)
clr.w y_vel(a0)
rts
; ===========================================================================
loc_3AE26:
move.w y_vel(a0),d0
cmpi.w #-$100,d0
ble.s loc_3AE34
addi.w #-$20,d0
loc_3AE34:
move.w d0,y_vel(a0)
return_3AE38:
rts
; ===========================================================================
; loc_3AE3A:
ObjB2_Move_obbey_player:
lea (MainCharacter).w,a1 ; a1=character
btst #3,status(a1)
beq.s ObjB2_Move_vert2
tst.b objoff_2F(a0)
bne.s loc_3AE72
clr.w y_vel(a0)
move.w (Ctrl_1).w,d2
move.w #$80,d3
andi.w #(button_up_mask|button_down_mask)<<8,d2
beq.s loc_3AE72
andi.w #button_down_mask<<8,d2
bne.s loc_3AE66
neg.w d3
loc_3AE66:
move.w d3,y_vel(a0)
bsr.w ObjB2_Vertical_limit
jsrto (ObjectMove).l, JmpTo26_ObjectMove
loc_3AE72:
bsr.w Obj_GetOrientationToPlayer
moveq #$10,d3
add.w d3,d2
cmpi.w #$20,d2
blo.s return_3AE9E
mvabs.w inertia(a1),d2
cmpi.w #$900,d2
bhs.s return_3AE9E
tst.w d0
beq.s loc_3AE94
neg.w d3
loc_3AE94:
move.w x_pos(a1),d1
add.w d3,d1
move.w d1,x_pos(a0)
return_3AE9E:
rts
; ===========================================================================
; loc_3AEA0:
ObjB2_Move_vert2:
tst.b objoff_30(a0)
bne.s loc_3AEC0
tst.b objoff_2E(a0)
beq.s return_3AE9E
st objoff_30(a0)
clr.b objoff_2F(a0)
move.w #$200,y_vel(a0)
move.b #$2B,objoff_31(a0)
loc_3AEC0:
subq.b #1,objoff_31(a0)
bpl.s loc_3AED0
clr.b objoff_30(a0)
clr.w y_vel(a0)
rts
; ===========================================================================
loc_3AED0:
move.w y_vel(a0),d0
cmpi.w #-$100,d0
ble.s loc_3AEDE
addi.w #-$20,d0
loc_3AEDE:
move.w d0,y_vel(a0)
bsr.w ObjB2_Vertical_limit
jsrto (ObjectMove).l, JmpTo26_ObjectMove
rts
; ===========================================================================
; loc_3AEEC:
ObjB2_Horizontal_limit:
bsr.w Obj_GetOrientationToPlayer
moveq #$10,d3
add.w d3,d2
cmpi.w #$20,d2
blo.s return_3AF0A
tst.w d0
beq.s loc_3AF00
neg.w d3
loc_3AF00:
move.w x_pos(a0),d1
sub.w d3,d1
move.w d1,x_pos(a1)
return_3AF0A:
rts
; ===========================================================================
; loc_3AF0C:
ObjB2_Vertical_limit:
move.w (Camera_Y_pos).w,d0
move.w y_pos(a0),d1
move.w y_vel(a0),d2
beq.s return_3AF32
bpl.s loc_3AF26
addi.w #$34,d0
cmp.w d0,d1
blo.s loc_3AF2E
rts
; ===========================================================================
loc_3AF26:
addi.w #$A8,d0
cmp.w d0,d1
blo.s return_3AF32
loc_3AF2E:
clr.w y_vel(a0)
return_3AF32:
rts
; ===========================================================================
; loc_3AF34:
ObjB2_Main_WFZ_Start_load_smoke:
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s +
_move.b #ObjID_TornadoSmoke2,id(a1) ; load objC3
move.b #$90,subtype(a1) ; <== ObjC3_SubObjData
move.w a0,objoff_2C(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
+ ; return_3AF56:
rts
; ===========================================================================
; loc_3AF58:
ObjB2_Animate_Pilot:
subq.b #1,objoff_37(a0)
bmi.s +
rts
; ===========================================================================
+ ; loc_3AF60:
move.b #8,objoff_37(a0)
moveq #0,d0
move.b objoff_36(a0),d0
moveq #Tails_pilot_frames_end-Tails_pilot_frames,d1
cmpi.w #2,(Player_mode).w
bne.s +
moveq #Sonic_pilot_frames_end-Sonic_pilot_frames,d1
+ ; loc_3AF78:
addq.b #1,d0
cmp.w d1,d0
blo.s +
moveq #0,d0
+ ; loc_3AF80:
move.b d0,objoff_36(a0)
cmpi.w #2,(Player_mode).w
bne.s +
move.b Sonic_pilot_frames(pc,d0.w),d0
jmpto (LoadSonicDynPLC_Part2).l, JmpTo_LoadSonicDynPLC_Part2
; ===========================================================================
+ ; loc_3AF94:
move.b Tails_pilot_frames(pc,d0.w),d0
jmpto (LoadTailsDynPLC_Part2).l, JmpTo_LoadTailsDynPLC_Part2
; ===========================================================================
; byte_3AF9C:
Sonic_pilot_frames:
dc.b $2D
dc.b $2E ; 1
dc.b $2F ; 2
dc.b $30 ; 3
Sonic_pilot_frames_end:
; byte_3AFA0:
Tails_pilot_frames:
dc.b $10
dc.b $10 ; 1
dc.b $10 ; 2
dc.b $10 ; 3
dc.b 1 ; 4
dc.b 2 ; 5
dc.b 3 ; 6
dc.b 2 ; 7
dc.b 1 ; 8
dc.b 1 ; 9
dc.b $10 ; 10
dc.b $10 ; 11
dc.b $10 ; 12
dc.b $10 ; 13
dc.b 1 ; 14
dc.b 2 ; 15
dc.b 3 ; 16
dc.b 2 ; 17
dc.b 1 ; 18
dc.b 1 ; 19
dc.b 4 ; 20
dc.b 4 ; 21
dc.b 1 ; 22
dc.b 1 ; 23
Tails_pilot_frames_end:
word_3AFB8:
dc.w objoff_3E
dc.b ObjID_Tornado
dc.b $58
word_3AFBC:
dc.w objoff_3C
dc.b ObjID_Tornado
dc.b $56
word_3AFC0:
dc.w objoff_3A
dc.b ObjID_Tornado
dc.b $5C
; seems unused
dc.w objoff_3E
dc.b ObjID_Tornado
dc.b $5A
; off_3AFC8:
ObjB2_SubObjData:
subObjData ObjB2_MapUnc_3AFF2,make_art_tile(ArtTile_ArtNem_Tornado,0,1),4,4,$60,0
; off_3AFD2:
ObjB2_SubObjData2:
subObjData ObjB2_MapUnc_3B292,make_art_tile(ArtTile_ArtNem_TornadoThruster,0,0),4,3,$40,0
; animation script
; off_3AFDC:
Ani_objB2_a: offsetTable
offsetTableEntry.w byte_3AFE0 ; 0
offsetTableEntry.w byte_3AFE6 ; 1
byte_3AFE0: dc.b 0, 0, 1, 2, 3,$FF
byte_3AFE6: dc.b 0, 4, 5, 6, 7,$FF
even
; animation script
; off_3AFEC:
Ani_objB2_b: offsetTable
offsetTableEntry.w + ; 0
; byte_3AFEE:
+ dc.b 0, 1, 2,$FF
even
; -----------------------------------------------------------------------------
; sprite mappings
; -----------------------------------------------------------------------------
ObjB2_MapUnc_3AFF2: BINCLUDE "mappings/sprite/objB2_a.bin"
; -----------------------------------------------------------------------------
; sprite mappings
; -----------------------------------------------------------------------------
ObjB2_MapUnc_3B292: BINCLUDE "mappings/sprite/objB2_b.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object B3 - Clouds (placeable object) from SCZ
; ----------------------------------------------------------------------------
; Sprite_3B2DE:
ObjB3:
moveq #0,d0
move.b routine(a0),d0
move.w ObjB3_Index(pc,d0.w),d1
jmp ObjB3_Index(pc,d1.w)
; ===========================================================================
; off_3B2EC:
ObjB3_Index: offsetTable
offsetTableEntry.w ObjB3_Init ; 0
offsetTableEntry.w ObjB3_Main ; 2
; ===========================================================================
; loc_3B2F0:
ObjB3_Init:
bsr.w LoadSubObject
moveq #0,d0
move.b subtype(a0),d0
subi.b #$5E,d0
move.w word_3B30C(pc,d0.w),x_vel(a0)
lsr.w #1,d0
move.b d0,mapping_frame(a0)
rts
; ===========================================================================
word_3B30C:
dc.w -$80
dc.w -$40 ; 1
dc.w -$20 ; 2
; ===========================================================================
; loc_3B312:
ObjB3_Main:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
move.w (Tornado_Velocity_X).w,d0
add.w d0,x_pos(a0)
bra.w Obj_DeleteBehindScreen
; ===========================================================================
; off_3B322:
ObjB3_SubObjData:
subObjData ObjB3_MapUnc_3B32C,make_art_tile(ArtTile_ArtNem_Clouds,2,0),4,6,$30,0
; -----------------------------------------------------------------------------
; sprite mappings
; -----------------------------------------------------------------------------
ObjB3_MapUnc_3B32C: BINCLUDE "mappings/sprite/objB3.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object B4 - Vertical propeller from WFZ
; ----------------------------------------------------------------------------
; Sprite_3B36A:
ObjB4:
moveq #0,d0
move.b routine(a0),d0
move.w ObjB4_Index(pc,d0.w),d1
jmp ObjB4_Index(pc,d1.w)
; ===========================================================================
; off_3B378:
ObjB4_Index: offsetTable
offsetTableEntry.w ObjB4_Init ; 0
offsetTableEntry.w ObjB4_Main ; 2
; ===========================================================================
; loc_3B37C:
ObjB4_Init:
bsr.w LoadSubObject
bclr #1,render_flags(a0)
beq.s +
clr.b collision_flags(a0)
+
rts
; ===========================================================================
; loc_3B38E:
ObjB4_Main:
lea (Ani_objB4).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
move.b (Vint_runcount+3).w,d0
andi.b #$1F,d0
bne.s +
moveq #SndID_Helicopter,d0
jsrto (PlaySoundLocal).l, JmpTo_PlaySoundLocal
+
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; off_3B3AC:
ObjB4_SubObjData:
subObjData ObjB4_MapUnc_3B3BE,make_art_tile(ArtTile_ArtNem_WfzVrtclPrpllr,1,1),4,4,4,$A8
; animation script
; off_3B3B6:
Ani_objB4: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 1, 0, 1, 2,$FF, 0
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjB4_MapUnc_3B3BE: BINCLUDE "mappings/sprite/objB4.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object B5 - Horizontal propeller from WFZ
; ----------------------------------------------------------------------------
; Sprite_3B3FA:
ObjB5:
moveq #0,d0
move.b routine(a0),d0
move.w ObjB5_Index(pc,d0.w),d1
jmp ObjB5_Index(pc,d1.w)
; ===========================================================================
; off_3B408:
ObjB5_Index: offsetTable
offsetTableEntry.w ObjB5_Init ; 0
offsetTableEntry.w ObjB5_Main ; 2 - used in WFZ
offsetTableEntry.w ObjB5_Animate ; 4 - used in SCZ, no effect on players
; ===========================================================================
; loc_3B40E:
ObjB5_Init:
bsr.w LoadSubObject
move.b #4,anim(a0)
move.b subtype(a0),d0
subi.b #$64,d0
move.b d0,routine(a0)
rts
; ===========================================================================
; loc_3B426:
ObjB5_Main:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3B442(pc,d0.w),d1
jsr off_3B442(pc,d1.w)
lea (Ani_objB5).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
off_3B442: offsetTable
offsetTableEntry.w + ; 0
; ===========================================================================
+ bra.w ObjB5_CheckPlayers
; ===========================================================================
; loc_3B448:
ObjB5_Animate:
lea (Ani_objB5).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_3B456:
ObjB5_CheckPlayers:
cmpi.b #4,anim(a0)
bne.s ++ ; rts
lea (MainCharacter).w,a1 ; a1=character
bsr.w ObjB5_CheckPlayer
lea (Sidekick).w,a1 ; a1=character
; loc_3B46A:
ObjB5_CheckPlayer:
move.w x_pos(a1),d0
sub.w x_pos(a0),d0
addi.w #$40,d0
cmpi.w #$80,d0
bhs.s ++ ; rts
moveq #0,d1
move.b (Oscillating_Data+$14).w,d1
add.w y_pos(a1),d1
addi.w #$60,d1
sub.w y_pos(a0),d1
bcs.s ++ ; rts
cmpi.w #$90,d1
bhs.s ++ ; rts
subi.w #$60,d1
bcs.s +
not.w d1
add.w d1,d1
+
addi.w #$60,d1
neg.w d1
asr.w #4,d1
add.w d1,y_pos(a1)
bset #1,status(a1)
move.w #0,y_vel(a1)
move.w #1,inertia(a1)
tst.b flip_angle(a1)
bne.s + ; rts
move.b #1,flip_angle(a1)
move.b #AniIDSonAni_Float2,anim(a1)
move.b #$7F,flips_remaining(a1)
move.b #8,flip_speed(a1)
+
rts
; ===========================================================================
; off_3B4DE:
ObjB5_SubObjData:
subObjData ObjB5_MapUnc_3B548,make_art_tile(ArtTile_ArtNem_WfzHrzntlPrpllr,1,1),4,4,$40,0
; animation script
; off_3B4E8:
Ani_objB5: offsetTable
offsetTableEntry.w byte_3B4FC ; 0
offsetTableEntry.w byte_3B506 ; 1
offsetTableEntry.w byte_3B50E ; 2
offsetTableEntry.w byte_3B516 ; 3
offsetTableEntry.w byte_3B51C ; 4
offsetTableEntry.w byte_3B524 ; 5
offsetTableEntry.w byte_3B52A ; 6
offsetTableEntry.w byte_3B532 ; 7
offsetTableEntry.w byte_3B53A ; 8
offsetTableEntry.w byte_3B544 ; 9
byte_3B4FC: dc.b 7, 0, 1, 2, 3, 4, 5,$FD, 1, 0
byte_3B506: dc.b 4, 0, 1, 2, 3, 4,$FD, 2
byte_3B50E: dc.b 3, 5, 0, 1, 2,$FD, 3, 0
byte_3B516: dc.b 2, 3, 4, 5,$FD, 4
byte_3B51C: dc.b 1, 0, 1, 2, 3, 4, 5,$FF
byte_3B524: dc.b 2, 5, 4, 3,$FD, 6
byte_3B52A: dc.b 3, 2, 1, 0, 5,$FD, 7, 0
byte_3B532: dc.b 4, 4, 3, 2, 1, 0,$FD, 8
byte_3B53A: dc.b 7, 5, 4, 3, 2, 1, 0,$FD, 9, 0
byte_3B544: dc.b $7E, 0,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjB5_MapUnc_3B548: BINCLUDE "mappings/sprite/objB5.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object B6 - Tilting platform from WFZ
; ----------------------------------------------------------------------------
; Sprite_3B5D0:
ObjB6:
moveq #0,d0
move.b routine(a0),d0
move.w ObjB6_Index(pc,d0.w),d1
jmp ObjB6_Index(pc,d1.w)
; ===========================================================================
; off_3B5DE:
ObjB6_Index: offsetTable
offsetTableEntry.w ObjB6_Init ; 0
offsetTableEntry.w loc_3B602 ; 2
offsetTableEntry.w loc_3B65C ; 4
offsetTableEntry.w loc_3B6C8 ; 6
offsetTableEntry.w loc_3B73C ; 8
; ===========================================================================
; loc_3B5E8:
ObjB6_Init:
moveq #0,d0
move.b #($35<<1),d0
bsr.w LoadSubObject_Part2
move.b subtype(a0),d0
andi.b #6,d0
addq.b #2,d0
move.b d0,routine(a0)
rts
; ===========================================================================
loc_3B602:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3B614(pc,d0.w),d1
jsr off_3B614(pc,d1.w)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
off_3B614: offsetTable
offsetTableEntry.w loc_3B61C ; 0
offsetTableEntry.w loc_3B624 ; 2
offsetTableEntry.w loc_3B644 ; 4
offsetTableEntry.w loc_3B64E ; 6
; ===========================================================================
loc_3B61C:
addq.b #2,routine_secondary(a0)
bra.w loc_3B77E
; ===========================================================================
loc_3B624:
bsr.w loc_3B790
move.b (Vint_runcount+3).w,d0
andi.b #$F0,d0
cmp.b subtype(a0),d0
beq.s loc_3B638
rts
; ===========================================================================
loc_3B638:
addq.b #2,routine_secondary(a0)
clr.b anim(a0)
bra.w loc_3B7BC
; ===========================================================================
loc_3B644:
lea (Ani_objB6).l,a1
jmpto (AnimateSprite).l, JmpTo25_AnimateSprite
; ===========================================================================
loc_3B64E:
move.b #2,routine_secondary(a0)
move.w #$C0,objoff_2A(a0)
rts
; ===========================================================================
loc_3B65C:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3B66E(pc,d0.w),d1
jsr off_3B66E(pc,d1.w)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
off_3B66E: offsetTable
offsetTableEntry.w loc_3B61C
offsetTableEntry.w loc_3B674
offsetTableEntry.w loc_3B6A6
; ===========================================================================
loc_3B674:
bsr.w loc_3B790
subq.w #1,objoff_2A(a0)
bmi.s +
rts
; ===========================================================================
+
addq.b #2,routine_secondary(a0)
move.b #$20,objoff_2A(a0)
move.b #3,anim(a0)
clr.b anim_frame(a0)
clr.b anim_frame_duration(a0)
bsr.w loc_3B7BC
bsr.w loc_3B7F8
moveq #SndID_Fire,d0
jmpto (PlaySound).l, JmpTo12_PlaySound
; ===========================================================================
loc_3B6A6:
subq.b #1,objoff_2A(a0)
bmi.s +
lea (Ani_objB6).l,a1
jmpto (AnimateSprite).l, JmpTo25_AnimateSprite
; ===========================================================================
+
move.b #2,routine_secondary(a0)
clr.b mapping_frame(a0)
move.w #$C0,objoff_2A(a0)
rts
; ===========================================================================
loc_3B6C8:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3B6DA(pc,d0.w),d1
jsr off_3B6DA(pc,d1.w)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
off_3B6DA: offsetTable
offsetTableEntry.w loc_3B6E2 ; 0
offsetTableEntry.w loc_3B6FE ; 2
offsetTableEntry.w loc_3B72C ; 4
offsetTableEntry.w loc_3B736 ; 6
; ===========================================================================
loc_3B6E2:
bsr.w loc_3B790
move.b status(a0),d0
andi.b #standing_mask,d0
bne.s +
rts
; ===========================================================================
+
addq.b #2,routine_secondary(a0)
move.w #$10,objoff_2A(a0)
rts
; ===========================================================================
loc_3B6FE:
bsr.w loc_3B790
subq.w #1,objoff_2A(a0)
bmi.s +
rts
; ===========================================================================
+
addq.b #2,routine_secondary(a0)
move.b #0,anim(a0)
bsr.w Obj_GetOrientationToPlayer
bclr #0,status(a0)
tst.w d0
bne.s +
bset #0,status(a0)
+
bra.w loc_3B7BC
; ===========================================================================
loc_3B72C:
lea (Ani_objB6).l,a1
jmpto (AnimateSprite).l, JmpTo25_AnimateSprite
; ===========================================================================
loc_3B736:
clr.b routine_secondary(a0)
rts
; ===========================================================================
loc_3B73C:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3B74E(pc,d0.w),d1
jsr off_3B74E(pc,d1.w)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
off_3B74E: offsetTable
offsetTableEntry.w loc_3B756 ; 0
offsetTableEntry.w loc_3B764 ; 2
offsetTableEntry.w loc_3B644 ; 4
offsetTableEntry.w loc_3B64E ; 6
; ===========================================================================
loc_3B756:
addq.b #2,routine_secondary(a0)
move.b #2,mapping_frame(a0)
bra.w loc_3B77E
; ===========================================================================
loc_3B764:
bsr.w loc_3B7A6
subq.w #1,objoff_2A(a0)
bmi.s loc_3B770
rts
; ===========================================================================
loc_3B770:
addq.b #2,routine_secondary(a0)
move.b #4,anim(a0)
bra.w loc_3B7BC
; ===========================================================================
loc_3B77E:
move.b subtype(a0),d0
andi.w #$F0,d0
move.b d0,subtype(a0)
move.w d0,objoff_2A(a0)
rts
; ===========================================================================
loc_3B790:
move.w x_pos(a0),-(sp)
move.w #$23,d1
move.w #4,d2
move.w #4,d3
move.w (sp)+,d4
jmpto (SolidObject).l, JmpTo27_SolidObject
; ===========================================================================
loc_3B7A6:
move.w x_pos(a0),-(sp)
move.w #$F,d1
move.w #$18,d2
move.w #$18,d3
move.w (sp)+,d4
jmpto (SolidObject).l, JmpTo27_SolidObject
; ===========================================================================
loc_3B7BC:
move.b status(a0),d0
if gameRevision<2
andi.b #standing_mask,d0
else
; I don't know what this change was meant to do, but it causes
; Sonic to not fall off ObjBD's ascending platforms when they retract,
; making him hover.
andi.b #2,d0
endif
beq.s return_3B7F6
bclr #p1_standing_bit,status(a0)
beq.s loc_3B7DE
lea (MainCharacter).w,a1 ; a1=character
bclr #3,status(a1)
bset #1,status(a1)
loc_3B7DE:
bclr #p2_standing_bit,status(a0)
beq.s return_3B7F6
lea (Sidekick).w,a1 ; a1=character
bclr #4,status(a1)
bset #1,status(a1)
return_3B7F6:
rts
; ===========================================================================
loc_3B7F8:
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s +
_move.b #ObjID_VerticalLaser,id(a1) ; load objB7 (huge unused vertical laser!)
move.b #$72,subtype(a1) ; <== ObjB7_SubObjData
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
+
rts
; ===========================================================================
; off_3B818:
ObjB6_SubObjData:
subObjData ObjB6_MapUnc_3B856,make_art_tile(ArtTile_ArtNem_WfzTiltPlatforms,1,1),4,4,$10,0
; animation script
; off_3B822:
Ani_objB6: offsetTable
offsetTableEntry.w byte_3B830 ; 0
offsetTableEntry.w byte_3B836 ; 1
offsetTableEntry.w byte_3B83A ; 2
offsetTableEntry.w byte_3B840 ; 3
offsetTableEntry.w byte_3B846 ; 4
offsetTableEntry.w byte_3B84C ; 5
offsetTableEntry.w byte_3B850 ; 6
byte_3B830: dc.b 3, 1, 2,$FD, 1, 0
byte_3B836: dc.b $3F, 2,$FD, 2
byte_3B83A: dc.b 3, 2, 1, 0,$FA, 0
byte_3B840: dc.b 1, 0, 1, 2, 3,$FF
byte_3B846: dc.b 3, 1, 0,$FD, 5, 0
byte_3B84C: dc.b $3F, 0,$FD, 6
byte_3B850: dc.b 3, 0, 1, 2,$FA, 0
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjB6_MapUnc_3B856: BINCLUDE "mappings/sprite/objB6.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object B7 - Unused huge vertical laser from WFZ
; ----------------------------------------------------------------------------
; Sprite_3B8A6:
ObjB7:
moveq #0,d0
move.b routine(a0),d0
move.w ObjB7_Index(pc,d0.w),d1
jmp ObjB7_Index(pc,d1.w)
; ===========================================================================
; off_3B8B4:
ObjB7_Index: offsetTable
offsetTableEntry.w ObjB7_Init ; 0
offsetTableEntry.w ObjB7_Main ; 2
; ===========================================================================
; loc_3B8B8:
ObjB7_Init:
bsr.w LoadSubObject
move.b #$20,objoff_2A(a0)
rts
; ===========================================================================
; loc_3B8C4:
ObjB7_Main:
subq.b #1,objoff_2A(a0)
beq.w JmpTo65_DeleteObject
bchg #0,objoff_2B(a0)
beq.w return_37A48
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; off_3B8DA:
ObjB7_SubObjData:
subObjData ObjB7_MapUnc_3B8E4,make_art_tile(ArtTile_ArtNem_WfzVrtclLazer,2,1),4,4,$18,$A9
ObjB7_MapUnc_3B8E4: BINCLUDE "mappings/sprite/objB7.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object B8 - Wall turret from WFZ
; ----------------------------------------------------------------------------
; Sprite_3B968:
ObjB8:
moveq #0,d0
move.b routine(a0),d0
move.w ObjB8_Index(pc,d0.w),d1
jmp ObjB8_Index(pc,d1.w)
; ===========================================================================
; off_3B976:
ObjB8_Index: offsetTable
offsetTableEntry.w ObjB8_Init ; 0
offsetTableEntry.w loc_3B980 ; 2
offsetTableEntry.w loc_3B9AA ; 4
; ===========================================================================
; BranchTo5_LoadSubObject
ObjB8_Init:
bra.w LoadSubObject
; ===========================================================================
loc_3B980:
tst.b render_flags(a0)
bpl.s +
bsr.w Obj_GetOrientationToPlayer
tst.w d1
beq.s +
addi.w #$60,d2
cmpi.w #$C0,d2
blo.s ++
+
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
+
addq.b #2,routine(a0)
move.w #2,objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3B9AA:
bsr.w Obj_GetOrientationToPlayer
moveq #0,d6
addi.w #$20,d2
cmpi.w #$40,d2
blo.s loc_3B9C0
move.w d0,d6
lsr.w #1,d6
addq.w #1,d6
loc_3B9C0:
move.b d6,mapping_frame(a0)
subq.w #1,objoff_2A(a0)
bne.s +
move.w #$60,objoff_2A(a0)
bsr.w loc_3B9D8
+
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3B9D8:
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s + ; rts
_move.b #ObjID_Projectile,id(a1) ; load obj98
move.b #3,mapping_frame(a1)
move.b #$8E,subtype(a1) ; <== ObjB8_SubObjData2
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
lea_ Obj98_WallTurretShotMove,a2
move.l a2,objoff_2A(a1)
moveq #0,d0
move.b mapping_frame(a0),d0
lsl.w #2,d0
lea byte_3BA2A(pc,d0.w),a2
move.b (a2)+,d0
ext.w d0
add.w d0,x_pos(a1)
move.b (a2)+,d0
ext.w d0
add.w d0,y_pos(a1)
move.b (a2)+,x_vel(a1)
move.b (a2)+,y_vel(a1)
+
rts
; ===========================================================================
byte_3BA2A:
dc.b 0
dc.b $18 ; 1
dc.b 0 ; 2
dc.b 1 ; 3
dc.b $EF ; 4
dc.b $10 ; 5
dc.b $FF ; 6
dc.b 1 ; 7
dc.b $11 ; 8
dc.b $10 ; 9
dc.b 1 ; 10
dc.b 1 ; 11
; off_3BA36:
ObjB8_SubObjData:
subObjData ObjB8_Obj98_MapUnc_3BA46,make_art_tile(ArtTile_ArtNem_WfzWallTurret,0,0),4,4,$10,0
; animation script
; off_3BA40:
Ani_WallTurretShot: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 2, 3, 4,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjB8_Obj98_MapUnc_3BA46: BINCLUDE "mappings/sprite/objB8.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object B9 - Laser from WFZ that shoots down the Tornado
; ----------------------------------------------------------------------------
; Sprite_3BABA:
ObjB9:
moveq #0,d0
move.b routine(a0),d0
move.w ObjB9_Index(pc,d0.w),d1
jmp ObjB9_Index(pc,d1.w)
; ===========================================================================
; off_3BAC8:
ObjB9_Index: offsetTable
offsetTableEntry.w ObjB9_Init
offsetTableEntry.w loc_3BAD2
offsetTableEntry.w loc_3BAF0
; ===========================================================================
; BranchTo6_LoadSubObject
ObjB9_Init:
bra.w LoadSubObject
; ===========================================================================
loc_3BAD2:
tst.b render_flags(a0)
bmi.s +
bra.w loc_3BAF8
; ===========================================================================
+
addq.b #2,routine(a0)
move.w #-$1000,x_vel(a0)
moveq #SndID_LargeLaser,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
bra.w loc_3BAF8
; ===========================================================================
loc_3BAF0:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
bra.w loc_3BAF8
loc_3BAF8:
move.w x_pos(a0),d0
move.w (Camera_X_pos).w,d1
subi.w #$40,d1
cmp.w d1,d0
blt.w JmpTo65_DeleteObject
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; off_3BB0E:
ObjB9_SubObjData:
subObjData ObjB9_MapUnc_3BB18,make_art_tile(ArtTile_ArtNem_WfzHrzntlLazer,2,1),4,1,$60,0
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjB9_MapUnc_3BB18: BINCLUDE "mappings/sprite/objB9.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object BA - Wheel from WFZ
; ----------------------------------------------------------------------------
; Sprite_3BB4C:
ObjBA:
moveq #0,d0
move.b routine(a0),d0
move.w ObjBA_Index(pc,d0.w),d1
jmp ObjBA_Index(pc,d1.w)
; ===========================================================================
; off_3BB5A:
ObjBA_Index: offsetTable
offsetTableEntry.w ObjBA_Init ; 0
offsetTableEntry.w ObjBA_Main ; 2
; ===========================================================================
; BranchTo7_LoadSubObject
ObjBA_Init:
bra.w LoadSubObject
; ===========================================================================
; BranchTo14_JmpTo39_MarkObjGone
ObjBA_Main:
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; off_3BB66:
ObjBA_SubObjData:
subObjData ObjBA_MapUnc_3BB70,make_art_tile(ArtTile_ArtNem_WfzConveyorBeltWheel,2,1),4,4,$10,0
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjBA_MapUnc_3BB70: BINCLUDE "mappings/sprite/objBA.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object BB - Removed object (unknown, unused)
; ----------------------------------------------------------------------------
; Sprite_3BB7C:
ObjBB:
moveq #0,d0
move.b routine(a0),d0
move.w ObjBB_Index(pc,d0.w),d1
jmp ObjBB_Index(pc,d1.w)
; ===========================================================================
; off_3BB8A:
ObjBB_Index: offsetTable
offsetTableEntry.w ObjBB_Init ; 0
offsetTableEntry.w ObjBB_Main ; 2
; ===========================================================================
; BranchTo8_LoadSubObject
ObjBB_Init:
bra.w LoadSubObject
; ===========================================================================
; BranchTo15_JmpTo39_MarkObjGone
ObjBB_Main:
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; off_3BB96:
ObjBB_SubObjData:
subObjData ObjBB_MapUnc_3BBA0,make_art_tile(ArtTile_ArtNem_Unknown,1,0),4,4,$C,9
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjBB_MapUnc_3BBA0: BINCLUDE "mappings/sprite/objBB.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object BC - Fire coming out of Robotnik's ship in WFZ
; ----------------------------------------------------------------------------
; Sprite_3BBBC:
ObjBC:
moveq #0,d0
move.b routine(a0),d0
move.w ObjBC_Index(pc,d0.w),d1
jmp ObjBC_Index(pc,d1.w)
; ===========================================================================
; off_3BBCA:
ObjBC_Index: offsetTable
offsetTableEntry.w ObjBC_Init
offsetTableEntry.w ObjBC_Main
; ===========================================================================
; loc_3BBCE:
ObjBC_Init:
bsr.w LoadSubObject
move.w x_pos(a0),objoff_2C(a0)
rts
; ===========================================================================
; loc_3BBDA:
ObjBC_Main:
move.w objoff_2C(a0),d0
move.w (Camera_BG_X_offset).w,d1
cmpi.w #$380,d1
bhs.w JmpTo65_DeleteObject
add.w d1,d0
move.w d0,x_pos(a0)
bchg #0,objoff_2A(a0)
beq.w return_37A48
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; off_3BBFE:
ObjBC_SubObjData2:
subObjData ObjBC_MapUnc_3BC08,make_art_tile(ArtTile_ArtNem_WfzThrust,2,0),4,4,$10,0
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjBC_MapUnc_3BC08: BINCLUDE "mappings/sprite/objBC.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object BD - Ascending/descending metal platforms from WFZ
; ----------------------------------------------------------------------------
; Sprite_3BC1C:
ObjBD:
moveq #0,d0
move.b routine(a0),d0
move.w ObjBD_Index(pc,d0.w),d1
jmp ObjBD_Index(pc,d1.w)
; ===========================================================================
; off_3BC2A:
ObjBD_Index: offsetTable
offsetTableEntry.w ObjBD_Init ; 0
offsetTableEntry.w loc_3BC3C ; 2
offsetTableEntry.w loc_3BC50 ; 4
; ===========================================================================
; loc_3BC30:
ObjBD_Init:
addq.b #2,routine(a0)
move.w #1,objoff_2A(a0)
rts
; ===========================================================================
loc_3BC3C:
subq.w #1,objoff_2A(a0)
bne.s +
move.w #$40,objoff_2A(a0)
bsr.w loc_3BCF8
+
jmpto (MarkObjGone3).l, JmpTo8_MarkObjGone3
; ===========================================================================
loc_3BC50:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3BC62(pc,d0.w),d1
jsr off_3BC62(pc,d1.w)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
off_3BC62: offsetTable
offsetTableEntry.w loc_3BC6C ; 0
offsetTableEntry.w loc_3BCAC ; 2
offsetTableEntry.w loc_3BCB6 ; 4
offsetTableEntry.w loc_3BCCC ; 6
offsetTableEntry.w loc_3BCD6 ; 8
; ===========================================================================
loc_3BC6C:
bsr.w LoadSubObject
move.b #2,mapping_frame(a0)
subq.b #2,routine(a0)
addq.b #2,routine_secondary(a0)
move.w #$C7,objoff_2A(a0)
btst #0,render_flags(a0)
beq.s loc_3BC92
move.w #$1C7,objoff_2A(a0)
loc_3BC92:
moveq #0,d0
move.b subtype(a0),d0
subi.b #$7E,d0
move.b d0,subtype(a0)
move.w word_3BCA8(pc,d0.w),y_vel(a0)
rts
; ===========================================================================
word_3BCA8:
dc.w -$100
dc.w $100 ; 1
; ===========================================================================
loc_3BCAC:
lea (Ani_objBD).l,a1
jmpto (AnimateSprite).l, JmpTo25_AnimateSprite
; ===========================================================================
loc_3BCB6:
subq.w #1,objoff_2A(a0)
bmi.s loc_3BCC0
bra.w loc_3BCDE
; ===========================================================================
loc_3BCC0:
addq.b #2,routine_secondary(a0)
move.b #1,anim(a0)
rts
; ===========================================================================
loc_3BCCC:
lea (Ani_objBD).l,a1
jmpto (AnimateSprite).l, JmpTo25_AnimateSprite
; ===========================================================================
loc_3BCD6:
bsr.w loc_3B7BC
bra.w JmpTo65_DeleteObject
; ===========================================================================
loc_3BCDE:
move.w x_pos(a0),-(sp)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
move.w #$23,d1
move.w #4,d2
move.w #5,d3
move.w (sp)+,d4
jmpto (PlatformObject).l, JmpTo9_PlatformObject
; ===========================================================================
loc_3BCF8:
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s + ; rts
_move.b #ObjID_SmallMetalPform,id(a1) ; load objBD
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.b #4,routine(a1)
move.b subtype(a0),subtype(a1)
move.b render_flags(a0),render_flags(a1)
+
rts
; ===========================================================================
; off_3BD24:
ObjBD_SubObjData:
subObjData ObjBD_MapUnc_3BD3E,make_art_tile(ArtTile_ArtNem_WfzBeltPlatform,3,1),4,4,$18,0
; animation script
; off_3BD2E:
Ani_objBD: offsetTable
offsetTableEntry.w byte_3BD32 ; 0
offsetTableEntry.w byte_3BD38 ; 1
byte_3BD32: dc.b 3, 2, 1, 0,$FA, 0
byte_3BD38: dc.b 1, 0, 1, 2,$FA
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjBD_MapUnc_3BD3E: BINCLUDE "mappings/sprite/objBD.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object BE - Lateral cannon (temporary platform that pops in/out) from WFZ
; ----------------------------------------------------------------------------
; Sprite_3BD7A:
ObjBE:
moveq #0,d0
move.b routine(a0),d0
move.w ObjBE_Index(pc,d0.w),d1
jmp ObjBE_Index(pc,d1.w)
; ===========================================================================
; off_3BD88:
ObjBE_Index: offsetTable
offsetTableEntry.w ObjBE_Init ; 0
offsetTableEntry.w loc_3BDA2 ; 2
offsetTableEntry.w loc_3BDC6 ; 4
offsetTableEntry.w loc_3BDD4 ; 6
offsetTableEntry.w loc_3BDC6 ; 8
offsetTableEntry.w loc_3BDF4 ; $A
; ===========================================================================
; loc_3BD94:
ObjBE_Init:
moveq #0,d0
move.b #($41<<1),d0
bsr.w LoadSubObject_Part2
bra.w loc_3B77E
; ===========================================================================
loc_3BDA2:
move.b (Vint_runcount+3).w,d0
andi.b #$F0,d0
cmp.b subtype(a0),d0
beq.s +
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ---------------------------------------------------------------------------
+
addq.b #2,routine(a0)
clr.b anim(a0)
move.w #$A0,objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3BDC6:
lea (Ani_objBE).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3BDD4:
subq.w #1,objoff_2A(a0)
beq.s +
bsr.w loc_3BE04
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ---------------------------------------------------------------------------
+
addq.b #2,routine(a0)
move.b #1,anim(a0)
bsr.w loc_3B7BC
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3BDF4:
move.b #2,routine(a0)
move.w #$40,objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3BE04:
move.b mapping_frame(a0),d0
cmpi.b #3,d0
beq.s +
cmpi.b #4,d0
bne.w loc_3B7BC
+
move.w x_pos(a0),-(sp)
move.w #$23,d1
move.w #$18,d2
move.w #$19,d3
move.w (sp)+,d4
jmpto (PlatformObject).l, JmpTo9_PlatformObject
; ===========================================================================
; off_3BE2C:
ObjBE_SubObjData:
subObjData ObjBE_MapUnc_3BE46,make_art_tile(ArtTile_ArtNem_WfzGunPlatform,3,1),4,4,$18,0
; animation script
; off_3BE36:
Ani_objBE: offsetTable
offsetTableEntry.w byte_3BE3A ; 0
offsetTableEntry.w byte_3BE40 ; 1
byte_3BE3A: dc.b 5, 0, 1, 2, 3,$FC
byte_3BE40: dc.b 5, 3, 2, 1, 0,$FC
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjBE_MapUnc_3BE46: BINCLUDE "mappings/sprite/objBE.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object BF - Rotaty-stick badnik from WFZ
; ----------------------------------------------------------------------------
; Sprite_3BEAA:
ObjBF:
moveq #0,d0
move.b routine(a0),d0
move.w ObjBF_Index(pc,d0.w),d1
jmp ObjBF_Index(pc,d1.w)
; ===========================================================================
; off_3BEB8:
ObjBF_Index: offsetTable
offsetTableEntry.w ObjBF_Init ; 0
offsetTableEntry.w ObjBF_Animate ; 2
; ===========================================================================
; BranchTo9_LoadSubObject
ObjBF_Init:
bra.w LoadSubObject
; ===========================================================================
; loc_3BEC0:
ObjBF_Animate:
lea (Ani_objBF).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; off_3BECE:
ObjBE_SubObjData2:
subObjData ObjBF_MapUnc_3BEE0,make_art_tile(ArtTile_ArtNem_WfzUnusedBadnik,3,1),4,4,4,4
; animation script
; off_3BED8:
Ani_objBF: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 1, 0, 1, 2,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjBF_MapUnc_3BEE0: BINCLUDE "mappings/sprite/objBF.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object C0 - Speed launcher from WFZ
; ----------------------------------------------------------------------------
; Sprite_3BF04:
ObjC0:
moveq #0,d0
move.b routine(a0),d0
move.w ObjC0_Index(pc,d0.w),d1
jmp ObjC0_Index(pc,d1.w)
; ===========================================================================
; off_3BF12:
ObjC0_Index: offsetTable
offsetTableEntry.w ObjC0_Init ; 0
offsetTableEntry.w ObjC0_Main ; 2
; ===========================================================================
; loc_3BF16:
ObjC0_Init:
move.w #($43<<1),d0
bsr.w LoadSubObject_Part2
moveq #0,d0
move.b subtype(a0),d0
lsl.w #4,d0
btst #0,status(a0)
bne.s +
neg.w d0
+
move.w x_pos(a0),d1
move.w d1,objoff_34(a0)
add.w d1,d0
move.w d0,objoff_32(a0)
; loc_3BF3E:
ObjC0_Main:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3BF60(pc,d0.w),d1
jsr off_3BF60(pc,d1.w)
move.w #$10,d1
move.w #$11,d3
move.w x_pos(a0),d4
jsrto (PlatformObject).l, JmpTo9_PlatformObject
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
off_3BF60: offsetTable
offsetTableEntry.w loc_3BF66
offsetTableEntry.w loc_3BFD8
offsetTableEntry.w loc_3C062
; ===========================================================================
loc_3BF66:
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s +++ ; rts
addq.b #2,routine_secondary(a0)
move.w #$C00,x_vel(a0)
move.w #$80,objoff_30(a0)
btst #0,status(a0)
bne.s +
neg.w x_vel(a0)
neg.w objoff_30(a0)
+
jsrto (ObjectMove).l, JmpTo26_ObjectMove
move.b status(a0),d0
move.b d0,d1
andi.b #p1_standing,d1
beq.s +
lea (MainCharacter).w,a1 ; a1=character
bsr.s loc_3BFB4
+
andi.b #p2_standing,d0
beq.s + ; rts
lea (Sidekick).w,a1 ; a1=character
bsr.s loc_3BFB4
+
rts
; ===========================================================================
loc_3BFB4:
clr.w inertia(a1)
clr.w x_vel(a1)
move.w x_pos(a0),x_pos(a1)
bclr #0,status(a1)
btst #0,status(a0)
bne.s +
bset #0,status(a1)
+
rts
; ===========================================================================
loc_3BFD8:
move.w objoff_30(a0),d0
add.w d0,x_vel(a0)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
move.w objoff_32(a0),d0
sub.w x_pos(a0),d0
btst #0,status(a0)
beq.s +
neg.w d0
+
tst.w d0
bpl.s loc_3C034
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s return_3C01E
move.b d0,d1
andi.b #p1_standing,d1
beq.s +
lea (MainCharacter).w,a1 ; a1=character
bsr.s loc_3BFB4
+
andi.b #p2_standing,d0
beq.s return_3C01E
lea (Sidekick).w,a1 ; a1=character
bsr.s loc_3BFB4
return_3C01E:
rts
; ===========================================================================
loc_3C020:
move.w x_vel(a0),x_vel(a1)
move.w #-$400,y_vel(a1)
bset #1,status(a1)
rts
; ===========================================================================
loc_3C034:
addq.b #2,routine_secondary(a0)
move.w objoff_32(a0),x_pos(a0)
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s loc_3C062
move.b d0,d1
andi.b #p1_standing,d1
beq.s loc_3C056
lea (MainCharacter).w,a1 ; a1=character
bsr.s loc_3C020
loc_3C056:
andi.b #p2_standing,d0
beq.s loc_3C062
lea (Sidekick).w,a1 ; a1=character
bsr.s loc_3C020
loc_3C062:
move.w x_pos(a0),d0
moveq #4,d1
tst.w objoff_30(a0) ; if objoff_30(a0) is positive,
spl d2 ; then set d2 to $FF, else set d2 to $00
bmi.s +
neg.w d1
+
add.w d1,d0
cmp.w objoff_34(a0),d0
bhs.s +
not.b d2
+
tst.b d2
bne.s +
clr.b routine_secondary(a0)
move.w objoff_34(a0),d0
+
move.w d0,x_pos(a0)
rts
; ===========================================================================
; off_3C08E:
ObjC0_SubObjData:
subObjData ObjC0_MapUnc_3C098,make_art_tile(ArtTile_ArtNem_WfzLaunchCatapult,1,0),4,4,$10,0
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjC0_MapUnc_3C098: BINCLUDE "mappings/sprite/objC0.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object C1 - Breakable plating from WFZ
; (and what sonic hangs onto on the back of Robotnic's getaway ship)
; ----------------------------------------------------------------------------
; Sprite_3C0AC:
ObjC1:
moveq #0,d0
move.b routine(a0),d0
move.w ObjC1_Index(pc,d0.w),d1
jmp ObjC1_Index(pc,d1.w)
; ===========================================================================
; off_3C0BA:
ObjC1_Index: offsetTable
offsetTableEntry.w ObjC1_Init ; 0
offsetTableEntry.w ObjC1_Main ; 2
offsetTableEntry.w ObjC1_Breakup ; 4
; ===========================================================================
; loc_3C0C0:
ObjC1_Init:
move.w #($44<<1),d0
bsr.w LoadSubObject_Part2
moveq #0,d0
move.b subtype(a0),d0
mulu.w #$3C,d0
move.w d0,objoff_30(a0)
ObjC1_Main:
tst.b objoff_32(a0)
beq.s loc_3C140
tst.w objoff_30(a0)
beq.s +
subq.w #1,objoff_30(a0)
beq.s loc_3C12E
+
lea (MainCharacter).w,a1 ; a1=character
move.w y_pos(a0),d0
subi.w #$18,d0
btst #button_up,(Ctrl_1_Held).w
beq.s +
subq.w #1,y_pos(a1)
cmp.w y_pos(a1),d0
blo.s +
move.w d0,y_pos(a1)
+
addi.w #$30,d0
btst #button_down,(Ctrl_1_Held).w
beq.s +
addq.w #1,y_pos(a1)
cmp.w y_pos(a1),d0
bhs.s +
move.w d0,y_pos(a1)
+
move.b (Ctrl_1_Press_Logical).w,d0
andi.w #button_B_mask|button_C_mask|button_A_mask,d0
beq.s BranchTo16_JmpTo39_MarkObjGone
loc_3C12E:
clr.b collision_flags(a0)
clr.b (MainCharacter+obj_control).w
clr.b (WindTunnel_holding_flag).w
clr.b objoff_32(a0)
bra.s loc_3C19A
; ===========================================================================
loc_3C140:
tst.b collision_property(a0)
beq.s BranchTo16_JmpTo39_MarkObjGone
lea (MainCharacter).w,a1 ; a1=character
move.w x_pos(a0),d0
subi.w #$14,d0
cmp.w x_pos(a1),d0
bhs.s BranchTo16_JmpTo39_MarkObjGone
clr.b collision_property(a0)
cmpi.b #4,routine(a1)
bhs.s BranchTo16_JmpTo39_MarkObjGone
clr.w x_vel(a1)
clr.w y_vel(a1)
move.w x_pos(a0),d0
subi.w #$14,d0
move.w d0,x_pos(a1)
bset #0,status(a1)
move.b #AniIDSonAni_Hang,anim(a1)
move.b #1,(MainCharacter+obj_control).w
move.b #1,(WindTunnel_holding_flag).w
move.b #1,objoff_32(a0)
BranchTo16_JmpTo39_MarkObjGone
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3C19A:
lea (byte_3C1E4).l,a4
lea (byte_3C1E0).l,a2
bsr.w loc_3C1F4
ObjC1_Breakup:
tst.b objoff_3F(a0)
beq.s +
subq.b #1,objoff_3F(a0)
bra.s ++
; ===========================================================================
+
jsrto (ObjectMove).l, JmpTo26_ObjectMove
addi_.w #8,y_vel(a0)
lea (Ani_objC1).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
+
tst.b render_flags(a0)
bpl.w JmpTo65_DeleteObject
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; animation script
; off_3C1D6:
Ani_objC1: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 3, 2, 3, 4, 5, 1,$FF
even
; unknown
byte_3C1E0:
dc.b 0
dc.b 4 ; 1
dc.b $18 ; 2
dc.b $20 ; 3
byte_3C1E4:
dc.w -$10
dc.w -$10 ; 2
dc.w -$10 ; 4
dc.w $10 ; 6
dc.w -$30 ; 8
dc.w -$10 ; 10
dc.w -$30 ; 12
dc.w $10 ; 14
; ===========================================================================
loc_3C1F4:
move.w x_pos(a0),d2
move.w y_pos(a0),d3
move.b priority(a0),d4
subq.b #1,d4
moveq #3,d1
movea.l a0,a1
bra.s loc_3C20E
; ===========================================================================
loc_3C208:
jsrto (SingleObjLoad2).l, JmpTo25_SingleObjLoad2
bne.s loc_3C26C
loc_3C20E:
move.b #4,routine(a1)
_move.b id(a0),id(a1) ; load obj
move.l mappings(a0),mappings(a1)
move.w art_tile(a0),art_tile(a1)
move.b #$84,render_flags(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w (a4)+,d0
add.w d2,d0
move.w d0,x_pos(a1)
move.w (a4)+,d0
add.w d3,d0
move.w d0,y_pos(a1)
move.b d4,priority(a1)
move.b #$10,width_pixels(a1)
move.b #1,mapping_frame(a1)
move.w #-$400,x_vel(a1)
move.w #0,y_vel(a1)
move.b (a2)+,objoff_3F(a1)
dbf d1,loc_3C208
loc_3C26C:
move.w #SndID_SlowSmash,d0
jmp (PlaySound).l
; ===========================================================================
; off_3C276:
ObjC1_SubObjData:
subObjData ObjC1_MapUnc_3C280,make_art_tile(ArtTile_ArtNem_BreakPanels,3,1),4,4,$40,$E1
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjC1_MapUnc_3C280: BINCLUDE "mappings/sprite/objC1.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object C2 - Rivet thing you bust to get into ship at the end of WFZ
; ----------------------------------------------------------------------------
; Sprite_3C328:
ObjC2:
moveq #0,d0
move.b routine(a0),d0
move.w ObjC2_Index(pc,d0.w),d1
jmp ObjC2_Index(pc,d1.w)
; ===========================================================================
; off_3C336:
ObjC2_Index: offsetTable
offsetTableEntry.w ObjC2_Init ; 0
offsetTableEntry.w ObjC2_Main ; 2
; ===========================================================================
; BranchTo10_LoadSubObject
ObjC2_Init:
bra.w LoadSubObject
; ===========================================================================
; loc_3C33E:
ObjC2_Main:
move.b (MainCharacter+anim).w,objoff_30(a0)
move.w x_pos(a0),-(sp)
move.w #$1B,d1
move.w #8,d2
move.w #9,d3
move.w (sp)+,d4
jsrto (SolidObject).l, JmpTo27_SolidObject
btst #p1_standing_bit,status(a0)
bne.s ObjC2_Bust
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; loc_3C366:
ObjC2_Bust:
cmpi.b #2,objoff_30(a0)
bne.s +
move.w #$2880,(Camera_Min_X_pos).w
bclr #p1_standing_bit,status(a0)
_move.b #ObjID_Explosion,id(a0) ; load 0bj27 (transform into explosion)
move.b #2,routine(a0)
bset #1,(MainCharacter+status).w
bclr #3,(MainCharacter+status).w
lea (Level_Layout+$850).w,a1 ; alter the level layout
move.l #$8A707172,(a1)+
move.w #$7374,(a1)+
lea (Level_Layout+$950).w,a1
move.l #$6E787978,(a1)+
move.w #$787A,(a1)+
move.b #1,(Screen_redraw_flag).w
+
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; off_3C3B8:
ObjC2_SubObjData:
subObjData ObjC2_MapUnc_3C3C2,make_art_tile(ArtTile_ArtNem_WfzSwitch,1,1),4,4,$10,0
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjC2_MapUnc_3C3C2: BINCLUDE "mappings/sprite/objC2.bin"
Invalid_SubObjData2:
; ===========================================================================
; ----------------------------------------------------------------------------
; Object C3,C4 - Plane's smoke from WFZ
; ----------------------------------------------------------------------------
; Sprite_3C3D6:
ObjC3:
moveq #0,d0
move.b routine(a0),d0
move.w ObjC3_Index(pc,d0.w),d1
jmp ObjC3_Index(pc,d1.w)
; ===========================================================================
; off_3C3E4:
ObjC3_Index: offsetTable
offsetTableEntry.w ObjC3_Init
offsetTableEntry.w ObjC3_Main
; ===========================================================================
; loc_3C3E8:
ObjC3_Init:
bsr.w LoadSubObject
move.b #7,anim_frame_duration(a0)
jsrto (RandomNumber).l, JmpTo6_RandomNumber
move.w (RNG_seed).w,d0
andi.w #$1C,d0
sub.w d0,x_pos(a0)
addi.w #$10,y_pos(a0)
move.w #-$100,y_vel(a0)
move.w #-$100,x_vel(a0)
rts
; ===========================================================================
; loc_3C416:
ObjC3_Main:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
subq.b #1,anim_frame_duration(a0)
bpl.s +
move.b #7,anim_frame_duration(a0)
addq.b #1,mapping_frame(a0)
cmpi.b #5,mapping_frame(a0)
beq.w JmpTo65_DeleteObject
+
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; off_3C438:
ObjC3_SubObjData:
subObjData Obj27_MapUnc_21120,make_art_tile(ArtTile_ArtNem_Explosion,0,0),4,5,$C,0
; ===========================================================================
; ----------------------------------------------------------------------------
; Object C5 - WFZ boss
; ----------------------------------------------------------------------------
; Sprite_3C442:
ObjC5:
moveq #0,d0
move.b routine(a0),d0
move.w ObjC5_Index(pc,d0.w),d1
jmp ObjC5_Index(pc,d1.w)
; ===========================================================================
ObjC5_Index: offsetTable
offsetTableEntry.w ObjC5_Init ; 0 - Main loading sequence
offsetTableEntry.w ObjC5_LaserCase ; 2 - Laser case (inside is laser)
offsetTableEntry.w ObjC5_LaserWall ; 4 - Laser wall
offsetTableEntry.w ObjC5_PlatformReleaser ; 6 - Platform releaser
offsetTableEntry.w ObjC5_Platform ; 8 - Platform
offsetTableEntry.w ObjC5_PlatformHurt ; $A - Invisible object that gets the platform's spikes to hurt sonic
offsetTableEntry.w ObjC5_LaserShooter ; $C - Laser shooter
offsetTableEntry.w ObjC5_Laser ; $E - Laser
offsetTableEntry.w ObjC5_Robotnik ; $10 - Robotnik
offsetTableEntry.w ObjC5_RobotnikPlatform ; $12 - Platform Robotnik's on
; ===========================================================================
ObjC5_Init:
bsr.w LoadSubObject
move.b subtype(a0),d0
subi.b #$90,d0
move.b d0,routine(a0)
rts
; ===========================================================================
ObjC5_LaserCase: ; also the "mother" object
moveq #0,d0
move.b routine_secondary(a0),d0
move.w ObjC5_CaseIndex(pc,d0.w),d1
jsr ObjC5_CaseIndex(pc,d1.w)
bra.w ObjC5_HandleHits
; ===========================================================================
ObjC5_CaseIndex:offsetTable
offsetTableEntry.w ObjC5_CaseBoundary ; 0 - Sets up boundaries for movement and basic things
offsetTableEntry.w ObjC5_CaseWaitStart ; 2 - Waits for sonic to start
offsetTableEntry.w ObjC5_CaseWaitDown ; 4 - Waits to make the laser go down
offsetTableEntry.w ObjC5_CaseDown ; 6 - Moves the case down
offsetTableEntry.w ObjC5_CaseXSpeed ; 8 - Sets an X speed for the case
offsetTableEntry.w ObjC5_CaseBoundaryChk ; $A - Checks to make sure the case doesn't go through the boundaries
offsetTableEntry.w ObjC5_CaseAnimate ; $C - Animates the case (opening and closing)
offsetTableEntry.w ObjC5_CaseLSLoad ; $E - Laser shooter loading
offsetTableEntry.w ObjC5_CaseLSDown ; $10 - Moves the laser shooter down
offsetTableEntry.w ObjC5_CaseWaitLoadLaser ; $12 - Waits to load the laser
offsetTableEntry.w ObjC5_CaseWaitMove ; $14 - Waits to move (checks if laser is completely loaded (as big as it gets))
offsetTableEntry.w ObjC5_CaseBoundaryLaserChk ; $16 - Checks boundaries when moving with the laser
offsetTableEntry.w ObjC5_CaseLSUp ; $18 - wait for laser shooter to go back up
offsetTableEntry.w ObjC5_CaseAnimate ; $1A - Animates the case (opening and closing)
offsetTableEntry.w ObjC5_CaseStartOver ; $1C - Sets secondary routine to 8
offsetTableEntry.w ObjC5_CaseDefeated ; $1E - When defeated goes here (explosions and stuff)
; ===========================================================================
ObjC5_CaseBoundary:
addq.b #2,routine_secondary(a0)
move.b #0,collision_flags(a0)
move.b #8,collision_property(a0) ; Hit points
move.w #$442,d0
move.w d0,(Camera_Max_Y_pos_now).w
move.w d0,(Camera_Max_Y_pos).w
move.w x_pos(a0),d0
subi.w #$60,d0 ; Max Left position
move.w d0,objoff_34(a0)
addi.w #$C0,d0 ; Max Right Position
move.w d0,objoff_36(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseWaitStart:
bsr.w Obj_GetOrientationToPlayer
addi.w #$20,d2
cmpi.w #$40,d2 ; How far away sonic is to start the boss
blo.s ObjC5_CaseStart
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseStart:
addq.b #2,routine_secondary(a0)
move.w #$40,y_vel(a0) ; Speed at which the laser carrier goes down
lea (ObjC5_LaserWallData).l,a2
bsr.w LoadChildObject
subi.w #$88,x_pos(a1) ; where to load the left laser wall (x)
addi.w #$60,y_pos(a1) ; left laser wall (y)
lea (ObjC5_LaserWallData).l,a2
bsr.w LoadChildObject
addi.w #$88,x_pos(a1) ; right laser wall (x)
addi.w #$60,y_pos(a1) ; right laser wall (y)
lea (ObjC5_LaserShooterData).l,a2
bsr.w LoadChildObject
lea (ObjC5_PlatformReleaserData).l,a2
bsr.w LoadChildObject
lea (ObjC5_RobotnikData).l,a2
bsr.w LoadChildObject
move.w #$5A,objoff_2A(a0) ; How long for the boss music to start playing and the boss to start
moveq #MusID_FadeOut,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseWaitDown:
subq.w #1,objoff_2A(a0)
bmi.s ObjC5_CaseSpeedDown
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseSpeedDown:
addq.b #2,routine_secondary(a0)
move.w #$60,objoff_2A(a0) ; How long the laser carrier goes down
moveq #MusID_Boss,d0
jsrto (PlayMusic).l, JmpTo5_PlayMusic
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseDown:
subq.w #1,objoff_2A(a0)
beq.s ObjC5_CaseStopDown
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseStopDown:
addq.b #2,routine_secondary(a0)
clr.w y_vel(a0) ; stop the laser carrier from going down
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseXSpeed:
addq.b #2,routine_secondary(a0)
bsr.w Obj_GetOrientationToPlayer
move.w #$100,d1 ; Speed of carrier (when going back and forth before sending out laser)
tst.w d0
bne.s ObjC5_CasePMLoader
neg.w d1
ObjC5_CasePMLoader:
move.w d1,x_vel(a0)
bset #2,status(a0) ; makes the platform maker load
move.w #$70,objoff_2A(a0) ; how long to go back and forth before letting out laser
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseBoundaryChk: ; waits and makes sure the carrier does not go beyond the limit
subq.w #1,objoff_2A(a0)
bmi.s ObjC5_CaseOpeningAnim
move.w x_pos(a0),d0
tst.w x_vel(a0)
bmi.s ObjC5_CaseBoundaryChk2
cmp.w objoff_36(a0),d0
bhs.s ObjC5_CaseNegSpeed
bra.w ObjC5_CaseMoveDisplay
; ===========================================================================
ObjC5_CaseBoundaryChk2:
cmp.w objoff_34(a0),d0
bhs.s ObjC5_CaseMoveDisplay
ObjC5_CaseNegSpeed:
neg.w x_vel(a0)
ObjC5_CaseMoveDisplay:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseOpeningAnim:
addq.b #2,routine_secondary(a0)
clr.b anim(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseAnimate:
lea (Ani_objC5).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseLSLoad: ; loads up the laser shooter (LS)
addq.b #2,routine_secondary(a0)
move.w #$E,objoff_2A(a0) ; Time the laser shooter moves down
movea.w objoff_3C(a0),a1 ; a1=object (laser shooter)
move.b #4,routine_secondary(a1)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseLSDown:
subq.w #1,objoff_2A(a0)
beq.s ObjC5_CaseAddCollision
movea.w objoff_3C(a0),a1 ; a1=object (laser shooter)
addq.w #1,y_pos(a1) ; laser shooter down speed
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseAddCollision:
addq.b #2,routine_secondary(a0)
move.w #$40,objoff_2A(a0) ; Length before shooting laser
bset #4,status(a0) ; makes the hit sound and flashes happen only once when you hit it
bset #6,status(a0) ; makes sure collision gets restored
move.b #6,collision_flags(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseWaitLoadLaser:
subq.w #1,objoff_2A(a0)
bmi.s ObjC5_CaseLoadLaser
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseLoadLaser:
addq.b #2,routine_secondary(a0)
lea (ObjC5_LaserData).l,a2
bsr.w LoadChildObject ; loads laser
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseWaitMove:
movea.w parent(a0),a1 ; a1=object
btst #2,status(a1) ; waits to check if laser fired
bne.s ObjC5_CaseLaserSpeed
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseLaserSpeed:
addq.b #2,routine_secondary(a0)
move.w #$80,objoff_2A(a0) ; how long to move the laser
bsr.w Obj_GetOrientationToPlayer ; tests if sonic is to the right or left
move.w #$80,d1 ; Speed when moving with laser
tst.w d0
bne.s ObjC5_CaseLaserSpeedSet
neg.w d1
ObjC5_CaseLaserSpeedSet:
move.w d1,x_vel(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseBoundaryLaserChk: ; make sure you stay in range when firing laser
subq.w #1,objoff_2A(a0)
bmi.s ObjC5_CaseStopLaserDelete
move.w x_pos(a0),d0
tst.w x_vel(a0)
bmi.s ObjC5_CaseBoundaryLaserChk2
cmp.w objoff_36(a0),d0
bhs.s ObjC5_CaseLaserStopMove
bra.w ObjC5_CaseLaserMoveDisplay
; ===========================================================================
ObjC5_CaseBoundaryLaserChk2:
cmp.w objoff_34(a0),d0
bhs.s ObjC5_CaseLaserMoveDisplay
ObjC5_CaseLaserStopMove:
clr.w x_vel(a0) ; stop moving
ObjC5_CaseLaserMoveDisplay:
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseStopLaserDelete: ; stops collision and deletes laser
addq.b #2,routine_secondary(a0)
move.w #$E,objoff_2A(a0) ; time for laser shooter to move back up
bclr #3,status(a0)
bclr #4,status(a0)
bclr #6,status(a0)
clr.b collision_flags(a0) ; no more collision
movea.w parent(a0),a1 ; a1=object (laser)
jsrto (DeleteObject2).l, JmpTo6_DeleteObject2 ; delete the laser
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseLSUp:
subq.w #1,objoff_2A(a0)
beq.s ObjC5_CaseClosingAnim
movea.w objoff_3C(a0),a1 ; a1=object (laser shooter)
subq.w #1,y_pos(a1)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseClosingAnim: ;sets which animation to do
addq.b #2,routine_secondary(a0)
move.b #1,anim(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseStartOver:
move.b #8,routine_secondary(a0)
bsr.w ObjC5_CaseXSpeed
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_CaseDefeated:
clr.b collision_flags(a0)
st collision_property(a0)
bclr #6,status(a0)
subq.w #1,objoff_30(a0) ; timer
bmi.s ObjC5_End
jsrto (Boss_LoadExplosion).l, JmpTo_Boss_LoadExplosion
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_End: ; play music and change camera speed
moveq #MusID_WFZ,d0
jsrto (PlayMusic).l, JmpTo5_PlayMusic
move.w #$720,d0
move.w d0,(Camera_Max_Y_pos_now).w
move.w d0,(Camera_Max_Y_pos).w
bsr.w JmpTo65_DeleteObject
addq.w #4,sp
rts
; ===========================================================================
ObjC5_LaserWall:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w ObjC5_LaserWallIndex(pc,d0.w),d1
jsr ObjC5_LaserWallIndex(pc,d1.w)
tst.b (a0)
beq.w return_37A48
move.w x_pos(a0),-(sp)
move.w #$13,d1
move.w #$40,d2
move.w #$80,d3
move.w (sp)+,d4
jmpto (SolidObject).l, JmpTo27_SolidObject
; ===========================================================================
ObjC5_LaserWallIndex: offsetTable
offsetTableEntry.w ObjC5_LaserWallMappings ; 0 - selects the mappings
offsetTableEntry.w ObjC5_LaserWallWaitDelete ; 2 - Waits till set to delete (when the boss is defeated)
offsetTableEntry.w ObjC5_LaserWallDelete ; 4 - After a little time it deletes
; ===========================================================================
ObjC5_LaserWallMappings:
addq.b #2,routine_secondary(a0)
move.b #$C,mapping_frame(a0) ; loads the laser wall from the WFZ boss art
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_LaserWallWaitDelete:
movea.w objoff_2C(a0),a1 ; a1=object
btst #5,status(a1)
bne.s ObjC5_LaserWallTimerSet
bchg #0,objoff_2F(a0) ; makes it "flash" if set it won't flash
bne.w return_37A48
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_LaserWallTimerSet: ; sets a small timer
addq.b #2,routine_secondary(a0)
move.b #4,objoff_30(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_LaserWallDelete:
subq.b #1,anim_frame_duration(a0)
bpl.w return_37A48
move.b anim_frame_duration(a0),d0
move.b anim_frame(a0),d1
addq.b #2,d0
bpl.s ObjC5_LaserWallDisplay
move.b d1,anim_frame_duration(a0)
subq.b #1,objoff_30(a0)
bpl.s ObjC5_LaserWallDisplay
move.b #$10,objoff_30(a0)
addq.b #1,d1
cmpi.b #5,d1
bhs.w JmpTo65_DeleteObject
move.b d1,anim_frame(a0)
move.b d1,anim_frame_duration(a0)
ObjC5_LaserWallDisplay:
bclr #0,objoff_2F(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_PlatformReleaser:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w ObjC5_PlatformReleaserIndex(pc,d0.w),d1
jmp ObjC5_PlatformReleaserIndex(pc,d1.w)
; ===========================================================================
ObjC5_PlatformReleaserIndex: offsetTable
offsetTableEntry.w ObjC5_PlatformReleaserInit ; 0 - Load mappings and position
offsetTableEntry.w ObjC5_PlatformReleaserWaitDown ; 2 - Waits for laser case to move down
offsetTableEntry.w ObjC5_PlatformReleaserDown ; 4 - Goes down until time limit is up
offsetTableEntry.w ObjC5_PlatformReleaserLoadWait ; 6 - Waits to load the platforms (the interval of time between each is from this) and makes sure only 3 are loaded
offsetTableEntry.w ObjC5_PlatformReleaserDelete ; 8 - Explodes then deletes
; ===========================================================================
ObjC5_PlatformReleaserInit:
addq.b #2,routine_secondary(a0)
move.b #5,mapping_frame(a0)
addq.w #8,y_pos(a0) ; Move down a little
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_PlatformReleaserWaitDown:
movea.w objoff_2C(a0),a1 ; a1=object laser case
btst #2,status(a1) ; checks if laser case is done moving down (so it starts loading the platforms)
bne.s ObjC5_PlatformReleaserSetDown
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_PlatformReleaserSetDown:
addq.b #2,routine_secondary(a0)
move.w #$40,objoff_2A(a0) ; time to go down
move.w #$40,y_vel(a0) ; speed to go down
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_PlatformReleaserDown:
subq.w #1,objoff_2A(a0)
beq.s ObjC5_PlatformReleaserStop
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_PlatformReleaserStop:
addq.b #2,routine_secondary(a0)
clr.w y_vel(a0)
move.w #$10,objoff_2A(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_PlatformReleaserLoadWait:
movea.w objoff_2C(a0),a1 ; a1=object
btst #5,status(a1)
bne.s ObjC5_PlatformReleaserDestroyP
subq.w #1,objoff_2A(a0)
bne.s BranchTo8_JmpTo45_DisplaySprite
move.w #$80,objoff_2A(a0) ; Time between loading platforms
moveq #0,d0
move.b objoff_2E(a0),d0
addq.b #1,d0
cmpi.b #3,d0 ; How many platforms to load
blo.s ObjC5_PlatformReleaserLoadP
moveq #0,d0
ObjC5_PlatformReleaserLoadP: ; P=Platforms
move.b d0,objoff_2E(a0)
tst.b objoff_30(a0,d0.w)
bne.s BranchTo8_JmpTo45_DisplaySprite
st objoff_30(a0,d0.w)
lea (ObjC5_PlatformData).l,a2
bsr.w LoadChildObject
move.b objoff_2E(a0),objoff_2E(a1)
BranchTo8_JmpTo45_DisplaySprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_PlatformReleaserDestroyP: ; P=Platforms
addq.b #2,routine_secondary(a0)
bset #5,status(a0) ; destroy platforms
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_PlatformReleaserDelete:
movea.w objoff_2C(a0),a1 ; a1=object
cmpi.b #ObjID_WFZBoss,id(a1)
bne.w JmpTo65_DeleteObject
jsrto (Boss_LoadExplosion).l, JmpTo_Boss_LoadExplosion
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_Platform:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w ObjC5_PlatformIndex(pc,d0.w),d1
jsr ObjC5_PlatformIndex(pc,d1.w)
lea (Ani_objC5).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
tst.b (a0)
beq.w return_37A48
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_PlatformIndex: offsetTable
offsetTableEntry.w ObjC5_PlatformInit ; 0 - Selects mappings, anim ation, y speed and loads the object that hurts sonic (by spiky area)
offsetTableEntry.w ObjC5_PlatformDownWait ; 2 - Wait till the platform goes down some
offsetTableEntry.w ObjC5_PlatformTestChangeDirection ; 4 - checks if time limit is over and if so to change direction
; ===========================================================================
ObjC5_PlatformInit:
addq.b #2,routine_secondary(a0)
move.b #3,anim(a0)
move.b #7,mapping_frame(a0)
move.w #$100,y_vel(a0) ; Y speed
move.w #$60,objoff_2A(a0)
lea (ObjC5_PlatformHurtData).l,a2 ; loads the invisible object that hurts sonic
bra.w LoadChildObject
; ===========================================================================
ObjC5_PlatformDownWait: ; waits for it to go down some
bsr.w ObjC5_PlatformCheckExplode
subq.w #1,objoff_2A(a0)
beq.s ObjC5_PlatformLeft
bra.w ObjC5_PlatformMakeSolid
; ===========================================================================
ObjC5_PlatformLeft: ; goes left and makes a time limit (for going left)
addq.b #2,routine_secondary(a0)
move.w #$60,objoff_2A(a0)
move.w #-$100,x_vel(a0) ; X speed
move.w y_pos(a0),objoff_34(a0)
bra.w ObjC5_PlatformMakeSolid
; ===========================================================================
ObjC5_PlatformTestChangeDirection:
bsr.w ObjC5_PlatformCheckExplode
subq.w #1,objoff_2A(a0)
bne.s ObjC5_PlatformTestLeftRight
move.w #$C0,objoff_2A(a0)
neg.w x_vel(a0)
ObjC5_PlatformTestLeftRight: ; tests to see if a value should be added to go left or right
moveq #4,d0
move.w y_pos(a0),d1
cmp.w objoff_34(a0),d1
blo.s ObjC5_PlatformChangeY
neg.w d0
ObjC5_PlatformChangeY: ; give it that curving feel
add.w d0,y_vel(a0)
bra.w ObjC5_PlatformMakeSolid
ObjC5_PlatformMakeSolid: ; makes into a platform and moves
move.w x_pos(a0),-(sp)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
move.w #$10,d1
move.w #8,d2
move.w #8,d3
move.w (sp)+,d4
jmpto (PlatformObject).l, JmpTo9_PlatformObject
; ===========================================================================
ObjC5_PlatformCheckExplode: ; checks to see if platforms should explode
movea.w objoff_2C(a0),a1 ; a1=object
btst #5,status(a1)
bne.w ObjC5_PlatformExplode
rts
; ===========================================================================
ObjC5_PlatformExplode:
bsr.w loc_3B7BC
move.b #ObjID_BossExplosion,id(a0) ; load 0bj58 (explosion)
clr.b routine(a0)
movea.w objoff_3C(a0),a1 ; a1=object (invisible hurting thing)
jsrto (DeleteObject2).l, JmpTo6_DeleteObject2
addq.w #4,sp
rts
; ===========================================================================
ObjC5_PlatformHurt:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w ObjC5_PlatformHurtIndex(pc,d0.w),d1
jmp ObjC5_PlatformHurtIndex(pc,d1.w)
; ===========================================================================
ObjC5_PlatformHurtIndex: offsetTable
offsetTableEntry.w ObjC5_PlatformHurtCollision ; 0 - Gives collision that hurts sonic
offsetTableEntry.w ObjC5_PlatformHurtFollowPlatform ; 2 - Follows around the platform and waits to be deleted
; ===========================================================================
ObjC5_PlatformHurtCollision:
addq.b #2,routine_secondary(a0)
move.b #$98,collision_flags(a0)
rts
; ===========================================================================
ObjC5_PlatformHurtFollowPlatform:
movea.w objoff_2C(a0),a1 ; a1=object (platform)
btst #5,status(a1)
bne.w JmpTo65_DeleteObject
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),d0
addi.w #$C,d0
move.w d0,y_pos(a0)
rts
; ===========================================================================
ObjC5_LaserShooter:
movea.w objoff_2C(a0),a1 ; a1=object (laser case)
btst #5,status(a1)
bne.w JmpTo65_DeleteObject
moveq #0,d0
move.b routine_secondary(a0),d0
move.w ObjC5_LaserShooterIndex(pc,d0.w),d1
jmp ObjC5_LaserShooterIndex(pc,d1.w)
; ===========================================================================
ObjC5_LaserShooterIndex: offsetTable
offsetTableEntry.w ObjC5_LaserShooterInit ; 0 - Loads up mappings
offsetTableEntry.w ObjC5_LaserShooterFollow ; 2 - Goes back and forth with the laser case
offsetTableEntry.w ObjC5_LaserShooterDown ; 4 - Laser case sets it to this routine which then makes it go down
; ===========================================================================
ObjC5_LaserShooterInit:
addq.b #2,routine_secondary(a0)
move.b #4,mapping_frame(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_LaserShooterFollow:
movea.w objoff_2C(a0),a1 ; a1=object (laser case)
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_LaserShooterDown:
movea.w objoff_2C(a0),a1 ; a1=object (laser case)
move.w x_pos(a1),x_pos(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_Laser:
movea.w objoff_2C(a0),a1 ; a1=object
btst #5,status(a1)
bne.w JmpTo65_DeleteObject
moveq #0,d0
move.b routine_secondary(a0),d0
move.w ObjC5_LaserIndex(pc,d0.w),d1
jsr ObjC5_LaserIndex(pc,d1.w)
bchg #0,objoff_2F(a0)
bne.w return_37A48
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_LaserIndex: offsetTable
offsetTableEntry.w ObjC5_LaserInit ; 0 - Loads mappings and collision and such
offsetTableEntry.w ObjC5_LaserFlash ; 2 - Makes the laser flash (gives the charging up effect)
offsetTableEntry.w ObjC5_LaseWaitShoot ; 4 - Waits a little to launch the laser when it's done flickering (charging)
offsetTableEntry.w ObjC5_LaserShoot ; 6 - Shoots down the laser untill it's fully shot out
offsetTableEntry.w ObjC5_LaserMove ; 8 - Moves with laser case and shooter
; ===========================================================================
ObjC5_LaserInit:
addq.b #2,routine_secondary(a0)
move.b #$D,mapping_frame(a0)
move.b #4,priority(a0)
move.b #0,collision_flags(a0)
addi.w #$10,y_pos(a0)
move.b #$C,anim_frame(a0)
subq.w #3,y_pos(a0)
rts
; ===========================================================================
ObjC5_LaserFlash:
bset #0,objoff_2F(a0)
subq.b #1,anim_frame_duration(a0)
bpl.s ObjC5_LaserNoLaser
move.b anim_frame_duration(a0),d0
addq.b #2,d0
bpl.s ObjC5_LaserFlicker
move.b anim_frame(a0),d0
subq.b #1,d0
beq.s ObjC5_LaseNext
move.b d0,anim_frame(a0)
move.b d0,anim_frame_duration(a0)
ObjC5_LaserFlicker: ; this is what makes the laser flicker before being fully loaded (covering laser shooter)
bclr #0,objoff_2F(a0)
ObjC5_LaserNoLaser: ; without this the laser would just stay on the shooter not going down
rts
; ===========================================================================
ObjC5_LaseNext: ; just sets up a time to wait for the laser to shoot when it's loaded and done flickering
addq.b #2,routine_secondary(a0)
move.w #$40,objoff_2A(a0)
rts
; ===========================================================================
ObjC5_LaseWaitShoot:
subq.w #1,objoff_2A(a0)
bmi.s ObjC5_LaseStartShooting
rts
; ===========================================================================
ObjC5_LaseStartShooting:
addq.b #2,routine_secondary(a0)
addi.w #$10,y_pos(a0)
rts
; ===========================================================================
ObjC5_LaserShoot:
moveq #0,d0
move.b objoff_2E(a0),d0
addq.b #1,d0
cmpi.b #5,d0
bhs.s ObjC5_LaseShotOut
addi.w #$10,y_pos(a0)
move.b d0,objoff_2E(a0)
move.b ObjC5_LaserMappingsData(pc,d0.w),mapping_frame(a0)
move.b ObjC5_LaserCollisionData(pc,d0.w),collision_flags(a0)
rts
; ===========================================================================
ObjC5_LaseShotOut: ; laser is fully shot out and lets the laser case know so it moves
addq.b #2,routine_secondary(a0)
move.w #$80,objoff_2A(a0)
bset #2,status(a0)
movea.w objoff_2C(a0),a1 ; a1=object (laser case)
bset #3,status(a1)
rts
; ===========================================================================
ObjC5_LaserMappingsData:
dc.b $E
dc.b $F ; 1
dc.b $10 ; 2
dc.b $11 ; 3
dc.b $12 ; 4
dc.b 0 ; 5
ObjC5_LaserCollisionData:
dc.b $86
dc.b $AB ; 1
dc.b $AC ; 2
dc.b $AD ; 3
dc.b $AE ; 4
dc.b 0 ; 5
; ===========================================================================
ObjC5_LaserMove:
movea.w objoff_2C(a0),a1 ; a1=object
move.w x_pos(a1),x_pos(a0)
rts
; ===========================================================================
ObjC5_Robotnik:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w ObjC5_RobotnikIndex(pc,d0.w),d1
jmp ObjC5_RobotnikIndex(pc,d1.w)
; ===========================================================================
ObjC5_RobotnikIndex: offsetTable
offsetTableEntry.w ObjC5_RobotnikInit ; 0 - Loads art, animation and position
offsetTableEntry.w ObjC5_RobotnikAnimate ; 2 - Animates Robotnik and waits till the case is defeated
offsetTableEntry.w ObjC5_RobotnikDown ; 4 - Goes down until timer is up
; ===========================================================================
ObjC5_RobotnikInit:
addq.b #2,routine_secondary(a0)
move.b #0,mapping_frame(a0)
move.b #1,anim(a0)
move.w #$2C60,x_pos(a0)
move.w #$4E6,y_pos(a0)
lea (ObjC5_RobotnikPlatformData).l,a2
bsr.w LoadChildObject
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_RobotnikAnimate:
movea.w objoff_2C(a0),a1 ; a1=object (laser case)
btst #5,status(a1)
bne.s ObjC5_RobotnikTimer
lea (Ani_objC5_objC6).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_RobotnikTimer: ; Increase routine and set timer
addq.b #2,routine_secondary(a0)
move.w #$C0,objoff_2A(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_RobotnikDown:
subq.w #1,objoff_2A(a0)
bmi.s ObjC5_RobotnikDelete
addq.w #1,y_pos(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
ObjC5_RobotnikDelete: ; Deletes robotnik and the platform he's on
movea.w parent(a0),a1 ; a1=object (Robotnik Platform)
jsrto (DeleteObject2).l, JmpTo6_DeleteObject2
bra.w JmpTo65_DeleteObject
; ===========================================================================
ObjC5_RobotnikPlatform: ; Just displays the platform and move accordingly to the robotnik object
movea.w objoff_2C(a0),a1 ; a1=object (robotnik)
move.w y_pos(a1),d0
addi.w #$26,d0
move.w d0,y_pos(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; some unused/dead code, At one point it appears a section of the platform was solid
move.w x_pos(a0),-(sp)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
move.w #$F,d1
move.w #8,d2
move.w #8,d3
move.w (sp)+,d4
jmpto (PlatformObject).l, JmpTo9_PlatformObject
; ===========================================================================
ObjC5_HandleHits:
tst.b collision_property(a0)
beq.s ObjC5_NoHitPointsLeft
tst.b collision_flags(a0)
bne.s return_3CC3A
tst.b objoff_30(a0)
bne.s ObjC5_FlashSetUp
btst #6,status(a0)
beq.s return_3CC3A
move.b #$20,objoff_30(a0)
move.w #SndID_BossHit,d0
jsr (PlaySound).l
ObjC5_FlashSetUp:
lea (Normal_palette_line2+2).w,a1
moveq #0,d0
tst.w (a1)
bne.s ObjC5_FlashCollisionRestore
move.w #$EEE,d0
ObjC5_FlashCollisionRestore:
move.w d0,(a1)
subq.b #1,objoff_30(a0)
bne.s return_3CC3A
btst #4,status(a0) ; makes sure the boss doesn't need collision
beq.s return_3CC3A
move.b #6,collision_flags(a0) ; restore collision
return_3CC3A:
rts
; ===========================================================================
ObjC5_NoHitPointsLeft: ; when the boss is defeated this tells it what to do
moveq #100,d0
bsr.w AddPoints
clr.b collision_flags(a0)
move.w #$EF,objoff_30(a0)
move.b #$1E,routine_secondary(a0)
bset #5,status(a0)
bclr #6,status(a0)
rts
; ===========================================================================
ObjC5_LaserWallData:
dc.w objoff_2A
dc.b ObjID_WFZBoss
dc.b $94
ObjC5_PlatformData:
dc.w objoff_3E
dc.b ObjID_WFZBoss
dc.b $98
ObjC5_PlatformHurtData:
dc.w objoff_3C
dc.b ObjID_WFZBoss
dc.b $9A
ObjC5_LaserShooterData:
dc.w objoff_3C
dc.b ObjID_WFZBoss
dc.b $9C
ObjC5_PlatformReleaserData:
dc.w objoff_3A
dc.b ObjID_WFZBoss
dc.b $96
ObjC5_LaserData:
dc.w objoff_3E
dc.b ObjID_WFZBoss
dc.b $9E
ObjC5_RobotnikData:
dc.w objoff_38
dc.b ObjID_WFZBoss
dc.b $A0
ObjC5_RobotnikPlatformData:
dc.w objoff_3E
dc.b ObjID_WFZBoss
dc.b $A2
; off_3CC80:
ObjC5_SubObjData: ; Laser Case
subObjData ObjC5_MapUnc_3CCD8,make_art_tile(ArtTile_ArtNem_WFZBoss,0,0),4,4,$20,0
; off_3CC8A:
ObjC5_SubObjData2: ; Laser Walls
subObjData ObjC5_MapUnc_3CCD8,make_art_tile(ArtTile_ArtNem_WFZBoss,0,0),4,1,8,0
; off_3CC94:
ObjC5_SubObjData3: ; Platforms, platform releaser, laser and laser shooter
subObjData ObjC5_MapUnc_3CCD8,make_art_tile(ArtTile_ArtNem_WFZBoss,0,0),4,5,$10,0
; off_3CC9E:
ObjC6_SubObjData2: ; Robotnik
subObjData ObjC6_MapUnc_3D0EE,make_art_tile(ArtTile_ArtKos_LevelArt,0,0),4,5,$20,0
; off_3CCA8:
ObjC5_SubObjData4: ; Robotnik platform
subObjData ObjC5_MapUnc_3CEBC,make_art_tile(ArtTile_ArtNem_WfzFloatingPlatform,1,1),4,5,$20,0
; animation script
; off_3CCB2:
Ani_objC5: offsetTable
offsetTableEntry.w byte_3CCBA ; 0
offsetTableEntry.w byte_3CCC4 ; 1
offsetTableEntry.w byte_3CCCC ; 2
offsetTableEntry.w byte_3CCD0 ; 3
byte_3CCBA: dc.b 5, 0, 1, 2, 3, 3, 3, 3,$FA, 0
byte_3CCC4: dc.b 3, 3, 2, 1, 0, 0,$FA, 0
byte_3CCCC: dc.b 3, 5, 6,$FF
byte_3CCD0: dc.b 3, 7, 8, 9, $A, $B,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjC5_MapUnc_3CCD8: BINCLUDE "mappings/sprite/objC5_a.bin"
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjC5_MapUnc_3CEBC: BINCLUDE "mappings/sprite/objC5_b.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object C6 - Eggman
; ----------------------------------------------------------------------------
; Sprite_3CED0:
ObjC6:
moveq #0,d0
move.b routine(a0),d0
move.w ObjC6_Index(pc,d0.w),d1
jmp ObjC6_Index(pc,d1.w)
; ===========================================================================
; off_3CEDE: ObjC6_States:
ObjC6_Index: offsetTable
offsetTableEntry.w ObjC6_Init ; 0
offsetTableEntry.w ObjC6_State2 ; 2
offsetTableEntry.w ObjC6_State3 ; 4
offsetTableEntry.w ObjC6_State4 ; 6
; ===========================================================================
; loc_3CEE6:
ObjC6_Init:
bsr.w LoadSubObject
move.b subtype(a0),d0
subi.b #$A4,d0
move.b d0,routine(a0) ; => ObjC6_State2, ObjC6_State3, or ObjC6_State4 ??
rts
; ===========================================================================
; loc_3CEF8:
ObjC6_State2:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w ObjC6_State2_States(pc,d0.w),d1
jmp ObjC6_State2_States(pc,d1.w)
; ===========================================================================
; off_3CF06:
ObjC6_State2_States: offsetTable
offsetTableEntry.w ObjC6_State2_State1 ; 0
offsetTableEntry.w ObjC6_State2_State2 ; 2
offsetTableEntry.w ObjC6_State2_State3 ; 4
offsetTableEntry.w ObjC6_State2_State4 ; 6
offsetTableEntry.w ObjC6_State2_State5 ; 8
; ===========================================================================
; loc_3CF10:
ObjC6_State2_State1: ; a1=object (set in loc_3D94C)
addq.b #2,routine_secondary(a0) ; => ObjC6_State2_State2
lea (word_3D0D0).l,a2
bsr.w LoadChildObject
move.w #$3F8,x_pos(a1)
move.w #$160,y_pos(a1)
move.w a0,(DEZ_Eggman).w
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; loc_3CF32:
ObjC6_State2_State2:
bsr.w Obj_GetOrientationToPlayer
addi.w #$5C,d2
cmpi.w #$B8,d2
blo.s loc_3CF44
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ---------------------------------------------------------------------------
loc_3CF44:
addq.b #2,routine_secondary(a0) ; => ObjC6_State2_State3
move.w #$18,objoff_2A(a0)
move.b #1,mapping_frame(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; loc_3CF58:
ObjC6_State2_State3:
subq.w #1,objoff_2A(a0)
bmi.s loc_3CF62
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ---------------------------------------------------------------------------
loc_3CF62:
addq.b #2,routine_secondary(a0) ; => ObjC6_State2_State4
bset #2,status(a0)
move.w #$200,x_vel(a0)
move.w #$10,objoff_2A(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; loc_3CF7C:
ObjC6_State2_State4:
cmpi.w #$810,x_pos(a0)
bhs.s loc_3CFC0
bsr.w Obj_GetOrientationToPlayer
addi.w #$50,d2
cmpi.w #$A0,d2
bhs.s +
move.w x_pos(a1),d0
addi.w #$50,d0
move.w d0,x_pos(a0)
+
subq.w #1,objoff_2A(a0)
bpl.s +
move.w #$20,objoff_2A(a0)
bsr.w loc_3D00C
+
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (Ani_objC5_objC6).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3CFC0:
move.b #2,mapping_frame(a0)
clr.w x_vel(a0)
tst.b render_flags(a0)
bpl.s +
addq.b #2,routine_secondary(a0) ; => ObjC6_State2_State5
move.w #$80,x_vel(a0)
move.w #-$200,y_vel(a0)
move.b #2,mapping_frame(a0)
move.w #$50,objoff_2A(a0)
bset #3,status(a0)
+
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; loc_3CFF6:
ObjC6_State2_State5:
subq.w #1,objoff_2A(a0)
bmi.w JmpTo65_DeleteObject
addi.w #$10,y_vel(a0)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3D00C:
lea (word_3D0D4).l,a2
bsr.w LoadChildObject
move.b #$AA,subtype(a1) ; <== ObjC6_SubObjData
move.b #5,mapping_frame(a1)
move.w #-$100,x_vel(a1)
subi.w #$18,y_pos(a1)
move.w #8,objoff_2A(a1)
rts
; ===========================================================================
; loc_3D036:
ObjC6_State3:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w ObjC6_State3_States(pc,d0.w),d1
jmp ObjC6_State3_States(pc,d1.w)
; ===========================================================================
; off_3D044:
ObjC6_State3_States: offsetTable
offsetTableEntry.w ObjC6_State3_State1 ; 0
offsetTableEntry.w ObjC6_State3_State2 ; 2
offsetTableEntry.w ObjC6_State3_State3 ; 4
; ===========================================================================
; loc_3D04A:
ObjC6_State3_State1:
movea.w objoff_2C(a0),a1 ; a1=object
btst #2,status(a1)
bne.s loc_3D05E
bsr.w loc_3D086
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ---------------------------------------------------------------------------
loc_3D05E:
addq.b #2,routine_secondary(a0) ; => ObjC6_State3_State2
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; loc_3D066:
ObjC6_State3_State2:
bsr.w loc_3D086
lea (Ani_objC6).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
; loc_3D078:
ObjC6_State3_State3:
lea (MainCharacter).w,a1 ; a1=character
bclr #5,status(a1)
bra.w JmpTo65_DeleteObject
; ===========================================================================
loc_3D086:
move.w x_pos(a0),-(sp)
move.w #$13,d1
move.w #$20,d2
move.w #$20,d3
move.w (sp)+,d4
jmpto (SolidObject).l, JmpTo27_SolidObject
; ===========================================================================
; loc_3D09C:
ObjC6_State4:
subq.w #1,objoff_2A(a0)
bmi.w JmpTo65_DeleteObject
addi.w #$10,y_vel(a0)
jsrto (ObjectMove).l, JmpTo26_ObjectMove
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
; off_3D0B2:
ObjC6_SubObjData3:
subObjData ObjC6_MapUnc_3D0EE,make_art_tile(ArtTile_ArtKos_LevelArt,0,0),4,5,$18,0
; off_3D0BC:
ObjC6_SubObjData4:
subObjData ObjC6_MapUnc_3D1DE,make_art_tile(ArtTile_ArtNem_ConstructionStripes_1,1,0),4,1,8,0
; off_3D0C6:
ObjC6_SubObjData:
subObjData ObjC6_MapUnc_3D0EE,make_art_tile(ArtTile_ArtKos_LevelArt,0,0),4,5,4,0
word_3D0D0:
dc.w objoff_3E
dc.b ObjID_Eggman
dc.b $A8
word_3D0D4:
dc.w objoff_3C
dc.b ObjID_Eggman
dc.b $AA
; animation script
; off_3D0D8:
Ani_objC5_objC6:offsetTable
offsetTableEntry.w byte_3D0DC ; 0
offsetTableEntry.w byte_3D0E2 ; 1
byte_3D0DC: dc.b 5, 2, 3, 4,$FF, 0
byte_3D0E2: dc.b 5, 6, 7,$FF
even
; animation script
; off_3D0E6:
Ani_objC6: offsetTable
offsetTableEntry.w + ; 0
+ dc.b 1, 0, 1, 2, 3,$FA
even
; ----------------------------------------------------------------------------
; sprite mappings ; Robotnik running
; ----------------------------------------------------------------------------
ObjC6_MapUnc_3D0EE: BINCLUDE "mappings/sprite/objC6_a.bin"
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
ObjC6_MapUnc_3D1DE: BINCLUDE "mappings/sprite/objC6_b.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object C8 - Crawl (shield badnik) from CNZ
; ----------------------------------------------------------------------------
; Sprite_3D23E:
ObjC8:
moveq #0,d0
move.b routine(a0),d0
move.w ObjC8_Index(pc,d0.w),d1
jmp ObjC8_Index(pc,d1.w)
; ===========================================================================
; off_3D24C:
ObjC8_Index: offsetTable
offsetTableEntry.w ObjC8_Init ; 0
offsetTableEntry.w loc_3D27C ; 2
offsetTableEntry.w loc_3D2A6 ; 4
offsetTableEntry.w loc_3D2D4 ; 6
; ===========================================================================
; loc_3D254:
ObjC8_Init:
bsr.w LoadSubObject
move.w #$200,objoff_2A(a0)
moveq #$20,d0
btst #0,render_flags(a0)
bne.s +
neg.w d0
+
move.w d0,x_vel(a0)
move.b #$F,y_radius(a0)
move.b #$10,x_radius(a0)
rts
; ===========================================================================
loc_3D27C:
subq.w #1,objoff_2A(a0)
beq.s +
jsrto (ObjectMove).l, JmpTo26_ObjectMove
bsr.w loc_3D416
lea (Ani_objC8).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
+
addq.b #2,routine(a0)
move.w #$3B,objoff_2A(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3D2A6:
subq.w #1,objoff_2A(a0)
bmi.s +
bsr.w loc_3D416
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
+
move.b #2,routine(a0)
move.w #$200,objoff_2A(a0)
neg.w x_vel(a0)
bchg #0,render_flags(a0)
bchg #0,status(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3D2D4:
move.b #$D7,collision_flags(a0)
bsr.w Obj_GetOrientationToPlayer
move.w d2,d4
addi.w #$40,d2
cmpi.w #$80,d2
bhs.w loc_3D39A
addi.w #$40,d3
cmpi.w #$80,d3
bhs.w loc_3D39A
bclr #3,status(a0)
bne.w loc_3D386
move.b collision_property(a0),d0
beq.s BranchTo18_JmpTo39_MarkObjGone
bclr #0,collision_property(a0)
beq.s +++
cmpi.b #AniIDSonAni_Roll,anim(a1)
bne.s loc_3D36C
btst #1,status(a1)
bne.s ++
bsr.w Obj_GetOrientationToPlayer
btst #0,render_flags(a0)
beq.s +
subq.w #2,d0
+
tst.w d0
bne.s loc_3D390
+
bsr.s loc_3D3A4
+
lea (Sidekick).w,a1 ; a1=character
bclr #1,collision_property(a0)
beq.s +++
cmpi.b #AniIDTailsAni_Roll,anim(a1)
bne.s loc_3D36C
btst #1,status(a1)
bne.s ++
bsr.w Obj_GetOrientationToPlayer
btst #0,render_flags(a0)
beq.s +
subq.w #2,d0
+
tst.w d0
bne.s loc_3D390
+
bsr.s loc_3D3A4
+
clr.b collision_property(a0)
BranchTo18_JmpTo39_MarkObjGone
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3D36C:
move.b #$97,collision_flags(a0)
btst #status_sec_isInvincible,status_secondary(a1)
beq.s +
move.b #$17,collision_flags(a0)
+
bset #3,status(a0)
loc_3D386:
move.b #1,mapping_frame(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3D390:
move.b #$17,collision_flags(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3D39A:
move.b objoff_2C(a0),routine(a0)
jmpto (MarkObjGone).l, JmpTo39_MarkObjGone
; ===========================================================================
loc_3D3A4:
move.b #2,mapping_frame(a0)
btst #1,status(a1)
beq.s +
move.b #3,mapping_frame(a0)
+
move.w x_pos(a0),d1
move.w y_pos(a0),d2
sub.w x_pos(a1),d1
sub.w y_pos(a1),d2
jsr (CalcAngle).l
move.b (Timer_frames).w,d1
andi.w #3,d1
add.w d1,d0
jsr (CalcSine).l
muls.w #-$700,d1
asr.l #8,d1
move.w d1,x_vel(a1)
muls.w #-$700,d0
asr.l #8,d0
move.w d0,y_vel(a1)
bset #1,status(a1)
bclr #4,status(a1)
bclr #5,status(a1)
clr.b jumping(a1)
move.w #SndID_Bumper,d0
jsr (PlaySound).l
rts
; ===========================================================================
; unused
rts
; ===========================================================================
loc_3D416:
bsr.w Obj_GetOrientationToPlayer
addi.w #$40,d2
cmpi.w #$80,d2
bhs.s + ; rts
addi.w #$40,d3
cmpi.w #$80,d3
bhs.s + ; rts
move.b routine(a0),objoff_2C(a0)
move.b #6,routine(a0)
clr.b mapping_frame(a0)
+
rts
; ===========================================================================
; off_3D440:
ObjC8_SubObjData:
subObjData ObjC8_MapUnc_3D450,make_art_tile(ArtTile_ArtNem_Crawl,0,1),4,3,$10,$D7
; animation script
; off_3D44A:
Ani_objC8: offsetTable
offsetTableEntry.w + ; 0
+ dc.b $13, 0, 1,$FF
even
; ----------------------------------------------------------------------------
; sprite mappings ; Crawl CNZ
; ----------------------------------------------------------------------------
ObjC8_MapUnc_3D450: BINCLUDE "mappings/sprite/objC8.bin"
; ===========================================================================
; ----------------------------------------------------------------------------
; Object C7 - Eggrobo (final boss) from Death Egg
; ----------------------------------------------------------------------------
; Sprite_3D4C8:
ObjC7:
moveq #0,d0
move.b routine(a0),d0
move.w ObjC7_Index(pc,d0.w),d1
jmp ObjC7_Index(pc,d1.w)
; ===========================================================================
; off_3D4D6:
ObjC7_Index: offsetTable
offsetTableEntry.w ObjC7_Init ; 0
offsetTableEntry.w ObjC7_Body ; 2
offsetTableEntry.w ObjC7_Shoulder ; 4
offsetTableEntry.w ObjC7_FrontLowerLeg ; 6
offsetTableEntry.w ObjC7_FrontForearm ; 8
offsetTableEntry.w ObjC7_Arm ; $A
offsetTableEntry.w ObjC7_FrontThigh ; $C
offsetTableEntry.w ObjC7_Head ; $E
offsetTableEntry.w ObjC7_Jet ; $10
offsetTableEntry.w ObjC7_BackLowerLeg ; $12
offsetTableEntry.w ObjC7_BackForearm ; $14
offsetTableEntry.w ObjC7_BackThigh ; $16
offsetTableEntry.w ObjC7_TargettingSensor ; $18
offsetTableEntry.w ObjC7_TargettingLock ; $1A
offsetTableEntry.w ObjC7_EggmanBomb ; $1C
offsetTableEntry.w ObjC7_FallingPieces ; $1E
offsetTableEntry.w ObjC7_SetupEnding ; $20
; ===========================================================================
; loc_3D4F8:
ObjC7_Init:
lea ObjC7_SubObjData(pc),a1
bsr.w LoadSubObject_Part3
move.b subtype(a0),routine(a0)
rts
; ===========================================================================
;loc_3D508
ObjC7_Body:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3D51A(pc,d0.w),d1
jsr off_3D51A(pc,d1.w)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
off_3D51A: offsetTable
offsetTableEntry.w loc_3D52A ; 0
offsetTableEntry.w loc_3D5A8 ; 2
offsetTableEntry.w loc_3D5C2 ; 4
offsetTableEntry.w loc_3D5EA ; 6
offsetTableEntry.w loc_3D62E ; 8
offsetTableEntry.w loc_3D640 ; $A
offsetTableEntry.w loc_3D684 ; $C
offsetTableEntry.w loc_3D8D2 ; $E
; ===========================================================================
loc_3D52A:
addq.b #2,routine_secondary(a0)
move.b #3,mapping_frame(a0)
move.b #5,priority(a0)
lea (ChildObjC7_Shoulder).l,a2
bsr.w LoadChildObject
lea (ChildObjC7_FrontForearm).l,a2
bsr.w LoadChildObject
lea (ChildObjC7_FrontLowerLeg).l,a2
bsr.w LoadChildObject
lea (ChildObjC7_Arm).l,a2
bsr.w LoadChildObject
lea (ChildObjC7_FrontThigh).l,a2
bsr.w LoadChildObject
lea (ChildObjC7_Head).l,a2
bsr.w LoadChildObject
lea (ChildObjC7_Jet).l,a2
bsr.w LoadChildObject
lea (ChildObjC7_BackLowerLeg).l,a2
bsr.w LoadChildObject
lea (ChildObjC7_BackForearm).l,a2
bsr.w LoadChildObject
lea (ChildObjC7_BackThigh).l,a2
bsr.w LoadChildObject
lea (ObjC7_ChildDeltas).l,a1
bra.w ObjC7_PositionChildren
; ===========================================================================
loc_3D5A8:
btst #2,status(a0)
bne.s +
rts
; ---------------------------------------------------------------------------
+
addq.b #2,routine_secondary(a0)
move.b #$3C,anim_frame_duration(a0)
moveq #MusID_FadeOut,d0
jmpto (PlaySound).l, JmpTo12_PlaySound
; ===========================================================================
loc_3D5C2:
subq.b #1,anim_frame_duration(a0)
bmi.s +
rts
; ---------------------------------------------------------------------------
+
addq.b #2,routine_secondary(a0)
move.b #$79,anim_frame_duration(a0)
move.w #-$100,y_vel(a0)
movea.w objoff_38(a0),a1 ; a1=object
move.b #4,routine_secondary(a1)
moveq #MusID_EndBoss,d0
jmpto (PlayMusic).l, JmpTo5_PlayMusic
; ===========================================================================
loc_3D5EA:
subq.b #1,anim_frame_duration(a0)
beq.s +
moveq #SndID_Rumbling,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (ObjC7_ChildDeltas).l,a1
bra.w ObjC7_PositionChildren
; ---------------------------------------------------------------------------
+
addq.b #2,routine_secondary(a0)
clr.w y_vel(a0)
move.b #$1F,anim_frame_duration(a0)
move.b #$16,collision_flags(a0)
move.b #$C,collision_property(a0)
bsr.w ObjC7_InitCollision
movea.w objoff_38(a0),a1 ; a1=object
move.b #6,routine_secondary(a1)
rts
; ===========================================================================
loc_3D62E:
bsr.w ObjC7_CheckHit
subq.b #1,anim_frame_duration(a0)
bmi.s +
rts
; ---------------------------------------------------------------------------
+
addq.b #2,routine_secondary(a0)
rts
; ===========================================================================
loc_3D640:
bsr.w ObjC7_CheckHit
addq.b #2,routine_secondary(a0)
move.b #$20,anim_frame_duration(a0)
move.b angle(a0),d0
addq.b #1,d0
move.b d0,angle(a0)
andi.w #3,d0
move.b byte_3D680(pc,d0.w),d0
move.b d0,anim(a0)
clr.b next_anim(a0)
cmpi.b #2,d0
bne.s + ; rts
movea.w objoff_38(a0),a1 ; a1=object
move.b #4,routine_secondary(a1)
move.b #2,anim(a1)
+
rts
; ===========================================================================
byte_3D680:
dc.b 2
dc.b 0 ; 1
dc.b 2 ; 2
dc.b 4 ; 3
; ===========================================================================
loc_3D684:
bsr.w ObjC7_CheckHit
moveq #0,d0
move.b anim(a0),d0
move.w off_3D696(pc,d0.w),d1
jmp off_3D696(pc,d1.w)
; ===========================================================================
off_3D696: offsetTable
offsetTableEntry.w loc_3D6AA ; 0
offsetTableEntry.w loc_3D702 ; 2
offsetTableEntry.w loc_3D83C ; 4
; ===========================================================================
subq.b #1,anim_frame_duration(a0)
bmi.s +
rts
; ---------------------------------------------------------------------------
+
addq.b #2,anim(a0)
rts
; ===========================================================================
loc_3D6AA:
moveq #0,d0
move.b next_anim(a0),d0
move.w off_3D6B8(pc,d0.w),d1
jmp off_3D6B8(pc,d1.w)
; ===========================================================================
off_3D6B8: offsetTable
offsetTableEntry.w loc_3D6C0 ; 0
offsetTableEntry.w loc_3D6CE ; 2
offsetTableEntry.w loc_3D6C0 ; 4
offsetTableEntry.w loc_3D6E8 ; 6
; ===========================================================================
loc_3D6C0:
subq.b #1,anim_frame_duration(a0)
bmi.s +
rts
; ---------------------------------------------------------------------------
+
addq.b #2,next_anim(a0)
rts
; ===========================================================================
loc_3D6CE:
lea (off_3E40C).l,a1
bsr.w loc_3E1AA
bne.s +
rts
; ---------------------------------------------------------------------------
+
addq.b #2,next_anim(a0)
move.b #$40,anim_frame_duration(a0)
rts
; ===========================================================================
loc_3D6E8:
lea (off_3E42C).l,a1
bsr.w loc_3E1AA
bne.s +
rts
; ---------------------------------------------------------------------------
+
subq.b #2,routine_secondary(a0)
move.b #$40,anim_frame_duration(a0)
rts
; ===========================================================================
loc_3D702:
moveq #0,d0
move.b next_anim(a0),d0
move.w off_3D710(pc,d0.w),d1
jmp off_3D710(pc,d1.w)
; ===========================================================================
off_3D710: offsetTable
offsetTableEntry.w loc_3D6C0 ; 0
offsetTableEntry.w loc_3D720 ; 2
offsetTableEntry.w loc_3D744 ; 4
offsetTableEntry.w loc_3D6C0 ; 6
offsetTableEntry.w loc_3D784 ; 8
offsetTableEntry.w loc_3D7B8 ; $A
offsetTableEntry.w loc_3D7F0 ; $C
offsetTableEntry.w loc_3D82E ; $C
; ===========================================================================
loc_3D720:
lea (off_3E3D0).l,a1
bsr.w loc_3E1AA
bne.s +
rts
; ---------------------------------------------------------------------------
+
addq.b #2,next_anim(a0)
move.b #$80,anim_frame_duration(a0)
clr.w x_vel(a0)
move.w #-$200,y_vel(a0)
rts
; ===========================================================================
loc_3D744:
subq.b #1,anim_frame_duration(a0)
bmi.s ++
move.b (Vint_runcount+3).w,d0
andi.b #$1F,d0
bne.s +
moveq #SndID_Fire,d0
jsrto (PlaySoundLocal).l, JmpTo_PlaySoundLocal
+
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (ObjC7_ChildDeltas).l,a1
bra.w ObjC7_PositionChildren
; ---------------------------------------------------------------------------
+
addq.b #2,next_anim(a0)
clr.w y_vel(a0)
lea (ChildObjC7_TargettingSensor).l,a2
bsr.w LoadChildObject
clr.w x_vel(a0)
clr.w objoff_28(a0)
rts
; ===========================================================================
loc_3D784:
move.w objoff_28(a0),d0
bne.s +
rts
; ---------------------------------------------------------------------------
+
addq.b #2,next_anim(a0)
move.w d0,x_pos(a0)
bclr #0,render_flags(a0)
cmpi.w #$780,d0
bhs.s +
bset #0,render_flags(a0)
+
bsr.w loc_3E168
move.w #$800,y_vel(a0)
move.b #$20,anim_frame_duration(a0)
rts
; ===========================================================================
loc_3D7B8:
subq.b #1,anim_frame_duration(a0)
bmi.s +
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (ObjC7_ChildDeltas).l,a1
bra.w ObjC7_PositionChildren
; ---------------------------------------------------------------------------
+
addq.b #2,next_anim(a0)
clr.w y_vel(a0)
move.b #1,(Screen_Shaking_Flag).w
move.w #$40,(DEZ_Shake_Timer).w
movea.w objoff_38(a0),a1 ; a1=object
move.b #6,routine_secondary(a1)
moveq #SndID_Smash,d0
jmpto (PlaySound).l, JmpTo12_PlaySound
; ===========================================================================
loc_3D7F0:
lea (off_3E30A).l,a1
bsr.w loc_3E1AA
bne.s +
rts
; ---------------------------------------------------------------------------
+
lea (ObjC7_ChildDeltas).l,a1
bsr.w ObjC7_PositionChildren
bsr.w Obj_GetOrientationToPlayer
btst #0,render_flags(a0)
beq.s +
subq.w #2,d0
+
tst.w d0
bne.s +
subq.b #2,routine_secondary(a0)
rts
; ---------------------------------------------------------------------------
+
addq.b #2,next_anim(a0)
move.b #$60,anim_frame_duration(a0)
bra.w CreateEggmanBombs
; ===========================================================================
loc_3D82E:
subq.b #1,anim_frame_duration(a0)
bmi.s +
rts
; ---------------------------------------------------------------------------
+
subq.b #2,routine_secondary(a0)
rts
; ===========================================================================
loc_3D83C:
moveq #0,d0
move.b next_anim(a0),d0
move.w off_3D84A(pc,d0.w),d1
jmp off_3D84A(pc,d1.w)
; ===========================================================================
off_3D84A: offsetTable
offsetTableEntry.w loc_3D6C0 ; 0
offsetTableEntry.w loc_3D856 ; 2
offsetTableEntry.w loc_3D6C0 ; 4
offsetTableEntry.w loc_3D89E ; 6
offsetTableEntry.w loc_3D6C0 ; 8
offsetTableEntry.w loc_3D8B8 ; $A
; ===========================================================================
loc_3D856:
bset #6,status(a0)
lea (off_3E2F6).l,a1
bsr.w loc_3E1AA
bne.s +
rts
; ---------------------------------------------------------------------------
+
bsr.w Obj_GetOrientationToPlayer
btst #0,render_flags(a0)
beq.s +
subq.w #2,d0
+
tst.w d0
bne.s +
addq.b #2,next_anim(a0)
move.b #$40,anim_frame_duration(a0)
bset #4,status(a0)
rts
; ---------------------------------------------------------------------------
+
move.b #8,next_anim(a0)
move.b #$20,anim_frame_duration(a0)
bra.w CreateEggmanBombs
; ===========================================================================
loc_3D89E:
subq.b #1,anim_frame_duration(a0)
bmi.s +
rts
; ---------------------------------------------------------------------------
+
addq.b #2,next_anim(a0)
bset #5,status(a0)
move.b #$40,anim_frame_duration(a0)
rts
; ===========================================================================
loc_3D8B8:
lea (off_3E300).l,a1
bsr.w loc_3E1AA
bne.s +
rts
; ---------------------------------------------------------------------------
+
subq.b #2,routine_secondary(a0)
bclr #6,status(a0)
rts
; ===========================================================================
loc_3D8D2:
moveq #0,d0
move.b anim(a0),d0
move.w off_3D8E0(pc,d0.w),d1
jmp off_3D8E0(pc,d1.w)
; ===========================================================================
off_3D8E0: offsetTable
offsetTableEntry.w loc_3D8E6 ; 0
offsetTableEntry.w loc_3D922 ; 2
offsetTableEntry.w loc_3D93C ; 4
; ===========================================================================
loc_3D8E6:
jsrto (Boss_LoadExplosion).l, JmpTo_Boss_LoadExplosion
jsrto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall
move.w y_pos(a0),d0
cmpi.w #$15C,d0
bhs.s +
rts
; ---------------------------------------------------------------------------
+
move.w #$15C,y_pos(a0)
move.w y_vel(a0),d0
bmi.s +
lsr.w #2,d0
cmpi.w #$100,d0
blo.s +
neg.w d0
move.w d0,y_vel(a0)
rts
; ---------------------------------------------------------------------------
+
addq.b #2,anim(a0)
move.b #$40,anim_frame_duration(a0)
rts
; ===========================================================================
loc_3D922:
subq.b #1,anim_frame_duration(a0)
bmi.s +
jmpto (Boss_LoadExplosion).l, JmpTo_Boss_LoadExplosion
; ---------------------------------------------------------------------------
+
addq.b #2,anim(a0)
st (Control_Locked).w
move.w #$1000,(Camera_Max_X_pos).w
rts
; ===========================================================================
loc_3D93C:
move.w #(button_right_mask<<8)|button_right_mask,(Ctrl_1_Logical).w
cmpi.w #$840,(Camera_X_pos).w
bhs.s +
rts
; ---------------------------------------------------------------------------
+
move.b #$20,routine(a0)
clr.b routine_secondary(a0)
move.w #$20,objoff_2A(a0)
move.b #1,(Screen_Shaking_Flag).w
move.w #$1000,(DEZ_Shake_Timer).w
movea.w objoff_36(a0),a1 ; a1=object
jmpto (DeleteObject2).l, JmpTo6_DeleteObject2
; ===========================================================================
;loc_3D970
ObjC7_SetupEnding:
move.b (Vint_runcount+3).w,d0
andi.b #$1F,d0
bne.s +
moveq #SndID_Rumbling2,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
subq.w #1,objoff_2A(a0)
+
lea (MainCharacter).w,a1 ; a1=character
move.w x_pos(a1),d0
sub.w objoff_2A(a0),d0
move.w d0,x_pos(a0)
move.w y_pos(a1),y_pos(a0)
bsr.w loc_3DFBA
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3D9AC(pc,d0.w),d1
jmp off_3D9AC(pc,d1.w)
; ===========================================================================
off_3D9AC: offsetTable
offsetTableEntry.w loc_3D9B0 ; 0
offsetTableEntry.w loc_3D9D6 ; 2
; ===========================================================================
loc_3D9B0:
lea (MainCharacter).w,a1 ; a1=character
cmpi.w #$EC0,x_pos(a1)
bhs.s loc_3D9BE
rts
; ===========================================================================
loc_3D9BE:
addq.b #2,routine_secondary(a0)
move.w #$3F,(Palette_fade_range).w
move.b #$16,anim_frame_duration(a0)
move.w #$7FFF,(PalCycle_Timer).w
rts
; ===========================================================================
loc_3D9D6:
subq.b #1,anim_frame_duration(a0)
beq.w +
movea.l a0,a1
lea (Normal_palette).w,a0
moveq #$3F,d0
- jsrto (Pal_FadeToWhite.UpdateColour).l, JmpTo_Pal_FadeToWhite_UpdateColour
dbf d0,-
movea.l a1,a0
rts
; ---------------------------------------------------------------------------
+
move.l #$EEE0EEE,d0
lea (Normal_palette).w,a1
moveq #$1F,d6
- move.l d0,(a1)+
dbf d6,-
moveq #MusID_FadeOut,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
move.b #GameModeID_EndingSequence,(Game_Mode).w ; => EndingSequence
bra.w JmpTo65_DeleteObject
; ===========================================================================
ObjC7_Shoulder:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3DA34(pc,d0.w),d1
jsr off_3DA34(pc,d1.w)
lea byte_3DA38(pc),a1
bsr.w loc_3E282
tst.b (a0)
beq.w return_37A48
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
off_3DA34: offsetTable
offsetTableEntry.w loc_3DA3C ; 0
offsetTableEntry.w return_3DA48 ; 2
; ===========================================================================
byte_3DA38:
dc.b 0
dc.b $C ; 1
dc.b $FF ; 2
dc.b $EC ; 3
; ===========================================================================
loc_3DA3C:
addq.b #2,routine_secondary(a0)
move.b #4,mapping_frame(a0)
rts
; ===========================================================================
return_3DA48:
rts
; ===========================================================================
;loc_3DA4A
ObjC7_FrontLowerLeg:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3DA62(pc,d0.w),d1
jsr off_3DA62(pc,d1.w)
tst.b (a0)
beq.w return_37A48
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
off_3DA62: offsetTable
offsetTableEntry.w loc_3DA66 ; 0
offsetTableEntry.w return_3DA72 ; 2
; ===========================================================================
loc_3DA66:
addq.b #2,routine_secondary(a0)
move.b #$B,mapping_frame(a0)
rts
; ===========================================================================
return_3DA72:
rts
; ===========================================================================
;loc_3DA74
ObjC7_FrontForearm:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3DA96(pc,d0.w),d1
jsr off_3DA96(pc,d1.w)
tst.b (a0)
beq.w return_37A48
btst #6,status(a0)
bne.w return_37A48
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
off_3DA96: offsetTable
offsetTableEntry.w loc_3DAA0 ; 0
offsetTableEntry.w loc_3DAAC ; 2
offsetTableEntry.w loc_3DACC ; 4
offsetTableEntry.w loc_3DB32 ; 6
offsetTableEntry.w loc_3DB5A ; 8
; ===========================================================================
loc_3DAA0:
addq.b #2,routine_secondary(a0)
move.b #6,mapping_frame(a0)
rts
; ===========================================================================
loc_3DAAC:
movea.w objoff_2C(a0),a1 ; a1=object
bclr #4,status(a1)
bne.s +
rts
; ---------------------------------------------------------------------------
+
addq.b #2,routine_secondary(a0)
move.w #$10,objoff_2A(a0)
move.w y_pos(a0),objoff_2E(a0)
rts
; ===========================================================================
loc_3DACC:
subq.w #1,objoff_2A(a0)
bmi.s +
addi.w #$20,y_vel(a0)
jmpto (ObjectMove).l, JmpTo26_ObjectMove
; ---------------------------------------------------------------------------
+
addq.b #2,routine_secondary(a0)
move.w #$20,objoff_2A(a0)
bsr.w Obj_GetOrientationToPlayer
abs.w d2
cmpi.w #$100,d2
blo.s +
move.w #$FF,d2
+
andi.w #$C0,d2
lsr.w #5,d2
move.w word_3DB2A(pc,d2.w),d2
tst.w d1
bne.s +
neg.w d2
+
move.w d2,y_vel(a0)
move.w #$800,d2
movea.w objoff_2C(a0),a1 ; a1=object
btst #0,render_flags(a0)
bne.s +
neg.w d2
+
move.w d2,x_vel(a0)
moveq #SndID_SpindashRelease,d0
jmpto (PlaySound).l, JmpTo12_PlaySound
; ===========================================================================
word_3DB2A:
dc.w $200
dc.w $100 ; 1
dc.w $80 ; 2
dc.w 0 ; 3
; ===========================================================================
loc_3DB32:
subq.w #1,objoff_2A(a0)
bmi.s +
jmpto (ObjectMove).l, JmpTo26_ObjectMove
; ---------------------------------------------------------------------------
+
addq.b #2,routine_secondary(a0)
neg.w x_vel(a0)
move.w #$20,objoff_2A(a0)
move.w objoff_2E(a0),d0
sub.w y_pos(a0),d0
asl.w #3,d0
move.w d0,y_vel(a0)
rts
; ===========================================================================
loc_3DB5A:
subq.w #1,objoff_2A(a0)
bmi.s +
jmpto (ObjectMove).l, JmpTo26_ObjectMove
; ---------------------------------------------------------------------------
+
move.b #2,routine_secondary(a0)
clr.w x_vel(a0)
clr.w y_vel(a0)
rts
; ===========================================================================
;loc_3DB74
ObjC7_Arm:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3DB8C(pc,d0.w),d1
jsr off_3DB8C(pc,d1.w)
tst.b (a0)
beq.w return_37A48
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
off_3DB8C: offsetTable
offsetTableEntry.w loc_3DB90 ; 0
offsetTableEntry.w return_3DB9C ; 2
; ===========================================================================
loc_3DB90:
addq.b #2,routine_secondary(a0)
move.b #5,mapping_frame(a0)
rts
; ===========================================================================
return_3DB9C:
rts
; ===========================================================================
;loc_3DB9E
ObjC7_FrontThigh:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3DBB6(pc,d0.w),d1
jsr off_3DBB6(pc,d1.w)
tst.b (a0)
beq.w return_37A48
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
off_3DBB6: offsetTable
offsetTableEntry.w loc_3DBBA ; 0
offsetTableEntry.w return_3DBC6 ; 2
; ===========================================================================
loc_3DBBA:
addq.b #2,routine_secondary(a0)
move.b #$A,mapping_frame(a0)
rts
; ===========================================================================
return_3DBC6:
rts
; ===========================================================================
;loc_3DBC8
ObjC7_Head:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3DBE8(pc,d0.w),d1
jsr off_3DBE8(pc,d1.w)
lea byte_3DBF2(pc),a1
bsr.w loc_3E282
tst.b (a0)
beq.w return_37A48
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
off_3DBE8: offsetTable
offsetTableEntry.w loc_3DBF6 ; 0
offsetTableEntry.w loc_3DC02 ; 2
offsetTableEntry.w loc_3DC1C ; 4
offsetTableEntry.w loc_3DC2A ; 6
offsetTableEntry.w loc_3DC46 ; 8
; ===========================================================================
byte_3DBF2:
dc.b 0
dc.b 0 ; 1
dc.b $FF ; 2
dc.b $CC ; 3
; ===========================================================================
loc_3DBF6:
addq.b #2,routine_secondary(a0)
move.b #$15,mapping_frame(a0)
rts
; ===========================================================================
loc_3DC02:
movea.w (DEZ_Eggman).w,a1
btst #3,$22(a1)
bne.s +
rts
; ---------------------------------------------------------------------------
+
addq.b #2,routine_secondary(a0)
move.w #$40,objoff_2A(a0)
rts
; ===========================================================================
loc_3DC1C:
lea (Ani_objC7_a).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3DC2A:
subq.w #1,objoff_2A(a0)
bmi.s +
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ---------------------------------------------------------------------------
+
addq.b #2,routine_secondary(a0)
movea.w objoff_2C(a0),a1 ; a1=object
bset #2,status(a1)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3DC46:
move.b #-1,collision_property(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
;loc_3DC50
ObjC7_Jet:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3DC66(pc,d0.w),d1
jsr off_3DC66(pc,d1.w)
lea byte_3DC70(pc),a1
bra.w loc_3E282
; ===========================================================================
off_3DC66: offsetTable
offsetTableEntry.w loc_3DC74
offsetTableEntry.w loc_3DC80
offsetTableEntry.w loc_3DC86
offsetTableEntry.w loc_3DC94
offsetTableEntry.w loc_3DC80
; ===========================================================================
byte_3DC70:
dc.b 0
dc.b $38 ; 1
dc.b 0 ; 2
dc.b $18 ; 3
; ===========================================================================
loc_3DC74:
addq.b #2,routine_secondary(a0)
move.b #$C,mapping_frame(a0)
rts
; ===========================================================================
loc_3DC80:
move.b #3,anim(a0)
loc_3DC86:
lea (Ani_objC7_b).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3DC94:
move.b #1,anim(a0)
bra.s loc_3DC86
; ===========================================================================
;loc_3DC9C
ObjC7_BackLowerLeg:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3DCB4(pc,d0.w),d1
jsr off_3DCB4(pc,d1.w)
tst.b (a0)
beq.w return_37A48
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
off_3DCB4: offsetTable
offsetTableEntry.w loc_3DCB8 ; 0
offsetTableEntry.w return_3DCCA ; 2
; ===========================================================================
loc_3DCB8:
addq.b #2,routine_secondary(a0)
move.b #$B,mapping_frame(a0)
move.b #5,priority(a0)
rts
; ===========================================================================
return_3DCCA:
rts
; ===========================================================================
;loc_3DCCC
ObjC7_BackForearm:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3DCE4(pc,d0.w),d1
jsr off_3DCE4(pc,d1.w)
tst.b (a0)
beq.w return_37A48
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
off_3DCE4: offsetTable
offsetTableEntry.w loc_3DCEE ; 0
offsetTableEntry.w loc_3DD00 ; 2
offsetTableEntry.w loc_3DACC ; 4
offsetTableEntry.w loc_3DB32 ; 6
offsetTableEntry.w loc_3DB5A ; 8
; ===========================================================================
loc_3DCEE:
addq.b #2,routine_secondary(a0)
move.b #6,mapping_frame(a0)
move.b #5,priority(a0)
rts
; ===========================================================================
loc_3DD00:
movea.w objoff_2C(a0),a1 ; a1=object
bclr #5,status(a1)
bne.s +
rts
; ---------------------------------------------------------------------------
+
addq.b #2,routine_secondary(a0)
move.w #$10,objoff_2A(a0)
move.w y_pos(a0),objoff_2E(a0)
rts
; ===========================================================================
;loc_3DD20
ObjC7_BackThigh:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3DD38(pc,d0.w),d1
jsr off_3DD38(pc,d1.w)
tst.b (a0)
beq.w return_37A48
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
off_3DD38: offsetTable
offsetTableEntry.w loc_3DD3C ; 0
offsetTableEntry.w return_3DD4E ; 2
; ===========================================================================
loc_3DD3C:
addq.b #2,routine_secondary(a0)
move.b #$A,mapping_frame(a0)
move.b #5,priority(a0)
rts
; ===========================================================================
return_3DD4E:
rts
; ===========================================================================
;loc_3DD50
ObjC7_TargettingSensor:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3DD5E(pc,d0.w),d1
jmp off_3DD5E(pc,d1.w)
; ===========================================================================
off_3DD5E: offsetTable
offsetTableEntry.w loc_3DD64 ; 0
offsetTableEntry.w loc_3DDA6 ; 2
offsetTableEntry.w loc_3DE3C ; 4
; ===========================================================================
loc_3DD64:
addq.b #2,routine_secondary(a0)
move.b #$10,mapping_frame(a0)
ori.w #high_priority,art_tile(a0)
move.b #1,priority(a0)
move.w #$A0,objoff_2A(a0)
lea (MainCharacter).w,a1 ; a1=character
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
move.w x_vel(a1),objoff_30(a0)
move.w y_vel(a1),objoff_32(a0)
move.w #$18,angle(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3DDA6:
subq.w #1,objoff_2A(a0)
bmi.s loc_3DE0A
lea next_object(a0),a1 ; a1=object
movea.l a1,a2
move.w -(a1),y_vel(a0)
move.w -(a1),x_vel(a0)
moveq #2,d6
- move.l -(a1),-(a2)
dbf d6,-
lea (MainCharacter).w,a2 ; a2=character
move.w x_vel(a2),d0
bne.s +
move.w x_pos(a2),x_pos(a0)
+
move.w d0,(a1)+
move.w y_vel(a2),d0
bne.s +
move.w y_pos(a2),y_pos(a0)
+
move.w d0,(a1)+
jsrto (ObjectMove).l, JmpTo26_ObjectMove
lea (Ani_objC7_c).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
subq.b #1,angle(a0)
bpl.s +
subq.b #1,objoff_27(a0)
move.b objoff_27(a0),angle(a0)
moveq #SndID_Beep,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
+
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3DE0A:
addq.b #2,routine_secondary(a0)
move.w #$40,objoff_2A(a0)
move.b #4,angle(a0)
lea (MainCharacter).w,a1 ; a1=character
move.w x_pos(a1),x_pos(a0)
move.w y_pos(a1),y_pos(a0)
lea (ChildObjC7_TargettingLock).l,a2
bsr.w LoadChildObject
clr.w x_vel(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3DE3C:
subq.w #1,objoff_2A(a0)
bmi.s loc_3DE62
lea (Ani_objC7_c).l,a1
jsrto (AnimateSprite).l, JmpTo25_AnimateSprite
subq.b #1,angle(a0)
bpl.s +
move.b #4,angle(a0)
moveq #SndID_Beep,d0
jsrto (PlaySound).l, JmpTo12_PlaySound
+
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3DE62:
movea.w objoff_2C(a0),a1 ; a1=object
move.w x_pos(a0),objoff_28(a1)
bra.w JmpTo65_DeleteObject
; ===========================================================================
;loc_3DE70
ObjC7_TargettingLock:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3DE7E(pc,d0.w),d1
jmp off_3DE7E(pc,d1.w)
; ===========================================================================
off_3DE7E: offsetTable
offsetTableEntry.w loc_3DE82 ; 0
offsetTableEntry.w loc_3DEA2 ; 2
; ===========================================================================
loc_3DE82:
addq.b #2,routine_secondary(a0)
move.b #$14,mapping_frame(a0)
move.b #1,priority(a0)
ori.w #high_priority,art_tile(a0)
move.w #4,objoff_2A(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3DEA2:
movea.w objoff_2C(a0),a1 ; a1=object
tst.b (a1)
beq.w JmpTo65_DeleteObject
subq.w #1,objoff_2A(a0)
bne.s +
move.w #4,objoff_2A(a0)
bchg #palette_bit_0,art_tile(a0)
+
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
;loc_3DEC2
ObjC7_EggmanBomb:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3DED0(pc,d0.w),d1
jmp off_3DED0(pc,d1.w)
; ===========================================================================
off_3DED0: offsetTable
offsetTableEntry.w loc_3DED8
offsetTableEntry.w loc_3DF04
offsetTableEntry.w loc_3DF36
offsetTableEntry.w loc_3DF80
; ===========================================================================
loc_3DED8:
addq.b #2,routine_secondary(a0)
move.b #$E,mapping_frame(a0)
move.b #$89,collision_flags(a0)
move.b #5,priority(a0)
move.b #$C,width_pixels(a0)
lea byte_3DF00(pc),a1
bsr.w loc_3E282
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
byte_3DF00:
dc.b 0
dc.b $38 ; 1
dc.b $FF ; 2
dc.b $EC ; 3
; ===========================================================================
loc_3DF04:
movea.w objoff_2C(a0),a1 ; a1=object
btst #7,status(a1)
bne.s loc_3DF4C
jsrto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall
move.w y_pos(a0),d0
cmpi.w #$170,d0
bhs.s +
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
+
addq.b #2,routine_secondary(a0)
move.w #$170,y_pos(a0)
move.w #$40,objoff_2A(a0)
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3DF36:
movea.w objoff_2C(a0),a1 ; a1=object
btst #7,status(a1)
bne.s loc_3DF4C
subq.w #1,objoff_2A(a0)
bmi.s loc_3DF4C
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3DF4C:
move.b #6,routine_secondary(a0)
move.l #Obj58_MapUnc_2D50A,mappings(a0)
move.w #make_art_tile(ArtTile_ArtNem_FieryExplosion,0,0),art_tile(a0)
move.b #1,priority(a0)
move.b #7,anim_frame_duration(a0)
move.b #0,mapping_frame(a0)
move.w #SndID_BossExplosion,d0
jsr (PlaySound).l
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3DF80:
subq.b #1,anim_frame_duration(a0)
bpl.s +
move.b #7,anim_frame_duration(a0)
addq.b #1,mapping_frame(a0)
cmpi.b #5,mapping_frame(a0)
blo.s +
clr.b collision_flags(a0)
cmpi.b #7,mapping_frame(a0)
beq.w JmpTo65_DeleteObject
+
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
;loc_3DFAA
ObjC7_FallingPieces:
subq.w #1,objoff_2A(a0)
bmi.w JmpTo65_DeleteObject
jsrto (ObjectMoveAndFall).l, JmpTo8_ObjectMoveAndFall
jmpto (DisplaySprite).l, JmpTo45_DisplaySprite
; ===========================================================================
loc_3DFBA:
jsr (SingleObjLoad).l
bne.s + ; rts
_move.b #ObjID_BossExplosion,id(a1) ; load obj
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
jsr (RandomNumber).l
move.w d0,d1
moveq #0,d1
move.b d0,d1
lsr.b #2,d1
subi.w #$30,d1
add.w d1,x_pos(a1)
lsr.w #8,d0
lsr.b #2,d0
subi.w #$30,d0
add.w d0,y_pos(a1)
+
rts
; ===========================================================================
;loc_3DFF8
ObjC7_CheckHit:
tst.b collision_property(a0)
beq.s ObjC7_Beaten
tst.b objoff_2A(a0)
bne.s ObjC7_Flashing
tst.b collision_flags(a0)
beq.s +
movea.w objoff_36(a0),a1 ; a1=object
tst.b collision_flags(a1)
bne.s +++ ; rts
clr.b collision_flags(a0)
subq.b #1,collision_property(a0)
beq.s ObjC7_Beaten
+
move.b #$3C,objoff_2A(a0)
move.w #SndID_BossHit,d0
jsr (PlaySound).l
;loc_3E02E
ObjC7_Flashing:
lea (Normal_palette_line2+2).w,a1
moveq #0,d0
tst.w (a1)
bne.s +
move.w #$EEE,d0
+
move.w d0,(a1)
subq.b #1,objoff_2A(a0)
bne.s +
clr.w (Normal_palette_line2+2).w
move.b #$16,collision_flags(a0)
movea.w objoff_36(a0),a1 ; a1=object
move.b #$2A,collision_flags(a1)
+
rts
; ===========================================================================
;loc_3E05A
ObjC7_Beaten:
moveq #100,d0
bsr.w AddPoints
clr.b anim_frame_duration(a0)
move.b #$E,routine_secondary(a0)
bset #7,status(a0)
clr.b anim(a0)
clr.b collision_flags(a0)
clr.w x_vel(a0)
clr.w y_vel(a0)
bsr.w ObjC7_RemoveCollision
bsr.w ObjC7_Break
movea.w objoff_38(a0),a1 ; a1=object
jsrto (DeleteObject2).l, JmpTo6_DeleteObject2
addq.w #4,sp
rts
; ===========================================================================
;loc_3E094
ObjC7_Break:
lea (ObjC7_BreakOffsets).l,a1
lea ObjC7_BreakSpeeds(pc),a2
moveq #0,d0
moveq #ObjC7_BreakOffsets_End-ObjC7_BreakOffsets-1,d6
- move.b (a1)+,d0
movea.w (a0,d0.w),a3 ; a3=object
move.b #$1E,routine(a3)
clr.b routine_secondary(a3)
move.w #$80,objoff_2A(a3)
move.w (a2)+,x_vel(a3)
move.w (a2)+,y_vel(a3)
dbf d6,-
rts
; ===========================================================================
;word_3E0C6
ObjC7_BreakSpeeds:
dc.w $200,-$400
dc.w -$100,-$100 ; 2
dc.w $300,-$300 ; 4
dc.w -$100,-$400 ; 6
dc.w $180,-$200 ; 8
dc.w -$200,-$300 ; 10
dc.w 0,-$400 ; 12
dc.w $100,-$300 ; 14
ObjC7_BreakSpeeds_End
;byte_3E0E6
ObjC7_BreakOffsets:
dc.b objoff_2C
dc.b objoff_2E ; 1
dc.b objoff_30 ; 2
dc.b objoff_32 ; 3
dc.b objoff_34 ; 4
dc.b objoff_3A ; 5
dc.b objoff_3C ; 6
dc.b objoff_3E ; 7
ObjC7_BreakOffsets_End
; ===========================================================================
;loc_3E0EE
ObjC7_InitCollision:
lea ObjC7_ChildOffsets(pc),a1
lea ObjC7_ChildCollision(pc),a2
moveq #0,d0
moveq #ObjC7_ChildCollision_End-ObjC7_ChildCollision-1,d6
- move.b (a1)+,d0
movea.w (a0,d0.w),a3 ; a3=object
move.b (a2)+,collision_flags(a3)
dbf d6,-
rts
; ===========================================================================
;byte_3E10A
ObjC7_ChildCollision:
dc.b 0
dc.b $8F ; 1
dc.b $9C ; 2
dc.b 0 ; 3
dc.b $86 ; 4
dc.b $2A ; 5
dc.b $8B ; 6
dc.b $8F ; 7
dc.b $9C ; 8
dc.b $8B ; 9
ObjC7_ChildCollision_End
;byte_3E114
ObjC7_ChildOffsets:
dc.b objoff_2C
dc.b objoff_2E ; 1
dc.b objoff_30 ; 2
dc.b objoff_32 ; 3
dc.b objoff_34 ; 4
dc.b objoff_36 ; 5
dc.b objoff_38 ; 6
dc.b objoff_3A ; 7
dc.b objoff_3C ; 8
dc.b objoff_3E ; 9
ObjC7_ChildOffsets_End
; ===========================================================================
;loc_3E11E
ObjC7_RemoveCollision:
lea ObjC7_ChildOffsets(pc),a1
moveq #0,d0
moveq #ObjC7_ChildOffsets_End-ObjC7_ChildOffsets-1,d6
- move.b (a1)+,d0
movea.w (a0,d0.w),a3 ; a3=object
clr.b collision_flags(a3)
dbf d6,-
rts
; ===========================================================================
;loc_3E136
CreateEggmanBombs:
lea EggmanBomb_InitSpeeds(pc),a3
moveq #1,d6
- lea (ChildObjC7_EggmanBomb).l,a2
bsr.w LoadChildObject
move.w (a3)+,d0
btst #0,render_flags(a0)
beq.s +
neg.w d0
+
move.w d0,x_vel(a1)
move.w (a3)+,y_vel(a1)
dbf d6,-
rts
; ===========================================================================
;word_3E160
EggmanBomb_InitSpeeds:
dc.w $60,-$800
dc.w $C0,-$A00
; ===========================================================================
loc_3E168:
move.b render_flags(a0),d0
andi.b #1,d0
moveq #0,d1
lea byte_3E19E(pc),a1
- move.b (a1)+,d1
beq.w return_37A48
movea.w (a0,d1.w),a2 ; a2=object
move.b render_flags(a2),d2
andi.b #$FE,d2
or.b d0,d2
move.b d2,render_flags(a2)
move.b status(a2),d2
andi.b #$FE,d2
or.b d0,d2
move.b d2,status(a2)
bra.s -
; ===========================================================================
byte_3E19E:
dc.b $2C
dc.b $2E ; 1
dc.b $30 ; 2
dc.b $32 ; 3
dc.b $34 ; 4
dc.b $36 ; 5
dc.b $38 ; 6
dc.b $3A ; 7
dc.b $3C ; 8
dc.b $3E ; 9
dc.b 0 ; 10
dc.b 0 ; 11
; ===========================================================================
loc_3E1AA:
movea.l (a1)+,a2
moveq #0,d0
move.b anim_frame(a0),d0
move.b (a1,d0.w),d0
move.b d0,d1
moveq #0,d4
andi.w #$C0,d1
beq.s +
bsr.w loc_3E23E
+
add.w d0,d0
adda.w (a2,d0.w),a2
move.b (a2)+,d0
move.b (a2)+,d3
move.b objoff_1F(a0),d2
addq.b #1,d2
cmp.b d3,d2
blo.s +
addq.b #1,anim_frame(a0)
moveq #0,d2
+
move.b d2,objoff_1F(a0)
moveq #0,d5
- move.b (a2)+,d5
movea.w (a0,d5.w),a3 ; a3=object
tst.w d5
bne.s +
movea.l a0,a3
+
move.l x_pos(a3),d2
move.b (a2)+,d1
ext.w d1
asl.w #4,d1
btst #0,render_flags(a0)
beq.s +
neg.w d1
+
tst.w d4
beq.s +
neg.w d1
+
ext.l d1
asl.l #8,d1
add.l d1,d2
move.l d2,x_pos(a3)
move.l y_pos(a3),d3
move.b (a2)+,d1
ext.w d1
asl.w #4,d1
tst.w d4
beq.s +
neg.w d1
+
ext.l d1
asl.l #8,d1
add.l d1,d3
move.l d3,y_pos(a3)
dbf d0,-
moveq #0,d1
rts
; ===========================================================================
loc_3E236:
clr.b anim_frame(a0)
moveq #1,d1
return_3E23C:
rts
; ===========================================================================
loc_3E23E:
andi.b #$3F,d0
rol.b #3,d1
move.w off_3E24C-2(pc,d1.w),d1
jmp off_3E24C(pc,d1.w)
; ===========================================================================
off_3E24C: offsetTable
offsetTableEntry.w loc_3E252
offsetTableEntry.w loc_3E27A
offsetTableEntry.w loc_3E27E
; ===========================================================================
loc_3E252:
tst.b objoff_1F(a0)
bne.s return_3E23C
move.b anim_frame(a0),d1
addq.b #1,d1
move.b (a1,d1.w),d0
jsrto (PlaySound).l, JmpTo12_PlaySound ; sound id most likely came from off_3E40C or off_3E42C
addq.b #1,d1
move.b d1,anim_frame(a0)
move.b (a1,d1.w),d0
move.b d0,d1
andi.b #$C0,d1
bne.s loc_3E23E
rts
; ===========================================================================
loc_3E27A:
moveq #1,d4
rts
; ===========================================================================
loc_3E27E:
addq.w #4,sp
bra.s loc_3E236
; ===========================================================================
loc_3E282:
movea.w objoff_2C(a0),a2 ; a2=object
move.w x_pos(a2),d0
move.w (a1)+,d1
btst #0,render_flags(a2)
beq.s +
neg.w d1
+
add.w d1,d0
move.w d0,x_pos(a0)
move.w y_pos(a2),d0
add.w (a1)+,d0
move.w d0,y_pos(a0)
rts
; ===========================================================================
;loc_3E2A8
ObjC7_PositionChildren:
moveq #0,d0
moveq #0,d6
move.b (a1)+,d6
- move.b (a1)+,d0
movea.w (a0,d0.w),a2 ; a2=object
move.w x_pos(a0),d1
move.b (a1)+,d2
ext.w d2
btst #0,render_flags(a0)
beq.s +
neg.w d2
+
add.w d2,d1
move.w d1,x_pos(a2)
move.w y_pos(a0),d1
move.b (a1)+,d2
ext.w d2
add.w d2,d1
move.w d1,y_pos(a2)
dbf d6,-
rts
; ===========================================================================
;byte_3E2E0
ObjC7_ChildDeltas:
dc.b 6
dc.b $2E ; 1
dc.b $FC ; 2
dc.b $3C ; 3
dc.b $30 ; 4
dc.b $F4 ; 5
dc.b 8 ; 6
dc.b $32 ; 7
dc.b $C ; 8
dc.b $F8 ; 9
dc.b $34 ; 10
dc.b 4 ; 11
dc.b $24 ; 12
dc.b $3A ; 13
dc.b $FC ; 14
dc.b $3C ; 15
dc.b $3C ; 16
dc.b $F4 ; 17
dc.b 8 ; 18
dc.b $3E ; 19
dc.b 4 ; 20
dc.b $24 ; 21
off_3E2F6:
dc.l ObjC7_GroupAni_3E318
dc.b 0, 1, 2, 3, $FF, 0
off_3E300:
dc.l ObjC7_GroupAni_3E318
dc.b 5, 6, 7, 8, $FF, 0
off_3E30A:
dc.l ObjC7_GroupAni_3E318
dc.b 0, 1, 2, 3, 4, 5, 6, 7, 8, $C0
; -----------------------------------------------------------------------------
; Custom animation
; -----------------------------------------------------------------------------
; must be on the same line as a label that has a corresponding _End label later
c7anilistheader macro maxframe,{INTLABEL}
__LABEL__ label *
dc.b ((__LABEL___End - __LABEL__ - 2) / 3) - 1,maxframe
endm
; macro for a animation data
c7ani macro pieceOffset,deltax,deltay
dc.b pieceOffset,deltax,deltay
endm
ObjC7_GroupAni_3E318: offsetTable ;BINCLUDE "mappings/sprite/objC7_a.bin"
offsetTableEntry.w byte_3E32A
offsetTableEntry.w byte_3E33E
offsetTableEntry.w byte_3E352
offsetTableEntry.w byte_3E366
offsetTableEntry.w byte_3E37A
offsetTableEntry.w byte_3E380
offsetTableEntry.w byte_3E394
offsetTableEntry.w byte_3E3A8
offsetTableEntry.w byte_3E3BC
byte_3E32A: c7anilistheader 8
c7ani $00, $E0, $0C
c7ani objoff_30, $E0, $0C
c7ani objoff_32, $E0, $0C
c7ani objoff_3C, $E0, $0C
c7ani objoff_34, $F8, $04
c7ani objoff_3E, $F8, $04
byte_3E32A_End
byte_3E33E: c7anilistheader 8
c7ani $00, $EC, $14
c7ani objoff_30, $EC, $14
c7ani objoff_32, $EC, $14
c7ani objoff_3C, $EC, $14
c7ani objoff_34, $FA, $06
c7ani objoff_3E, $FA, $06
byte_3E33E_End
byte_3E352: c7anilistheader 8
c7ani $00, $F8, $14
c7ani objoff_30, $F8, $14
c7ani objoff_32, $F8, $14
c7ani objoff_3C, $F8, $14
c7ani objoff_34, $FE, $04
c7ani objoff_3E, $FE, $04
byte_3E352_End
byte_3E366: c7anilistheader 8
c7ani $00, $FC, $0C
c7ani objoff_30, $FC, $0C
c7ani objoff_32, $FC, $0C
c7ani objoff_3C, $FC, $0c
c7ani objoff_34, $00, $02
c7ani objoff_3E, $00, $02
byte_3E366_End
byte_3E37A: c7anilistheader 8
c7ani $00, $00, $00
byte_3E37A_End
even
byte_3E380: c7anilistheader 8
c7ani $00, $04, $E8
c7ani objoff_30, $04, $E8
c7ani objoff_32, $04, $E8
c7ani objoff_3C, $04, $E8
c7ani objoff_34, $02, $FA
c7ani objoff_3E, $02, $FA
byte_3E380_End
byte_3E394: c7anilistheader 8
c7ani $00, $0C, $E8
c7ani objoff_30, $0C, $E8
c7ani objoff_32, $0C, $E8
c7ani objoff_3C, $0C, $E8
c7ani objoff_34, $04, $FC
c7ani objoff_3E, $04, $FC
byte_3E394_End
byte_3E3A8: c7anilistheader 8
c7ani $00, $18, $F4
c7ani objoff_30, $18, $F4
c7ani objoff_32, $18, $F4
c7ani objoff_3C, $18, $F4
c7ani objoff_34, $04, $FC
c7ani objoff_3E, $04, $FC
byte_3E3A8_End
byte_3E3BC: c7anilistheader 8
c7ani $00, $18, $FC
c7ani objoff_30, $18, $FC
c7ani objoff_32, $18, $FC
c7ani objoff_3C, $18, $FC
c7ani objoff_34, $06, $FE
c7ani objoff_3E, $06, $FE
byte_3E3BC_End
off_3E3D0:
dc.l ObjC7_GroupAni_3E3D8
dc.b 0, 1, 2, $C0
; -----------------------------------------------------------------------------
; Custom animation
; -----------------------------------------------------------------------------
ObjC7_GroupAni_3E3D8: offsetTable ;BINCLUDE "mappings/sprite/objC7_b.bin"
offsetTableEntry.w byte_3E3DE
offsetTableEntry.w byte_3E3F2
offsetTableEntry.w byte_3E3F8
byte_3E3DE: c7anilistheader $10
c7ani $00, $00, $04
c7ani objoff_30, $00, $04
c7ani objoff_32, $00, $04
c7ani objoff_3C, $00, $04
c7ani objoff_34, $00, $04
c7ani objoff_3E, $00, $04
byte_3E3DE_End
byte_3E3F2: c7anilistheader $10
c7ani $00, $00, $00
byte_3E3F2_End
even
byte_3E3F8: c7anilistheader 8
c7ani $00, $00, $F8
c7ani objoff_30, $00, $F8
c7ani objoff_32, $00, $F8
c7ani objoff_3C, $00, $F8
c7ani objoff_34, $00, $F8
c7ani objoff_3E, $00, $F8
byte_3E3F8_End
off_3E40C:
dc.l ObjC7_GroupAni_3E438
dc.b 0, 1, 2, 3, $40, SndID_Hammer
dc.b 4, 5, 6, 7, 8, $40, SndID_Hammer
dc.b 9, $A, 1, 2, 3, $40, SndID_Hammer
dc.b 4, 5, 6, 7, 8, $40, SndID_Hammer, $C0
off_3E42C:
dc.l ObjC7_GroupAni_3E438
dc.b $88, $87, $86, $85, $B, $40, SndID_Hammer, $C0
; -----------------------------------------------------------------------------
; Custom animation
; -----------------------------------------------------------------------------
ObjC7_GroupAni_3E438: offsetTable ;BINCLUDE "mappings/sprite/objC7_c.bin"
offsetTableEntry.w byte_3E450
offsetTableEntry.w byte_3E468
offsetTableEntry.w byte_3E480
offsetTableEntry.w byte_3E494
offsetTableEntry.w byte_3E4AC
offsetTableEntry.w byte_3E4C4
offsetTableEntry.w byte_3E4D6
offsetTableEntry.w byte_3E4EE
offsetTableEntry.w byte_3E502
offsetTableEntry.w byte_3E51A
offsetTableEntry.w byte_3E532
offsetTableEntry.w byte_3E544
byte_3E450: c7anilistheader $20
c7ani objoff_34, $F8, $F8
c7ani objoff_2E, $F8, $F8
c7ani $00, $00, $FC
c7ani objoff_30, $04, $FB
c7ani objoff_32, $03, $FB
c7ani objoff_3C, $FC, $FB
c7ani objoff_3E, $00, $FE
byte_3E450_End
even
byte_3E468: c7anilistheader $10
c7ani objoff_34, $F0, $FC
c7ani objoff_2E, $F0, $FC
c7ani $00, $F0, $FC
c7ani objoff_30, $F4, $FB
c7ani objoff_32, $F3, $FB
c7ani objoff_3C, $EC, $FB
c7ani objoff_3E, $F8, $00
byte_3E468_End
even
byte_3E480: c7anilistheader $10
c7ani objoff_34, $F8, $04
c7ani objoff_2E, $F8, $04
c7ani $00, $F8, $04
c7ani objoff_30, $FC, $03
c7ani objoff_32, $FB, $03
c7ani objoff_3C, $F4, $03
byte_3E480_End
byte_3E494: c7anilistheader $10
c7ani objoff_34, $FC, $10
c7ani objoff_2E, $F8, $10
c7ani $00, $00, $08
c7ani objoff_30, $F8, $0A
c7ani objoff_32, $FA, $0A
c7ani objoff_3C, $08, $0A
c7ani objoff_3E, $00, $08
byte_3E494_End
even
byte_3E4AC: c7anilistheader $20
c7ani objoff_34, $FE, $FE
c7ani $00, $F4, $FC
c7ani objoff_30, $F0, $FD
c7ani objoff_32, $F1, $FD
c7ani objoff_3C, $F8, $FD
c7ani objoff_3E, $EC, $FA
c7ani objoff_3A, $E8, $FC
byte_3E4AC_End
even
byte_3E4C4: c7anilistheader $20
c7ani objoff_3E, $F8, $FC
c7ani objoff_3A, $F8, $FC
c7ani objoff_30, $FC, $FF
c7ani objoff_32, $FD, $FF
c7ani objoff_3C, $04, $FF
byte_3E4C4_End
even
byte_3E4D6: c7anilistheader $10
c7ani objoff_3E, $F0, $FC
c7ani objoff_3A, $F0, $FC
c7ani $00, $F0, $FC
c7ani objoff_30, $EC, $FB
c7ani objoff_32, $ED, $FB
c7ani objoff_3C, $F4, $FB
c7ani objoff_34, $F8, $00
byte_3E4D6_End
even
byte_3E4EE: c7anilistheader $10
c7ani objoff_3E, $F8, $04
c7ani objoff_3A, $F8, $04
c7ani $00, $F8, $04
c7ani objoff_30, $F4, $03
c7ani objoff_32, $F5, $03
c7ani objoff_3C, $FC, $03
byte_3E4EE_End
byte_3E502: c7anilistheader $10
c7ani objoff_3E, $FC, $10
c7ani objoff_3A, $F8, $10
c7ani $00, $00, $08
c7ani objoff_30, $08, $0A
c7ani objoff_32, $06, $0A
c7ani objoff_3C, $F8, $0A
c7ani objoff_34, $00, $08
byte_3E502_End
even
byte_3E51A: c7anilistheader $20
c7ani objoff_3E, $FE, $FE
c7ani $00, $F4, $FC
c7ani objoff_30, $F8, $FD
c7ani objoff_32, $F7, $FD
c7ani objoff_3C, $F1, $FD
c7ani objoff_34, $EC, $FA
c7ani objoff_2E, $E8, $FC
byte_3E51A_End
even
byte_3E532: c7anilistheader $20
c7ani objoff_34, $F8, $FC
c7ani objoff_2E, $F8, $FC
c7ani objoff_30, $04, $FF
c7ani objoff_32, $03, $FF
c7ani objoff_3C, $FC, $FF
byte_3E532_End
even
byte_3E544: c7anilistheader $10
c7ani objoff_3E, $00, $08
c7ani objoff_3A, $00, $08
c7ani $00, $00, $08
c7ani objoff_30, $00, $08
c7ani objoff_32, $00, $08
c7ani objoff_3C, $00, $08
c7ani objoff_34, $00, $08
byte_3E544_End
even
;word_3E55C
ChildObjC7_Shoulder:
dc.w objoff_2C
dc.b ObjID_Eggrobo
dc.b 4
;word_3E560
ChildObjC7_FrontLowerLeg:
dc.w objoff_2E
dc.b ObjID_Eggrobo
dc.b 6
;word_3E564
ChildObjC7_FrontForearm:
dc.w objoff_30
dc.b ObjID_Eggrobo
dc.b 8
;word_3E568
ChildObjC7_Arm:
dc.w objoff_32
dc.b ObjID_Eggrobo
dc.b $A
;word_3E56C
ChildObjC7_FrontThigh:
dc.w objoff_34
dc.b ObjID_Eggrobo
dc.b $C
;word_3E570
ChildObjC7_Head:
dc.w objoff_36
dc.b ObjID_Eggrobo
dc.b $E
;word_3E574
ChildObjC7_Jet:
dc.w objoff_38
dc.b ObjID_Eggrobo
dc.b $10
;word_3E578
ChildObjC7_BackLowerLeg:
dc.w objoff_3A
dc.b ObjID_Eggrobo
dc.b $12
;word_3E57C
ChildObjC7_BackForearm:
dc.w objoff_3C
dc.b ObjID_Eggrobo
dc.b $14
;word_3E580
ChildObjC7_BackThigh:
dc.w objoff_3E
dc.b ObjID_Eggrobo
dc.b $16
;word_3E584
ChildObjC7_TargettingSensor:
dc.w objoff_10
dc.b ObjID_Eggrobo
dc.b $18
;word_3E588
ChildObjC7_TargettingLock:
dc.w objoff_10
dc.b ObjID_Eggrobo
dc.b $1A
;word_3E58C
ChildObjC7_EggmanBomb:
dc.w objoff_10
dc.b ObjID_Eggrobo
dc.b $1C
;off_3E590
ObjC7_SubObjData:
subObjData ObjC7_MapUnc_3E5F8,make_art_tile(ArtTile_ArtNem_DEZBoss,0,0),4,4,$38,$00
; animation script
; off_3E59A:
Ani_objC7_a: offsetTable
offsetTableEntry.w +
+ dc.b 7,$15,$15,$15,$15,$15,$15,$15,$15, 0, 1, 2,$FA
even
; animation script
; off_3E5AA:
Ani_objC7_b: offsetTable
offsetTableEntry.w byte_3E5B2
offsetTableEntry.w byte_3E5B6
offsetTableEntry.w byte_3E5D0
offsetTableEntry.w byte_3E5EA
byte_3E5B2: dc.b 1, $C, $D,$FF
byte_3E5B6: dc.b 1, $C, $D, $C, $C, $D, $D, $C, $C, $C, $D, $D, $D, $C, $C, $C
dc.b $C, $C, $D, $D, $D, $D, $D, $D,$FA, 0; 16
byte_3E5D0: dc.b 1, $D, $D, $D, $D, $D, $D, $C, $C, $C, $C, $C, $D, $D, $D, $C
dc.b $C, $C, $D, $D, $C, $C, $D, $C,$FD, 0; 16
byte_3E5EA: dc.b 0, $D,$15,$FF
even
; animation script
; off_3E5EE:
Ani_objC7_c: offsetTable
offsetTableEntry.w byte_3E5F0
byte_3E5F0: dc.b 3,$13,$12,$11,$10,$16,$FF
even
; ------------------------------------------------------------------------------
; sprite mappings
; ------------------------------------------------------------------------------
ObjC7_MapUnc_3E5F8: BINCLUDE "mappings/sprite/objC7.bin"
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to upscale graphics by a factor of 2x, based on given mappings
; data for correct positioning of tiles.
;
; This code is awfully structured and planned: whenever a 3-column sprite piece
; is scaled, it scales the next tiles that were copied to RAM as if the piece
; had 4 columns; this will then be promptly overwritten by the next piece. If
; this happens near the end of the buffer, you will get a buffer overrun.
; Moreover, when the number of rows in the sprite piece is also 3 or 4, the code
; will make an incorrect computation for the output of the next subpiece, which
; causes the output to overwrite art from the previous subpiece. Thus, this code
; fails if there is a 3x3 or a 3x4 sprite piece in the source mappings. Sadly,
; this issue is basically unfixable without rewriting the code entirely.
;
; Input:
; a1 Location of tiles to be enlarged
; a2 Destination buffer for enlarged tiles
; d0 Width-1 of sprite piece
; d1 Height-1 of sprite piece
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
;loc_3E89E
Scale_2x:
move.w d1,d2 ; Copy piece height-1
andi.w #1,d2 ; Want only low bit -- this is 1 for Wx2 or Wx4 pieces, 0 otherwise
addq.w #1,d2 ; Make it into 2 for Wx2 or Wx4 pieces, 1 otherwise
lsl.w #6,d2 ; This is now $80 (4 tiles) for Wx2 or Wx4 pieces, $40 (2 tiles) otherwise
swap d2 ; Save it to high word
move.w d1,d3 ; Copy piece height-1 again
lsr.w #1,d3 ; This time, want high bit (1 for Wx3 or Wx4, 0 for Wx2 or Wx1)
addq.w #1,d3 ; Make it into 2 for Wx3 or Wx4 pieces, 1 otherwise
lsl.w #6,d3 ; This is now $80 (4 tiles) for Wx3 or Wx4 pieces, $40 (2 tiles) otherwise
swap d3 ; Save it to high word
bsr.w .upscale_part1 ; Scale the first line???; sets a3 = ???, a5 = ???
btst #1,d0 ; Is this a 1xH or a 2xH piece?
beq.w return_37A48 ; Return if yes
btst #1,d1 ; Is this a Wx3 or a Wx4 piece?
bne.s .set_dest ; Branch if yes
movea.l a3,a5 ; Advance to next column instead
.set_dest:
movea.l a5,a2 ; Set new output location
.upscale_part1:
movea.l a2,a4 ; Copy destination to a4
swap d2 ; Get height offset
lea (a2,d2.w),a3 ; Output location for next tile
swap d2 ; Save height offset again
move.w d1,d5 ; Copy height-1
andi.w #1,d5 ; How many tiles we want to do-1 -- this is 1 for Wx2 or Wx4 pieces, 0 otherwise
bsr.w Scale2x_SingleTile
btst #1,d1 ; Are we upscaling a Wx3 or Wx4 piece?
beq.s .done_cols ; Branch if not
swap d2 ; Get height offset
move.w d2,d4 ; Copy it to d4
swap d2 ; Save height offset again
add.w d4,d4 ; This is now $100 (8 tiles) for Wx4 pieces, $80 (4 tiles) for Wx3 pieces
move.w d0,d3 ; Copy piece width-1
andi.w #1,d3 ; Want only low bit -- this is 1 for 2xH or 4xH pieces, 0 otherwise
lsl.w d3,d4 ; This is now: $200 (16 tiles) for 2x4 or 4x4 pieces; $100 (8 tiles) for 2x3, 4x3, 1x4 or 3x4 pieces; $80 (4 tiles) for 1x3 or 3x3 pieces
adda.w d4,a4 ; Advance to this location
move.w d1,d5 ; Copy height-1
lsr.w #1,d5 ; How many tiles we want to do-1 -- this is 1 for Wx4 pieces, 0 for Wx3 pieces
swap d3 ; Get height offset
lea (a4,d3.w),a5 ; Output location for next tile
swap d3 ; Save height offset again
bsr.w Scale2x_SingleTile2
.done_cols:
btst #0,d0 ; Is this a 1xH or 3xH piece?
bne.s .keep_upscaling ; Branch if not
btst #1,d0 ; Was this a single column piece?
beq.s .done ; Return if so
.keep_upscaling:
swap d2 ; Get height offset
lea (a2,d2.w),a2 ; Output location for next tile
lea (a2,d2.w),a3 ; Output location for next tile
swap d2 ; Save height offset again
move.w d1,d5 ; Copy height-1
andi.w #1,d5 ; How many tiles we want to do -- this is 1 for Wx2 or Wx4 pieces, 0 otherwise
bsr.w Scale2x_SingleTile
btst #1,d1 ; Are we upscaling a Wx3 or Wx4 piece?
beq.s .done ; Branch if not
move.w d1,d5 ; Copy height-1
lsr.w #1,d5 ; How many tiles we want to do-1 -- this is 1 for Wx4 or Wx3 pieces, 0 otherwise
swap d3 ; Get height offset
lea (a4,d3.w),a4 ; Output location for next tile
lea (a4,d3.w),a5 ; Output location for next tile
swap d3 ; Save height offset again
bsr.w Scale2x_SingleTile2
.done:
rts
; ===========================================================================
; Upscales the given tile to the pair of tiles on the output pointers.
;
; Input:
; a1 Pixel source
; d5 Number of tiles-1 to upscale
; a2 Location of output tiles for left pixels
; a3 Location of output tiles for right pixels
; Output:
; a1 Pixel source after processed tiles
; a2 Location of output tiles for left pixels after scaled tiles
; a3 Location of output tiles for right pixels after scaled tiles
;loc_3E944
Scale2x_SingleTile:
moveq #7,d6 ; 8 rows per tile
.loop:
bsr.w Scale_2x_LeftPixels ; Upscale pixels 0-3 of current row
addq.w #4,a2 ; Advance write destination by one row (8 pixels)
bsr.w Scale_2x_RightPixels ; Upscale pixels 4-7 of current row
addq.w #4,a3 ; Advance write destination by one row (8 pixels)
dbf d6,.loop
dbf d5,Scale2x_SingleTile
rts
; ===========================================================================
; Upscales the given tile to the pair of tiles on the output pointers.
;
; Input:
; a1 Pixel source
; d5 Number of tiles-1 to upscale
; a4 Location of output tiles for left pixels
; a5 Location of output tiles for right pixels
; Output:
; a1 Pixel source after processed tiles
; a4 Location of output tiles for left pixels after scaled tiles
; a5 Location of output tiles for right pixels after scaled tiles
;loc_3E95C
Scale2x_SingleTile2:
moveq #7,d6 ; 8 rows per tile
.loop:
bsr.w Scale_2x_LeftPixels2 ; Upscale pixels 0-3 of current row
addq.w #4,a4 ; Advance write destination by one row (8 pixels)
bsr.w Scale_2x_RightPixels2 ; Upscale pixels 4-7 of current row
addq.w #4,a5 ; Advance write destination by one row (8 pixels)
dbf d6,.loop
dbf d5,Scale2x_SingleTile2
rts
; ===========================================================================
; Upscales the leftmost 4 pixels on the current row into the corresponding two
; rows of the output tile
;loc_3E974
Scale_2x_LeftPixels:
bsr.w .upscale_pixel_pair
.upscale_pixel_pair:
move.b (a1)+,d2 ; Read two pixels
move.b d2,d3 ; Save them
andi.b #$F0,d2 ; Get left pixel
move.b d2,d4 ; Copy it...
lsr.b #4,d4 ; ... shift it down into place...
or.b d2,d4 ; ... and make it into two pixels of the same color
move.b d4,(a2)+ ; Save to top tile, both on one row...
move.b d4,3(a2) ; ... and on the row below
andi.b #$F,d3 ; Get saved right pixel
move.b d3,d4 ; Copy it...
lsl.b #4,d4 ; ... shift it up into place...
or.b d3,d4 ; ... and make it into two pixels of the same color
move.b d4,(a2)+ ; Save to top tile, both on one row...
move.b d4,3(a2) ; ... and on the row below
rts
; ===========================================================================
; Upscales the rightmost 4 pixels on the current row into the corresponding two
; rows of the output tile
;loc_3E99E
Scale_2x_RightPixels:
bsr.w .upscale_pixel_pair
.upscale_pixel_pair:
move.b (a1)+,d2 ; Read two pixels
move.b d2,d3 ; Save them
andi.b #$F0,d2 ; Get left pixel
move.b d2,d4 ; Copy it...
lsr.b #4,d4 ; ... shift it down into place...
or.b d2,d4 ; ... and make it into two pixels of the same color
move.b d4,(a3)+ ; Save to bottom tile, both on one row...
move.b d4,3(a3) ; ... and on the row below
andi.b #$F,d3 ; Get saved right pixel
move.b d3,d4 ; Copy it...
lsl.b #4,d4 ; ... shift it up into place...
or.b d3,d4 ; ... and make it into two pixels of the same color
move.b d4,(a3)+ ; Save to bottom tile, both on one row...
move.b d4,3(a3) ; ... and on the row below
rts
; ===========================================================================
; Upscales the leftmost 4 pixels on the current row into the corresponding two
; rows of the output tile
;loc_3E9C8
Scale_2x_LeftPixels2:
bsr.w .upscale_pixel_pair
.upscale_pixel_pair:
move.b (a1)+,d2 ; Read two pixels
move.b d2,d3 ; Save them
andi.b #$F0,d2 ; Get left pixel
move.b d2,d4 ; Copy it...
lsr.b #4,d4 ; ... shift it down into place...
or.b d2,d4 ; ... and make it into two pixels of the same color
move.b d4,(a4)+ ; Save to top tile, both on one row...
move.b d4,3(a4) ; ... and on the row below
andi.b #$F,d3 ; Get saved right pixel
move.b d3,d4 ; Copy it...
lsl.b #4,d4 ; ... shift it up into place...
or.b d3,d4 ; ... and make it into two pixels of the same color
move.b d4,(a4)+ ; Save to top tile, both on one row...
move.b d4,3(a4) ; ... and on the row below
rts
; ===========================================================================
; Upscales the rightmost 4 pixels on the current row into the corresponding two
; rows of the output tile
;loc_3E9F2
Scale_2x_RightPixels2:
bsr.w .upscale_pixel_pair
.upscale_pixel_pair:
move.b (a1)+,d2 ; Read two pixels
move.b d2,d3 ; Save them
andi.b #$F0,d2 ; Get left pixel
move.b d2,d4 ; Copy it...
lsr.b #4,d4 ; ... shift it down into place...
or.b d2,d4 ; ... and make it into two pixels of the same color
move.b d4,(a5)+ ; Save to bottom tile, both on one row...
move.b d4,3(a5) ; ... and on the row below
andi.b #$F,d3 ; Get saved right pixel
move.b d3,d4 ; Copy it...
lsl.b #4,d4 ; ... shift it up into place...
or.b d3,d4 ; ... and make it into two pixels of the same color
move.b d4,(a5)+ ; Save to bottom tile, both on one row...
move.b d4,3(a5) ; ... and on the row below
rts
; ===========================================================================
; this data seems to be unused
dc.b $12,$34,$56,$78
dc.b $12,$34,$56,$78 ; 4
dc.b $12,$34,$56,$78 ; 8
dc.b $12,$34,$56,$78 ; 12
dc.b $12,$34,$56,$78 ; 16
dc.b $12,$34,$56,$78 ; 20
dc.b $12,$34,$56,$78 ; 24
dc.b $12,$34,$56,$78 ; 28
; ===========================================================================
if ~~removeJmpTos
JmpTo5_DisplaySprite3
jmp (DisplaySprite3).l
JmpTo45_DisplaySprite
jmp (DisplaySprite).l
JmpTo65_DeleteObject
jmp (DeleteObject).l
JmpTo19_SingleObjLoad
jmp (SingleObjLoad).l
JmpTo39_MarkObjGone
jmp (MarkObjGone).l
JmpTo6_DeleteObject2
jmp (DeleteObject2).l
JmpTo12_PlaySound
jmp (PlaySound).l
JmpTo25_SingleObjLoad2
jmp (SingleObjLoad2).l
JmpTo25_AnimateSprite
jmp (AnimateSprite).l
JmpTo_PlaySoundLocal
jmp (PlaySoundLocal).l
JmpTo6_RandomNumber
jmp (RandomNumber).l
JmpTo2_MarkObjGone_P1
jmp (MarkObjGone_P1).l
JmpTo_Pal_FadeToWhite_UpdateColour
jmp (Pal_FadeToWhite.UpdateColour).l
JmpTo_LoadTailsDynPLC_Part2
jmp (LoadTailsDynPLC_Part2).l
JmpTo_LoadSonicDynPLC_Part2
jmp (LoadSonicDynPLC_Part2).l
JmpTo8_MarkObjGone3
jmp (MarkObjGone3).l
JmpTo64_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
JmpTo5_PlayMusic
jmp (PlayMusic).l
JmpTo_Boss_LoadExplosion
jmp (Boss_LoadExplosion).l
JmpTo9_PlatformObject
jmp (PlatformObject).l
JmpTo27_SolidObject
jmp (SolidObject).l
JmpTo8_ObjectMoveAndFall
jmp (ObjectMoveAndFall).l
; loc_3EAC0:
JmpTo26_ObjectMove
jmp (ObjectMove).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 8A - Sonic Team Presents/Credits (leftover from S1) (seemingly unused)
; ----------------------------------------------------------------------------
; Sprite_3EAC8:
Obj8A: ; (screen-space obj)
moveq #0,d0
move.b routine(a0),d0
move.w Obj8A_Index(pc,d0.w),d1
jmp Obj8A_Index(pc,d1.w)
; ===========================================================================
; off_3EAD6:
Obj8A_Index: offsetTable
offsetTableEntry.w Obj8A_Init
offsetTableEntry.w Obj8A_Display
; ===========================================================================
; loc_3EADA:
Obj8A_Init:
addq.b #2,routine(a0)
move.w #$120,x_pixel(a0)
move.w #$F0,y_pixel(a0)
move.l #Obj8A_MapUnc_3EB4E,mappings(a0)
move.w #make_art_tile($05A0,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo65_Adjust2PArtPointer
move.w (Ending_demo_number).w,d0
move.b d0,mapping_frame(a0)
move.b #0,render_flags(a0)
move.b #0,priority(a0)
cmpi.b #GameModeID_TitleScreen,(Game_Mode).w ; title screen??
bne.s Obj8A_Display ; if not, branch
move.w #make_art_tile($0300,0,0),art_tile(a0)
jsrto (Adjust2PArtPointer).l, JmpTo65_Adjust2PArtPointer
move.b #$A,mapping_frame(a0)
tst.b ($FFFFFFD3).w
beq.s Obj8A_Display
cmpi.b #button_down_mask|button_B_mask|button_C_mask|button_A_mask,(Ctrl_1_Held).w
bne.s Obj8A_Display
move.w #$EEE,(Target_palette_line3).w
move.w #$880,(Target_palette_line3+2).w
jmp (DeleteObject).l
; ===========================================================================
; JmpTo46_DisplaySprite
Obj8A_Display:
jmp (DisplaySprite).l
; ===========================================================================
; ----------------------------------------------------------------------------
; sprite mappings (unused?)
; ----------------------------------------------------------------------------
Obj8A_MapUnc_3EB4E: BINCLUDE "mappings/sprite/obj8A.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo65_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ===========================================================================
; ----------------------------------------------------------------------------
; Object 3E - Egg prison
; ----------------------------------------------------------------------------
; Sprite_3F1E4:
Obj3E:
moveq #0,d0
move.b routine(a0),d0
move.w Obj3E_Index(pc,d0.w),d1
jmp Obj3E_Index(pc,d1.w)
; ===========================================================================
; off_3F1F2:
Obj3E_Index: offsetTable
offsetTableEntry.w loc_3F212 ; 0
offsetTableEntry.w loc_3F278 ; 2
offsetTableEntry.w loc_3F354 ; 4
offsetTableEntry.w loc_3F38E ; 6
offsetTableEntry.w loc_3F3A8 ; 8
offsetTableEntry.w loc_3F406 ; $A
; ----------------------------------------------------------------------------
; byte_3F1FE:
Obj3E_ObjLoadData:
dc.b 0, 2,$20, 4, 0
dc.b $28, 4,$10, 5, 4 ; 5
dc.b $18, 6, 8, 3, 5 ; 10
dc.b 0, 8,$20, 4, 0 ; 15
; ===========================================================================
loc_3F212:
movea.l a0,a1
lea objoff_38(a0),a3
lea Obj3E_ObjLoadData(pc),a2
moveq #3,d1
bra.s loc_3F228
; ===========================================================================
loc_3F220:
jsrto (SingleObjLoad).l, JmpTo20_SingleObjLoad
bne.s loc_3F272
move.w a1,(a3)+
loc_3F228:
_move.b id(a0),id(a1) ; load obj
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w y_pos(a0),objoff_30(a1)
move.l #Obj3E_MapUnc_3F436,mappings(a1)
move.w #make_art_tile(ArtTile_ArtNem_Capsule,1,0),art_tile(a1)
move.b #$84,render_flags(a1)
moveq #0,d0
move.b (a2)+,d0
sub.w d0,y_pos(a1)
move.w y_pos(a1),objoff_30(a1)
move.b (a2)+,routine(a1)
move.b (a2)+,width_pixels(a1)
move.b (a2)+,priority(a1)
move.b (a2)+,mapping_frame(a1)
loc_3F272:
dbf d1,loc_3F220
rts
; ===========================================================================
loc_3F278:
moveq #0,d0
move.b routine_secondary(a0),d0
move.w off_3F2AE(pc,d0.w),d1
jsr off_3F2AE(pc,d1.w)
move.w #$2B,d1
move.w #$18,d2
move.w #$18,d3
move.w x_pos(a0),d4
jsr (SolidObject).l
lea (Ani_obj3E).l,a1
jsr (AnimateSprite).l
jmp (MarkObjGone).l
; ===========================================================================
off_3F2AE: offsetTable
offsetTableEntry.w loc_3F2B4 ; 0
offsetTableEntry.w loc_3F2FC ; 2
offsetTableEntry.w return_3F352 ; 4
; ===========================================================================
loc_3F2B4:
movea.w objoff_38(a0),a1 ; a1=object
tst.w objoff_32(a1)
beq.s ++ ; rts
movea.w objoff_3A(a0),a2 ; a2=object
jsr (SingleObjLoad).l
bne.s +
_move.b #ObjID_Explosion,id(a1) ; load obj
addq.b #2,routine(a1)
move.w x_pos(a2),x_pos(a1)
move.w y_pos(a2),y_pos(a1)
+
move.w #-$400,y_vel(a2)
move.w #$800,x_vel(a2)
addq.b #2,routine_secondary(a2)
move.w #$1D,objoff_34(a0)
addq.b #2,routine_secondary(a0)
+
rts
; ===========================================================================
loc_3F2FC:
subq.w #1,objoff_34(a0)
bpl.s return_3F352
move.b #1,anim(a0)
moveq #7,d6
move.w #$9A,d5
moveq #-$1C,d4
- jsr (SingleObjLoad).l
bne.s +
_move.b #ObjID_Animal,id(a1) ; load obj
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
add.w d4,x_pos(a1)
move.b #1,objoff_38(a1)
addq.w #7,d4
move.w d5,objoff_36(a1)
subq.w #8,d5
dbf d6,-
+
movea.w objoff_3C(a0),a2 ; a2=object
move.w #$B4,anim_frame_duration(a2)
addq.b #2,routine_secondary(a2)
addq.b #2,routine_secondary(a0)
return_3F352:
rts
; ===========================================================================
loc_3F354:
move.w #$1B,d1
move.w #8,d2
move.w #8,d3
move.w x_pos(a0),d4
jsr (SolidObject).l
move.w objoff_30(a0),y_pos(a0)
move.b status(a0),d0
andi.b #standing_mask,d0
beq.s +
addq.w #8,y_pos(a0)
clr.b (Update_HUD_timer).w
move.w #1,objoff_32(a0)
+
jmp (MarkObjGone).l
; ===========================================================================
loc_3F38E:
tst.b routine_secondary(a0)
beq.s +
tst.b render_flags(a0)
bpl.w JmpTo66_DeleteObject
jsr (ObjectMoveAndFall).l
+
jmp (MarkObjGone).l
if removeJmpTos
JmpTo66_DeleteObject
jmp (DeleteObject).l
endif
; ===========================================================================
loc_3F3A8:
tst.b routine_secondary(a0)
beq.s return_3F404
move.b (Vint_runcount+3).w,d0
andi.b #7,d0
bne.s loc_3F3F4
jsr (SingleObjLoad).l
bne.s loc_3F3F4
_move.b #ObjID_Animal,id(a1) ; load obj
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
jsr (RandomNumber).l
andi.w #$1F,d0
subq.w #6,d0
tst.w d1
bpl.s +
neg.w d0
+
add.w d0,x_pos(a1)
move.b #1,objoff_38(a1)
move.w #$C,objoff_36(a1)
loc_3F3F4:
subq.w #1,anim_frame_duration(a0)
bne.s return_3F404
addq.b #2,routine(a0)
move.w #$B4,anim_frame_duration(a0)
return_3F404:
rts
; ===========================================================================
loc_3F406:
moveq #(Dynamic_Object_RAM_End-Dynamic_Object_RAM)/object_size-1,d0
moveq #ObjID_Animal,d1
lea (Dynamic_Object_RAM).w,a1
- cmp.b id(a1),d1
beq.s + ; rts
lea next_object(a1),a1 ; a1=object
dbf d0,-
jsr (Load_EndOfAct).l
jmp (DeleteObject).l
; ===========================================================================
+ rts
; ===========================================================================
; animation script
; off_3F428:
Ani_obj3E: offsetTable
offsetTableEntry.w byte_3F42C ; 0
offsetTableEntry.w byte_3F42F ; 1
byte_3F42C: dc.b $F, 0,$FF
rev02even
byte_3F42F: dc.b 3, 0, 1, 2, 3,$FE, 1
even
; ----------------------------------------------------------------------------
; sprite mappings
; ----------------------------------------------------------------------------
Obj3E_MapUnc_3F436: BINCLUDE "mappings/sprite/obj3E.bin"
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo66_DeleteObject
jmp (DeleteObject).l
JmpTo20_SingleObjLoad
jmp (SingleObjLoad).l
align 4
endif
; ---------------------------------------------------------------------------
; Object touch response subroutine - $20(a0) in the object RAM
; collides Sonic with most objects (enemies, rings, monitors...) in the level
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_3F554:
TouchResponse:
nop
jsrto (Touch_Rings).l, JmpTo_Touch_Rings
; Bumpers in CNZ
cmpi.b #casino_night_zone,(Current_Zone).w
bne.s +
jsrto (Check_CNZ_bumpers).l, JmpTo_Check_CNZ_bumpers
+
tst.b (Current_Boss_ID).w
bne.w Touch_Boss
move.w x_pos(a0),d2 ; load Sonic's position into d2,d3
move.w y_pos(a0),d3
subi_.w #8,d2
moveq #0,d5
move.b y_radius(a0),d5
subq.b #3,d5
sub.w d5,d3
cmpi.b #$4D,mapping_frame(a0) ; is Sonic ducking?
bne.s Touch_NoDuck ; if not, branch
addi.w #$C,d3
moveq #$A,d5
; loc_3F592:
Touch_NoDuck:
move.w #$10,d4
add.w d5,d5
lea (Dynamic_Object_RAM).w,a1
move.w #(Dynamic_Object_RAM_End-Dynamic_Object_RAM)/object_size-1,d6
; loc_3F5A0:
Touch_Loop:
move.b collision_flags(a1),d0
bne.w Touch_Width
; loc_3F5A8:
Touch_NextObj:
lea next_object(a1),a1 ; load obj address ; goto next object
dbf d6,Touch_Loop ; repeat 6F more times
moveq #0,d0
rts
; ===========================================================================
; loc_3F5B4: Touch_Height:
Touch_Width:
andi.w #$3F,d0
add.w d0,d0
lea Touch_Sizes(pc,d0.w),a2
moveq #0,d1
move.b (a2)+,d1
move.w x_pos(a1),d0
sub.w d1,d0
sub.w d2,d0
bcc.s loc_3F5D6
add.w d1,d1
add.w d1,d0
bcs.s Touch_Height
bra.w Touch_NextObj
; ===========================================================================
loc_3F5D6:
cmp.w d4,d0
bhi.w Touch_NextObj
; loc_3F5DC: Touch_Width:
Touch_Height:
moveq #0,d1
move.b (a2)+,d1
move.w y_pos(a1),d0
sub.w d1,d0
sub.w d3,d0
bcc.s loc_3F5F6
add.w d1,d1
add.w d1,d0
bcs.w Touch_ChkValue
bra.w Touch_NextObj
; ===========================================================================
loc_3F5F6:
cmp.w d5,d0
bhi.w Touch_NextObj
bra.w Touch_ChkValue
; ===========================================================================
; collision sizes (width,height)
; byte_3F600:
Touch_Sizes:
dc.b 4, 4 ; 0
dc.b $14,$14 ; 1
dc.b $C,$14 ; 2
dc.b $14, $C ; 3
dc.b 4,$10 ; 4
dc.b $C,$12 ; 5
dc.b $10,$10 ; 6 - monitors
dc.b 6, 6 ; 7 - rings
dc.b $18, $C ; 8
dc.b $C,$10 ; 9
dc.b $10, 8 ; $A
dc.b 8, 8 ; $B
dc.b $14,$10 ; $C
dc.b $14, 8 ; $D
dc.b $E, $E ; $E
dc.b $18,$18 ; $F
dc.b $28,$10 ; $10
dc.b $10,$18 ; $11
dc.b 8,$10 ; $12
dc.b $20,$70 ; $13
dc.b $40,$20 ; $14
dc.b $80,$20 ; $15
dc.b $20,$20 ; $16
dc.b 8, 8 ; $17
dc.b 4, 4 ; $18
dc.b $20, 8 ; $19
dc.b $C, $C ; $1A
dc.b 8, 4 ; $1B
dc.b $18, 4 ; $1C
dc.b $28, 4 ; $1D
dc.b 4, 8 ; $1E
dc.b 4,$18 ; $1F
dc.b 4,$28 ; $20
dc.b 4,$10 ; $21
dc.b $18,$18 ; $22
dc.b $C,$18 ; $23
dc.b $48, 8 ; $24
dc.b $18,$28 ; $25
dc.b $10, 4 ; $26
dc.b $20, 2 ; $27
dc.b 4,$40 ; $28
dc.b $18,$80 ; $29
dc.b $20,$10 ; $2A
dc.b $10,$20 ; $2B
dc.b $10,$30 ; $2C
dc.b $10,$40 ; $2D
dc.b $10,$50 ; $2E
dc.b $10, 2 ; $2F
dc.b $10, 1 ; $30
dc.b 2, 8 ; $31
dc.b $20,$1C ; $32
; ===========================================================================
; loc_3F666:
Touch_Boss:
lea Touch_Sizes(pc),a3
move.w x_pos(a0),d2
move.w y_pos(a0),d3
subi_.w #8,d2
moveq #0,d5
move.b y_radius(a0),d5
subq.b #3,d5
sub.w d5,d3
cmpi.b #$4D,mapping_frame(a0)
bne.s +
addi.w #$C,d3
moveq #$A,d5
+
move.w #$10,d4
add.w d5,d5
lea (Dynamic_Object_RAM).w,a1
move.w #(Dynamic_Object_RAM_End-Dynamic_Object_RAM)/object_size-1,d6
loc_3F69C:
move.b collision_flags(a1),d0
bne.s loc_3F6AE
loc_3F6A2:
lea next_object(a1),a1 ; a1=object
dbf d6,loc_3F69C
moveq #0,d0
rts
; ===========================================================================
loc_3F6AE:
bsr.w BossSpecificCollision
andi.w #$3F,d0
beq.s loc_3F6A2
add.w d0,d0
lea (a3,d0.w),a2
moveq #0,d1
move.b (a2)+,d1
move.w x_pos(a1),d0
sub.w d1,d0
sub.w d2,d0
bcc.s loc_3F6D4
add.w d1,d1
add.w d1,d0
bcs.s loc_3F6D8
bra.s loc_3F6A2
; ===========================================================================
loc_3F6D4:
cmp.w d4,d0
bhi.s loc_3F6A2
loc_3F6D8:
moveq #0,d1
move.b (a2)+,d1
move.w y_pos(a1),d0
sub.w d1,d0
sub.w d3,d0
bcc.s loc_3F6EE
add.w d1,d1
add.w d1,d0
bcs.s Touch_ChkValue
bra.s loc_3F6A2
; ===========================================================================
loc_3F6EE:
cmp.w d5,d0
bhi.s loc_3F6A2
; loc_3F6F2:
Touch_ChkValue:
move.b collision_flags(a1),d1 ; load touch response number
andi.b #$C0,d1 ; is touch response $40 or higher?
beq.w Touch_Enemy ; if not, branch
cmpi.b #$C0,d1 ; is touch response $C0 or higher?
beq.w Touch_Special ; if yes, branch
tst.b d1 ; is touch response $80-$BF ?
bmi.w Touch_ChkHurt ; if yes, branch
; touch response is $40-$7F
move.b collision_flags(a1),d0
andi.b #$3F,d0
cmpi.b #6,d0 ; is touch response $46 ?
beq.s Touch_Monitor ; if yes, branch
move.w (MainCharacter+invulnerable_time).w,d0
tst.w (Two_player_mode).w
beq.s +
move.w invulnerable_time(a0),d0
+
cmpi.w #90,d0
bhs.w +
move.b #4,routine(a1) ; set the object's routine counter
move.w a0,parent(a1)
+
rts
; ===========================================================================
; loc_3F73C:
Touch_Monitor:
tst.w y_vel(a0) ; is Sonic moving upwards?
bpl.s loc_3F768 ; if not, branch
move.w y_pos(a0),d0
subi.w #$10,d0
cmp.w y_pos(a1),d0
blo.s return_3F78A
neg.w y_vel(a0) ; reverse Sonic's y-motion
move.w #-$180,y_vel(a1)
tst.b routine_secondary(a1)
bne.s return_3F78A
move.b #4,routine_secondary(a1) ; set the monitor's routine counter
rts
; ===========================================================================
loc_3F768:
cmpa.w #MainCharacter,a0
beq.s +
tst.w (Two_player_mode).w
beq.s return_3F78A
+
cmpi.b #AniIDSonAni_Roll,anim(a0)
bne.s return_3F78A
neg.w y_vel(a0) ; reverse Sonic's y-motion
move.b #4,routine(a1)
move.w a0,parent(a1)
return_3F78A:
rts
; ===========================================================================
; loc_3F78C:
Touch_Enemy:
btst #status_sec_isInvincible,status_secondary(a0) ; is Sonic invincible?
bne.s + ; if yes, branch
cmpi.b #AniIDSonAni_Spindash,anim(a0)
beq.s +
cmpi.b #AniIDSonAni_Roll,anim(a0) ; is Sonic rolling?
bne.w Touch_ChkHurt ; if not, branch
+
btst #6,render_flags(a1)
beq.s Touch_Enemy_Part2
tst.b boss_hitcount2(a1)
beq.s return_3F7C6
neg.w x_vel(a0)
neg.w y_vel(a0)
move.b #0,collision_flags(a1)
subq.b #1,boss_hitcount2(a1)
return_3F7C6:
rts
; ---------------------------------------------------------------------------
; loc_3F7C8:
Touch_Enemy_Part2:
tst.b collision_property(a1)
beq.s Touch_KillEnemy
neg.w x_vel(a0)
neg.w y_vel(a0)
move.b #0,collision_flags(a1)
subq.b #1,collision_property(a1)
bne.s return_3F7E8
bset #7,status(a1)
return_3F7E8:
rts
; ===========================================================================
; loc_3F7EA:
Touch_KillEnemy:
bset #7,status(a1)
moveq #0,d0
move.w (Chain_Bonus_counter).w,d0
addq.w #2,(Chain_Bonus_counter).w ; add 2 to chain bonus counter
cmpi.w #6,d0
blo.s loc_3F802
moveq #6,d0
loc_3F802:
move.w d0,objoff_3E(a1)
move.w Enemy_Points(pc,d0.w),d0
cmpi.w #$20,(Chain_Bonus_counter).w ; have 16 enemies been destroyed?
blo.s loc_3F81C ; if not, branch
move.w #1000,d0 ; fix bonus to 10000 points
move.w #$A,objoff_3E(a1)
loc_3F81C:
movea.w a0,a3
bsr.w AddPoints2
_move.b #ObjID_Explosion,id(a1) ; load obj
move.b #0,routine(a1)
tst.w y_vel(a0)
bmi.s loc_3F844
move.w y_pos(a0),d0
cmp.w y_pos(a1),d0
bhs.s loc_3F84C
neg.w y_vel(a0)
rts
; ===========================================================================
loc_3F844:
addi.w #$100,y_vel(a0)
rts
; ===========================================================================
loc_3F84C:
subi.w #$100,y_vel(a0)
rts
; ===========================================================================
; byte_3F854:
Enemy_Points: dc.w 10, 20, 50, 100
; ===========================================================================
loc_3F85C:
bset #7,status(a1)
; ---------------------------------------------------------------------------
; Subroutine for checking if Sonic/Tails should be hurt and hurting them if so
; note: sonic or tails must be at a0
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_3F862:
Touch_ChkHurt:
btst #status_sec_isInvincible,status_secondary(a0) ; is Sonic invincible?
beq.s Touch_Hurt ; if not, branch
; loc_3F86A:
Touch_NoHurt:
moveq #-1,d0
rts
; ---------------------------------------------------------------------------
; loc_3F86E:
Touch_Hurt:
nop
tst.w invulnerable_time(a0)
bne.s Touch_NoHurt
movea.l a1,a2
; End of function TouchResponse
; continue straight to HurtCharacter
; ---------------------------------------------------------------------------
; Hurting Sonic/Tails subroutine
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_3F878: HurtSonic:
HurtCharacter:
move.w (Ring_count).w,d0
cmpa.w #MainCharacter,a0
beq.s loc_3F88C
tst.w (Two_player_mode).w
beq.s Hurt_Sidekick
move.w (Ring_count_2P).w,d0
loc_3F88C:
btst #status_sec_hasShield,status_secondary(a0)
bne.s Hurt_Shield
tst.w d0
beq.w KillCharacter
jsr (SingleObjLoad).l
bne.s Hurt_Shield
_move.b #ObjID_LostRings,id(a1) ; load obj
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.w a0,parent(a1)
; loc_3F8B8:
Hurt_Shield:
bclr #status_sec_hasShield,status_secondary(a0) ; remove shield
; loc_3F8BE:
Hurt_Sidekick:
move.b #4,routine(a0)
jsrto (Sonic_ResetOnFloor_Part2).l, JmpTo_Sonic_ResetOnFloor_Part2
bset #1,status(a0)
move.w #-$400,y_vel(a0) ; make Sonic bounce away from the object
move.w #-$200,x_vel(a0)
btst #6,status(a0) ; underwater?
beq.s Hurt_Reverse ; if not, branch
move.w #-$200,y_vel(a0) ; bounce slower
move.w #-$100,x_vel(a0)
; loc_3F8EE:
Hurt_Reverse:
move.w x_pos(a0),d0
cmp.w x_pos(a2),d0
blo.s Hurt_ChkSpikes ; if Sonic is left of the object, branch
neg.w x_vel(a0) ; if Sonic is right of the object, reverse
; loc_3F8FC:
Hurt_ChkSpikes:
move.w #0,inertia(a0)
move.b #AniIDSonAni_Hurt2,anim(a0)
move.w #$78,invulnerable_time(a0)
move.w #SndID_Hurt,d0 ; load normal damage sound
cmpi.b #ObjID_Spikes,(a2) ; was damage caused by spikes?
bne.s Hurt_Sound ; if not, branch
move.w #SndID_HurtBySpikes,d0 ; load spikes damage sound
; loc_3F91C:
Hurt_Sound:
jsr (PlaySound).l
moveq #-1,d0
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to kill Sonic or Tails
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_3F926: KillSonic:
KillCharacter:
tst.w (Debug_placement_mode).w
bne.s ++
clr.b status_secondary(a0)
move.b #6,routine(a0)
jsrto (Sonic_ResetOnFloor_Part2).l, JmpTo_Sonic_ResetOnFloor_Part2
bset #1,status(a0)
move.w #-$700,y_vel(a0)
move.w #0,x_vel(a0)
move.w #0,inertia(a0)
move.b #AniIDSonAni_Death,anim(a0)
bset #high_priority_bit,art_tile(a0)
move.w #SndID_Hurt,d0
cmpi.b #ObjID_Spikes,id(a2)
bne.s +
move.w #SndID_HurtBySpikes,d0
+
jsr (PlaySound).l
+
moveq #-1,d0
rts
; ===========================================================================
;loc_3F976:
Touch_Special:
move.b collision_flags(a1),d1
andi.b #$3F,d1
cmpi.b #6,d1
beq.s loc_3FA00
cmpi.b #7,d1
beq.w loc_3FA18
cmpi.b #$B,d1
beq.s BranchTo_loc_3F85C
cmpi.b #$A,d1
beq.s loc_3FA00
cmpi.b #$C,d1
beq.s loc_3F9CE
cmpi.b #$14,d1
beq.s loc_3FA00
cmpi.b #$15,d1
beq.s loc_3FA00
cmpi.b #$16,d1
beq.s loc_3FA00
cmpi.b #$17,d1
beq.s loc_3FA00
cmpi.b #$18,d1
beq.s loc_3FA00
cmpi.b #$1A,d1
beq.s loc_3FA22
cmpi.b #$21,d1
beq.s loc_3FA12
rts
; ===========================================================================
BranchTo_loc_3F85C
bra.w loc_3F85C
; ===========================================================================
loc_3F9CE:
sub.w d0,d5
cmpi.w #8,d5
bhs.s BranchTo_Touch_Enemy
move.w x_pos(a1),d0
subq.w #4,d0
btst #0,status(a1)
beq.s loc_3F9E8
subi.w #$10,d0
loc_3F9E8:
sub.w d2,d0
bcc.s loc_3F9F4
addi.w #$18,d0
bcs.s BranchTo_Touch_ChkHurt
bra.s BranchTo_Touch_Enemy
; ===========================================================================
loc_3F9F4:
cmp.w d4,d0
bhi.s BranchTo_Touch_Enemy
BranchTo_Touch_ChkHurt
bra.w Touch_ChkHurt
; ===========================================================================
BranchTo_Touch_Enemy
bra.w Touch_Enemy
; ===========================================================================
loc_3FA00:
move.w a0,d1
subi.w #Object_RAM,d1
beq.s +
addq.b #1,collision_property(a1)
+
addq.b #1,collision_property(a1)
rts
; ===========================================================================
loc_3FA12:
addq.b #1,collision_property(a1)
rts
; ===========================================================================
loc_3FA18:
move.b #2,collision_property(a1)
bra.w Touch_Enemy
; ===========================================================================
loc_3FA22:
move.b #-1,collision_property(a1)
bra.w Touch_Enemy
; ===========================================================================
; loc_3FA2C:
BossSpecificCollision:
cmpi.b #$F,d0
bne.s + ; rts
moveq #0,d0
move.b (Current_Boss_ID).w,d0
beq.s + ; rts
subq.w #1,d0
add.w d0,d0
move.w BossCollision_Index(pc,d0.w),d0
jmp BossCollision_Index(pc,d0.w)
; ===========================================================================
+ rts
; ===========================================================================
; off_3FA48:
BossCollision_Index:offsetTable ; jump depending on boss ID
offsetTableEntry.w BossCollision_EHZ_CPZ
offsetTableEntry.w BossCollision_EHZ_CPZ
offsetTableEntry.w BossCollision_HTZ
offsetTableEntry.w BossCollision_ARZ
offsetTableEntry.w BossCollision_MCZ
offsetTableEntry.w BossCollision_CNZ
offsetTableEntry.w BossCollision_MTZ
offsetTableEntry.w BossCollision_OOZ
offsetTableEntry.w return_3FA5E
; ===========================================================================
;loc_3FA5A:
BossCollision_EHZ_CPZ:
move.b collision_flags(a1),d0
return_3FA5E:
rts
; ===========================================================================
;loc_3FA60:
BossCollision_HTZ:
tst.b (Boss_CollisionRoutine).w
bne.s +
rts
; ---------------------------------------------------------------------------
+
move.w d7,-(sp)
moveq #0,d1
move.b objoff_15(a1),d1
subq.b #2,d1
cmpi.b #7,d1
bgt.s loc_3FAA8
move.w d1,d7
add.w d7,d7
move.w x_pos(a1),d0
btst #0,render_flags(a1)
beq.s loc_3FA8E
add.w word_3FAB0(pc,d7.w),d0
bra.s loc_3FA92
; ===========================================================================
loc_3FA8E:
sub.w word_3FAB0(pc,d7.w),d0
loc_3FA92:
move.b byte_3FAC0(pc,d1.w),d1
ori.l #$40000,d1
move.w y_pos(a1),d7
subi.w #$1C,d7
bsr.w Boss_DoCollision
loc_3FAA8:
move.w (sp)+,d7
move.b collision_flags(a1),d0
rts
; ===========================================================================
word_3FAB0:
dc.w $1C
dc.w $20 ; 1
dc.w $28 ; 2
dc.w $34 ; 3
dc.w $3C ; 4
dc.w $44 ; 5
dc.w $60 ; 6
dc.w $70 ; 7
byte_3FAC0:
dc.b 4
dc.b 4 ; 1
dc.b 8 ; 2
dc.b $C ; 3
dc.b $14 ; 4
dc.b $1C ; 5
dc.b $24 ; 6
dc.b 8 ; 7
; ===========================================================================
;loc_3FAC8:
BossCollision_ARZ:
move.w d7,-(sp)
move.w x_pos(a1),d0
move.w y_pos(a1),d7
tst.b (Boss_CollisionRoutine).w
beq.s ++
addi_.w #4,d7
subi.w #$50,d0
btst #0,render_flags(a1)
beq.s +
addi.w #$A0,d0
+
move.l #$140010,d1
bsr.w Boss_DoCollision
+
move.w (sp)+,d7
move.b collision_flags(a1),d0
rts
; ===========================================================================
;loc_3FAFE:
BossCollision_MCZ:
sf boss_hurt_sonic(a1)
cmpi.b #1,(Boss_CollisionRoutine).w
blt.s BossCollision_MCZ2
; Boss_CollisionRoutine = 1, i.e. diggers pointing to the side
move.w d7,-(sp)
move.w x_pos(a1),d0
move.w y_pos(a1),d7
addi_.w #4,d7
subi.w #$30,d0
btst #0,render_flags(a1) ; left or right?
beq.s +
addi.w #$60,d0 ; x+$30, otherwise x-$30
+
move.l #$40004,d1 ; heigth 4, width 4
bsr.w Boss_DoCollision
move.w (sp)+,d7
move.b collision_flags(a1),d0
cmpi.w #$78,invulnerable_time(a0)
bne.s + ; rts
st boss_hurt_sonic(a1) ; sonic has just been hurt flag
+
rts
; ===========================================================================
; Boss_CollisionRoutine = 0, i.e. diggers pointing towards top
;loc_3FB46:
BossCollision_MCZ2:
move.w d7,-(sp)
movea.w #$14,a5
movea.w #0,a4
- move.w x_pos(a1),d0
move.w y_pos(a1),d7
subi.w #$20,d7
add.w a5,d0 ; first check x+$14, second x-$14
move.l #$100004,d1 ; heigth $10, width 4
bsr.w Boss_DoCollision
movea.w #-$14,a5
adda_.w #1,a4
cmpa.w #1,a4
beq.s - ; jump back once for second check
move.w (sp)+,d7
move.b collision_flags(a1),d0
cmpi.w #$78,invulnerable_time(a0)
bne.s + ; rts
st boss_hurt_sonic(a1) ; sonic has just been hurt flag
+
rts
; ===========================================================================
;loc_3FB8A:
BossCollision_CNZ:
tst.b (Boss_CollisionRoutine).w
beq.s ++
move.w d7,-(sp)
move.w x_pos(a1),d0
move.w y_pos(a1),d7
addi.w #$28,d7
move.l #$80010,d1
cmpi.b #1,(Boss_CollisionRoutine).w
beq.s +
move.w #$20,d1
subi_.w #8,d7
addi_.w #4,d0
+
bsr.w Boss_DoCollision
move.w (sp)+,d7
+
move.b collision_flags(a1),d0
rts
; ===========================================================================
;loc_3FBC4:
BossCollision_MTZ:
move.b collision_flags(a1),d0
rts
; ===========================================================================
;loc_3FBCA:
BossCollision_OOZ:
cmpi.b #1,(Boss_CollisionRoutine).w
blt.s loc_3FC46
beq.s loc_3FC1C
move.w d7,-(sp)
move.w x_pos(a1),d0
move.w y_pos(a1),d7
moveq #0,d1
move.b mainspr_mapframe(a1),d1
subq.b #2,d1
add.w d1,d1
btst #0,render_flags(a1)
beq.s loc_3FBF6
add.w word_3FC10(pc,d1.w),d0
bra.s loc_3FBFA
; ===========================================================================
loc_3FBF6:
sub.w word_3FC10(pc,d1.w),d0
loc_3FBFA:
sub.w word_3FC10+2(pc,d1.w),d7
move.l #$60008,d1
bsr.w Boss_DoCollision
move.w (sp)+,d7
move.w #0,d0
rts
; ===========================================================================
word_3FC10:
dc.w $14, 0
dc.w $10, $10
dc.w $10, -$10
; ===========================================================================
loc_3FC1C:
move.w d7,-(sp)
move.w x_pos(a1),d0
move.w y_pos(a1),d7
moveq #$10,d1
btst #0,render_flags(a1)
beq.s +
neg.w d1
+
sub.w d1,d0
move.l #$8000C,d1
bsr.w loc_3FC7A
move.w (sp)+,d7
move.b #0,d0
rts
; ===========================================================================
loc_3FC46:
move.b collision_flags(a1),d0
rts
; ===========================================================================
;loc_3FC4C:
; d7 = y_boss, d3 = y_sonic, d1 (high word) = heigth
; d0 = x_boss, d2 = x_sonic, d1 (low word) = width
Boss_DoCollision:
sub.w d1,d0
sub.w d2,d0
bcc.s loc_3FC5A
add.w d1,d1
add.w d1,d0
bcs.s loc_3FC5E
return_3FC58:
rts
; ===========================================================================
loc_3FC5A:
cmp.w d4,d0
bhi.s return_3FC58
loc_3FC5E:
swap d1
sub.w d1,d7
sub.w d3,d7
bcc.s loc_3FC70
add.w d1,d1
add.w d1,d7
bcs.w Touch_ChkHurt
bra.s return_3FC58
; ===========================================================================
loc_3FC70:
cmp.w d5,d7
bhi.w return_3FC58
bra.w Touch_ChkHurt
; ===========================================================================
loc_3FC7A:
sub.w d1,d0
sub.w d2,d0
bcc.s loc_3FC88
add.w d1,d1
add.w d1,d0
bcs.s loc_3FC8C
return_3FC86:
rts
; ===========================================================================
loc_3FC88:
cmp.w d4,d0
bhi.s return_3FC86
loc_3FC8C:
swap d1
sub.w d1,d7
sub.w d3,d7
bcc.s loc_3FC9E
add.w d1,d1
add.w d1,d7
bcs.w loc_3FCA4
bra.s return_3FC86
; ===========================================================================
loc_3FC9E:
cmp.w d5,d7
bhi.w return_3FC86
loc_3FCA4:
neg.w x_vel(a0)
neg.w y_vel(a0)
rts
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo_Sonic_ResetOnFloor_Part2
jmp (Sonic_ResetOnFloor_Part2).l
JmpTo_Check_CNZ_bumpers
jmp (Check_CNZ_bumpers).l
JmpTo_Touch_Rings
jmp (Touch_Rings).l
align 4
endif
; ===========================================================================
;loc_3FCC4:
AniArt_Load:
moveq #0,d0
move.b (Current_Zone).w,d0
add.w d0,d0
add.w d0,d0
move.w PLC_DYNANM+2(pc,d0.w),d1
lea PLC_DYNANM(pc,d1.w),a2
move.w PLC_DYNANM(pc,d0.w),d0
jmp PLC_DYNANM(pc,d0.w)
; ===========================================================================
rts
; ===========================================================================
; ---------------------------------------------------------------------------
; ZONE ANIMATION PROCEDURES AND SCRIPTS
;
; Each zone gets two entries in this jump table. The first entry points to the
; zone's animation procedure (usually Dynamic_Normal, but some zones have special
; procedures for complicated animations). The second points to the zone's animation
; script.
;
; Note that Animated_Null is not a valid animation script, so don't pair it up
; with anything except Dynamic_Null, or bad things will happen (for example, a bus error exception).
; ---------------------------------------------------------------------------
PLC_DYNANM: zoneOrderedOffsetTable 2,2 ; Zone ID
zoneOffsetTableEntry.w Dynamic_Normal ; $00
zoneOffsetTableEntry.w Animated_EHZ
zoneOffsetTableEntry.w Dynamic_Null ; $01
zoneOffsetTableEntry.w Animated_Null
zoneOffsetTableEntry.w Dynamic_Null ; $02
zoneOffsetTableEntry.w Animated_Null
zoneOffsetTableEntry.w Dynamic_Null ; $03
zoneOffsetTableEntry.w Animated_Null
zoneOffsetTableEntry.w Dynamic_Normal ; $04
zoneOffsetTableEntry.w Animated_MTZ
zoneOffsetTableEntry.w Dynamic_Normal ; $05
zoneOffsetTableEntry.w Animated_MTZ
zoneOffsetTableEntry.w Dynamic_Null ; $06
zoneOffsetTableEntry.w Animated_Null
zoneOffsetTableEntry.w Dynamic_HTZ ; $07
zoneOffsetTableEntry.w Animated_HTZ
zoneOffsetTableEntry.w Dynamic_Normal ; $08
zoneOffsetTableEntry.w Animated_HPZ
zoneOffsetTableEntry.w Dynamic_Null ; $09
zoneOffsetTableEntry.w Animated_Null
zoneOffsetTableEntry.w Dynamic_Normal ; $0A
zoneOffsetTableEntry.w Animated_OOZ
zoneOffsetTableEntry.w Dynamic_Null ; $0B
zoneOffsetTableEntry.w Animated_Null
zoneOffsetTableEntry.w Dynamic_CNZ ; $0C
zoneOffsetTableEntry.w Animated_CNZ
zoneOffsetTableEntry.w Dynamic_Normal ; $0D
zoneOffsetTableEntry.w Animated_CPZ
zoneOffsetTableEntry.w Dynamic_Normal ; $0E
zoneOffsetTableEntry.w Animated_DEZ
zoneOffsetTableEntry.w Dynamic_ARZ ; $0F
zoneOffsetTableEntry.w Animated_ARZ
zoneOffsetTableEntry.w Dynamic_Null ; $10
zoneOffsetTableEntry.w Animated_Null
zoneTableEnd
; ===========================================================================
Dynamic_Null:
rts
; ===========================================================================
Dynamic_HTZ:
tst.w (Two_player_mode).w
bne.w Dynamic_Normal
lea (Anim_Counters).w,a3
moveq #0,d0
move.w (Camera_X_pos).w,d1
neg.w d1
asr.w #3,d1
move.w (Camera_X_pos).w,d0
lsr.w #4,d0
add.w d1,d0
subi.w #$10,d0
divu.w #$30,d0
swap d0
cmp.b 1(a3),d0
beq.s BranchTo_loc_3FE5C
move.b d0,1(a3)
move.w d0,d2
andi.w #7,d0
add.w d0,d0
add.w d0,d0
add.w d0,d0
move.w d0,d1
add.w d0,d0
add.w d1,d0
andi.w #$38,d2
lsr.w #2,d2
add.w d2,d0
lea word_3FD9C(pc,d0.w),a4
moveq #5,d5
move.w #tiles_to_bytes(ArtTile_ArtUnc_HTZMountains),d4
loc_3FD7C:
moveq #-1,d1
move.w (a4)+,d1
andi.l #$FFFFFF,d1
move.w d4,d2
moveq #$40,d3
jsr (QueueDMATransfer).l
addi.w #$80,d4
dbf d5,loc_3FD7C
BranchTo_loc_3FE5C
bra.w loc_3FE5C
; ===========================================================================
; HTZ mountain art main RAM addresses?
word_3FD9C:
dc.w $80, $180, $280, $580, $600, $700 ; 6
dc.w $80, $180, $280, $580, $600, $700 ; 12
dc.w $980, $A80, $B80, $C80, $D00, $D80 ; 18
dc.w $980, $A80, $B80, $C80, $D00, $D80 ; 24
dc.w $E80,$1180,$1200,$1280,$1300,$1380 ; 30
dc.w $E80,$1180,$1200,$1280,$1300,$1380 ; 36
dc.w $1400,$1480,$1500,$1580,$1600,$1900 ; 42
dc.w $1400,$1480,$1500,$1580,$1600,$1900 ; 48
dc.w $1D00,$1D80,$1E00,$1F80,$2400,$2580 ; 54
dc.w $1D00,$1D80,$1E00,$1F80,$2400,$2580 ; 60
dc.w $2600,$2680,$2780,$2B00,$2F00,$3280 ; 66
dc.w $2600,$2680,$2780,$2B00,$2F00,$3280 ; 72
dc.w $3600,$3680,$3780,$3C80,$3D00,$3F00 ; 78
dc.w $3600,$3680,$3780,$3C80,$3D00,$3F00 ; 84
dc.w $3F80,$4080,$4480,$4580,$4880,$4900 ; 90
dc.w $3F80,$4080,$4480,$4580,$4880,$4900 ; 96
; ===========================================================================
loc_3FE5C:
lea (TempArray_LayerDef).w,a1
move.w (Camera_X_pos).w,d2
neg.w d2
asr.w #3,d2
move.l a2,-(sp)
lea (ArtUnc_HTZClouds).l,a0
lea (Chunk_Table+$7C00).l,a2
moveq #$F,d1
loc_3FE78:
move.w (a1)+,d0
neg.w d0
add.w d2,d0
andi.w #$1F,d0
lsr.w #1,d0
bcc.s loc_3FE8A
addi.w #$200,d0
loc_3FE8A:
lea (a0,d0.w),a4
lsr.w #1,d0
bcs.s loc_3FEB4
move.l (a4)+,(a2)+
adda.w #$3C,a2
move.l (a4)+,(a2)+
adda.w #$3C,a2
move.l (a4)+,(a2)+
adda.w #$3C,a2
move.l (a4)+,(a2)+
suba.w #$C0,a2
adda.w #$20,a0
dbf d1,loc_3FE78
bra.s loc_3FEEC
; ===========================================================================
loc_3FEB4:
rept 3
rept 4
move.b (a4)+,(a2)+
endm
adda.w #$3C,a2
endm
rept 4
move.b (a4)+,(a2)+
endm
suba.w #$C0,a2
adda.w #$20,a0
dbf d1,loc_3FE78
loc_3FEEC:
move.l #(Chunk_Table+$7C00) & $FFFFFF,d1
move.w #tiles_to_bytes(ArtTile_ArtUnc_HTZClouds),d2
move.w #$80,d3
jsr (QueueDMATransfer).l
movea.l (sp)+,a2
addq.w #2,a3
bra.w loc_3FF30
; ===========================================================================
Dynamic_CNZ:
tst.b (Current_Boss_ID).w
beq.s +
rts
; ---------------------------------------------------------------------------
+
lea (Animated_CNZ).l,a2
tst.w (Two_player_mode).w
beq.s Dynamic_Normal
lea (Animated_CNZ_2P).l,a2
bra.s Dynamic_Normal
; ===========================================================================
Dynamic_ARZ:
tst.b (Current_Boss_ID).w
beq.s Dynamic_Normal
rts
; ===========================================================================
Dynamic_Normal:
lea (Anim_Counters).w,a3
loc_3FF30:
move.w (a2)+,d6 ; Get number of scripts in list
; S&K checks for empty lists, here
; bpl.s .listnotempty ; If there are any, continue
; rts
;.listnotempty:
; loc_3FF32:
.loop:
subq.b #1,(a3) ; Tick down frame duration
bcc.s .nextscript ; If frame isn't over, move on to next script
;.nextframe:
moveq #0,d0
move.b 1(a3),d0 ; Get current frame
cmp.b 6(a2),d0 ; Have we processed the last frame in the script?
blo.s .notlastframe
moveq #0,d0 ; If so, reset to first frame
move.b d0,1(a3) ; ''
; loc_3FF48:
.notlastframe:
addq.b #1,1(a3) ; Consider this frame processed; set counter to next frame
move.b (a2),(a3) ; Set frame duration to global duration value
bpl.s .globalduration
; If script uses per-frame durations, use those instead
add.w d0,d0
move.b 9(a2,d0.w),(a3) ; Set frame duration to current frame's duration value
; loc_3FF56:
.globalduration:
; Prepare for DMA transfer
; Get relative address of frame's art
move.b 8(a2,d0.w),d0 ; Get tile ID
lsl.w #5,d0 ; Turn it into an offset
; Get VRAM destination address
move.w 4(a2),d2
; Get ROM source address
move.l (a2),d1 ; Get start address of animated tile art
andi.l #$FFFFFF,d1
add.l d0,d1 ; Offset into art, to get the address of new frame
; Get size of art to be transferred
moveq #0,d3
move.b 7(a2),d3
lsl.w #4,d3 ; Turn it into actual size (in words)
; Use d1, d2 and d3 to queue art for transfer
jsr (QueueDMATransfer).l
; loc_3FF78:
.nextscript:
move.b 6(a2),d0 ; Get total size of frame data
tst.b (a2) ; Is per-frame duration data present?
bpl.s .globalduration2; If not, keep the current size; it's correct
add.b d0,d0 ; Double size to account for the additional frame duration data
; loc_3FF82:
.globalduration2:
addq.b #1,d0
andi.w #$FE,d0 ; Round to next even address, if it isn't already
lea 8(a2,d0.w),a2 ; Advance to next script in list
addq.w #2,a3 ; Advance to next script's slot in a3 (usually Anim_Counters)
dbf d6,.loop
rts
; ===========================================================================
; ZONE ANIMATION SCRIPTS
;
; The Dynamic_Normal subroutine uses these scripts to reload certain tiles,
; thus animating them. All the relevant art must be uncompressed, because
; otherwise the subroutine would spend so much time waiting for the art to be
; decompressed that the VBLANK window would close before all the animating was done.
; zoneanimdecl -1, ArtUnc_Flowers1, ArtTile_ArtUnc_Flowers1, 6, 2
; -1 Global frame duration. If -1, then each frame will use its own duration, instead
; ArtUnc_Flowers1 Source address
; ArtTile_ArtUnc_Flowers1 Destination VRAM address
; 6 Number of frames
; 2 Number of tiles to load into VRAM for each frame
; dc.b 0,$7F ; Start of the script proper
; 0 Tile ID of first tile in ArtUnc_Flowers1 to transfer
; $7F Frame duration. Only here if global duration is -1
; loc_3FF94:
Animated_EHZ: zoneanimstart
; Flowers
zoneanimdecl -1, ArtUnc_Flowers1, ArtTile_ArtUnc_Flowers1, 6, 2
dc.b 0,$7F ; Start of the script proper
dc.b 2,$13
dc.b 0, 7
dc.b 2, 7
dc.b 0, 7
dc.b 2, 7
even
; Flowers
zoneanimdecl -1, ArtUnc_Flowers2, ArtTile_ArtUnc_Flowers2, 8, 2
dc.b 2,$7F
dc.b 0, $B
dc.b 2, $B
dc.b 0, $B
dc.b 2, 5
dc.b 0, 5
dc.b 2, 5
dc.b 0, 5
even
; Flowers
zoneanimdecl 7, ArtUnc_Flowers3, ArtTile_ArtUnc_Flowers3, 2, 2
dc.b 0
dc.b 2
even
; Flowers
zoneanimdecl -1, ArtUnc_Flowers4, ArtTile_ArtUnc_Flowers4, 8, 2
dc.b 0,$7F
dc.b 2, 7
dc.b 0, 7
dc.b 2, 7
dc.b 0, 7
dc.b 2, $B
dc.b 0, $B
dc.b 2, $B
even
; Pulsing thing against checkered background
zoneanimdecl -1, ArtUnc_EHZPulseBall, ArtTile_ArtUnc_EHZPulseBall, 6, 2
dc.b 0,$17
dc.b 2, 9
dc.b 4, $B
dc.b 6,$17
dc.b 4, $B
dc.b 2, 9
even
zoneanimend
Animated_MTZ: zoneanimstart
; Spinning metal cylinder
zoneanimdecl 0, ArtUnc_MTZCylinder, ArtTile_ArtUnc_MTZCylinder, 8,$10
dc.b 0
dc.b $10
dc.b $20
dc.b $30
dc.b $40
dc.b $50
dc.b $60
dc.b $70
even
; lava
zoneanimdecl $D, ArtUnc_Lava, ArtTile_ArtUnc_Lava, 6,$C
dc.b 0
dc.b $C
dc.b $18
dc.b $24
dc.b $18
dc.b $C
even
; MTZ background animated section
zoneanimdecl -1, ArtUnc_MTZAnimBack, ArtTile_ArtUnc_MTZAnimBack_1, 4, 6
dc.b 0,$13
dc.b 6, 7
dc.b $C,$13
dc.b 6, 7
even
; MTZ background animated section
zoneanimdecl -1, ArtUnc_MTZAnimBack, ArtTile_ArtUnc_MTZAnimBack_2, 4, 6
dc.b $C,$13
dc.b 6, 7
dc.b 0,$13
dc.b 6, 7
even
zoneanimend
Animated_HTZ: zoneanimstart
; Flowers
zoneanimdecl -1, ArtUnc_Flowers1, ArtTile_ArtUnc_Flowers1, 6, 2
dc.b 0,$7F
dc.b 2,$13
dc.b 0, 7
dc.b 2, 7
dc.b 0, 7
dc.b 2, 7
even
; Flowers
zoneanimdecl -1, ArtUnc_Flowers2, ArtTile_ArtUnc_Flowers2, 8, 2
dc.b 2,$7F
dc.b 0, $B
dc.b 2, $B
dc.b 0, $B
dc.b 2, 5
dc.b 0, 5
dc.b 2, 5
dc.b 0, 5
even
; Flowers
zoneanimdecl 7, ArtUnc_Flowers3, ArtTile_ArtUnc_Flowers3, 2, 2
dc.b 0
dc.b 2
even
; Flowers
zoneanimdecl -1, ArtUnc_Flowers4, ArtTile_ArtUnc_Flowers4, 8, 2
dc.b 0,$7F
dc.b 2, 7
dc.b 0, 7
dc.b 2, 7
dc.b 0, 7
dc.b 2, $B
dc.b 0, $B
dc.b 2, $B
even
; Pulsing thing against checkered background
zoneanimdecl -1, ArtUnc_EHZPulseBall, ArtTile_ArtUnc_EHZPulseBall, 6, 2
dc.b 0,$17
dc.b 2, 9
dc.b 4, $B
dc.b 6,$17
dc.b 4, $B
dc.b 2, 9
even
zoneanimend
; word_4009C: Animated_OOZ:
Animated_HPZ: zoneanimstart
; Supposed to be the pulsing orb from HPZ, but uses OOZ's pulsing ball art
zoneanimdecl 8, ArtUnc_HPZPulseOrb, ArtTile_ArtUnc_HPZPulseOrb_1, 6, 8
dc.b 0
dc.b 0
dc.b 8
dc.b $10
dc.b $10
dc.b 8
even
; Supposed to be the pulsing orb from HPZ, but uses OOZ's pulsing ball art
zoneanimdecl 8, ArtUnc_HPZPulseOrb, ArtTile_ArtUnc_HPZPulseOrb_2, 6, 8
dc.b 8
dc.b $10
dc.b $10
dc.b 8
dc.b 0
dc.b 0
even
; Supposed to be the pulsing orb from HPZ, but uses OOZ's pulsing ball art
zoneanimdecl 8, ArtUnc_HPZPulseOrb, ArtTile_ArtUnc_HPZPulseOrb_3, 6, 8
dc.b $10
dc.b 8
dc.b 0
dc.b 0
dc.b 8
dc.b $10
even
zoneanimend
; word_400C8: Animated_OOZ2:
Animated_OOZ: zoneanimstart
; Pulsing ball from OOZ
zoneanimdecl -1, ArtUnc_OOZPulseBall, ArtTile_ArtUnc_OOZPulseBall, 4, 4
dc.b 0, $B
dc.b 4, 5
dc.b 8, 9
dc.b 4, 3
even
; Square rotating around ball in OOZ
zoneanimdecl 6, ArtUnc_OOZSquareBall1, ArtTile_ArtUnc_OOZSquareBall1, 4, 4
dc.b 0
dc.b 4
dc.b 8
dc.b $C
even
; Square rotating around ball
zoneanimdecl 6, ArtUnc_OOZSquareBall2, ArtTile_ArtUnc_OOZSquareBall2, 4, 4
dc.b 0
dc.b 4
dc.b 8
dc.b $C
even
; Oil
zoneanimdecl $11, ArtUnc_Oil1, ArtTile_ArtUnc_Oil1, 6,$10
dc.b 0
dc.b $10
dc.b $20
dc.b $30
dc.b $20
dc.b $10
even
; Oil
zoneanimdecl $11, ArtUnc_Oil2, ArtTile_ArtUnc_Oil2, 6,$10
dc.b 0
dc.b $10
dc.b $20
dc.b $30
dc.b $20
dc.b $10
even
zoneanimend
Animated_CNZ: zoneanimstart
; Flipping foreground section in CNZ
zoneanimdecl -1, ArtUnc_CNZFlipTiles, ArtTile_ArtUnc_CNZFlipTiles_2, $10,$10
dc.b 0,$C7
dc.b $10, 5
dc.b $20, 5
dc.b $30, 5
dc.b $40,$C7
dc.b $50, 5
dc.b $20, 5
dc.b $60, 5
dc.b 0, 5
dc.b $10, 5
dc.b $20, 5
dc.b $30, 5
dc.b $40, 5
dc.b $50, 5
dc.b $20, 5
dc.b $60, 5
even
; Flipping foreground section in CNZ
zoneanimdecl -1, ArtUnc_CNZFlipTiles, ArtTile_ArtUnc_CNZFlipTiles_1, $10,$10
dc.b $70, 5
dc.b $80, 5
dc.b $20, 5
dc.b $90, 5
dc.b $A0, 5
dc.b $B0, 5
dc.b $20, 5
dc.b $C0, 5
dc.b $70,$C7
dc.b $80, 5
dc.b $20, 5
dc.b $90, 5
dc.b $A0,$C7
dc.b $B0, 5
dc.b $20, 5
dc.b $C0, 5
even
zoneanimend
; word_40160:
Animated_CNZ_2P: zoneanimstart
; Flipping foreground section in CNZ
zoneanimdecl -1, ArtUnc_CNZFlipTiles, ArtTile_ArtUnc_CNZFlipTiles_2_2p, $10,$10
dc.b 0,$C7
dc.b $10, 5
dc.b $20, 5
dc.b $30, 5
dc.b $40,$C7
dc.b $50, 5
dc.b $20, 5
dc.b $60, 5
dc.b 0, 5
dc.b $10, 5
dc.b $20, 5
dc.b $30, 5
dc.b $40, 5
dc.b $50, 5
dc.b $20, 5
dc.b $60, 5
even
; Flipping foreground section in CNZ
zoneanimdecl -1, ArtUnc_CNZFlipTiles, ArtTile_ArtUnc_CNZFlipTiles_1_2p, $10,$10
dc.b $70, 5
dc.b $80, 5
dc.b $20, 5
dc.b $90, 5
dc.b $A0, 5
dc.b $B0, 5
dc.b $20, 5
dc.b $C0, 5
dc.b $70,$C7
dc.b $80, 5
dc.b $20, 5
dc.b $90, 5
dc.b $A0,$C7
dc.b $B0, 5
dc.b $20, 5
dc.b $C0, 5
even
zoneanimend
Animated_CPZ: zoneanimstart
; Animated background section in CPZ and DEZ
zoneanimdecl 4, ArtUnc_CPZAnimBack, ArtTile_ArtUnc_CPZAnimBack, 8, 2
dc.b 0
dc.b 2
dc.b 4
dc.b 6
dc.b 8
dc.b $A
dc.b $C
dc.b $E
even
zoneanimend
Animated_DEZ: zoneanimstart
; Animated background section in CPZ and DEZ
zoneanimdecl 4, ArtUnc_CPZAnimBack, ArtTile_ArtUnc_DEZAnimBack, 8, 2
dc.b 0
dc.b 2
dc.b 4
dc.b 6
dc.b 8
dc.b $A
dc.b $C
dc.b $E
even
zoneanimend
Animated_ARZ: zoneanimstart
; Waterfall patterns
zoneanimdecl 5, ArtUnc_Waterfall1, ArtTile_ArtUnc_Waterfall1_2, 2, 4
dc.b 0
dc.b 4
even
; Waterfall patterns
zoneanimdecl 5, ArtUnc_Waterfall1, ArtTile_ArtUnc_Waterfall1_1, 2, 4
dc.b 4
dc.b 0
even
; Waterfall patterns
zoneanimdecl 5, ArtUnc_Waterfall2, ArtTile_ArtUnc_Waterfall2, 2, 4
dc.b 0
dc.b 4
even
; Waterfall patterns
zoneanimdecl 5, ArtUnc_Waterfall3, ArtTile_ArtUnc_Waterfall3, 2, 4
dc.b 0
dc.b 4
even
zoneanimend
Animated_Null:
; invalid
; ===========================================================================
; ---------------------------------------------------------------------------
; Unused mystery function
; In CPZ, within a certain range of camera X coordinates spanning
; exactly 2 screens (a boss fight or cutscene?),
; once every 8 frames, make the entire screen refresh and do... SOMETHING...
; (in 2 separate 512-byte blocks of memory, move around a bunch of bytes)
; Maybe some abandoned scrolling effect?
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_40200:
cmpi.b #chemical_plant_zone,(Current_Zone).w
beq.s +
- rts
; ===========================================================================
; this shifts all blocks of the chunks $EA-$ED and $FA-$FD one block to the
; left and the last block in each row (chunk $ED/$FD) to the beginning
; i.e. rotates the blocks to the left by one
+
move.w (Camera_X_pos).w,d0
cmpi.w #$1940,d0
blo.s - ; rts
cmpi.w #$1F80,d0
bhs.s - ; rts
subq.b #1,(CPZ_UnkScroll_Timer).w
bpl.s - ; rts ; do it every 8th frame
move.b #7,(CPZ_UnkScroll_Timer).w
move.b #1,(Screen_redraw_flag).w
lea (Chunk_Table+$7500).l,a1 ; chunks $EA-$ED, $FFFF7500 - $FFFF7700
bsr.s +
lea (Chunk_Table+$7D00).l,a1 ; chunks $FA-$FD, $FFFF7D00 - $FFFF7F00
+
move.w #7,d1
- move.w (a1),d0
rept 3 ; do this for 3 chunks
rept 7
move.w 2(a1),(a1)+ ; shift 1st line of chunk by 1 block to the left (+3*14 bytes)
endm
move.w $72(a1),(a1)+ ; first block of next chunk to the left into previous chunk (+3*2 bytes)
adda.w #$70,a1 ; go to next chunk (+336 bytes)
endm
rept 7 ; now do it for the 4th chunk
move.w 2(a1),(a1)+ ; shift 1st line of chunk by 1 block to the left (+14 bytes)
endm
move.w d0,(a1)+ ; move 1st block of 1st chunk to last block of last chunk (+2 bytes, subsubtotal = 400 bytes)
suba.w #$180,a1 ; go to the next row in the first chunk (-384 bytes, subtotal = -16 bytes)
dbf d1,- ; now do this again for rows 2-8 in these chunks
; 400 + 7 * (-16) = 512 byte range was affected
rts
; ===========================================================================
loc_402D4:
cmpi.b #hill_top_zone,(Current_Zone).w
bne.s +
bsr.w PatchHTZTiles
move.b #-1,(Anim_Counters+1).w
move.w #-1,(TempArray_LayerDef+$20).w
+
cmpi.b #chemical_plant_zone,(Current_Zone).w
bne.s +
move.b #-1,(Anim_Counters+1).w
+
moveq #0,d0
move.b (Current_Zone).w,d0
add.w d0,d0
move.w AnimPatMaps(pc,d0.w),d0
lea AnimPatMaps(pc,d0.w),a0
tst.w (Two_player_mode).w
beq.s +
cmpi.b #casino_night_zone,(Current_Zone).w
bne.s +
lea (APM_CNZ2P).l,a0
+
tst.w (a0)
beq.s + ; rts
lea (Block_Table).w,a1
adda.w (a0)+,a1
move.w (a0)+,d1
tst.w (Two_player_mode).w
bne.s LoadLevelBlocks_2P
; loc_40330:
LoadLevelBlocks:
move.w (a0)+,(a1)+ ; copy blocks to RAM
dbf d1,LoadLevelBlocks ; loop using d1
+
rts
; ===========================================================================
; loc_40338:
LoadLevelBlocks_2P:
; There's a bug in here, where d1, the loop counter,
; is overwritten with VRAM data
move.w (a0)+,d0
move.w d0,d1
andi.w #nontile_mask,d0 ; d0 holds the preserved non-tile data
andi.w #tile_mask,d1 ; d1 holds the tile index (overwrites loop counter!)
lsr.w #1,d1 ; half tile index
or.w d1,d0 ; put them back together
move.w d0,(a1)+
dbf d1,LoadLevelBlocks_2P ; loop using d1, which we just overwrote
rts
; ===========================================================================
; --------------------------------------------------------------------------------------
; Animated Pattern Mappings (16x16)
; --------------------------------------------------------------------------------------
; off_40350:
AnimPatMaps: zoneOrderedOffsetTable 2,1
zoneOffsetTableEntry.w APM_EHZ ; 0
zoneOffsetTableEntry.w APM_Null ; 1
zoneOffsetTableEntry.w APM_Null ; 2
zoneOffsetTableEntry.w APM_Null ; 3
zoneOffsetTableEntry.w APM_MTZ ; 4
zoneOffsetTableEntry.w APM_MTZ ; 5
zoneOffsetTableEntry.w APM_Null ; 6
zoneOffsetTableEntry.w APM_EHZ ; 7
zoneOffsetTableEntry.w APM_HPZ ; 8
zoneOffsetTableEntry.w APM_Null ; 9
zoneOffsetTableEntry.w APM_OOZ ; $A
zoneOffsetTableEntry.w APM_Null ; $B
zoneOffsetTableEntry.w APM_CNZ ; $C
zoneOffsetTableEntry.w APM_CPZ ; $D
zoneOffsetTableEntry.w APM_DEZ ; $E
zoneOffsetTableEntry.w APM_ARZ ; $F
zoneOffsetTableEntry.w APM_Null ;$10
zoneTableEnd
begin_animpat macro {INTLABEL}
__LABEL__ label *
__LABEL___Len := __LABEL___End - __LABEL___Blocks
dc.w $1800 - __LABEL___Len
dc.w bytesToWcnt(__LABEL___Len)
__LABEL___Blocks:
endm
; byte_40372:
APM_EHZ: begin_animpat
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$0 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$4 ,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$1 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$5 ,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$8 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$C ,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$9 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$D ,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$10,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$14,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$11,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$15,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$2 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$6 ,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$3 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$7 ,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$A ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$E ,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$B ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$F ,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$12,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$16,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$13,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$17,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$18,0,0,3,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$1A,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$19,0,0,3,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$1B,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$1C,0,0,3,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$1E,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZMountains+$1D,0,0,3,0),make_block_tile(ArtTile_ArtUnc_EHZMountains+$1F,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$0,1,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$1,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$1,1,0,2,0)
dc.w make_block_tile(ArtTile_ArtKos_Checkers+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$0,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtKos_Checkers+$1,0,0,2,0),make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$1,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$0,1,0,2,0),make_block_tile(ArtTile_ArtKos_Checkers+$0,1,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_EHZPulseBall+$1,1,0,2,0),make_block_tile(ArtTile_ArtKos_Checkers+$1,1,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_Flowers1+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_Flowers1+$0,1,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_Flowers1+$1,0,0,3,0),make_block_tile(ArtTile_ArtUnc_Flowers1+$1,1,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_Flowers2+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_Flowers2+$0,1,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_Flowers2+$1,0,0,3,1),make_block_tile(ArtTile_ArtUnc_Flowers2+$1,1,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_Flowers3+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_Flowers3+$0,1,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_Flowers3+$1,0,0,3,0),make_block_tile(ArtTile_ArtUnc_Flowers3+$1,1,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_Flowers4+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_Flowers4+$0,1,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_Flowers4+$1,0,0,3,1),make_block_tile(ArtTile_ArtUnc_Flowers4+$1,1,0,3,1)
APM_EHZ_End:
; byte_403EE:
APM_MTZ: begin_animpat
dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$0,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$0,1,0,1,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$1,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$1,1,0,1,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$2,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$2,1,0,1,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$3,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$3,1,0,1,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$E,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$E,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$F,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$F,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$C,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$C,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$D,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$D,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$A,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$A,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$B,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$B,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$8,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$8,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$9,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$9,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$6,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$6,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$7,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$7,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$4,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$4,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$5,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$5,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$2,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$2,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$3,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$3,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$1,0,0,3,0),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$1,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$4,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$4,1,0,1,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$5,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_1+$5,1,0,1,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$0,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$0,1,0,1,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$1,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$1,1,0,1,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$2,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$2,1,0,1,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$3,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$3,1,0,1,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$4,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$4,1,0,1,0)
dc.w make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$5,0,0,1,0),make_block_tile(ArtTile_ArtUnc_MTZAnimBack_2+$5,1,0,1,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,1),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Lava+$0 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Lava+$1 ,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,1),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Lava+$2 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Lava+$3 ,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Lava+$4 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Lava+$5 ,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Lava+$8 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Lava+$9 ,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Lava+$6 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Lava+$7 ,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Lava+$A ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Lava+$B ,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$E,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$E,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$F,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$F,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$C,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$C,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$D,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$D,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$A,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$A,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$B,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$B,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$8,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$8,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$9,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$9,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$6,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$6,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$7,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$7,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$4,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$4,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$5,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$5,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$2,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$2,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$3,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$3,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$0,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_MTZCylinder+$1,0,0,3,1),make_block_tile(ArtTile_ArtUnc_MTZCylinder+$1,0,0,3,1)
APM_MTZ_End:
; byte_404C2:
APM_HPZ: begin_animpat
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$1,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$2,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$3,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$4,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$5,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$6,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$7,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$1,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$2,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$3,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$4,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$5,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$6,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$7,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$1,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$2,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$3,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$4,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$5,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$6,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$7,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$1,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$2,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$3,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$4,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$5,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$6,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$7,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$1,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$2,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$3,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$4,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$5,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$6,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$7,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$1,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$2,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$3,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$4,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$5,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$6,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$7,0,0,2,0)
if gameRevision<2
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$2,0,0,3,0)
else
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$2,0,0,3,0)
endif
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$1,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$4,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$3,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$6,0,0,3,0)
if gameRevision<2
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$5,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$7,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$2,0,0,3,0)
else
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$5,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$7,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$2,0,0,3,0)
endif
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$1,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$4,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$3,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$6,0,0,3,0)
if gameRevision<2
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$5,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$7,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$2,0,0,3,0)
else
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$5,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$7,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$2,0,0,3,0)
endif
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$1,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$4,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$3,0,0,3,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$6,0,0,3,0)
if gameRevision<2
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$5,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$7,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$0,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$2,0,0,2,0)
else
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$5,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$7,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$0,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$2,0,0,2,0)
endif
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$1,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$4,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$3,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$6,0,0,2,0)
if gameRevision<2
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$5,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$7,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$0,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$2,0,0,2,0)
else
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$5,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_1+$7,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$0,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$2,0,0,2,0)
endif
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$1,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$4,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$3,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$6,0,0,2,0)
if gameRevision<2
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$5,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$7,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$0,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$2,0,0,2,0)
else
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$5,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_2+$7,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$0,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$2,0,0,2,0)
endif
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$1,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$4,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$3,0,0,2,0),make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$6,0,0,2,0)
if gameRevision<2
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$5,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$7,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0)
else
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$5,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_HPZPulseOrb_3+$7,0,0,2,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0)
endif
APM_HPZ_End:
; byte_405B6:
APM_OOZ: begin_animpat
dc.w make_block_tile(ArtTile_ArtUnc_OOZPulseBall+$0,0,0,0,1),make_block_tile(ArtTile_ArtUnc_OOZPulseBall+$2,0,0,0,1)
dc.w make_block_tile(ArtTile_ArtUnc_OOZPulseBall+$1,0,0,0,1),make_block_tile(ArtTile_ArtUnc_OOZPulseBall+$3,0,0,0,1)
dc.w make_block_tile(ArtTile_ArtUnc_OOZSquareBall1+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_OOZSquareBall1+$1,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_OOZSquareBall1+$2,0,0,3,1),make_block_tile(ArtTile_ArtUnc_OOZSquareBall1+$3,0,0,3,1)
if gameRevision<2
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$2,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$1,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$3,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,0,0)
else
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$0,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$2,0,0,3,0)
dc.w make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$1,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_OOZSquareBall2+$3,0,0,3,0),make_block_tile(ArtTile_ArtKos_LevelArt+$0,0,0,2,0)
endif
dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$0,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$1,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$8,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$9,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$2,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$3,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$A,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$B,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$4,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$5,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$C,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$D,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$6,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$7,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil1+$E,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil1+$F,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$0,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$1,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$8,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$9,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$2,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$3,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$A,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$B,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$4,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$5,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$C,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$D,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$6,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$7,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Oil2+$E,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Oil2+$F,0,0,2,1)
APM_OOZ_End:
; byte_4061A:
APM_CNZ: begin_animpat
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$4,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$1,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$5,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$8,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$C,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$9,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$D,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$2,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$6,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$3,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$7,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$A,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$E,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$B,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1+$F,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$4,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$1,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$5,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$8,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$C,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$9,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$D,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$2,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$6,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$3,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$7,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$A,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$E,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$B,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2+$F,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$4,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$1,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$5,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$8,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$C,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$9,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$D,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$2,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$6,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$3,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$7,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$A,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$E,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$B,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3+$F,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$4,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$1,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$5,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$8,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$C,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$9,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$D,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$2,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$6,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$3,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$7,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$A,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$E,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$B,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2+$F,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$4,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$1,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$5,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$8,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$C,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$9,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$D,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$2,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$6,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$3,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$7,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$A,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$E,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$B,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1+$F,0,0,3,1)
APM_CNZ_End:
; byte_406BE:
APM_CNZ2P: begin_animpat
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$4,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$1,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$5,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$8,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$C,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$9,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$D,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$2,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$6,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$3,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$7,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$A,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$E,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$B,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_1_2p+$F,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$4,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$1,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$5,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$8,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$C,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$9,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$D,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$2,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$6,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$3,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$7,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$A,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$E,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$B,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_2_2p+$F,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$0,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$4,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$1,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$5,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$8,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$C,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$9,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$D,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$2,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$6,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$3,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$7,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$A,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$E,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$B,0,0,0,0),make_block_tile(ArtTile_ArtUnc_CNZSlotPics_3_2p+$F,0,0,0,0)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$4,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$1,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$5,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$8,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$C,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$9,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$D,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$2,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$6,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$3,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$7,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$A,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$E,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$B,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_2_2p+$F,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$0,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$4,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$1,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$5,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$8,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$C,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$9,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$D,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$2,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$6,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$3,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$7,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$A,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$E,0,0,3,1)
dc.w make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$B,0,0,3,1),make_block_tile(ArtTile_ArtUnc_CNZFlipTiles_1_2p+$F,0,0,3,1)
APM_CNZ2P_End:
; byte_40762:
APM_CPZ: begin_animpat
dc.w make_block_tile(ArtTile_ArtUnc_CPZAnimBack+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_CPZAnimBack+$1,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_CPZAnimBack+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_CPZAnimBack+$1,0,0,2,0)
APM_CPZ_End:
; byte_4076E:
APM_DEZ: begin_animpat
dc.w make_block_tile(ArtTile_ArtUnc_DEZAnimBack+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_DEZAnimBack+$1,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_DEZAnimBack+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_DEZAnimBack+$1,0,0,2,0)
APM_DEZ_End:
; byte_4077A:
APM_ARZ: begin_animpat
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall3+$0 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall3+$1 ,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall3+$2 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall3+$3 ,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall2+$0 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall2+$1 ,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall2+$2 ,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall2+$3 ,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$0,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$1,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$2,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$3,0,0,2,1)
;These are invalid animation entries for waterfalls (bug in original game):
if 1==1
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$C,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$D,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$E,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$F,0,0,2,1)
else
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$0,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$1,0,0,2,1)
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$2,0,0,2,1),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$3,0,0,2,1)
endif
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall3+$0 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall3+$1 ,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall3+$2 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall3+$3 ,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall2+$0 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall2+$1 ,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall2+$2 ,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall2+$3 ,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$1,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$2,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall1_1+$3,0,0,2,0)
;These are invalid animation entries for waterfalls (bug in original game):
if 1==1
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$C,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$D,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$E,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$F,0,0,2,0)
else
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$0,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$1,0,0,2,0)
dc.w make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$2,0,0,2,0),make_block_tile(ArtTile_ArtUnc_Waterfall1_2+$3,0,0,2,0)
endif
APM_ARZ_End:
; byte_407BE:
APM_Null: dc.w 0
; ===========================================================================
; loc_407C0:
PatchHTZTiles:
lea (ArtNem_HTZCliffs).l,a0
lea (Object_RAM+$800).w,a4
jsrto (NemDecToRAM).l, JmpTo2_NemDecToRAM
lea (Object_RAM+$800).w,a1
lea_ word_3FD9C,a4
moveq #0,d2
moveq #7,d4
loc_407DA:
moveq #5,d3
loc_407DC:
moveq #-1,d0
move.w (a4)+,d0
movea.l d0,a2
moveq #$1F,d1
loc_407E4:
move.l (a1),(a2)+
move.l d2,(a1)+
dbf d1,loc_407E4
dbf d3,loc_407DC
adda.w #$C,a4
dbf d4,loc_407DA
rts
; ===========================================================================
if gameRevision<2
nop
endif
if ~~removeJmpTos
JmpTo2_NemDecToRAM
jmp (NemDecToRAM).l
align 4
endif
; ---------------------------------------------------------------------------
; Subroutine to draw the HUD
; ---------------------------------------------------------------------------
hud_letter_num_tiles = 2
hud_letter_vdp_delta = vdpCommDelta(tiles_to_bytes(hud_letter_num_tiles))
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_40804:
BuildHUD:
tst.w (Ring_count).w
beq.s ++ ; blink ring count if it's 0
moveq #0,d1
btst #3,(Timer_frames+1).w
bne.s + ; only blink on certain frames
cmpi.b #9,(Timer_minute).w ; should the minutes counter blink?
bne.s + ; if not, branch
addq.w #2,d1 ; set mapping frame time counter blink
+
bra.s ++
+
moveq #0,d1
btst #3,(Timer_frames+1).w
bne.s + ; only blink on certain frames
addq.w #1,d1 ; set mapping frame for ring count blink
cmpi.b #9,(Timer_minute).w
bne.s +
addq.w #2,d1 ; set mapping frame for double blink
+
move.w #128+16,d3 ; set X pos
move.w #128+136,d2 ; set Y pos
lea (HUD_MapUnc_40A9A).l,a1
movea.w #make_art_tile(ArtTile_ArtNem_HUD,0,1),a3 ; set art tile and flags
add.w d1,d1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
bmi.s +
jsrto (DrawSprite_Loop).l, JmpTo_DrawSprite_Loop ; draw frame
+
rts
; End of function BuildHUD
; ===========================================================================
BuildHUD_P1:
tst.w (Ring_count).w
beq.s BuildHUD_P1_NoRings
moveq #0,d1
btst #3,(Timer_frames+1).w
bne.s +
cmpi.b #9,(Timer_minute).w
bne.s +
addq.w #2,d1 ; make TIME flash
+
bra.s BuildHUD_P1_Continued
; ===========================================================================
; loc_40876:
BuildHUD_P1_NoRings:
moveq #0,d1
btst #3,(Timer_frames+1).w
bne.s BuildHUD_P1_Continued
addq.w #1,d1 ; make RINGS flash
cmpi.b #9,(Timer_minute).w
bne.s BuildHUD_P1_Continued
addq.w #2,d1 ; make TIME flash
; loc_4088C:
BuildHUD_P1_Continued:
move.w #$90,d3
move.w #$188,d2
lea (HUD_MapUnc_40BEA).l,a1
movea.w #make_art_tile_2p(ArtTile_Art_HUD_Text_2P,0,1),a3
add.w d1,d1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
jsrto (DrawSprite_2P_Loop).l, JmpTo_DrawSprite_2P_Loop
move.w #$B8,d3
move.w #$108,d2
movea.w #make_art_tile_2p(ArtTile_Art_HUD_Numbers_2P,0,1),a3
moveq #0,d7
move.b (Timer_minute).w,d7
bsr.w sub_4092E
bsr.w sub_4096A
moveq #0,d7
move.b (Timer_second).w,d7
bsr.w loc_40938
move.w #$C0,d3
move.w #$118,d2
movea.w #make_art_tile_2p(ArtTile_Art_HUD_Numbers_2P,0,1),a3
moveq #0,d7
move.w (Ring_count).w,d7
bsr.w sub_40984
tst.b (Update_HUD_timer_2P).w
bne.s +
tst.b (Update_HUD_timer).w
beq.s +
move.w #$110,d3
move.w #$1B8,d2
movea.w #make_art_tile_2p(ArtTile_Art_HUD_Numbers_2P,0,1),a3
moveq #0,d7
move.b (Loser_Time_Left).w,d7
bsr.w loc_40938
+
moveq #4,d1
move.w #$90,d3
move.w #$188,d2
lea (HUD_MapUnc_40BEA).l,a1
movea.w #make_art_tile_2p(ArtTile_Art_HUD_Text_2P,0,1),a3
add.w d1,d1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
jsrto (DrawSprite_2P_Loop).l, JmpTo_DrawSprite_2P_Loop
moveq #0,d4
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_4092E:
lea (Hud_1).l,a4
moveq #0,d6
bra.s loc_40940
; ===========================================================================
loc_40938:
lea (Hud_10).l,a4
moveq #1,d6
loc_40940:
moveq #0,d1
move.l (a4)+,d4
loc_40944:
sub.l d4,d7
bcs.s loc_4094C
addq.w #1,d1
bra.s loc_40944
; ===========================================================================
loc_4094C:
add.l d4,d7
lea (HUD_MapUnc_40C82).l,a1
add.w d1,d1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
jsrto (DrawSprite_2P_Loop).l, JmpTo_DrawSprite_2P_Loop
addq.w #8,d3
dbf d6,loc_40940
rts
; End of function sub_4092E
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_4096A:
moveq #$A,d1
lea (HUD_MapUnc_40C82).l,a1
add.w d1,d1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
jsrto (DrawSprite_2P_Loop).l, JmpTo_DrawSprite_2P_Loop
addq.w #8,d3
rts
; End of function sub_4096A
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_40984:
lea (Hud_100).l,a4
moveq #2,d6
loc_4098C:
moveq #0,d1
move.l (a4)+,d4
loc_40990:
sub.l d4,d7
bcs.s loc_40998
addq.w #1,d1
bra.s loc_40990
; ===========================================================================
loc_40998:
add.l d4,d7
tst.w d6
beq.s loc_409AA
tst.w d1
beq.s loc_409A6
bset #$1F,d6
loc_409A6:
tst.l d6
bpl.s loc_409BE
loc_409AA:
lea (HUD_MapUnc_40C82).l,a1
add.w d1,d1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
jsrto (DrawSprite_2P_Loop).l, JmpTo_DrawSprite_2P_Loop
loc_409BE:
addq.w #8,d3
dbf d6,loc_4098C
rts
; End of function sub_40984
; ===========================================================================
BuildHUD_P2:
tst.w (Ring_count_2P).w
beq.s BuildHUD_P2_NoRings
moveq #0,d1
btst #3,(Timer_frames+1).w
bne.s +
cmpi.b #9,(Timer_minute_2P).w
bne.s +
addq.w #2,d1
+
bra.s BuildHUD_P2_Continued
; ===========================================================================
; loc_409E2:
BuildHUD_P2_NoRings:
moveq #0,d1
btst #3,(Timer_frames+1).w
bne.s BuildHUD_P2_Continued
addq.w #1,d1
cmpi.b #9,(Timer_minute_2P).w
bne.s BuildHUD_P2_Continued
addq.w #2,d1
; loc_409F8:
BuildHUD_P2_Continued:
move.w #$90,d3
move.w #$268,d2
lea (HUD_MapUnc_40BEA).l,a1
movea.w #make_art_tile_2p(ArtTile_Art_HUD_Text_2P,0,1),a3
add.w d1,d1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
jsrto (DrawSprite_2P_Loop).l, JmpTo_DrawSprite_2P_Loop
move.w #$B8,d3
move.w #$1E8,d2
movea.w #make_art_tile_2p(ArtTile_Art_HUD_Numbers_2P,0,1),a3
moveq #0,d7
move.b (Timer_minute_2P).w,d7
bsr.w sub_4092E
bsr.w sub_4096A
moveq #0,d7
move.b (Timer_second_2P).w,d7
bsr.w loc_40938
move.w #$C0,d3
move.w #$1F8,d2
movea.w #make_art_tile_2p(ArtTile_Art_HUD_Numbers_2P,0,1),a3
moveq #0,d7
move.w (Ring_count_2P).w,d7
bsr.w sub_40984
tst.b (Update_HUD_timer).w
bne.s +
tst.b (Update_HUD_timer_2P).w
beq.s +
move.w #$110,d3
move.w #$298,d2
movea.w #make_art_tile_2p(ArtTile_Art_HUD_Numbers_2P,0,1),a3
moveq #0,d7
move.b (Loser_Time_Left).w,d7
bsr.w loc_40938
+
moveq #5,d1
move.w #$90,d3
move.w #$268,d2
lea (HUD_MapUnc_40BEA).l,a1
movea.w #make_art_tile_2p(ArtTile_ArtNem_Powerups,0,1),a3
add.w d1,d1
adda.w (a1,d1.w),a1
move.w (a1)+,d1
subq.w #1,d1
jsrto (DrawSprite_2P_Loop).l, JmpTo_DrawSprite_2P_Loop
moveq #0,d4
rts
; ===========================================================================
; sprite mappings for the HUD
; uses the art in VRAM from $D940 - $FC00
HUD_MapUnc_40A9A: BINCLUDE "mappings/sprite/hud_a.bin"
HUD_MapUnc_40BEA: BINCLUDE "mappings/sprite/hud_b.bin"
HUD_MapUnc_40C82: BINCLUDE "mappings/sprite/hud_c.bin"
; ---------------------------------------------------------------------------
; Add points subroutine
; subroutine to add to Player 1's score
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_40D06:
AddPoints:
move.b #1,(Update_HUD_score).w
lea (Score).w,a3
add.l d0,(a3) ; add d0*10 to the score
move.l #999999,d1
cmp.l (a3),d1 ; is #999999 higher than the score?
bhi.s + ; if yes, branch
move.l d1,(a3) ; set score to #999999
+
move.l (a3),d0
cmp.l (Next_Extra_life_score).w,d0
blo.s + ; rts
addi.l #5000,(Next_Extra_life_score).w
addq.b #1,(Life_count).w
addq.b #1,(Update_HUD_lives).w
move.w #MusID_ExtraLife,d0
jmp (PlayMusic).l
; ===========================================================================
+ rts
; End of function AddPoints
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; ---------------------------------------------------------------------------
; Add points subroutine
; subroutine to add to Player 2's score
; (goes to AddPoints to add to Player 1's score instead if this is not Player 2)
; ---------------------------------------------------------------------------
; sub_40D42:
AddPoints2:
tst.w (Two_player_mode).w
beq.s AddPoints
cmpa.w #MainCharacter,a3
beq.s AddPoints
move.b #1,(Update_HUD_score_2P).w
lea (Score_2P).w,a3
add.l d0,(a3) ; add d0*10 to the score
move.l #999999,d1
cmp.l (a3),d1 ; is #999999 higher than the score?
bhi.s + ; if yes, branch
move.l d1,(a3) ; set score to #999999
+
move.l (a3),d0
cmp.l (Next_Extra_life_score_2P).w,d0
blo.s + ; rts
addi.l #5000,(Next_Extra_life_score_2P).w
addq.b #1,(Life_count_2P).w
addq.b #1,(Update_HUD_lives_2P).w
move.w #MusID_ExtraLife,d0
jmp (PlayMusic).l
; ===========================================================================
+ rts
; End of function AddPoints2
; ---------------------------------------------------------------------------
; Subroutine to update the HUD
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_40D8A:
HudUpdate:
nop
lea (VDP_data_port).l,a6
tst.w (Two_player_mode).w
bne.w loc_40F50
tst.w (Debug_mode_flag).w ; is debug mode on?
bne.w loc_40E9A ; if yes, branch
tst.b (Update_HUD_score).w ; does the score need updating?
beq.s Hud_ChkRings ; if not, branch
clr.b (Update_HUD_score).w
move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Score),VRAM,WRITE),d0 ; set VRAM address
move.l (Score).w,d1 ; load score
bsr.w Hud_Score
; loc_40DBA:
Hud_ChkRings:
tst.b (Update_HUD_rings).w ; does the ring counter need updating?
beq.s Hud_ChkTime ; if not, branch
bpl.s loc_40DC6
bsr.w Hud_InitRings
loc_40DC6:
clr.b (Update_HUD_rings).w
move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Rings),VRAM,WRITE),d0
moveq #0,d1
move.w (Ring_count).w,d1
bsr.w Hud_Rings
; loc_40DDA:
Hud_ChkTime:
tst.b (Update_HUD_timer).w ; does the time need updating?
beq.s Hud_ChkLives ; if not, branch
tst.w (Game_paused).w ; is the game paused?
bne.s Hud_ChkLives ; if yes, branch
lea (Timer).w,a1
cmpi.l #$93B3B,(a1)+ ; is the time 9.59?
beq.w loc_40E84 ; if yes, branch
addq.b #1,-(a1)
cmpi.b #60,(a1)
blo.s Hud_ChkLives
move.b #0,(a1)
addq.b #1,-(a1)
cmpi.b #60,(a1)
blo.s +
move.b #0,(a1)
addq.b #1,-(a1)
cmpi.b #9,(a1)
blo.s +
move.b #9,(a1)
+
move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Minutes),VRAM,WRITE),d0
moveq #0,d1
move.b (Timer_minute).w,d1
bsr.w Hud_Mins
move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Seconds),VRAM,WRITE),d0
moveq #0,d1
move.b (Timer_second).w,d1
bsr.w Hud_Secs
; loc_40E38:
Hud_ChkLives:
tst.b (Update_HUD_lives).w ; does the lives counter need updating?
beq.s Hud_ChkBonus ; if not, branch
clr.b (Update_HUD_lives).w
bsr.w Hud_Lives
; loc_40E46:
Hud_ChkBonus:
tst.b (Update_Bonus_score).w ; do time/ring bonus counters need updating?
beq.s Hud_End ; if not, branch
clr.b (Update_Bonus_score).w
move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Bonus_Score),VRAM,WRITE),(VDP_control_port).l
moveq #0,d1
move.w (Total_Bonus_Countdown).w,d1
bsr.w Hud_TimeRingBonus
moveq #0,d1
move.w (Bonus_Countdown_1).w,d1 ; load time bonus
bsr.w Hud_TimeRingBonus
moveq #0,d1
move.w (Bonus_Countdown_2).w,d1 ; load ring bonus
bsr.w Hud_TimeRingBonus
moveq #0,d1
move.w (Bonus_Countdown_3).w,d1 ; load perfect bonus
bsr.w Hud_TimeRingBonus
; return_40E82:
Hud_End:
rts
; ===========================================================================
loc_40E84:
clr.b (Update_HUD_timer).w
lea (MainCharacter).w,a0 ; a0=character
movea.l a0,a2
bsr.w KillCharacter
move.b #1,(Time_Over_flag).w
rts
; ===========================================================================
loc_40E9A:
bsr.w HudDb_XY
tst.b (Update_HUD_rings).w
beq.s loc_40EBE
bpl.s loc_40EAA
bsr.w Hud_InitRings
loc_40EAA:
clr.b (Update_HUD_rings).w
move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Rings),VRAM,WRITE),d0
moveq #0,d1
move.w (Ring_count).w,d1
bsr.w Hud_Rings
loc_40EBE:
move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Seconds),VRAM,WRITE),d0
moveq #0,d1
move.b (Sprite_count).w,d1
bsr.w Hud_Secs
tst.b (Update_HUD_lives).w
beq.s loc_40EDC
clr.b (Update_HUD_lives).w
bsr.w Hud_Lives
loc_40EDC:
tst.b (Update_Bonus_score).w
beq.s loc_40F18
clr.b (Update_Bonus_score).w
move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Bonus_Score),VRAM,WRITE),(VDP_control_port).l
moveq #0,d1
move.w (Total_Bonus_Countdown).w,d1
bsr.w Hud_TimeRingBonus
moveq #0,d1
move.w (Bonus_Countdown_1).w,d1
bsr.w Hud_TimeRingBonus
moveq #0,d1
move.w (Bonus_Countdown_2).w,d1
bsr.w Hud_TimeRingBonus
moveq #0,d1
move.w (Bonus_Countdown_3).w,d1
bsr.w Hud_TimeRingBonus
loc_40F18:
tst.w (Game_paused).w
bne.s return_40F4E
lea (Timer).w,a1
cmpi.l #$93B3B,(a1)+
nop
addq.b #1,-(a1)
cmpi.b #$3C,(a1)
blo.s return_40F4E
move.b #0,(a1)
addq.b #1,-(a1)
cmpi.b #$3C,(a1)
blo.s return_40F4E
move.b #0,(a1)
addq.b #1,-(a1)
cmpi.b #9,(a1)
blo.s return_40F4E
move.b #9,(a1)
return_40F4E:
rts
; ===========================================================================
loc_40F50:
tst.w (Game_paused).w
bne.w return_4101A
tst.b (Update_HUD_timer).w
beq.s loc_40F90
lea (Timer).w,a1
cmpi.l #$93B3B,(a1)+
beq.w TimeOver
addq.b #1,-(a1)
cmpi.b #$3C,(a1)
blo.s loc_40F90
move.b #0,(a1)
addq.b #1,-(a1)
cmpi.b #$3C,(a1)
blo.s loc_40F90
move.b #0,(a1)
addq.b #1,-(a1)
cmpi.b #9,(a1)
blo.s loc_40F90
move.b #9,(a1)
loc_40F90:
tst.b (Update_HUD_timer_2P).w
beq.s loc_40FC8
lea (Timer_2P).w,a1
cmpi.l #$93B3B,(a1)+
beq.w TimeOver2
addq.b #1,-(a1)
cmpi.b #$3C,(a1)
blo.s loc_40FC8
move.b #0,(a1)
addq.b #1,-(a1)
cmpi.b #$3C,(a1)
blo.s loc_40FC8
move.b #0,(a1)
addq.b #1,-(a1)
cmpi.b #9,(a1)
blo.s loc_40FC8
move.b #9,(a1)
loc_40FC8:
tst.b (Update_HUD_lives).w
beq.s loc_40FD6
clr.b (Update_HUD_lives).w
bsr.w Hud_Lives
loc_40FD6:
tst.b (Update_HUD_lives_2P).w
beq.s loc_40FE4
clr.b (Update_HUD_lives_2P).w
bsr.w Hud_Lives2
loc_40FE4:
move.b (Update_HUD_timer).w,d0
or.b (Update_HUD_timer_2P).w,d0
beq.s return_4101A
lea (Loser_Time_Left).w,a1
tst.w (a1)+
beq.s return_4101A
subq.b #1,-(a1)
bhi.s return_4101A
move.b #$3C,(a1)
cmpi.b #$C,-1(a1)
bne.s loc_41010
move.w #MusID_Countdown,d0
jsr (PlayMusic).l
loc_41010:
subq.b #1,-(a1)
bcc.s return_4101A
move.w #0,(a1)
bsr.s TimeOver0
return_4101A:
rts
; End of function HudUpdate
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_4101C:
TimeOver0:
tst.b (Update_HUD_timer).w
bne.s TimeOver
tst.b (Update_HUD_timer_2P).w
bne.s TimeOver2
rts
; ===========================================================================
; loc_4102A:
TimeOver:
clr.b (Update_HUD_timer).w
lea (MainCharacter).w,a0 ; a0=character
movea.l a0,a2
bsr.w KillCharacter
move.b #1,(Time_Over_flag).w
tst.b (Update_HUD_timer_2P).w
beq.s + ; rts
; loc_41044:
TimeOver2:
clr.b (Update_HUD_timer_2P).w
lea (Sidekick).w,a0 ; a0=character
movea.l a0,a2
bsr.w KillCharacter
move.b #1,(Time_Over_flag_2P).w
+
rts
; End of function TimeOver0
; ---------------------------------------------------------------------------
; Subroutine to initialize ring counter on the HUD
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_4105A:
; Hud_LoadZero:
Hud_InitRings:
move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Rings),VRAM,WRITE),(VDP_control_port).l
lea Hud_TilesRings(pc),a2
move.w #(Hud_TilesBase_End-Hud_TilesRings)-1,d2
bra.s loc_41090
; ---------------------------------------------------------------------------
; Subroutine to load uncompressed HUD patterns ("E", "0", colon)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; loc_4106E:
Hud_Base:
lea (VDP_data_port).l,a6
bsr.w Hud_Lives
tst.w (Two_player_mode).w
bne.s loc_410BC
move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Score_E),VRAM,WRITE),(VDP_control_port).l
lea Hud_TilesBase(pc),a2
move.w #(Hud_TilesBase_End-Hud_TilesBase)-1,d2
loc_41090:
lea Art_Hud(pc),a1
loc_41094:
move.w #8*hud_letter_num_tiles-1,d1
move.b (a2)+,d0
bmi.s loc_410B0
ext.w d0
lsl.w #5,d0
lea (a1,d0.w),a3
loc_410A4:
move.l (a3)+,(a6)
dbf d1,loc_410A4
loc_410AA:
dbf d2,loc_41094
rts
; ===========================================================================
loc_410B0:
move.l #0,(a6)
dbf d1,loc_410B0
bra.s loc_410AA
; End of function Hud_Base
; ===========================================================================
loc_410BC:
bsr.w Hud_Lives2
move.l #Art_Hud,d1 ; source addreses
move.w #tiles_to_bytes(ArtTile_Art_HUD_Numbers_2P),d2 ; destination VRAM address
move.w #$160,d3 ; DMA transfer length
jmp (QueueDMATransfer).l
; ===========================================================================
charset ' ',$FF
charset '0',0
charset '1',2
charset '2',4
charset '3',6
charset '4',8
charset '5',$A
charset '6',$C
charset '7',$E
charset '8',$10
charset '9',$12
charset ':',$14
charset 'E',$16
; byte_410D4:
Hud_TilesBase:
dc.b "E 0"
dc.b "0:00"
; byte_410E0:
; Hud_TilesZero:
Hud_TilesRings:
dc.b " 0"
Hud_TilesBase_End
charset
even
; ---------------------------------------------------------------------------
; Subroutine to load debug mode numbers patterns
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_410E4:
HudDb_XY:
move.l #vdpComm(tiles_to_bytes(ArtTile_HUD_Score_E),VRAM,WRITE),(VDP_control_port).l
move.w (Camera_X_pos).w,d1
swap d1
move.w (MainCharacter+x_pos).w,d1
bsr.s HudDb_XY2
move.w (Camera_Y_pos).w,d1
swap d1
move.w (MainCharacter+y_pos).w,d1
; loc_41104:
HudDb_XY2:
moveq #7,d6
lea (Art_Text).l,a1
; loc_4110C:
HudDb_XYLoop:
rol.w #4,d1
move.w d1,d2
andi.w #$F,d2
cmpi.w #$A,d2
blo.s loc_4111E
addi_.w #7,d2
loc_4111E:
lsl.w #5,d2
lea (a1,d2.w),a3
rept 8
move.l (a3)+,(a6)
endm
swap d1
dbf d6,HudDb_XYLoop
rts
; End of function HudDb_XY
; ---------------------------------------------------------------------------
; Subroutine to load rings numbers patterns
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_4113C:
Hud_Rings:
lea (Hud_100).l,a2
moveq #2,d6
bra.s Hud_LoadArt
; End of function Hud_Rings
; ---------------------------------------------------------------------------
; Subroutine to load score numbers patterns
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_41146:
Hud_Score:
lea (Hud_100000).l,a2
moveq #5,d6
; loc_4114E:
Hud_LoadArt:
moveq #0,d4
lea Art_Hud(pc),a1
; loc_41154:
Hud_ScoreLoop:
moveq #0,d2
move.l (a2)+,d3
loc_41158:
sub.l d3,d1
bcs.s loc_41160
addq.w #1,d2
bra.s loc_41158
; ===========================================================================
loc_41160:
add.l d3,d1
tst.w d2
beq.s loc_4116A
move.w #1,d4
loc_4116A:
tst.w d4
beq.s loc_41198
lsl.w #6,d2
move.l d0,4(a6)
lea (a1,d2.w),a3
rept 8*hud_letter_num_tiles
move.l (a3)+,(a6)
endm
loc_41198:
addi.l #hud_letter_vdp_delta,d0
dbf d6,Hud_ScoreLoop
rts
; End of function Hud_Score
; ---------------------------------------------------------------------------
; Subroutine to load countdown numbers on the continue screen
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_411A4:
ContScrCounter:
move.l #vdpComm(tiles_to_bytes(ArtTile_ContinueCountdown),VRAM,WRITE),(VDP_control_port).l
lea (VDP_data_port).l,a6
lea (Hud_10).l,a2
moveq #1,d6
moveq #0,d4
lea Art_Hud(pc),a1
; loc_411C2:
ContScr_Loop:
moveq #0,d2
move.l (a2)+,d3
loc_411C6:
sub.l d3,d1
bcs.s loc_411CE
addq.w #1,d2
bra.s loc_411C6
; ===========================================================================
loc_411CE:
add.l d3,d1
lsl.w #6,d2
lea (a1,d2.w),a3
rept 16
move.l (a3)+,(a6)
endm
dbf d6,ContScr_Loop ; repeat 1 more time
rts
; End of function ContScrCounter
; ===========================================================================
; ---------------------------------------------------------------------------
; for HUD counter
; ---------------------------------------------------------------------------
; byte_411FC:
Hud_100000: dc.l 100000 ; byte_41200: ; Hud_10000:
dc.l 10000 ; byte_41204:
Hud_1000: dc.l 1000 ; byte_41208:
Hud_100: dc.l 100 ; byte_4120C:
Hud_10: dc.l 10 ; byte_41210:
Hud_1: dc.l 1
; ---------------------------------------------------------------------------
; Subroutine to load time numbers patterns
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_41214:
Hud_Mins:
lea_ Hud_1,a2
moveq #0,d6
bra.s loc_41222
; ===========================================================================
; loc_4121C:
Hud_Secs:
lea_ Hud_10,a2
moveq #1,d6
loc_41222:
moveq #0,d4
lea Art_Hud(pc),a1
; loc_41228:
Hud_TimeLoop:
moveq #0,d2
move.l (a2)+,d3
loc_4122C:
sub.l d3,d1
bcs.s loc_41234
addq.w #1,d2
bra.s loc_4122C
; ===========================================================================
loc_41234:
add.l d3,d1
tst.w d2
beq.s loc_4123E
move.w #1,d4
loc_4123E:
lsl.w #6,d2
move.l d0,4(a6)
lea (a1,d2.w),a3
rept 8*hud_letter_num_tiles
move.l (a3)+,(a6)
endm
addi.l #hud_letter_vdp_delta,d0
dbf d6,Hud_TimeLoop
rts
; End of function Hud_Mins
; ---------------------------------------------------------------------------
; Subroutine to load time/ring bonus numbers patterns
; ---------------------------------------------------------------------------
; ===========================================================================
; loc_41274:
Hud_TimeRingBonus:
lea_ Hud_1000,a2
moveq #3,d6
moveq #0,d4
lea Art_Hud(pc),a1
; loc_41280:
Hud_BonusLoop:
moveq #0,d2
move.l (a2)+,d3
loc_41284:
sub.l d3,d1
bcs.s loc_4128C
addq.w #1,d2
bra.s loc_41284
; ===========================================================================
loc_4128C:
add.l d3,d1
tst.w d2
beq.s loc_41296
move.w #1,d4
loc_41296:
tst.w d4
beq.s Hud_ClrBonus
lsl.w #6,d2
lea (a1,d2.w),a3
rept 8*hud_letter_num_tiles
move.l (a3)+,(a6)
endm
loc_412C0:
dbf d6,Hud_BonusLoop ; repeat 3 more times
rts
; ===========================================================================
; loc_412C6:
Hud_ClrBonus:
moveq #8*hud_letter_num_tiles-1,d5
; loc_412C8:
Hud_ClrBonusLoop:
move.l #0,(a6)
dbf d5,Hud_ClrBonusLoop
bra.s loc_412C0
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; ---------------------------------------------------------------------------
; Subroutine to load uncompressed lives counter patterns (Sonic)
; ---------------------------------------------------------------------------
; sub_412D4:
Hud_Lives2:
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtUnc_2p_life_counter_lives),VRAM,WRITE),d0
moveq #0,d1
move.b (Life_count_2P).w,d1
bra.s loc_412EE
; End of function Hud_Lives2
; ---------------------------------------------------------------------------
; Subroutine to load uncompressed lives counter patterns (Tails)
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_412E2:
Hud_Lives:
move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_life_counter_lives),VRAM,WRITE),d0
moveq #0,d1
move.b (Life_count).w,d1
loc_412EE:
lea_ Hud_10,a2
moveq #1,d6
moveq #0,d4
lea Art_LivesNums(pc),a1
; loc_412FA:
Hud_LivesLoop:
move.l d0,4(a6)
moveq #0,d2
move.l (a2)+,d3
- sub.l d3,d1
bcs.s loc_4130A
addq.w #1,d2
bra.s -
; ===========================================================================
loc_4130A:
add.l d3,d1
tst.w d2
beq.s loc_41314
move.w #1,d4
loc_41314:
tst.w d4
beq.s Hud_ClrLives
loc_41318:
lsl.w #5,d2
lea (a1,d2.w),a3
rept 8
move.l (a3)+,(a6)
endm
loc_4132E:
addi.l #hud_letter_vdp_delta,d0
dbf d6,Hud_LivesLoop ; repeat 1 more time
rts
; ===========================================================================
; loc_4133A:
Hud_ClrLives:
tst.w d6
beq.s loc_41318
moveq #7,d5
; loc_41340:
Hud_ClrLivesLoop:
move.l #0,(a6)
dbf d5,Hud_ClrLivesLoop
bra.s loc_4132E
; End of function Hud_Lives
; ===========================================================================
; ArtUnc_4134C:
Art_Hud: BINCLUDE "art/uncompressed/Big and small numbers used on counters - 1.bin"
; ArtUnc_4164C:
Art_LivesNums: BINCLUDE "art/uncompressed/Big and small numbers used on counters - 2.bin"
; ArtUnc_4178C:
Art_Text: BINCLUDE "art/uncompressed/Big and small numbers used on counters - 3.bin"
if ~~removeJmpTos
JmpTo_DrawSprite_2P_Loop
jmp (DrawSprite_2P_Loop).l
JmpTo_DrawSprite_Loop
jmp (DrawSprite_Loop).l
align 4
endif
; ===========================================================================
; ---------------------------------------------------------------------------
; When debug mode is currently in use
; ---------------------------------------------------------------------------
; loc_41A78:
DebugMode:
moveq #0,d0
move.b (Debug_placement_mode).w,d0
move.w Debug_Index(pc,d0.w),d1
jmp Debug_Index(pc,d1.w)
; ===========================================================================
; off_41A86:
Debug_Index: offsetTable
offsetTableEntry.w Debug_Init ; 0
offsetTableEntry.w Debug_Main ; 2
; ===========================================================================
; loc_41A8A: Debug_Main:
Debug_Init:
addq.b #2,(Debug_placement_mode).w
move.w (Camera_Min_Y_pos).w,(Camera_Min_Y_pos_Debug_Copy).w
move.w (Camera_Max_Y_pos).w,(Camera_Max_Y_pos_Debug_Copy).w
cmpi.b #sky_chase_zone,(Current_Zone).w
bne.s +
move.w #0,(Camera_Min_X_pos).w
move.w #$3FFF,(Camera_Max_X_pos).w
+
andi.w #$7FF,(MainCharacter+y_pos).w
andi.w #$7FF,(Camera_Y_pos).w
andi.w #$7FF,(Camera_BG_Y_pos).w
clr.b (Scroll_lock).w
move.b #0,mapping_frame(a0)
move.b #AniIDSonAni_Walk,anim(a0)
; S1 leftover
cmpi.b #GameModeID_SpecialStage,(Game_Mode).w ; special stage mode? (you can't enter debug mode in S2's special stage)
bne.s .islevel ; if not, branch
moveq #6,d0 ; force zone 6's debug object list (was the ending in S1)
bra.s .selectlist
; ===========================================================================
.islevel:
moveq #0,d0
move.b (Current_Zone).w,d0
.selectlist:
lea (JmpTbl_DbgObjLists).l,a2
add.w d0,d0
adda.w (a2,d0.w),a2
move.w (a2)+,d6
cmp.b (Debug_object).w,d6
bhi.s +
move.b #0,(Debug_object).w
+
bsr.w LoadDebugObjectSprite
move.b #$C,(Debug_Accel_Timer).w
move.b #1,(Debug_Speed).w
; loc_41B0C:
Debug_Main:
; S1 leftover
moveq #6,d0 ; force zone 6's debug object list (was the ending in S1)
cmpi.b #GameModeID_SpecialStage,(Game_Mode).w ; special stage mode? (you can't enter debug mode in S2's special stage)
beq.s .isntlevel ; if yes, branch
moveq #0,d0
move.b (Current_Zone).w,d0
.isntlevel:
lea (JmpTbl_DbgObjLists).l,a2
add.w d0,d0
adda.w (a2,d0.w),a2
move.w (a2)+,d6
bsr.w Debug_Control
jmp (DisplaySprite).l
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_41B34:
Debug_Control:
;Debug_ControlMovement:
moveq #0,d4
move.w #1,d1
move.b (Ctrl_1_Press).w,d4
andi.w #button_up_mask|button_down_mask|button_left_mask|button_right_mask,d4
bne.s Debug_Move
move.b (Ctrl_1_Held).w,d0
andi.w #button_up_mask|button_down_mask|button_left_mask|button_right_mask,d0
bne.s Debug_ContinueMoving
move.b #$C,(Debug_Accel_Timer).w
move.b #$F,(Debug_Speed).w
bra.w Debug_ControlObjects
; ===========================================================================
; loc_41B5E:
Debug_ContinueMoving:
subq.b #1,(Debug_Accel_Timer).w
bne.s Debug_TimerNotOver
move.b #1,(Debug_Accel_Timer).w
addq.b #1,(Debug_Speed).w
bne.s Debug_Move
move.b #-1,(Debug_Speed).w
; loc_41B76:
Debug_Move:
move.b (Ctrl_1_Held).w,d4
; loc_41B7A:
Debug_TimerNotOver:
moveq #0,d1
move.b (Debug_Speed).w,d1
addq.w #1,d1
swap d1
asr.l #4,d1
move.l y_pos(a0),d2
move.l x_pos(a0),d3
; Move up
btst #button_up,d4
beq.s .upNotHeld
sub.l d1,d2
moveq #0,d0
move.w (Camera_Min_Y_pos).w,d0
swap d0
cmp.l d0,d2
bge.s .minYPosNotReached
move.l d0,d2
.minYPosNotReached:
; loc_41BA4:
.upNotHeld:
; Move down
btst #button_down,d4
beq.s .downNotHeld
add.l d1,d2
moveq #0,d0
move.w (Camera_Max_Y_pos).w,d0
addi.w #224-1,d0
swap d0
cmp.l d0,d2
blt.s .maxYPosNotReached
move.l d0,d2
.maxYPosNotReached:
; loc_41BBE:
.downNotHeld:
; Move left
btst #button_left,d4
beq.s .leftNotHeld
sub.l d1,d3
bcc.s .minXPosNotReached
moveq #0,d3
.minXPosNotReached:
; loc_41BCA:
.leftNotHeld:
; Move right
btst #button_right,d4
beq.s .rightNotHeld
add.l d1,d3
; loc_41BD2:
.rightNotHeld:
move.l d2,y_pos(a0)
move.l d3,x_pos(a0)
; loc_41BDA:
Debug_ControlObjects:
;Debug_CycleObjectsBackwards:
btst #button_A,(Ctrl_1_Held).w
beq.s Debug_SpawnObject
btst #button_C,(Ctrl_1_Press).w
beq.s Debug_CycleObjects
; Cycle backwards though object list
subq.b #1,(Debug_object).w
bcc.s BranchTo_LoadDebugObjectSprite
add.b d6,(Debug_object).w
bra.s BranchTo_LoadDebugObjectSprite
; ===========================================================================
; loc_41BF6:
Debug_CycleObjects:
btst #button_A,(Ctrl_1_Press).w
beq.s Debug_SpawnObject
; Cycle forwards though object list
addq.b #1,(Debug_object).w
cmp.b (Debug_object).w,d6
bhi.s BranchTo_LoadDebugObjectSprite
move.b #0,(Debug_object).w
BranchTo_LoadDebugObjectSprite
bra.w LoadDebugObjectSprite
; ===========================================================================
; loc_41C12:
Debug_SpawnObject:
btst #button_C,(Ctrl_1_Press).w
beq.s Debug_ExitDebugMode
; Spawn object
jsr (SingleObjLoad).l
bne.s Debug_ExitDebugMode
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
_move.b mappings(a0),id(a1) ; load obj
move.b render_flags(a0),render_flags(a1)
move.b render_flags(a0),status(a1)
andi.b #$7F,status(a1)
moveq #0,d0
move.b (Debug_object).w,d0
lsl.w #3,d0
move.b 4(a2,d0.w),subtype(a1)
rts
; ===========================================================================
; loc_41C56:
Debug_ExitDebugMode:
btst #button_B,(Ctrl_1_Press).w
beq.s return_41CB6
; Exit debug mode
moveq #0,d0
move.w d0,(Debug_placement_mode).w
lea (MainCharacter).w,a1 ; a1=character
move.l #Mapunc_Sonic,mappings(a1)
move.w #make_art_tile(ArtTile_ArtUnc_Sonic,0,0),art_tile(a1)
tst.w (Two_player_mode).w
beq.s .notTwoPlayerMode
move.w #make_art_tile_2p(ArtTile_ArtUnc_Sonic,0,0),art_tile(a1)
; loc_41C82:
.notTwoPlayerMode:
bsr.s sub_41CB8
move.b #$13,y_radius(a1)
move.b #9,x_radius(a1)
move.w (Camera_Min_Y_pos_Debug_Copy).w,(Camera_Min_Y_pos).w
move.w (Camera_Max_Y_pos_Debug_Copy).w,(Camera_Max_Y_pos).w
; useless leftover; this is for S1's special stage
cmpi.b #GameModeID_SpecialStage,(Game_Mode).w ; special stage mode?
bne.s return_41CB6 ; if not, branch
move.b #AniIDSonAni_Roll,(MainCharacter+anim).w
bset #2,(MainCharacter+status).w
bset #1,(MainCharacter+status).w
return_41CB6:
rts
; End of function Debug_Control
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_41CB8:
move.b d0,anim(a1)
move.w d0,2+x_pos(a1) ; subpixel x
move.w d0,2+y_pos(a1) ; subpixel y
move.b d0,obj_control(a1)
move.b d0,spindash_flag(a1)
move.w d0,x_vel(a1)
move.w d0,y_vel(a1)
move.w d0,inertia(a1)
move.b #2,status(a1)
move.b #2,routine(a1)
move.b #0,routine_secondary(a1)
rts
; End of function sub_41CB8
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; sub_41CEC:
LoadDebugObjectSprite:
moveq #0,d0
move.b (Debug_object).w,d0
lsl.w #3,d0
move.l (a2,d0.w),mappings(a0)
move.w 6(a2,d0.w),art_tile(a0)
move.b 5(a2,d0.w),mapping_frame(a0)
jsrto (Adjust2PArtPointer).l, JmpTo66_Adjust2PArtPointer
rts
; End of function LoadDebugObjectSprite
; ===========================================================================
; ---------------------------------------------------------------------------
; OBJECT DEBUG LISTS
; The jump table goes by level ID, so Metropolis Zone's list is repeated to
; account for its third act. Hidden Palace Zone uses Oil Ocean Zone's list.
; ---------------------------------------------------------------------------
JmpTbl_DbgObjLists: zoneOrderedOffsetTable 2,1
zoneOffsetTableEntry.w DbgObjList_EHZ ; 0
zoneOffsetTableEntry.w DbgObjList_Def ; 1
zoneOffsetTableEntry.w DbgObjList_Def ; 2
zoneOffsetTableEntry.w DbgObjList_Def ; 3
zoneOffsetTableEntry.w DbgObjList_MTZ ; 4
zoneOffsetTableEntry.w DbgObjList_MTZ ; 5
zoneOffsetTableEntry.w DbgObjList_WFZ ; 6
zoneOffsetTableEntry.w DbgObjList_HTZ ; 7
zoneOffsetTableEntry.w DbgObjList_HPZ ; 8
zoneOffsetTableEntry.w DbgObjList_Def ; 9
zoneOffsetTableEntry.w DbgObjList_OOZ ; $A
zoneOffsetTableEntry.w DbgObjList_MCZ ; $B
zoneOffsetTableEntry.w DbgObjList_CNZ ; $C
zoneOffsetTableEntry.w DbgObjList_CPZ ; $D
zoneOffsetTableEntry.w DbgObjList_Def ; $E
zoneOffsetTableEntry.w DbgObjList_ARZ ; $F
zoneOffsetTableEntry.w DbgObjList_SCZ ; $10
zoneTableEnd
; macro for a debug object list header
; must be on the same line as a label that has a corresponding _End label later
dbglistheader macro {INTLABEL}
__LABEL__ label *
dc.w ((__LABEL___End - __LABEL__ - 2) >> 3)
endm
; macro to define debug list object data
dbglistobj macro obj, mapaddr, subtype, frame, vram
dc.l obj<<24|mapaddr
dc.b subtype,frame
dc.w vram
endm
DbgObjList_Def: dbglistheader
dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0) ; obj25 = ring
dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0) ; obj26 = monitor
DbgObjList_Def_End
DbgObjList_EHZ: dbglistheader
dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0)
dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0)
dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, 9, 1, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_EHZWaterfall, Obj49_MapUnc_20C50, 0, 0, make_art_tile(ArtTile_ArtNem_Waterfall,1,0)
dbglistobj ObjID_EHZWaterfall, Obj49_MapUnc_20C50, 2, 3, make_art_tile(ArtTile_ArtNem_Waterfall,1,0)
dbglistobj ObjID_EHZWaterfall, Obj49_MapUnc_20C50, 4, 5, make_art_tile(ArtTile_ArtNem_Waterfall,1,0)
dbglistobj ObjID_EHZPlatform, Obj18_MapUnc_107F6, 1, 0, make_art_tile(ArtTile_ArtKos_LevelArt,2,0)
dbglistobj ObjID_EHZPlatform, Obj18_MapUnc_107F6, $9A, 1, make_art_tile(ArtTile_ArtKos_LevelArt,2,0)
dbglistobj ObjID_Spikes, Obj36_MapUnc_15B68, 0, 0, make_art_tile(ArtTile_ArtNem_Spikes,1,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $81, 0, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $90, 3, make_art_tile(ArtTile_ArtNem_HrzntlSprng,0,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $A0, 6, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $30, 7, make_art_tile(ArtTile_ArtNem_DignlSprng,0,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $40, $A, make_art_tile(ArtTile_ArtNem_DignlSprng,0,0)
dbglistobj ObjID_Buzzer, Obj4B_MapUnc_2D2EA, 0, 0, make_art_tile(ArtTile_ArtNem_Buzzer,0,0)
dbglistobj ObjID_Masher, Obj5C_MapUnc_2D442, 0, 0, make_art_tile(ArtTile_ArtNem_Masher,0,0)
dbglistobj ObjID_Coconuts, Obj9D_Obj98_MapUnc_37D96, $1E, 0, make_art_tile(ArtTile_ArtNem_Coconuts,0,0)
dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0)
DbgObjList_EHZ_End
DbgObjList_MTZ: dbglistheader
dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0)
dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0)
dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, 9, 1, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_SteamSpring, Obj42_MapUnc_2686C, 1, 7, make_art_tile(ArtTile_ArtKos_LevelArt,3,0)
dbglistobj ObjID_MTZTwinStompers, Obj64_MapUnc_26A5C, 1, 0, make_art_tile(ArtTile_ArtKos_LevelArt,1,0)
dbglistobj ObjID_MTZTwinStompers, Obj64_MapUnc_26A5C, $11, 1, make_art_tile(ArtTile_ArtKos_LevelArt,1,0)
dbglistobj ObjID_MTZLongPlatform, Obj65_Obj6A_Obj6B_MapUnc_26EC8, $80, 0, make_art_tile(ArtTile_ArtKos_LevelArt,3,0)
dbglistobj ObjID_MTZLongPlatform, Obj65_Obj6A_Obj6B_MapUnc_26EC8, $13, 1, make_art_tile(ArtTile_ArtKos_LevelArt,3,0)
dbglistobj ObjID_Button, Obj47_MapUnc_24D96, 0, 2, make_art_tile(ArtTile_ArtNem_Button,0,0)
dbglistobj ObjID_Barrier, Obj2D_MapUnc_11822, 1, 1, make_art_tile(ArtTile_ArtKos_LevelArt,3,0)
dbglistobj ObjID_MTZSpringWall, Obj66_MapUnc_27120, 1, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,1)
dbglistobj ObjID_MTZSpringWall, Obj66_MapUnc_27120, $11, 1, make_art_tile(ArtTile_ArtNem_Powerups,0,1)
dbglistobj ObjID_SpikyBlock, Obj68_Obj6D_MapUnc_27750, 0, 4, make_art_tile(ArtTile_ArtNem_MtzSpikeBlock,3,0)
dbglistobj ObjID_Nut, Obj69_MapUnc_27A26, 4, 0, make_art_tile(ArtTile_ArtNem_MtzAsstBlocks,1,0)
dbglistobj ObjID_MTZMovingPforms, Obj65_Obj6A_Obj6B_MapUnc_26EC8, 0, 1, make_art_tile(ArtTile_ArtKos_LevelArt,3,0)
dbglistobj ObjID_MTZPlatform, Obj65_Obj6A_Obj6B_MapUnc_26EC8, 7, 1, make_art_tile(ArtTile_ArtKos_LevelArt,3,0)
dbglistobj ObjID_FloorSpike, Obj68_Obj6D_MapUnc_27750, 0, 0, make_art_tile(ArtTile_ArtNem_MtzSpike,1,0)
dbglistobj ObjID_LargeRotPform, Obj6E_MapUnc_2852C, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,3,0)
dbglistobj ObjID_LargeRotPform, Obj6E_MapUnc_2852C, $10, 1, make_art_tile(ArtTile_ArtKos_LevelArt,3,0)
dbglistobj ObjID_LargeRotPform, Obj6E_MapUnc_2852C, $20, 2, make_art_tile(ArtTile_ArtKos_LevelArt,3,0)
dbglistobj ObjID_Cog, Obj70_MapUnc_28786, $10, 0, make_art_tile(ArtTile_ArtNem_MtzWheel,3,1)
dbglistobj ObjID_MTZLavaBubble, Obj71_MapUnc_11576, $22, 5, make_art_tile(ArtTile_ArtNem_MtzLavaBubble,2,0)
dbglistobj ObjID_Scenery, Obj1C_MapUnc_11552, 0, 0, make_art_tile(ArtTile_ArtNem_BoltEnd_Rope,2,0)
dbglistobj ObjID_Scenery, Obj1C_MapUnc_11552, 1, 1, make_art_tile(ArtTile_ArtNem_BoltEnd_Rope,2,0)
dbglistobj ObjID_Scenery, Obj1C_MapUnc_11552, 3, 2, make_art_tile(ArtTile_ArtNem_BoltEnd_Rope,1,0)
dbglistobj ObjID_MTZLongPlatform, Obj65_Obj6A_Obj6B_MapUnc_26EC8, $B0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,3,0)
dbglistobj ObjID_Shellcracker, Obj9F_MapUnc_38314, $24, 0, make_art_tile(ArtTile_ArtNem_Crabmeat,0,0)
dbglistobj ObjID_Asteron, ObjA4_Obj98_MapUnc_38A96, $2E, 0, make_art_tile(ArtTile_ArtNem_MtzSupernova,0,1)
dbglistobj ObjID_Slicer, ObjA1_MapUnc_385E2, $28, 0, make_art_tile(ArtTile_ArtNem_MtzMantis,1,0)
dbglistobj ObjID_LavaMarker, Obj31_MapUnc_20E74, 0, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,1)
dbglistobj ObjID_LavaMarker, Obj31_MapUnc_20E74, 1, 1, make_art_tile(ArtTile_ArtNem_Powerups,0,1)
dbglistobj ObjID_LavaMarker, Obj31_MapUnc_20E74, 2, 2, make_art_tile(ArtTile_ArtNem_Powerups,0,1)
dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0)
DbgObjList_MTZ_End
DbgObjList_WFZ: dbglistheader
dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0)
dbglistobj ObjID_WFZPalSwitcher, Obj03_MapUnc_1FFB8, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,0,0)
dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0)
dbglistobj ObjID_Cloud, ObjB3_MapUnc_3B32C, $5E, 0, make_art_tile(ArtTile_ArtNem_Clouds,2,0)
dbglistobj ObjID_Cloud, ObjB3_MapUnc_3B32C, $60, 1, make_art_tile(ArtTile_ArtNem_Clouds,2,0)
dbglistobj ObjID_Cloud, ObjB3_MapUnc_3B32C, $62, 2, make_art_tile(ArtTile_ArtNem_Clouds,2,0)
dbglistobj ObjID_VPropeller, ObjB4_MapUnc_3B3BE, $64, 0, make_art_tile(ArtTile_ArtNem_WfzVrtclPrpllr,1,1)
dbglistobj ObjID_HPropeller, ObjB5_MapUnc_3B548, $66, 0, make_art_tile(ArtTile_ArtNem_WfzHrzntlPrpllr,1,1)
dbglistobj ObjID_HPropeller, ObjB5_MapUnc_3B548, $68, 0, make_art_tile(ArtTile_ArtNem_WfzHrzntlPrpllr,1,1)
dbglistobj ObjID_CluckerBase, ObjAD_Obj98_MapUnc_395B4, $42, $C, make_art_tile(ArtTile_ArtNem_WfzScratch,0,0)
dbglistobj ObjID_Clucker, ObjAD_Obj98_MapUnc_395B4, $44, $B, make_art_tile(ArtTile_ArtNem_WfzScratch,0,0)
dbglistobj ObjID_TiltingPlatform, ObjB6_MapUnc_3B856, $6A, 0, make_art_tile(ArtTile_ArtNem_WfzTiltPlatforms,1,1)
dbglistobj ObjID_TiltingPlatform, ObjB6_MapUnc_3B856, $6C, 0, make_art_tile(ArtTile_ArtNem_WfzTiltPlatforms,1,1)
dbglistobj ObjID_TiltingPlatform, ObjB6_MapUnc_3B856, $6E, 0, make_art_tile(ArtTile_ArtNem_WfzTiltPlatforms,1,1)
dbglistobj ObjID_TiltingPlatform, ObjB6_MapUnc_3B856, $70, 0, make_art_tile(ArtTile_ArtNem_WfzTiltPlatforms,1,1)
dbglistobj ObjID_VerticalLaser, ObjB7_MapUnc_3B8E4, $72, 0, make_art_tile(ArtTile_ArtNem_WfzVrtclLazer,2,1)
dbglistobj ObjID_WallTurret, ObjB8_Obj98_MapUnc_3BA46, $74, 0, make_art_tile(ArtTile_ArtNem_WfzWallTurret,0,0)
dbglistobj ObjID_Laser, ObjB9_MapUnc_3BB18, $76, 0, make_art_tile(ArtTile_ArtNem_WfzHrzntlLazer,2,1)
dbglistobj ObjID_WFZWheel, ObjBA_MapUnc_3BB70, $78, 0, make_art_tile(ArtTile_ArtNem_WfzConveyorBeltWheel,2,1)
dbglistobj ObjID_WFZShipFire, ObjBC_MapUnc_3BC08, $7C, 0, make_art_tile(ArtTile_ArtNem_WfzThrust,2,0)
dbglistobj ObjID_SmallMetalPform, ObjBD_MapUnc_3BD3E, $7E, 0, make_art_tile(ArtTile_ArtNem_WfzBeltPlatform,3,1)
dbglistobj ObjID_SmallMetalPform, ObjBD_MapUnc_3BD3E, $80, 0, make_art_tile(ArtTile_ArtNem_WfzBeltPlatform,3,1)
dbglistobj ObjID_LateralCannon, ObjBE_MapUnc_3BE46, $82, 0, make_art_tile(ArtTile_ArtNem_WfzGunPlatform,3,1)
dbglistobj ObjID_WFZStick, ObjBF_MapUnc_3BEE0, $84, 0, make_art_tile(ArtTile_ArtNem_WfzUnusedBadnik,3,1)
dbglistobj ObjID_SpeedLauncher, ObjC0_MapUnc_3C098, 8, 0, make_art_tile(ArtTile_ArtNem_WfzLaunchCatapult,1,0)
dbglistobj ObjID_BreakablePlating, ObjC1_MapUnc_3C280, $88, 0, make_art_tile(ArtTile_ArtNem_BreakPanels,3,1)
dbglistobj ObjID_Rivet, ObjC2_MapUnc_3C3C2, $8A, 0, make_art_tile(ArtTile_ArtNem_WfzSwitch,1,1)
dbglistobj ObjID_WFZPlatform, Obj19_MapUnc_2222A, $38, 3, make_art_tile(ArtTile_ArtNem_WfzFloatingPlatform,1,1)
dbglistobj ObjID_Grab, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_MovingVine, Obj80_MapUnc_29DD0, 0, 0, make_art_tile(ArtTile_ArtNem_WfzHook_Fudge,1,0)
dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0)
DbgObjList_WFZ_End
DbgObjList_HTZ: dbglistheader
dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0)
dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0)
dbglistobj ObjID_ForcedSpin, Obj03_MapUnc_1FFB8, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,0,0)
dbglistobj ObjID_ForcedSpin, Obj03_MapUnc_1FFB8, 4, 4, make_art_tile(ArtTile_ArtNem_Ring,0,0)
dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, 9, 1, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_EHZPlatform, Obj18_MapUnc_107F6, 1, 0, make_art_tile(ArtTile_ArtKos_LevelArt,2,0)
dbglistobj ObjID_EHZPlatform, Obj18_MapUnc_107F6, $9A, 1, make_art_tile(ArtTile_ArtKos_LevelArt,2,0)
dbglistobj ObjID_Spikes, Obj36_MapUnc_15B68, 0, 0, make_art_tile(ArtTile_ArtNem_Spikes,1,0)
dbglistobj ObjID_Seesaw, Obj14_MapUnc_21CF0, 0, 0, make_art_tile(ArtTile_ArtNem_HtzSeeSaw,0,0)
dbglistobj ObjID_Barrier, Obj2D_MapUnc_11822, 0, 0, make_art_tile(ArtTile_ArtNem_HtzValveBarrier,1,0)
dbglistobj ObjID_SmashableGround, Obj2F_MapUnc_236FA, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,2,1)
dbglistobj ObjID_LavaBubble, Obj20_MapUnc_23254, $44, 2, make_art_tile(ArtTile_ArtNem_HtzFireball,0,1)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $81, 0, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $90, 3, make_art_tile(ArtTile_ArtNem_HrzntlSprng,0,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $A0, 6, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $30, 7, make_art_tile(ArtTile_ArtNem_DignlSprng,0,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $40, $A, make_art_tile(ArtTile_ArtNem_DignlSprng,0,0)
dbglistobj ObjID_HTZLift, Obj16_MapUnc_21F14, 0, 0, make_art_tile(ArtTile_ArtNem_HtzZipline,2,0)
dbglistobj ObjID_BridgeStake, Obj16_MapUnc_21F14, 4, 3, make_art_tile(ArtTile_ArtNem_HtzZipline,2,0)
dbglistobj ObjID_BridgeStake, Obj16_MapUnc_21F14, 5, 4, make_art_tile(ArtTile_ArtNem_HtzZipline,2,0)
dbglistobj ObjID_Scenery, Obj1C_MapUnc_113D6, 7, 0, make_art_tile(ArtTile_ArtKos_LevelArt,2,0)
dbglistobj ObjID_Scenery, Obj1C_MapUnc_113D6, 8, 1, make_art_tile(ArtTile_ArtKos_LevelArt,2,0)
dbglistobj ObjID_BreakableRock, Obj32_MapUnc_23852, 0, 0, make_art_tile(ArtTile_ArtNem_HtzRock,2,0)
dbglistobj ObjID_LavaMarker, Obj31_MapUnc_20E74, 0, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,1)
dbglistobj ObjID_LavaMarker, Obj31_MapUnc_20E74, 1, 1, make_art_tile(ArtTile_ArtNem_Powerups,0,1)
dbglistobj ObjID_LavaMarker, Obj31_MapUnc_20E74, 2, 2, make_art_tile(ArtTile_ArtNem_Powerups,0,1)
dbglistobj ObjID_Rexon2, Obj94_Obj98_MapUnc_37678, $E, 2, make_art_tile(ArtTile_ArtNem_Rexon,3,0)
dbglistobj ObjID_Spiker, Obj92_Obj93_MapUnc_37092, $A, 0, make_art_tile(ArtTile_ArtKos_LevelArt,0,0)
dbglistobj ObjID_Sol, Obj95_MapUnc_372E6, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,0,0)
dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0)
DbgObjList_HTZ_End
DbgObjList_HPZ:; dbglistheader
; dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0)
; dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0)
;DbgObjList_HPZ_End
DbgObjList_OOZ: dbglistheader
dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0)
dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0)
dbglistobj ObjID_OOZPoppingPform, Obj33_MapUnc_23DDC, 1, 0, make_art_tile(ArtTile_ArtNem_BurnerLid,3,0)
dbglistobj ObjID_SlidingSpike, Obj43_MapUnc_23FE0, 0, 0, make_art_tile(ArtTile_ArtNem_SpikyThing,2,1)
dbglistobj ObjID_OOZMovingPform, Obj19_MapUnc_2222A, $23, 2, make_art_tile(ArtTile_ArtNem_OOZElevator,3,0)
dbglistobj ObjID_OOZSpring, Obj45_MapUnc_2451A, 2, 0, make_art_tile(ArtTile_ArtNem_PushSpring,2,0)
dbglistobj ObjID_OOZSpring, Obj45_MapUnc_2451A, $12, $A, make_art_tile(ArtTile_ArtNem_PushSpring,2,0)
dbglistobj ObjID_OOZBall, Obj46_MapUnc_24C52, 0, 1, make_art_tile(ArtTile_ArtNem_BallThing,3,0)
dbglistobj ObjID_Button, Obj47_MapUnc_24D96, 0, 2, make_art_tile(ArtTile_ArtNem_Button,0,0)
dbglistobj ObjID_SwingingPlatform, Obj15_MapUnc_101E8, $88, 1, make_art_tile(ArtTile_ArtNem_OOZSwingPlat,2,0)
dbglistobj ObjID_OOZLauncher, Obj3D_MapUnc_250BA, 0, 0, make_art_tile(ArtTile_ArtNem_StripedBlocksVert,3,0)
dbglistobj ObjID_LauncherBall, Obj48_MapUnc_254FE, $80, 0, make_art_tile(ArtTile_ArtNem_LaunchBall,3,0)
dbglistobj ObjID_LauncherBall, Obj48_MapUnc_254FE, $81, 1, make_art_tile(ArtTile_ArtNem_LaunchBall,3,0)
dbglistobj ObjID_LauncherBall, Obj48_MapUnc_254FE, $82, 2, make_art_tile(ArtTile_ArtNem_LaunchBall,3,0)
dbglistobj ObjID_LauncherBall, Obj48_MapUnc_254FE, $83, 3, make_art_tile(ArtTile_ArtNem_LaunchBall,3,0)
dbglistobj ObjID_CollapsPform, Obj1F_MapUnc_110C6, 0, 0, make_art_tile(ArtTile_ArtNem_OOZPlatform,3,0)
dbglistobj ObjID_Fan, Obj3F_MapUnc_2AA12, 0, 0, make_art_tile(ArtTile_ArtNem_OOZFanHoriz,3,0)
dbglistobj ObjID_Fan, Obj3F_MapUnc_2AAC4, $80, 0, make_art_tile(ArtTile_ArtNem_OOZFanHoriz,3,0)
dbglistobj ObjID_Aquis, Obj50_MapUnc_2CF94, 0, 0, make_art_tile(ArtTile_ArtNem_Aquis,1,0)
dbglistobj ObjID_Octus, Obj4A_MapUnc_2CBFE, 0, 0, make_art_tile(ArtTile_ArtNem_Octus,1,0)
dbglistobj ObjID_FallingOil, Obj1C_MapUnc_11406, $A, 0, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0)
dbglistobj ObjID_FallingOil, Obj1C_MapUnc_11406, $B, 1, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0)
dbglistobj ObjID_FallingOil, Obj1C_MapUnc_11406, $C, 2, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0)
dbglistobj ObjID_FallingOil, Obj1C_MapUnc_11406, $D, 3, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0)
dbglistobj ObjID_FallingOil, Obj1C_MapUnc_11406, $E, 4, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0)
dbglistobj ObjID_FallingOil, Obj1C_MapUnc_11406, $F, 5, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0)
dbglistobj ObjID_FallingOil, Obj1C_MapUnc_114AE, $10, 0, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0)
dbglistobj ObjID_FallingOil, Obj1C_MapUnc_114AE, $11, 1, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0)
dbglistobj ObjID_FallingOil, Obj1C_MapUnc_114AE, $12, 2, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0)
dbglistobj ObjID_FallingOil, Obj1C_MapUnc_114AE, $13, 3, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0)
dbglistobj ObjID_FallingOil, Obj1C_MapUnc_114AE, $14, 4, make_art_tile(ArtTile_ArtNem_Oilfall2,2,0)
dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0)
DbgObjList_OOZ_End
DbgObjList_MCZ: dbglistheader
dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0)
dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0)
dbglistobj ObjID_SwingingPlatform, Obj15_Obj7A_MapUnc_10256, $48, 2, make_art_tile(ArtTile_ArtKos_LevelArt,0,0)
dbglistobj ObjID_CollapsPform, Obj1F_MapUnc_11106, 0, 0, make_art_tile(ArtTile_ArtNem_MCZCollapsePlat,3,0)
dbglistobj ObjID_RotatingRings, Obj73_MapUnc_28B9C, $F5, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_MCZRotPforms, Obj6A_MapUnc_27D30, $18, 0, make_art_tile(ArtTile_ArtNem_Crate,3,0)
dbglistobj ObjID_Stomper, Obj2A_MapUnc_11666, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,2,0)
dbglistobj ObjID_Spikes, Obj36_MapUnc_15B68, 0, 0, make_art_tile(ArtTile_ArtNem_Spikes,1,0)
dbglistobj ObjID_Spikes, Obj36_MapUnc_15B68, $40, 4, make_art_tile(ArtTile_ArtNem_HorizSpike,1,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $81, 0, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $90, 3, make_art_tile(ArtTile_ArtNem_HrzntlSprng,0,0)
dbglistobj ObjID_Springboard, Obj40_MapUnc_265F4, 1, 0, make_art_tile(ArtTile_ArtNem_LeverSpring,0,0)
dbglistobj ObjID_InvisibleBlock, Obj74_MapUnc_20F66, $11, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,1)
dbglistobj ObjID_MCZBrick, Obj75_MapUnc_28D8A, $18, 2, make_art_tile(ArtTile_ArtKos_LevelArt,1,0)
dbglistobj ObjID_SlidingSpikes, Obj76_MapUnc_28F3A, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,0,0)
dbglistobj ObjID_MCZBridge, Obj77_MapUnc_29064, 1, 0, make_art_tile(ArtTile_ArtNem_MCZGateLog,3,0)
dbglistobj ObjID_VineSwitch, Obj7F_MapUnc_29938, 0, 0, make_art_tile(ArtTile_ArtNem_VineSwitch,3,0)
dbglistobj ObjID_MovingVine, Obj80_MapUnc_29C64, 0, 0, make_art_tile(ArtTile_ArtNem_VinePulley,3,0)
dbglistobj ObjID_MCZDrawbridge, Obj81_MapUnc_2A24E, 0, 1, make_art_tile(ArtTile_ArtNem_MCZGateLog,3,0)
dbglistobj ObjID_SidewaysPform, Obj15_Obj7A_MapUnc_10256, $12, 0, make_art_tile(ArtTile_ArtKos_LevelArt,0,0)
dbglistobj ObjID_Flasher, ObjA3_MapUnc_388F0, $2C, 0, make_art_tile(ArtTile_ArtNem_Flasher,0,1)
dbglistobj ObjID_Crawlton, Obj9E_MapUnc_37FF2, $22, 0, make_art_tile(ArtTile_ArtNem_Crawlton,1,0)
dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0)
DbgObjList_MCZ_End
DbgObjList_CNZ: dbglistheader
dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0)
dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0)
dbglistobj ObjID_PinballMode, Obj03_MapUnc_1FFB8, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,0,0)
dbglistobj ObjID_PinballMode, Obj03_MapUnc_1FFB8, 4, 4, make_art_tile(ArtTile_ArtNem_Ring,0,0)
dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, 9, 1, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, $D, 5, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_RoundBumper, Obj44_MapUnc_1F85A, 0, 0, make_art_tile(ArtTile_ArtNem_CNZRoundBumper,2,0)
dbglistobj ObjID_LauncherSpring, Obj85_MapUnc_2B07E, 0, 0, make_art_tile(ArtTile_ArtNem_CNZVertPlunger,0,0)
dbglistobj ObjID_LauncherSpring, Obj85_MapUnc_2B0EC, $81, 0, make_art_tile(ArtTile_ArtNem_CNZDiagPlunger,0,0)
dbglistobj ObjID_Flipper, Obj86_MapUnc_2B45A, 0, 0, make_art_tile(ArtTile_ArtNem_CNZFlipper,2,0)
dbglistobj ObjID_Flipper, Obj86_MapUnc_2B45A, 1, 4, make_art_tile(ArtTile_ArtNem_CNZFlipper,2,0)
dbglistobj ObjID_CNZRectBlocks, ObjD2_MapUnc_2B694, 1, 0, make_art_tile(ArtTile_ArtNem_CNZSnake,2,0)
dbglistobj ObjID_BombPrize, ObjD3_MapUnc_2B8D4, 0, 0, make_art_tile(ArtTile_ArtNem_CNZBonusSpike,0,0)
dbglistobj ObjID_CNZBigBlock, ObjD4_MapUnc_2B9CA, 0, 0, make_art_tile(ArtTile_ArtNem_BigMovingBlock,2,0)
dbglistobj ObjID_CNZBigBlock, ObjD4_MapUnc_2B9CA, 2, 0, make_art_tile(ArtTile_ArtNem_BigMovingBlock,2,0)
dbglistobj ObjID_Elevator, ObjD5_MapUnc_2BB40, $18, 0, make_art_tile(ArtTile_ArtNem_CNZElevator,2,0)
dbglistobj ObjID_PointPokey, ObjD6_MapUnc_2BEBC, 1, 0, make_art_tile(ArtTile_ArtNem_CNZCage,0,0)
dbglistobj ObjID_Bumper, ObjD7_MapUnc_2C626, 0, 0, make_art_tile(ArtTile_ArtNem_CNZHexBumper,2,0)
dbglistobj ObjID_BonusBlock, ObjD8_MapUnc_2C8C4, 0, 0, make_art_tile(ArtTile_ArtNem_CNZMiniBumper,2,0)
dbglistobj ObjID_BonusBlock, ObjD8_MapUnc_2C8C4, $40, 1, make_art_tile(ArtTile_ArtNem_CNZMiniBumper,2,0)
dbglistobj ObjID_BonusBlock, ObjD8_MapUnc_2C8C4, $80, 2, make_art_tile(ArtTile_ArtNem_CNZMiniBumper,2,0)
dbglistobj ObjID_Crawl, ObjC8_MapUnc_3D450, $AC, 0, make_art_tile(ArtTile_ArtNem_Crawl,0,1)
dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0)
DbgObjList_CNZ_End
DbgObjList_CPZ: dbglistheader
dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0)
dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0)
dbglistobj ObjID_TippingFloor, Obj0B_MapUnc_201A0, $70, 0, make_art_tile(ArtTile_ArtNem_CPZAnimatedBits,3,1)
dbglistobj ObjID_SpeedBooster, Obj1B_MapUnc_223E2, 0, 0, make_art_tile(ArtTile_ArtNem_CPZBooster,3,1)
dbglistobj ObjID_BlueBalls, Obj1D_MapUnc_22576, 5, 0, make_art_tile(ArtTile_ArtNem_CPZDroplet,3,1)
dbglistobj ObjID_CPZPlatform, Obj19_MapUnc_2222A, 6, 0, make_art_tile(ArtTile_ArtNem_CPZElevator,3,0)
dbglistobj ObjID_Barrier, Obj2D_MapUnc_11822, 2, 2, make_art_tile(ArtTile_ArtNem_ConstructionStripes_2,1,0)
dbglistobj ObjID_BreakableBlock, Obj32_MapUnc_23886, 0, 0, make_art_tile(ArtTile_ArtNem_CPZMetalBlock,3,0)
dbglistobj ObjID_CPZSquarePform, Obj6B_MapUnc_2800E, $10, 0, make_art_tile(ArtTile_ArtNem_CPZStairBlock,3,0)
dbglistobj ObjID_CPZStaircase, Obj6B_MapUnc_2800E, 0, 0, make_art_tile(ArtTile_ArtNem_CPZStairBlock,3,0)
dbglistobj ObjID_SidewaysPform, Obj7A_MapUnc_29564, 0, 0, make_art_tile(ArtTile_ArtNem_CPZStairBlock,3,1)
dbglistobj ObjID_PipeExitSpring, Obj7B_MapUnc_29780, 2, 0, make_art_tile(ArtTile_ArtNem_CPZTubeSpring,0,0)
dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, 9, 1, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, $D, 5, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_Spikes, Obj36_MapUnc_15B68, 0, 0, make_art_tile(ArtTile_ArtNem_Spikes,1,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $81, 0, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $90, 3, make_art_tile(ArtTile_ArtNem_HrzntlSprng,0,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $A0, 6, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0)
dbglistobj ObjID_Springboard, Obj40_MapUnc_265F4, 1, 0, make_art_tile(ArtTile_ArtNem_LeverSpring,0,0)
dbglistobj ObjID_Spiny, ObjA5_ObjA6_Obj98_MapUnc_38CCA, $32, 0, make_art_tile(ArtTile_ArtNem_Spiny,1,0)
dbglistobj ObjID_SpinyOnWall, ObjA5_ObjA6_Obj98_MapUnc_38CCA, $32, 3, make_art_tile(ArtTile_ArtNem_Spiny,1,0)
dbglistobj ObjID_Grabber, ObjA7_ObjA8_ObjA9_Obj98_MapUnc_3921A, $36, 0, make_art_tile(ArtTile_ArtNem_Grabber,1,1)
dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0)
DbgObjList_CPZ_End
DbgObjList_ARZ: dbglistheader
dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0)
dbglistobj ObjID_Starpost, Obj79_MapUnc_1F424, 1, 0, make_art_tile(ArtTile_ArtNem_Checkpoint,0,0)
dbglistobj ObjID_SwingingPlatform, Obj15_Obj83_MapUnc_1021E, $88, 2, make_art_tile(ArtTile_ArtKos_LevelArt,0,0)
dbglistobj ObjID_ARZPlatform, Obj18_MapUnc_1084E, 1, 0, make_art_tile(ArtTile_ArtKos_LevelArt,2,0)
dbglistobj ObjID_ARZPlatform, Obj18_MapUnc_1084E, $9A, 1, make_art_tile(ArtTile_ArtKos_LevelArt,2,0)
dbglistobj ObjID_ArrowShooter, Obj22_MapUnc_25804, 0, 1, make_art_tile(ArtTile_ArtNem_ArrowAndShooter,0,0)
dbglistobj ObjID_FallingPillar, Obj23_MapUnc_259E6, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,1,0)
dbglistobj ObjID_RisingPillar, Obj2B_MapUnc_25C6E, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,1,0)
dbglistobj ObjID_LeavesGenerator, Obj31_MapUnc_20E74, 0, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,1)
dbglistobj ObjID_LeavesGenerator, Obj31_MapUnc_20E74, 1, 1, make_art_tile(ArtTile_ArtNem_Powerups,0,1)
dbglistobj ObjID_LeavesGenerator, Obj31_MapUnc_20E74, 2, 2, make_art_tile(ArtTile_ArtNem_Powerups,0,1)
dbglistobj ObjID_Springboard, Obj40_MapUnc_265F4, 1, 0, make_art_tile(ArtTile_ArtNem_LeverSpring,0,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $81, 0, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $90, 3, make_art_tile(ArtTile_ArtNem_HrzntlSprng,0,0)
dbglistobj ObjID_Spring, Obj41_MapUnc_1901C, $A0, 6, make_art_tile(ArtTile_ArtNem_VrtclSprng,0,0)
dbglistobj ObjID_PlaneSwitcher, Obj03_MapUnc_1FFB8, 9, 1, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_Spikes, Obj36_MapUnc_15B68, 0, 0, make_art_tile(ArtTile_ArtNem_Spikes,1,0)
dbglistobj ObjID_Barrier, Obj2D_MapUnc_11822, 3, 3, make_art_tile(ArtTile_ArtNem_ARZBarrierThing,1,0)
dbglistobj ObjID_CollapsPform, Obj1F_MapUnc_1115E, 0, 0, make_art_tile(ArtTile_ArtKos_LevelArt,2,0)
dbglistobj ObjID_SwingingPform, Obj82_MapUnc_2A476, 3, 0, make_art_tile(ArtTile_ArtKos_LevelArt,0,0)
dbglistobj ObjID_SwingingPform, Obj82_MapUnc_2A476, $11, 1, make_art_tile(ArtTile_ArtKos_LevelArt,0,0)
dbglistobj ObjID_ARZRotPforms, Obj15_Obj83_MapUnc_1021E, $10, 1, make_art_tile(ArtTile_ArtKos_LevelArt,0,0)
dbglistobj ObjID_ARZBubbles, Obj24_MapUnc_1FBF6, $81, $E, make_art_tile(ArtTile_ArtNem_BigBubbles,0,1)
dbglistobj ObjID_ChopChop, Obj91_MapUnc_36EF6, 8, 0, make_art_tile(ArtTile_ArtNem_ChopChop,1,0)
dbglistobj ObjID_Whisp, Obj8C_MapUnc_36A4E, 0, 0, make_art_tile(ArtTile_ArtNem_Whisp,1,1)
dbglistobj ObjID_GrounderInWall, Obj8D_MapUnc_36CF0, 2, 0, make_art_tile(ArtTile_ArtNem_Grounder,1,1)
dbglistobj ObjID_GrounderInWall2, Obj8D_MapUnc_36CF0, 2, 0, make_art_tile(ArtTile_ArtNem_Grounder,1,1)
dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0)
DbgObjList_ARZ_End
DbgObjList_SCZ: dbglistheader
dbglistobj ObjID_Ring, Obj25_MapUnc_12382, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,1,0)
dbglistobj ObjID_Monitor, Obj26_MapUnc_12D36, 8, 0, make_art_tile(ArtTile_ArtNem_Powerups,0,0)
dbglistobj ObjID_WFZPalSwitcher, Obj03_MapUnc_1FFB8, 0, 0, make_art_tile(ArtTile_ArtNem_Ring,0,0)
dbglistobj ObjID_Cloud, ObjB3_MapUnc_3B32C, $5E, 0, make_art_tile(ArtTile_ArtNem_Clouds,2,0)
dbglistobj ObjID_Cloud, ObjB3_MapUnc_3B32C, $60, 1, make_art_tile(ArtTile_ArtNem_Clouds,2,0)
dbglistobj ObjID_Cloud, ObjB3_MapUnc_3B32C, $62, 2, make_art_tile(ArtTile_ArtNem_Clouds,2,0)
dbglistobj ObjID_VPropeller, ObjB4_MapUnc_3B3BE, $64, 0, make_art_tile(ArtTile_ArtNem_WfzVrtclPrpllr,1,1)
dbglistobj ObjID_HPropeller, ObjB5_MapUnc_3B548, $66, 0, make_art_tile(ArtTile_ArtNem_WfzHrzntlPrpllr,1,1)
dbglistobj ObjID_HPropeller, ObjB5_MapUnc_3B548, $68, 0, make_art_tile(ArtTile_ArtNem_WfzHrzntlPrpllr,1,1)
dbglistobj ObjID_Turtloid, Obj9A_Obj98_MapUnc_37B62, $16, 0, make_art_tile(ArtTile_ArtNem_Turtloid,0,0)
dbglistobj ObjID_Balkiry, ObjAC_MapUnc_393CC, $40, 0, make_art_tile(ArtTile_ArtNem_Balkrie,0,0)
dbglistobj ObjID_Nebula, Obj99_Obj98_MapUnc_3789A, $12, 0, make_art_tile(ArtTile_ArtNem_Nebula,1,1)
dbglistobj ObjID_EggPrison, Obj3E_MapUnc_3F436, 0, 0, make_art_tile(ArtTile_ArtNem_Capsule,1,0)
DbgObjList_SCZ_End
if ~~removeJmpTos
JmpTo66_Adjust2PArtPointer
jmp (Adjust2PArtPointer).l
align 4
endif
; ---------------------------------------------------------------------------
; "MAIN LEVEL LOAD BLOCK" (after Nemesis)
;
; This struct array tells the engine where to find all the art associated with
; a particular zone. Each zone gets three longwords, in which it stores three
; pointers (in the lower 24 bits) and three jump table indeces (in the upper eight
; bits). The assembled data looks something like this:
;
; aaBBBBBB
; ccDDDDDD
; eeFFFFFF
;
; aa = index for primary pattern load request list
; BBBBBB = pointer to level art
; cc = index for secondary pattern load request list
; DDDDDD = pointer to 16x16 block mappings
; ee = index for palette
; FFFFFF = pointer to 128x128 block mappings
;
; Nemesis refers to this as the "main level load block". However, that name implies
; that this is code (obviously, it isn't), or at least that it points to the level's
; collision, object and ring placement arrays (it only points to art...
; although the 128x128 mappings do affect the actual level layout and collision)
; ---------------------------------------------------------------------------
; declare some global variables to be used by the levartptrs macro
cur_zone_id := 0
cur_zone_str := "0"
; macro for declaring a "main level load block" (MLLB)
levartptrs macro plc1,plc2,palette,art,map16x16,map128x128
!org LevelArtPointers+zone_id_{cur_zone_str}*12
dc.l (plc1<<24)|art
dc.l (plc2<<24)|map16x16
dc.l (palette<<24)|map128x128
cur_zone_id := cur_zone_id+1
cur_zone_str := "\{cur_zone_id}"
endm
; BEGIN SArt_Ptrs Art_Ptrs_Array[17]
; dword_42594: MainLoadBlocks: saArtPtrs:
LevelArtPointers:
levartptrs PLCID_Ehz1, PLCID_Ehz2, PalID_EHZ, ArtKos_EHZ, BM16_EHZ, BM128_EHZ ; 0 ; EHZ ; EMERALD HILL ZONE
levartptrs PLCID_Miles1up, PLCID_MilesLife, PalID_EHZ2, ArtKos_EHZ, BM16_EHZ, BM128_EHZ ; 1 ; LEV1 ; LEVEL 1 (UNUSED)
levartptrs PLCID_Tails1up, PLCID_TailsLife, PalID_WZ, ArtKos_EHZ, BM16_EHZ, BM128_EHZ ; 2 ; LEV2 ; LEVEL 2 (UNUSED)
levartptrs PLCID_Unused1, PLCID_Unused2, PalID_EHZ3, ArtKos_EHZ, BM16_EHZ, BM128_EHZ ; 3 ; LEV3 ; LEVEL 3 (UNUSED)
levartptrs PLCID_Mtz1, PLCID_Mtz2, PalID_MTZ, ArtKos_MTZ, BM16_MTZ, BM128_MTZ ; 4 ; MTZ ; METROPOLIS ZONE ACTS 1 & 2
levartptrs PLCID_Mtz1, PLCID_Mtz2, PalID_MTZ, ArtKos_MTZ, BM16_MTZ, BM128_MTZ ; 5 ; MTZ3 ; METROPOLIS ZONE ACT 3
levartptrs PLCID_Wfz1, PLCID_Wfz2, PalID_WFZ, ArtKos_SCZ, BM16_WFZ, BM128_WFZ ; 6 ; WFZ ; WING FORTRESS ZONE
levartptrs PLCID_Htz1, PLCID_Htz2, PalID_HTZ, ArtKos_EHZ, BM16_EHZ, BM128_EHZ ; 7 ; HTZ ; HILL TOP ZONE
levartptrs PLCID_Hpz1, PLCID_Hpz2, PalID_HPZ, ArtKos_HPZ, BM16_HPZ, BM128_HPZ ; 8 ; HPZ ; HIDDEN PALACE ZONE (UNUSED)
levartptrs PLCID_Unused3, PLCID_Unused4, PalID_EHZ4, ArtKos_EHZ, BM16_EHZ, BM128_EHZ ; 9 ; LEV9 ; LEVEL 9 (UNUSED)
levartptrs PLCID_Ooz1, PLCID_Ooz2, PalID_OOZ, ArtKos_OOZ, BM16_OOZ, BM128_OOZ ; $A ; OOZ ; OIL OCEAN ZONE
levartptrs PLCID_Mcz1, PLCID_Mcz2, PalID_MCZ, ArtKos_MCZ, BM16_MCZ, BM128_MCZ ; $B ; MCZ ; MYSTIC CAVE ZONE
levartptrs PLCID_Cnz1, PLCID_Cnz2, PalID_CNZ, ArtKos_CNZ, BM16_CNZ, BM128_CNZ ; $C ; CNZ ; CASINO NIGHT ZONE
levartptrs PLCID_Cpz1, PLCID_Cpz2, PalID_CPZ, ArtKos_CPZ, BM16_CPZ, BM128_CPZ ; $D ; CPZ ; CHEMICAL PLANT ZONE
levartptrs PLCID_Dez1, PLCID_Dez2, PalID_DEZ, ArtKos_CPZ, BM16_CPZ, BM128_CPZ ; $E ; DEZ ; DEATH EGG ZONE
levartptrs PLCID_Arz1, PLCID_Arz2, PalID_ARZ, ArtKos_ARZ, BM16_ARZ, BM128_ARZ ; $F ; ARZ ; AQUATIC RUIN ZONE
levartptrs PLCID_Scz1, PLCID_Scz2, PalID_SCZ, ArtKos_SCZ, BM16_WFZ, BM128_WFZ ; $10 ; SCZ ; SKY CHASE ZONE
if (cur_zone_id<>no_of_zones)&&(MOMPASS=1)
message "Warning: Table LevelArtPointers has \{cur_zone_id/1.0} entries, but it should have \{no_of_zones/1.0} entries"
endif
!org LevelArtPointers+cur_zone_id*12
; ---------------------------------------------------------------------------
; END Art_Ptrs_Array[17]
; ---------------------------------------------------------------------------
; PATTERN LOAD REQUEST LISTS
;
; Pattern load request lists are simple structures used to load
; Nemesis-compressed art for sprites.
;
; The decompressor predictably moves down the list, so request 0 is processed first, etc.
; This only matters if your addresses are bad and you overwrite art loaded in a previous request.
;
; NOTICE: The load queue buffer can only hold $10 (16) load requests. None of the routines
; that load PLRs into the queue do any bounds checking, so it's possible to create a buffer
; overflow and completely screw up the variables stored directly after the queue buffer.
; (in my experience this is a guaranteed crash or hang)
;
; Many levels queue more than 16 items overall,
; but they don't exceed the limit because
; their PLRs are split into multiple parts (like PlrList_Mtz1 and PlrList_Mtz2)
; and they fully process the first part before requesting the rest.
;
; If you can find some extra RAM for it (which is easy in Sonic 2),
; you can increase this limit by increasing the size of Plc_Buffer.
; ---------------------------------------------------------------------------
;---------------------------------------------------------------------------------------
; Table of pattern load request lists. Remember to use word-length data when adding lists
; otherwise you'll break the array.
;---------------------------------------------------------------------------------------
; word_42660 ; OffInd_PlrLists:
ArtLoadCues: offsetTable
PLCptr_Std1: offsetTableEntry.w PlrList_Std1 ; 0
PLCptr_Std2: offsetTableEntry.w PlrList_Std2 ; 1
PLCptr_StdWtr: offsetTableEntry.w PlrList_StdWtr ; 2
PLCptr_GameOver: offsetTableEntry.w PlrList_GameOver ; 3
PLCptr_Ehz1: offsetTableEntry.w PlrList_Ehz1 ; 4
PLCptr_Ehz2: offsetTableEntry.w PlrList_Ehz2 ; 5
PLCptr_Miles1up: offsetTableEntry.w PlrList_Miles1up ; 6
PLCptr_MilesLife: offsetTableEntry.w PlrList_MilesLifeCounter ; 7
PLCptr_Tails1up: offsetTableEntry.w PlrList_Tails1up ; 8
PLCptr_TailsLife: offsetTableEntry.w PlrList_TailsLifeCounter ; 9
PLCptr_Unused1: offsetTableEntry.w PlrList_Mtz1 ; 10
PLCptr_Unused2: offsetTableEntry.w PlrList_Mtz1 ; 11
PLCptr_Mtz1: offsetTableEntry.w PlrList_Mtz1 ; 12
PLCptr_Mtz2: offsetTableEntry.w PlrList_Mtz2 ; 13
offsetTableEntry.w PlrList_Wfz1 ; 14
offsetTableEntry.w PlrList_Wfz1 ; 15
PLCptr_Wfz1: offsetTableEntry.w PlrList_Wfz1 ; 16
PLCptr_Wfz2: offsetTableEntry.w PlrList_Wfz2 ; 17
PLCptr_Htz1: offsetTableEntry.w PlrList_Htz1 ; 18
PLCptr_Htz2: offsetTableEntry.w PlrList_Htz2 ; 19
PLCptr_Hpz1: offsetTableEntry.w PlrList_Hpz1 ; 20
PLCptr_Hpz2: offsetTableEntry.w PlrList_Hpz2 ; 21
PLCptr_Unused3: offsetTableEntry.w PlrList_Ooz1 ; 22
PLCptr_Unused4: offsetTableEntry.w PlrList_Ooz1 ; 23
PLCptr_Ooz1: offsetTableEntry.w PlrList_Ooz1 ; 24
PLCptr_Ooz2: offsetTableEntry.w PlrList_Ooz2 ; 25
PLCptr_Mcz1: offsetTableEntry.w PlrList_Mcz1 ; 26
PLCptr_Mcz2: offsetTableEntry.w PlrList_Mcz2 ; 27
PLCptr_Cnz1: offsetTableEntry.w PlrList_Cnz1 ; 28
PLCptr_Cnz2: offsetTableEntry.w PlrList_Cnz2 ; 29
PLCptr_Cpz1: offsetTableEntry.w PlrList_Cpz1 ; 30
PLCptr_Cpz2: offsetTableEntry.w PlrList_Cpz2 ; 31
PLCptr_Dez1: offsetTableEntry.w PlrList_Dez1 ; 32
PLCptr_Dez2: offsetTableEntry.w PlrList_Dez2 ; 33
PLCptr_Arz1: offsetTableEntry.w PlrList_Arz1 ; 34
PLCptr_Arz2: offsetTableEntry.w PlrList_Arz2 ; 35
PLCptr_Scz1: offsetTableEntry.w PlrList_Scz1 ; 36
PLCptr_Scz2: offsetTableEntry.w PlrList_Scz2 ; 37
PLCptr_Results: offsetTableEntry.w PlrList_Results ; 38
PLCptr_Signpost: offsetTableEntry.w PlrList_Signpost ; 39
PLCptr_CpzBoss: offsetTableEntry.w PlrList_CpzBoss ; 40
PLCptr_EhzBoss: offsetTableEntry.w PlrList_EhzBoss ; 41
PLCptr_HtzBoss: offsetTableEntry.w PlrList_HtzBoss ; 42
PLCptr_ArzBoss: offsetTableEntry.w PlrList_ArzBoss ; 43
PLCptr_MczBoss: offsetTableEntry.w PlrList_MczBoss ; 44
PLCptr_CnzBoss: offsetTableEntry.w PlrList_CnzBoss ; 45
PLCptr_MtzBoss: offsetTableEntry.w PlrList_MtzBoss ; 46
PLCptr_OozBoss: offsetTableEntry.w PlrList_OozBoss ; 47
PLCptr_FieryExplosion: offsetTableEntry.w PlrList_FieryExplosion ; 48
PLCptr_DezBoss: offsetTableEntry.w PlrList_DezBoss ; 49
PLCptr_EhzAnimals: offsetTableEntry.w PlrList_EhzAnimals ; 50
PLCptr_MczAnimals: offsetTableEntry.w PlrList_MczAnimals ; 51
PLCptr_HtzAnimals:
PLCptr_MtzAnimals:
PLCptr_WfzAnimals: offsetTableEntry.w PlrList_WfzAnimals ; 52
PLCptr_DezAnimals: offsetTableEntry.w PlrList_DezAnimals ; 53
PLCptr_HpzAnimals: offsetTableEntry.w PlrList_HpzAnimals ; 54
PLCptr_OozAnimals: offsetTableEntry.w PlrList_OozAnimals ; 55
PLCptr_SczAnimals: offsetTableEntry.w PlrList_SczAnimals ; 56
PLCptr_CnzAnimals: offsetTableEntry.w PlrList_CnzAnimals ; 57
PLCptr_CpzAnimals: offsetTableEntry.w PlrList_CpzAnimals ; 58
PLCptr_ArzAnimals: offsetTableEntry.w PlrList_ArzAnimals ; 59
PLCptr_SpecialStage: offsetTableEntry.w PlrList_SpecialStage ; 60
PLCptr_SpecStageBombs: offsetTableEntry.w PlrList_SpecStageBombs ; 61
PLCptr_WfzBoss: offsetTableEntry.w PlrList_WfzBoss ; 62
PLCptr_Tornado: offsetTableEntry.w PlrList_Tornado ; 63
PLCptr_Capsule: offsetTableEntry.w PlrList_Capsule ; 64
PLCptr_Explosion: offsetTableEntry.w PlrList_Explosion ; 65
PLCptr_ResultsTails: offsetTableEntry.w PlrList_ResultsTails ; 66
; macro for a pattern load request list header
; must be on the same line as a label that has a corresponding _End label later
plrlistheader macro {INTLABEL}
__LABEL__ label *
dc.w (((__LABEL___End - __LABEL__Plc) / 6) - 1)
__LABEL__Plc:
endm
; macro for a pattern load request
plreq macro toVRAMaddr,fromROMaddr
dc.l fromROMaddr
dc.w tiles_to_bytes(toVRAMaddr)
endm
;---------------------------------------------------------------------------------------
; PATTERN LOAD REQUEST LIST
; Standard 1 - loaded for every level
;---------------------------------------------------------------------------------------
PlrList_Std1: plrlistheader
plreq ArtTile_ArtNem_HUD, ArtNem_HUD
plreq ArtTile_ArtNem_life_counter, ArtNem_Sonic_life_counter
plreq ArtTile_ArtNem_Ring, ArtNem_Ring
plreq ArtTile_ArtNem_Numbers, ArtNem_Numbers
PlrList_Std1_End
;---------------------------------------------------------------------------------------
; PATTERN LOAD REQUEST LIST
; Standard 2 - loaded for every level
;---------------------------------------------------------------------------------------
PlrList_Std2: plrlistheader
plreq ArtTile_ArtNem_Checkpoint, ArtNem_Checkpoint
plreq ArtTile_ArtNem_Powerups, ArtNem_Powerups
plreq ArtTile_ArtNem_Shield, ArtNem_Shield
plreq ArtTile_ArtNem_Invincible_stars, ArtNem_Invincible_stars
PlrList_Std2_End
;---------------------------------------------------------------------------------------
; PATTERN LOAD REQUEST LIST
; Aquatic level standard
;---------------------------------------------------------------------------------------
PlrList_StdWtr: plrlistheader
plreq ArtTile_ArtNem_Explosion, ArtNem_Explosion
plreq ArtTile_ArtNem_SuperSonic_stars, ArtNem_SuperSonic_stars
plreq ArtTile_ArtNem_Bubbles, ArtNem_Bubbles
PlrList_StdWtr_End
;---------------------------------------------------------------------------------------
; PATTERN LOAD REQUEST LIST
; Game/Time over
;---------------------------------------------------------------------------------------
PlrList_GameOver: plrlistheader
plreq ArtTile_ArtNem_Game_Over, ArtNem_Game_Over
PlrList_GameOver_End
;---------------------------------------------------------------------------------------
; PATTERN LOAD REQUEST LIST
; Emerald Hill Zone primary
;---------------------------------------------------------------------------------------
PlrList_Ehz1: plrlistheader
plreq ArtTile_ArtNem_Waterfall, ArtNem_Waterfall
plreq ArtTile_ArtNem_EHZ_Bridge, ArtNem_EHZ_Bridge
plreq ArtTile_ArtNem_Buzzer_Fireball_2, ArtNem_Buzzer_Fireball
plreq ArtTile_ArtNem_Buzzer, ArtNem_Buzzer
plreq ArtTile_ArtNem_Coconuts, ArtNem_Coconuts
plreq ArtTile_ArtNem_Masher, ArtNem_Masher
PlrList_Ehz1_End
;---------------------------------------------------------------------------------------
; PATTERN LOAD REQUEST LIST
; Emerald Hill Zone secondary
;---------------------------------------------------------------------------------------
PlrList_Ehz2: plrlistheader
plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes
plreq ArtTile_ArtNem_DignlSprng, ArtNem_DignlSprng
plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng
plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng
PlrList_Ehz2_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; Miles 1up patch
;---------------------------------------------------------------------------------------
PlrList_Miles1up: plrlistheader
plreq ArtTile_ArtUnc_2p_life_counter, ArtUnc_MilesLife
PlrList_Miles1up_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; Miles life counter
;---------------------------------------------------------------------------------------
PlrList_MilesLifeCounter: plrlistheader
plreq ArtTile_ArtNem_life_counter, ArtUnc_MilesLife
PlrList_MilesLifeCounter_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; Tails 1up patch
;---------------------------------------------------------------------------------------
PlrList_Tails1up: plrlistheader
plreq ArtTile_ArtUnc_2p_life_counter, ArtNem_TailsLife
PlrList_Tails1up_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; Tails life counter
;---------------------------------------------------------------------------------------
PlrList_TailsLifeCounter: plrlistheader
plreq ArtTile_ArtNem_life_counter, ArtNem_TailsLife
PlrList_TailsLifeCounter_End
;---------------------------------------------------------------------------------------
; PATTERN LOAD REQUEST LIST
; Metropolis Zone primary
;---------------------------------------------------------------------------------------
PlrList_Mtz1: plrlistheader
plreq ArtTile_ArtNem_MtzWheel, ArtNem_MtzWheel
plreq ArtTile_ArtNem_MtzWheelIndent, ArtNem_MtzWheelIndent
plreq ArtTile_ArtNem_LavaCup, ArtNem_LavaCup
plreq ArtTile_ArtNem_BoltEnd_Rope, ArtNem_BoltEnd_Rope
plreq ArtTile_ArtNem_MtzSteam, ArtNem_MtzSteam
plreq ArtTile_ArtNem_MtzSpikeBlock, ArtNem_MtzSpikeBlock
plreq ArtTile_ArtNem_MtzSpike, ArtNem_MtzSpike
plreq ArtTile_ArtNem_Crabmeat, ArtNem_Crabmeat
plreq ArtTile_ArtNem_MtzSupernova, ArtNem_MtzSupernova
PlrList_Mtz1_End
;---------------------------------------------------------------------------------------
; PATTERN LOAD REQUEST LIST
; Metropolis Zone secondary
;---------------------------------------------------------------------------------------
PlrList_Mtz2: plrlistheader
plreq ArtTile_ArtNem_Button, ArtNem_Button
plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes
plreq ArtTile_ArtNem_MtzMantis, ArtNem_MtzMantis
plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng
plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng
plreq ArtTile_ArtNem_MtzAsstBlocks, ArtNem_MtzAsstBlocks
plreq ArtTile_ArtNem_MtzLavaBubble, ArtNem_MtzLavaBubble
plreq ArtTile_ArtNem_MtzCog, ArtNem_MtzCog
plreq ArtTile_ArtNem_MtzSpinTubeFlash, ArtNem_MtzSpinTubeFlash
PlrList_Mtz2_End
;---------------------------------------------------------------------------------------
; PATTERN LOAD REQUEST LIST
; Wing Fortress Zone primary
;---------------------------------------------------------------------------------------
PlrList_Wfz1: plrlistheader
plreq ArtTile_ArtNem_Tornado, ArtNem_Tornado
plreq ArtTile_ArtNem_Clouds, ArtNem_Clouds
plreq ArtTile_ArtNem_WfzVrtclPrpllr, ArtNem_WfzVrtclPrpllr
plreq ArtTile_ArtNem_WfzHrzntlPrpllr, ArtNem_WfzHrzntlPrpllr
plreq ArtTile_ArtNem_Balkrie, ArtNem_Balkrie
plreq ArtTile_ArtNem_BreakPanels, ArtNem_BreakPanels
plreq ArtTile_ArtNem_WfzScratch, ArtNem_WfzScratch
plreq ArtTile_ArtNem_WfzTiltPlatforms, ArtNem_WfzTiltPlatforms
; These two are already in the list, so this is redundant
plreq ArtTile_ArtNem_Tornado, ArtNem_Tornado
plreq ArtTile_ArtNem_Clouds, ArtNem_Clouds
PlrList_Wfz1_End
;---------------------------------------------------------------------------------------
; PATTERN LOAD REQUEST LIST
; Wing Fortress Zone secondary
;---------------------------------------------------------------------------------------
PlrList_Wfz2: plrlistheader
plreq ArtTile_ArtNem_WfzVrtclPrpllr, ArtNem_WfzVrtclPrpllr
plreq ArtTile_ArtNem_WfzHrzntlPrpllr, ArtNem_WfzHrzntlPrpllr
plreq ArtTile_ArtNem_WfzVrtclLazer, ArtNem_WfzVrtclLazer
plreq ArtTile_ArtNem_WfzWallTurret, ArtNem_WfzWallTurret
plreq ArtTile_ArtNem_WfzHrzntlLazer, ArtNem_WfzHrzntlLazer
plreq ArtTile_ArtNem_WfzConveyorBeltWheel, ArtNem_WfzConveyorBeltWheel
plreq ArtTile_ArtNem_WfzHook, ArtNem_WfzHook
plreq ArtTile_ArtNem_WfzThrust, ArtNem_WfzThrust
plreq ArtTile_ArtNem_WfzBeltPlatform, ArtNem_WfzBeltPlatform
plreq ArtTile_ArtNem_WfzGunPlatform, ArtNem_WfzGunPlatform
plreq ArtTile_ArtNem_WfzUnusedBadnik, ArtNem_WfzUnusedBadnik
plreq ArtTile_ArtNem_WfzLaunchCatapult, ArtNem_WfzLaunchCatapult
plreq ArtTile_ArtNem_WfzSwitch, ArtNem_WfzSwitch
plreq ArtTile_ArtNem_WfzFloatingPlatform, ArtNem_WfzFloatingPlatform
PlrList_Wfz2_End
;---------------------------------------------------------------------------------------
; PATTERN LOAD REQUEST LIST
; Hill Top Zone primary
;---------------------------------------------------------------------------------------
PlrList_Htz1: plrlistheader
plreq ArtTile_ArtNem_Buzzer_Fireball_1, ArtNem_Buzzer_Fireball
plreq ArtTile_ArtNem_HtzRock, ArtNem_HtzRock
plreq ArtTile_ArtNem_HtzSeeSaw, ArtNem_HtzSeeSaw
plreq ArtTile_ArtNem_Sol, ArtNem_Sol
plreq ArtTile_ArtNem_Rexon, ArtNem_Rexon
plreq ArtTile_ArtNem_Spiker, ArtNem_Spiker
plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes
plreq ArtTile_ArtNem_DignlSprng, ArtNem_DignlSprng
plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng
plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng
PlrList_Htz1_End
;---------------------------------------------------------------------------------------
; PATTERN LOAD REQUEST LIST
; Hill Top Zone secondary
;---------------------------------------------------------------------------------------
PlrList_Htz2: plrlistheader
plreq ArtTile_ArtNem_HtzZipline, ArtNem_HtzZipline
plreq ArtTile_ArtNem_HtzFireball, ArtNem_HtzFireball
plreq ArtTile_ArtNem_HtzValveBarrier, ArtNem_HtzValveBarrier
PlrList_Htz2_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; HPZ Primary
;---------------------------------------------------------------------------------------
PlrList_Hpz1: ;plrlistheader
; plreq ArtTile_ArtNem_WaterSurface, ArtNem_WaterSurface
;PlrList_Hpz1_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; HPZ Secondary
;---------------------------------------------------------------------------------------
PlrList_Hpz2: ;plrlistheader
;PlrList_Hpz2_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; OOZ Primary
;---------------------------------------------------------------------------------------
PlrList_Ooz1: plrlistheader
plreq ArtTile_ArtNem_OOZBurn, ArtNem_OOZBurn
plreq ArtTile_ArtNem_OOZElevator, ArtNem_OOZElevator
plreq ArtTile_ArtNem_SpikyThing, ArtNem_SpikyThing
plreq ArtTile_ArtNem_BurnerLid, ArtNem_BurnerLid
plreq ArtTile_ArtNem_StripedBlocksVert, ArtNem_StripedBlocksVert
plreq ArtTile_ArtNem_Oilfall, ArtNem_Oilfall
plreq ArtTile_ArtNem_Oilfall2, ArtNem_Oilfall2
plreq ArtTile_ArtNem_BallThing, ArtNem_BallThing
plreq ArtTile_ArtNem_LaunchBall, ArtNem_LaunchBall
PlrList_Ooz1_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; OOZ Secondary
;---------------------------------------------------------------------------------------
PlrList_Ooz2: plrlistheader
plreq ArtTile_ArtNem_OOZPlatform, ArtNem_OOZPlatform
plreq ArtTile_ArtNem_PushSpring, ArtNem_PushSpring
plreq ArtTile_ArtNem_OOZSwingPlat, ArtNem_OOZSwingPlat
plreq ArtTile_ArtNem_StripedBlocksHoriz, ArtNem_StripedBlocksHoriz
plreq ArtTile_ArtNem_OOZFanHoriz, ArtNem_OOZFanHoriz
plreq ArtTile_ArtNem_Button, ArtNem_Button
plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes
plreq ArtTile_ArtNem_DignlSprng, ArtNem_DignlSprng
plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng
plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng
plreq ArtTile_ArtNem_Aquis, ArtNem_Aquis
plreq ArtTile_ArtNem_Octus, ArtNem_Octus
PlrList_Ooz2_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; MCZ Primary
;---------------------------------------------------------------------------------------
PlrList_Mcz1: plrlistheader
plreq ArtTile_ArtNem_Crate, ArtNem_Crate
plreq ArtTile_ArtNem_MCZCollapsePlat, ArtNem_MCZCollapsePlat
plreq ArtTile_ArtNem_VineSwitch, ArtNem_VineSwitch
plreq ArtTile_ArtNem_VinePulley, ArtNem_VinePulley
plreq ArtTile_ArtNem_Flasher, ArtNem_Flasher
plreq ArtTile_ArtNem_Crawlton, ArtNem_Crawlton
PlrList_Mcz1_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; MCZ Secondary
;---------------------------------------------------------------------------------------
PlrList_Mcz2: plrlistheader
plreq ArtTile_ArtNem_HorizSpike, ArtNem_HorizSpike
plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes
plreq ArtTile_ArtNem_MCZGateLog, ArtNem_MCZGateLog
plreq ArtTile_ArtNem_LeverSpring, ArtNem_LeverSpring
plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng
plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng
PlrList_Mcz2_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; CNZ Primary
;---------------------------------------------------------------------------------------
PlrList_Cnz1: plrlistheader
plreq ArtTile_ArtNem_Crawl, ArtNem_Crawl
plreq ArtTile_ArtNem_BigMovingBlock, ArtNem_BigMovingBlock
plreq ArtTile_ArtNem_CNZSnake, ArtNem_CNZSnake
plreq ArtTile_ArtNem_CNZBonusSpike, ArtNem_CNZBonusSpike
plreq ArtTile_ArtNem_CNZElevator, ArtNem_CNZElevator
plreq ArtTile_ArtNem_CNZCage, ArtNem_CNZCage
plreq ArtTile_ArtNem_CNZHexBumper, ArtNem_CNZHexBumper
plreq ArtTile_ArtNem_CNZRoundBumper, ArtNem_CNZRoundBumper
plreq ArtTile_ArtNem_CNZFlipper, ArtNem_CNZFlipper
plreq ArtTile_ArtNem_CNZMiniBumper, ArtNem_CNZMiniBumper
PlrList_Cnz1_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; CNZ Secondary
;---------------------------------------------------------------------------------------
PlrList_Cnz2: plrlistheader
plreq ArtTile_ArtNem_CNZDiagPlunger, ArtNem_CNZDiagPlunger
plreq ArtTile_ArtNem_CNZVertPlunger, ArtNem_CNZVertPlunger
plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes
plreq ArtTile_ArtNem_DignlSprng, ArtNem_DignlSprng
plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng
plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng
PlrList_Cnz2_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; CPZ Primary
;---------------------------------------------------------------------------------------
PlrList_Cpz1: plrlistheader
plreq ArtTile_ArtNem_CPZMetalThings, ArtNem_CPZMetalThings
plreq ArtTile_ArtNem_ConstructionStripes_2, ArtNem_ConstructionStripes
plreq ArtTile_ArtNem_CPZBooster, ArtNem_CPZBooster
plreq ArtTile_ArtNem_CPZElevator, ArtNem_CPZElevator
plreq ArtTile_ArtNem_CPZAnimatedBits, ArtNem_CPZAnimatedBits
plreq ArtTile_ArtNem_CPZTubeSpring, ArtNem_CPZTubeSpring
plreq ArtTile_ArtNem_WaterSurface, ArtNem_WaterSurface
plreq ArtTile_ArtNem_CPZStairBlock, ArtNem_CPZStairBlock
plreq ArtTile_ArtNem_CPZMetalBlock, ArtNem_CPZMetalBlock
PlrList_Cpz1_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; CPZ Secondary
;---------------------------------------------------------------------------------------
PlrList_Cpz2: plrlistheader
plreq ArtTile_ArtNem_Grabber, ArtNem_Grabber
plreq ArtTile_ArtNem_Spiny, ArtNem_Spiny
plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes
plreq ArtTile_ArtNem_DignlSprng, ArtNem_CPZDroplet
plreq ArtTile_ArtNem_LeverSpring, ArtNem_LeverSpring
plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng
plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng
PlrList_Cpz2_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; DEZ Primary
;---------------------------------------------------------------------------------------
PlrList_Dez1: plrlistheader
plreq ArtTile_ArtNem_ConstructionStripes_1, ArtNem_ConstructionStripes
PlrList_Dez1_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; DEZ Secondary
;---------------------------------------------------------------------------------------
PlrList_Dez2: plrlistheader
plreq ArtTile_ArtNem_SilverSonic, ArtNem_SilverSonic
plreq ArtTile_ArtNem_DEZWindow, ArtNem_DEZWindow
plreq ArtTile_ArtNem_RobotnikRunning, ArtNem_RobotnikRunning
plreq ArtTile_ArtNem_RobotnikUpper, ArtNem_RobotnikUpper
plreq ArtTile_ArtNem_RobotnikLower, ArtNem_RobotnikLower
PlrList_Dez2_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; ARZ Primary
;---------------------------------------------------------------------------------------
PlrList_Arz1: plrlistheader
plreq ArtTile_ArtNem_ARZBarrierThing, ArtNem_ARZBarrierThing
plreq ArtTile_ArtNem_WaterSurface, ArtNem_WaterSurface2
plreq ArtTile_ArtNem_Leaves, ArtNem_Leaves
plreq ArtTile_ArtNem_ArrowAndShooter, ArtNem_ArrowAndShooter
PlrList_Arz1_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; ARZ Secondary
;---------------------------------------------------------------------------------------
PlrList_Arz2: plrlistheader
plreq ArtTile_ArtNem_ChopChop, ArtNem_ChopChop
plreq ArtTile_ArtNem_Whisp, ArtNem_Whisp
plreq ArtTile_ArtNem_Grounder, ArtNem_Grounder
plreq ArtTile_ArtNem_BigBubbles, ArtNem_BigBubbles
plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes
plreq ArtTile_ArtNem_LeverSpring, ArtNem_LeverSpring
plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng
plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng
PlrList_Arz2_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; SCZ Primary
;---------------------------------------------------------------------------------------
PlrList_Scz1: plrlistheader
plreq ArtTile_ArtNem_Tornado, ArtNem_Tornado
PlrList_Scz1_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; SCZ Secondary
;---------------------------------------------------------------------------------------
PlrList_Scz2: plrlistheader
plreq ArtTile_ArtNem_Clouds, ArtNem_Clouds
plreq ArtTile_ArtNem_WfzVrtclPrpllr, ArtNem_WfzVrtclPrpllr
plreq ArtTile_ArtNem_WfzHrzntlPrpllr, ArtNem_WfzHrzntlPrpllr
plreq ArtTile_ArtNem_Balkrie, ArtNem_Balkrie
plreq ArtTile_ArtNem_Turtloid, ArtNem_Turtloid
plreq ArtTile_ArtNem_Nebula, ArtNem_Nebula
PlrList_Scz2_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; Sonic end of level results screen
;---------------------------------------------------------------------------------------
PlrList_Results: plrlistheader
plreq ArtTile_ArtNem_TitleCard, ArtNem_TitleCard
plreq ArtTile_ArtNem_ResultsText, ArtNem_ResultsText
plreq ArtTile_ArtNem_MiniCharacter, ArtNem_MiniSonic
plreq ArtTile_ArtNem_Perfect, ArtNem_Perfect
PlrList_Results_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; End of level signpost
;---------------------------------------------------------------------------------------
PlrList_Signpost: plrlistheader
plreq ArtTile_ArtNem_Signpost, ArtNem_Signpost
PlrList_Signpost_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; CPZ Boss
;---------------------------------------------------------------------------------------
PlrList_CpzBoss: plrlistheader
plreq ArtTile_ArtNem_Eggpod_3, ArtNem_Eggpod
plreq ArtTile_ArtNem_CPZBoss, ArtNem_CPZBoss
plreq ArtTile_ArtNem_EggpodJets_1, ArtNem_EggpodJets
plreq ArtTile_ArtNem_BossSmoke_1, ArtNem_BossSmoke
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_CpzBoss_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; EHZ Boss
;---------------------------------------------------------------------------------------
PlrList_EhzBoss: plrlistheader
plreq ArtTile_ArtNem_Eggpod_1, ArtNem_Eggpod
plreq ArtTile_ArtNem_EHZBoss, ArtNem_EHZBoss
plreq ArtTile_ArtNem_EggChoppers, ArtNem_EggChoppers
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_EhzBoss_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; HTZ Boss
;---------------------------------------------------------------------------------------
PlrList_HtzBoss: plrlistheader
plreq ArtTile_ArtNem_Eggpod_2, ArtNem_Eggpod
plreq ArtTile_ArtNem_HTZBoss, ArtNem_HTZBoss
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
plreq ArtTile_ArtNem_BossSmoke_2, ArtNem_BossSmoke
PlrList_HtzBoss_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; ARZ Boss
;---------------------------------------------------------------------------------------
PlrList_ArzBoss: plrlistheader
plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod
plreq ArtTile_ArtNem_ARZBoss, ArtNem_ARZBoss
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_ArzBoss_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; MCZ Boss
;---------------------------------------------------------------------------------------
PlrList_MczBoss: plrlistheader
plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod
plreq ArtTile_ArtNem_MCZBoss, ArtNem_MCZBoss
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_MczBoss_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; CNZ Boss
;---------------------------------------------------------------------------------------
PlrList_CnzBoss: plrlistheader
plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod
plreq ArtTile_ArtNem_CNZBoss, ArtNem_CNZBoss
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_CnzBoss_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; MTZ Boss
;---------------------------------------------------------------------------------------
PlrList_MtzBoss: plrlistheader
plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod
plreq ArtTile_ArtNem_MTZBoss, ArtNem_MTZBoss
plreq ArtTile_ArtNem_EggpodJets_2, ArtNem_EggpodJets
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_MtzBoss_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; OOZ Boss
;---------------------------------------------------------------------------------------
PlrList_OozBoss: plrlistheader
plreq ArtTile_ArtNem_OOZBoss, ArtNem_OOZBoss
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_OozBoss_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; Fiery Explosion
;---------------------------------------------------------------------------------------
PlrList_FieryExplosion: plrlistheader
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_FieryExplosion_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; Death Egg
;---------------------------------------------------------------------------------------
PlrList_DezBoss: plrlistheader
plreq ArtTile_ArtNem_DEZBoss, ArtNem_DEZBoss
PlrList_DezBoss_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; EHZ Animals
;---------------------------------------------------------------------------------------
PlrList_EhzAnimals: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Squirrel
plreq ArtTile_ArtNem_Animal_2, ArtNem_Bird
PlrList_EhzAnimals_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; MCZ Animals
;---------------------------------------------------------------------------------------
PlrList_MczAnimals: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Mouse
plreq ArtTile_ArtNem_Animal_2, ArtNem_Chicken
PlrList_MczAnimals_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; HTZ/MTZ/WFZ animals
;---------------------------------------------------------------------------------------
PlrList_HtzAnimals:
PlrList_MtzAnimals:
PlrList_WfzAnimals: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Beaver
plreq ArtTile_ArtNem_Animal_2, ArtNem_Eagle
PlrList_HtzAnimals_End
PlrList_MtzAnimals_End
PlrList_WfzAnimals_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; DEZ Animals
;---------------------------------------------------------------------------------------
PlrList_DezAnimals: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Pig
plreq ArtTile_ArtNem_Animal_2, ArtNem_Chicken
PlrList_DezAnimals_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; HPZ animals
;---------------------------------------------------------------------------------------
PlrList_HpzAnimals: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Mouse
plreq ArtTile_ArtNem_Animal_2, ArtNem_Seal
PlrList_HpzAnimals_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; OOZ Animals
;---------------------------------------------------------------------------------------
PlrList_OozAnimals: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Penguin
plreq ArtTile_ArtNem_Animal_2, ArtNem_Seal
PlrList_OozAnimals_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; SCZ Animals
;---------------------------------------------------------------------------------------
PlrList_SczAnimals: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Turtle
plreq ArtTile_ArtNem_Animal_2, ArtNem_Chicken
PlrList_SczAnimals_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; CNZ Animals
;---------------------------------------------------------------------------------------
PlrList_CnzAnimals: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Bear
plreq ArtTile_ArtNem_Animal_2, ArtNem_Bird
PlrList_CnzAnimals_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; CPZ Animals
;---------------------------------------------------------------------------------------
PlrList_CpzAnimals: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Rabbit
plreq ArtTile_ArtNem_Animal_2, ArtNem_Eagle
PlrList_CpzAnimals_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; ARZ Animals
;---------------------------------------------------------------------------------------
PlrList_ArzAnimals: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Penguin
plreq ArtTile_ArtNem_Animal_2, ArtNem_Bird
PlrList_ArzAnimals_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; Special Stage
;---------------------------------------------------------------------------------------
PlrList_SpecialStage: plrlistheader
plreq ArtTile_ArtNem_SpecialEmerald, ArtNem_SpecialEmerald
plreq ArtTile_ArtNem_SpecialMessages, ArtNem_SpecialMessages
plreq ArtTile_ArtNem_SpecialHUD, ArtNem_SpecialHUD
plreq ArtTile_ArtNem_SpecialFlatShadow, ArtNem_SpecialFlatShadow
plreq ArtTile_ArtNem_SpecialDiagShadow, ArtNem_SpecialDiagShadow
plreq ArtTile_ArtNem_SpecialSideShadow, ArtNem_SpecialSideShadow
plreq ArtTile_ArtNem_SpecialExplosion, ArtNem_SpecialExplosion
plreq ArtTile_ArtNem_SpecialRings, ArtNem_SpecialRings
plreq ArtTile_ArtNem_SpecialStart, ArtNem_SpecialStart
plreq ArtTile_ArtNem_SpecialPlayerVSPlayer, ArtNem_SpecialPlayerVSPlayer
plreq ArtTile_ArtNem_SpecialBack, ArtNem_SpecialBack
plreq ArtTile_ArtNem_SpecialStars, ArtNem_SpecialStars
plreq ArtTile_ArtNem_SpecialTailsText, ArtNem_SpecialTailsText
PlrList_SpecialStage_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; Special Stage Bombs
;---------------------------------------------------------------------------------------
PlrList_SpecStageBombs: plrlistheader
plreq ArtTile_ArtNem_SpecialBomb, ArtNem_SpecialBomb
PlrList_SpecStageBombs_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; WFZ Boss
;---------------------------------------------------------------------------------------
PlrList_WfzBoss: plrlistheader
plreq ArtTile_ArtNem_WFZBoss, ArtNem_WFZBoss
plreq ArtTile_ArtNem_RobotnikRunning, ArtNem_RobotnikRunning
plreq ArtTile_ArtNem_RobotnikUpper, ArtNem_RobotnikUpper
plreq ArtTile_ArtNem_RobotnikLower, ArtNem_RobotnikLower
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_WfzBoss_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; Tornado
;---------------------------------------------------------------------------------------
PlrList_Tornado: plrlistheader
plreq ArtTile_ArtNem_Tornado, ArtNem_Tornado
plreq ArtTile_ArtNem_TornadoThruster, ArtNem_TornadoThruster
plreq ArtTile_ArtNem_Clouds, ArtNem_Clouds
PlrList_Tornado_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; Capsule/Egg Prison
;---------------------------------------------------------------------------------------
PlrList_Capsule: plrlistheader
plreq ArtTile_ArtNem_Capsule, ArtNem_Capsule
PlrList_Capsule_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; Normal explosion
;---------------------------------------------------------------------------------------
PlrList_Explosion: plrlistheader
plreq ArtTile_ArtNem_Explosion, ArtNem_Explosion
PlrList_Explosion_End
;---------------------------------------------------------------------------------------
; Pattern load queue
; Tails end of level results screen
;---------------------------------------------------------------------------------------
PlrList_ResultsTails: plrlistheader
plreq ArtTile_ArtNem_TitleCard, ArtNem_TitleCard
plreq ArtTile_ArtNem_ResultsText, ArtNem_ResultsText
plreq ArtTile_ArtNem_MiniCharacter, ArtNem_MiniTails
plreq ArtTile_ArtNem_Perfect, ArtNem_Perfect
PlrList_ResultsTails_End
;---------------------------------------------------------------------------------------
; Weird revision-specific duplicates of portions of the PLR lists (unused)
;---------------------------------------------------------------------------------------
if gameRevision=0
; half of PlrList_ResultsTails
plreq ArtTile_ArtNem_MiniCharacter, ArtNem_MiniTails
plreq ArtTile_ArtNem_Perfect, ArtNem_Perfect
PlrList_ResultsTails_Dup_End
dc.l 0
elseif gameRevision=2
; half of the second ARZ PLR list
;plreq ArtTile_ArtNem_Grounder, ArtNem_Grounder ; cut in half
;dc.l ArtNem_Grounder
dc.w tiles_to_bytes(ArtTile_ArtNem_Grounder)
plreq ArtTile_ArtNem_BigBubbles, ArtNem_BigBubbles
plreq ArtTile_ArtNem_Spikes, ArtNem_Spikes
plreq ArtTile_ArtNem_LeverSpring, ArtNem_LeverSpring
plreq ArtTile_ArtNem_VrtclSprng, ArtNem_VrtclSprng
plreq ArtTile_ArtNem_HrzntlSprng, ArtNem_HrzntlSprng
PlrList_Arz2_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; SCZ Primary
;---------------------------------------------------------------------------------------
PlrList_Scz1_Dup: plrlistheader
plreq ArtTile_ArtNem_Tornado, ArtNem_Tornado
PlrList_Scz1_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; SCZ Secondary
;---------------------------------------------------------------------------------------
PlrList_Scz2_Dup: plrlistheader
plreq ArtTile_ArtNem_Clouds, ArtNem_Clouds
plreq ArtTile_ArtNem_WfzVrtclPrpllr, ArtNem_WfzVrtclPrpllr
plreq ArtTile_ArtNem_WfzHrzntlPrpllr, ArtNem_WfzHrzntlPrpllr
plreq ArtTile_ArtNem_Balkrie, ArtNem_Balkrie
plreq ArtTile_ArtNem_Turtloid, ArtNem_Turtloid
plreq ArtTile_ArtNem_Nebula, ArtNem_Nebula
PlrList_Scz2_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; Sonic end of level results screen
;---------------------------------------------------------------------------------------
PlrList_Results_Dup: plrlistheader
plreq ArtTile_ArtNem_TitleCard, ArtNem_TitleCard
plreq ArtTile_ArtNem_ResultsText, ArtNem_ResultsText
plreq ArtTile_ArtNem_MiniCharacter, ArtNem_MiniSonic
plreq ArtTile_ArtNem_Perfect, ArtNem_Perfect
PlrList_Results_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; End of level signpost
;---------------------------------------------------------------------------------------
PlrList_Signpost_Dup: plrlistheader
plreq ArtTile_ArtNem_Signpost, ArtNem_Signpost
PlrList_Signpost_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; CPZ Boss
;---------------------------------------------------------------------------------------
PlrList_CpzBoss_Dup: plrlistheader
plreq ArtTile_ArtNem_Eggpod_3, ArtNem_Eggpod
plreq ArtTile_ArtNem_CPZBoss, ArtNem_CPZBoss
plreq ArtTile_ArtNem_EggpodJets_1, ArtNem_EggpodJets
plreq ArtTile_ArtNem_BossSmoke_1, ArtNem_BossSmoke
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_CpzBoss_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; EHZ Boss
;---------------------------------------------------------------------------------------
PlrList_EhzBoss_Dup: plrlistheader
plreq ArtTile_ArtNem_Eggpod_1, ArtNem_Eggpod
plreq ArtTile_ArtNem_EHZBoss, ArtNem_EHZBoss
plreq ArtTile_ArtNem_EggChoppers, ArtNem_EggChoppers
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_EhzBoss_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; HTZ Boss
;---------------------------------------------------------------------------------------
PlrList_HtzBoss_Dup: plrlistheader
plreq ArtTile_ArtNem_Eggpod_2, ArtNem_Eggpod
plreq ArtTile_ArtNem_HTZBoss, ArtNem_HTZBoss
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
plreq ArtTile_ArtNem_BossSmoke_2, ArtNem_BossSmoke
PlrList_HtzBoss_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; ARZ Boss
;---------------------------------------------------------------------------------------
PlrList_ArzBoss_Dup: plrlistheader
plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod
plreq ArtTile_ArtNem_ARZBoss, ArtNem_ARZBoss
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_ArzBoss_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; MCZ Boss
;---------------------------------------------------------------------------------------
PlrList_MczBoss_Dup: plrlistheader
plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod
plreq ArtTile_ArtNem_MCZBoss, ArtNem_MCZBoss
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_MczBoss_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; CNZ Boss
;---------------------------------------------------------------------------------------
PlrList_CnzBoss_Dup: plrlistheader
plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod
plreq ArtTile_ArtNem_CNZBoss, ArtNem_CNZBoss
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_CnzBoss_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; MTZ Boss
;---------------------------------------------------------------------------------------
PlrList_MtzBoss_Dup: plrlistheader
plreq ArtTile_ArtNem_Eggpod_4, ArtNem_Eggpod
plreq ArtTile_ArtNem_MTZBoss, ArtNem_MTZBoss
plreq ArtTile_ArtNem_EggpodJets_2, ArtNem_EggpodJets
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_MtzBoss_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; OOZ Boss
;---------------------------------------------------------------------------------------
PlrList_OozBoss_Dup: plrlistheader
plreq ArtTile_ArtNem_OOZBoss, ArtNem_OOZBoss
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_OozBoss_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; Fiery Explosion
;---------------------------------------------------------------------------------------
PlrList_FieryExplosion_Dup: plrlistheader
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_FieryExplosion_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; Death Egg
;---------------------------------------------------------------------------------------
PlrList_DezBoss_Dup: plrlistheader
plreq ArtTile_ArtNem_DEZBoss, ArtNem_DEZBoss
PlrList_DezBoss_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; EHZ Animals
;---------------------------------------------------------------------------------------
PlrList_EhzAnimals_Dup: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Squirrel
plreq ArtTile_ArtNem_Animal_2, ArtNem_Bird
PlrList_EhzAnimals_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; MCZ Animals
;---------------------------------------------------------------------------------------
PlrList_MczAnimals_Dup: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Mouse
plreq ArtTile_ArtNem_Animal_2, ArtNem_Chicken
PlrList_MczAnimals_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; HTZ/MTZ/WFZ animals
;---------------------------------------------------------------------------------------
PlrList_HtzAnimals_Dup:
PlrList_MtzAnimals_Dup:
PlrList_WfzAnimals_Dup: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Beaver
plreq ArtTile_ArtNem_Animal_2, ArtNem_Eagle
PlrList_HtzAnimals_Dup_End
PlrList_MtzAnimals_Dup_End
PlrList_WfzAnimals_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; DEZ Animals
;---------------------------------------------------------------------------------------
PlrList_DezAnimals_Dup: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Pig
plreq ArtTile_ArtNem_Animal_2, ArtNem_Chicken
PlrList_DezAnimals_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; HPZ animals
;---------------------------------------------------------------------------------------
PlrList_HpzAnimals_Dup: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Mouse
plreq ArtTile_ArtNem_Animal_2, ArtNem_Seal
PlrList_HpzAnimals_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; OOZ Animals
;---------------------------------------------------------------------------------------
PlrList_OozAnimals_Dup: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Penguin
plreq ArtTile_ArtNem_Animal_2, ArtNem_Seal
PlrList_OozAnimals_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; SCZ Animals
;---------------------------------------------------------------------------------------
PlrList_SczAnimals_Dup: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Turtle
plreq ArtTile_ArtNem_Animal_2, ArtNem_Chicken
PlrList_SczAnimals_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; CNZ Animals
;---------------------------------------------------------------------------------------
PlrList_CnzAnimals_Dup: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Bear
plreq ArtTile_ArtNem_Animal_2, ArtNem_Bird
PlrList_CnzAnimals_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; CPZ Animals
;---------------------------------------------------------------------------------------
PlrList_CpzAnimals_Dup: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Rabbit
plreq ArtTile_ArtNem_Animal_2, ArtNem_Eagle
PlrList_CpzAnimals_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; ARZ Animals
;---------------------------------------------------------------------------------------
PlrList_ArzAnimals_Dup: plrlistheader
plreq ArtTile_ArtNem_Animal_1, ArtNem_Penguin
plreq ArtTile_ArtNem_Animal_2, ArtNem_Bird
PlrList_ArzAnimals_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; Special Stage
;---------------------------------------------------------------------------------------
PlrList_SpecialStage_Dup: plrlistheader
plreq ArtTile_ArtNem_SpecialEmerald, ArtNem_SpecialEmerald
plreq ArtTile_ArtNem_SpecialMessages, ArtNem_SpecialMessages
plreq ArtTile_ArtNem_SpecialHUD, ArtNem_SpecialHUD
plreq ArtTile_ArtNem_SpecialFlatShadow, ArtNem_SpecialFlatShadow
plreq ArtTile_ArtNem_SpecialDiagShadow, ArtNem_SpecialDiagShadow
plreq ArtTile_ArtNem_SpecialSideShadow, ArtNem_SpecialSideShadow
plreq ArtTile_ArtNem_SpecialExplosion, ArtNem_SpecialExplosion
plreq ArtTile_ArtNem_SpecialRings, ArtNem_SpecialRings
plreq ArtTile_ArtNem_SpecialStart, ArtNem_SpecialStart
plreq ArtTile_ArtNem_SpecialPlayerVSPlayer, ArtNem_SpecialPlayerVSPlayer
plreq ArtTile_ArtNem_SpecialBack, ArtNem_SpecialBack
plreq ArtTile_ArtNem_SpecialStars, ArtNem_SpecialStars
plreq ArtTile_ArtNem_SpecialTailsText, ArtNem_SpecialTailsText
PlrList_SpecialStage_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; Special Stage Bombs
;---------------------------------------------------------------------------------------
PlrList_SpecStageBombs_Dup: plrlistheader
plreq ArtTile_ArtNem_SpecialBomb, ArtNem_SpecialBomb
PlrList_SpecStageBombs_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; WFZ Boss
;---------------------------------------------------------------------------------------
PlrList_WfzBoss_Dup: plrlistheader
plreq ArtTile_ArtNem_WFZBoss, ArtNem_WFZBoss
plreq ArtTile_ArtNem_RobotnikRunning, ArtNem_RobotnikRunning
plreq ArtTile_ArtNem_RobotnikUpper, ArtNem_RobotnikUpper
plreq ArtTile_ArtNem_RobotnikLower, ArtNem_RobotnikLower
plreq ArtTile_ArtNem_FieryExplosion, ArtNem_FieryExplosion
PlrList_WfzBoss_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; Tornado
;---------------------------------------------------------------------------------------
PlrList_Tornado_Dup: plrlistheader
plreq ArtTile_ArtNem_Tornado, ArtNem_Tornado
plreq ArtTile_ArtNem_TornadoThruster, ArtNem_TornadoThruster
plreq ArtTile_ArtNem_Clouds, ArtNem_Clouds
PlrList_Tornado_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; Capsule/Egg Prison
;---------------------------------------------------------------------------------------
PlrList_Capsule_Dup: plrlistheader
plreq ArtTile_ArtNem_Capsule, ArtNem_Capsule
PlrList_Capsule_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; Normal explosion
;---------------------------------------------------------------------------------------
PlrList_Explosion_Dup: plrlistheader
plreq ArtTile_ArtNem_Explosion, ArtNem_Explosion
PlrList_Explosion_Dup_End
;---------------------------------------------------------------------------------------
; Pattern load queue (duplicate)
; Tails end of level results screen
;---------------------------------------------------------------------------------------
PlrList_ResultsTails_Dup: plrlistheader
plreq ArtTile_ArtNem_TitleCard, ArtNem_TitleCard
plreq ArtTile_ArtNem_ResultsText, ArtNem_ResultsText
plreq ArtTile_ArtNem_MiniCharacter, ArtNem_MiniTails
plreq ArtTile_ArtNem_Perfect, ArtNem_Perfect
PlrList_ResultsTails_Dup_End
endif
;---------------------------------------------------------------------------------------
; Curve and resistance mapping
;---------------------------------------------------------------------------------------
ColCurveMap: BINCLUDE "collision/Curve and resistance mapping.bin"
even
;--------------------------------------------------------------------------------------
; Collision arrays
;--------------------------------------------------------------------------------------
ColArray: BINCLUDE "collision/Collision array 1.bin"
ColArray2: BINCLUDE "collision/Collision array 2.bin"
even
;---------------------------------------------------------------------------------------
; EHZ and HTZ primary 16x16 collision index (Kosinski compression)
ColP_EHZHTZ: BINCLUDE "collision/EHZ and HTZ primary 16x16 collision index.bin"
even
;---------------------------------------------------------------------------------------
; EHZ and HTZ secondary 16x16 collision index (Kosinski compression)
ColS_EHZHTZ: BINCLUDE "collision/EHZ and HTZ secondary 16x16 collision index.bin"
even
;---------------------------------------------------------------------------------------
; MTZ primary 16x16 collision index (Kosinski compression)
ColP_MTZ: BINCLUDE "collision/MTZ primary 16x16 collision index.bin"
even
;---------------------------------------------------------------------------------------
; HPZ primary 16x16 collision index (Kosinski compression)
ColP_HPZ: ;BINCLUDE "collision/HPZ primary 16x16 collision index.bin"
;even
;---------------------------------------------------------------------------------------
; HPZ secondary 16x16 collision index (Kosinski compression)
ColS_HPZ: ;BINCLUDE "collision/HPZ secondary 16x16 collision index.bin"
;even
;---------------------------------------------------------------------------------------
; OOZ primary 16x16 collision index (Kosinski compression)
ColP_OOZ: BINCLUDE "collision/OOZ primary 16x16 collision index.bin"
even
;---------------------------------------------------------------------------------------
; MCZ primary 16x16 collision index (Kosinski compression)
ColP_MCZ: BINCLUDE "collision/MCZ primary 16x16 collision index.bin"
even
;---------------------------------------------------------------------------------------
; CNZ primary 16x16 collision index (Kosinski compression)
ColP_CNZ: BINCLUDE "collision/CNZ primary 16x16 collision index.bin"
even
;---------------------------------------------------------------------------------------
; CNZ secondary 16x16 collision index (Kosinski compression)
ColS_CNZ: BINCLUDE "collision/CNZ secondary 16x16 collision index.bin"
even
;---------------------------------------------------------------------------------------
; CPZ and DEZ primary 16x16 collision index (Kosinski compression)
ColP_CPZDEZ: BINCLUDE "collision/CPZ and DEZ primary 16x16 collision index.bin"
even
;---------------------------------------------------------------------------------------
; CPZ and DEZ secondary 16x16 collision index (Kosinski compression)
ColS_CPZDEZ: BINCLUDE "collision/CPZ and DEZ secondary 16x16 collision index.bin"
even
;---------------------------------------------------------------------------------------
; ARZ primary 16x16 collision index (Kosinski compression)
ColP_ARZ: BINCLUDE "collision/ARZ primary 16x16 collision index.bin"
even
;---------------------------------------------------------------------------------------
; ARZ secondary 16x16 collision index (Kosinski compression)
ColS_ARZ: BINCLUDE "collision/ARZ secondary 16x16 collision index.bin"
even
;---------------------------------------------------------------------------------------
; WFZ/SCZ primary 16x16 collision index (Kosinski compression)
ColP_WFZSCZ: BINCLUDE "collision/WFZ and SCZ primary 16x16 collision index.bin"
even
;---------------------------------------------------------------------------------------
; WFZ/SCZ secondary 16x16 collision index (Kosinski compression)
ColS_WFZSCZ: BINCLUDE "collision/WFZ and SCZ secondary 16x16 collision index.bin"
even
;---------------------------------------------------------------------------------------
ColP_Invalid:
;---------------------------------------------------------------------------------------
; Offset index of level layouts
; Two entries per zone, pointing to the level layouts for acts 1 and 2 of each zone
; respectively.
;---------------------------------------------------------------------------------------
Off_Level: zoneOrderedOffsetTable 2,2
zoneOffsetTableEntry.w Level_EHZ1
zoneOffsetTableEntry.w Level_EHZ2 ; 1
zoneOffsetTableEntry.w Level_EHZ1 ; 2
zoneOffsetTableEntry.w Level_EHZ1 ; 3
zoneOffsetTableEntry.w Level_EHZ1 ; 4
zoneOffsetTableEntry.w Level_EHZ1 ; 5
zoneOffsetTableEntry.w Level_EHZ1 ; 6
zoneOffsetTableEntry.w Level_EHZ1 ; 7
zoneOffsetTableEntry.w Level_MTZ1 ; 8
zoneOffsetTableEntry.w Level_MTZ2 ; 9
zoneOffsetTableEntry.w Level_MTZ3 ; 10
zoneOffsetTableEntry.w Level_MTZ3 ; 11
zoneOffsetTableEntry.w Level_WFZ ; 12
zoneOffsetTableEntry.w Level_WFZ ; 13
zoneOffsetTableEntry.w Level_HTZ1 ; 14
zoneOffsetTableEntry.w Level_HTZ2 ; 15
zoneOffsetTableEntry.w Level_HPZ1 ; 16
zoneOffsetTableEntry.w Level_HPZ1 ; 17
zoneOffsetTableEntry.w Level_EHZ1 ; 18
zoneOffsetTableEntry.w Level_EHZ1 ; 19
zoneOffsetTableEntry.w Level_OOZ1 ; 20
zoneOffsetTableEntry.w Level_OOZ2 ; 21
zoneOffsetTableEntry.w Level_MCZ1 ; 22
zoneOffsetTableEntry.w Level_MCZ2 ; 23
zoneOffsetTableEntry.w Level_CNZ1 ; 24
zoneOffsetTableEntry.w Level_CNZ2 ; 25
zoneOffsetTableEntry.w Level_CPZ1 ; 26
zoneOffsetTableEntry.w Level_CPZ2 ; 27
zoneOffsetTableEntry.w Level_DEZ ; 28
zoneOffsetTableEntry.w Level_DEZ ; 29
zoneOffsetTableEntry.w Level_ARZ1 ; 30
zoneOffsetTableEntry.w Level_ARZ2 ; 31
zoneOffsetTableEntry.w Level_SCZ ; 32
zoneOffsetTableEntry.w Level_SCZ ; 33
zoneTableEnd
;---------------------------------------------------------------------------------------
; EHZ act 1 level layout (Kosinski compression)
Level_EHZ1: BINCLUDE "level/layout/EHZ_1.bin"
even
;---------------------------------------------------------------------------------------
; EHZ act 2 level layout (Kosinski compression)
Level_EHZ2: BINCLUDE "level/layout/EHZ_2.bin"
even
;---------------------------------------------------------------------------------------
; MTZ act 1 level layout (Kosinski compression)
Level_MTZ1: BINCLUDE "level/layout/MTZ_1.bin"
even
;---------------------------------------------------------------------------------------
; MTZ act 2 level layout (Kosinski compression)
Level_MTZ2: BINCLUDE "level/layout/MTZ_2.bin"
even
;---------------------------------------------------------------------------------------
; MTZ act 3 level layout (Kosinski compression)
Level_MTZ3: BINCLUDE "level/layout/MTZ_3.bin"
even
;---------------------------------------------------------------------------------------
; WFZ level layout (Kosinski compression)
Level_WFZ: BINCLUDE "level/layout/WFZ.bin"
even
;---------------------------------------------------------------------------------------
; HTZ act 1 level layout (Kosinski compression)
Level_HTZ1: BINCLUDE "level/layout/HTZ_1.bin"
even
;---------------------------------------------------------------------------------------
; HTZ act 2 level layout (Kosinski compression)
Level_HTZ2: BINCLUDE "level/layout/HTZ_2.bin"
even
;---------------------------------------------------------------------------------------
; HPZ act 1 level layout (Kosinski compression)
Level_HPZ1: ;BINCLUDE "level/layout/HPZ_1.bin"
;even
;---------------------------------------------------------------------------------------
; OOZ act 1 level layout (Kosinski compression)
Level_OOZ1: BINCLUDE "level/layout/OOZ_1.bin"
even
;---------------------------------------------------------------------------------------
; OOZ act 2 level layout (Kosinski compression)
Level_OOZ2: BINCLUDE "level/layout/OOZ_2.bin"
even
;---------------------------------------------------------------------------------------
; MCZ act 1 level layout (Kosinski compression)
Level_MCZ1: BINCLUDE "level/layout/MCZ_1.bin"
even
;---------------------------------------------------------------------------------------
; MCZ act 2 level layout (Kosinski compression)
Level_MCZ2: BINCLUDE "level/layout/MCZ_2.bin"
even
;---------------------------------------------------------------------------------------
; CNZ act 1 level layout (Kosinski compression)
Level_CNZ1: BINCLUDE "level/layout/CNZ_1.bin"
even
;---------------------------------------------------------------------------------------
; CNZ act 2 level layout (Kosinski compression)
Level_CNZ2: BINCLUDE "level/layout/CNZ_2.bin"
even
;---------------------------------------------------------------------------------------
; CPZ act 1 level layout (Kosinski compression)
Level_CPZ1: BINCLUDE "level/layout/CPZ_1.bin"
even
;---------------------------------------------------------------------------------------
; CPZ act 2 level layout (Kosinski compression)
Level_CPZ2: BINCLUDE "level/layout/CPZ_2.bin"
even
;---------------------------------------------------------------------------------------
; DEZ level layout (Kosinski compression)
Level_DEZ: BINCLUDE "level/layout/DEZ.bin"
even
;---------------------------------------------------------------------------------------
; ARZ act 1 level layout (Kosinski compression)
Level_ARZ1: BINCLUDE "level/layout/ARZ_1.bin"
even
;---------------------------------------------------------------------------------------
; ARZ act 2 level layout (Kosinski compression)
Level_ARZ2: BINCLUDE "level/layout/ARZ_2.bin"
even
;---------------------------------------------------------------------------------------
; SCZ level layout (Kosinski compression)
Level_SCZ: BINCLUDE "level/layout/SCZ.bin"
even
;---------------------------------------------------------------------------------------
; Uncompressed art
; Animated flowers in EHZ and HTZ ; ArtUnc_49714: ArtUnc_49794: ArtUnc_49814: ArtUnc_49894:
;---------------------------------------------------------------------------------------
ArtUnc_Flowers1: BINCLUDE "art/uncompressed/EHZ and HTZ flowers - 1.bin"
ArtUnc_Flowers2: BINCLUDE "art/uncompressed/EHZ and HTZ flowers - 2.bin"
ArtUnc_Flowers3: BINCLUDE "art/uncompressed/EHZ and HTZ flowers - 3.bin"
ArtUnc_Flowers4: BINCLUDE "art/uncompressed/EHZ and HTZ flowers - 4.bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Pulsing thing against checkered backing from EHZ ; ArtUnc_49914:
ArtUnc_EHZPulseBall: BINCLUDE "art/uncompressed/Pulsing ball against checkered background (EHZ).bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (192 blocks)
; Dynamically reloaded cliffs in background from HTZ ; ArtNem_49A14: ArtUnc_HTZCliffs:
ArtNem_HTZCliffs: BINCLUDE "art/nemesis/Dynamically reloaded cliffs in HTZ background.bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Dynamically reloaded clouds in background from HTZ ; ArtUnc_4A33E:
ArtUnc_HTZClouds: BINCLUDE "art/uncompressed/Background clouds (HTZ).bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Spinning metal cylinder patterns in MTZ ; ArtUnc_4A73E:
ArtUnc_MTZCylinder: BINCLUDE "art/uncompressed/Spinning metal cylinder (MTZ).bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Lava patterns in MTZ and HTZ ; ArtUnc_4B73E:
ArtUnc_Lava: BINCLUDE "art/uncompressed/Lava.bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Animated section of MTZ background ; ArtUnc_4BD3E:
ArtUnc_MTZAnimBack: BINCLUDE "art/uncompressed/Animated section of MTZ background.bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Pulsing orb in HPZ
ArtUnc_HPZPulseOrb: ;BINCLUDE "art/uncompressed/Pulsing orb (HPZ).bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Pulsing ball in OOZ ; ArtUnc_4BF7E:
ArtUnc_OOZPulseBall: BINCLUDE "art/uncompressed/Pulsing ball (OOZ).bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Square rotating around ball in OOZ ; ArtUnc_4C0FE: ArtUnc_4C2FE:
ArtUnc_OOZSquareBall1: BINCLUDE "art/uncompressed/Square rotating around ball in OOZ - 1.bin"
ArtUnc_OOZSquareBall2: BINCLUDE "art/uncompressed/Square rotating around ball in OOZ - 2.bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Oil in OOZ ; ArtUnc_4C4FE: ArtUnc_4CCFE:
ArtUnc_Oil1: BINCLUDE "art/uncompressed/Oil - 1.bin"
ArtUnc_Oil2: BINCLUDE "art/uncompressed/Oil - 2.bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Flipping foreground section in CNZ ; ArtUnc_4D4FE:
ArtUnc_CNZFlipTiles: BINCLUDE "art/uncompressed/Flipping foreground section (CNZ).bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Bonus pictures for slots in CNZ ; ArtUnc_4EEFE:
ArtUnc_CNZSlotPics: BINCLUDE "art/uncompressed/Slot pictures.bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Animated background section in CPZ and DEZ ; ArtUnc_4FAFE:
ArtUnc_CPZAnimBack: BINCLUDE "art/uncompressed/Animated background section (CPZ and DEZ).bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Waterfall patterns from ARZ ; ArtUnc_4FCFE: ArtUnc_4FDFE: ArtUnc_4FEFE:
ArtUnc_Waterfall1: BINCLUDE "art/uncompressed/ARZ waterfall patterns - 1.bin"
ArtUnc_Waterfall2: BINCLUDE "art/uncompressed/ARZ waterfall patterns - 2.bin"
ArtUnc_Waterfall3: BINCLUDE "art/uncompressed/ARZ waterfall patterns - 3.bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Patterns for Sonic ; ArtUnc_50000:
;---------------------------------------------------------------------------------------
align $20
ArtUnc_Sonic: BINCLUDE "art/uncompressed/Sonic's art.bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Patterns for Tails ; ArtUnc_64320:
;---------------------------------------------------------------------------------------
align $20
ArtUnc_Tails: BINCLUDE "art/uncompressed/Tails's art.bin"
;--------------------------------------------------------------------------------------
; Sprite Mappings
; Sonic ; MapUnc_6FBE0: SprTbl_Sonic:
;--------------------------------------------------------------------------------------
Mapunc_Sonic: BINCLUDE "mappings/sprite/Sonic.bin"
;--------------------------------------------------------------------------------------
; Sprite Dynamic Pattern Reloading
; Sonic DPLCs ; MapRUnc_714E0:
;--------------------------------------------------------------------------------------
; WARNING: the build script needs editing if you rename this label
; or if you move Sonic's running frame to somewhere else than frame $2D
MapRUnc_Sonic: BINCLUDE "mappings/spriteDPLC/Sonic.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (32 blocks)
; Shield ; ArtNem_71D8E:
ArtNem_Shield: BINCLUDE "art/nemesis/Shield.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (34 blocks)
; Invincibility stars ; ArtNem_71F14:
ArtNem_Invincible_stars: BINCLUDE "art/nemesis/Invincibility stars.bin"
;--------------------------------------------------------------------------------------
; Uncompressed art
; Splash in water ; ArtUnc_71FFC:
ArtUnc_Splash: BINCLUDE "art/uncompressed/Splash.bin"
;--------------------------------------------------------------------------------------
; Uncompressed art
; Smoke from Skidding ; ArtUnc_7373C:
ArtUnc_SkidDust: BINCLUDE "art/uncompressed/Skid smoke.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (14 blocks)
; Supersonic stars ; ArtNem_7393C:
ArtNem_SuperSonic_stars: BINCLUDE "art/nemesis/Super Sonic stars.bin"
;--------------------------------------------------------------------------------------
; Sprite Mappings
; Tails ; MapUnc_739E2:
;--------------------------------------------------------------------------------------
MapUnc_Tails: BINCLUDE "mappings/sprite/Tails.bin"
;--------------------------------------------------------------------------------------
; Sprite Dynamic Pattern Reloading
; Tails DPLCs ; MapRUnc_7446C:
;--------------------------------------------------------------------------------------
MapRUnc_Tails: BINCLUDE "mappings/spriteDPLC/Tails.bin"
;-------------------------------------------------------------------------------------
; Nemesis compressed art (127 blocks)
; "SEGA" Patterns ; ArtNem_74876:
ArtNem_SEGA: BINCLUDE "art/nemesis/SEGA.bin"
;-------------------------------------------------------------------------------------
; Nemesis compressed art (9 blocks)
; Shaded blocks from intro ; ArtNem_74CF6:
ArtNem_IntroTrails: BINCLUDE "art/nemesis/Shaded blocks from intro.bin"
;---------------------------------------------------------------------------------------
; Enigma compressed art mappings
; "SEGA" mappings ; MapEng_74D0E:
MapEng_SEGA: BINCLUDE "mappings/misc/SEGA mappings.bin"
;---------------------------------------------------------------------------------------
; Enigma compressed art mappings
; Mappings for title screen background ; ArtNem_74DC6:
MapEng_TitleScreen: BINCLUDE "mappings/misc/Mappings for title screen background.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed art mappings
; Mappings for title screen background (smaller part, water/horizon) ; MapEng_74E3A:
MapEng_TitleBack: BINCLUDE "mappings/misc/Mappings for title screen background 2.bin"
;---------------------------------------------------------------------------------------
; Enigma compressed art mappings
; "Sonic the Hedgehog 2" title screen logo mappings ; MapEng_74E86:
MapEng_TitleLogo: BINCLUDE "mappings/misc/Sonic the Hedgehog 2 title screen logo mappings.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (336 blocks)
; Main patterns from title screen ; ArtNem_74F6C:
even
ArtNem_Title: BINCLUDE "art/nemesis/Main patterns from title screen.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (674 blocks)
; Sonic and tails from title screen ; ArtNem_7667A:
even
ArtNem_TitleSprites: BINCLUDE "art/nemesis/Sonic and Tails from title screen.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (10 blocks)
; A few menu patterns ; ArtNem_78CBC:
even
ArtNem_MenuJunk: BINCLUDE "art/nemesis/A few menu blocks.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (16 blocks)
; Button ArtNem_78DAC:
even
ArtNem_Button: BINCLUDE "art/nemesis/Button.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (20 blocks)
; Vertical Spring ArtNem_78E84:
even
ArtNem_VrtclSprng: BINCLUDE "art/nemesis/Vertical spring.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (12 blocks)
; Horizontal spring ArtNem_78FA0:
even
ArtNem_HrzntlSprng: BINCLUDE "art/nemesis/Horizontal spring.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (32 blocks)
; Diagonal spring ArtNem_7906A:
even
ArtNem_DignlSprng: BINCLUDE "art/nemesis/Diagonal spring.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (24 blocks)
; Score, Rings, Time patterns ArtNem_7923E:
even
ArtNem_HUD: BINCLUDE "art/nemesis/HUD.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (12 blocks)
; Sonic lives counter ArtNem_79346:
even
ArtNem_Sonic_life_counter: BINCLUDE "art/nemesis/Sonic lives counter.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (14 blocks)
; Ring ArtNem_7945C:
even
ArtNem_Ring: BINCLUDE "art/nemesis/Ring.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (60 blocks)
; Monitors and contents ArtNem_79550:
even
ArtNem_Powerups: BINCLUDE "art/nemesis/Monitor and contents.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (8 blocks)
; Spikes 7995C:
even
ArtNem_Spikes: BINCLUDE "art/nemesis/Spikes.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (18 blocks)
; Numbers 799AC:
even
ArtNem_Numbers: BINCLUDE "art/nemesis/Numbers.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (16 blocks)
; Star pole 79A86:
even
ArtNem_Checkpoint: BINCLUDE "art/nemesis/Star pole.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (78 blocks)
; Signpost ; ArtNem_79BDE:
even
ArtNem_Signpost: BINCLUDE "art/nemesis/Signpost.bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Signpost ; ArtUnc_7A18A:
; Yep, it's in the ROM twice: once compressed and once uncompressed
even
ArtUnc_Signpost: BINCLUDE "art/uncompressed/Signpost.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (28 blocks)
; Lever spring ; ArtNem_7AB4A:
even
ArtNem_LeverSpring: BINCLUDE "art/nemesis/Lever spring.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (8 blocks)
; Long horizontal spike ; ArtNem_7AC9A:
even
ArtNem_HorizSpike: BINCLUDE "art/nemesis/Long horizontal spike.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (24 blocks)
; Bubble thing from underwater ; ArtNem_7AD16:
even
ArtNem_BigBubbles: BINCLUDE "art/nemesis/Bubble generator.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (10 blocks)
; Bubbles from character 7AEE2:
even
ArtNem_Bubbles: BINCLUDE "art/nemesis/Bubbles.bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Countdown text for drowning ; ArtUnc_7AF80:
even
ArtUnc_Countdown: BINCLUDE "art/uncompressed/Numbers for drowning countdown.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (34 blocks)
; Game/Time over text 7B400:
even
ArtNem_Game_Over: BINCLUDE "art/nemesis/Game and Time Over text.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (68 blocks)
; Explosion 7B592:
even
ArtNem_Explosion: BINCLUDE "art/nemesis/Explosion.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (12 blocks)
; Miles life counter ; ArtNem_7B946:
even
ArtUnc_MilesLife: BINCLUDE "art/nemesis/Miles life counter.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (49 blocks)
; Egg prison ; ArtNem_7BA32:
even
ArtNem_Capsule: BINCLUDE "art/nemesis/Egg Prison.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (36 blocks)
; Tails on the continue screen (nagging Sonic) ; ArtNem_7BDBE:
even
ArtNem_ContinueTails: BINCLUDE "art/nemesis/Tails on continue screen.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (12 blocks)
; Sonic extra continue icon ; ArtNem_7C0AA:
even
ArtNem_MiniSonic: BINCLUDE "art/nemesis/Sonic continue.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (12 blocks)
; Tails life counter ; ArtNem_7C20C:
even
ArtNem_TailsLife: BINCLUDE "art/nemesis/Tails life counter.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (12 blocks)
; Tails extra continue icon ; ArtNem_7C2F2:
even
ArtNem_MiniTails: BINCLUDE "art/nemesis/Tails continue.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (88 blocks)
; Standard font ; ArtNem_7C43A:
even
ArtNem_FontStuff: BINCLUDE "art/nemesis/Standard font.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (38 blocks)
; 1P/2P wins text from 2P mode ; ArtNem_7C9AE:
even
ArtNem_1P2PWins: BINCLUDE "art/nemesis/1P and 2P wins text from 2P mode.bin"
;---------------------------------------------------------------------------------------
; Enigma compressed art mappings
; Sonic/Miles animated background mappings ; MapEng_7CB80:
MapEng_MenuBack: BINCLUDE "mappings/misc/Sonic and Miles animated background.bin"
;---------------------------------------------------------------------------------------
; Uncompressed art
; Sonic/Miles animated background patterns ; ArtUnc_7CD2C:
even
ArtUnc_MenuBack: BINCLUDE "art/uncompressed/Sonic and Miles animated background.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (94 blocks)
; Title card patterns ; ArtNem_7D22C:
even
ArtNem_TitleCard: BINCLUDE "art/nemesis/Title card.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (92 blocks)
; Alphabet for font using large broken letters ; ArtNem_7D58A:
even
ArtNem_TitleCard2: BINCLUDE "art/nemesis/Font using large broken letters.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (21 blocks)
; A menu box with a shadow ; ArtNem_7D990:
even
ArtNem_MenuBox: BINCLUDE "art/nemesis/A menu box with a shadow.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (170 blocks)
; Pictures in level preview box in level select ; ArtNem_7DA10:
even
ArtNem_LevelSelectPics: BINCLUDE "art/nemesis/Pictures in level preview box from level select.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (68 blocks)
; Text for Sonic or Tails Got Through Act and Bonus/Perfect ; ArtNem_7E86A:
even
ArtNem_ResultsText: BINCLUDE "art/nemesis/End of level results text.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (72 blocks)
; Text for end of special stage, along with patterns for 3 emeralds. ; ArtNem_7EB58:
even
ArtNem_SpecialStageResults: BINCLUDE "art/nemesis/Special stage results screen art and some emeralds.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (14 blocks)
; "Perfect" text ; ArtNem_7EEBE:
even
ArtNem_Perfect: BINCLUDE "art/nemesis/Perfect text.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (16 blocks)
; Flicky ; ArtNem_7EF60:
even
ArtNem_Bird: BINCLUDE "art/nemesis/Flicky.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (20 blocks)
; Squirrel ; ArtNem_7F0A2:
even
ArtNem_Squirrel: BINCLUDE "art/nemesis/Squirrel.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (16 blocks)
; Mouse ; ArtNem_7F206:
even
ArtNem_Mouse: BINCLUDE "art/nemesis/Mouse.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (16 blocks)
; Chicken ; ArtNem_7F340:
even
ArtNem_Chicken: BINCLUDE "art/nemesis/Chicken.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (20 blocks)
; Beaver ; ArtNem_7F4A2:
even
ArtNem_Beaver: BINCLUDE "art/nemesis/Beaver.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (16 blocks)
; Some bird ; ArtNem_7F5E2:
even
ArtNem_Eagle: BINCLUDE "art/nemesis/Penguin.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (10 blocks)
; Pig ; ArtNem_7F710:
even
ArtNem_Pig: BINCLUDE "art/nemesis/Pig.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (14 blocks)
; Seal ; ArtNem_7F846:
even
ArtNem_Seal: BINCLUDE "art/nemesis/Seal.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (18 blocks)
; Penguin ; ArtNem_7F962:
even
ArtNem_Penguin: BINCLUDE "art/nemesis/Penguin 2.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (20 blocks)
; Turtle ; ArtNem_7FADE:
even
ArtNem_Turtle: BINCLUDE "art/nemesis/Turtle.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (20 blocks)
; Bear ; ArtNem_7FC90:
even
ArtNem_Bear: BINCLUDE "art/nemesis/Bear.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (18 blocks)
; Splats ; ArtNem_7FDD2:
even
ArtNem_Rabbit: BINCLUDE "art/nemesis/Rabbit.bin"
;---------------------------------------------------------------------------------------
; Nemesis compressed art (4 blocks)
; Rivet thing that you bust to get inside ship at the end of WFZ ; ArtNem_7FF2A:
even
ArtNem_WfzSwitch: BINCLUDE "art/nemesis/WFZ boss chamber switch.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (15 blocks)
; Breakaway panels in WFZ ; ArtNem_7FF98:
even
ArtNem_BreakPanels: BINCLUDE "art/nemesis/Breakaway panels from WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (32 blocks)
; Spiked thing from OOZ ; ArtNem_8007C:
even
ArtNem_SpikyThing: BINCLUDE "art/nemesis/Spiked ball from OOZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (6 blocks)
; Green platform over the burners in OOZ ; ArtNem_80274:
even
ArtNem_BurnerLid: BINCLUDE "art/nemesis/Burner Platform from OOZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (4 blocks)
; Striped blocks from OOZ ; ArtNem_8030A:
even
ArtNem_StripedBlocksVert: BINCLUDE "art/nemesis/Striped blocks from CPZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (16 blocks)
; Oil splashing into oil in OOZ ; ArtNem_80376:
even
ArtNem_Oilfall: BINCLUDE "art/nemesis/Cascading oil hitting oil from OOZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (13 blocks)
; Cascading oil from OOZ ; ArtNem_804F2:
even
ArtNem_Oilfall2: BINCLUDE "art/nemesis/Cascading oil from OOZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (20 blocks)
; Ball thing (unused?) from OOZ ; ArtNem_805C0:
even
ArtNem_BallThing: BINCLUDE "art/nemesis/Ball on spring from OOZ (beta holdovers).bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (53 blocks)
; Spinball from OOZ ; ArtNem_806E0:
even
ArtNem_LaunchBall: BINCLUDE "art/nemesis/Transporter ball from OOZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (40 blocks)
; Collapsing platform from OOZ ; ArtNem_809D0:
even
ArtNem_OOZPlatform: BINCLUDE "art/nemesis/OOZ collapsing platform.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (30 blocks)
; Diagonal and vertical weird spring from OOZ ; ArtNem_80C64:
even
ArtNem_PushSpring: BINCLUDE "art/nemesis/Push spring from OOZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (28 blocks)
; Swinging platform from OOZ ; ArtNem_80E26:
even
ArtNem_OOZSwingPlat: BINCLUDE "art/nemesis/Swinging platform from OOZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (4 blocks)
; 4 stripy blocks from OOZ ; ArtNem_81048:
even
ArtNem_StripedBlocksHoriz: BINCLUDE "art/nemesis/4 stripy blocks from OOZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (24 blocks)
; Raising platform from OOZ ; ArtNem_810B8:
even
ArtNem_OOZElevator: BINCLUDE "art/nemesis/Rising platform from OOZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (30 blocks)
; Fan in OOZ ; ArtNem_81254:
even
ArtNem_OOZFanHoriz: BINCLUDE "art/nemesis/Fan from OOZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (18 blocks)
; Green flame thing that shoots platform up in OOZ ; ArtNem_81514:
even
ArtNem_OOZBurn: BINCLUDE "art/nemesis/Green flame from OOZ burners.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (4 blocks)
; Patterns for appearing and disappearing string of platforms in CNZ ; ArtNem_81600:
even
ArtNem_CNZSnake: BINCLUDE "art/nemesis/Caterpiller platforms from CNZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (4 blocks)
; Spikey ball from pokie in CNZ ; ArtNem_81668:
even
ArtNem_CNZBonusSpike: BINCLUDE "art/nemesis/Spikey ball from CNZ slots.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (16 blocks)
; Moving cube from either CNZ or CPZ ; ArtNem_816C8:
even
ArtNem_BigMovingBlock: BINCLUDE "art/nemesis/Moving block from CNZ and CPZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (4 blocks)
; Elevator in CNZ ; ArtNem_817B4:
even
ArtNem_CNZElevator: BINCLUDE "art/nemesis/CNZ elevator.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (12 blocks)
; Bars from pokies in CNZ ; ArtNem_81826:
even
ArtNem_CNZCage: BINCLUDE "art/nemesis/CNZ slot machine bars.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (6 blocks)
; Hexagonal bumper in CNZ ; ArtNem_81894:
even
ArtNem_CNZHexBumper: BINCLUDE "art/nemesis/Hexagonal bumper from CNZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (24 blocks)
; Normal round bumper from CNZ ; ArtNem_8191E:
even
ArtNem_CNZRoundBumper: BINCLUDE "art/nemesis/Round bumper from CNZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (32 blocks)
; Diagonal spring from CNZ that you charge up ; ArtNem_81AB0:
even
ArtNem_CNZDiagPlunger: BINCLUDE "art/nemesis/Diagonal impulse spring from CNZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (18 blocks)
; Vertical red spring ; ArtNem_81C96:
even
ArtNem_CNZVertPlunger: BINCLUDE "art/nemesis/Vertical impulse spring.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (28 blocks)
; Weird blocks from CNZ that you hit 3 times to get rid of ; ArtNem_81DCC:
even
ArtNem_CNZMiniBumper: BINCLUDE "art/nemesis/Drop target from CNZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (52 blocks)
; Flippers from CNZ ; ArtNem_81EF2:
even
ArtNem_CNZFlipper: BINCLUDE "art/nemesis/Flippers.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (16 blocks)
; Large moving platform from CPZ ; ArtNem_82216:
even
ArtNem_CPZElevator: BINCLUDE "art/nemesis/Large moving platform from CNZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (24 blocks)
; Top of water in HPZ and CPZ ; ArtNem_82364:
even
ArtNem_WaterSurface: BINCLUDE "art/nemesis/Top of water in HPZ and CNZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (4 blocks)
; Booster things in CPZ ; ArtNem_824D4:
even
ArtNem_CPZBooster: BINCLUDE "art/nemesis/Speed booster from CPZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (4 blocks)
; CPZ droplet chain enemy ; ArtNem_8253C:
even
ArtNem_CPZDroplet: BINCLUDE "art/nemesis/CPZ worm enemy.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (33 blocks)
; CPZ metal things (girder, cylinders) ; ArtNem_825AE:
even
ArtNem_CPZMetalThings: BINCLUDE "art/nemesis/CPZ metal things.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (4 blocks)
; CPZ metal block ; ArtNem_827B8:
even
ArtNem_CPZMetalBlock: BINCLUDE "art/nemesis/CPZ large moving platform blocks.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (8 blocks)
; Yellow and black stripy tiles from DEZ ; ArtNem_827F8:
even
ArtNem_ConstructionStripes: BINCLUDE "art/nemesis/Stripy blocks from CPZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (48 blocks)
; Yellow flipping platforms and stuff CPZ ; ArtNem_82864:
even
ArtNem_CPZAnimatedBits: BINCLUDE "art/nemesis/Small yellow moving platform from CPZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (24 blocks)
; Moving block from CPZ ; ArtNem_82A46:
even
ArtNem_CPZStairBlock: BINCLUDE "art/nemesis/Moving block from CPZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (32 blocks)
; Spring that covers tube in CPZ ; ArtNem_82C06:
even
ArtNem_CPZTubeSpring: BINCLUDE "art/nemesis/CPZ spintube exit cover.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (16 blocks)
; Top of water in ARZ ; ArtNem_82E02:
even
ArtNem_WaterSurface2: BINCLUDE "art/nemesis/Top of water in ARZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (7 blocks)
; Leaves from ARZ ; ArtNem_82EE8:
even
ArtNem_Leaves: BINCLUDE "art/nemesis/Leaves in ARZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (17 blocks)
; Arrow shooter and arrow from ARZ ; ArtNem_82F74:
even
ArtNem_ArrowAndShooter: BINCLUDE "art/nemesis/Arrow shooter and arrow from ARZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (8 blocks)
; One way barrier from ARZ (unused?) ; ArtNem_830D2:
even
ArtNem_ARZBarrierThing: BINCLUDE "art/nemesis/One way barrier from ARZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (28 blocks)
; Buzz bomber ; ArtNem_8316A:
even
ArtNem_Buzzer: BINCLUDE "art/nemesis/Buzzer enemy.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (58 blocks)
; Octopus badnik from OOZ ; ArtNem_8336A:
even
ArtNem_Octus: BINCLUDE "art/nemesis/Octopus badnik from OOZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (56 blocks)
; Flying badnik from OOZ ; ArtNem_8368A:
even
ArtNem_Aquis: BINCLUDE "art/nemesis/Seahorse from OOZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (22 blocks)
; Fish badnik from EHZ ; ArtNem_839EA: ArtNem_Pirahna:
even
ArtNem_Masher: BINCLUDE "art/nemesis/EHZ Pirahna badnik.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (96 blocks)
; Robotnik's main ship ; ArtNem_83BF6:
even
ArtNem_Eggpod: BINCLUDE "art/nemesis/Eggpod.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (111 blocks)
; CPZ Boss ; ArtNem_84332:
even
ArtNem_CPZBoss: BINCLUDE "art/nemesis/CPZ boss.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (100 blocks)
; Large explosion ; ArtNem_84890:
even
ArtNem_FieryExplosion: BINCLUDE "art/nemesis/Large explosion.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (8 blocks)
; Horizontal jet ; ArtNem_84F18:
even
ArtNem_EggpodJets: BINCLUDE "art/nemesis/Horizontal jet.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (16 blocks)
; Smoke trail from CPZ and HTZ bosses ; ArtNem_84F96:
even
ArtNem_BossSmoke: BINCLUDE "art/nemesis/Smoke trail from CPZ and HTZ bosses.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (128 blocks)
; EHZ Boss ; ArtNem_8507C:
even
ArtNem_EHZBoss: BINCLUDE "art/nemesis/EHZ boss.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (20 blocks)
; Helicopter blades for EHZ boss ; ArtNem_85868:
even
ArtNem_EggChoppers: BINCLUDE "art/nemesis/Chopper blades for EHZ boss.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (107 blocks)
; HTZ boss ; ArtNem_8595C:
even
ArtNem_HTZBoss: BINCLUDE "art/nemesis/HTZ boss.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (166 blocks)
; ARZ boss ; ArtNem_86128:
even
ArtNem_ARZBoss: BINCLUDE "art/nemesis/ARZ boss.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (204 blocks)
; MCZ boss ; ArtNem_86B6E:
even
ArtNem_MCZBoss: BINCLUDE "art/nemesis/MCZ boss.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (133 blocks)
; CNZ boss ; ArtNem_87AAC:
even
ArtNem_CNZBoss: BINCLUDE "art/nemesis/CNZ boss.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (181 blocks)
; OOZ boss ; ArtNem_882D6:
even
ArtNem_OOZBoss: BINCLUDE "art/nemesis/OOZ boss.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (124 blocks)
; MTZ boss ; ArtNem_88DA6:
even
ArtNem_MTZBoss: BINCLUDE "art/nemesis/MTZ boss.bin"
;--------------------------------------------------------------------------------------
; Uncompressed art (8 blocks)
; Falling rocks and stalactites from MCZ ; ArtUnc_894E4:
even
ArtUnc_FallingRocks: BINCLUDE "art/uncompressed/Falling rocks and stalactites from MCZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (9 blocks)
; Blowfly from ARZ ; ArtNem_895E4:
even
ArtNem_Whisp: BINCLUDE "art/nemesis/Blowfly from ARZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (50 blocks)
; Grounder from ARZ ; ArtNem_8970E:
even
ArtNem_Grounder: BINCLUDE "art/nemesis/Grounder from ARZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (24 blocks)
; Fish from ARZ ; ArtNem_89B9A:
even
ArtNem_ChopChop: BINCLUDE "art/nemesis/Shark from ARZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (19 blocks)
; Lava snake from HTZ 89DEC: ArtNem_HtzRexxon:
even
ArtNem_Rexon: BINCLUDE "art/nemesis/Rexxon (lava snake) from HTZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (20 blocks)
; Enemy with spike cone on top from HTZ 89FAA: ArtNem_HtzDriller:
even
ArtNem_Spiker: BINCLUDE "art/nemesis/Driller badnik from HTZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (28 blocks)
; Bomber badnik from SCZ ; ArtNem_8A142:
even
ArtNem_Nebula: BINCLUDE "art/nemesis/Bomber badnik from SCZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (57 blocks)
; Turtle badnik from SCZ ; ArtNem_8A362:
even
ArtNem_Turtloid: BINCLUDE "art/nemesis/Turtle badnik from SCZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (38 blocks)
; Coconuts monkey badnik from EHZ
even
ArtNem_Coconuts: BINCLUDE "art/nemesis/Coconuts badnik from EHZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (10 blocks)
; Snake badnik from MCZ ; ArtNem_8AB36:
even
ArtNem_Crawlton: BINCLUDE "art/nemesis/Snake badnik from MCZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (20 blocks)
; Firefly from MCZ ; ArtNem_8AC5E:
even
ArtNem_Flasher: BINCLUDE "art/nemesis/Firefly from MCZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (32 blocks)
; Praying mantis badnik from MTZ 8AD80:
even
ArtNem_MtzMantis: BINCLUDE "art/nemesis/Praying mantis badnik from MTZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (36 blocks)
; Crab badnik from MCZ 8B058:
even
ArtNem_Crabmeat: BINCLUDE "art/nemesis/Crabmeat badnik from MCZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (15 blocks)
; Exploding star badnik from MTZ 8B300:
even
ArtNem_MtzSupernova: BINCLUDE "art/nemesis/Exploding star badnik from MTZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (32 blocks)
; Weird crawling badnik from CPZ ; ArtNem_8B430:
even
ArtNem_Spiny: BINCLUDE "art/nemesis/Weird crawling badnik from CPZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (45 blocks)
; Spider badnik from CPZ ArtNem_8B6B4:
even
ArtNem_Grabber: BINCLUDE "art/nemesis/Spider badnik from CPZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (26 blocks)
; Chicken badnik from WFZ 8B9DC:
even
ArtNem_WfzScratch: BINCLUDE "art/nemesis/Scratch from WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (25 blocks)
; Jet like badnik from SCZ 8BC16:
even
ArtNem_Balkrie: BINCLUDE "art/nemesis/Balkrie (jet badnik) from SCZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (217 blocks)
; Silver Sonic ; ArtNem_8BE12:
even
ArtNem_SilverSonic: BINCLUDE "art/nemesis/Silver Sonic.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (79 blocks)
; The Tornado 8CC44:
even
ArtNem_Tornado: BINCLUDE "art/nemesis/The Tornado.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (24 blocks)
; Wall turret from WFZ 8D1A0:
even
ArtNem_WfzWallTurret: BINCLUDE "art/nemesis/Wall turret from WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (20 blocks)
; Hook on chain in WFZ 8D388:
even
ArtNem_WfzHook: BINCLUDE "art/nemesis/Hook on chain from WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (54 blocks)
; Retracting platform from WFZ 8D540:
even
ArtNem_WfzGunPlatform: BINCLUDE "art/nemesis/Retracting platform from WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (16 blocks)
; Wheel for belt in WFZ 8D7D8:
even
ArtNem_WfzConveyorBeltWheel: BINCLUDE "art/nemesis/Wheel for belt in WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (12 blocks)
; Moving platform in WFZ 8D96E:
even
ArtNem_WfzFloatingPlatform: BINCLUDE "art/nemesis/Moving platform from WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (12 blocks)
; Giant unused vertical red laser in WFZ 8DA6E:
even
ArtNem_WfzVrtclLazer: BINCLUDE "art/nemesis/Unused vertical laser in WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (18 blocks)
; Clouds 8DAFC:
even
ArtNem_Clouds: BINCLUDE "art/nemesis/Clouds.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (10 blocks)
; Red horizontal laser in WFZ 8DC42:
even
ArtNem_WfzHrzntlLazer: BINCLUDE "art/nemesis/Red horizontal laser from WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (5 blocks)
; Catapult that shoots sonic across quickly in WFZ 8DCA2:
even
ArtNem_WfzLaunchCatapult: BINCLUDE "art/nemesis/Catapult that shoots Sonic to the side from WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (12 blocks)
; Rising platforms on belt from WFZ 8DD0C:
even
ArtNem_WfzBeltPlatform: BINCLUDE "art/nemesis/Platform on belt in WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (12 blocks)
; Unused badnik in WFZ 8DDF6:
even
ArtNem_WfzUnusedBadnik: BINCLUDE "art/nemesis/Unused badnik from WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (4 blocks)
; Vertical spinning blades from WFZ 8DEB8:
even
ArtNem_WfzVrtclPrpllr: BINCLUDE "art/nemesis/Vertical spinning blades in WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (29 blocks)
; Horizontal spinning blades from WFZ 8DEE8:
even
ArtNem_WfzHrzntlPrpllr: BINCLUDE "art/nemesis/Horizontal spinning blades in WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (12 blocks)
; Platforms that tilt in WFZ 8E010:
even
ArtNem_WfzTiltPlatforms: BINCLUDE "art/nemesis/Tilting plaforms in WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (8 blocks)
; Thrust from Robotnic's getaway ship in WFZ 8E0C4:
even
ArtNem_WfzThrust: BINCLUDE "art/nemesis/Thrust from Robotnik's getaway ship in WFZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (117 blocks)
; Laser boss from WFZ ; ArtNem_8E138:
even
ArtNem_WFZBoss: BINCLUDE "art/nemesis/WFZ boss.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (24 blocks)
; Robotnik's head ; ArtNem_8E886:
even
ArtNem_RobotnikUpper: BINCLUDE "art/nemesis/Robotnik's head.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (76 blocks)
; Robotnik ; ArtNem_8EA5A:
even
ArtNem_RobotnikRunning: BINCLUDE "art/nemesis/Robotnik.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (28 blocks)
; Robotnik's lower half ; ArtNem_8EE52:
even
ArtNem_RobotnikLower: BINCLUDE "art/nemesis/Robotnik's lover half.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (8 blocks)
; Window in back that Robotnic looks through in DEZ ; ArtNem_8EF96:
even
ArtNem_DEZWindow: BINCLUDE "art/nemesis/Window in back that Robotnik looks through in DEZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (327 blocks)
; Eggrobo ; ArtNem_8F024:
even
ArtNem_DEZBoss: BINCLUDE "art/nemesis/Eggrobo.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (42 blocks)
; Bouncer badnik from CNZ ; ArtNem_901A4:
even
ArtNem_Crawl: BINCLUDE "art/nemesis/Bouncer badnik from CNZ.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (26 blocks)
; Rocket thruster for Tornado ; ArtNem_90520:
even
ArtNem_TornadoThruster: BINCLUDE "art/nemesis/Rocket thruster for Tornado.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Frame 1 of end of game sequence ; MapEng_906E0:
MapEng_Ending1: BINCLUDE "mappings/misc/End of game sequence frame 1.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Frame 2 of end of game sequence ; MapEng_906F8:
MapEng_Ending2: BINCLUDE "mappings/misc/End of game sequence frame 2.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Frame 3 of end of game sequence ; MapEng_90722:
MapEng_Ending3: BINCLUDE "mappings/misc/End of game sequence frame 3.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Frame 4 of end of game sequence ; MapEng_9073C:
MapEng_Ending4: BINCLUDE "mappings/misc/End of game sequence frame 4.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Closeup of Tails flying plane in ending sequence ; MapEng_9076E:
MapEng_EndingTailsPlane: BINCLUDE "mappings/misc/Closeup of Tails flying plane in ending sequence.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Closeup of Sonic flying plane in ending sequence ; MapEng_907C0:
MapEng_EndingSonicPlane: BINCLUDE "mappings/misc/Closeup of Sonic flying plane in ending sequence.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Strange unused mappings (duplicate of MapEng_EndGameLogo)
; MapEng_9082A:
BINCLUDE "mappings/misc/Strange unused mappings 1 - 1.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Strange unused mappings (same as above)
; MapEng_90852:
BINCLUDE "mappings/misc/Strange unused mappings 1 - 2.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Strange unused mappings (same as above)
; MapEng_9087A:
BINCLUDE "mappings/misc/Strange unused mappings 1 - 3.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Strange unused mappings (same as above)
; MapEng_908A2:
BINCLUDE "mappings/misc/Strange unused mappings 1 - 4.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Strange unused mappings (same as above)
; MapEng_908CA:
BINCLUDE "mappings/misc/Strange unused mappings 1 - 5.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Strange unused mappings (same as above)
; MapEng_908F2:
BINCLUDE "mappings/misc/Strange unused mappings 1 - 6.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Strange unused mappings (same as above)
; MapEng_9091A:
BINCLUDE "mappings/misc/Strange unused mappings 1 - 7.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Strange unused mappings (same as above)
; MapEng_90942:
BINCLUDE "mappings/misc/Strange unused mappings 1 - 8.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed sprite mappings
; Strange unused mappings (same as above)
; MapEng_9096A:
BINCLUDE "mappings/misc/Strange unused mappings 2.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (363 blocks)
; Movie sequence at end of game ; ArtNem_90992:
even
ArtNem_EndingPics: BINCLUDE "art/nemesis/Movie sequence at end of game.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (127 blocks)
; Final image of Tornado with it and Sonic facing screen ; ArtNem_91F3C:
even
ArtNem_EndingFinalTornado: BINCLUDE "art/nemesis/Final image of Tornado with it and Sonic facing screen.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (109 blocks)
; Mini pictures of Tornado in final ending sequence ; ArtNem_927E0:
even
ArtNem_EndingMiniTornado: BINCLUDE "art/nemesis/Small pictures of Tornado in final ending sequence.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (135 blocks)
; Mini pictures of Sonic and final image of Sonic
even
ArtNem_EndingSonic: BINCLUDE "art/nemesis/Small pictures of Sonic and final image of Sonic.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (117 blocks)
; Mini pictures of Sonic and final image of Sonic in supersonic mode ; ArtNem_93848:
even
ArtNem_EndingSuperSonic: BINCLUDE "art/nemesis/Small pictures of Sonic and final image of Sonic in Super Sonic mode.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (181 blocks)
; Final image of Tails ; ArtNem_93F3C:
even
ArtNem_EndingTails: BINCLUDE "art/nemesis/Final image of Tails.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (72 blocks)
; Sonic the Hedgehog 2 image at end of credits ; ArtNem_94B28:
even
ArtNem_EndingTitle: BINCLUDE "art/nemesis/Sonic the Hedgehog 2 image at end of credits.bin"
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; LEVEL ART AND BLOCK MAPPINGS (16x16 and 128x128)
;
; #define BLOCK_TBL_LEN // table length unknown
; #define BIGBLOCK_TBL_LEN // table length unknown
; typedef uint16_t uword
;
; struct blockMapElement {
; uword unk : 5; // u
; uword patternIndex : 11; }; // i
; // uuuu uiii iiii iiii
;
; blockMapElement (*blockMapTable)[BLOCK_TBL_LEN][4] = 0xFFFF9000
;
; struct bigBlockMapElement {
; uword : 4
; uword blockMapIndex : 12; }; //I
; // 0000 IIII IIII IIII
;
; bigBlockMapElement (*bigBlockMapTable)[BIGBLOCK_TBL_LEN][64] = 0xFFFF0000
;
; /*
; This data determines how the level blocks will be constructed graphically. There are
; two kinds of block mappings: 16x16 and 128x128.
;
; 16x16 blocks are made up of four cells arranged in a square (thus, 16x16 pixels).
; Two bytes are used to define each cell, so the block is 8 bytes long. It can be
; represented by the bitmap blockMapElement, of which the members are:
;
; unk
; These bits have to do with pattern orientation. I do not know their exact
; meaning.
; patternIndex
; The pattern's address divided by $20. Otherwise said: an index into the
; pattern array.
;
; Each mapping can be expressed as an array of four blockMapElements, while the
; whole table is expressed as a two-dimensional array of blockMapElements (blockMapTable).
; The maps are read in left-to-right, top-to-bottom order.
;
; 128x128 maps are basically lists of indices into blockMapTable. The levels are built
; out of these "big blocks", rather than the "small" 16x16 blocks. bigBlockMapTable is,
; predictably, the table of big block mappings.
; Each big block is 8 16x16 blocks, or 16 cells, square. This produces a total of 16
; blocks or 64 cells.
; As noted earlier, each element of the table provides 'i' for blockMapTable[i][j].
; */
;----------------------------------------------------------------------------------
; EHZ 16x16 block mappings (Kosinski compression) ; was: (Kozinski compression)
BM16_EHZ: BINCLUDE "mappings/16x16/EHZ.bin"
;-----------------------------------------------------------------------------------
; EHZ/HTZ main level patterns (Kosinski compression)
; ArtKoz_95C24:
ArtKos_EHZ: BINCLUDE "art/kosinski/EHZ_HTZ.bin"
;-----------------------------------------------------------------------------------
; HTZ 16x16 block mappings (Kosinski compression)
BM16_HTZ: BINCLUDE "mappings/16x16/HTZ.bin"
;-----------------------------------------------------------------------------------
; HTZ pattern suppliment to EHZ level patterns (Kosinski compression)
; ArtKoz_98AB4:
ArtKos_HTZ: BINCLUDE "art/kosinski/HTZ_Supp.bin"
;-----------------------------------------------------------------------------------
; EHZ/HTZ 128x128 block mappings (Kosinski compression)
BM128_EHZ: BINCLUDE "mappings/128x128/EHZ_HTZ.bin"
;-----------------------------------------------------------------------------------
; MTZ 16x16 block mappings (Kosinski compression)
BM16_MTZ: BINCLUDE "mappings/16x16/MTZ.bin"
;-----------------------------------------------------------------------------------
; MTZ main level patterns (Kosinski compression)
; ArtKoz_9DB64:
ArtKos_MTZ: BINCLUDE "art/kosinski/MTZ.bin"
;-----------------------------------------------------------------------------------
; MTZ 128x128 block mappings (Kosinski compression)
BM128_MTZ: BINCLUDE "mappings/128x128/MTZ.bin"
;-----------------------------------------------------------------------------------
; HPZ 16x16 block mappings (Kosinski compression)
BM16_HPZ: ;BINCLUDE "mappings/16x16/HPZ.bin"
;-----------------------------------------------------------------------------------
; HPZ main level patterns (Kosinski compression)
ArtKos_HPZ: ;BINCLUDE "art/kosinski/HPZ.bin"
;-----------------------------------------------------------------------------------
; HPZ 128x128 block mappings (Kosinski compression)
BM128_HPZ: ;BINCLUDE "mappings/128x128/HPZ.bin"
;-----------------------------------------------------------------------------------
; OOZ 16x16 block mappings (Kosinski compression)
BM16_OOZ: BINCLUDE "mappings/16x16/OOZ.bin"
;-----------------------------------------------------------------------------------
; OOZ main level patterns (Kosinski compression)
; ArtKoz_A4204:
ArtKos_OOZ: BINCLUDE "art/kosinski/OOZ.bin"
;-----------------------------------------------------------------------------------
; OOZ 128x128 block mappings (Kosinski compression)
BM128_OOZ: BINCLUDE "mappings/128x128/OOZ.bin"
;-----------------------------------------------------------------------------------
; MCZ 16x16 block mappings (Kosinski compression)
BM16_MCZ: BINCLUDE "mappings/16x16/MCZ.bin"
;-----------------------------------------------------------------------------------
; MCZ main level patterns (Kosinski compression)
; ArtKoz_A9D74:
ArtKos_MCZ: BINCLUDE "art/kosinski/MCZ.bin"
;-----------------------------------------------------------------------------------
; MCZ 128x128 block mappings (Kosinski compression)
BM128_MCZ: BINCLUDE "mappings/128x128/MCZ.bin"
;-----------------------------------------------------------------------------------
; CNZ 16x16 block mappings (Kosinski compression)
BM16_CNZ: BINCLUDE "mappings/16x16/CNZ.bin"
;-----------------------------------------------------------------------------------
; CNZ main level patterns (Kosinski compression)
; ArtKoz_B0894:
ArtKos_CNZ: BINCLUDE "art/kosinski/CNZ.bin"
;-----------------------------------------------------------------------------------
; CNZ 128x128 block mappings (Kosinski compression)
BM128_CNZ: BINCLUDE "mappings/128x128/CNZ.bin"
;-----------------------------------------------------------------------------------
; CPZ/DEZ 16x16 block mappings (Kosinski compression)
BM16_CPZ: BINCLUDE "mappings/16x16/CPZ_DEZ.bin"
;-----------------------------------------------------------------------------------
; CPZ/DEZ main level patterns (Kosinski compression)
; ArtKoz_B6174:
ArtKos_CPZ: BINCLUDE "art/kosinski/CPZ_DEZ.bin"
;-----------------------------------------------------------------------------------
; CPZ/DEZ 128x128 block mappings (Kosinski compression)
BM128_CPZ: BINCLUDE "mappings/128x128/CPZ_DEZ.bin"
;-----------------------------------------------------------------------------------
; ARZ 16x16 block mappings (Kosinski compression)
BM16_ARZ: BINCLUDE "mappings/16x16/ARZ.bin"
;-----------------------------------------------------------------------------------
; ARZ main level patterns (Kosinski compression)
; ArtKoz_BCC24:
ArtKos_ARZ: BINCLUDE "art/kosinski/ARZ.bin"
;-----------------------------------------------------------------------------------
; ARZ 128x128 block mappings (Kosinski compression)
BM128_ARZ: BINCLUDE "mappings/128x128/ARZ.bin"
;-----------------------------------------------------------------------------------
; WFZ/SCZ 16x16 block mappings (Kosinski compression)
BM16_WFZ: BINCLUDE "mappings/16x16/WFZ_SCZ.bin"
;-----------------------------------------------------------------------------------
; WFZ/SCZ main level patterns (Kosinski compression)
; ArtKoz_C5004:
ArtKos_SCZ: BINCLUDE "art/kosinski/WFZ_SCZ.bin"
;-----------------------------------------------------------------------------------
; WFZ pattern suppliment to SCZ tiles (Kosinski compression)
; ArtKoz_C7EC4:
ArtKos_WFZ: BINCLUDE "art/kosinski/WFZ_Supp.bin"
;-----------------------------------------------------------------------------------
; WFZ/SCZ 128x128 block mappings (Kosinski compression)
BM128_WFZ: BINCLUDE "mappings/128x128/WFZ_SCZ.bin"
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;-----------------------------------------------------------------------------------
; Exit curve + slope up
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CA904:
MapSpec_Rise1: BINCLUDE "mappings/special stage/Slope up - Frame 1.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CADA8:
MapSpec_Rise2: BINCLUDE "mappings/special stage/Slope up - Frame 2.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CB376:
MapSpec_Rise3: BINCLUDE "mappings/special stage/Slope up - Frame 3.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CB92E:
MapSpec_Rise4: BINCLUDE "mappings/special stage/Slope up - Frame 4.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CBF92:
MapSpec_Rise5: BINCLUDE "mappings/special stage/Slope up - Frame 5.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CC5BE:
MapSpec_Rise6: BINCLUDE "mappings/special stage/Slope up - Frame 6.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CCC7A:
MapSpec_Rise7: BINCLUDE "mappings/special stage/Slope up - Frame 7.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CD282:
MapSpec_Rise8: BINCLUDE "mappings/special stage/Slope up - Frame 8.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CD7C0:
MapSpec_Rise9: BINCLUDE "mappings/special stage/Slope up - Frame 9.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CDD44:
MapSpec_Rise10: BINCLUDE "mappings/special stage/Slope up - Frame 10.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CE2BE:
MapSpec_Rise11: BINCLUDE "mappings/special stage/Slope up - Frame 11.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CE7DE:
MapSpec_Rise12: BINCLUDE "mappings/special stage/Slope up - Frame 12.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CEC52:
MapSpec_Rise13: BINCLUDE "mappings/special stage/Slope up - Frame 13.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CF0BC:
MapSpec_Rise14: BINCLUDE "mappings/special stage/Slope up - Frame 14.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CF580:
MapSpec_Rise15: BINCLUDE "mappings/special stage/Slope up - Frame 15.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CFA00:
MapSpec_Rise16: BINCLUDE "mappings/special stage/Slope up - Frame 16.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_CFE4A:
MapSpec_Rise17: BINCLUDE "mappings/special stage/Slope up - Frame 17.bin"
;-----------------------------------------------------------------------------------
; Straight path
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D028C:
MapSpec_Straight1: BINCLUDE "mappings/special stage/Straight path - Frame 1.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D090A:
MapSpec_Straight2: BINCLUDE "mappings/special stage/Straight path - Frame 2.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D0EA6:
MapSpec_Straight3: BINCLUDE "mappings/special stage/Straight path - Frame 3.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D1400:
MapSpec_Straight4: BINCLUDE "mappings/special stage/Straight path - Frame 4.bin"
;-----------------------------------------------------------------------------------
; Exit curve + slope down
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D19FC:
MapSpec_Drop1: BINCLUDE "mappings/special stage/Slope down - Frame 1.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D1EAC:
MapSpec_Drop2: BINCLUDE "mappings/special stage/Slope down - Frame 2.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D23AE:
MapSpec_Drop3: BINCLUDE "mappings/special stage/Slope down - Frame 3.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D27C6:
MapSpec_Drop4: BINCLUDE "mappings/special stage/Slope down - Frame 4.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D2C14:
MapSpec_Drop5: BINCLUDE "mappings/special stage/Slope down - Frame 5.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D3092:
MapSpec_Drop6: BINCLUDE "mappings/special stage/Slope down - Frame 6.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D3522:
MapSpec_Drop7: BINCLUDE "mappings/special stage/Slope down - Frame 7.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D39EC:
MapSpec_Drop8: BINCLUDE "mappings/special stage/Slope down - Frame 8.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D3F78:
MapSpec_Drop9: BINCLUDE "mappings/special stage/Slope down - Frame 9.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D4660:
MapSpec_Drop10: BINCLUDE "mappings/special stage/Slope down - Frame 10.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D4DA6:
MapSpec_Drop11: BINCLUDE "mappings/special stage/Slope down - Frame 11.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D53FC:
MapSpec_Drop12: BINCLUDE "mappings/special stage/Slope down - Frame 12.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D5958:
MapSpec_Drop13: BINCLUDE "mappings/special stage/Slope down - Frame 13.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D5F02:
MapSpec_Drop14: BINCLUDE "mappings/special stage/Slope down - Frame 14.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D6596:
MapSpec_Drop15: BINCLUDE "mappings/special stage/Slope down - Frame 15.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D6BAA:
MapSpec_Drop16: BINCLUDE "mappings/special stage/Slope down - Frame 16.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D702E:
MapSpec_Drop17: BINCLUDE "mappings/special stage/Slope down - Frame 17.bin"
;-----------------------------------------------------------------------------------
; Curved path
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D749C:
MapSpec_Turning1: BINCLUDE "mappings/special stage/Curve right - Frame 1.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D7912:
MapSpec_Turning2: BINCLUDE "mappings/special stage/Curve right - Frame 2.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D7DAA:
MapSpec_Turning3: BINCLUDE "mappings/special stage/Curve right - Frame 3.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D8250:
MapSpec_Turning4: BINCLUDE "mappings/special stage/Curve right - Frame 4.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D85F8:
MapSpec_Turning5: BINCLUDE "mappings/special stage/Curve right - Frame 5.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings ; MapSpec_D89EC:
MapSpec_Turning6: BINCLUDE "mappings/special stage/Curve right - Frame 6.bin"
;-----------------------------------------------------------------------------------
; Exit curve
;-----------------------------------------------------------------------------------
; Special stage tube mappings
; Exit curve ; MapSpec_D8E24:
MapSpec_Unturn1: BINCLUDE "mappings/special stage/Curve right - Frame 7.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings
; Exit curve ; MapSpec_D92B6:
MapSpec_Unturn2: BINCLUDE "mappings/special stage/Curve right - Frame 8.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings
; Exit curve ; MapSpec_D9778:
MapSpec_Unturn3: BINCLUDE "mappings/special stage/Curve right - Frame 9.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings
; Exit curve ; MapSpec_D9B80:
MapSpec_Unturn4: BINCLUDE "mappings/special stage/Curve right - Frame 10.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings
; Exit curve ; MapSpec_DA016:
MapSpec_Unturn5: BINCLUDE "mappings/special stage/Curve right - Frame 11.bin"
;-----------------------------------------------------------------------------------
; Enter curve
;-----------------------------------------------------------------------------------
; Special stage tube mappings
; Begin curve right ; MapSpec_DA4CE:
MapSpec_Turn1: BINCLUDE "mappings/special stage/Begin curve right - Frame 1.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings
; Begin curve right ; MapSpec_DAB20:
MapSpec_Turn2: BINCLUDE "mappings/special stage/Begin curve right - Frame 2.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings
; Begin curve right ; MapSpec_DB086:
MapSpec_Turn3: BINCLUDE "mappings/special stage/Begin curve right - Frame 3.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings
; Begin curve right ; MapSpec_DB5AE:
MapSpec_Turn4: BINCLUDE "mappings/special stage/Begin curve right - Frame 4.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings
; Begin curve right ; MapSpec_DBB62:
MapSpec_Turn5: BINCLUDE "mappings/special stage/Begin curve right - Frame 5.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings
; Begin curve right ; MapSpec_DC154:
MapSpec_Turn6: BINCLUDE "mappings/special stage/Begin curve right - Frame 6.bin"
;-----------------------------------------------------------------------------------
; Special stage tube mappings
; Begin curve right ; MapSpec_DC5E8:
MapSpec_Turn7: BINCLUDE "mappings/special stage/Begin curve right - Frame 7.bin"
;--------------------------------------------------------------------------------------
; Kosinski compressed art
; Special stage level patterns
; Note: Only one line of each tile is stored in this archive. The other 7 lines are
; the same as this one line, so to get the full tiles, each line needs to be
; duplicated 7 times over. ; ArtKoz_DCA38:
;--------------------------------------------------------------------------------------
ArtKos_Special: BINCLUDE "art/kosinski/SpecStag.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (127 blocks)
; Background patterns for special stage ; ArtNem_DCD68:
even
ArtNem_SpecialBack: BINCLUDE "art/nemesis/Background art for special stage.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed tile mappings
; Main background mappings for special stage ; MapEng_DD1DE:
MapEng_SpecialBack: BINCLUDE "mappings/misc/Main background mappings for special stage.bin"
;--------------------------------------------------------------------------------------
; Enigma compressed tile mappings
; Lower background mappings for special stage ; MapEng_DD30C:
MapEng_SpecialBackBottom: BINCLUDE "mappings/misc/Lower background mappings for special stage.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (62 blocks)
; Sonic/Miles and number text from special stage ; ArtNem_DD48A:
even
ArtNem_SpecialHUD: BINCLUDE "art/nemesis/Sonic and Miles number text from special stage.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (48 blocks)
; "Start" and checkered flag patterns in special stage ; ArtNem_DD790:
even
ArtNem_SpecialStart: BINCLUDE "art/nemesis/Start text from special stage.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (37 blocks)
; Stars in special stage ; ArtNem_DD8CE:
even
ArtNem_SpecialStars: BINCLUDE "art/nemesis/Stars in special stage.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (13 blocks)
; Text for most of the "Player VS Player" message in 2P special stage ; ArtNem_DD9C8:
even
ArtNem_SpecialPlayerVSPlayer: BINCLUDE "art/nemesis/Special stage Player VS Player text.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (104 blocks)
; Ring patterns in special stage ; ArtNem_DDA7E:
even
ArtNem_SpecialRings: BINCLUDE "art/nemesis/Special stage ring art.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (38 blocks)
; Horizontal shadow patterns in special stage ; ArtNem_DDFA4:
even
ArtNem_SpecialFlatShadow: BINCLUDE "art/nemesis/Horizontal shadow from special stage.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (58 blocks)
; Diagonal shadow patterns in special stage ; ArtNem_DE05A:
even
ArtNem_SpecialDiagShadow: BINCLUDE "art/nemesis/Diagonal shadow from special stage.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (25 blocks)
; Vertical shadow patterns in special stage ; ArtNem_DE120:
even
ArtNem_SpecialSideShadow: BINCLUDE "art/nemesis/Vertical shadow from special stage.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (48 blocks)
; Explosion patterns in special stage ; ArtNem_DE188:
even
ArtNem_SpecialExplosion: BINCLUDE "art/nemesis/Explosion from special stage.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (80 blocks)
; Bomb patterns in special stage ; ArtNem_DE4BC:
even
ArtNem_SpecialBomb: BINCLUDE "art/nemesis/Bomb from special stage.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (46 blocks)
; Emerald patterns in special stage ; ArtNem_DE8AC:
even
ArtNem_SpecialEmerald: BINCLUDE "art/nemesis/Emerald from special stage.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (99 blocks)
; Text for the messages and thumbs up/down icon in special stage ; ArtNem_DEAF4:
even
ArtNem_SpecialMessages: BINCLUDE "art/nemesis/Special stage messages and icons.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (851 blocks)
; Sonic and Tails animation frames from special stage
; Art for Obj09 and Obj10 and Obj88 ; ArtNem_DEEAE:
even
ArtNem_SpecialSonicAndTails: BINCLUDE "art/nemesis/Sonic and Tails animation frames in special stage.bin"
;--------------------------------------------------------------------------------------
; Nemesis compressed art (5 blocks)
; "Tails" patterns from special stage ; ArtNem_E247E:
even
ArtNem_SpecialTailsText: BINCLUDE "art/nemesis/Tails text patterns from special stage.bin"
;--------------------------------------------------------------------------------------
; Special stage object perspective data (Kosinski compression) ; MiscKoz_E24FE:
;--------------------------------------------------------------------------------------
MiscKoz_SpecialPerspective: BINCLUDE "misc/Special stage object perspective data (Kosinski compression).bin"
;--------------------------------------------------------------------------------------
; Special stage level layout (Nemesis compression) ; MiscNem_E34EE:
;--------------------------------------------------------------------------------------
MiscKoz_SpecialLevelLayout: BINCLUDE "misc/Special stage level layouts (Nemesis compression).bin"
;--------------------------------------------------------------------------------------
; Special stage object location list (Kosinski compression) ; MiscKoz_E35F2:
;--------------------------------------------------------------------------------------
MiscKoz_SpecialObjectLocations: BINCLUDE "misc/Special stage object location lists (Kosinski compression).bin"
;--------------------------------------------------------------------------------------
; Filler (free space) (unnecessary; could be replaced with "even")
;--------------------------------------------------------------------------------------
align $100
;--------------------------------------------------------------------------------------
; Offset index of ring locations
; The first commented number on each line is an array index; the second is the
; associated zone.
;--------------------------------------------------------------------------------------
Off_Rings: zoneOrderedOffsetTable 2,2
zoneOffsetTableEntry.w Rings_EHZ_1 ; 0 $00
zoneOffsetTableEntry.w Rings_EHZ_2 ; 1
zoneOffsetTableEntry.w Rings_Lev1_1 ; 2 $01
zoneOffsetTableEntry.w Rings_Lev1_2 ; 3
zoneOffsetTableEntry.w Rings_Lev2_1 ; 4 $02
zoneOffsetTableEntry.w Rings_Lev2_2 ; 5
zoneOffsetTableEntry.w Rings_Lev3_1 ; 6 $03
zoneOffsetTableEntry.w Rings_Lev3_2 ; 7
zoneOffsetTableEntry.w Rings_MTZ_1 ; 8 $04
zoneOffsetTableEntry.w Rings_MTZ_2 ; 9
zoneOffsetTableEntry.w Rings_MTZ_3 ; 10 $05
zoneOffsetTableEntry.w Rings_MTZ_4 ; 11
zoneOffsetTableEntry.w Rings_WFZ_1 ; 12 $06
zoneOffsetTableEntry.w Rings_WFZ_2 ; 13
zoneOffsetTableEntry.w Rings_HTZ_1 ; 14 $07
zoneOffsetTableEntry.w Rings_HTZ_2 ; 15
zoneOffsetTableEntry.w Rings_HPZ_1 ; 16 $08
zoneOffsetTableEntry.w Rings_HPZ_2 ; 17
zoneOffsetTableEntry.w Rings_Lev9_1 ; 18 $09
zoneOffsetTableEntry.w Rings_Lev9_2 ; 19
zoneOffsetTableEntry.w Rings_OOZ_1 ; 20 $0A
zoneOffsetTableEntry.w Rings_OOZ_2 ; 21
zoneOffsetTableEntry.w Rings_MCZ_1 ; 22 $0B
zoneOffsetTableEntry.w Rings_MCZ_2 ; 23
zoneOffsetTableEntry.w Rings_CNZ_1 ; 24 $0C
zoneOffsetTableEntry.w Rings_CNZ_2 ; 25
zoneOffsetTableEntry.w Rings_CPZ_1 ; 26 $0D
zoneOffsetTableEntry.w Rings_CPZ_2 ; 27
zoneOffsetTableEntry.w Rings_DEZ_1 ; 28 $0E
zoneOffsetTableEntry.w Rings_DEZ_2 ; 29
zoneOffsetTableEntry.w Rings_ARZ_1 ; 30 $0F
zoneOffsetTableEntry.w Rings_ARZ_2 ; 31
zoneOffsetTableEntry.w Rings_SCZ_1 ; 32 $10
zoneOffsetTableEntry.w Rings_SCZ_2 ; 33
zoneTableEnd
Rings_EHZ_1: BINCLUDE "level/rings/EHZ_1.bin"
Rings_EHZ_2: BINCLUDE "level/rings/EHZ_2.bin"
Rings_Lev1_1: BINCLUDE "level/rings/01_1.bin"
Rings_Lev1_2: BINCLUDE "level/rings/01_2.bin"
Rings_Lev2_1: BINCLUDE "level/rings/02_1.bin"
Rings_Lev2_2: BINCLUDE "level/rings/02_2.bin"
Rings_Lev3_1: BINCLUDE "level/rings/03_1.bin"
Rings_Lev3_2: BINCLUDE "level/rings/03_2.bin"
Rings_MTZ_1: BINCLUDE "level/rings/MTZ_1.bin"
Rings_MTZ_2: BINCLUDE "level/rings/MTZ_2.bin"
Rings_MTZ_3: BINCLUDE "level/rings/MTZ_3.bin"
Rings_MTZ_4: BINCLUDE "level/rings/MTZ_4.bin"
Rings_HTZ_1: BINCLUDE "level/rings/HTZ_1.bin"
Rings_HTZ_2: BINCLUDE "level/rings/HTZ_2.bin"
Rings_HPZ_1: BINCLUDE "level/rings/HPZ_1.bin"
Rings_HPZ_2: BINCLUDE "level/rings/HPZ_2.bin"
Rings_Lev9_1: BINCLUDE "level/rings/09_1.bin"
Rings_Lev9_2: BINCLUDE "level/rings/09_2.bin"
Rings_OOZ_1: BINCLUDE "level/rings/OOZ_1.bin"
Rings_OOZ_2: BINCLUDE "level/rings/OOZ_2.bin"
Rings_MCZ_1: BINCLUDE "level/rings/MCZ_1.bin"
Rings_MCZ_2: BINCLUDE "level/rings/MCZ_2.bin"
Rings_CNZ_1: BINCLUDE "level/rings/CNZ_1.bin"
Rings_CNZ_2: BINCLUDE "level/rings/CNZ_2.bin"
Rings_CPZ_1: BINCLUDE "level/rings/CPZ_1.bin"
Rings_CPZ_2: BINCLUDE "level/rings/CPZ_2.bin"
Rings_DEZ_1: BINCLUDE "level/rings/DEZ_1.bin"
Rings_DEZ_2: BINCLUDE "level/rings/DEZ_2.bin"
Rings_WFZ_1: BINCLUDE "level/rings/WFZ_1.bin"
Rings_WFZ_2: BINCLUDE "level/rings/WFZ_2.bin"
Rings_ARZ_1: BINCLUDE "level/rings/ARZ_1.bin"
Rings_ARZ_2: BINCLUDE "level/rings/ARZ_2.bin"
Rings_SCZ_1: BINCLUDE "level/rings/SCZ_1.bin"
Rings_SCZ_2: BINCLUDE "level/rings/SCZ_2.bin"
; --------------------------------------------------------------------------------------
; Filler (free space) (unnecessary; could be replaced with "even")
; --------------------------------------------------------------------------------------
align $200
; --------------------------------------------------------------------------------------
; Offset index of object locations
; --------------------------------------------------------------------------------------
Off_Objects: zoneOrderedOffsetTable 2,2
zoneOffsetTableEntry.w Objects_EHZ_1 ; 0 $00
zoneOffsetTableEntry.w Objects_EHZ_2 ; 1
zoneOffsetTableEntry.w Objects_Null3 ; 2 $01
zoneOffsetTableEntry.w Objects_Null3 ; 3
zoneOffsetTableEntry.w Objects_Null3 ; 4 $02
zoneOffsetTableEntry.w Objects_Null3 ; 5
zoneOffsetTableEntry.w Objects_Null3 ; 6 $03
zoneOffsetTableEntry.w Objects_Null3 ; 7
zoneOffsetTableEntry.w Objects_MTZ_1 ; 8 $04
zoneOffsetTableEntry.w Objects_MTZ_2 ; 9
zoneOffsetTableEntry.w Objects_MTZ_3 ; 10 $05
zoneOffsetTableEntry.w Objects_MTZ_3 ; 11
zoneOffsetTableEntry.w Objects_WFZ_1 ; 12 $06
zoneOffsetTableEntry.w Objects_WFZ_2 ; 13
zoneOffsetTableEntry.w Objects_HTZ_1 ; 14 $07
zoneOffsetTableEntry.w Objects_HTZ_2 ; 15
zoneOffsetTableEntry.w Objects_HPZ_1 ; 16 $08
zoneOffsetTableEntry.w Objects_HPZ_2 ; 17
zoneOffsetTableEntry.w Objects_Null3 ; 18 $09
zoneOffsetTableEntry.w Objects_Null3 ; 19
zoneOffsetTableEntry.w Objects_OOZ_1 ; 20 $0A
zoneOffsetTableEntry.w Objects_OOZ_2 ; 21
zoneOffsetTableEntry.w Objects_MCZ_1 ; 22 $0B
zoneOffsetTableEntry.w Objects_MCZ_2 ; 23
zoneOffsetTableEntry.w Objects_CNZ_1 ; 24 $0C
zoneOffsetTableEntry.w Objects_CNZ_2 ; 25
zoneOffsetTableEntry.w Objects_CPZ_1 ; 26 $0D
zoneOffsetTableEntry.w Objects_CPZ_2 ; 27
zoneOffsetTableEntry.w Objects_DEZ_1 ; 28 $0E
zoneOffsetTableEntry.w Objects_DEZ_2 ; 29
zoneOffsetTableEntry.w Objects_ARZ_1 ; 30 $0F
zoneOffsetTableEntry.w Objects_ARZ_2 ; 31
zoneOffsetTableEntry.w Objects_SCZ_1 ; 32 $10
zoneOffsetTableEntry.w Objects_SCZ_2 ; 33
zoneTableEnd
;Objects_Null1: ; looks unused, but it's really not. there must be a null entry first or you will get crashes. (try going left from second screen of EHZ1)
BINCLUDE "level/objects/Null_1.bin"
Objects_EHZ_1: BINCLUDE "level/objects/EHZ_1.bin"
if gameRevision=0
Objects_EHZ_2: BINCLUDE "level/objects/EHZ_2 (REV00).bin"
else
; a collision switcher was moved
Objects_EHZ_2: BINCLUDE "level/objects/EHZ_2.bin"
endif
Objects_MTZ_1: BINCLUDE "level/objects/MTZ_1.bin"
Objects_MTZ_2: BINCLUDE "level/objects/MTZ_2.bin"
Objects_MTZ_3: BINCLUDE "level/objects/MTZ_3.bin"
if gameRevision=0
Objects_WFZ_1: BINCLUDE "level/objects/WFZ_1 (REV00).bin"
else
; lampposts' 'remember state' flags were set
Objects_WFZ_1: BINCLUDE "level/objects/WFZ_1.bin"
endif
Objects_WFZ_2: BINCLUDE "level/objects/WFZ_2.bin"
Objects_HTZ_1: BINCLUDE "level/objects/HTZ_1.bin"
Objects_HTZ_2: BINCLUDE "level/objects/HTZ_2.bin"
Objects_HPZ_1: BINCLUDE "level/objects/HPZ_1.bin"
Objects_HPZ_2: BINCLUDE "level/objects/HPZ_2.bin"
;Objects_Null2: ; unused
BINCLUDE "level/objects/Null_2.bin"
Objects_OOZ_1: BINCLUDE "level/objects/OOZ_1.bin"
Objects_OOZ_2: BINCLUDE "level/objects/OOZ_2.bin"
Objects_MCZ_1: BINCLUDE "level/objects/MCZ_1.bin"
Objects_MCZ_2: BINCLUDE "level/objects/MCZ_2.bin"
if gameRevision=0
Objects_CNZ_1: BINCLUDE "level/objects/CNZ_1 (REV00).bin"
Objects_CNZ_2: BINCLUDE "level/objects/CNZ_2 (REV00).bin"
else
; the signposts were moved up slightly so they weren't poking out the bottom of the ground
Objects_CNZ_1: BINCLUDE "level/objects/CNZ_1.bin"
Objects_CNZ_2: BINCLUDE "level/objects/CNZ_2.bin"
endif
Objects_CPZ_1: BINCLUDE "level/objects/CPZ_1.bin"
Objects_CPZ_2: BINCLUDE "level/objects/CPZ_2.bin"
Objects_DEZ_1: BINCLUDE "level/objects/DEZ_1.bin"
Objects_DEZ_2: BINCLUDE "level/objects/DEZ_2.bin"
Objects_ARZ_1: BINCLUDE "level/objects/ARZ_1.bin"
Objects_ARZ_2: BINCLUDE "level/objects/ARZ_2.bin"
Objects_SCZ_1: BINCLUDE "level/objects/SCZ_1.bin"
Objects_SCZ_2: BINCLUDE "level/objects/SCZ_2.bin"
Objects_Null3: BINCLUDE "level/objects/Null_3.bin"
;Objects_Null4: ; unused
BINCLUDE "level/objects/Null_4.bin"
;Objects_Null5: ; unused
BINCLUDE "level/objects/Null_5.bin"
;Objects_Null6: ; unused
BINCLUDE "level/objects/Null_6.bin"
; --------------------------------------------------------------------------------------
; Filler (free space) (unnecessary; could be replaced with "even")
; --------------------------------------------------------------------------------------
align $1000
; ---------------------------------------------------------------------------
; Subroutine to load the sound driver
; ---------------------------------------------------------------------------
; sub_EC000:
SoundDriverLoad:
move sr,-(sp)
movem.l d0-a6,-(sp)
move #$2700,sr
lea (Z80_Bus_Request).l,a3
lea (Z80_Reset).l,a2
moveq #0,d2
move.w #$100,d1
move.w d1,(a3) ; get Z80 bus
move.w d1,(a2) ; release Z80 reset (was held high by console on startup)
- btst d2,(a3)
bne.s - ; wait until the 68000 has the bus
jsr DecompressSoundDriver(pc)
btst #0,(VDP_control_port+1).l ; check video mode
sne (Z80_RAM+zPalModeByte).l ; set if PAL
move.w d2,(a2) ; hold Z80 reset
move.w d2,(a3) ; release Z80 bus
moveq #$E6,d0
- dbf d0,- ; wait for 2,314 cycles
move.w d1,(a2) ; release Z80 reset
movem.l (sp)+,d0-a6
move (sp)+,sr
rts
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
; slightly modified Saxman decompression of the sound driver
; a4 == $A00000 (start of Z80 RAM)
; a5 == current position in Z80 RAM?
; a6 == current position in compressed sound driver?
; d0 == data to decompress? (byte)
; d4 == ???
; d5 == ???
; d6 == ???
; d7 == bytes left to decompress
; loc_EC04A:
DecompressSoundDriver:
lea Snd_Driver(pc),a6
; WARNING: the build script needs editing if you rename this label
movewZ80CompSize: move.w #Snd_Driver_End-Snd_Driver,d7 ; patched (by fixpointer.exe) after compression since the exact size can't be known beforehand
moveq #0,d6
lea (Z80_RAM).l,a5
moveq #0,d5
lea (Z80_RAM).l,a4
loc_EC062:
lsr.w #1,d6
btst #8,d6
bne.s +
jsr sub_EC0DE(pc)
move.b d0,d6
ori.w #$FF00,d6
+
btst #0,d6
beq.s loc_EC086
jsr sub_EC0DE(pc)
move.b d0,(a5)+
addq.w #1,d5
bra.w loc_EC062
; ---------------------------------------------------------------------------
loc_EC086:
jsr sub_EC0DE(pc)
moveq #0,d4
move.b d0,d4
jsr sub_EC0DE(pc)
move.b d0,d3
andi.w #$F,d3
addq.w #2,d3
andi.w #$F0,d0
lsl.w #4,d0
add.w d0,d4
addi.w #$12,d4
andi.w #$FFF,d4
move.w d5,d0
andi.w #$F000,d0
add.w d0,d4
cmp.w d4,d5
bhs.s loc_EC0CC
subi.w #$1000,d4
bcc.s loc_EC0CC
add.w d3,d5
addq.w #1,d5
- move.b #0,(a5)+
dbf d3,-
bra.w loc_EC062
; ---------------------------------------------------------------------------
loc_EC0CC:
add.w d3,d5
addq.w #1,d5
- move.b (a4,d4.w),(a5)+
addq.w #1,d4
dbf d3,-
bra.w loc_EC062
; End of function DecompressSoundDriver
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_EC0DE:
move.b (a6)+,d0
subq.w #1,d7
bne.s +
addq.w #4,sp
+
rts
; End of function sub_EC0DE
; ===========================================================================
; ---------------------------------------------------------------------------
; S2 sound driver (Sound driver compression (slightly modified Saxman))
; ---------------------------------------------------------------------------
; loc_EC0E8:
Snd_Driver:
save
include "s2.sounddriver.asm" ; CPU Z80
restore
padding off
!org (Snd_Driver+Size_of_Snd_driver_guess) ; don't worry; I know what I'm doing
; loc_ED04C:
Snd_Driver_End:
; ---------------------------------------------------------------------------
; Filler (free space)
; ---------------------------------------------------------------------------
; the DAC data has to line up with the end of the bank.
; actually it only has to fit within one bank, but we'll line it up to the end anyway
; because the padding gives the sound driver some room to grow
cnop -Size_of_DAC_samples, $8000
; ---------------------------------------------------------------------------
; DAC samples
; ---------------------------------------------------------------------------
; loc_ED100:
SndDAC_Start:
SndDAC_Sample1:
BINCLUDE "sound/DAC/Sample 1.bin"
SndDAC_Sample1_End
SndDAC_Sample2:
BINCLUDE "sound/DAC/Sample 2.bin"
SndDAC_Sample2_End
SndDAC_Sample5:
BINCLUDE "sound/DAC/Sample 5.bin"
SndDAC_Sample5_End
SndDAC_Sample6:
BINCLUDE "sound/DAC/Sample 6.bin"
SndDAC_Sample6_End
SndDAC_Sample3:
BINCLUDE "sound/DAC/Sample 3.bin"
SndDAC_Sample3_End
SndDAC_Sample4:
BINCLUDE "sound/DAC/Sample 4.bin"
SndDAC_Sample4_End
SndDAC_Sample7:
BINCLUDE "sound/DAC/Sample 7.bin"
SndDAC_Sample7_End
SndDAC_End
if SndDAC_End - SndDAC_Start > $8000
fatal "DAC samples must fit within $8000 bytes, but you have $\{SndDAC_End-SndDAC_Start } bytes of DAC samples."
endif
if SndDAC_End - SndDAC_Start > Size_of_DAC_samples
fatal "Size_of_DAC_samples = $\{Size_of_DAC_samples}, but you have $\{SndDAC_End-SndDAC_Start} bytes of DAC samples."
endif
; ---------------------------------------------------------------------------
; Music pointers
; ---------------------------------------------------------------------------
; loc_F0000:
MusicPoint1: startBank
MusPtr_Continue: rom_ptr_z80 Mus_Continue
Mus_Continue: BINCLUDE "sound/music/Continue.bin"
finishBank
; --------------------------------------------------------------------
; Nemesis compressed art (20 blocks)
; Buzzer's fireball
ArtNem_Buzzer_Fireball: BINCLUDE "art/nemesis/Fireball 1 (Buzzer).bin"
; --------------------------------------------------------------------
; Nemesis compressed art (24 blocks)
; Waterfall tiles
ArtNem_Waterfall: BINCLUDE "art/nemesis/Waterfall tiles.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (16 blocks)
; Another fireball
ArtNem_HtzFireball: BINCLUDE "art/nemesis/Fireball 2.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (8 blocks)
; Bridge in EHZ
ArtNem_EHZ_Bridge: BINCLUDE "art/nemesis/EHZ bridge.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (48 blocks)
; Diagonally moving lift in HTZ
ArtNem_HtzZipline: BINCLUDE "art/nemesis/HTZ zip-line platform.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (4 blocks)
; One way barrier from HTZ
ArtNem_HtzValveBarrier: BINCLUDE "art/nemesis/One way barrier from HTZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (24 blocks)
; See-saw in HTZ
ArtNem_HtzSeeSaw: BINCLUDE "art/nemesis/See-saw in HTZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (24 blocks)
; Unused Fireball
;ArtNem_F0B06:
BINCLUDE "art/nemesis/Fireball 3.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (20 blocks)
; Rock from HTZ
ArtNem_HtzRock: BINCLUDE "art/nemesis/Rock from HTZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (4 blocks)
; Orbit badnik from HTZ ; ArtNem_HtzSol:
ArtNem_Sol: BINCLUDE "art/nemesis/Sol badnik from HTZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (120 blocks)
; Large spinning wheel from MTZ
ArtNem_MtzWheel: BINCLUDE "art/nemesis/Large spinning wheel from MTZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (9 blocks)
; Indent in large spinning wheel from MTZ
ArtNem_MtzWheelIndent: BINCLUDE "art/nemesis/Large spinning wheel from MTZ - indent.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (8 blocks)
; Spike block from MTZ
ArtNem_MtzSpikeBlock: BINCLUDE "art/nemesis/MTZ spike block.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (15 blocks)
; Steam from MTZ
ArtNem_MtzSteam: BINCLUDE "art/nemesis/Steam from MTZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (8 blocks)
; Spike from MTZ
ArtNem_MtzSpike: BINCLUDE "art/nemesis/Spike from MTZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (54 blocks)
; Similarly shaded blocks from MTZ
ArtNem_MtzAsstBlocks: BINCLUDE "art/nemesis/Similarly shaded blocks from MTZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (9 blocks)
; Lava bubble from MTZ
ArtNem_MtzLavaBubble: BINCLUDE "art/nemesis/Lava bubble from MTZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (4 blocks)
; Lava cup
ArtNem_LavaCup: BINCLUDE "art/nemesis/Lava cup from MTZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (8 blocks)
; End of a bolt and rope from MTZ
ArtNem_BoltEnd_Rope: BINCLUDE "art/nemesis/Bolt end and rope from MTZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (12 blocks)
; Small cog from MTZ
ArtNem_MtzCog: BINCLUDE "art/nemesis/Small cog from MTZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (4 blocks)
; Flash inside spin tube from MTZ
ArtNem_MtzSpinTubeFlash: BINCLUDE "art/nemesis/Spin tube flash from MTZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (32 blocks)
; Large wooden box from MCZ ; ArtNem_F187C:
ArtNem_Crate: BINCLUDE "art/nemesis/Large wooden box from MCZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (26 blocks)
; Collapsing platform from MCZ ; ArtNem_F1ABA:
ArtNem_MCZCollapsePlat: BINCLUDE "art/nemesis/Collapsing platform from MCZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (16 blocks)
; Switch that you pull on from MCZ ; ArtNem_F1C64:
ArtNem_VineSwitch: BINCLUDE "art/nemesis/Pull switch from MCZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (10 blocks)
; Vine that lowers in MCZ ; ArtNem_F1D5C:
ArtNem_VinePulley: BINCLUDE "art/nemesis/Vine that lowers from MCZ.bin"
; --------------------------------------------------------------------
; Nemesis compressed art (20 blocks)
; Log viewed from the end for folding gates in MCZ (start of MCZ2) ; ArtNem_F1E06:
ArtNem_MCZGateLog: BINCLUDE "art/nemesis/Drawbridge logs from MCZ.bin"
; ----------------------------------------------------------------------------------
; Filler (free space)
; ----------------------------------------------------------------------------------
; the PCM data has to line up with the end of the bank.
cnop -Size_of_SEGA_sound, $8000
; -------------------------------------------------------------------------------
; Sega Intro Sound
; 8-bit unsigned raw audio at 16Khz
; -------------------------------------------------------------------------------
; loc_F1E8C:
Snd_Sega: BINCLUDE "sound/PCM/SEGA.bin"
Snd_Sega_End:
if Snd_Sega_End - Snd_Sega > $8000
fatal "Sega sound must fit within $8000 bytes, but you have a $\{Snd_Sega_End-Snd_Sega} byte Sega sound."
endif
if Snd_Sega_End - Snd_Sega > Size_of_SEGA_sound
fatal "Size_of_SEGA_sound = $\{Size_of_SEGA_sound}, but you have a $\{Snd_Sega_End-Snd_Sega} byte Sega sound."
endif
; ------------------------------------------------------------------------------
; Music pointers
; ------------------------------------------------------------------------------
; loc_F8000:
MusicPoint2: startBank
MusPtr_CNZ_2P: rom_ptr_z80 Mus_CNZ_2P
MusPtr_EHZ: rom_ptr_z80 Mus_EHZ
MusPtr_MTZ: rom_ptr_z80 Mus_MTZ
MusPtr_CNZ: rom_ptr_z80 Mus_CNZ
MusPtr_MCZ: rom_ptr_z80 Mus_MCZ
MusPtr_MCZ_2P: rom_ptr_z80 Mus_MCZ_2P
MusPtr_ARZ: rom_ptr_z80 Mus_ARZ
MusPtr_DEZ: rom_ptr_z80 Mus_DEZ
MusPtr_SpecStage: rom_ptr_z80 Mus_SpecStage
MusPtr_Options: rom_ptr_z80 Mus_Options
MusPtr_Ending: rom_ptr_z80 Mus_Ending
MusPtr_EndBoss: rom_ptr_z80 Mus_EndBoss
MusPtr_CPZ: rom_ptr_z80 Mus_CPZ
MusPtr_Boss: rom_ptr_z80 Mus_Boss
MusPtr_SCZ: rom_ptr_z80 Mus_SCZ
MusPtr_OOZ: rom_ptr_z80 Mus_OOZ
MusPtr_WFZ: rom_ptr_z80 Mus_WFZ
MusPtr_EHZ_2P: rom_ptr_z80 Mus_EHZ_2P
MusPtr_2PResult: rom_ptr_z80 Mus_2PResult
MusPtr_SuperSonic: rom_ptr_z80 Mus_SuperSonic
MusPtr_HTZ: rom_ptr_z80 Mus_HTZ
MusPtr_ExtraLife: rom_ptr_z80 Mus_ExtraLife
MusPtr_Title: rom_ptr_z80 Mus_Title
MusPtr_EndLevel: rom_ptr_z80 Mus_EndLevel
MusPtr_GameOver: rom_ptr_z80 Mus_GameOver
MusPtr_Invincible: rom_ptr_z80 Mus_Invincible
MusPtr_Emerald: rom_ptr_z80 Mus_Emerald
MusPtr_HPZ: rom_ptr_z80 Mus_HPZ
MusPtr_Drowning: rom_ptr_z80 Mus_Drowning
MusPtr_Credits: rom_ptr_z80 Mus_Credits
; loc_F803C:
Mus_HPZ: BINCLUDE "sound/music/HPZ.bin"
Mus_Drowning: BINCLUDE "sound/music/Drowning.bin"
Mus_Invincible: BINCLUDE "sound/music/Invincible.bin"
Mus_CNZ_2P: BINCLUDE "sound/music/CNZ_2p.bin"
Mus_EHZ: BINCLUDE "sound/music/EHZ.bin"
Mus_MTZ: BINCLUDE "sound/music/MTZ.bin"
Mus_CNZ: BINCLUDE "sound/music/CNZ.bin"
Mus_MCZ: BINCLUDE "sound/music/MCZ.bin"
Mus_MCZ_2P: BINCLUDE "sound/music/MCZ_2p.bin"
Mus_ARZ: BINCLUDE "sound/music/ARZ.bin"
Mus_DEZ: BINCLUDE "sound/music/DEZ.bin"
Mus_SpecStage: BINCLUDE "sound/music/SpecStg.bin"
Mus_Options: BINCLUDE "sound/music/Options.bin"
Mus_Ending: BINCLUDE "sound/music/Ending.bin"
Mus_EndBoss: BINCLUDE "sound/music/End_Boss.bin"
Mus_CPZ: BINCLUDE "sound/music/CPZ.bin"
Mus_Boss: BINCLUDE "sound/music/Boss.bin"
Mus_SCZ: BINCLUDE "sound/music/SCZ.bin"
Mus_OOZ: BINCLUDE "sound/music/OOZ.bin"
Mus_WFZ: BINCLUDE "sound/music/WFZ.bin"
Mus_EHZ_2P: BINCLUDE "sound/music/EHZ_2p.bin"
Mus_2PResult: BINCLUDE "sound/music/2player results screen.bin"
Mus_SuperSonic: BINCLUDE "sound/music/Supersonic.bin"
Mus_HTZ: BINCLUDE "sound/music/HTZ.bin"
Mus_Title: BINCLUDE "sound/music/Title screen.bin"
Mus_EndLevel: BINCLUDE "sound/music/End of level.bin"
; The following act mostly like sound effects
; despite being listed with the music.
; This means they're uncompressed format with absolute pointers
; instead of compressed with relative pointers.
; Because they have absolute pointers,
; they have to be assembled rather than BINCLUDE'd.
; See below (right before Sound20) for other notes
; about the sound format that apply to these too.
;Mus_ExtraLife: BINCLUDE "sound/music/Extra life.bin"
Mus_ExtraLife: dc.w z80_ptr(Mus_EL_Voices),$0603,$02CD
dc.w z80_ptr(Mus_EL_DAC),$0000
dc.w z80_ptr(Mus_EL_FM1),$E810
dc.w z80_ptr(Mus_EL_FM2),$E810
dc.w z80_ptr(Mus_EL_FM3),$E810
dc.w z80_ptr(Mus_EL_FM4),$E810
dc.w z80_ptr(Mus_EL_FM5),$E810
dc.w z80_ptr(Mus_EL_PSG1),$D008,$0005
dc.w z80_ptr(Mus_EL_PSG2),$DC08,$0005
dc.w z80_ptr(Mus_EL_PSG3),$DC00,$0004
Mus_EL_FM4: dc.b $E1,$03,$E0,$40,$F6
dc.w z80_ptr(+)
Mus_EL_FM1: dc.b $E0,$80
+ dc.b $EF,$00,$E8,$06,$D9,$06,$03,$03,$06,$06
dc.b $E8,$00,$DB,$09,$D7,$D6,$06,$D9,$18,$F2
Mus_EL_FM2: dc.b $EF,$01,$E8,$06,$E2,$01,$D6,$06,$03,$03,$06,$06
dc.b $E8,$00,$D7,$09,$D4,$D2,$06,$D6,$18,$E2,$01,$F2
Mus_EL_FM5: dc.b $E1,$03,$E0,$40,$F6
dc.w z80_ptr(+)
Mus_EL_FM3: dc.b $E0,$80
+ dc.b $EF,$02,$BA,$0C,$80,$06,$BA,$B8,$80,$03
dc.b $B8,$06,$80,$03,$B8,$06,$BA,$18,$F2
Mus_EL_PSG1: dc.b $E8,$06,$D6,$06,$03,$03,$06,$06,$E8,$00,$D7,$09
dc.b $D4,$D2,$06,$D6,$18
Mus_EL_PSG2:
Mus_EL_PSG3: dc.b $F2
Mus_EL_DAC: dc.b $88,$12,$06,$8B,$09,$09,$06,$88,$06,$8A,$88,$8A
dc.b $88,$0C,$E4
Mus_EL_Voices: dc.b $3A,$01,$01,$07,$01,$8E,$8D,$8E,$53,$0E,$0E,$0E
dc.b $03,$00,$00,$00,$00,$1F,$1F,$FF,$0F,$18,$16,$4E,$80
dc.b $3A,$01,$01,$07,$01,$8E,$8D,$8E,$53,$0E,$0E,$0E
dc.b $03,$00,$00,$00,$00,$1F,$1F,$FF,$0F,$18,$27,$28,$80
dc.b $3A,$01,$01,$07,$01,$8E,$8D,$8E,$53,$0E,$0E,$0E
dc.b $03,$00,$00,$00,$07,$1F,$1F,$FF,$0F,$18,$27,$28,$80
;Mus_GameOver: BINCLUDE "sound/music/Game over.bin"
Mus_GameOver: dc.w z80_ptr(MusGO_Voices),$0603,$02F2
dc.w z80_ptr(MusGOver_DAC),$0000
dc.w z80_ptr(MusGOver_FM1),$E80A
dc.w z80_ptr(MusGOver_FM2),$F40F
dc.w z80_ptr(MusGOver_FM3),$F40F
dc.w z80_ptr(MusGOver_FM4),$F40D
dc.w z80_ptr(MusGOver_FM5),$DC16
dc.w z80_ptr(MusGOver_PSG),$D003,$0005
dc.w z80_ptr(MusGOver_PSG),$DC06,$0005
dc.w z80_ptr(MusGOver_PSG),$DC00,$0004
MusGOver_FM1: dc.b $EF,$00
dc.b $F0,$20,$01,$04,$05
dc.b $80,$0C,$CA,$12,$80,$06,$CA,$80,$CB,$12,$C8,$1E
dc.b $CA,$06,$80,$CA,$80,$CA,$80,$C6,$80,$C4,$12,$C8
dc.b $0C,$80,$12,$C9,$04,$80,$C9,$C8,$06,$80,$C7,$80
dc.b $C6,$80
dc.b $F0,$28,$01,$18,$05
dc.b $C5,$60,$F2
MusGOver_FM2: dc.b $EF,$01,$80,$01,$D9,$06,$80,$D9,$80,$D6,$80,$D6
dc.b $80,$D7,$15,$D7,$1B,$D9,$06,$80,$D9,$80,$D6,$80
dc.b $D6,$80,$DC,$15,$DC,$1B,$F2
MusGOver_FM3: dc.b $EF,$01,$D6,$0C,$D6,$D2,$D2,$D4,$15,$D4,$1B,$D6
dc.b $0C,$D6,$D2,$D2,$D7,$15,$D7,$1B,$F2
MusGOver_FM4: dc.b $EF,$02,$E2,$01,$AE,$06,$80,$AE,$80,$A9,$80,$A9
dc.b $80,$AC,$15,$AB,$0C,$AC,$03,$AB,$0C,$AE,$06,$80
dc.b $AE,$80,$A9,$80,$A9,$80,$B3,$15,$B2,$0C,$B3,$03
dc.b $B2,$0C,$AE,$04,$80,$AE,$AD,$06,$80,$AC,$80,$AB
dc.b $80,$AB,$60,$E2,$01,$F2
MusGOver_FM5: dc.b $EF,$03,$80,$30,$D7,$12,$80,$03,$D7,$1B,$80,$30
dc.b $DC,$12,$80,$03,$DC,$1B
MusGOver_PSG: dc.b $F2
MusGOver_DAC: dc.b $80,$18,$81
dc.b $F7,$00,$04
dc.w z80_ptr(MusGOver_DAC)
dc.b $F2
MusGO_Voices: dc.b $3A,$51,$51,$08,$02,$1E,$1E,$1E,$10,$1F,$1F,$1F
dc.b $0F,$00,$00,$00,$02,$0F,$0F,$0F,$1F,$18,$22,$24,$81
dc.b $3C,$33,$73,$30,$70,$94,$96,$9F,$9F,$12,$14,$00
dc.b $0F,$04,$04,$0A,$0D,$2F,$4F,$0F,$2F,$33,$1A,$80,$80
dc.b $3A,$01,$01,$07,$01,$8E,$8D,$8E,$53,$0E,$0E,$0E
dc.b $03,$00,$00,$00,$07,$1F,$1F,$FF,$0F,$1C,$27,$28,$80
dc.b $1F,$66,$53,$31,$22,$1C,$1F,$98,$1F,$12,$0F,$0F
dc.b $0F,$00,$00,$00,$00,$FF,$0F,$0F,$0F,$8C,$8A,$8D,$8B
;Mus_Emerald: BINCLUDE "sound/music/Got an emerald.bin"
Mus_Emerald: dc.w z80_ptr(MusEmrldVoices),$0703,$01D5
dc.w z80_ptr(MusEmeraldDAC),$0000
dc.w z80_ptr(MusEmeraldFM1),$F408
dc.w z80_ptr(MusEmeraldFM2),$F408
dc.w z80_ptr(MusEmeraldFM3),$F407
dc.w z80_ptr(MusEmeraldFM4),$F416
dc.w z80_ptr(MusEmeraldFM5),$F416
dc.w z80_ptr(MusEmeraldFM6),$F416
dc.w z80_ptr(MusEmeraldPSG1),$F402,$0004
dc.w z80_ptr(MusEmeraldPSG2),$F402,$0005
dc.w z80_ptr(MusEmeraldPSG3),$F400,$0004
MusEmeraldFM3: dc.b $E1,$02
MusEmeraldFM1: dc.b $EF,$00,$C1,$06,$C4,$C9,$CD,$0C,$C9,$D0,$2A,$F2
MusEmeraldFM2: dc.b $EF,$00,$BD,$06,$C1,$C4,$C9,$0C,$C6,$CB,$2A,$F2
MusEmeraldFM4: dc.b $EF,$01,$C1,$0C,$C1,$06,$C4,$06,$80,$C4,$80,$C9
dc.b $2A,$F2
MusEmeraldFM5: dc.b $EF,$01,$C9,$0C,$C9,$06,$CD,$06,$80,$CD,$80,$D0
dc.b $2A,$F2
MusEmeraldFM6: dc.b $EF,$01,$C4,$0C,$C4,$06,$C9,$06,$80,$C9,$80,$CD
dc.b $2A,$F2
MusEmeraldPSG2: dc.b $80,$2D
- dc.b $C4,$06,$C2,$C1,$BF,$EC,$03
dc.b $F7,$00,$04
dc.w z80_ptr(-)
dc.b $F2
MusEmeraldPSG1: dc.b $E2,$01,$80,$02,$80,$2D
- dc.b $C4,$06,$C2,$C1,$BF,$EC,$03
dc.b $F7,$00,$04
dc.w z80_ptr(-)
MusEmeraldPSG3:
MusEmeraldDAC: dc.b $E2,$01,$F2
MusEmrldVoices: dc.b $04,$35,$54,$72,$46,$1F,$1F,$1F,$1F,$07,$07,$0A
dc.b $0D,$00,$00,$0B,$0B,$1F,$1F,$0F,$0F,$23,$1D,$14,$80
dc.b $3C,$31,$50,$52,$30,$52,$52,$53,$53,$08,$08,$00
dc.b $00,$04,$04,$00,$00,$10,$10,$07,$07,$1A,$16,$80,$80
;Mus_Credits: BINCLUDE "sound/music/Credits.bin"
Mus_Credits: dc.w z80_ptr(MusCred_Voices),$0603,$01F0
dc.w z80_ptr(MusCred_DAC),$0000
dc.w z80_ptr(MusCred_FM1),$000E
dc.w z80_ptr(MusCred_FM2),$180A
dc.w z80_ptr(MusCred_FM3),$0014
dc.w z80_ptr(MusCred_FM4),$0016
dc.w z80_ptr(MusCred_FM5),$0C16
dc.w z80_ptr(MusCred_PSG1),$E806,$000B
dc.w z80_ptr(MusCred_PSG2),$DC07,$000B
dc.w z80_ptr(MusCred_PSG3),$0002,$0003
MusCred_FM1: dc.b $E9,$F4,$E6,$FE,$F8
dc.w z80_ptr(MusCreditsDB06)
dc.b $E9,$0C,$E6,$02
- dc.b $80,$30
dc.b $F7,$00,$08
dc.w z80_ptr(-)
dc.b $EF,$03,$F8
dc.w z80_ptr(MusCreditsD9D1)
dc.b $AE,$06,$A2,$F8
dc.w z80_ptr(MusCreditsD9D1)
dc.b $E6,$FD
- dc.b $EF,$00,$B7,$06,$BA,$F8
dc.w z80_ptr(MusCreditsDA13)
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $80,$06,$80,$80,$30,$80,$EF,$0B,$E9,$18,$E6,$02
- dc.b $94,$0C,$8F,$92,$8F,$06,$94,$05,$94,$07,$06,$8F
dc.b $0C,$92,$8F
dc.b $F7,$00,$05
dc.w z80_ptr(-)
dc.b $80,$30,$80,$EF,$0E,$E6,$FF,$E9,$E8,$F8
dc.w z80_ptr(MusCreditsDAE5)
dc.b $80,$12,$91,$94,$06,$80,$18,$96,$12,$9A,$06,$80
dc.b $80,$12,$8F,$93,$08,$80,$16,$96,$06,$91,$92,$94
dc.b $96,$F8
dc.w z80_ptr(MusCreditsDAE5)
dc.b $80,$12,$9D,$9A,$08,$80,$16,$96,$12,$9D,$08,$80
dc.b $04,$EF,$12
dc.b $F0,$18,$01,$0A,$04
dc.b $80,$30,$80,$F8
dc.w z80_ptr(MusCreditsDA5F)
dc.b $E7,$24,$E7,$C5,$01,$E7,$C4,$E7,$C3,$E7,$C2,$E7
dc.b $C1,$E7,$C0,$E7,$BF,$E7,$BE,$E7,$BD,$E7,$BC,$E7
dc.b $BB,$E7,$BA,$80,$60,$EF,$01,$E9,$F4,$E6,$FA,$F4
dc.b $F8
dc.w z80_ptr(MusCreditsDA99)
dc.b $B1,$03,$F8
dc.w z80_ptr(MusCreditsDA99)
dc.b $80,$03,$80,$60,$E6,$04,$E1,$01,$EF,$1B,$E6,$06
dc.b $C1,$0C,$E8,$06,$BD,$06,$BA,$BD,$0C,$80,$80,$EF
dc.b $1C,$E6,$FA,$E8,$00,$BC,$0C,$12,$06,$EF,$1B,$E6
dc.b $06,$E8,$06,$C2,$06,$C2,$80,$C2,$80,$C2,$E8,$00
dc.b $C3,$0C,$C4,$80,$E8,$06,$C4,$06,$06,$C6,$C4,$E8
dc.b $00,$C1,$0C,$E8,$06,$BD,$06,$BA,$BD,$0C,$80,$80
dc.b $E8,$00,$EF,$1C,$E6,$FA,$C1,$C4,$C1,$EF,$1A,$E6
dc.b $06,$E8,$06,$C2,$06,$C2,$80,$C2,$80,$C2,$E8,$00
dc.b $C3,$0C,$C4,$06,$80,$80,$24,$80,$30,$80,$EF,$1F
dc.b $E9,$18,$E6,$F7,$E1,$00,$80,$06,$AC,$AE,$80,$B1
dc.b $80,$B3,$80,$B4,$80,$B3,$80,$B1,$B3,$80,$B1,$E9
dc.b $F4,$EF,$00,$80,$0C,$AC,$06,$AE,$B1,$80,$12,$AC
dc.b $06,$AE,$B1,$80,$B4,$B1,$80,$B1,$E9,$0C,$EF,$1F
dc.b $80,$06,$B8,$12,$B4,$06,$80,$B3,$80,$B4,$80,$B3
dc.b $80,$B1,$AE,$80,$B1,$E9,$F4,$EF,$00,$80,$06,$AF
dc.b $12,$AE,$06,$80,$12,$AF,$06,$80,$AE,$80,$AF,$B1
dc.b $80,$B1,$80,$30,$80,$EF,$21,$E9,$0C,$80,$30,$80
dc.b $08,$A0,$04,$9E,$0C,$9D,$9B,$99,$08,$04,$91,$0C
dc.b $92,$93,$94,$98,$99,$9B,$9D,$98,$95,$93,$91,$98
dc.b $9D,$91,$96,$98,$99,$98,$96,$99,$9D,$96,$95,$97
dc.b $99,$97,$95,$96,$97,$98,$99,$98,$99,$9B,$9D,$08
dc.b $04,$98,$0C,$91,$95,$96,$98,$99,$9D,$9E,$08,$96
dc.b $10,$97,$0C,$98,$F8
dc.w z80_ptr(MusCreditsDAFE)
dc.b $9E,$E6,$04,$F8
dc.w z80_ptr(MusCreditsDAFE)
dc.b $9E,$E6,$FC,$F8
dc.w z80_ptr(MusCreditsDAFE)
dc.b $9E,$08,$99,$04,$EF,$23,$E9,$E8,$E6,$07,$80,$60
dc.b $F8
dc.w z80_ptr(MusCreditsDABE)
dc.b $80,$60,$E6,$FB,$80,$0C,$CD,$06,$80,$D4,$CD,$06
dc.b $80,$0C,$CD,$06,$80,$D4,$CD,$06,$80,$18,$E6,$05
dc.b $80,$0C,$AE,$80,$AE,$80,$24,$E1,$02,$E6,$08,$A2
dc.b $6C,$F2
MusCreditsD9D1: dc.b $A5,$0C,$B1,$06,$80,$B1,$0C,$AC,$B3,$12,$B1,$0C
dc.b $AC,$06,$AE,$B1,$A7,$0C,$B3,$06,$80,$B3,$0C,$AE
dc.b $B5,$12,$B3,$06,$80,$AE,$B0,$B3,$A3,$0C,$AF,$06
dc.b $80,$AF,$0C,$AA,$B1,$12,$AF,$0C,$AA,$06,$AC,$AF
dc.b $A2,$0C,$AE,$06,$A2,$A4,$0C,$B0,$06,$A4,$A5,$0C
dc.b $B1,$06,$A5,$A2,$0C,$E3
MusCreditsDA13: dc.b $BE,$0C,$BC,$06,$BA,$BC,$BA,$04,$E7,$08,$BA,$04
dc.b $80,$0E,$EF,$07,$B7,$06,$B2,$B5,$B7,$EF,$00,$B7
dc.b $BA,$BE,$0C,$BC,$06,$BA,$BC,$BA,$0C,$BC,$04,$80
dc.b $08,$BA,$04,$80,$08,$BC,$04,$80,$08,$BE,$12,$BA
dc.b $06,$B7,$80,$B7,$80,$24,$EF,$07,$B7,$06,$B2,$B5
dc.b $B7,$80,$0C,$80,$30,$BE,$06,$BE,$BA,$04,$80,$08
dc.b $BC,$06,$BE,$E3
MusCreditsDA5F: dc.b $C3,$01,$E7,$C4,$E7,$C5,$E7,$C6,$2D,$E9,$02,$C3
dc.b $01,$E7,$C4,$E7,$C5,$E7,$C6,$2D,$E9,$01,$C3,$01
dc.b $E7,$C4,$E7,$C5,$E7,$C6,$2D,$E9,$FC,$C3,$01,$E7
dc.b $C4,$E7,$C5,$E7,$C6,$2D,$E9,$01,$C3,$01,$E7,$C4
dc.b $E7,$C5,$E7,$C6,$2D,$E7,$30,$E7,$30,$E3
MusCreditsDA99: dc.b $A7,$0C,$B3,$06,$80,$B1,$80,$B3,$0C,$A7,$03,$80
dc.b $06,$A7,$03,$B3,$0C,$B1,$B3,$09,$AE,$03,$AC,$06
dc.b $80,$AC,$0C,$AE,$06,$80,$AE,$0C,$AF,$06,$80,$27
dc.b $E3
MusCreditsDABE: dc.b $80,$0C,$CA,$15,$80,$03,$CA,$06,$80,$CB,$0F,$80
dc.b $03,$C8,$18,$80,$06,$CA,$80,$CA,$80,$CA,$80,$C6
dc.b $80,$C4,$0F,$80,$03,$C8,$18,$80,$06
dc.b $F7,$00,$02
dc.w z80_ptr(MusCreditsDABE)
dc.b $E3
MusCreditsDAE5: dc.b $80,$12,$94,$97,$06,$80,$18,$99,$12,$94,$06,$80
dc.b $80,$12,$92,$96,$06,$80,$18,$97,$12,$92,$06,$80
dc.b $E3
MusCreditsDAFE: dc.b $80,$99,$80,$99,$80,$9E,$80,$E3
MusCreditsDB06: dc.b $EF,$07,$80,$54,$C7,$04,$C8,$C9,$CA,$24,$CD,$D2
dc.b $18,$D0,$24,$CF,$CB,$18,$CB,$0C,$CA,$80,$CD,$60
dc.b $E7,$3C,$CA,$24,$CD,$D2,$18,$D4,$24,$D0,$D4,$18
dc.b $D4,$24,$D6,$60,$E7,$3C,$E3
MusCred_FM2: dc.b $80,$60,$EF,$01,$E8,$06,$F8
dc.w z80_ptr(MusCreditsDE2A)
dc.b $F8
dc.w z80_ptr(MusCreditsDE2A)
- dc.b $85,$0C
dc.b $F7,$00,$0C
dc.w z80_ptr(-)
dc.b $8A,$87,$88,$89,$F8
dc.w z80_ptr(MusCreditsDE2A)
- dc.b $88
dc.b $F7,$00,$0B
dc.w z80_ptr(-)
- dc.b $8A
dc.b $F7,$00,$0A
dc.w z80_ptr(-)
dc.b $E8,$00,$E6,$FC,$8A,$8B,$8C,$E6,$04,$E8,$09
- dc.b $8D,$0C
dc.b $F7,$00,$0C
dc.w z80_ptr(-)
dc.b $E8,$00,$8D,$8A,$8B,$8C,$E8,$09
- dc.b $8D,$0C
dc.b $F7,$00,$0C
dc.w z80_ptr(-)
dc.b $8D,$06,$99,$E8,$00,$8A,$0C,$8B,$8C,$E9,$E8,$E6
dc.b $0C,$EF,$04
- dc.b $F8
dc.w z80_ptr(MusCreditsDD59)
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $E6,$F9,$EF,$08
MusCreditsDB93: dc.b $F8
dc.w z80_ptr(MusCreditsDD8D)
- dc.b $9F,$04,$80,$08,$9F,$0C
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $06,$9C,$12,$9D,$0C,$9E,$F8
dc.w z80_ptr(MusCreditsDD8D)
- dc.b $9D,$04,$80,$08,$9D,$0C
dc.b $F7,$00,$02
dc.w z80_ptr(-)
- dc.b $9C,$04,$80,$08,$9C,$0C
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $F7,$01,$02
dc.w z80_ptr(MusCreditsDB93)
dc.b $80,$60,$80,$48,$EF,$0C,$E6,$13,$F8
dc.w z80_ptr(MusCreditsDD9D)
dc.b $24,$80,$60,$EF,$0F,$E6,$F3
dc.b $F0,$04,$02,$03,$02
dc.b $F8
dc.w z80_ptr(MusCreditsDDB5)
dc.b $C4,$18,$C3,$30,$E7,$18,$80,$0C,$F8
dc.w z80_ptr(MusCreditsDDB5)
dc.b $BE,$EF,$13,$E6,$F5,$F4,$80,$60
- dc.b $F8
dc.w z80_ptr(MusCreditsDDEA)
dc.b $A8,$0C,$A9,$08,$A1,$10,$F8
dc.w z80_ptr(MusCreditsDDEA)
dc.b $A8,$08,$A9,$04,$80,$18
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $80,$60,$EF,$17,$E1,$02,$E9,$F4,$E6,$0A,$F8
dc.w z80_ptr(MusCreditsDDD5)
dc.b $CE,$15,$CD,$03,$CB,$06,$80,$C9,$0C,$CD,$06,$80
dc.b $C9,$0C,$CB,$06,$80,$12,$80,$60,$EF,$1B,$E1,$00
dc.b $E8,$06,$80,$3C,$B8,$06,$06,$BA,$BD,$BD,$BA,$EF
dc.b $1D,$E6,$FA,$E8,$00,$F8
dc.w z80_ptr(MusCreditsDDF9)
dc.b $80,$F8
dc.w z80_ptr(MusCreditsDE09)
dc.b $F8
dc.w z80_ptr(MusCreditsDDF9)
dc.b $EF,$1C,$BD,$EF,$1D,$F8
dc.w z80_ptr(MusCreditsDE09)
dc.b $80,$30,$80,$EF,$01,$E9,$18,$E6,$F9
- dc.b $99,$0C,$A5,$06,$80,$96,$0C,$A2,$06,$80,$97,$0C
dc.b $A3,$06,$80,$98,$0C,$A8,$06,$A7,$99,$06,$99,$12
dc.b $96,$0C,$A2,$06,$80,$97,$0C,$A3,$06,$80,$98,$0C
dc.b $A4,$06,$80
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $80,$60,$EF,$22,$E9,$E8,$E6,$03
dc.b $F0,$1C,$01,$06,$04
dc.b $80,$50,$AC,$04,$AE,$08,$B1,$04,$B5,$30,$80,$0C
dc.b $B5,$08,$80,$04,$B6,$08,$B5,$10,$B9,$08,$04,$80
dc.b $08,$B5,$34,$80,$0C,$B5,$BA,$08,$04,$80,$08,$B5
dc.b $04,$B1,$24,$80,$0C,$B1,$08,$80,$04,$B3,$08,$B1
dc.b $04,$B4,$0C,$B3,$08,$B1,$4C,$80,$0C,$B5,$08,$80
dc.b $04,$B6,$08,$80,$04,$B5,$08,$80,$04,$B9,$08,$04
dc.b $80,$08,$B5,$1C,$80,$0C,$BA,$18,$BC,$08,$BA,$04
dc.b $BD,$18,$80,$0C,$BA,$04,$80,$08,$B8,$18,$B5,$B1
dc.b $B3,$0C,$E6,$04,$F8
dc.w z80_ptr(MusCreditsDE17)
dc.b $B3,$0C,$E6,$FC,$F8
dc.w z80_ptr(MusCreditsDE17)
dc.b $B3,$14,$B1,$04,$E6,$FF,$EF,$24,$F4,$80,$60
- dc.b $F8
dc.w z80_ptr(MusCreditsDE20)
dc.b $AC,$12,$AB,$0C,$AC,$06,$AB,$0C,$F8
dc.w z80_ptr(MusCreditsDE20)
dc.b $B3,$12,$B2,$0C,$B3,$06,$B2,$0C
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $AC,$06,$80,$A9,$80,$AA,$80,$AB,$80,$AC,$AC,$A9
dc.b $80,$AA,$80,$AC,$80,$A9,$80,$A9,$80,$AD,$80,$AD
dc.b $80,$B0,$80,$B0,$80,$B3,$80,$B3,$80,$80,$0C,$A2
dc.b $12,$80,$06,$A2,$12,$AD,$AE,$06,$80,$E6,$FD,$A2
dc.b $6C,$F2
MusCreditsDD59: dc.b $80,$0C,$C4,$06,$80,$C6,$80,$C4,$80,$C9,$80,$C9
dc.b $80,$CB,$CD,$80,$0C,$80,$CB,$18,$C6,$06,$80,$C9
dc.b $C9,$80,$CB,$0C,$80,$12,$80,$1E,$C7,$06,$C9,$C7
dc.b $CB,$80,$C9,$80,$C7,$C9,$80,$C6,$E7,$C6,$30,$E7
dc.b $18,$80,$18,$E3
MusCreditsDD8D: dc.b $9F,$04,$80,$08,$9F,$0C
dc.b $F7,$00,$03
dc.w z80_ptr(MusCreditsDD8D)
dc.b $06,$AB,$9F,$0C,$E3
MusCreditsDD9D: dc.b $B8,$08,$BA,$BC,$B6,$30,$E7,$30,$E7,$B6,$80,$18
dc.b $B8,$08,$BA,$BC,$B6,$30,$E7,$30,$E7,$30,$E7,$E3
MusCreditsDDB5: dc.b $BF,$06,$BD,$BF,$12,$C2,$BF,$0C,$C1,$80,$06,$12
dc.b $C4,$0C,$C2,$06,$80,$C9,$C6,$3C,$80,$06,$0C,$C7
dc.b $12,$C6,$C4,$06,$C2,$C1,$18,$E3
MusCreditsDDD5: dc.b $CE,$15,$CD,$03,$CB,$06,$80,$C9,$0C,$CD,$06,$80
dc.b $C9,$0C,$CB,$06,$80,$12,$80,$60,$E3
MusCreditsDDEA: dc.b $A2,$0C,$AE,$AC,$08,$AE,$04,$AC,$08,$A9,$04,$A7
dc.b $08,$04,$E3
MusCreditsDDF9: dc.b $80,$0C,$B1,$AE,$06,$06,$AC,$0C,$80,$B0,$AE,$06
dc.b $06,$AC,$0C,$E3
MusCreditsDE09: dc.b $AE,$AC,$06,$06,$AA,$0C,$80,$AC,$0C,$06,$06,$AE
dc.b $AC,$E3
MusCreditsDE17: dc.b $BA,$04,$80,$08,$B8,$18,$B5,$B1,$E3
MusCreditsDE20: dc.b $AE,$06,$80,$AE,$80,$A9,$80,$A9,$80,$E3
MusCreditsDE2A: dc.b $8A,$0C
dc.b $F7,$00,$08
dc.w z80_ptr(MusCreditsDE2A)
dc.b $E3
MusCred_FM3: dc.b $80,$60,$F8
dc.w z80_ptr(MusCreditsE065)
dc.b $E9,$18,$EF,$02,$F8
dc.w z80_ptr(MusCreditsE040)
dc.b $B8,$3C,$F8
dc.w z80_ptr(MusCreditsE040)
dc.b $BD,$3C,$E9,$E8,$E6,$02,$E1,$03,$EF,$04,$E0,$80
- dc.b $F8
dc.w z80_ptr(MusCreditsDD59)
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $EF,$09,$E9,$0C,$E6,$FD,$E0,$40
dc.b $F0,$06,$01,$05,$04
dc.b $E1,$00
- dc.b $9F,$0C,$AB,$06,$80,$A9,$80,$AB,$9F,$80,$9F,$AB
dc.b $80,$A9,$80,$AB,$0C
dc.b $F7,$00,$03
dc.w z80_ptr(-)
dc.b $9D,$0C,$A9,$06,$80,$A8,$80,$A9,$9C,$80,$9C,$A8
dc.b $80,$A6,$80,$A8,$0C
dc.b $F7,$01,$02
dc.w z80_ptr(-)
dc.b $80,$60,$EF,$0D,$E6,$FB,$E0,$C0,$F4,$80,$60
- dc.b $F8
dc.w z80_ptr(MusCreditsDFF2)
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $80,$60,$EF,$0F,$E0,$80,$E6,$0B,$F8
dc.w z80_ptr(MusCreditsDDB5)
dc.b $C4,$18,$C3,$48,$80,$0C,$F8
dc.w z80_ptr(MusCreditsDDB5)
dc.b $BE,$0C
dc.b $F0,$18,$01,$03,$04
dc.b $E6,$F3,$E0,$C0,$EF,$14,$A2,$14,$A4,$04,$A5,$04
dc.b $80,$08,$A9,$04,$80,$08,$A8,$04,$80,$08,$A9,$04
dc.b $80,$08,$AC,$08,$A9,$10
- dc.b $80,$30
dc.b $F7,$00,$0A
dc.w z80_ptr(-)
dc.b $EF,$18,$E9,$F4,$E6,$08,$F4,$E0,$40,$80,$60,$80
dc.b $30,$C6,$06,$80,$C2,$0C,$C4,$09,$C2,$03,$BF,$0C
dc.b $80,$60,$80,$3C,$80,$60,$EF,$1B,$E6,$FB,$E0,$C0
dc.b $E8,$06,$C4,$06,$06,$C6,$C9,$C9,$C6,$E8,$00,$CD
dc.b $0C,$E8,$06,$C9,$06,$C6,$C9,$0C,$80,$80,$12,$EF
dc.b $1C,$E8,$00,$BD,$BA,$0C,$E8,$06,$EF,$1B,$CE,$06
dc.b $CE,$80,$CE,$80,$CE,$E8,$00,$CF,$0C,$D0,$80,$E8
dc.b $06,$D0,$06,$06,$D2,$D0,$E8,$00,$CD,$0C,$E8,$06
dc.b $C9,$06,$C6,$C9,$0C,$E8,$00,$EF,$1C,$80,$1E,$C2
dc.b $0C,$C2,$BD,$06,$80,$60,$80,$60,$EF,$00,$E9,$18
dc.b $80,$60,$80,$0C,$AC,$06,$AE,$B1,$80,$12,$AC,$06
dc.b $AE,$B1,$80,$B4,$B1,$80,$B1,$80,$60,$80,$06,$AF
dc.b $12,$AE,$06,$80,$12,$AF,$06,$80,$AE,$80,$AF,$B1
dc.b $80,$B1,$80,$60,$EF,$22,$E9,$DC,$E6,$FF,$E0,$80
dc.b $80,$60,$F8
dc.w z80_ptr(MusCreditsE004)
dc.b $CD,$30,$CB,$18,$CD,$0C,$CB,$C9,$30,$CE,$F8
dc.w z80_ptr(MusCreditsE051)
dc.b $E6,$04,$F8
dc.w z80_ptr(MusCreditsE051)
dc.b $E6,$FC,$80,$C4,$80,$C4,$80,$C6,$18,$08,$C4,$04
dc.b $E9,$0C,$E6,$FF,$E0,$C0,$EF,$00,$80,$60
- dc.b $F8
dc.w z80_ptr(MusCreditsE05B)
dc.b $CB,$12,$CB,$1E,$F8
dc.w z80_ptr(MusCreditsE05B)
dc.b $D0,$12,$D0,$1E
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $80,$0C,$CB,$12,$80,$06,$CB,$80,$CA,$12,$CB,$CA
dc.b $0C,$C5,$18,$C8,$CB,$D1,$80,$0C,$CD,$80,$CD,$12
dc.b $CC,$CD,$06,$80,$E6,$F8,$EF,$01,$E1,$03,$A2,$6C
dc.b $F2
MusCreditsDFF2: dc.b $80,$60,$BC,$06,$BD,$BC,$B8,$BA,$B6,$0C,$B8,$B3
dc.b $B3,$06,$B6,$0C,$B8,$E3
MusCreditsE004: dc.b $80,$0C,$CD,$04,$80,$10,$CD,$04,$80,$0C,$CD,$0C
dc.b $CE,$08,$CD,$04,$80,$18,$80,$0C,$CB,$04,$80,$10
dc.b $CB,$04,$80,$0C,$CB,$0C,$CD,$08,$CB,$04,$80,$18
- dc.b $80,$0C,$C9,$04,$80,$10,$C9,$04,$80,$0C,$C9,$0C
dc.b $CB,$08,$C9,$04,$80,$18
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $E3
MusCreditsE040: dc.b $80,$18,$B8,$0B,$80,$0D,$BA,$0C,$0B,$80,$19,$BD
dc.b $0C,$0B,$80,$0D,$E3
MusCreditsE051: dc.b $80,$0C,$C4,$80,$C4,$80,$C6,$80,$C6,$E3
MusCreditsE05B: dc.b $CD,$06,$80,$CD,$80,$CA,$80,$CA,$80,$E3
MusCreditsE065: dc.b $EF,$05,$E9,$F4,$C6,$60,$CB,$CD,$E7,$CD,$C6,$60
dc.b $D0,$D0,$24,$D2,$60,$E7,$3C,$E3
MusCred_FM4: dc.b $80,$60,$E9,$FB,$E6,$FE,$F8
dc.w z80_ptr(MusCreditsE065)
dc.b $E9,$1D,$E6,$02,$EF,$02,$F8
dc.w z80_ptr(MusCreditsE2AE)
dc.b $B5,$3C,$F8
dc.w z80_ptr(MusCreditsE2AE)
dc.b $B8,$3C,$E6,$06,$EF,$05
dc.b $F0,$02,$01,$FE,$04
- dc.b $C1,$30,$E7,$30,$C3,$E7,$30,$BF,$E7,$30,$BD,$E7
dc.b $30
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $EF,$0A,$E9,$F4,$E6,$F7
dc.b $F0,$0C,$01,$FB,$04
- dc.b $F8
dc.w z80_ptr(MusCreditsE2BF)
dc.b $80,$25,$C3,$06,$C3,$80,$0C,$C3,$06,$C3,$05,$80
dc.b $0D,$C3,$06,$C5,$30,$E7,$06,$F8
dc.w z80_ptr(MusCreditsE2BF)
dc.b $80,$31,$80,$60
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $80,$60,$80,$48,$EF,$0C,$E6,$05,$F4,$E1,$02,$E0
dc.b $80,$F8
dc.w z80_ptr(MusCreditsDD9D)
dc.b $24,$80,$0C,$80,$60,$EF,$10,$E6,$F7,$E1,$00,$E0
dc.b $40,$F8
dc.w z80_ptr(MusCreditsE2D2)
dc.b $B3,$B7,$06,$AE,$0C,$B1,$B3,$B7,$06,$80,$B7,$AE
dc.b $0C,$B1,$F8
dc.w z80_ptr(MusCreditsE2D2)
dc.b $EF,$15,$E6,$01,$F8
dc.w z80_ptr(MusCreditsE22D)
- dc.b $EF,$14,$80,$4E,$E0,$40,$A1,$12,$A2,$06,$E0,$C0
dc.b $EF,$16,$80,$30,$80,$06,$BA,$08,$B9,$04,$B8,$08
dc.b $B7,$04,$B6,$08,$B5,$04
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $80,$60,$EF,$17,$E9,$F4,$E6,$02,$E0,$C0
dc.b $F0,$01,$01,$03,$03
- dc.b $F8
dc.w z80_ptr(MusCreditsDDD5)
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $80,$60,$EF,$1E,$E0,$40,$E6,$FE,$E9,$F4,$F4,$E8
dc.b $06,$80,$0C,$C1,$06,$12,$18,$C4,$06,$12,$0C,$EF
dc.b $1C,$E0,$C0,$E6,$FA,$E8,$00,$C6,$E8,$06,$E6,$06
dc.b $EF,$1E,$E0,$40,$C2,$06,$12,$18,$C4,$06,$12,$18
dc.b $C1,$06,$12,$18,$C4,$06,$12,$0C,$EF,$1A,$E0,$C0
dc.b $E9,$0C,$C6,$06,$C6,$80,$C6,$80,$C6,$E8,$00,$C7
dc.b $0C,$C8,$06,$EF,$1E,$E0,$40,$E9,$F4,$E8,$06,$80
dc.b $C4,$06,$12,$0C,$80,$60,$EF,$20,$E9,$18,$E6,$FA
dc.b $E0,$C0,$E8,$00,$B4,$03,$E7,$B6,$5D,$B3,$03,$E7
dc.b $B5,$5D,$B1,$03,$E7,$B3,$5D,$B3,$03,$E7,$B5,$5D
dc.b $80,$60,$EF,$22,$E0,$40,$E9,$E8,$E6,$04,$80,$30
dc.b $80,$F8
dc.w z80_ptr(MusCreditsE246)
dc.b $C9,$30,$C8,$18,$C9,$0C,$C8,$C6,$30,$C9,$80,$0C
dc.b $C1,$80,$C1,$80,$C2,$80,$C2,$E6,$04,$80,$C1,$80
dc.b $C1,$80,$C2,$80,$C2,$E6,$FC,$80,$C1,$80,$C1,$80
dc.b $C2,$18,$08,$C1,$04,$E9,$0C,$E6,$FF,$E0,$C0,$EF
dc.b $00,$80,$60
- dc.b $F8
dc.w z80_ptr(MusCreditsE2C8)
dc.b $C8,$12,$C8,$1E,$F8
dc.w z80_ptr(MusCreditsE2C8)
dc.b $CB,$12,$CB,$1E
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $E1,$03,$E6,$08,$F8
dc.w z80_ptr(MusCreditsE28F)
dc.b $E6,$F0,$EF,$01
dc.b $F0,$00,$01,$06,$04
dc.b $A2,$6C,$F2
MusCreditsE22D: dc.b $A2,$14,$A4,$04,$A5,$04,$80,$08,$A9,$04,$80,$08
dc.b $A8,$04,$80,$08,$A9,$04,$80,$08,$AC,$08,$A9,$10
dc.b $E3
MusCreditsE246: dc.b $80,$0C
dc.b $C9,$04,$80,$10
dc.b $C9,$04,$80,$0C
dc.b $C9,$0C
dc.b $CB,$08
dc.b $C9,$04,$80,$18,$80,$0C
dc.b $C8,$04,$80,$10
dc.b $C8,$04,$80,$0C
dc.b $C8,$0C
dc.b $C9,$08
dc.b $C8,$04,$80,$18,$80,$0C
if 1==1
; this part of the original credits music (CNZ PSG) sounds buggy (dissonant)
dc.b $C6,$04,$80,$10
dc.b $C6,$04,$80,$0C
dc.b $C6,$0C
dc.b $C8,$08
dc.b $C6,$04,$80,$18,$80,$0C
dc.b $C5,$04,$80,$10
dc.b $C5,$04,$80,$0C
dc.b $C5,$0C
dc.b $C7,$08
else
; replace the above block of notes with this to fix it.
; (I'm not sure why, but the notes $C6 and $C7 are broken here,
; so I've replaced them with pitch-shifted $C8s)
dc.b $E1,-64
dc.b $C8,$04,$80,$10 ; $C6
dc.b $C8,$04,$80,$0C ; $C6
dc.b $C8,$0C ; $C6
dc.b $E1,0
dc.b $C8,$08
dc.b $E1,-64
dc.b $C8,$04,$80,$24 ; $C6
dc.b $E1,0
dc.b $C5,$04,$80,$10
dc.b $C5,$04,$80,$0C
dc.b $C5,$0C
dc.b $E1,-32
dc.b $C8,$08 ; $C7
dc.b $E1,0
endif
dc.b $C5,$04,$80,$18
dc.b $E3
MusCreditsE28F: dc.b $EF,$25,$80,$0C,$D0,$D4,$D7,$DB,$0C,$80,$06,$DB
dc.b $0C,$DC,$06,$DB,$0C,$DD,$60,$DE,$0C,$80,$DE,$80
dc.b $80,$06,$DD,$12,$DE,$0C,$E3
MusCreditsE2AE: dc.b $80,$18,$B5,$0B,$80,$0D,$B7,$0C,$0B,$80,$19,$BA
dc.b $0C,$0B,$80,$0D,$E3
MusCreditsE2BF: dc.b $C3,$05,$80,$13,$C3,$12,$C3,$05,$E3
MusCreditsE2C8: dc.b $CA,$06,$80,$CA,$80,$C6,$80,$C6,$80,$E3
MusCreditsE2D2: dc.b $AF,$0C,$B3,$06,$B6,$0C,$AF,$B1,$06,$80,$B1,$0C
dc.b $B5,$06,$B8,$0C,$B1,$06,$80,$B6,$0C,$BA,$06,$B1
dc.b $0C,$B5,$B6,$BA,$06,$80,$BA,$AF,$0C,$B3,$B5,$B8
dc.b $06,$B2,$0C,$B3,$B5,$B8,$06,$80,$B8,$B2,$0C,$B5
dc.b $E3
MusCred_FM5: dc.b $E9,$E8,$E6,$F8,$E1,$05,$F8
dc.w z80_ptr(MusCreditsDB06)
dc.b $E9,$18,$E6,$08,$E1,$00,$EF,$02
dc.b $F0,$0C,$01,$FC,$04
dc.b $F8
dc.w z80_ptr(MusCreditsE4E8)
dc.b $B1,$3C,$F8
dc.w z80_ptr(MusCreditsE4E8)
dc.b $B5,$3C,$E9,$F4,$E6,$07
dc.b $F0,$30,$01,$04,$04
dc.b $EF,$06
- dc.b $C4,$30,$E7,$30,$C6,$E7,$30,$C2,$E7,$30,$C1,$E7
dc.b $30
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $EF,$0A,$E6,$F6
dc.b $F0,$0C,$01,$05,$04
dc.b $E0,$80
- dc.b $F8
dc.w z80_ptr(MusCreditsE4F9)
dc.b $80,$25,$C6,$06,$C6,$80,$0C,$C6,$06,$C6,$05,$80
dc.b $0D,$C6,$06,$C8,$30,$E7,$06,$F8
dc.w z80_ptr(MusCreditsE4F9)
dc.b $80,$31,$80,$60
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $80,$60,$80,$48,$E6,$05,$F4,$80,$01,$EF,$0C,$E1
dc.b $FE,$E0,$40,$F8
dc.w z80_ptr(MusCreditsDD9D)
dc.b $23,$80,$0C,$80,$60,$EF,$11,$E9,$F4,$E6,$F4,$E1
dc.b $00,$E0,$C0
dc.b $F0,$06,$01,$06,$05
dc.b $80,$60,$80,$30,$C2,$06,$C2,$C9,$C6,$1E,$80,$60
dc.b $80,$06,$CB,$80,$CB,$C9,$80,$C9,$80,$C7,$80,$C7
dc.b $80,$C6,$03,$80,$C6,$80,$09,$80,$06,$80,$60,$80
dc.b $30,$C2,$06,$C2,$C9,$C6,$1E,$80,$60,$EF,$16,$E9
dc.b $0C,$E6,$04,$F4,$E0,$80,$80,$01,$F8
dc.w z80_ptr(MusCreditsE22D)
dc.b $80,$2F,$F8
dc.w z80_ptr(MusCreditsE4CD)
dc.b $80,$30,$F8
dc.w z80_ptr(MusCreditsE4CD)
dc.b $80,$60,$EF,$19,$E9,$F4,$E0,$C0,$F8
dc.w z80_ptr(MusCreditsE502)
dc.b $80,$27,$B1,$03,$F8
dc.w z80_ptr(MusCreditsE502)
dc.b $80,$2A,$80,$60,$EF,$1E,$E9,$F4,$E8,$06
- dc.b $80,$0C,$C4,$06,$12,$18,$C8,$06,$12,$0C,$80,$C6
dc.b $06,$12,$18,$C8,$06,$12,$0C
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $80,$60,$EF,$20,$E8,$00,$E9,$18,$E6,$FA,$B8,$03
dc.b $E7,$BA,$5D,$B6,$03,$E7,$B8,$5D,$B4,$03,$E7,$B6
dc.b $5D,$B6,$03,$E7,$B8,$5D,$80,$60,$EF,$22,$E9,$F4
dc.b $E6,$05
dc.b $F0,$1C,$01,$06,$04
dc.b $80,$50,$A7,$04,$A9,$08,$AC,$04,$B1,$30,$80,$0C
dc.b $B1,$08,$80,$04,$B3,$08,$B1,$10,$B5,$08,$B5,$04
dc.b $80,$08,$B0,$34,$80,$0C,$B0,$B5,$08,$04,$80,$08
dc.b $B1,$04,$AE,$24,$80,$0C,$AE,$08,$80,$04,$B0,$08
dc.b $AE,$04,$B1,$0C,$AF,$08,$AD,$4C,$80,$0C,$B1,$08
dc.b $80,$04,$B3,$08,$80,$04,$B1,$08,$80,$04,$B5,$08
dc.b $B5,$04,$80,$08,$B0,$1C,$80,$0C,$B5,$18,$B8,$08
dc.b $B5,$04,$BA,$18,$80,$0C,$B6,$04,$80,$08,$B5,$18
dc.b $B1,$AE,$B0,$0C,$E6,$04,$B6,$04,$80,$08,$B5,$18
dc.b $B1,$AE,$B0,$0C,$E6,$F8,$B6,$04,$80,$08,$B5,$18
dc.b $B1,$AE,$AA,$14,$A9,$04,$E6,$0C,$EF,$23,$E1,$03
dc.b $E6,$F7,$80,$60,$F8
dc.w z80_ptr(MusCreditsDABE)
dc.b $E6,$09
dc.b $F0,$00,$01,$06,$04
dc.b $F8
dc.w z80_ptr(MusCreditsE28F)
dc.b $F2
MusCreditsE4CD: dc.b $80,$1E,$EF,$14,$A4,$12,$A5,$06,$EF,$16,$80,$30
dc.b $80,$06,$BD,$08,$BC,$04,$BB,$08,$BA,$04,$B9,$08
dc.b $B8,$04,$E3
MusCreditsE4E8: dc.b $80,$18,$B1,$0B,$80,$0D,$B3,$0C,$0B,$80,$19,$B6
dc.b $0C,$0B,$80,$0D,$E3
MusCreditsE4F9: dc.b $C6,$05,$80,$13,$C6,$12,$C6,$05,$E3
MusCreditsE502: dc.b $80,$60,$AC,$06,$80,$AC,$0C,$AE,$06,$80,$AE,$0C
dc.b $AF,$06,$E3
MusCred_PSG1: dc.b $80,$30
dc.b $F7,$00,$1A
dc.w z80_ptr(MusCred_PSG1)
- dc.b $C4,$30,$E7,$30,$C6,$E7,$30,$C2,$E7,$30,$C1,$E7
dc.b $30
dc.b $F7,$00,$02
dc.w z80_ptr(-)
- dc.b $80,$30
dc.b $F7,$00,$10
dc.w z80_ptr(-)
dc.b $80,$60
- dc.b $80,$30
dc.b $F7,$00,$0A
dc.w z80_ptr(-)
dc.b $80,$60,$E9,$F4,$E6,$FE,$F5,$01,$F8
dc.w z80_ptr(MusCreditsE635)
dc.b $AE,$B3,$06,$AC,$0C,$AE,$AE,$B3,$06,$80,$B3,$AB
dc.b $0C,$AE,$F8
dc.w z80_ptr(MusCreditsE635)
dc.b $F5,$0B,$80,$04,$80,$60,$F8
dc.w z80_ptr(MusCreditsDA5F)
dc.b $E7,$20,$E7,$C5,$01,$E7,$C4,$E7,$C3,$E7,$C2,$E7
dc.b $C1,$E7,$C0,$E7,$BF,$E7,$BE,$E7,$BD,$E7,$BC,$E7
dc.b $BB,$E7,$BA,$80,$60,$F5,$00,$E8,$06,$E9,$F4,$F8
dc.w z80_ptr(MusCreditsE62C)
dc.b $C2,$80,$C2,$F8
dc.w z80_ptr(MusCreditsE62C)
dc.b $C2,$04,$80,$C2,$80,$0C,$C2,$80,$60,$F5,$08,$E9
dc.b $04,$EC,$02,$E8,$06
- dc.b $F8
dc.w z80_ptr(MusCreditsE618)
dc.b $F7,$00,$02
dc.w z80_ptr(-)
- dc.b $80,$30
dc.b $F7,$00,$0A
dc.w z80_ptr(-)
dc.b $80,$60,$F5,$00,$E9,$F0,$EC,$FF,$80,$60
dc.b $F8
dc.w z80_ptr(MusCreditsE004)
dc.b $E9,$18,$EC,$02,$B5,$30,$B3,$18,$B5,$0C,$B3,$B1
dc.b $30,$B6,$EC,$FE,$80,$0C,$B8,$80,$B8,$80,$BA,$80
dc.b $BA,$EC,$03,$C4,$18,$C1,$BD,$BF,$0C,$80,$EC,$FC
dc.b $80,$B8,$80,$B8,$80,$BA,$18,$08,$B8,$04,$E9,$F4
dc.b $EC,$01,$F5,$05
- dc.b $80,$60
dc.b $F7,$00,$05
dc.w z80_ptr(-)
dc.b $80,$0C,$C8,$12,$80,$06,$C8,$80,$C6,$12,$C8,$C6
dc.b $0C,$C1,$18,$C5,$C8,$CB,$80,$0C,$CA,$80,$CA,$12
dc.b $C9,$CA,$06,$80,$09,$E9,$30,$EC,$FC,$F6
dc.w z80_ptr(MusCreditsE770)
dc.b $F2
MusCreditsE618: dc.b $80,$0C,$BD,$06,$12,$18,$C4,$06,$12,$0C,$80,$C2
dc.b $06,$12,$18,$C4,$06,$12,$0C,$E3
MusCreditsE62C: dc.b $80,$60,$80,$0C,$C2,$80,$C2,$80,$E3
MusCreditsE635: dc.b $AC,$0C,$AF,$06,$B3,$0C,$AC,$AC,$06,$80,$AC,$0C
dc.b $AF,$06,$B5,$0C,$AC,$06,$80,$06,$B1,$0C,$B6,$06
dc.b $AE,$0C,$B1,$B3,$B6,$06,$80,$B6,$AA,$0C,$AF,$AF
dc.b $B5,$06,$AC,$0C,$AF,$B2,$B5,$06,$80,$B5,$AE,$0C
dc.b $B2,$E3
MusCred_PSG2: dc.b $80,$30
dc.b $F7,$00,$1A
dc.w z80_ptr(MusCred_PSG2)
- dc.b $C1,$30,$E7,$30,$C3,$E7,$30,$BF,$E7,$30,$BD,$E7
dc.b $30
dc.b $F7,$00,$02
dc.w z80_ptr(-)
- dc.b $80,$30
dc.b $F7,$00,$10
dc.w z80_ptr(-)
dc.b $80,$60,$E9,$0C,$EC,$FD,$F5,$04,$80
- dc.b $F8
dc.w z80_ptr(MusCreditsDFF2)
dc.b $F7,$00,$02
dc.w z80_ptr(-)
dc.b $80,$60
dc.b $F0,$03,$02,$01,$05
dc.b $F5,$0A,$E9,$E8,$EC,$02,$80,$30,$80,$80,$BD,$06
dc.b $BF,$C6,$C2,$1E,$80,$60,$80,$06,$C6,$80,$C6,$C4
dc.b $80,$C4,$80,$C3,$80,$C3,$80,$BF,$03,$80,$BF,$80
dc.b $09,$80,$06,$80,$30,$80,$80,$BD,$06,$BF,$C6,$C2
dc.b $1E,$80,$60,$F4
- dc.b $80,$30
dc.b $F7,$00,$0C
dc.w z80_ptr(-)
dc.b $F5,$00,$EC,$FE,$E8,$06,$80,$60,$80,$0C,$BF,$80
dc.b $BF,$80,$BF,$80,$BF,$80,$60,$80,$0C,$BF,$80,$BF
dc.b $80,$BF,$04,$80,$BF,$80,$0C,$BF,$80,$60,$EC,$02
- dc.b $F8
dc.w z80_ptr(MusCreditsE618)
dc.b $F7,$00,$02
dc.w z80_ptr(-)
- dc.b $80,$30
dc.b $F7,$00,$0A
dc.w z80_ptr(-)
dc.b $80,$60,$F5,$00,$E9,$F4,$EC,$FF,$E9,$E8,$80,$60
dc.b $F8
dc.w z80_ptr(MusCreditsE246)
dc.b $E9,$18,$EC,$02,$B1,$30,$B0,$18,$B1,$0C,$B0,$AE
dc.b $30,$B1,$EC,$FE,$80,$0C,$B5,$80,$B5,$80,$B6,$80
dc.b $B6,$EC,$03,$80,$B1,$80,$B1,$80,$B1,$80,$B1,$EC
dc.b $FC,$80,$B1,$80,$B1,$80,$B1,$18,$08,$B1,$04,$EC
dc.b $01,$E9,$18,$F5,$05,$E1,$01,$80,$60,$80,$80,$80
dc.b $80,$80,$80,$0C,$CD,$06,$80,$D4,$CD,$80,$0C,$CD
dc.b $06,$80,$D4,$CD,$80,$18,$80,$54,$E9,$24,$EC,$FD
MusCreditsE770: dc.b $F5,$03,$80,$06
- dc.b $BF,$03,$C1,$C3,$EC,$01,$E9,$FF
dc.b $F7,$00,$05
dc.w z80_ptr(-)
- dc.b $BF,$03,$C1,$C3,$EC,$01,$E9,$01
dc.b $F7,$00,$07
dc.w z80_ptr(-)
dc.b $F2
MusCred_PSG3: dc.b $F3,$E7,$80,$60,$F5,$02
- dc.b $C6,$0C,$0C,$0C,$06,$06,$0C,$0C,$06,$06,$0C
dc.b $F7,$00,$08
dc.w z80_ptr(-)
- dc.b $80,$30
dc.b $F7,$00,$08
dc.w z80_ptr(-)
- dc.b $C6,$0C,$06,$06
dc.b $F7,$00,$1F
dc.w z80_ptr(-)
dc.b $0C,$F5,$03,$C6,$F5,$02
- dc.b $C6,$0C,$06,$06
dc.b $F7,$00,$07
dc.w z80_ptr(-)
dc.b $06,$06,$06,$06
dc.b $F7,$01,$04
dc.w z80_ptr(-)
- dc.b $80,$30
dc.b $F7,$00,$0C
dc.w z80_ptr(-)
dc.b $F5,$04,$EC,$02
- dc.b $E8,$03,$C6,$06,$06,$E8,$00,$0C
dc.b $F7,$00,$04
dc.w z80_ptr(-)
dc.b $F5,$02,$EC,$FD
- dc.b $80,$0C,$C6,$06,$80,$07,$C6,$06,$80,$11,$C6,$0C
dc.b $80,$06,$C6,$0C,$80,$06,$C6,$80
dc.b $F7,$00,$07
dc.w z80_ptr(-)
dc.b $EC,$02
- dc.b $C6,$0C,$08,$04
dc.b $F7,$00,$18
dc.w z80_ptr(-)
- dc.b $C6,$0C,$0C,$0C,$08,$04
dc.b $F7,$00,$08
dc.w z80_ptr(-)
dc.b $80,$60,$F5,$04,$EC,$02
- dc.b $C6,$06,$06,$0C
dc.b $F7,$00,$10
dc.w z80_ptr(-)
- dc.b $80,$30
dc.b $F7,$00,$0A
dc.w z80_ptr(-)
dc.b $80,$60,$EC,$FF
- dc.b $F5,$01,$C6,$0C,$F5,$02,$EC,$FF,$08,$F5,$01,$EC
dc.b $01,$04
dc.b $F7,$00,$27
dc.w z80_ptr(-)
dc.b $EC,$FF,$F5,$04
- dc.b $E8,$03,$C6,$0C,$E8,$0C,$0C
dc.b $F7,$00,$1E
dc.w z80_ptr(-)
dc.b $E8,$03,$C6,$06,$E8,$0E,$12,$E8,$03,$0C,$E8,$0F
dc.b $0C,$F2
MusCred_DAC: dc.b $82,$06,$82,$82,$82,$82,$0C,$06,$0C,$06,$0C,$0C
dc.b $0C
- dc.b $81,$18,$82
dc.b $F7,$00,$0E
dc.w z80_ptr(-)
dc.b $81,$0C
- dc.b $82
dc.b $F7,$00,$07
dc.w z80_ptr(-)
dc.b $EA,$EA,$F8
dc.w z80_ptr(MusCreditsEA6E)
dc.b $81,$0C,$8D,$82,$81,$81,$8E,$82,$84,$04,$06,$02
dc.b $81,$0C,$82,$06,$82,$82,$82,$81,$0C,$82,$06,$82
dc.b $81,$81,$82,$82,$82,$82
- dc.b $81,$18,$82,$81,$82
dc.b $F7,$00,$07
dc.w z80_ptr(-)
dc.b $81,$0C,$82,$82,$82,$82,$06,$82,$8C,$8C,$8D,$8D
dc.b $8E,$8E,$F8
dc.w z80_ptr(MusCreditsEA84)
dc.b $81,$18,$82,$0C,$81,$18,$82,$0C,$82,$82,$06,$82
dc.b $F8
dc.w z80_ptr(MusCreditsEA84)
dc.b $81,$0C,$82,$82,$82,$8D,$06,$8D,$8E,$8E,$82,$06
dc.b $82,$8D,$0C,$82,$0C,$82,$06,$82,$80,$82,$82,$0C
MusCreditsE8E5: dc.b $82,$0C,$82,$82,$06,$82,$8D,$8D
- dc.b $81,$0C,$8F,$06,$90,$82,$0C,$90,$06,$91,$81,$0C
dc.b $8F,$06,$91,$82,$0C,$8F,$06,$91
dc.b $F7,$00,$04
dc.w z80_ptr(-)
dc.b $81,$0C,$8F,$06,$91,$82,$0C,$8F,$06,$91,$8C,$06
dc.b $03,$03,$8D,$06,$8D,$8D,$8E,$8E,$8E,$81,$06,$0C
dc.b $82,$06,$80,$0C,$81,$82,$8E,$82,$06,$82,$82,$82
- dc.b $81,$0C,$82,$06,$81,$12,$81,$06,$81,$12,$8C,$06
dc.b $82,$0C,$83,$06,$81,$80
dc.b $F7,$00,$06
dc.w z80_ptr(-)
dc.b $81,$0C,$82,$06,$81,$12,$81,$06,$81,$06,$82,$06
dc.b $81,$0C,$06,$82,$0C,$08,$04,$EA,$CD,$82,$30,$82
dc.b $0C,$82,$82,$82,$08,$04,$F8
dc.w z80_ptr(MusCreditsEA9F)
dc.b $F8
dc.w z80_ptr(MusCreditsEA9F)
dc.b $81,$08,$0C,$04,$82,$0C,$81,$08,$04,$82,$08,$04
dc.b $08,$04,$04,$04,$04,$08,$04,$EA,$C5
- dc.b $81,$09,$81,$03,$0C,$82,$81,$81,$18,$82
dc.b $F7,$00,$03
dc.w z80_ptr(-)
dc.b $81,$09,$81,$03,$0C,$82,$81,$81,$18,$82,$0C,$06
dc.b $06,$81,$0C,$82,$06,$82,$82,$82,$8D,$0C,$82,$0C
dc.b $0C,$0C,$06,$06
- dc.b $81,$0C,$81,$82,$80,$81,$81,$82,$83
dc.b $F7,$00,$03
dc.w z80_ptr(-)
dc.b $81,$82,$82,$82,$82,$06,$06,$06,$06,$0C,$06,$06
dc.b $81,$06,$81,$82,$82,$81,$82,$81,$81,$82,$02,$82
dc.b $04,$81,$0C,$06,$82,$0C,$06,$06,$81,$18,$82,$0C
dc.b $81,$81,$18,$82,$81,$06,$81,$12,$82,$0C,$81,$81
dc.b $18,$82,$81,$18,$82,$0C,$81,$81,$18,$82,$81,$06
dc.b $81,$12,$82,$0C,$0C,$06,$06,$06,$06,$0C,$06,$06
dc.b $82,$02,$04,$81,$0C,$06,$0C,$82,$02,$04,$81,$0C
dc.b $06,$0C,$82,$06,$82,$82,$82,$EA,$C0,$81,$0C,$82
dc.b $81,$82,$81,$82,$81,$08,$82,$04,$0C
- dc.b $81,$0C,$82
dc.b $F7,$00,$0F
dc.w z80_ptr(-)
dc.b $81,$08,$82,$04,$0C
- dc.b $81,$0C,$82
dc.b $F7,$00,$13
dc.w z80_ptr(-)
dc.b $82,$08,$0C,$04,$81,$0C,$82,$81,$82,$81,$0C,$82
dc.b $81,$06,$80,$02,$82,$82,$82,$09,$82,$03
- dc.b $81,$0C,$82
dc.b $F7,$00,$06
dc.w z80_ptr(-)
dc.b $81,$0C,$82,$81,$06,$80,$02,$82,$82,$82,$09,$82
dc.b $03
dc.b $F7,$01,$03
dc.w z80_ptr(-)
dc.b $81,$0C,$82,$81,$82,$81,$06,$82,$12,$82,$0C,$81
dc.b $F2
MusCreditsEA6E: dc.b $81,$0C,$8D,$82,$81,$81,$8E,$82,$84,$04,$06,$02
dc.b $81,$0C,$8D,$82,$81,$81,$8E,$82,$83,$E3
MusCreditsEA84: dc.b $81,$18,$82,$0C,$81,$18,$0C,$82,$81,$81,$18,$82
dc.b $0C,$81,$12,$81,$82,$18,$81,$82,$0C,$81,$18,$0C
dc.b $82,$81,$E3
MusCreditsEA9F: dc.b $81,$08,$0C,$04,$82,$0C,$81,$08,$0C,$82,$04,$81
dc.b $0C,$82,$81,$81,$08,$0C,$04,$82,$0C,$81,$08,$0C
dc.b $82,$04,$81,$0C,$82,$82,$08,$04,$E3,$81,$06,$80
dc.b $03,$81,$81,$06,$82,$81,$06,$80,$03,$81,$81,$06
dc.b $82,$03,$82,$81,$06,$80,$03,$81,$81,$06,$82,$E3
MusCred_Voices: dc.b $3A,$01,$01,$07,$01,$8E,$8D,$8E,$53,$0E,$0E,$0E
dc.b $03,$00,$00,$00,$01,$1F,$1F,$FF,$0F,$17,$27,$28,$80
dc.b $08,$09,$30,$70,$00,$1F,$5F,$1F,$5F,$12,$0A,$0E
dc.b $0A,$00,$04,$04,$03,$2F,$2F,$2F,$2F,$25,$0E,$30,$84
dc.b $3C,$31,$50,$52,$30,$52,$52,$53,$53,$08,$08,$00
dc.b $00,$04,$04,$00,$00,$10,$10,$0B,$0D,$19,$0B,$80,$80
dc.b $08,$0A,$30,$70,$00,$1F,$5F,$1F,$5F,$12,$0A,$0E
dc.b $0A,$00,$04,$04,$03,$2F,$2F,$2F,$2F,$24,$13,$2D,$80
dc.b $3D,$01,$51,$21,$01,$12,$14,$14,$0F,$0A,$05,$05
dc.b $05,$00,$00,$00,$00,$2B,$2B,$2B,$1B,$19,$80,$80,$80
dc.b $04,$57,$70,$02,$50,$1F,$1F,$1F,$1F,$00,$00,$00
dc.b $00,$06,$00,$0A,$0A,$00,$00,$0F,$0F,$1A,$10,$80,$80
dc.b $35,$01,$13,$01,$00,$1F,$18,$1D,$19,$00,$06,$09
dc.b $0D,$00,$02,$00,$03,$00,$15,$06,$16,$1E,$83,$80,$80
dc.b $3C,$31,$50,$52,$30,$52,$52,$53,$53,$08,$08,$00
dc.b $00,$04,$04,$00,$00,$1F,$1F,$0F,$0F,$1A,$16,$88,$88
dc.b $20,$36,$30,$35,$31,$DF,$9F,$DF,$9F,$07,$09,$06
dc.b $06,$07,$06,$06,$08,$2F,$1F,$1F,$FF,$14,$0F,$37,$80
dc.b $3B,$0F,$01,$06,$02,$DF,$1F,$1F,$DF,$0C,$0A,$00
dc.b $03,$0F,$00,$00,$01,$F3,$55,$05,$5C,$22,$22,$20,$80
dc.b $3C,$31,$50,$52,$30,$52,$52,$53,$53,$08,$08,$00
dc.b $00,$04,$04,$00,$00,$1F,$1F,$0F,$0F,$1C,$14,$84,$80
dc.b $3A,$69,$50,$70,$60,$1C,$1A,$18,$18,$10,$02,$0C
dc.b $09,$08,$06,$06,$03,$F9,$06,$56,$06,$28,$14,$15,$00
dc.b $3D,$00,$02,$01,$01,$4C,$50,$0F,$12,$0C,$00,$02
dc.b $05,$01,$00,$00,$00,$28,$2A,$29,$19,$1A,$06,$00,$00
dc.b $2C,$71,$31,$71,$31,$1F,$1F,$16,$16,$00,$00,$0F
dc.b $0F,$00,$00,$0F,$0F,$00,$00,$FA,$FA,$15,$14,$00,$00
dc.b $18,$37,$31,$32,$31,$9E,$1C,$DC,$9C,$0D,$04,$06
dc.b $01,$08,$03,$0A,$05,$B6,$36,$B6,$28,$2C,$14,$22,$00
dc.b $3D,$01,$02,$02,$02,$10,$50,$50,$50,$07,$08,$08
dc.b $08,$01,$00,$00,$00,$24,$18,$18,$18,$1C,$82,$82,$82
dc.b $32,$71,$33,$0D,$01,$5F,$5F,$99,$94,$05,$05,$05
dc.b $07,$02,$02,$02,$02,$11,$11,$11,$72,$23,$26,$2D,$80
dc.b $3A,$32,$52,$01,$31,$1F,$1F,$1F,$18,$01,$00,$1F
dc.b $00,$00,$00,$0F,$00,$5A,$03,$0F,$1A,$3B,$4F,$30,$00
dc.b $3C,$42,$32,$41,$41,$12,$12,$12,$12,$00,$00,$00
dc.b $00,$00,$00,$00,$00,$06,$06,$08,$08,$24,$24,$08,$08
dc.b $31,$34,$30,$35,$31,$DF,$9F,$DF,$9F,$0C,$0C,$07
dc.b $09,$07,$07,$07,$08,$2F,$1F,$1F,$2F,$17,$14,$32,$80
dc.b $3D,$01,$01,$01,$01,$10,$50,$50,$50,$07,$08,$08
dc.b $08,$01,$00,$00,$00,$20,$1A,$1A,$1A,$19,$84,$84,$84
dc.b $24,$70,$30,$74,$38,$12,$1F,$1F,$1F,$05,$05,$03
dc.b $03,$05,$05,$03,$03,$36,$26,$2C,$2C,$0A,$06,$08,$08
dc.b $3A,$01,$01,$01,$02,$8D,$07,$07,$52,$09,$00,$00
dc.b $03,$01,$02,$02,$00,$5F,$0F,$0F,$2F,$18,$18,$22,$80
dc.b $3A,$01,$01,$07,$01,$8E,$8D,$8E,$53,$0E,$0E,$0E
dc.b $03,$00,$00,$00,$00,$1F,$1F,$FF,$0F,$18,$16,$4E,$80
dc.b $3A,$03,$03,$08,$01,$8E,$8D,$8E,$53,$0E,$0E,$0E
dc.b $03,$00,$00,$00,$00,$1F,$1F,$FF,$0F,$17,$20,$28,$80
dc.b $20,$7A,$00,$31,$00,$9F,$DC,$D8,$DF,$10,$04,$0A
dc.b $04,$0F,$08,$08,$08,$5F,$BF,$5F,$BF,$14,$17,$2B,$80
dc.b $3A,$61,$51,$08,$02,$5D,$5D,$5D,$50,$04,$1F,$0F
dc.b $1F,$00,$00,$00,$00,$1F,$0F,$5F,$0F,$22,$22,$1E,$80
dc.b $02,$01,$02,$55,$04,$92,$8E,$8D,$54,$0D,$00,$0C
dc.b $03,$00,$00,$00,$00,$FF,$0F,$2F,$5F,$16,$1D,$2A,$80
dc.b $02,$75,$73,$71,$31,$1F,$96,$58,$9F,$01,$03,$1B
dc.b $08,$01,$01,$04,$05,$FF,$3F,$2F,$2F,$24,$30,$29,$80
dc.b $20,$66,$60,$65,$60,$DF,$9F,$DF,$1F,$00,$09,$06
dc.b $0C,$07,$06,$06,$08,$2F,$1F,$1F,$FF,$1C,$16,$3A,$80
dc.b $0D,$32,$06,$08,$01,$1F,$19,$19,$19,$0A,$05,$05
dc.b $05,$00,$02,$02,$02,$3F,$2F,$2F,$2F,$28,$86,$80,$8D
dc.b $38,$3A,$11,$0A,$02,$D4,$50,$14,$0E,$05,$02,$08
dc.b $88,$00,$00,$00,$00,$99,$09,$09,$1A,$2D,$19,$2C,$86
dc.b $0D,$32,$02,$04,$01,$1F,$19,$19,$19,$0A,$05,$05
dc.b $05,$00,$02,$02,$02,$3F,$2F,$2F,$2F,$28,$8B,$86,$93
dc.b $3A,$20,$60,$23,$01,$1E,$1F,$1F,$1F,$0A,$0B,$0A
dc.b $0A,$05,$0A,$07,$08,$A4,$96,$85,$78,$21,$28,$25,$00
dc.b $3A,$32,$32,$56,$42,$8D,$15,$4F,$52,$06,$07,$08
dc.b $04,$02,$00,$00,$00,$18,$28,$18,$28,$19,$2A,$20,$00
dc.b $3A,$51,$51,$08,$02,$1E,$1E,$1E,$10,$1F,$1F,$1F
dc.b $0F,$00,$00,$00,$02,$0F,$0F,$0F,$1F,$18,$22,$24,$81
dc.b $20,$36,$30,$35,$31,$DF,$9F,$DF,$9F,$07,$09,$06
dc.b $06,$07,$06,$06,$08,$2F,$1F,$1F,$FF,$19,$13,$37,$80
dc.b $3D,$01,$02,$02,$02,$14,$8C,$0E,$0E,$08,$02,$05
dc.b $05,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$1A,$80,$80,$80
; end of Mus_Credits
; ------------------------------------------------------------------------------------------
; Sound effect pointers
; ------------------------------------------------------------------------------------------
; WARNING the sound driver treats certain sounds specially
; going by the ID of the sound.
; SndID_Ring, SndID_RingLeft, SndID_Gloop, SndID_SpindashRev
; are referenced by the sound driver directly.
; If needed you can change this in s2.sounddriver.asm
; NOTE: the exact order of this list determines the priority of each sound, since it determines the sound's SndID.
; a sound can get dropped if a higher-priority sound is already playing.
; see zSFXPriority for the priority allocation itself.
; loc_FEE91: SoundPoint:
SoundIndex:
SndPtr_Jump: rom_ptr_z80 Sound20 ; jumping sound
SndPtr_Checkpoint: rom_ptr_z80 Sound21 ; checkpoint ding-dong sound
SndPtr_SpikeSwitch: rom_ptr_z80 Sound22 ; spike switch sound
SndPtr_Hurt: rom_ptr_z80 Sound23 ; hurt sound
SndPtr_Skidding: rom_ptr_z80 Sound24 ; skidding sound
SndPtr_BlockPush: rom_ptr_z80 Sound25 ; block push sound
SndPtr_HurtBySpikes: rom_ptr_z80 Sound26 ; spiky impalement sound
SndPtr_Sparkle: rom_ptr_z80 Sound27 ; sparkling sound
SndPtr_Beep: rom_ptr_z80 Sound28 ; short beep
SndPtr_Bwoop: rom_ptr_z80 Sound29 ; bwoop (unused)
SndPtr_Splash: rom_ptr_z80 Sound2A ; splash sound
SndPtr_Swish: rom_ptr_z80 Sound2B ; swish
SndPtr_BossHit: rom_ptr_z80 Sound2C ; boss hit
SndPtr_InhalingBubble: rom_ptr_z80 Sound2D ; inhaling a bubble
SndPtr_ArrowFiring:
SndPtr_LavaBall: rom_ptr_z80 Sound2E ; arrow firing
SndPtr_Shield: rom_ptr_z80 Sound2F ; shield sound
SndPtr_LaserBeam: rom_ptr_z80 Sound30 ; laser beam
SndPtr_Zap: rom_ptr_z80 Sound31 ; zap (unused)
SndPtr_Drown: rom_ptr_z80 Sound32 ; drownage
SndPtr_FireBurn: rom_ptr_z80 Sound33 ; fire + burn
SndPtr_Bumper: rom_ptr_z80 Sound34 ; bumper bing
SndPtr_Ring:
SndPtr_RingRight: rom_ptr_z80 Sound35 ; ring sound
SndPtr_SpikesMove: rom_ptr_z80 Sound36
SndPtr_Rumbling: rom_ptr_z80 Sound37 ; rumbling
rom_ptr_z80 Sound38 ; (unused)
SndPtr_Smash: rom_ptr_z80 Sound39 ; smash/breaking
rom_ptr_z80 Sound3A ; nondescript ding (unused)
SndPtr_DoorSlam: rom_ptr_z80 Sound3B ; door slamming shut
SndPtr_SpindashRelease: rom_ptr_z80 Sound3C ; spindash unleashed
SndPtr_Hammer: rom_ptr_z80 Sound3D ; slide-thunk
SndPtr_Roll: rom_ptr_z80 Sound3E ; rolling sound
SndPtr_ContinueJingle: rom_ptr_z80 Sound3F ; got continue
SndPtr_CasinoBonus: rom_ptr_z80 Sound40 ; short bonus ding
SndPtr_Explosion: rom_ptr_z80 Sound41 ; badnik bust
SndPtr_WaterWarning: rom_ptr_z80 Sound42 ; warning ding-ding
SndPtr_EnterGiantRing: rom_ptr_z80 Sound43 ; special stage ring flash (mostly unused)
SndPtr_BossExplosion: rom_ptr_z80 Sound44 ; thunk
SndPtr_TallyEnd: rom_ptr_z80 Sound45 ; cha-ching
SndPtr_RingSpill: rom_ptr_z80 Sound46 ; losing rings
rom_ptr_z80 Sound47 ; chain pull chink-chink (unused)
SndPtr_Flamethrower: rom_ptr_z80 Sound48 ; flamethrower
SndPtr_Bonus: rom_ptr_z80 Sound49 ; bonus pwoieeew (mostly unused)
SndPtr_SpecStageEntry: rom_ptr_z80 Sound4A ; special stage entry
SndPtr_SlowSmash: rom_ptr_z80 Sound4B ; slower smash/crumble
SndPtr_Spring: rom_ptr_z80 Sound4C ; spring boing
SndPtr_Blip: rom_ptr_z80 Sound4D ; selection blip
SndPtr_RingLeft: rom_ptr_z80 Sound4E ; another ring sound (only plays in the left speaker?)
SndPtr_Signpost: rom_ptr_z80 Sound4F ; signpost spin sound
SndPtr_CNZBossZap: rom_ptr_z80 Sound50 ; mosquito zapper
rom_ptr_z80 Sound51 ; (unused)
rom_ptr_z80 Sound52 ; (unused)
SndPtr_Signpost2P: rom_ptr_z80 Sound53
SndPtr_OOZLidPop: rom_ptr_z80 Sound54 ; OOZ lid pop sound
SndPtr_SlidingSpike: rom_ptr_z80 Sound55
SndPtr_CNZElevator: rom_ptr_z80 Sound56
SndPtr_PlatformKnock: rom_ptr_z80 Sound57
SndPtr_BonusBumper: rom_ptr_z80 Sound58 ; CNZ bonusy bumper sound
SndPtr_LargeBumper: rom_ptr_z80 Sound59 ; CNZ baaang bumper sound
SndPtr_Gloop: rom_ptr_z80 Sound5A ; CNZ gloop / water droplet sound
SndPtr_PreArrowFiring: rom_ptr_z80 Sound5B
SndPtr_Fire: rom_ptr_z80 Sound5C
SndPtr_ArrowStick: rom_ptr_z80 Sound5D ; chain clink
SndPtr_Helicopter:
SndPtr_WingFortress: rom_ptr_z80 Sound5E ; helicopter
SndPtr_SuperTransform: rom_ptr_z80 Sound5F
SndPtr_SpindashRev: rom_ptr_z80 Sound60 ; spindash charge
SndPtr_Rumbling2: rom_ptr_z80 Sound61 ; rumbling
SndPtr_CNZLaunch: rom_ptr_z80 Sound62
SndPtr_Flipper: rom_ptr_z80 Sound63 ; CNZ blooing bumper
SndPtr_HTZLiftClick: rom_ptr_z80 Sound64 ; HTZ track click sound
SndPtr_Leaves: rom_ptr_z80 Sound65 ; kicking up leaves sound
SndPtr_MegaMackDrop: rom_ptr_z80 Sound66 ; leaf splash?
SndPtr_DrawbridgeMove: rom_ptr_z80 Sound67
SndPtr_QuickDoorSlam: rom_ptr_z80 Sound68 ; door slamming quickly (unused)
SndPtr_DrawbridgeDown: rom_ptr_z80 Sound69
SndPtr_LaserBurst: rom_ptr_z80 Sound6A ; robotic laser burst
SndPtr_Scatter:
SndPtr_LaserFloor: rom_ptr_z80 Sound6B ; scatter
SndPtr_Teleport: rom_ptr_z80 Sound6C
SndPtr_Error: rom_ptr_z80 Sound6D ; error sound
SndPtr_MechaSonicBuzz: rom_ptr_z80 Sound6E ; silver sonic buzz saw
SndPtr_LargeLaser: rom_ptr_z80 Sound6F
SndPtr_OilSlide: rom_ptr_z80 Sound70
SndPtr__End:
; There are many non-relative pointers in these sound effects,
; so the sounds shouldn't simply be BINCLUDE'd.
; They could be included as separate .asm files using "include" instead of "binclude",
; but I wanted to minimize the number of included asm files.
; some comments on what the various script commands do (after the header):
; 0x00-0x7F sets the note duration (of the previous note and following notes)
; 0x81-0xDF plays a note (the valid range may be smaller for PSG or DAC)
; 0x80 plays silence
; 0xE0-0xFF does special things. I won't list them here... search for "Coordination flags" sonic 2.
; the FM voices (poorly named "ssamp" or "samples" below)
; are 25 bytes each and go directly to YM2612 registers.
; they can be hard to edit (there's an art to it)
; but search for sonic "Voice editing" for more info if you want to try.
; jumping sound
Sound20: dc.w $0000,$0101
dc.w $8080,z80_ptr(+),$F400
+ dc.b $F5,$00,$9E,$05,$F0,$02,$01,$F8,$65,$A3,$15,$F2
; checkpoint ding-dong sound
Sound21: dc.w z80_ptr(ssamp21),$0101
dc.w $8005,z80_ptr(+),$0001
ssamp21: dc.b $3C,$05,$0A,$01,$01,$56,$5C,$5C,$5C,$0E,$11,$11
dc.b $11,$09,$06,$0A,$0A,$4F,$3F,$3F,$3F,$17,$20,$80,$80
+ dc.b $EF,$00,$BD,$06,$BA,$16,$F2
; spike switch sound
Sound22: dc.w $0000,$0101
dc.w $80C0,z80_ptr(+),$0000
+ dc.b $F0,$01,$01,$F0,$08,$F3,$E7,$C0,$04,$CA,$04
- dc.b $C0,$01,$EC
dc.w $01F7,$0006,z80_ptr(-)
dc.b $F2
; hurt sound
Sound23: dc.w z80_ptr(ssamp23),$0101
dc.w $8005,z80_ptr(+),$F400
+ dc.b $EF,$00,$B0,$07,$E7,$AD
- dc.b $01,$E6
dc.w $01F7,$002F,z80_ptr(-)
dc.b $F2
ssamp23: dc.b $30,$30,$30,$30,$30,$9E,$DC,$D8,$DC,$0E,$04,$0A
dc.b $05,$08,$08,$08,$08,$BF,$BF,$BF,$BF,$14,$14,$3C,$80
; skidding sound
Sound24: dc.w $0000,$0102 ; sound header... no sample and 2 script entries
dc.w $80A0,z80_ptr(+),$F400 ; entry 1 header
dc.w $80C0,z80_ptr(++),$F400 ; entry 2 header
+ dc.b $F5,$00,$AF,$01,$80,$AF,$80,$03 ; script entry 1
- dc.b $AF,$01,$80
dc.w $01F7,$000B,z80_ptr(-) ; loopback
dc.b $F2 ; script 1 end
+ dc.b $F5,$00,$80,$01,$AD,$80,$AD,$80,$03 ; script entry 2
- dc.b $AD,$01,$80
dc.w $01F7,$000B,z80_ptr(-) ; loopback
dc.b $F2 ; script 2 end
; block push sound
Sound25: dc.w z80_ptr(ssamp25),$0101
dc.w $8005,z80_ptr(+),$0000
+ dc.b $EF,$00,$80,$01,$8B,$0A,$80,$02,$F2
ssamp25: dc.b $FA,$21,$10,$30,$32,$2F,$2F,$1F,$2F,$05,$09,$08
dc.b $02,$06,$06,$0F,$02,$1F,$4F,$2F,$2F,$0F,$0E,$1A,$80
; spiky impalement sound
Sound26: dc.w z80_ptr(ssamp26),$0101
dc.w $8005,z80_ptr(+),$F200
+ dc.b $EF,$00,$F0,$01,$01,$10,$FF,$CF,$05,$D7,$25,$F2
ssamp26: dc.b $3B,$3C,$30,$39,$31,$DF,$1F,$1F,$DF,$04,$04,$05
dc.b $01,$04,$04,$04,$02,$FF,$1F,$0F,$AF,$29,$0F,$20,$80
; sparkling sound
Sound27: dc.w z80_ptr(ssamp27),$0101
dc.w $8004,z80_ptr(+),$0C1C
+ dc.b $EF,$00,$C1,$05,$C4,$05,$C9,$2B,$F2
ssamp27: dc.b $07,$73,$33,$33,$73,$0F,$19,$14,$1A,$0A,$0A,$0A
dc.b $0A,$0A,$0A,$0A,$0A,$57,$57,$57,$57,$00,$00,$00,$00
; short beep
Sound28: dc.w $0000,$0101
dc.w $8080,z80_ptr(+),$E803
+ dc.b $F5,$04,$CB,$04,$F2
; bwoop (unused)
Sound29: dc.w $0000,$0101
dc.w $80A0,z80_ptr(+),$0000
+ dc.b $F0,$01,$01,$E6,$35,$8E,$06,$F2
; splash sound
Sound2A: dc.w z80_ptr(ssamp2A),$0102
dc.w $80C0,z80_ptr(+),$0000
dc.w $8005,z80_ptr(++),$0003
+ dc.b $F5,$00,$F3,$E7,$C2,$05,$C6,$05,$E7
- dc.b $07,$EC,$01
dc.w $E7F7,$000F,z80_ptr(-)
dc.b $F2
+ dc.b $EF,$00,$A6,$14,$F2
ssamp2A: dc.b $00,$00,$02,$03,$00,$D9,$1F,$DF,$1F,$12,$14,$11
dc.b $0F,$0A,$0A,$00,$0D,$FF,$FF,$FF,$FF,$22,$27,$07,$80
; swish
Sound2B: dc.w $0000,$0101
dc.w $80C0,z80_ptr(+),$0000
+ dc.b $F5,$00,$F3,$E7,$C6,$03,$80,$03,$C6,$01,$E7
- dc.b $01,$EC,$01
dc.w $E7F7,$0015,z80_ptr(-)
dc.b $F2
; boss hit
Sound2C: dc.w z80_ptr(smashsamp),$0101
dc.w $8005,z80_ptr(+),$0000
+ dc.b $EF,$00,$F0,$01,$01,$0C,$01
- dc.b $81,$0A,$E6
dc.w $10F7,$0004,z80_ptr(-)
dc.b $F2
smashsamp: dc.b $F9,$21,$10,$30,$32,$1F,$1F,$1F,$1F,$05,$09,$18
dc.b $02,$0B,$10,$1F,$05,$1F,$4F,$2F,$2F,$0E,$04,$07,$80
; inhaling a bubble
Sound2D: dc.w z80_ptr(ssamp2D),$0101
dc.w $8005,z80_ptr(+),$0E00
+ dc.b $EF,$00,$F0,$01,$01,$21,$6E,$A6,$07
dc.b $80,$06,$F0,$01,$01,$44,$1E,$AD,$08,$F2
ssamp2D: dc.b $35,$05,$08,$09,$07,$1E,$0D,$0D,$0E,$0C,$03,$15
dc.b $06,$16,$09,$0E,$10,$2F,$1F,$2F,$1F,$15,$12,$12,$80
; arrow firing
Sound2E: dc.w z80_ptr(ssamp2E),$0102
dc.w $8005,z80_ptr(+),$0000
dc.w $80C0,z80_ptr(++),$0000
+ dc.b $EF,$00,$80,$01,$F0,$01,$01,$40,$48,$83,$06,$85,$02,$F2
+ dc.b $F5,$00,$80,$0B,$F3,$E7,$C6,$01,$E7
- dc.b $02,$EC,$01
dc.w $E7F7,$0010,z80_ptr(-)
dc.b $F2
ssamp2E: dc.b $FA,$02,$00,$03,$05,$12,$0F,$11,$13,$05,$09,$18
dc.b $02,$06,$06,$0F,$02,$1F,$4F,$2F,$2F,$2F,$0E,$1A,$80
; shield sound
Sound2F: dc.w z80_ptr(ssamp2F),$0101
dc.w $8005,z80_ptr(+),$0C00
+ dc.b $EF,$00,$80,$01,$A3,$05,$E7,$A4,$26,$F2
ssamp2F: dc.b $30,$30,$30,$30,$30,$9E,$AC,$A8,$DC,$0E,$04,$0A
dc.b $05,$08,$08,$08,$08,$BF,$BF,$BF,$BF,$04,$14,$2C,$80
; laser beam
Sound30: dc.w z80_ptr(ssamp30),$0101 ; sound header... a voice and 1 script entry
dc.w $8005,z80_ptr(+),$FB05 ; script entry header
+ dc.b $EF,$00,$DF,$7F ; script start
- dc.b $DF,$02,$E6 ; script continued
dc.w $01F7,$001B,z80_ptr(-) ; loopback
dc.b $F2 ; script end
ssamp30: dc.b $83,$1F,$1F,$15,$1F,$1F,$1F,$1F,$1F,$00,$00,$00 ; voice
dc.b $00,$02,$02,$02,$02,$2F,$FF,$2F,$3F,$0B,$01,$16,$82 ; (fixed length)
; zap (unused)
Sound31: dc.w z80_ptr(ssamp31),$0101
dc.w $8005,z80_ptr(+),$FB02
+ dc.b $EF,$00,$B3,$05,$80,$01,$B3,$09,$F2
ssamp31: dc.b $83,$12,$13,$10,$1E,$1F,$1F,$1F,$1F,$00,$00,$00
dc.b $00,$02,$02,$02,$02,$2F,$FF,$2F,$3F,$05,$34,$10,$87
; drownage
Sound32: dc.w z80_ptr(ssamp32),$0102
dc.w $8004,z80_ptr(++),$0C04
dc.w $8005,z80_ptr(+),$0E02
+ dc.b $EF,$00,$F0,$01,$01,$83,$0C
- dc.b $8A,$05,$05,$E6
dc.w $03F7,$000A,z80_ptr(-)
dc.b $F2
+ dc.b $80,$06,$EF,$00,$F0,$01,$01,$6F,$0E
- dc.b $8D,$04,$05,$E6
dc.w $03F7,$000A,z80_ptr(-)
dc.b $F2
ssamp32: dc.b $35,$14,$04,$1A,$09,$0E,$11,$10,$0E,$0C,$03,$15
dc.b $06,$16,$09,$0E,$10,$2F,$4F,$2F,$4F,$2F,$12,$12,$80
; fire + burn
Sound33: dc.w z80_ptr(ssamp2E),$0102
dc.w $8005,z80_ptr(+),$0000
dc.w $80C0,z80_ptr(++),$0000
+ dc.b $EF,$00,$80,$01,$F0,$01,$01,$40,$48,$83,$06,$85,$02,$F2
+ dc.b $F5,$00,$80,$0B,$F3,$E7,$A7,$25,$E7
- dc.b $02,$EC,$01
dc.w $E7F7,$0010,z80_ptr(-)
dc.b $F2
; bumper bing
Sound34: dc.w z80_ptr(ssamp34),$0103
dc.w $8005,z80_ptr(+),$0000
dc.w $8004,z80_ptr(++),$0000
dc.w $8002,z80_ptr(+++),$0002
+ dc.b $EF,$00,$F6
dc.w z80_ptr(Sound34_3)
+ dc.b $EF,$00,$E1,$07,$80,$01
Sound34_3:
dc.b $BA,$20,$F2
+ dc.b $EF,$01,$9A,$03,$F2
ssamp34: dc.b $3C,$05,$0A,$01,$01,$56,$5C,$5C,$5C,$0E,$11,$11
dc.b $11,$09,$06,$0A,$0A,$4F,$3F,$3F,$3F,$1F,$2B,$80,$80
dc.b $05,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$12,$0C,$0C
dc.b $0C,$12,$08,$08,$08,$1F,$5F,$5F,$5F,$07,$80,$80,$80
; ring sound
Sound35: dc.w z80_ptr(ringsamp),$0101
dc.w $8005,z80_ptr(+),$0005
+ dc.b $EF,$00,$E0,$40,$C1,$05,$C4,$05,$C9,$1B,$F2
Sound36: dc.w $0000,$0101
dc.w $80C0,z80_ptr(+),$0000
+ dc.b $F0,$01,$01,$F0,$08,$F3,$E7,$C1,$07
- dc.b $D0,$01,$EC
dc.w $01F7,$000C,z80_ptr(-)
dc.b $F2
; rumbling
Sound37: dc.w z80_ptr(ssamp37),$0101
dc.w $8005,z80_ptr(+),$0000
+ dc.b $EF,$00,$F0,$01,$01,$20,$08
- dc.b $8B
dc.w $0AF7,$0008,z80_ptr(-)
- dc.b $8B,$10,$E6
dc.w $03F7,$0009,z80_ptr(-)
dc.b $F2
ssamp37: dc.b $FA,$21,$10,$30,$32,$1F,$1F,$1F,$1F,$05,$09,$18
dc.b $02,$06,$06,$0F,$02,$1F,$4F,$2F,$2F,$0F,$0E,$1A,$80
; (unused)
Sound38: dc.w $0000,$0101
dc.w $80C0,z80_ptr(+),$0000
+ dc.b $F0,$01,$01,$F0,$08,$F3,$E7,$B4,$08
- dc.b $B0,$02,$EC
dc.w $01F7,$0003,z80_ptr(-)
dc.b $F2
; smash/breaking
Sound39: dc.w z80_ptr(smashsamp),$0104
dc.w $8002,z80_ptr(+),$1000
dc.w $8004,z80_ptr(+++),$0000
dc.w $8005,z80_ptr(++),$1000
dc.w $80C0,z80_ptr(s39s4),$0000
+ dc.b $E0,$40,$80,$02,$F6
dc.w z80_ptr(++)
+ dc.b $E0,$80,$80,$01
+ dc.b $EF,$00,$F0,$03,$01,$20,$04
- dc.b $81,$18,$E6
dc.w $0AF7,$0006,z80_ptr(-)
dc.b $F2
s39s4: dc.b $F0,$01,$01,$0F,$05,$F3,$E7
- dc.b $B0,$18,$E7,$EC
dc.w $03F7,$0005,z80_ptr(-)
dc.b $F2
; nondescript ding (unused)
Sound3A: dc.w z80_ptr(ssamp3A),$0101
dc.w $8005,z80_ptr(+),$0007
+ dc.b $EF,$00,$AE,$08,$F2
ssamp3A: dc.b $1C,$2E,$0F,$02,$02,$1F,$1F,$1F,$1F,$18,$14,$0F
dc.b $0E,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$20,$1B,$80,$80
; door slamming shut
Sound3B: dc.w z80_ptr(ssamp3B),$0101
dc.w $8005,z80_ptr(+),$F400
+ dc.b $EF,$00,$9B,$04,$80,$A0,$06,$F2
ssamp3B: dc.b $3C,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$00,$0F,$16
dc.b $0F,$00,$00,$00,$00,$0F,$FF,$AF,$FF,$00,$0A,$80,$80
; spindash unleashed
Sound3C: dc.w z80_ptr(ssamp3C),$0102
dc.w $8005,z80_ptr(+),$9000
dc.w $80C0,z80_ptr(++),$0000
+ dc.b $EF,$00,$F0,$01,$01,$C5,$1A,$CD,$07,$F2
+ dc.b $F5,$07,$80,$07,$F0,$01,$02,$05,$FF,$F3,$E7,$BB,$4F,$F2
ssamp3C: dc.b $FD,$09,$00,$03,$00,$1F,$1F,$1F,$1F,$10,$0C,$0C
dc.b $0C,$0B,$10,$1F,$05,$1F,$4F,$2F,$2F,$09,$92,$84,$8E
; slide-thunk
Sound3D: dc.w z80_ptr(ssamp3D),$0102
dc.w $8005,z80_ptr(+),$100A
dc.w $8004,z80_ptr(++),$0000
+ dc.b $EF,$00,$F0,$01,$01,$60,$01,$A7,$08,$F2
+ dc.b $80,$08,$EF,$01,$84,$22,$F2
ssamp3D: dc.b $FA,$21,$19,$3A,$30,$1F,$1F,$1F,$1F,$05,$09,$18
dc.b $02,$0B,$10,$1F,$05,$1F,$4F,$2F,$2F,$0E,$04,$07,$80
dc.b $FA,$31,$10,$30,$32,$1F,$1F,$1F,$1F,$05,$05,$18
dc.b $10,$0B,$10,$1F,$10,$1F,$1F,$2F,$2F,$0D,$01,$00,$80
; rolling sound
Sound3E: dc.w z80_ptr(ssamp3E),$0101
dc.w $8004,z80_ptr(+),$0C05
+ dc.b $EF,$00,$80,$01,$F0,$03,$01,$09,$FF,$CA,$25,$F4
- dc.b $E7,$E6,$01,$D0
dc.w $02F7,$002A,z80_ptr(-)
dc.b $F2
ssamp3E: dc.b $3C,$00,$02,$44,$02,$1F,$1F,$1F,$15,$00,$00,$1F
dc.b $00,$00,$00,$00,$00,$0F,$0F,$0F,$0F,$0D,$28,$00,$00
; got continue
Sound3F: dc.w z80_ptr(ssamp3F),$0103
dc.w $8002,z80_ptr(+),$F406
dc.w $8004,z80_ptr(++),$F406
dc.w $8005,z80_ptr(+++),$F406
+ dc.b $EF,$00,$C9,$07,$CD,$D0,$CB,$CE,$D2,$CD,$D0,$D4,$CE,$D2,$D5
- dc.b $D0,$07,$D4,$D7,$E6
dc.w $05F7,$0008,z80_ptr(-)
dc.b $F2
+ dc.b $EF,$00,$E1,$01,$80,$07,$CD,$15,$CE,$D0,$D2
- dc.b $D4,$15,$E6
dc.w $05F7,$0008,z80_ptr(-)
dc.b $F2
+ dc.b $EF,$00,$E1,$01,$C9,$15,$CB,$CD,$CE
- dc.b $D0,$15,$E6
dc.w $05F7,$0008,z80_ptr(-)
dc.b $F2
ssamp3F: dc.b $14,$25,$36,$33,$11,$1F,$1F,$1F,$1F,$15,$1C,$18
dc.b $13,$0B,$0D,$08,$09,$0F,$8F,$9F,$0F,$24,$0A,$05,$80
; short bonus ding
Sound40: dc.w z80_ptr(ssamp3F),$0102
dc.w $8005,z80_ptr(++),$0008
dc.w $8004,z80_ptr(+),$0008
+ dc.b $E1,$03,$80,$02
+ dc.b $EF,$00,$C4,$16,$F2
; badnik bust
Sound41: dc.w z80_ptr(ssamp41),$0102
dc.w $8005,z80_ptr(+),$0000
dc.w $80C0,z80_ptr(++),$0002
+ dc.b $F0,$03,$01,$72,$0B,$EF,$00,$BA,$16,$F2
+ dc.b $F5,$01,$F3,$E7,$B0,$1B,$F2
ssamp41: dc.b $3C,$0F,$03,$01,$01,$1F,$1F,$1F,$1F,$19,$19,$12
dc.b $0E,$05,$00,$12,$0F,$0F,$FF,$7F,$FF,$00,$00,$80,$80
; warning ding-ding
Sound42: dc.w z80_ptr(ssamp3F),$0101
dc.w $8005,z80_ptr(+),$0C08
+ dc.b $EF,$00,$BA,$08,$BA,$25,$F2
; special stage ring flash (mostly unused)
Sound43: dc.w z80_ptr(ssamp43),$0102
dc.w $8004,z80_ptr(+),$0C00
dc.w $8005,z80_ptr(++),$0013
+ dc.b $EF,$01,$80,$01,$A2,$08,$EF,$00,$E7,$AD,$26,$F2
+ dc.b $EF,$02,$F0,$06,$01,$03,$FF,$80,$0A
- dc.b $C3
dc.w $06F7,$0005,z80_ptr(-)
dc.b $C3,$17,$F2
ssamp43: dc.b $30,$30,$34,$5C,$30,$9E,$AC,$A8,$DC,$0E,$04,$0A
dc.b $05,$08,$08,$08,$08,$BF,$BF,$BF,$BF,$24,$04,$1C,$80
dc.b $30,$30,$34,$5C,$30,$9E,$AC,$A8,$DC,$0E,$04,$0A
dc.b $05,$08,$08,$08,$08,$BF,$BF,$BF,$BF,$24,$04,$2C,$80
dc.b $04,$37,$77,$72,$49,$1F,$1F,$1F,$1F,$07,$07,$0A
dc.b $0D,$00,$00,$0B,$0B,$1F,$1F,$0F,$0F,$13,$13,$81,$88
; thunk
Sound44: dc.w z80_ptr(ssamp44),$0101
dc.w $8005,z80_ptr(+),$0000
+ dc.b $EF,$00,$8A,$22,$F2
ssamp44: dc.b $FA,$21,$10,$30,$32,$1F,$1F,$1F,$1F,$05,$05,$18
dc.b $10,$0B,$10,$1F,$10,$1F,$4F,$2F,$2F,$0D,$04,$07,$80
; cha-ching
Sound45: dc.w z80_ptr(ssamp45),$0103
dc.w $8005,z80_ptr(+),$0000
dc.w $8004,z80_ptr(++),$0000
dc.w $80C0,z80_ptr(+++),$0000
+ dc.b $EF,$00,$8A,$08,$80,$02,$8A,$08,$F2
+ dc.b $EF,$01,$80,$12,$C6,$55,$F2
+ dc.b $F5,$02,$F3,$E7,$80,$02,$C2,$05,$C4,$04,$C2,$05,$C4,$04,$F2
ssamp45: dc.b $3B,$03,$02,$02,$06,$18,$1A,$1A,$96,$17,$0A,$0E
dc.b $10,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$00,$39,$28,$80
ringsamp: dc.b $04,$37,$77,$72,$49,$1F,$1F,$1F,$1F,$07,$07,$0A
dc.b $0D,$00,$00,$0B,$0B,$1F,$1F,$0F,$0F,$23,$23,$80,$80
; losing rings (scatter)
Sound46: dc.w z80_ptr(ringsamp),$0102
dc.w $8004,z80_ptr(+),$0005
dc.w $8005,z80_ptr(++),$0008
+ dc.b $EF,$00,$C6,$02,$05,$05,$05,$05,$05,$05,$3A,$F2
+ dc.b $EF,$00,$80,$02,$C4,$02,$05,$15,$02,$05,$32,$F2
; chain pull chink-chink (unused)
Sound47: dc.w z80_ptr(ssamp47),$0101
dc.w $8005,z80_ptr(+),$0000
+ dc.b $EF,$00,$BE,$05,$80,$04,$BE,$04,$80,$04,$F2
ssamp47: dc.b $28,$2F,$37,$5F,$2B,$1F,$1F,$1F,$1F,$15,$15,$15
dc.b $13,$13,$0D,$0C,$10,$2F,$3F,$2F,$2F,$00,$1F,$10,$80
; flamethrower
Sound48: dc.w $0000,$0101
dc.w $80C0,z80_ptr(+),$0000
+ dc.b $F5,$00,$F3,$E7,$A7,$25,$F2
; bonus pwoieeew (mostly unused)
Sound49: dc.w z80_ptr(ssamp49),$0101
dc.w $8005,z80_ptr(+),$0E00
+ dc.b $EF,$00,$F0,$01,$01,$33,$18,$B9,$1A,$F2
ssamp49: dc.b $3B,$0A,$05,$31,$02,$5F,$5F,$5F,$5F,$04,$16,$14
dc.b $0C,$00,$00,$04,$00,$1F,$D8,$6F,$FF,$03,$00,$25,$80
; special stage entry
Sound4A: dc.w z80_ptr(ssamp4A),$0101
dc.w $8005,z80_ptr(+),$0002
+ dc.b $EF,$00,$F0,$01,$01,$5B,$02,$CC,$65,$F2
ssamp4A: dc.b $20,$36,$30,$35,$31,$41,$3B,$49,$4B,$09,$09,$06
dc.b $08,$01,$02,$03,$A9,$0F,$0F,$0F,$0F,$29,$23,$27,$80
; slower smash/crumble
Sound4B: dc.w z80_ptr(smashsamp),$0102
dc.w $8005,z80_ptr(+),$0000
dc.w $80C0,z80_ptr(++),$0000
+ dc.b $EF,$00,$F0,$03,$01,$20,$04
- dc.b $81,$18,$E6
dc.w $0AF7,$0006,z80_ptr(-)
dc.b $F2
+ dc.b $F0,$01,$01,$0F,$05,$F3,$E7
- dc.b $B0,$18,$E7,$EC
dc.w $03F7,$0005,z80_ptr(-)
dc.b $F2
; spring boing
Sound4C: dc.w z80_ptr(ssamp4C),$0101
dc.w $8004,z80_ptr(+),$0002
+ dc.b $EF,$00,$80,$01,$F0,$03,$01,$5D,$0F,$B0,$0C,$F4
- dc.b $E7,$E6,$02,$BD
dc.w $02F7,$0019,z80_ptr(-)
dc.b $F2
ssamp4C: dc.b $20,$36,$30,$35,$31,$DF,$9F,$DF,$9F,$07,$09,$06
dc.b $06,$07,$06,$06,$08,$2F,$1F,$1F,$FF,$16,$13,$30,$80
; selection blip
Sound4D: dc.w $0000,$0101
dc.w $80C0,z80_ptr(+),$0000
+ dc.b $BB,$02,$F2
; another ring sound (only plays in the left speaker?)
Sound4E: dc.w z80_ptr(ringsamp),$0101
dc.w $8004,z80_ptr(+),$0005
+ dc.b $EF,$00,$E0,$80,$C1,$04,$C4,$05,$C9,$1B,$F2
; signpost spin sound
Sound4F: dc.w z80_ptr(ssamp4F),$0102
dc.w $8004,z80_ptr(+),$2703
dc.w $8005,z80_ptr(++),$2700
+ dc.b $80,$04
+ dc.b $EF,$00
- dc.b $B4,$05,$E6
dc.w $02F7,$0015,z80_ptr(-)
dc.b $F2
ssamp4F: dc.b $F4,$06,$0F,$04,$0E,$1F,$1F,$1F,$1F,$00,$0B,$00
dc.b $0B,$00,$05,$00,$08,$0F,$FF,$0F,$FF,$0C,$03,$8B,$80
; mosquito zapper
Sound50: dc.w z80_ptr(ssamp50),$0101
dc.w $8005,z80_ptr(+),$F400
+ dc.b $EF,$00,$B3,$04,$80,$01
- dc.b $B4,$04,$80
dc.w $01F7,$0004,z80_ptr(-)
dc.b $F2
ssamp50: dc.b $83,$12,$13,$10,$1E,$1F,$1F,$1F,$1F,$00,$00,$00
dc.b $00,$02,$02,$02,$02,$2F,$FF,$2F,$3F,$06,$34,$10,$87
; (unused)
Sound51: dc.w z80_ptr(ssamp51),$0102
dc.w $80C0,z80_ptr(+),$0001
dc.w $8005,z80_ptr(++),$000B
+ dc.b $F5,$02,$F3,$E4,$B0,$04,$85,$02,$F2
+ dc.b $EF,$00,$E8,$04,$A5,$06,$F2
ssamp51: dc.b $3C,$02,$01,$00,$01,$1F,$1F,$1F,$1F,$00,$19,$0E
dc.b $10,$00,$00,$0C,$0F,$0F,$FF,$EF,$FF,$05,$00,$80,$80
; (unused)
Sound52: dc.w z80_ptr(ssamp52),$0101
dc.w $8005,z80_ptr(+),$0002
+ dc.b $F0,$01,$01,$2A,$07,$EF,$00
- dc.b $A5,$03
dc.w $E7F7,$0013,z80_ptr(-)
- dc.b $A5,$03,$E7,$E6
dc.w $02F7,$0013,z80_ptr(-)
dc.b $F2
ssamp52: dc.b $28,$21,$21,$21,$30,$1F,$1F,$1F,$1F,$00,$00,$00
dc.b $00,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$29,$20,$29,$80
Sound53: dc.w z80_ptr(ssamp53),$0101
dc.w $8005,z80_ptr(+),$F503
+ dc.b $EF,$00,$F0,$01,$01,$46,$09,$A7,$14,$E7,$14,$E7,$E6,$04
dc.b $14,$E7,$E6,$04,$14,$E7,$E6,$04,$0A,$E7,$E6,$04,$0A,$F2
ssamp53: dc.b $07,$0A,$0C,$0C,$0C,$1F,$1F,$1F,$1F,$00,$00,$00
dc.b $00,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$2A,$0F,$0F,$80
; OOZ lid pop sound
Sound54: dc.w z80_ptr(ssamp54),$0102
dc.w $8005,z80_ptr(+),$0000
dc.w $80C0,z80_ptr(++),$0006
+ dc.b $EF,$00,$B6,$15,$F2
+ dc.b $F3,$E7,$F5,$04,$C6,$03,$E7,$C5,$E7
dc.b $C4,$E7,$C3,$E7,$C2,$E7,$C1,$E7,$C0,$F2
ssamp54: dc.b $07,$03,$02,$03,$00,$FF,$6F,$6F,$3F,$12,$14,$11
dc.b $0E,$1A,$0A,$03,$0D,$FF,$FF,$FF,$FF,$03,$07,$07,$80
Sound55: dc.w z80_ptr(ssamp55),$0101
dc.w $8005,z80_ptr(+),$0000
+ dc.b $EF,$00,$AA,$07,$B6,$15,$F2
ssamp55: dc.b $42,$20,$0E,$0F,$0F,$1F,$1F,$1F,$1F,$1F,$1F,$1F
dc.b $1F,$0F,$0E,$0F,$0E,$0F,$0F,$0F,$0F,$2E,$80,$20,$80
Sound56: dc.w z80_ptr(ssamp56),$0101
dc.w $8005,z80_ptr(+),$100E
+ dc.b $EF,$00,$F0,$01,$01,$1E,$FF,$8F,$1C,$F4
- dc.b $E7,$9A
dc.w $05F7,$0009,z80_ptr(-)
- dc.b $E7,$9A,$04,$E6,$02,$E7,$9A,$04,$E6
dc.w $02F7,$0008,z80_ptr(-)
dc.b $F2
ssamp56: dc.b $0D,$06,$00,$00,$E5,$1F,$1F,$1F,$1F,$00,$00,$00
dc.b $00,$00,$00,$00,$00,$0F,$0F,$0F,$0F,$27,$80,$80,$80
Sound57: dc.w z80_ptr(ssamp57),$0101
dc.w $8005,z80_ptr(+),$0000
+ dc.b $EF,$00,$CA,$15,$F2
ssamp57: dc.b $04,$09,$70,$00,$30,$1C,$1F,$DF,$1F,$15,$12,$0B
dc.b $0F,$0C,$0D,$00,$0D,$07,$2F,$FA,$FA,$00,$29,$00,$00
; CNZ bonusy bumper sound
Sound58: dc.w z80_ptr(ssamp58),$0101
dc.w $8005,z80_ptr(+),$0007
+ dc.b $EF,$00,$B3,$06,$B3,$15,$F2
ssamp58: dc.b $3C,$05,$0A,$01,$01,$56,$5C,$5C,$5C,$0E,$11,$11
dc.b $11,$09,$06,$0A,$0A,$4F,$3F,$3F,$3F,$17,$20,$80,$80
; CNZ baaang bumper sound
Sound59: dc.w z80_ptr(ssamp59),$0103
dc.w $8004,z80_ptr(+),$0000
dc.w $8002,z80_ptr(++),$0002
dc.w $8005,z80_ptr(+++),$0000
+ dc.b $EF,$00,$E1,$0C,$B5,$14,$F2
+ dc.b $EF,$01,$9A,$03,$F2
+ dc.b $EF,$00,$B6,$14,$F2
ssamp59: dc.b $32,$30,$30,$40,$70,$1F,$1F,$1F,$1F,$12,$0A,$01
dc.b $0D,$00,$01,$01,$0C,$00,$23,$C3,$F6,$08,$07,$1C,$03
dc.b $05,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$12,$0C,$0C
dc.b $0C,$12,$08,$08,$08,$1F,$5F,$5F,$5F,$07,$80,$80,$80
; CNZ gloop / water droplet sound
Sound5A: dc.w z80_ptr(ssamp5A),$0101
dc.w $8005,z80_ptr(+),$0000
+ dc.b $EF,$00,$F0,$01,$01,$7F,$F1,$AA,$0A,$F2
ssamp5A: dc.b $47,$03,$02,$02,$04,$5F,$5F,$5F,$5F,$0E,$1A,$11
dc.b $0A,$09,$0A,$0A,$0A,$4F,$3F,$3F,$3F,$7F,$80,$80,$A3
Sound5B: dc.w z80_ptr(ssamp5B),$0101
dc.w $8005,z80_ptr(+),$0000
+ dc.b $EF,$00,$80,$02,$A5,$01,$E7
- dc.b $01,$E7,$E6
dc.w $02F7,$0005,z80_ptr(-)
dc.b $F2
ssamp5B: dc.b $38,$0F,$0F,$0F,$0F,$1F,$1F,$1F,$0E,$00,$00,$00
dc.b $00,$00,$00,$00,$00,$0F,$0F,$0F,$1F,$00,$00,$00,$80
Sound5C: dc.w z80_ptr(ssamp5C),$0102
dc.w $8004,z80_ptr(+),$000E
dc.w $80C0,z80_ptr(++),$0000
+ dc.b $EF,$00,$85,$40
- dc.b $E7,$04,$E6
dc.w $04F7,$000A,z80_ptr(-)
dc.b $F2
+ dc.b $F5,$00,$F3,$E7,$A7,$40
- dc.b $E7,$08,$E6
dc.w $01F7,$0005,z80_ptr(-)
dc.b $F2
ssamp5C: dc.b $FA,$12,$01,$01,$01,$1F,$1F,$1F,$1F,$00,$00,$00
dc.b $00,$00,$00,$00,$00,$0F,$0F,$0F,$0F,$81,$8E,$14,$80
; chain clink
Sound5D: dc.w z80_ptr(ssamp5D),$0101
dc.w $8005,z80_ptr(+),$0000
+ dc.b $EF,$00,$C0,$04,$F2
ssamp5D: dc.b $28,$2F,$37,$5F,$2B,$1F,$1F,$1F,$1F,$15,$15,$15
dc.b $13,$13,$0D,$0C,$10,$2F,$3F,$2F,$2F,$00,$1F,$10,$80
; helicopter
Sound5E: dc.w z80_ptr(ssamp5E),$0101
dc.w $8002,z80_ptr(+),$1405
+ dc.b $EF,$00
- dc.b $95,$02,$95
dc.w $01F7,$0013,z80_ptr(-)
- dc.b $95,$02,$95,$01,$E6
dc.w $01F7,$001B,z80_ptr(-)
dc.b $F2
ssamp5E: dc.b $35,$30,$44,$40,$51,$1F,$1F,$1F,$1F,$10,$00,$13
dc.b $15,$1F,$00,$1F,$1A,$7F,$0F,$7F,$5F,$02,$A8,$80,$80
Sound5F: dc.w z80_ptr(ssamp5F),$0103
dc.w $8005,z80_ptr(s5Fs1),$0000
dc.w $80C0,z80_ptr(s5Fs2),$0000
dc.w $80A0,z80_ptr(s5Fs3),$0000
s5Fs1 dc.b $EF,$00,$F0,$01,$01,$C5,$1A,$CD,$07,$E6,$0A,$80
dc.b $06,$EF,$01,$F0,$01,$01,$11,$FF,$A2,$28
- dc.b $E7,$03,$E6
dc.w $03F7,$0005,z80_ptr(-)
dc.b $F2
s5Fs2 dc.b $80,$07,$F0,$01,$02,$05,$FF,$F3,$E7,$BB,$1D
- dc.b $E7,$07,$EC
dc.w $01F7,$0010,z80_ptr(-)
dc.b $F2
s5Fs3 dc.b $80,$16,$F5,$03
- dc.b $BF,$04,$C1,$C3,$EC,$01,$E9
dc.w $FFF7,$0005,z80_ptr(-)
- dc.b $BF,$04,$C1,$C3,$EC,$01,$E9
dc.w $01F7,$0007,z80_ptr(-)
dc.b $F2
ssamp5F: dc.b $FD,$09,$00,$03,$00,$1F,$1F,$1F,$1F,$10,$0C,$0C
dc.b $0C,$0B,$10,$1F,$05,$1F,$4F,$2F,$2F,$09,$92,$84,$8E
dc.b $3A,$70,$30,$04,$01,$0F,$14,$19,$16,$08,$0A,$0B
dc.b $05,$03,$03,$03,$05,$1F,$6F,$8F,$5F,$1F,$22,$1F,$80
; spindash charge
Sound60: dc.w z80_ptr(ssamp60),$0101
dc.w $8005,z80_ptr(+),$FE00
+ dc.b $EF,$00,$F0,$00,$01,$20,$F6,$C4,$16,$E7,$F4,$D0,$18,$E7
- dc.b $04,$E7,$E6
dc.w $03F7,$0010,z80_ptr(-)
dc.b $F2
ssamp60: dc.b $34,$00,$03,$0C,$09,$9F,$8C,$8F,$95,$00,$00,$00
dc.b $00,$00,$00,$00,$00,$0F,$0F,$0F,$0F,$00,$1D,$00,$00
; rumbling
Sound61: dc.w z80_ptr(ssamp61),$0101
dc.w $8004,z80_ptr(+),$0004
+ dc.b $80,$01,$EF,$00,$F0,$00,$01,$70,$06,$82,$06,$85,$08,$83
dc.b $01,$82,$05,$86,$06,$89,$03,$82,$08,$88,$04,$82,$06,$E6
dc.b $02,$85,$08,$E6,$02,$83,$01,$E6,$02,$82,$05,$E6,$02,$86
dc.b $06,$E6,$02,$89,$03,$E6,$02,$82,$08,$E6,$02,$88,$04,$E6,$02,$F2
ssamp61: dc.b $32,$30,$30,$50,$30,$1F,$0E,$19,$0E,$07,$12,$15
dc.b $09,$0A,$09,$1D,$06,$E8,$03,$0A,$17,$07,$00,$00,$00
Sound62: dc.w z80_ptr(ssamp62),$0101
dc.w $8005,z80_ptr(+),$FF00
+ dc.b $EF,$00,$A6,$05,$F0,$01,$01,$E7,$40
- dc.b $C4,$02,$E7,$E6
dc.w $01F7,$0012,z80_ptr(-)
dc.b $F2
ssamp62: dc.b $34,$0C,$10,$73,$0C,$AF,$AC,$FF,$D5,$06,$00,$02
dc.b $01,$02,$0A,$04,$08,$BF,$BF,$BF,$BF,$00,$08,$80,$80
; CNZ blooing bumper
Sound63: dc.w z80_ptr(ssamp63),$0101
dc.w $8005,z80_ptr(+),$0907
+ dc.b $EF,$00,$F0,$01,$01,$04,$56,$92,$03,$9A,$25,$F2
ssamp63: dc.b $3D,$12,$10,$77,$30,$5F,$5F,$5F,$5F,$0F,$0A,$00
dc.b $01,$0A,$0A,$0D,$0D,$4F,$0F,$0F,$0F,$13,$80,$80,$80
; HTZ track click sound
Sound64: dc.w z80_ptr(ssamp64),$0101
dc.w $8005,z80_ptr(+),$1100
+ dc.b $EF,$00,$C7,$02,$F2
ssamp64: dc.b $24,$2A,$02,$05,$01,$1A,$1F,$10,$1F,$0F,$1F,$1F
dc.b $1F,$0C,$0D,$11,$11,$0C,$09,$09,$0F,$0E,$04,$80,$80
; kicking up leaves sound
Sound65: dc.w z80_ptr(ssamp65),$0101
dc.w $80C0,z80_ptr(+),$F800
+ dc.b $F5,$03,$F3,$E7,$CE,$03,$F5,$06,$CE,$04,$EC
dc.b $02,$CE,$02,$F5,$03,$EC,$FE,$CE,$08,$CE,$18,$F2
ssamp65: ; uhm... apparently they forgot to null out the pointer to here.
; luckily, sound 65 doesn't really use its sample
; leaf splash?
Sound66: dc.w z80_ptr(ssamp66),$0102
dc.w $8005,z80_ptr(++),$EE08
dc.w $80C0,z80_ptr(+),$0000
+ dc.b $F3,$E7,$F5,$09,$C6,$36,$F2
+ dc.b $EF,$00,$80,$01,$92,$02,$02,$02,$30,$F2
ssamp66: dc.b $32,$33,$17,$34,$13,$0F,$0D,$1B,$17,$00,$04,$02
dc.b $0B,$08,$00,$08,$09,$6F,$5F,$4F,$6F,$05,$00,$00,$80
Sound67: dc.w z80_ptr(ssamp67),$0101
dc.w $80C0,z80_ptr(+),$0000
+ dc.b $F5,$06,$F3,$E7,$90,$0A,$94,$0A,$98,$0A,$9C
dc.b $0A,$A0,$0A,$A4,$08,$A8,$08,$AC,$08,$B0,$08,$F2
ssamp67: ; another not-really-used sample (like Sound65)
; door slamming quickly (unused)
Sound68: dc.w z80_ptr(ssamp68),$0101
dc.w $8005,z80_ptr(+),$F400
+ dc.b $EF,$00,$9B,$04,$A5,$06,$F2
ssamp68: dc.b $3C,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$00,$0F,$16
dc.b $0F,$00,$00,$00,$00,$0F,$FF,$AF,$FF,$00,$0A,$80,$80
Sound69: dc.w z80_ptr(ssamp69),$0102
dc.w $8005,z80_ptr(+),$F400
dc.w $80C0,z80_ptr(++),$0000
+ dc.b $EF,$00,$9B,$03,$A8,$06,$9E,$08,$F2
+ dc.b $F5,$04,$F3,$E7,$C6,$03,$C6,$06,$C6,$08,$F2
ssamp69: dc.b $3C,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$00,$0F,$16
dc.b $0F,$00,$00,$00,$00,$0F,$FF,$AF,$FF,$00,$0A,$80,$80
; robotic laser burst
Sound6A: dc.w z80_ptr(ssamp6A),$0101
dc.w $8005,z80_ptr(+),$0004
+ dc.b $EF,$00,$DF,$14,$E6,$18,$06,$F2
ssamp6A: dc.b $3D,$09,$34,$34,$28,$1F,$16,$16,$16,$00,$00,$00
dc.b $04,$00,$00,$00,$00,$0F,$0F,$0F,$0F,$15,$02,$02,$00
; scatter
Sound6B: dc.w z80_ptr(ssamp6B),$0101
dc.w $8004,z80_ptr(+),$0002
+ dc.b $EF,$00,$81,$04,$80,$0C,$F2
ssamp6B: dc.b $3A,$30,$30,$40,$70,$1F,$1F,$1F,$1F,$12,$0A,$01
dc.b $07,$00,$01,$01,$03,$00,$23,$C3,$46,$08,$07,$1C,$03
Sound6C: dc.w z80_ptr(ssamp6C),$0104
dc.w $8005,z80_ptr(++),$0010
dc.w $8004,z80_ptr(+),$0010
dc.w $80C0,z80_ptr(s5Fs2),$0000
dc.w $80A0,z80_ptr(s5Fs3),$0000
+ dc.b $E1,$10
+ dc.b $EF,$01,$F0,$01,$01,$EC,$56,$C0,$24,$F4,$EF,$00,$E6,$F0
- dc.b $BB,$02,$E7,$E6,$02,$E9
dc.w $01F7,$0020,z80_ptr(-)
dc.b $F2
ssamp6C: dc.b $00,$53,$30,$03,$30,$1F,$1F,$1F,$1F,$00,$00,$00
dc.b $00,$00,$00,$00,$00,$00,$00,$00,$0F,$0F,$06,$23,$80
dc.b $3C,$72,$32,$32,$72,$14,$14,$0F,$0F,$00,$00,$00
dc.b $00,$00,$00,$00,$00,$02,$02,$08,$08,$35,$14,$00,$00
; error sound
Sound6D: dc.w z80_ptr(ssamp6D),$0101
dc.w $8005,z80_ptr(+),$0004
+ dc.b $EF,$00,$B0,$06,$80,$06,$B0,$18,$F2
ssamp6D: dc.b $38,$00,$00,$00,$00,$1F,$1F,$1F,$1F,$00,$00,$00
dc.b $00,$00,$00,$00,$00,$0F,$0F,$0F,$0F,$1F,$0C,$17,$00
; silver sonic buzz saw
Sound6E: dc.w z80_ptr(ssamp6E),$0102
dc.w $8005,z80_ptr(+),$0000
dc.w $80C0,z80_ptr(++),$0000
+ dc.b $EF,$00,$C6,$24,$E7
- dc.b $C6,$04,$E7,$E6
dc.w $04F7,$0008,z80_ptr(-)
dc.b $F2
+ dc.b $F3,$E7,$C7,$44,$F2
ssamp6E: dc.b $33,$00,$10,$00,$31,$1F,$1D,$1E,$0E,$00,$0C,$1D
dc.b $00,$00,$00,$01,$00,$0F,$0F,$0F,$0F,$08,$06,$07,$80
Sound6F: dc.w z80_ptr(ssamp6A),$0103
dc.w $8005,z80_ptr(++),$000B
dc.w $8004,z80_ptr(+),$0012
dc.w $80C0,z80_ptr(+++),$0000
+ dc.b $E1,$02,$80,$02
+ dc.b $EF,$00,$E6,$0C,$DF,$06,$E7,$E6,$F4,$06,$E7
dc.b $E6,$F4,$12,$E7,$E6,$0C,$06,$E7,$E6,$0C,$06,$F2
+ dc.b $F3,$E7,$C6,$04,$C0,$BA,$B4,$AE,$E6
dc.b $01,$AE,$E6,$01,$AE,$E6,$01,$AE,$F2
Sound70: dc.w $0000,$0101
dc.w $80C0,z80_ptr(+),$0000
+ dc.b $F3,$E7,$C6,$18
- dc.b $E7,$03,$E6
dc.w $01F7,$0008,z80_ptr(-)
dc.b $F2
finishBank
; end of 'ROM'
if padToPowerOfTwo && (*)&(*-1)
cnop -1,2<<lastbit(*-1)
dc.b 0
paddingSoFar := paddingSoFar+1
else
even
endif
if MOMPASS=2
; "About" because it will be off by the same amount that Size_of_Snd_driver_guess is incorrect (if you changed it), and because I may have missed a small amount of internal padding somewhere
message "ROM size is $\{*} bytes (\{*/1024.0} kb). About $\{paddingSoFar} bytes are padding. "
endif
; share these symbols externally (WARNING: don't rename, move or remove these labels!)
shared word_728C_user,Obj5F_MapUnc_7240,off_3A294,MapRUnc_Sonic,movewZ80CompSize
EndOfRom:
END
Comments