NoahJosephHall icon

sonic 2 asm

NoahJosephHall | PRO | 01/21/17 06:01:52 PM UTC | 0 ⭐ | 718 👁️ | Never ⏰ | []
text |

2.61 MB

|

None

|

0 👍

/

0 👎

; 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