//////////////////////////////////////
// Obj01 - Sonic					//
// Port by Saxman					//
//////////////////////////////////////

#include <stdio.h>
#include <math.h>
#include <allegro.h>

#include "structs.h"
#include "common.h"
#include "m68k.h"
#include "obj01.h"

const short SpindashSpeeds[9] = {
	0x800,
	0x880,
	0x900,
	0x980,
	0xA00,
	0xA80,
	0xB00,
	0xB80,
	0xC00
};

const short SpindashSpeedsSuper[9] = {
	0xB00,
	0xB80,
	0xC00,
	0xC80,
	0xD00,
	0xD80,
	0xE00,
	0xE80,
	0xF00
};

const short Sine_Data[320] = {
	0x0000, 0x0006, 0x000C, 0x0012, 0x0019, 0x001F, 0x0025, 0x002B, 
	0x0031, 0x0038, 0x003E, 0x0044, 0x004A, 0x0050, 0x0056, 0x005C, 
	0x0061, 0x0067, 0x006D, 0x0073, 0x0078, 0x007E, 0x0083, 0x0088, 
	0x008E, 0x0093, 0x0098, 0x009D, 0x00A2, 0x00A7, 0x00AB, 0x00B0, 
	0x00B5, 0x00B9, 0x00BD, 0x00C1, 0x00C5, 0x00C9, 0x00CD, 0x00D1, 
	0x00D4, 0x00D8, 0x00DB, 0x00DE, 0x00E1, 0x00E4, 0x00E7, 0x00EA, 
	0x00EC, 0x00EE, 0x00F1, 0x00F3, 0x00F4, 0x00F6, 0x00F8, 0x00F9, 
	0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FE, 0x00FF, 0x00FF, 0x00FF, 
	0x0100, 0x00FF, 0x00FF, 0x00FF, 0x00FE, 0x00FE, 0x00FD, 0x00FC, 
	0x00FB, 0x00F9, 0x00F8, 0x00F6, 0x00F4, 0x00F3, 0x00F1, 0x00EE, 
	0x00EC, 0x00EA, 0x00E7, 0x00E4, 0x00E1, 0x00DE, 0x00DB, 0x00D8, 
	0x00D4, 0x00D1, 0x00CD, 0x00C9, 0x00C5, 0x00C1, 0x00BD, 0x00B9, 
	0x00B5, 0x00B0, 0x00AB, 0x00A7, 0x00A2, 0x009D, 0x0098, 0x0093, 
	0x008E, 0x0088, 0x0083, 0x007E, 0x0078, 0x0073, 0x006D, 0x0067, 
	0x0061, 0x005C, 0x0056, 0x0050, 0x004A, 0x0044, 0x003E, 0x0038, 
	0x0031, 0x002B, 0x0025, 0x001F, 0x0019, 0x0012, 0x000C, 0x0006, 
	0x0000, 0xFFFA, 0xFFF4, 0xFFEE, 0xFFE7, 0xFFE1, 0xFFDB, 0xFFD5, 
	0xFFCF, 0xFFC8, 0xFFC2, 0xFFBC, 0xFFB6, 0xFFB0, 0xFFAA, 0xFFA4, 
	0xFF9F, 0xFF99, 0xFF93, 0xFF8B, 0xFF88, 0xFF82, 0xFF7D, 0xFF78, 
	0xFF72, 0xFF6D, 0xFF68, 0xFF63, 0xFF5E, 0xFF59, 0xFF55, 0xFF50, 
	0xFF4B, 0xFF47, 0xFF43, 0xFF3F, 0xFF3B, 0xFF37, 0xFF33, 0xFF2F, 
	0xFF2C, 0xFF28, 0xFF25, 0xFF22, 0xFF1F, 0xFF1C, 0xFF19, 0xFF16, 
	0xFF14, 0xFF12, 0xFF0F, 0xFF0D, 0xFF0C, 0xFF0A, 0xFF08, 0xFF07, 
	0xFF05, 0xFF04, 0xFF03, 0xFF02, 0xFF02, 0xFF01, 0xFF01, 0xFF01, 
	0xFF00, 0xFF01, 0xFF01, 0xFF01, 0xFF02, 0xFF02, 0xFF03, 0xFF04, 
	0xFF05, 0xFF07, 0xFF08, 0xFF0A, 0xFF0C, 0xFF0D, 0xFF0F, 0xFF12, 
	0xFF14, 0xFF16, 0xFF19, 0xFF1C, 0xFF1F, 0xFF22, 0xFF25, 0xFF28, 
	0xFF2C, 0xFF2F, 0xFF33, 0xFF37, 0xFF3B, 0xFF3F, 0xFF43, 0xFF47, 
	0xFF4B, 0xFF50, 0xFF55, 0xFF59, 0xFF5E, 0xFF63, 0xFF68, 0xFF6D, 
	0xFF72, 0xFF78, 0xFF7D, 0xFF82, 0xFF88, 0xFF8B, 0xFF93, 0xFF99, 
	0xFF9F, 0xFFA4, 0xFFAA, 0xFFB0, 0xFFB6, 0xFFBC, 0xFFC2, 0xFFC8, 
	0xFFCF, 0xFFD5, 0xFFDB, 0xFFE1, 0xFFE7, 0xFFEE, 0xFFF4, 0xFFFA, 
	0x0000, 0x0006, 0x000C, 0x0012, 0x0019, 0x001F, 0x0025, 0x002B, 
	0x0031, 0x0038, 0x003E, 0x0044, 0x004A, 0x0050, 0x0056, 0x005C, 
	0x0061, 0x0067, 0x006D, 0x0073, 0x0078, 0x007E, 0x0083, 0x0088, 
	0x008E, 0x0093, 0x0098, 0x009D, 0x00A2, 0x00A7, 0x00AB, 0x00B0, 
	0x00B5, 0x00B9, 0x00BD, 0x00C1, 0x00C5, 0x00C9, 0x00CD, 0x00D1, 
	0x00D4, 0x00D8, 0x00DB, 0x00DE, 0x00E1, 0x00E4, 0x00E7, 0x00EA, 
	0x00EC, 0x00EE, 0x00F1, 0x00F3, 0x00F4, 0x00F6, 0x00F8, 0x00F9, 
	0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FE, 0x00FF, 0x00FF, 0x00FF, 
};

const char Angle_Data[258] = {
	0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 
	0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 
	0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 
	0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 
	0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 
	0x09, 0x09, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 
	0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 
	0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 
	0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 
	0x0D, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 
	0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 
	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 
	0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 
	0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 
	0x13, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 
	0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 
	0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 
	0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 
	0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x18, 
	0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
	0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 
	0x19, 0x19, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 
	0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 
	0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1C, 0x1C, 0x1C, 
	0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 
	0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 
	0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 
	0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 
	0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 
	0x1F, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
	0x20, 0x00, 
};




int CalcSine(){
	#ifdef ENABLE_LOGGING
	WriteLog("CalcSine()");	TabLog(1);	RegLog();
	#endif
	//d1 = (cos((90.0/64*0.0174532925)*d0)) * 255;
	//d0 = (sin((90.0/64*0.0174532925)*d0)) * 255;
	d0 &= 0xFF;
	d1 = Sine_Data[d0+0x40];
	d0 = Sine_Data[d0];
	
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int CalcAngle(){
	#ifdef ENABLE_LOGGING
	WriteLog("CalcAngle()");	TabLog(1);	RegLog();
	#endif
	//d0 = atan2(d2, d1);
	i = d3;
	n = d4;
	d3 = d1 & 0xFFFF;
	d4 = d2 & 0xFFFF;
	d4 |= d3;
	if(d4 == 0)
		goto loc_36AA;
	d4 = d2;
	
	if((short)d3 < 0)
		d3 = -d3;
	
	if((short)d4 < 0)
		d4 = -d4;
	
	if((short)d4 < (short)d3){
		d4 <<= 8;
		if((short)d3 == 0){
			//allegro_message("DIVIDE BY ZERO! (section 1)");
			d4 = 0;
		}
		else{
			d4 = (unsigned short)d4 / (unsigned short)d3;
			//if(d4 >= 258)
				//allegro_message("OUT OF RANGE! A %X", d4);
			d0 = Angle_Data[d4];
		}
	}
	else{
		d3 <<= 8;
		if((short)d4 == 0){
			//allegro_message("DIVIDE BY ZERO! (section 2)");
			d3 = 0;
		}
		else{
			d3 = (unsigned short)d3 / (unsigned short)d4;
			//if(d3 >= 258)
				//allegro_message("OUT OF RANGE! B %X", d3);
			d0 = 0x40 - Angle_Data[d3];
		}
	}
	
	if((short)d1 < 0)
		d0 = -d0 + 0x80;
	
	if((short)d2 < 0)
		d0 = -d0 + 0x100;
	
	d3 = i;
	d4 = n;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_36AA:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_36AA");
	#endif
	d0 = 0x40;
	d3 = i;
	d4 = n;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}



/*void PalCycle_SuperSonic(){
	// this may solve the Super Sonic transformation problem
	d0 = Super_Sonic_palette;
	if(d0 == 0)
		goto return_2186;
	if(d0 < 0)
		goto loc_21E6;
	d0--;
	if(d0 != 0)
		goto loc_2188;
	Palette_frame_count--;
	if(Palette_frame_count >= 0)
		return_2186;
	Palette_frame_count = 3;
	// lea (Pal_2246).l,a0
	// move.w ($FFFFF65C).w,d0
	// addq.w #8,($FFFFF65C).w
	// cmpi.w #$30,($FFFFF65C).w
	// bcs.s +
	Super_Sonic_palette = -1;
	p->obj_control = 0;
	// +
	// lea (Normal_palette+4).w,a1
	// move.l (a0,d0.w),(a1)+
	// move.l 4(a0,d0.w),(a1)
	
return_2186:
	return;
	
loc_2188:
	Palette_frame_count--;
	if(Palette_frame_count >= 0)
		goto return_2186;
	Palette_frame_count = 3;
	// lea (Pal_2246).l,a0
	// move.w ($FFFFF65C).w,d0
	// subq.w #8,($FFFFF65C).w
	// bcc.s loc_21B0
	// move.b #0,($FFFFF65C).w
	Super_Sonic_palette = 0;
loc_21B0:
//	lea	(Normal_palette+4).w,a1
//	move.l	(a0,d0.w),(a1)+
//	move.l	4(a0,d0.w),(a1)
//	lea	(Pal_22C6).l,a0
//	cmpi.b	#$D,(Current_Zone).w
//	beq.s	+
//	cmpi.b	#$F,(Current_Zone).w
//	bne.s	return_2186
//	lea	(Pal_2346).l,a0
//+	lea	(Underwater_palette+4).w,a1
//	move.l	(a0,d0.w),(a1)+
//	move.l	4(a0,d0.w),(a1)
//	rts
//; ===========================================================================
//
loc_21E6:
//	subq.b	#1,(Palette_frame_count).w
//	bpl.s	return_2186
//	move.b	#7,(Palette_frame_count).w
//	lea	(Pal_2246).l,a0
//	move.w	($FFFFF65C).w,d0
//	addq.w	#8,($FFFFF65C).w
//	cmpi.w	#$78,($FFFFF65C).w
//	bcs.s	+
//	move.w	#$30,($FFFFF65C).w
//+	lea	(Normal_palette+4).w,a1
//	move.l	(a0,d0.w),(a1)+
//	move.l	4(a0,d0.w),(a1)
//	lea	(Pal_22C6).l,a0
//	cmpi.b	#$D,(Current_Zone).w
//	beq.s	+
//	cmpi.b	#$F,(Current_Zone).w
//	bne.w	return_2186
//	lea	(Pal_2346).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:	BINCLUDE	"art/palettes/Super Sonic transformation.bin"
//;----------------------------------------------------------------------------
//;Palette for transformation to Super Sonic while underwater in CPZ
//;----------------------------------------------------------------------------
//Pal_22C6:	BINCLUDE	"art/palettes/CPZWater SS transformation.bin"
//;----------------------------------------------------------------------------
//;Palette for transformation to Super Sonic while underwater in ARZ
//;----------------------------------------------------------------------------
//Pal_2346:	BINCLUDE	"art/palettes/ARZWater SS transformation.bin"
}*/



inline int Obj01(){
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01()");	TabLog(1);	RegLog();
	VarLog(VAR_X_POS);
	VarLog(VAR_X_POS_PRE);
	VarLog(VAR_Y_POS);
	VarLog(VAR_Y_POS_PRE);
	VarLog(VAR_X_VEL);
	VarLog(VAR_Y_VEL);
	VarLog(VAR_INERTIA);
	VarLog(VAR_STATUS);
	VarLog(VAR_ANGLE);
	VarLog(VAR_ANIM);
	#endif
	//if(Debug_placement_mode)
	//	goto DebugMode;
	
Obj01_Normal:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_Normal");
	#endif
	d0 = p->routine;
	switch(d0){
		case 0:
			goto Obj01_Init;
		case 2:
			goto Obj01_Control;
		case 4:
			Obj01_Hurt();
			#ifdef ENABLE_LOGGING
			RegLog();	TabLog(-1);
			#endif
			return 0;
		case 6:
			Obj01_Dead();
			#ifdef ENABLE_LOGGING
			RegLog();	TabLog(-1);
			#endif
			return 0;
		case 8:
			Obj01_Gone();
			#ifdef ENABLE_LOGGING
			RegLog();	TabLog(-1);
			#endif
			return 0;
		case 10:
			Obj01_Respawning();
			#ifdef ENABLE_LOGGING
			RegLog();	TabLog(-1);
			#endif
			return 0;
	}
	
Obj01_Init:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_Init");
	#endif
	p->routine += 2;
	p->y_radius = 0x13;
	p->x_radius = 9;
	// mappings = Mapunc_Sonic;
	p->priority = 2;
	p->width_pixels = 0x18;
	p->render_flags = 4;
	p->Sonic_top_speed = 0x600;
	p->Sonic_acceleration = 0xC;
	p->Sonic_deceleration = 0x80;
	if(p->Last_star_pole_hit != 0)
		goto Obj01_Init_Continued;
	p->art_tile = 0x780;
	//Adjust2PArtPointer();
	p->layer = 0x10;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_LAYER);
	#endif
	p->layer_plus = 0x11;
	p->Saved_x_pos = p->x_pos;
	p->Saved_y_pos = p->y_pos;
	p->Saved_art_tile = p->art_tile;
	p->Saved_layer = p->layer;
		
Obj01_Init_Continued:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_Init_Continued");
	#endif
	p->flips_remaining = 0;
	p->flip_speed = 4;
	Super_Sonic_flag = 0;
	p->air_left = 0x1E;
	p->x_pos -= 0x20;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS);
	#endif
	p->y_pos += 0x4;	
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	p->Sonic_Pos_Record_Index = 0;
	
	for(d2=0x3F; d2>=0; d2--)
		Sonic_RecordPos();
	
	p->x_pos += 0x20;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS);
	#endif
	p->y_pos -= 4;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	
	init_player = *p;

Obj01_Control:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_Control");
	#endif
	if(Debug_mode_flag){
		if(p->Ctrl_Press & 0x10){
			Debug_placement_mode = 1;
			Control_Locked = 0;
			#ifdef ENABLE_LOGGING
			RegLog();	TabLog(-1);
			#endif
			return 0;
		}
	}
	
	if(Control_Locked == 0){
		p->Ctrl_Held_Logical = p->Ctrl_Held;
		p->Ctrl_Press_Logical = p->Ctrl_Press;
	}
	
	if((p->obj_control & 1) == 0){
		d0 = p->status & 6;
		switch(d0){
			case 0:
				Obj01_MdNormal_Checks();
				break;
			case 2:
				Obj01_MdAir();
				break;
			case 4:
				Obj01_MdRoll();
				break;
			case 6:
				Obj01_MdJump();
		}
	}
	
	if(p->Camera_Min_Y_pos == -0x100){
		p->y_pos &= 0x7FF;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_Y_POS);
		#endif
	}
	
	Sonic_Display();
	Sonic_Super();
	Sonic_RecordPos();
	Sonic_Water();
	
	p->next_tilt = p->ram_F768;
	p->tilt = p->ram_F76A;
	if(p->ram_F7C7){
		if(p->anim == 0){
			p->anim = p->next_anim;
			#ifdef ENABLE_LOGGING
			VarLog(VAR_ANIM);
			#endif
		}
	}
	
	Sonic_Animate();
	if(p->obj_control >= 0)
		TouchResponse();
	LoadSonicDynPLC();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Sonic_Display(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_Display()");	TabLog(1);	RegLog();
	#endif
	d0 = p->invulnerable_time;
	if(d0 == 0)
		goto Obj01_Display;
	p->invulnerable_time--;
	if((d0 & 7) == 0){
		d0 >>= 3;
		goto Obj01_ChkInvin;
	}
	d0 >>= 3;
	
Obj01_Display:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_Display");
	#endif
	DisplaySprite();
	
Obj01_ChkInvin:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_ChkInvin");
	#endif
	if((p->status_secondary & 2) == 0)
		goto Obj01_ChkShoes;
	if(p->invincibility_time == 0)
		goto Obj01_ChkShoes;
	p->invincibility_time--;
	if(p->invincibility_time != 0)
		goto Obj01_ChkShoes;
	if(Current_Boss_ID != 0)
		goto Obj01_RmvInvin;
	if((unsigned char)p->air_left < 0xC)
		goto Obj01_RmvInvin;
	// move.w	(Level_Music).w, d0
	// jsr		(PlayMusic).l
	
Obj01_RmvInvin:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_RmvInvin");
	#endif
	p->status_secondary &= 0xFD;
	
Obj01_ChkShoes:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_ChkShoes");
	#endif
	if((p->status_secondary & 4) == 0)
		goto Obj01_ExitChk;
	if(p->speedshoes_time == 0)
		goto Obj01_ExitChk;
	p->speedshoes_time--;
	if(p->speedshoes_time != 0)
		goto Obj01_ExitChk;
	p->Sonic_top_speed = 0x600;
	p->Sonic_acceleration = 0xC;
	p->Sonic_deceleration = 0x80;
	if(Super_Sonic_flag == 0)
		goto Obj01_RmvSpeed;
	p->Sonic_top_speed = 0xA00;
	p->Sonic_acceleration = 0x30;
	p->Sonic_deceleration = 0x100;
	
Obj01_RmvSpeed:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_RmvSpeed");
	#endif
	p->status_secondary &= 0xFB;
	// move.w	#$7C+$80, d0
	// jmp		(PlayMusic).l
	
Obj01_ExitChk:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_ExitChk");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Sonic_RecordPos(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_RecordPos()");	TabLog(1);	RegLog();
	#endif
	d0 = p->Sonic_Pos_Record_Index;
	p->Sonic_Pos_Record_Index += 2;
	p->Sonic_Pos_Record_Index &= 0x7F;
	
	if(d0 >= 127)
		allegro_message("OUT OF RANGE! C %X", d0);
	p->Sonic_Pos_Record_Buf[d0] = p->x_pos;
	p->Sonic_Pos_Record_Buf[d0+1] = p->y_pos;
	
	p->Sonic_Stat_Record_Buf[d0] = (p->Ctrl_Held << 8) + p->Ctrl_Press;
	p->Sonic_Stat_Record_Buf[d0+1] = p->status;
	
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Sonic_Water(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_Water()");	TabLog(1);	RegLog();
	#endif
	if(Water_flag != 0)
		goto Obj01_InWater;
	
return_1A18C:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1A18C");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Obj01_InWater:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_InWater");
	#endif
	d0 = Water_Level_1;
	if(d0 >= p->y_pos)
		goto Obj01_OutWater;
	
	if(p->status & 0x40)
		goto return_1A18C;
	p->status |= 0x40;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	// movea.l	a0,a1
	// bsr.w	ResumeMusic
	// move.b	#$A,(Object_RAM+$2080).w
	// move.b	#$81,(Object_RAM+$2080+subtype).w
	// move.l	a0,(Object_RAM+$2080+$3C).w
	p->Sonic_top_speed = 0x300;
	p->Sonic_acceleration = 0x6;
	p->Sonic_deceleration = 0x40;
	if(Super_Sonic_flag != 0){
		p->Sonic_top_speed = 0x500;
		p->Sonic_acceleration = 0x18;
		p->Sonic_deceleration = 0x80;
	}
	
	if(p->x_vel < 0){	// p->x_vel /= 2; -- DONE THIS WAY FOR ACCURACY
		p->x_vel >>= 1;
		p->x_vel |= 0x8000;
	}
	else
		p->x_vel >>= 1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	
	if(p->y_vel < 0){	// p->y_vel /= 4; -- DONE THIS WAY FOR ACCURACY
		p->y_vel >>= 2;
		p->y_vel |= 0xC000;
	}
	else
		p->y_vel >>= 2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	
	if(p->y_vel == 0)
		goto return_1A18C;
	// move.w	#$100, (Sonic_Dust+p->anim).w
	// move.w	#$2A+$80, d0
	// jmp		(PlaySound).l
	
Obj01_OutWater:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_OutWater");
	#endif
	if((p->status & 0x40) == 0)
		goto return_1A18C;
	p->status &= 0xBF;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	
	// movea.l	a0, a1
	// bsr.w	ResumeMusic
	p->Sonic_top_speed = 0x600;
	p->Sonic_acceleration = 0xC;
	p->Sonic_deceleration = 0x80;
	if(Super_Sonic_flag != 0){
		p->Sonic_top_speed = 0xA00;
		p->Sonic_acceleration = 0x30;
		p->Sonic_deceleration = 0x100;
	}
	
	if(p->routine != 4){
		p->y_vel *= 2;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_Y_VEL);
		#endif
	}
	
	if(p->y_vel == 0)
		goto return_1A18C;
	// move.w	#$100, (Sonic_Dust+p->anim).w
	// movea.l	a0, a1
	// bsr.w	ResumeMusic
	if(p->y_vel < -0x1000){
		p->y_vel = -0x1000;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_Y_VEL);
		#endif
	}
	
	// move.w	#$2A+$80, d0
	// jmp		(PlaySound).l
	Obj01_MdNormal_Checks();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Obj01_MdNormal_Checks(){
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_MdNormal_Checks()");	TabLog(1);	RegLog();
	#endif
	d0 = p->Ctrl_Press_Logical & 0x70;
	if(d0 != 0)
		goto Obj01_MdNormal;
	if(p->anim == 0xA)
		goto return_1A2DE;
	if(p->anim == 0xB)
		goto return_1A2DE;
	if(p->anim != 0x5)
		goto Obj01_MdNormal;
	if((unsigned char)p->anim_frame < 0x1E)
		goto Obj01_MdNormal;
		
	d0 = p->Ctrl_Held_Logical & 0x7F;
	if(d0 == 0)
		goto return_1A2DE;
	p->anim = 0xA;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	if((unsigned char)p->anim_frame < 0xAC)
		goto return_1A2DE;
	p->anim = 0xB;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	goto return_1A2DE;
	
Obj01_MdNormal:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_MdNormal");
	#endif
	Sonic_CheckSpindash();
	if(double_return){
		double_return = 0;
		#ifdef ENABLE_LOGGING
		RegLog();	TabLog(-1);
		#endif
		return 0;
	}
	Sonic_Jump();
	if(double_return){
		double_return = 0;
		#ifdef ENABLE_LOGGING
		RegLog();	TabLog(-1);
		#endif
		return 0;
	}
	Sonic_SlopeResist();
	Sonic_Move();
	Sonic_Roll();
	Sonic_LevelBound();
	ObjectMove();
	AnglePos();
	Sonic_SlopeRepel();
	
return_1A2DE:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1A2DE");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Obj01_MdAir(){
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_MdAir()");	TabLog(1);	RegLog();
	#endif
	Sonic_JumpHeight();
	Sonic_ChgJumpDir();
	Sonic_LevelBound();
	ObjectMoveAndFall();
	if(p->status & 0x40){
		p->y_vel -= 0x28;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_Y_VEL);
		#endif
	}
	Sonic_JumpAngle();
	Sonic_DoLevelCollision();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Obj01_MdRoll(){
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_MdRoll()");	TabLog(1);	RegLog();
	#endif
	if(p->spindash_flag == 0){
		Sonic_Jump();
		if(double_return){
			double_return = 0;
			#ifdef ENABLE_LOGGING
			RegLog();	TabLog(-1);
			#endif
			return 0;
		}
	}
	Sonic_RollRepel();
	Sonic_RollSpeed();
	Sonic_LevelBound();
	ObjectMove();
	AnglePos();
	Sonic_SlopeRepel();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Obj01_MdJump(){
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_MdJump()");	TabLog(1);	RegLog();
	#endif
	Sonic_JumpHeight();
	Sonic_ChgJumpDir();
	Sonic_LevelBound();
	ObjectMoveAndFall();
	if(p->status & 0x40){
		p->y_vel -= 0x28;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_Y_VEL);
		#endif
	}
	Sonic_JumpAngle();
	Sonic_DoLevelCollision();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Sonic_Move(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_Move()");	TabLog(1);	RegLog();
	#endif
	d6 = p->Sonic_top_speed;
	d5 = p->Sonic_acceleration;
	d4 = p->Sonic_deceleration;
	if(p->status_secondary < 0)
		goto Obj01_Traction;
	if(p->move_lock != 0)
		goto Obj01_ResetScr;
	if((p->Ctrl_Held_Logical & 4) == 0)
		goto Obj01_NotLeft;
	Sonic_MoveLeft();
	
Obj01_NotLeft:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_NotLeft");
	#endif
	if((p->Ctrl_Held_Logical & 8) == 0)
		goto Obj01_NotRight;
	Sonic_MoveRight();
	
Obj01_NotRight:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_NotRight");
	#endif
	d0 = (p->angle + 0x20) & 0xC0;
	if(d0 != 0)
		goto Obj01_ResetScr;
	if(p->inertia != 0)
		goto Obj01_ResetScr;
	p->status &= 0xDF;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->anim = 5;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	if((p->status & 8) == 0)
		goto Sonic_Balance;
	d0 = p->interact << 6;
	// lea	(MainCharacter).w,a1 ; a1=character
	// lea	(a1,d0.w),a1 ; a1=object
	if(a1_status < 0)/////////////////////////////////////// (a1)
		goto Sonic_Lookup;
	d2 = (a1_width_pixels << 1) - 2;//////////////////////// (a1)
	d1 = a1_width_pixels + p->x_pos - a1_x_pos;////////// (a1)
	if(Super_Sonic_flag != 0)
		goto SuperSonic_Balance;
	if((short)d1 < 2)
		goto Sonic_BalanceOnObjLeft;
	if((short)d1 >= (short)d2)
		goto Sonic_BalanceOnObjRight;
	goto Sonic_Lookup;
	
SuperSonic_Balance:
	#ifdef ENABLE_LOGGING
	WriteLog("SuperSonic_Balance");
	#endif
	if((short)d1 < 2)
		goto SuperSonic_BalanceOnObjLeft;
	if((short)d1 >= (short)d2)
		goto SuperSonic_BalanceOnObjRight;
	goto Sonic_Lookup;
	
Sonic_BalanceOnObjRight:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_BalanceOnObjRight");
	#endif
	if((p->status & 1) == 0){
		p->anim = 6;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_ANIM);
		#endif
		d2 += 6;
		if((short)d1 < (short)d2)
			goto Obj01_ResetScr;
		p->anim = 0xC;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_ANIM);
		#endif
		goto Obj01_ResetScr;
	}
	
	p->anim = 0x1D;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	d2 += 6;
	if((short)d1 < (short)d2)
		goto Obj01_ResetScr;
	p->anim = 0x1E;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->status &= 0xFE;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	goto Obj01_ResetScr;
	
Sonic_BalanceOnObjLeft:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_BalanceOnObjLeft");
	#endif
	if(p->status & 1){
		p->anim = 6;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_ANIM);
		#endif
		if((short)d1 >= -4)
			goto Obj01_ResetScr;
		p->anim = 0xC;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_ANIM);
		#endif
		goto Obj01_ResetScr;
	}
	
	p->anim = 0x1D;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	if(d1 >= -4)
		goto Obj01_ResetScr;
	p->anim = 0x1E;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->status |= 1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	goto Obj01_ResetScr;
	
Sonic_Balance:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_Balance");
	#endif
	ChkFloorEdge();
	if((short)d1 < 0xC)
		goto Sonic_Lookup;
	if(Super_Sonic_flag != 0)
		goto SuperSonic_Balance2;
	if(p->next_tilt != 3)
		goto Sonic_BalanceLeft;
	if((p->status & 1) == 0){
		p->anim = 6;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_ANIM);
		#endif
		d3 = p->x_pos - 6;
		ChkFloorEdge_Part2();
		if((short)d1 < 0xC)
			goto Obj01_ResetScr;
		p->anim = 0xC;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_ANIM);
		#endif
		goto Obj01_ResetScr;
	}
	
	p->anim = 0x1D;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	d3 = p->x_pos - 6;
	ChkFloorEdge_Part2();
	if((short)d1 < 0xC)
		goto Obj01_ResetScr;
	p->anim = 0x1E;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->status &= 0xFE;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	goto Obj01_ResetScr;
	
Sonic_BalanceLeft:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_BalanceLeft");
	#endif
	if(p->tilt != 3)
		goto Sonic_Lookup;
	if(p->status & 1){
		p->anim = 6;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_ANIM);
		#endif
		d3 = p->x_pos + 6;
		ChkFloorEdge_Part2();
		if((short)d1 < 0xC)
			goto Obj01_ResetScr;
		p->anim = 0xC;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_ANIM);
		#endif
		goto Obj01_ResetScr;
	}
	p->anim = 0x1D;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	d3 = p->x_pos + 6;
	ChkFloorEdge_Part2();
	if((short)d1 < 0xC)
		goto Obj01_ResetScr;
	p->anim = 0x1E;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->status |= 1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	goto Obj01_ResetScr;
	
SuperSonic_Balance2:
	#ifdef ENABLE_LOGGING
	WriteLog("SuperSonic_Balance2");
	#endif
	if(p->next_tilt != 3)
		goto loc_1A56E;
	
SuperSonic_BalanceOnObjRight:
	#ifdef ENABLE_LOGGING
	WriteLog("SuperSonic_BalanceOnObjRight");
	#endif
	p->status &= 0xFE;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	goto loc_1A57C;
	
loc_1A56E:
	#ifdef ENABLE_LOGGING
	WriteLog("log_1A56E");
	#endif
	if(p->tilt != 3)
		goto Sonic_Lookup;
		
SuperSonic_BalanceOnObjLeft:
	#ifdef ENABLE_LOGGING
	WriteLog("SuperSonic_BalanceOnObjLeft");
	#endif
	p->status |= 1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	
loc_1A57C:
	#ifdef ENABLE_LOGGING
	WriteLog("log_1A57C");
	#endif
	p->anim = 6;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	goto Obj01_ResetScr;
	
Sonic_Lookup:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_Lookup");
	#endif
	if((p->Ctrl_Held_Logical & 1) == 0)
		goto Sonic_Duck;
	p->anim = 7;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->Sonic_Look_delay_counter++;
	if((unsigned short)p->Sonic_Look_delay_counter < 0x78)
		goto Obj01_ResetScr_Part2;
	p->Sonic_Look_delay_counter = 0x78;
	if(p->Camera_Y_pos_bias == 0xC8)
		goto Obj01_UpdateSpeedOnGround;
	p->Camera_Y_pos_bias += 2;
	goto Obj01_UpdateSpeedOnGround;
	
Sonic_Duck:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_Duck");
	#endif
	if((p->Ctrl_Held_Logical & 2) == 0)
		goto Obj01_ResetScr;
	p->anim = 8;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->Sonic_Look_delay_counter++;
	if((unsigned short)p->Sonic_Look_delay_counter < 0x78)
		goto Obj01_ResetScr_Part2;
	p->Sonic_Look_delay_counter = 0x78;
	if(p->Camera_Y_pos_bias == 8)
		goto Obj01_UpdateSpeedOnGround;
	p->Camera_Y_pos_bias -= 2;
	goto Obj01_UpdateSpeedOnGround;
	
Obj01_ResetScr:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_ResetScr");
	#endif
	p->Sonic_Look_delay_counter = 0;
	
Obj01_ResetScr_Part2:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_ResetScr_Part2");
	#endif
	if(p->Camera_Y_pos_bias == 0x60)
		goto Obj01_UpdateSpeedOnGround;
	if((unsigned short)p->Camera_Y_pos_bias < 0x60)
		p->Camera_Y_pos_bias += 4;
	p->Camera_Y_pos_bias -= 2;
	
Obj01_UpdateSpeedOnGround:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_UpdateSpeedOnGround");
	#endif
	if(Super_Sonic_flag != 0)
		d5 = 0xC;
	d0 = p->Ctrl_Held_Logical & 0xC;
	if(d0 != 0)
		goto Obj01_Traction;
	d0 = p->inertia;
	if(d0 == 0)
		goto Obj01_Traction;
	if((short)d0 < 0)
		goto Obj01_SettleLeft;
	
	d0 -= d5;
	if((short)d0 < 0)
		d0 = 0;
	p->inertia = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	goto Obj01_Traction;
	
Obj01_SettleLeft:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_SettleLeft");
	#endif
	d0 += d5;
	if((short)d0 > 0)
		d0 = 0;
	p->inertia = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	
Obj01_Traction:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_Traction");
	#endif
	d0 = p->angle;
	CalcSine();
	
	d1 *= p->inertia;
	if(d1 < 0){	// d1 /= 256; -- DONE THIS WAY FOR ACCURACY
		d1 >>= 8;
		d1 |= 0xFF000000;
	}
	else
		d1 >>= 8;
	p->x_vel = d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	
	d0 *= p->inertia;
	if(d0 < 0){	// d0 /= 256; -- DONE THIS WAY FOR ACCURACY
		d0 >>= 8;
		d0 |= 0xFF000000;
	}
	else
		d0 >>= 8;
	p->y_vel = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	
	Obj01_CheckWallsOnGround();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}
	
int Obj01_CheckWallsOnGround(){
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_CheckWallsOnGround()");	TabLog(1);	RegLog();
	#endif
	d0 = p->angle + 0x40;
	if((char)d0 < 0)
		goto return_1A6BE;
	d1 = 0x40;
	if(p->inertia == 0)
		goto return_1A6BE;
	if(p->inertia >= 0)
		d1 = -d1;
	
	d0 = p->angle + d1;
	n = d0;
	CalcRoomInFront();
	d0 = n;
	if((short)d1 >= 0)
		goto return_1A6BE;
	d1 *= 256;
	d0 += 0x20;
	d0 &= 0xC0;
	if(d0 == 0)
		goto loc_1A6BA;
	if(d0 == 0x40)
		goto loc_1A6A8;
	if(d0 == 0x80)
		goto loc_1A6A2;
	p->x_vel += d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	p->status |= 0x20;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->inertia = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1A6A2:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1A6A2");
	#endif
	p->y_vel -= d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1A6A8:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1A6A8");
	#endif
	p->x_vel -= d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	p->status |= 0x20;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->inertia = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1A6BA:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1A6BA");
	#endif
	p->y_vel += d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	
return_1A6BE:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1A6BE");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Sonic_MoveLeft(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_MoveLeft()");	TabLog(1);	RegLog();
	#endif
	d0 = p->inertia;
	if(d0 != 0){
		if((short)d0 >= 0)
			goto Sonic_TurnLeft;
	}
	
	p->status |= 1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	if(p->status == 0){
		p->status &= 0xDF;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_STATUS);
		#endif
		p->next_anim = 1;
	}
	
	d0 -= d5;
	d1 = d6;
	d1 = -d1;
	if(d0 <= d1){
		d0 += d5;
		if(d0 > d1)
			d0 = d1;
	}
	
	p->inertia = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	p->anim = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_TurnLeft:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_TurnLeft");
	#endif
	d0 -= d4;
	if((short)d0 <= 0)
		d0 = -0x80;
	
	p->inertia = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	d0 = (d0 & 0xFFFFFF00) + ((p->angle + 0x20) & 0xFF);
	d0 &= 0xFFFFFFC0;
	if(d0 == 0)
		goto return_1A744;
	if((short)d0 < 0x400)
		goto return_1A744;
	p->anim = 0xD;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->status &= 0xFE;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	// move.w	#$A4, d0
	// jsr		(PlaySound).l
	PlayFM(0x24, 3, 0);
	if((unsigned char)p->air_left < 0xC)
		goto return_1A744;
	// move.b	#6, (Sonic_Dust+p->routine).w
	// move.b	#$15, (Sonic_Dust+mapping_frame).w
	
return_1A744:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1A744");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Sonic_MoveRight(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_MoveRight()");	TabLog(1);	RegLog();
	#endif
	d0 = p->inertia;
	if(d0 < 0)
		goto Sonic_TurnRight;
	if((p->status & 1) != 0){
		p->status &= 0xDE;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_STATUS);
		#endif
		p->next_anim = 1;
	}
	
	d0 += d5;
	if(d0 >= d6){
		d0 -= d5;
		if(d0 < d6)
			d0 = d6;
	}
	
	p->inertia = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	p->anim = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_TurnRight:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_TurnRight");
	#endif
	d0 += d4;
	if((short)d0 >= 0)
		d0 = 0x80;
	
	p->inertia = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	d0 = (d0 & 0xFFFFFF00) + ((p->angle + 0x20) & 0xFF);
	d0 &= 0xFFFFFFC0;
	if(d0 == 0)
		goto return_1A7C4;
	if(d0 > -0x400)
		goto return_1A7C4;
	p->anim = 0xD;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->status |= 1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	// move.w	#$24+$80, d0
	// jsr		(PlaySound).l
	PlayFM(0x24, 3, 0);
	if((unsigned char)p->air_left < 0xC)
		goto return_1A7C4;
	// move.b	#6, (Sonic_Dust+p->routine).w
	// move.b	#$15, (Sonic_Dust+mapping_frame).w
	
return_1A7C4:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1A7C4");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Sonic_RollSpeed(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_RollSpeed()");	TabLog(1);	RegLog();
	#endif
	d6 = p->Sonic_top_speed * 2;
	d5 = p->Sonic_acceleration;
	if(d5 < 0){	// d5 /= 2; -- DONE THIS WAY FOR ACCURACY
		d5 >>= 1;
		d5 |= 0x80000000;
	}
	else
		d5 >>= 1;
	
	d4 = 0x20;
	
	if(p->status_secondary < 0)
		goto Obj01_Roll_ResetScr;
	if(p->move_lock != 0)
		goto Sonic_ApplyRollSpeed;
	if(p->Ctrl_Held_Logical & 4)
		Sonic_RollLeft();
	
	if((p->Ctrl_Held_Logical & 8) == 0)
		goto Sonic_ApplyRollSpeed;
	Sonic_RollRight();
	
Sonic_ApplyRollSpeed:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_ApplyRollSpeed");
	#endif
	d0 = p->inertia;
	if(d0 == 0)
		goto Sonic_CheckRollStop;
	if(d0 < 0)
		goto Sonic_ApplyRollSpeedLeft;
	
	d0 -= d5;
	if(d0 < 0)
		d0 = 0;
	
	p->inertia = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	goto Sonic_CheckRollStop;
	
Sonic_ApplyRollSpeedLeft:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_ApplyRollSpeedLeft");
	#endif
	d0 += d5;
	if(d0 > 0)
		d0 = 0;
	
	p->inertia = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	
Sonic_CheckRollStop:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_CheckRollStop");
	#endif
	if(p->inertia != 0)
		goto Obj01_Roll_ResetScr;
	if(p->spindash_flag != 0)
		goto Sonic_KeepRolling;
	p->status &= 0xFB;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->y_radius = 0x13;
	p->x_radius = 9;
	p->anim = 5;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->y_pos -= 5;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	goto Obj01_Roll_ResetScr;
	
Sonic_KeepRolling:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_KeepRolling");
	#endif
	p->inertia = 0x400;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	if((p->status & 1) == 0)
		goto Obj01_Roll_ResetScr;
	p->inertia = -p->inertia;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	
Obj01_Roll_ResetScr://///////////////////////// rest screen during spindash??
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_Roll_ResetScr");
	#endif
	if(p->Camera_Y_pos_bias == 0x60)
		goto Sonic_SetRollSpeeds;
	if((unsigned short)p->Camera_Y_pos_bias < 0x60)
		p->Camera_Y_pos_bias += 4;
	p->Camera_Y_pos_bias -= 2;
	
Sonic_SetRollSpeeds:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_SetRollSpeeds");
	#endif
	d0 = p->angle;
	CalcSine();
	
	d0 *= p->inertia;
	if(d0 < 0){	// d0 /= 256; -- DONE THIS WAY FOR ACCURACY
		d0 >>= 8;
		d0 |= 0xFF000000;
	}
	else
		d0 >>= 8;
	
	p->y_vel = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	
	d1 *= p->inertia;
	if(d1 < 0){	// d1 /= 256; -- DONE THIS WAY FOR ACCURACY
		d1 >>= 8;
		d1 |= 0xFF000000;
	}
	else
		d1 >>= 8;
	
	if(d1 > 0x1000)
		d1 = 0x1000;
	if(d1 < -0x1000)
		d1 = -0x1000;
	p->x_vel = d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	
	Obj01_CheckWallsOnGround();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Sonic_RollLeft(){
	#ifdef ENABLE_LOGGING	
	WriteLog("Sonic_RollLeft()");	TabLog(1);	RegLog();
	#endif
	d0 = p->inertia;
	if(d0 != 0){
		if(d0 > 0)
			goto Sonic_BrakeRollingRight;
	}
	
	p->status |= 1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->anim = 2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_BrakeRollingRight:
	#ifdef ENABLE_LOGGING	
	WriteLog("Sonic_BrakeRollingRight");
	#endif
	d0 -= d4;
	if(d0 < 0)
		d0 = -0x80;
		
	p->inertia = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Sonic_RollRight(){
	#ifdef ENABLE_LOGGING	
	WriteLog("Sonic_RollRight()");	TabLog(1);	RegLog();
	#endif
	d0 = p->inertia;
	if(d0 < 0)
		goto Sonic_BrakeRollingLeft;
	p->status &= 0xFE;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->anim = 2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_BrakeRollingLeft:
	#ifdef ENABLE_LOGGING	
	WriteLog("Sonic_BrakeRollingLeft");
	#endif
	d0 += d4;
	if(d0 > 0)
		d0 = 0x80;
		
	p->inertia = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Sonic_ChgJumpDir(){
	#ifdef ENABLE_LOGGING	
	WriteLog("Sonic_ChgJumpDir()");	TabLog(1);	RegLog();
	#endif
	d6 = p->Sonic_top_speed;
	d5 = p->Sonic_acceleration;
	d5 *= 2;
	if(p->status & 0x10)
		goto Obj01_Jump_ResetScr;
	d0 = p->x_vel;
	
	if(p->Ctrl_Held_Logical & 4){
		p->status |= 1;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_STATUS);
		#endif
		d0 -= d5;
		d1 = d6;
		d1 = -d1;
		if(d0 <= d1)
			d0 = d1;
	}
	
	if(p->Ctrl_Held_Logical & 8){
		p->status &= 0xFE;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_STATUS);
		#endif
		d0 += d5;
		if(d0 >= d6)
			d0 = d6;
	}
	
	p->x_vel = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	
Obj01_Jump_ResetScr:
	#ifdef ENABLE_LOGGING	
	WriteLog("Obj01_Jump_ResetScr");
	#endif
	if(p->Camera_Y_pos_bias == 0x60)
		goto Sonic_JumpPeakDecelerate;
	if((unsigned short)p->Camera_Y_pos_bias < 0x60)
		p->Camera_Y_pos_bias += 4;
	p->Camera_Y_pos_bias -= 2;
	
Sonic_JumpPeakDecelerate:
	#ifdef ENABLE_LOGGING	
	WriteLog("Sonic_JumpPeakDecelerate");
	#endif
	if(p->y_vel < -0x400 || p->y_vel >= 0)
		goto return_1A972;
	d0 = p->x_vel;
	d1 = d0;
	if(d1 < 0){	// d1 /= 32; -- DONE THIS WAY FOR ACCURACY
		d1 >>= 5;
		d1 |= 0xF8000000;
	}
	else
		d1 >>= 5;
	#ifdef ENABLE_LOGGING
	VarLog(REG_D0);
	VarLog(REG_D1);
	#endif
	
	if(d1 == 0)
		goto return_1A972;
	if(d1 < 0)
		goto Sonic_JumpPeakDecelerateLeft;
	
	d0 -= d1;
	if(d0 < 0)
		d0 = 0;
	p->x_vel = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_JumpPeakDecelerateLeft:
	#ifdef ENABLE_LOGGING	
	WriteLog("Sonic_JumpPeakDecelerateLeft");
	#endif
	d0 -= d1;
	if(d0 > 0)
		d0 = 0;
	p->x_vel = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	
return_1A972:
	#ifdef ENABLE_LOGGING	
	WriteLog("return_1A972");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Sonic_LevelBound(){
	#ifdef ENABLE_LOGGING	
	WriteLog("Sonic_LevelBound()");	TabLog(1);	RegLog();
	#endif
	d1 = (p->x_pos << 16) + p->x_pos_pre;
	d0 = p->x_vel;
	d0 *= 256;
	d1 += d0;
	d1 = (d1 >> 16) + (d1 << 16);
	d0 = p->Camera_Min_X_pos;
	d0 += 0x10;
	if((unsigned short)(d0 & 0xFFFF) > (unsigned short)(d1 & 0xFFFF))
		goto Sonic_Boundary_Sides;
	d0 = p->Camera_Max_X_pos;
	d0 += 0x128;
	if(Current_Boss_ID == 0)
		d0 += 0x40;
	if((unsigned short)(d0 & 0xFFFF) <= (unsigned short)(d1 & 0xFFFF))
		goto Sonic_Boundary_Sides;
	
Sonic_Boundary_CheckBottom:
	#ifdef ENABLE_LOGGING	
	WriteLog("Sonic_Boundary_CheckBottom");
	#endif
	d0 = p->Camera_Max_Y_pos_now;
	d0 += 0xE0;
	if(d0 < p->y_pos)
		goto Sonic_Boundary_Bottom;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_Boundary_Bottom:
	#ifdef ENABLE_LOGGING	
	WriteLog("Sonic_Boundary_Bottom");
	#endif
	KillCharacter();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_Boundary_Sides:
	#ifdef ENABLE_LOGGING	
	WriteLog("Sonic_Boundary_Sides");
	#endif
	p->x_pos = d0 & 0xFFFF;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS);
	#endif
	p->x_pos_pre = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS_PRE);
	#endif
	p->x_vel = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	p->inertia = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	goto Sonic_Boundary_CheckBottom;
	
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;/////////// exclude
}

inline int Sonic_Roll(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_Roll()");	TabLog(1);	RegLog();
	#endif
	if(p->status_secondary < 0)
		goto Obj01_NoRoll;
	d0 = p->inertia;
	if(d0 < 0)
		d0 = -d0;
	
	if((unsigned short)d0 < 0x80)
		goto Obj01_NoRoll;
	d0 = p->Ctrl_Held_Logical & 0xC;
	if(d0 != 0)
		goto Obj01_NoRoll;
	if(p->Ctrl_Held_Logical & 2)
		goto Obj01_ChkRoll;
	
Obj01_NoRoll:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_NoRoll");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Obj01_ChkRoll:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_ChkRoll");
	#endif
	if((p->status & 4) == 0)
		goto Obj01_DoRoll;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Obj01_DoRoll:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_DoRoll");
	#endif
	p->status |= 4;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->y_radius = 0xE;
	p->x_radius = 7;
	p->anim = 2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->y_pos += 5;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	// move.w	#$BE, d0
	// jsr		(PlaySound).l
	PlayFM(0x3E, 3, 0);
	if(p->inertia != 0)
		goto return_1AA36;
	p->inertia = 0x200;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	
return_1AA36:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1AA36");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Sonic_Jump(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_Jump()");	TabLog(1);	RegLog();
	#endif
	d0 = p->Ctrl_Press_Logical & 0x70;
	if(d0 == 0)
		goto return_1AAE6;
	d0 = (p->angle + 0x80) & 0xFF;
	CalcRoomOverHead();
	if(d1 < 6)
		goto return_1AAE6;
	d2 = 0x680;
	if(Super_Sonic_flag != 0)
		d2 = 0x800;
	
	if(p->status & 0x40)
		d2 = 0x380;
	
	d0 = p->angle;
	d0 -= 0x40;
	CalcSine();
	d1 *= d2;
	if(d1 < 0){	// d1 /= 256; -- DONE THIS WAY FOR ACCURACY
		d1 >>= 8;
		d1 |= 0xFF000000;
	}
	else
		d1 >>= 8;
	p->x_vel += d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	
	d0 *= d2;
	if(d0 < 0){	// d0 /= 256; -- DONE THIS WAY FOR ACCURACY
		d0 >>= 8;
		d0 |= 0xFF000000;
	}
	else
		d0 >>= 8;
	p->y_vel += d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	
	p->status |= 2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->status &= 0xDF;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	double_return = 1; // addq.l	#4, sp
	p->jumping = 1;
	p->stick_to_convex = 0;
	// move.w	#$A0, d0
	// jsr		(PlaySound).l
	PlayFM(0x20, 2, 0);
	p->y_radius = 19;
	p->x_radius = 9;
	if((p->status & 4) != 0)
		goto Sonic_RollJump;
	p->y_radius = 0xE;
	p->x_radius = 0x7;
	p->anim = 2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->status |= 4;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->y_pos += 5;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	
return_1AAE6:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1AAE6");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_RollJump:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_RollJump");
	#endif
	p->status |= 0x10;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Sonic_JumpHeight(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_JumpHeight()");	TabLog(1);	RegLog();
	#endif
	if(p->jumping == 0)
		goto Sonic_UpVelCap;
	
	d1 = -0x400;
	if(p->status & 0x40)
		d1 = -0x200;
	
	if(d1 > p->y_vel){
		d0 = p->Ctrl_Held_Logical & 0x70;
		if(d0 == 0){
			p->y_vel = d1;
			#ifdef ENABLE_LOGGING
			VarLog(VAR_Y_VEL);
			#endif
		}
	}
	
	if((p->y_vel >> 8) == 0)
		goto Sonic_CheckGoSuper;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_UpVelCap:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_UpVelCap");
	#endif
	if(p->spindash_flag != 0)
		goto return_1AB36;
	if(p->y_vel >= -0xFC0)
		goto return_1AB36;
	p->y_vel = -0xFC0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	
return_1AB36:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1AB36");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_CheckGoSuper:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_CheckGoSuper");
	#endif
	if(Super_Sonic_flag != 0)
		goto return_1ABA4;
	if(Emerald_count != 7)
		goto return_1ABA4;
	if((signed short)p->Ring_count < 50)	// changed from (unsigned short)
		goto return_1ABA4;
		
	Super_Sonic_palette = 1;
	Palette_frame_count = 0xF;
	Super_Sonic_flag = 1;
	//p->obj_control = 0x81;				// commented out only temporarily
	p->anim = 0x1F;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	// move.b	#$7E, (Object_RAM+$2040).w
	p->Sonic_top_speed = 0xA00;
	p->Sonic_acceleration = 0x30;
	p->Sonic_deceleration = 0x100;
	p->invincibility_time = 0;
	p->status_secondary |= 2;
	// move.w	#$5F+$80, d0
	// jsr		(PlaySound).l
	// move.w	#$16+$80, d0
	// jmp		(PlayMusic).l
	
return_1ABA4:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1ABA4");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Sonic_Super(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_Super()");	TabLog(1);	RegLog();
	#endif
	if(Super_Sonic_flag == 0)
		goto return_1AC3C;
	if(Update_HUD_timer == 0)
		goto Sonic_RevertToNormal;
		
	Super_Sonic_frame_count--;
	if(Super_Sonic_frame_count >= 0)
		goto return_1AC3C;
	
	if(compat_super_sonic_countdown)
		Super_Sonic_frame_count = 60;
	else
		Super_Sonic_frame_count = 59;
	
	if(p->Ring_count == 0)
		goto Sonic_RevertToNormal;
	Update_HUD_rings |= 1;
	
	if(p->Ring_count == 1 || p->Ring_count == 10 || p->Ring_count == 100)
		Update_HUD_rings |= 0x80;
	
	p->Ring_count--;
	if(p->Ring_count > 0)	//if(p->Ring_count != 0)
		goto return_1AC3C;
	
Sonic_RevertToNormal:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_RevertToNormal");
	#endif
	Super_Sonic_palette = 2;
	p->ram_F65C = 0x28;
	Super_Sonic_flag = 0;
	p->next_anim = 1;
	p->invincibility_time = 1;
	p->Sonic_top_speed = 0x600;
	p->Sonic_acceleration = 0xC;
	p->Sonic_deceleration = 0x80;
	if(p->status & 0x40){
		p->Sonic_top_speed = 0x300;
		p->Sonic_acceleration = 0x6;
		p->Sonic_deceleration = 0x40;
	}
	
return_1AC3C:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1AC3C");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Sonic_CheckSpindash(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_CheckSpindash()");	TabLog(1);	RegLog();
	#endif
	a0 = p->spindash_flag;
	if(p->spindash_flag != 0)
		goto Sonic_UpdateSpindash;
	if(p->anim != 8)
		goto return_1AC8C;
	d0 = p->Ctrl_Press_Logical & 0x70;
	if(d0 == 0)
		goto return_1AC8C;
	p->anim = 9;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	// move.w	#$E0, d0
	// jsr		(PlaySound).l
	PlayFM(0x60, 3, 0);
	double_return = 1;	// addq.l	#4, sp
	p->spindash_flag = 1;
	p->spindash_counter = 0;
	if((unsigned char)p->air_left >= 0xC)
		;// move.b	#2, (Sonic_Dust+p->anim).w
	Sonic_LevelBound();
	AnglePos();
	
return_1AC8C:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1AC8C");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_UpdateSpindash:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_UpdateSpindash");
	#endif
	d0 = p->Ctrl_Held_Logical;
	if((d0 & 2) != 0)
		goto Sonic_ChargingSpindash;
	
	p->y_radius = 0xE;
	p->x_radius = 0x7;
	p->anim = 2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->y_pos += 5;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	p->spindash_flag = 0;
	d0 = (p->spindash_counter >> 8);
	// add.w	d0, d0
	//if(d0 >= 9)
	//	allegro_message("OUT OF RANGE! D %X", d0);
	p->inertia = SpindashSpeeds[d0];
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	if(Super_Sonic_flag != 0){
		//if(d0 >= 9)
		//	allegro_message("OUT OF RANGE! E %X", d0);
		p->inertia = SpindashSpeedsSuper[d0];
		#ifdef ENABLE_LOGGING
		VarLog(VAR_INERTIA);
		#endif
	}
	
	d0 = p->inertia;
	d0 -= 0x800;
	d0 <<= 1;
	d0 &= 0x1F00;
	d0 = -d0;
	d0 += 0x2000;
	p->ram_EED0 = d0;
	if((p->status & 1) != 0){
		p->inertia = -p->inertia;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_INERTIA);
		#endif
	}
	
	p->status |= 4;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	// move.b	#0, (Sonic_Dust+p->anim).w
	// move.w	#$3C+$80, d0
	// jsr		(PlaySound).l
	PlayFM(0x3C, 3, 0);
	goto Obj01_Spindash_ResetScr;
	
Sonic_ChargingSpindash:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_ChargingSpindash");
	#endif
	if(p->spindash_counter != 0){
		d0 = p->spindash_counter;
		d0 >>= 5;
		p->spindash_counter -= d0;
		if(p->spindash_counter < 0)
			p->spindash_counter = 0;
	}
	
	d0 = p->Ctrl_Press_Logical & 0x70;
	if(d0 == 0)
		goto Obj01_Spindash_ResetScr;
	p->anim = 0x9;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->next_anim = 0;
	// move.w	#$E0, d0
	// jsr		(PlaySound).l
	PlayFM(0x60, 3, 0);
	p->spindash_counter += 0x200;
	if((unsigned short)p->spindash_counter < 0x800)
		goto Obj01_Spindash_ResetScr;
	p->spindash_counter = 0x800;
	
Obj01_Spindash_ResetScr:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_Spindash_ResetScr");
	#endif
	double_return = 1;	// addq.l	#4, sp
	if(p->Camera_Y_pos_bias == 0x60)
		goto loc_1AD8C;
	if((unsigned short)p->Camera_Y_pos_bias < 0x60)
		p->Camera_Y_pos_bias += 4;
	p->Camera_Y_pos_bias -= 2;
	
loc_1AD8C:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1AD8C");
	#endif
	Sonic_LevelBound();
	AnglePos();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Sonic_SlopeResist(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_SlopeResist()");	TabLog(1);	RegLog();
	#endif
	d0 = p->angle + 0x60;
	if((unsigned char)d0 >= 0xC0)
		goto return_1ADCA;
	
	d0 = p->angle;
	CalcSine();
	d0 *= 0x20;
	if(d0 < 0){	// d0 /= 256; -- DONE THIS WAY FOR ACCURACY
		d0 >>= 8;
		d0 |= 0xFF000000;
	}
	else
		d0 >>= 8;
	if(p->inertia == 0)
		goto return_1ADCA;
	if(p->inertia < 0)
		goto loc_1ADC6;
	
	if((short)d0 != 0){
		p->inertia += d0;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_INERTIA);
		#endif
	}
	
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1ADC6:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1ADC6");
	#endif
	p->inertia += d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	
return_1ADCA:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1ADCA");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Sonic_RollRepel(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_RollRepel()");	TabLog(1);	RegLog();
	#endif
	d0 = p->angle + 0x60;
	if((unsigned char)d0 >= 0xC0)//if(d0 >= -0x40)
		goto return_1AE06;
	d0 = p->angle;
	CalcSine();
	d0 *= 0x50;
	if(d0 < 0){	// d0 /= 256; -- DONE THIS WAY FOR ACCURACY
		d0 >>= 8;
		d0 |= 0xFF000000;
	}
	else
		d0 >>= 8;
	
	if(p->inertia < 0)
		goto loc_1ADFC;
	if(d0 >= 0)
		goto loc_1ADF6;
	if(d0 < 0){	// d0 /= 4; -- DONE THIS WAY FOR ACCURACY
		d0 >>= 2;
		d0 |= 0xC0000000;
	}
	else
		d0 >>= 2;
	
loc_1ADF6:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1ADF6");
	#endif
	p->inertia += d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1ADFC:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1ADFC");
	#endif
	if(d0 < 0)
		goto loc_1AE02;
	if(d0 < 0){	// d0 /= 4; -- DONE THIS WAY FOR ACCURACY
		d0 >>= 2;
		d0 |= 0xC0000000;
	}
	else
		d0 >>= 2;
	
loc_1AE02:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1AE02");
	#endif
	p->inertia += d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	
return_1AE06:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1AE06");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Sonic_SlopeRepel(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_SlopeRepel()");	TabLog(1);	RegLog();
	#endif
	// nop
	if(p->stick_to_convex != 0)
		goto return_1AE42;
	if(p->move_lock != 0)
		goto loc_1AE44;
	d0 = (p->angle + 0x20) & 0xC0;
	if(d0 == 0)
		goto return_1AE42;
	d0 = p->inertia;
	if(d0 >= 0)
		goto loc_1AE2C;
	d0 = -d0;
	
loc_1AE2C:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1AE2C");
	#endif
	if((unsigned short)d0 >= 0x280)
		goto return_1AE42;
	p->inertia = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	p->status |= 2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->move_lock = 0x1E;
	
return_1AE42:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1AE42");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1AE44:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1AE44");
	#endif
	p->move_lock--;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Sonic_JumpAngle(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_JumpAngle()");	TabLog(1);	RegLog();
	#endif
	d0 = p->angle;
	if(d0 == 0)
		goto Sonic_JumpFlip;
	if((char)d0 >= 0)
		goto loc_1AE5A;
	
	d0 += 2;
	if((char)d0 < 0)
		goto Sonic_JumpAngleSet;
	d0 = 0;
	goto Sonic_JumpAngleSet;
	
loc_1AE5A:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1AE5A");
	#endif
	d0 -= 2;
	if((char)d0 > 0)
		goto Sonic_JumpAngleSet;
	d0 = 0;
	
Sonic_JumpAngleSet:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_JumpAngleSet");
	#endif
	p->angle = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANGLE);
	#endif
	
Sonic_JumpFlip:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_JumpFlip");
	#endif
	d0 = p->flip_angle;
	if(d0 == 0)
		goto return_1AEA8;
	if(p->inertia < 0)
		goto Sonic_JumpLeftFlip;
	
Sonic_JumpRightFlip:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_JumpRightFlip");
	#endif
	d1 = p->flip_speed;
	d0 += d1;
	if((char)d0 > 0)
		goto Sonic_JumpFlipSet;
	p->flips_remaining--;
	if(p->flips_remaining < 0)
		goto Sonic_JumpFlipSet;
	p->flips_remaining = 0;
	d0 = 0;
	goto Sonic_JumpFlipSet;
	
Sonic_JumpLeftFlip:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_JumpLeftFlip");
	#endif
	if(p->flip_turned != 0)
		goto Sonic_JumpRightFlip;
	d1 = p->flip_speed;
	d0 -= d1;
	if((char)d0 < 0)
		goto Sonic_JumpFlipSet;
	p->flips_remaining--;
	if(p->flips_remaining < 0)
		goto Sonic_JumpFlipSet;
	p->flips_remaining = 0;
	d0 = 0;
	
Sonic_JumpFlipSet:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_JumpFlipSet");
	#endif
	p->flip_angle = d0;
	
return_1AEA8:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1AEA8");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Sonic_DoLevelCollision(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_DoLevelCollision()");	TabLog(1);	RegLog();
	#endif
	p->Collision_addr = 0;
	if(p->layer != 0x10)
		p->Collision_addr = 0x400;
	
	d5 = p->layer_plus;
	d1 = p->x_vel;
	d2 = p->y_vel;
	CalcAngle();
	d0 -= 0x20;
	d0 &= 0xC0;
	if((char)d0 == 0x40)
		goto Sonic_HitLeftWall;
	if((unsigned char)d0 == 0x80)
		goto Sonic_HitCeilingAndWalls;
	if((char)d0 == -0x40)
		goto Sonic_HitRightWall;
	CheckLeftWallDist();
	if(d1 < 0){
		p->x_pos -= d1;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_X_POS);
		#endif
		p->x_vel = 0;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_X_VEL);
		#endif
	}
	
	CheckRightWallDist();
	if(d1 < 0){
		p->x_pos += d1;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_X_POS);
		#endif
		p->x_vel = 0;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_X_VEL);
		#endif
	}
	
	Sonic_CheckFloor();
	if(d1 >= 0)
		goto return_1AF8A;
	d2 = (p->y_vel >> 8) + 8;
	d2 = -d2;
	if(d1 < d2){
		if(d0 < d2)
			goto return_1AF8A;
	}
	p->y_pos += d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	p->angle = d3;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANGLE);
	#endif
	Sonic_ResetOnFloor(0);
	d0 = (d3 + 0x20) & 0x40;
	if((char)d0 != 0)
		goto loc_1AF68;
	d0 = (d3 + 0x10) & 0x20;
	if((char)d0 == 0)
		goto loc_1AF5A;
	if(p->y_vel < 0){	// p->y_vel /= 2; -- DONE THIS WAY FOR ACCURACY
		p->y_vel >>= 1;
		p->y_vel |= 0x80000000;
	}
	else
		p->y_vel >>= 1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	goto loc_1AF7C;
	
loc_1AF5A:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1AF5A");
	#endif
	p->y_vel = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	p->inertia = p->x_vel;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1AF68:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1AF68");
	#endif
	p->x_vel = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	if(p->y_vel <= 0xFC0)
		goto loc_1AF7C;
	p->y_vel = 0xFC0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	
loc_1AF7C:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1AF7C");
	#endif
	p->inertia = p->y_vel;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	if((char)d3 >= 0)
		goto return_1AF8A;
	p->inertia = -p->inertia;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	
return_1AF8A:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1AF8A");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_HitLeftWall:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_HitLeftWall");
	#endif
	CheckLeftWallDist();
	if(d1 >= 0)
		goto Sonic_HitCeiling;
	p->x_pos -= d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS);
	#endif
	p->x_vel = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	p->inertia = p->y_vel;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_HitCeiling:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_HitCeiling");
	#endif
	CheckCeilingDist();
	if(d1 >= 0)
		goto Sonic_HitFloor;
	p->y_pos -= d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	if(p->y_vel >= 0)
		goto return_1AFBE;
	p->y_vel = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	
return_1AFBE:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1AFBE");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_HitFloor:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_HitFloor");
	#endif
	if(p->y_vel < 0)
		goto return_1AFE6;
	Sonic_CheckFloor();
	if(d1 >= 0)
		goto return_1AFE6;
	p->y_pos += d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	p->angle = d3;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANGLE);
	#endif
	Sonic_ResetOnFloor(0);
	p->y_vel = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	p->inertia = p->x_vel;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	
return_1AFE6:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1AFE6");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_HitCeilingAndWalls:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_HitCeilingAndWalls");
	#endif
	CheckLeftWallDist();
	if(d1 < 0){
		p->x_pos -= d1;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_X_POS);
		#endif
		p->x_vel = 0;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_X_VEL);
		#endif
	}
	
	CheckRightWallDist();
	if(d1 < 0){
		p->x_pos += d1;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_X_POS);
		#endif
		p->x_vel = 0;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_X_VEL);
		#endif
	}
	
	CheckCeilingDist();
	if(d1 >= 0)
		goto return_1B042;
	p->y_pos -= d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	d0 = (d3 + 0x20) & 0x40;
	if(d0 != 0)
		goto loc_1B02C;
	p->y_vel = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1B02C:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1B02C");
	#endif
	p->angle = d3;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANGLE);
	#endif
	Sonic_ResetOnFloor(0);
	p->inertia = p->y_vel;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	if(d3 >= 0)
		goto return_1B042;
	p->inertia = -p->inertia;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	
return_1B042:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1B042");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_HitRightWall:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_HitRightWall");
	#endif
	CheckRightWallDist();
	if(d1 >= 0)
		goto Sonic_HitCeiling2;
	p->x_pos += d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS);
	#endif
	p->x_vel = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	p->inertia = p->y_vel;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_HitCeiling2:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_HitCeiling2");
	#endif
	CheckCeilingDist();
	if(d1 >= 0)
		goto Sonic_HitFloor2;
	p->y_pos -= d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	if(p->y_vel >= 0)
		goto return_1B076;
	p->y_vel = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	
return_1B076:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1B076");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_HitFloor2:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_HitFloor2");
	#endif
	if(p->y_vel < 0)
		goto return_1B09E;
	Sonic_CheckFloor();
	if((short)d1 >= 0)
		goto return_1B09E;
	p->y_pos += d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	p->angle = d3;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANGLE);
	#endif
	Sonic_ResetOnFloor(0);
	p->y_vel = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	p->inertia = p->x_vel;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	
return_1B09E:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1B09E");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Sonic_ResetOnFloor(char label){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_ResetOnFloor()");	TabLog(1);	RegLog();
	#endif
	switch(label){
		case 1:
			goto Sonic_ResetOnFloor_Part2;
		case 2:
			goto Sonic_ResetOnFloor_Part3;
	}
	
	if(p->spindash_flag != 0)
		goto Sonic_ResetOnFloor_Part3;
	p->anim = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	
Sonic_ResetOnFloor_Part2:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_ResetOnFloor_Part2");
	#endif
	// _cmpi.b	#1, 0(a0)
	// bne.w	Tails_ResetOnFloor_Part2
	
	if((p->status & 4) == 0)
		goto Sonic_ResetOnFloor_Part3;
	p->status &= 0xFB;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->y_radius = 0x13;
	p->x_radius = 0x9;
	p->anim = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->y_pos -= 5;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	
Sonic_ResetOnFloor_Part3:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_ResetOnFloor_Part3");
	#endif
	p->status &= 0xCD;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->jumping = 0;
	Chain_Bonus_counter = 0;
	p->flip_angle = 0;
	p->flip_turned = 0;
	p->flips_remaining = 0;
	p->Sonic_Look_delay_counter = 0;
	if(p->anim != 0x14)
		goto return_1B11E;
	p->anim = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	
return_1B11E:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1B11E");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Obj01_Hurt(){///////////////////////////////////////////
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_Hurt()");	TabLog(1);	RegLog();
	#endif
	if(Debug_mode_flag == 0)
		goto Obj01_Hurt_Normal;
	if((p->Ctrl_Press & 0x10) == 0)
		goto Obj01_Hurt_Normal;
	Debug_placement_mode = 1;
	Control_Locked = 0;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Obj01_Hurt_Normal:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_Hurt_Normal");
	#endif
	if(p->routine_secondary < 0){
		Sonic_HurtInstantRecover();
		#ifdef ENABLE_LOGGING
		RegLog();	TabLog(-1);
		#endif
		return 0;
	}
	ObjectMove();
	p->y_vel += 0x30;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	if(p->status & 0x40){
		p->y_vel -= 0x20;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_Y_VEL);
		#endif
	}
	
	if(p->Camera_Min_Y_pos == -0x100){
		p->y_pos &= 0x7FF;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_Y_POS);
		#endif
	}
	
	Sonic_HurtStop();
	Sonic_LevelBound();
	Sonic_RecordPos();
	Sonic_Animate();
	LoadSonicDynPLC();
	DisplaySprite();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Sonic_HurtStop(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_HurtStop()");	TabLog(1);	RegLog();
	#endif
	d0 = p->Camera_Max_Y_pos_now + 0xE0;
	if(d0 < p->y_pos){
		KillCharacter();
		#ifdef ENABLE_LOGGING
		RegLog();	TabLog(-1);
		#endif
		return 0;
	}
	Sonic_DoLevelCollision();
	if(p->status & 2)
		goto return_1B1C8;
	d0 = 0;
	p->y_vel = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	p->x_vel = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	p->inertia = d0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	p->obj_control = d0;
	p->anim = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->routine -= 2;
	p->invulnerable_time = 0x78;
	p->spindash_flag = 0;
	
return_1B1C8:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1B1C8");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Sonic_HurtInstantRecover(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_HurtInstantRecover()");	TabLog(1);	RegLog();
	#endif
	p->routine -= 2;
	p->routine_secondary = 0;
	Sonic_RecordPos();
	Sonic_Animate();
	LoadSonicDynPLC();
	DisplaySprite();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Obj01_Dead(){
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_Dead()");	TabLog(1);	RegLog();
	#endif
	if(Debug_mode_flag != 0){
		if(p->Ctrl_Press & 0x10){
			Debug_placement_mode = 1;
			Control_Locked = 0;
			#ifdef ENABLE_LOGGING
			RegLog();	TabLog(-1);
			#endif
			return 0;
		}
	}
	
	CheckGameOver();
	ObjectMoveAndFall();
	Sonic_RecordPos();
	Sonic_Animate();
	LoadSonicDynPLC();
	DisplaySprite();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int CheckGameOver(){
	#ifdef ENABLE_LOGGING
	WriteLog("CheckGameOver()");	TabLog(1);	RegLog();
	#endif
	p->ram_EEBE = 1;
	p->spindash_flag = 0;
	d0 = p->Camera_Max_Y_pos_now + 0x100;
	if(d0 >= p->y_pos)
		goto return_1B31A;
	p->routine = 8;
	p->spindash_counter = 0x3C;
	Update_HUD_lives += 1;
	p->Life_count -= 1;
	if(p->Life_count != 0)
		goto Obj01_ResetLevel;
	p->spindash_counter = 0;
	// move.b	#$39, (Object_RAM+$80).w
	// move.b	#$39, (Object_RAM+$C0).w
	// move.b	#1, (Object_RAM+$C0+mapping_frame).w
	// move.w	a0, (Object_RAM+$80+parent).w
	Time_Over_flag = 0;
	
Obj01_Finished:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_Finished");
	#endif
	Update_HUD_timer = 0;
	Update_HUD_timer_2P = 0;
	p->routine = 8;
	// move.w	#$9B, d0
	// jsr		(PlayMusic).l
	// moveq	#3, d0
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0; // jmp		(LoadPLC).l
	
Obj01_ResetLevel:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_ResetLevel");
	#endif
	if(Time_Over_flag == 0)
		goto Obj01_ResetLevel_Part2;
	p->spindash_counter = 0;
	// move.b	#$39, (Object_RAM+$80).w
	// move.b	#$39, (Object_RAM+$C0).w
	// move.b	#2, (Object_RAM+$80+mapping_frame).w
	// move.b	#3, (Object_RAM+$C0+mapping_frame).w
	// move.w	a0, (Object_RAM+$80+parent).w
	goto Obj01_Finished;
	
Obj01_ResetLevel_Part2:
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_ResetLevel_Part2");
	#endif
	if(Two_player_mode == 0)
		goto return_1B31A;
	p->ram_EEBE = 0;
	p->routine = 0xA;
	p->x_pos = p->Saved_x_pos;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS);
	#endif
	p->y_pos = p->Saved_y_pos;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	p->art_tile = p->Saved_art_tile;
	p->layer = p->Saved_layer;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_LAYER);
	#endif
	p->Ring_count = 0;
	p->Extra_life_flags = 0;
	p->obj_control = 0;
	p->anim = 5;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->x_vel = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	p->y_vel = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	p->inertia = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	p->status = 2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->move_lock = 0;
	p->spindash_counter = 0;
	
return_1B31A:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1B31A");
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Obj01_Gone(){
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_Gone()");	TabLog(1);	RegLog();
	#endif
	if(p->spindash_counter != 0){
		p->spindash_counter -= 1;
		if(p->spindash_counter == 0)
			Level_Inactive_flag = 1;
	}
	
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int Obj01_Respawning(){
	#ifdef ENABLE_LOGGING
	WriteLog("Obj01_Respawning()");	TabLog(1);	RegLog();
	#endif
	if(p->ram_EEB0 == 0){
		if(p->ram_EEB2 == 0)
			p->routine = 2;
	}
	
	Sonic_Animate();
	LoadSonicDynPLC();
	//DisplaySprite();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Sonic_Animate(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_Animate()");	TabLog(1);	RegLog();
	#endif
Read_Animation:
	if(p->next_anim != p->anim){
		p->next_anim = p->anim;
		p->anim_frame = 0;
		p->anim_frame_duration = 0;
		p->status &= 0xDF;
		#ifdef ENABLE_LOGGING
		VarLog(VAR_STATUS);
		#endif
	}
	
	d0 = GetAnimationSpeed(0, &p->anim);
	//DrawCounter16(LayerSH[frame-1], p->anim_frame_duration, 80, 80);
	//DrawCounter16(LayerSH[frame-1], d0, 80, 88);
	switch(d0){
		case 0xFF:
			goto SAnim_WalkRun;
		case 0xFE:
			goto SAnim_Roll;
		//case 0xFD:
		//	goto SAnim_Push;
	}
	
	p->render_flags = (p->render_flags & 0xFC) | (p->status & 1);
	ReadAnimation(0x00, &p->anim, &p->anim_frame, &p->anim_frame_duration, &d0);
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
	
	
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;//////////////////////////////////////////////
	
SAnim_WalkRun:
	d0 = p->inertia;
	if(d0 < 0)
		d0 = -d0;
	p->anim = 1;		// running
	if(d0 < 0x600)
		p->anim = 0;	// walking
	d0 = 7 - (d0 >> 8);
	ReadAnimation(0x00, &p->anim, &p->anim_frame, &p->anim_frame_duration, &d0);
	/*if(p->flip_angle)
		goto SAnim_Tumble;
	
	d1 = 0;
	d0 = p->angle;
	if(d0 > 0)
		d0--;
	
	d2 = p->status & 1;
	if(d2)
		d0 = ~d0;
	
	d0 += 0x10;
	if(d0 < 0)
		d1 = 3;
	
	p->render_flags &= 0xFC;
	d2 ^= d1;
	p->render_flags |= d2;
	if(p->status & 0xDF)
		goto SAnim_Push;
	d0 >>= 4;
	d0 &= 6;
	d2 = p->inertia;
	if(d2 < 0)
		d2 = -d2;
	
	if(p->status_secondary < 0)
		d2 += d2;
	
	p->anim = 1;	// running
	if(d2 < 0x600){
		p->anim = 0;	// walking
		d0 += d0;
	}
	
	d0 += d0;
	d3 = d0;
	d1 = p->anim_frame;///////////////////////////////////////
	//a7 = GetAnimationSpeed(0, &p->anim);
	a7 = d4;
	ReadAnimation(0x00, &p->anim, &p->anim_frame, &p->anim_frame_duration, &a7);
	
	if(p->anim_frame_duration == a7){
		d2 = -d2;
		d2 += 0x800;
		if(d2 >= 0)
			d2 = 0;
		
		d2 >>= 8;
		p->anim_frame_duration = d2;
		p->anim_frame++;
	}*/
	
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	// LINE NUMBER 34901
	
	
	
	
	
	
	
	
	
	
	
	
	
	/*d0++;
	if(d0 != 0)
		goto SAnim_Roll;
	d0 = p->flip_angle;
	if(d0 != 0)
		goto SAnim_Tumble;
	d0 = p->angle;
	if(d0 > 0)
		d0--;
	
	d2 = p->status & 1;
	if(d2 == 0)
		d0 = ~d0;
	
	d0 += 0x10;
	if(d0 < 0)
		d1 = 3;
	
	p->render_flags &= 0xFC;
	d2 ^= d1;
	p->render_flags |= d2;
	if(p->status & 0x20)
		goto SAnim_Push;
	d0 >>= 4;
	d0 &= 6;
	d2 = p->inertia;
	if(d2 < 0)
		d2 = -d2;
	
	if(p->status_secondary < 0)
		d2 += d2;
	
	if(Super_Sonic_flag)
		goto SAnim_Super;
	a1 = 1;
	if(d2 >= 0x600){
		a1 = 0;
		d0 += d0;
	}
	
	d0 += d0;
	d3 = d0;
	d1 = p->anim_frame;
	d0 = DrawAnimation(z, LayerL[frame-1], 0, &p->anim, NORMAL, 0, &p->anim_frame, &p->anim_frame_duration, 160, 112);
	if(d0 == -1){
		p->anim_frame = 0;
		d0 = DrawAnimation(z, LayerL[frame-1], 0, &p->anim, NORMAL, 0, &p->anim_frame, &p->anim_frame_duration, 160, 112);
	}
	
	//p->mapping_frame = d0 + d3;
	p->anim_frame_duration--;
	if(p->anim_frame_duration >= 0)
		return 0;
	d2 = -d2;
	d2 += 0x800;
	if(d2 < 0)
		d2 = 0;
	
	d2 >>= 8;
	p->anim_frame_duration = d2;
	p->anim_frame++;
	
	return 0;
	
SAnim_Super:
	return 0;
	
SAnim_SuperRun:
	return 0;
	
SAnim_SuperWalk:
	return 0;
	
SAnim_Tumble:
	return 0;
	
SAnim_Tumble_Left:
	return 0;
	*/
SAnim_Roll:
	d0 = p->inertia;
	if(d0 < 0)
		d0 = -d0;
	d0 = 7 - (d0 >> 8);
	ReadAnimation(0x00, &p->anim, &p->anim_frame, &p->anim_frame_duration, &d0);
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
SAnim_Push:
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int AnglePos(){
	#ifdef ENABLE_LOGGING
	WriteLog("AnglePos()");	TabLog(1);	RegLog();
	#endif
	p->Collision_addr = 0;
	if(p->layer != 0x10)
		p->Collision_addr = 0x400;
	
	d5 = p->layer;
	if(p->status & 8){
		d0 = 0;
		p->ram_F768 = d0;
		p->ram_F76A = d0;
		#ifdef ENABLE_LOGGING
		RegLog();	TabLog(-1);
		#endif
		return 0;
	}
	
	d0 = 3;
	p->ram_F768 = d0;
	p->ram_F76A = d0;
	
	d0 = p->angle + 0x20;
	if((char)d0 >= 0)
		goto loc_1E286;
	d0 = p->angle;
	if((char)d0 < 0)
		d0--;
	
	d0 +=  0x20;
	goto loc_1E292;
	
loc_1E286:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E286");
	#endif
	d0 = p->angle;
	if((char)d0 < 0)
		d0++;
	
loc_1E28E:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E28E");
	#endif
	d0 += 0x1F;
	
loc_1E292:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E292");
	#endif
	d0 &= 0xC0;
	if(d0 == 0x40)
		goto loc_1E4E8;
	if(d0 == 0x80)
		goto loc_1E43A;
	if(d0 == 0xC0)
		goto Sonic_WalkVertR;
	
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->y_radius;
	d2 += d0;
	d0 = p->x_radius;
	d3 += d0;
	a4 = p->ram_F768;
	a3 = 0x10;
	d6 = 0;
	FindFloor();
	p->ram_F768 = a4;
	
	n = d1;
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->y_radius;
	d2 += d0;
	d0 = p->x_radius;
	d0 = -d0;
	d3 += d0;
	a4 = p->ram_F76A;
	a3 = 0x10;
	d6 = 0;
	FindFloor();
	p->ram_F76A = a4;
	
	d0 = n;
	Sonic_Angle();
	if((short)d1 == 0)
		goto return_1E31C;
	if((short)d1 >= 0)
		goto loc_1E31E;		// FIX ME: Should do this on init frame, but doesn't.
	if((short)d1 < -0xE)
		goto return_1E31C;
	p->y_pos += (short)d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	
return_1E31C:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1E31C");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E31E:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E31E");
	#endif
	d0 = (p->x_vel >> 8);
	if((char)d0 < 0)
		d0 = -d0;
	
	d0 += 4;
	
	if((unsigned char)d0 >= 0xE)
		d0 = 0xE;
	
	if((char)d1 > (char)d0)
		goto loc_1E33C;
	
loc_1E336:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E336");
	#endif
	p->y_pos += (short)d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E33C:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E33C");
	#endif
	if(p->stick_to_convex != 0)
		goto loc_1E336;
	p->status |= 2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->status &= 0xDF;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->next_anim = 1;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
Sonic_WalkVertR:
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_WalkVertR");
	#endif
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->x_radius;
	d0 = -d0;
	d2 += d0;
	d0 = p->y_radius;
	d3 += d0;
	a4 = p->ram_F768;
	a3 = 0x10;
	d6 = 0;
	FindWall();
	p->ram_F768 = a4;
	
	n = d1;
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->x_radius;
	d2 += d0;
	d0 = p->y_radius;
	d3 += d0;
	a4 = p->ram_F76A;
	a3 = 0x10;
	d6 = 0;
	FindWall();
	p->ram_F76A = a4;
	d0 = n;
	Sonic_Angle();
	if(d1 == 0)
		goto return_1E400;
	if(d1 >= 0)
		goto loc_1E402;
	if(d1 < -0xE)
		goto return_1E400;
	p->x_pos += d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS);
	#endif
	
return_1E400:
	#ifdef ENABLE_LOGGING
	WriteLog("return_1E400");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E402:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E402");
	#endif
	d0 = (p->y_vel >> 8);
	if((char)d0 < 0)
		d0 = -d0;
	
	d0 += 4;
	if((unsigned char)d0 >= 0xE)
		d0 = 0xE;
	
	if((char)d1 > (char)d0)
		goto loc_1E420;
	
loc_1E41A:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E41A");
	#endif
	p->x_pos += d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E420:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E420");
	#endif
	if(p->stick_to_convex != 0)
		goto loc_1E41A;
	p->status |= 2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->status &= 0xDF;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->next_anim = 1;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E43A:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E43A");
	#endif
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->y_radius;
	d2 -= d0;
	d2 ^= 0xF;
	d0 = p->x_radius;
	d3 += d0;
	a4 = p->ram_F768;
	a3 = -0x10;
	d6 = 0x8000;
	FindFloor();
	p->ram_F768 = a4;
	
	n = d1;
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->y_radius;
	d2 -= d0;
	d2 ^= 0xF;
	d0 = p->x_radius;
	d3 -= d0;
	a4 = p->ram_F76A;
	a3 = -0x10;
	d6 = 0x8000;
	FindFloor();
	p->ram_F76A = a4;
	d0 = n;
	Sonic_Angle();
	if(d1 == 0)
		goto return_1E4AE;
	if(d1 >= 0)
		goto loc_1E4B0;
	if(d1 < -0xE)
		goto return_1E4AE;
	p->y_pos -= d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	
return_1E4AE:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E4AE");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E4B0:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E4B0");
	#endif
	d0 = (p->x_vel >> 8);
	if((char)d0 < 0)
		d0 = -d0;
	
	d0 += 4;
	if((unsigned char)d0 >= 0xE)
		d0 = 0xE;
	
	if((char)d1 > (char)d0)
		goto loc_1E4CE;
	
loc_1E4C8:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E4C8");
	#endif
	p->y_pos -= d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E4CE:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E4CE");
	#endif
	if(p->stick_to_convex != 0)
		goto loc_1E4C8;
	p->status |= 2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->status &= 0xDF;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->next_anim = 1;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E4E8:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E4E8");
	#endif
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->x_radius;
	d2 -= d0;
	d0 = p->y_radius;
	d3 -= d0;
	d3 ^= 0xF;
	//WriteLog("*******************************");
	//VarLog(VAR_X_POS);
	//VarLog(VAR_Y_POS);
	//VarLog(VAR_X_RADIUS);
	//VarLog(VAR_Y_RADIUS);
	//VarLog(REG_D3);
	//VarLog(REG_D2);
	//WriteLog("*******************************");
	a4 = p->ram_F768;
	a3 = -0x10;
	d6 = 0x4000;
	FindWall();
	p->ram_F768 = a4;
	
	n = d1;
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->x_radius;
	d2 += d0;
	d0 = p->y_radius;
	d3 -= d0;
	d3 ^= 0xF;
	//WriteLog("*******************************");
	//VarLog(VAR_X_POS);
	//VarLog(VAR_Y_POS);
	//VarLog(VAR_X_RADIUS);
	//VarLog(VAR_Y_RADIUS);
	//VarLog(REG_D3);
	//VarLog(REG_D2);
	//WriteLog("*******************************");
	a4 = p->ram_F76A;
	a3 = -0x10;
	d6 = 0x4000;
	FindWall();
	p->ram_F76A = a4;
	d0 = n;
	Sonic_Angle();
	if(d1 == 0)
		goto return_1E55C;
	if(d1 >= 0)
		goto loc_1E55E;
	if(d1 < -0xE)
		goto return_1E55C;
	p->x_pos -= d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS);
	#endif
	
return_1E55C:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E55C");
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E55E:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E55E");
	#endif
	d0 = (p->y_vel >> 8);
	if((char)d0 < 0)
		d0 = -d0;
	
	d0 += 4;
	if((unsigned char)d0 >= 0xE)
		d0 = 0xE;
	
	if((char)d1 > (char)d0)
		goto loc_1E57C;
	
loc_1E576:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E576");
	#endif
	p->x_pos -= (short)d1;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E57C:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E57C");
	#endif
	if(p->stick_to_convex != 0)
		goto loc_1E576;
	p->status |= 2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->status &= 0xDF;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->next_anim = 1;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Sonic_Angle(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_Angle()");	TabLog(1);	RegLog();
	#endif
	d2 = p->ram_F76A;
	if(d1 > d0){
		d2 = p->ram_F768;
		d1 = d0;
	}
	
	if((d2 & 1) != 0)
		goto loc_1E380;
	d0 = d2 - p->angle;
	if((char)d0 < 0)
		d0 = -d0;
	
	if((char)d0 >= 0x20)
		goto loc_1E380;
	p->angle = d2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANGLE);
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E380:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E380");
	#endif
	d2 = p->angle;
	d2 += 0x20;
	d2 &= 0xC0;
	p->angle = d2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANGLE);
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Floor_ChkTile(){
	short x, y;
	#ifdef ENABLE_LOGGING
	WriteLog("Floor_ChkTile()");	TabLog(1);	RegLog();
	#endif
	x = (((short)d3)>>4);
	y = (((short)d2)>>4);
	// this function is customized for ProSonic
	// d3 is a modified 'p->x_pos'
	// d2 is a modified 'p->y_pos'
	
	if(x < 0) x = ((z.TMAP[tmap_ptr-2]+1) * (2<<tilesize)) - x;
	if(y < 0) y = ((z.TMAP[tmap_ptr-1]+1) * (2<<tilesize)) - y;
	
	a1 = COMPILED_MAP[
					(x % ((z.TMAP[tmap_ptr-2]+1) * (2<<tilesize)))
					+ ((y % ((z.TMAP[tmap_ptr-1]+1) * (2<<tilesize)))
					* ((z.TMAP[tmap_ptr-2]+1) * (2<<tilesize)))];
	//a1 = ReadBlock(&z, (short)d3, (short)d2);
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int FindFloor(){
	#ifdef ENABLE_LOGGING
	WriteLog("FindFloor()");	TabLog(1);	RegLog();
	#endif
	Floor_ChkTile();
	d0 = a1;
	d4 = d0;
	d0 &= 0x3FFF;
	if(d0 == 0)
		goto loc_1E7E2;
	if((d4 & (1 << d5)) != 0)
		goto loc_1E7F0;
	
loc_1E7E2:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E7E2");
	#endif
	d2 += a3;
	FindFloor2();
	d2 -= a3;
	d1 += 0x10;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E7F0:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E7F0");
	#endif
	a2 = p->Collision_addr;
	i = z.Act[act].Stage[stage].BlockSolidity;
	i = z.BSOL_AddressTable[i];
	a4 = z.BATT[a2 + d0 + i];	// slope
	d0 <<= 5;	// we do this because solidity is 32 bytes per block
	d1 = d3 & 0xFFFF;
	#ifdef ENABLE_LOGGING
	WriteLog(">>>---->");
	RegLog();
	WriteLog("<----<<<");
	#endif
	
	if(d4 & 0x4000){
		d1 = ~d1;
		a4 = -a4;
	}
	
	if(d4 & 0x8000){
		a4 += 0x40;
		a4 = -a4;
		a4 -= 0x40;
	}
	
	d1 &= 0xF;
	d1 += d0;
	d0 = z.BSOL[(a2 << 5) + d1 + i];
	// ext.w	d0
	d4 ^= d6;
	if(d4 & 0x8000)
		d0 = -d0;
	
	if(d0 == 0)
		goto loc_1E7E2;
	if((char)d0 < 0)
		goto loc_1E85E;
	if(d0 == 0x10)
		goto loc_1E86A;
	
	d1 = d2 & 0xF;
	d0 += d1;
	d1 = 0xF - (char)d0;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E85E:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E85E");
	#endif
	d1 = d2 & 0xF;
	d0 += d1;
	if(d0 >= 0)
		goto loc_1E7E2;
	
loc_1E86A:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E86A");
	#endif
	d2 -= a3;
	FindFloor2();
	d2 += a3;
	d1 -= 0x10;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int FindFloor2(){
	#ifdef ENABLE_LOGGING
	WriteLog("FindFloor2()");	TabLog(1);	RegLog();
	#endif
	Floor_ChkTile();
	d0 = a1;
	d4 = d0;
	d0 &= 0x3FFF;
	if(d0 == 0)
		goto loc_1E88A;
	if((d4 & (1 << d5)) != 0)
		goto loc_1E898;
	
loc_1E88A:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E88A");
	#endif
	d1 = 0xF;
	d0 = d2 & 0xF;
	d1 -= d0;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E898:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E898");
	#endif
	a2 = p->Collision_addr;
	i = z.Act[act].Stage[stage].BlockSolidity;
	i = z.BSOL_AddressTable[i];
	a4 = z.BATT[a2 + d0 + i];	// slope
	d0 <<= 5;
	d1 = d3 & 0xFFFF;
	#ifdef ENABLE_LOGGING
	WriteLog(">>>---->");
	RegLog();
	WriteLog("<----<<<");
	#endif
	
	if(d4 & 0x4000){
		d1 = ~d1;
		a4 = -a4;
	}
	
	if(d4 & 0x8000){
		a4 += 0x40;
		a4 = -a4;
		a4 -= 0x40;
	}
	
	d1 &= 0xF;
	d1 += d0;
	d0 = z.BSOL[(a2 << 5) + d1 + i];
	// ext.w	d0
	d4 ^= d6;
	if(d4 & 0x8000)
		d0 = -d0;
	
	if(d0 == 0)
		goto loc_1E88A;
	if((char)d0 < 0)
		goto loc_1E900;
	
	d1 = d2 & 0xF;
	d0 += d1;
	d1 = 0xF - (char)d0;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E900:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E900");
	#endif
	d1 = d2 & 0xF;
	d0 += d1;
	if(d0 >= 0)
		goto loc_1E88A;
	d1 = (~d1) & 0xFFFF;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Obj_CheckInFloor(){
	#ifdef ENABLE_LOGGING
	WriteLog("Obj_CheckInFloor()");	TabLog(1);	RegLog();
	#endif
	Floor_ChkTile();
	d0 = a1;
	d4 = d0;
	d0 &= 0x3FFF;
	if(d0 == 0)
		goto loc_1E922;
	if((d4 & (1 << d5)) != 0)
		goto loc_1E928;
	
loc_1E922:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E922");
	#endif
	d1 = 0x10;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E928:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E928");
	#endif
	a2 = p->Collision_addr;
	i = z.Act[act].Stage[stage].BlockSolidity;
	i = z.BSOL_AddressTable[i];
	a4 = z.BATT[a2 + d0 + i];	// slope
	d0 <<= 5;
	d1 = d3 & 0xFFFF;
	
	if(d4 & 0x4000){
		d1 = ~d1;
		a4 = -a4;
	}
	
	if(d4 & 0x8000){
		a4 += 0x40;
		a4 = -a4;
		a4 -= 0x40;
	}
	
	d1 &= 0xF;
	d1 += d0;
	d0 = z.BSOL[(a2 << 5) + d1 + i];
	// ext.w	d0
	d4 ^= d6;
	if(d4 & 0x8000)
		d0 = -d0;
	
	if(d0 == 0)
		goto loc_1E922;
	if((char)d0 < 0)
		goto loc_1E996;
	if(d0 == 0x10)
		goto loc_1E9A2;
	
	d1 = d2 & 0xF;
	d0 += d1;
	d1 = 0xF - (char)d0;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E996:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E996");
	#endif
	d1 = d2 & 0xF;
	d0 += d1;
	if(d0 >= 0)
		goto loc_1E922;
	//RegLog();	TabLog(-1);	return 0;		// ???? ???? ???? ????
	
loc_1E9A2:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E9A2");
	#endif
	d2 -= a3;
	FindFloor2();
	d2 += a3;
	d1 -= 0x10;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int FindWall(){
	#ifdef ENABLE_LOGGING
	WriteLog("FindWall()");	TabLog(1);	RegLog();
	#endif
	Floor_ChkTile();
	d0 = a1;
	d4 = d0;
	d0 &= 0x3FFF;
	if(d0 == 0)
		goto loc_1E9C2;
	if((d4 & (1 << d5)) != 0)
		goto loc_1E9D0;
	
loc_1E9C2:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E9C2");
	#endif
	d3 += a3;
	FindWall2();
	d3 -= a3;
	d1 += 0x10;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1E9D0:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1E9D0");
	#endif
	a2 = p->Collision_addr;
	i = z.Act[act].Stage[stage].BlockSolidity;
	i = z.BSOL_AddressTable[i];
	a4 = z.BATT[a2 + d0 + i];	// slope
	d0 <<= 5;
	d1 = d2 & 0xFFFF;
	#ifdef ENABLE_LOGGING
	WriteLog("// slope");
	VarLog(REG_A4);
	WriteLog("// slope index");
	VarLog(REG_D0);
	WriteLog("// something else");
	VarLog(REG_D1);
	WriteLog("// something else");
	VarLog(REG_D2);
	#endif
	
	if(d4 & 0x8000){
		d1 = ~d1;
		a4 += 0x40;
		a4 = -a4;
		a4 -= 0x40;
	}
	
	if(d4 & 0x4000)
		a4 = -a4;
	
	d1 &= 0xF;
	d1 += d0;
	d0 = z.BSOL[(a2 << 5) + d1 + i + 0x10];
	#ifdef ENABLE_LOGGING
	WriteLog("// solidity");
	VarLog(REG_D0);
	#endif
	// ext.w	d0
	d4 ^= d6;
	if(d4 & 0x4000)
		d0 = -d0;
	
	if(d0 == 0)
		goto loc_1E9C2;
	if((char)d0 < 0)
		goto loc_1EA3E;
	if(d0 == 0x10)
		goto loc_1EA4A;
	
	d1 = d3 & 0xF;
	d0 += d1;
	d1 = 0xF - (char)d0;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1EA3E:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1EA3E");
	#endif
	d1 = d3 & 0xF;
	d0 += d1;
	if((short)d0 >= 0)
		goto loc_1E9C2;
	
loc_1EA4A:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1EA4A");
	#endif
	d3 -= a3;
	FindWall2();
	d3 += a3;
	d1 -= 0x10;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int FindWall2(){
	#ifdef ENABLE_LOGGING
	WriteLog("FindWall2()");	TabLog(1);	RegLog();
	#endif
	Floor_ChkTile();
	d0 = a1;
	d4 = d0;
	d0 &= 0x3FFF;
	if(d0 == 0)
		goto loc_1EA6A;
	if((d4 & (1 << d5)) != 0)
		goto loc_1EA78;
	
loc_1EA6A:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1EA6A");
	#endif
	d1 = 0xF;
	d0 = d3 & 0xF;
	d1 -= d0;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1EA78:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1EA78");
	#endif
	a2 = p->Collision_addr;
	i = z.Act[act].Stage[stage].BlockSolidity;
	i = z.BSOL_AddressTable[i];
	a4 = z.BATT[a2 + d0 + i];	// slope
	d0 <<= 5;
	d1 = d2 & 0xFFFF;
	
	if(d4 & 0x8000){
		d1 = ~d1;
		a4 += 0x40;
		a4 = -a4;
		a4 -= 0x40;
	}
	
	if(d4 & 0x4000)
		a4 = -a4;
	
	d1 &= 0xF;
	d1 += d0;
	d0 = z.BSOL[(a2 << 5) + d1 + i + 0x10];
	// ext.w	d0
	d4 ^= d6;
	if(d4 & 0x4000)
		d0 = -d0;
	
	if(d0 == 0)
		goto loc_1EA6A;
	if((char)d0 < 0)
		goto loc_1EAE0;
	
	d1 = d3 & 0xF;
	d0 += d1;
	d1 = 0xF - (char)d0;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
	
loc_1EAE0:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1EAE0");
	#endif
	d1 = d3 & 0xF;
	d0 += d1;
	if(d0 >= 0)
		goto loc_1EA6A;
	d1 = (~d1) & 0xFFFF;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int CalcRoomInFront(){
	#ifdef ENABLE_LOGGING
	WriteLog("CalcRoomInFront()");	TabLog(1);	RegLog();
	#endif
	p->Collision_addr = 0;
	if(p->layer != 0x10)
		p->Collision_addr = 0x400;
	
	d5 = p->layer_plus;
	d3 = (p->x_pos << 16) + p->x_pos_pre;
	d2 = (p->y_pos << 16) + p->y_pos_pre;
	d1 = p->x_vel;
	d1 *= 256;
	d3 += d1;
	d1 = p->y_vel;
	d1 *= 256;
	d2 += d1;
	d2 = (d2 >> 16) + (d2 << 16);
	d3 = (d3 >> 16) + (d3 << 16);
	p->ram_F768 = d0;
	p->ram_F76A = d0;
	d1 &= 0xFFFFFF00;
	d1 |= d0;
	d0 += 0x20;
	if((char)d0 >= 0)
		goto loc_1EBDC;
	
	d0 = (char)d1;
	if((char)d0 < 0)
		d0--;
	
	d0 += 0x20;
	goto loc_1EBE6;
	
loc_1EBDC:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1EBDC");
	#endif
	d0 &= 0xFFFFFF00;
	d0 |= d1;
	if((char)d0 < 0)
		d0++;
	d0 += 0x1F;
	
loc_1EBE6:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1EBE6");
	RegLog();
	#endif
	d0 &= 0xC0;
	if(d0 == 0){
		// Copied the code here
		d2 += 0xA;
		a4 = p->ram_F768;
		a3 = 0x10;
		d6 = 0;
		FindFloor();
		p->ram_F768 = a4;
		d2 = 0;
		
		d3 = p->ram_F768;
		if((d3 & 1) != 0)
			d3 = d2;
		
		#ifdef ENABLE_LOGGING
		RegLog();	TabLog(-1);
		#endif
		return 0;
	}
	if((unsigned char)d0 == 0x80){
		CheckSlopeDist();
		#ifdef ENABLE_LOGGING
		RegLog();	TabLog(-1);
		#endif
		return 0;
	}
	d1 &= 0xFFFFFF38;
	if((char)d1 == 0)
		d2 += 8;
	
	if((char)d0 == 0x40){
		CheckLeftWallDist_Part2();
		#ifdef ENABLE_LOGGING
		RegLog();	TabLog(-1);
		#endif
		return 0;
	}
	CheckRightWallDist_Part2();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int CalcRoomOverHead(){
	#ifdef ENABLE_LOGGING
	WriteLog("CalcRoomOverHead()");	TabLog(1);	RegLog();
	#endif
	p->Collision_addr = 0;
	if(p->layer != 0x10)
		p->Collision_addr = 0x400;
	
	d5 = p->layer_plus;
	p->ram_F768 = d0;
	p->ram_F76A = d0;
	d0 += 0x20;
	d0 &= 0xC0;
	if(d0 == 0x40){
		CheckLeftCeilingDist();
		#ifdef ENABLE_LOGGING
		RegLog();	TabLog(-1);
		#endif
		return 0;
	}
	if(d0 == 0x80){
		CheckCeilingDist();
		#ifdef ENABLE_LOGGING
		RegLog();	TabLog(-1);
		#endif
		return 0;
	}
	if(d0 == 0xC0){
		CheckRightCeilingDist();
		#ifdef ENABLE_LOGGING
		RegLog();	TabLog(-1);
		#endif
		return 0;
	}
	
	Sonic_CheckFloor();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int Sonic_CheckFloor(){
	#ifdef ENABLE_LOGGING
	WriteLog("Sonic_CheckFloor()");	TabLog(1);	RegLog();
	#endif
	p->Collision_addr = 0;
	if(p->layer != 0x10)
		p->Collision_addr = 0x400;
	
	d5 = p->layer;
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->y_radius;
	d2 += d0;
	d0 = p->x_radius;
	d3 += d0;
	a4 = p->ram_F768;
	a3 = 0x10;
	d6 = 0;
	FindFloor();
	p->ram_F768 = a4;
	
	n = d1;
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->y_radius;
	d2 += d0;
	d0 = p->x_radius;
	d3 -= d0;
	a4 = p->ram_F76A;
	a3 = 0x10;
	d6 = 0;
	FindFloor();
	p->ram_F76A = a4;
	
	d0 = n;
	d2 = 0;
	
loc_1ECC6:	// COPY THIS CODE WHERE BRANCHED
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1ECC6");
	#endif
	d3 = p->ram_F76A;
	if(d1 > d0){
		d3 = p->ram_F768;
		i = d1;
		d1 = d0;
		d0 = i;
	}
loc_1ECD4:	// ALONG WITH THIS
	#ifdef ENABLE_LOGGING
	WriteLog("loc_1ECD4");
	#endif
	if(d3 & 1)
		d3 = d2;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int ChkFloorEdge(){
	#ifdef ENABLE_LOGGING
	WriteLog("ChkFloorEdge()");	TabLog(1);	RegLog();
	#endif
	d3 = p->x_pos;
	ChkFloorEdge_Part2();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int ChkFloorEdge_Part2(){
	#ifdef ENABLE_LOGGING
	WriteLog("ChkFloorEdge_Part2()");	TabLog(1);	RegLog();
	#endif
	d2 = p->y_pos;
	d0 = p->y_radius;
	d2 += d0;
	p->Collision_addr = 0;
	if(p->layer != 0x10)
		p->Collision_addr = 0x400;
	
	p->ram_F768 = 0;
	a4 = p->ram_F768;
	a3 = 0x10;
	d6 = 0;
	d5 = p->layer;
	FindFloor();
	p->ram_F768 = a4;
	d3 = p->ram_F768;
	if(d3 & 1)
		d0 = 0;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int CheckRightCeilingDist(){
	#ifdef ENABLE_LOGGING
	WriteLog("CheckRightCeilingDist()");	TabLog(1);	RegLog();
	#endif
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->x_radius;
	d2 -= d0;
	d0 = p->y_radius;
	d3 += d0;
	a4 = p->ram_F768;
	a3 = 0x10;
	d6 = 0;
	FindWall();
	p->ram_F768 = a4;
	
	n = d1;
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->x_radius;
	d2 += d0;
	d0 = p->y_radius;
	d3 += d0;
	a4 = p->ram_F76A;
	a3 = 0x10;
	d6 = 0;
	FindWall();
	p->ram_F76A = a4;
	
	d0 = n;
	d2 = -0x40;
	
	d3 = p->ram_F76A;
	if(d1 > d0){
		d3 = p->ram_F768;
		i = d1;
		d1 = d0;
		d0 = i;
	}
	
	if(d3 & 1)
		d3 = d2;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int CheckRightWallDist(){
	#ifdef ENABLE_LOGGING
	WriteLog("CheckRightWallDist()");	TabLog(1);	RegLog();
	#endif
	d2 = p->y_pos;
	d3 = p->x_pos;
	CheckRightWallDist_Part2();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int CheckRightWallDist_Part2(){
	#ifdef ENABLE_LOGGING
	WriteLog("CheckRightWallDist_Part2()");	TabLog(1);	RegLog();
	#endif
	d3 += 0xA;
	a4 = p->ram_F768;
	a3 = 0x10;
	d6 = 0;
	FindWall();
	p->ram_F768 = a4;
	d2 = -0x40;
	
	d3 = p->ram_F768;
	if(d3 & 1)
		d3 = d2;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int CheckCeilingDist(){
	#ifdef ENABLE_LOGGING
	WriteLog("CheckCeilingDist()");	TabLog(1);	RegLog();
	#endif
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->y_radius;
	d2 -= d0;
	d2 ^= 0xF;
	d0 = p->x_radius;
	d3 += d0;
	a4 = p->ram_F768;
	a3 = -0x10;
	d6 = 0x800;
	FindFloor();
	p->ram_F768 = a4;
	
	n = d1;
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->y_radius;
	d2 -= d0;
	d2 ^= 0xF;
	d0 = p->x_radius;
	d3 -= d0;
	a4 = p->ram_F76A;
	a3 = -0x10;
	d6 = 0x800;
	FindFloor();
	p->ram_F76A = a4;
	
	d0 = n;
	d2 = 0x80;
	
	d3 = p->ram_F76A;
	if(d1 > d0){
		d3 = p->ram_F768;
		i = d1;
		d1 = d0;
		d0 = i;
	}
	
	if(d3 & 1)
		d3 = d2;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int CheckSlopeDist(){
	#ifdef ENABLE_LOGGING
	WriteLog("CheckSlopeDist()");	TabLog(1);	RegLog();
	#endif
	d2 -= 0xA;
	d2 ^= 0xF;
	a4 = p->ram_F768;
	a3 = -0x10;
	d6 = 0x800;
	FindFloor();
	p->ram_F768 = a4;
	d2 = 0x80;
	
	d3 = p->ram_F768;
	if(d3 & 1)
		d3 = d2;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

inline int CheckLeftCeilingDist(){
	#ifdef ENABLE_LOGGING
	WriteLog("CheckLeftCeilingDist()");	TabLog(1);	RegLog();
	#endif
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->x_radius;
	d2 -= d0;
	d0 = p->y_radius;
	d3 -= d0;
	d3 ^= 0xF;
	a4 = p->ram_F768;
	a3 = -0x10;
	d6 = 0x400;
	FindWall();
	p->ram_F768 = a4;
	
	n = d1;
	d2 = p->y_pos;
	d3 = p->x_pos;
	d0 = p->x_radius;
	d2 += d0;
	d0 = p->y_radius;
	d3 -= d0;
	d3 ^= 0xF;
	a4 = p->ram_F76A;
	a3 = -0x10;
	d6 = 0x400;
	FindWall();
	p->ram_F76A = a4;
	
	d0 = n;
	d2 = 0x40;
	
	d3 = p->ram_F76A;
	if(d1 > d0){
		d3 = p->ram_F768;
		i = d1;
		d1 = d0;
		d0 = i;
	}
	
	if(d3 & 1)
		d3 = d2;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int CheckLeftWallDist(){
	#ifdef ENABLE_LOGGING
	WriteLog("CheckLeftWallDist()");	TabLog(1);	RegLog();
	#endif
	d2 = p->y_pos;
	d3 = p->x_pos;
	CheckLeftWallDist_Part2();
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int CheckLeftWallDist_Part2(){
	#ifdef ENABLE_LOGGING
	WriteLog("CheckLeftWallDist_Part2()");	TabLog(1);	RegLog();
	#endif
	d3 -= 0xA;
	d3 ^= 0xF;
	a4 = p->ram_F768;
	a3 = -0x10;
	d6 = 0x4000; // add extra zero for mirror flag//0x400;
	FindWall();
	p->ram_F768 = a4;
	d2 = 0x40;
	
	d3 = p->ram_F768;
	if(d3 & 1)
		d3 = d2;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}

int LoadSonicDynPLC(){
	#ifdef ENABLE_LOGGING
	WriteLog("*** LoadSonicDynPLC()");	TabLog(1);	RegLog();
	#endif
	/*p->anim = 1;
	p->anim_frame = 1;
	p->anim_frame_duration = 1;
	d0 = 1;*/
	//DrawSprite(&z, LayerH[frame-1], 0, 1, 0, 0, 160, 112);
	PositionCamera(p->x_pos, p->y_pos);
	
	a7 = (unsigned char)p->angle >> 5;
	if(a7 >= 4)
		a7 = (((unsigned char)(p->angle-1) >> 5) + 1) & 7;
	a6 = 0;
	
	if(p->status & 1){
		if(a7 == 4)
			a6 = ROTATE;
		
		else if(a7 > 4 && p->anim == 0){
			p->anim = 0x40 + a7 - 5;
			a6 = ROTATE;
		}
		else if(a7 > 0 && p->anim == 0)
			p->anim = 0x40 + a7 - 1;
		
		else if(a7 > 4 && p->anim == 1){
			p->anim = 0x43 + a7 - 5;
			a6 = ROTATE;
		}
		else if(a7 > 0 && p->anim == 1)
			p->anim = 0x43 + a7 - 1;
	}
	else{
		if(a7 == 4)
			a6 = ROTATE;
		
		else if(a7 > 4 && p->anim == 0)
			p->anim = 0x40 + 7 - a7;
		else if(a7 > 0 && p->anim == 0){
			p->anim = 0x40 + 3 - a7;
			a6 = ROTATE;
		}
		
		else if(a7 > 4 && p->anim == 1)
			p->anim = 0x40 + 7 - a7;
		else if(a7 > 0 && p->anim == 1){
			p->anim = 0x43 + 3 - a7;
			a6 = ROTATE;
		}
	}
	
	if(p->art_tile & 0x8000)
		DrawAnimation(&z, LayerSH[frame-1], 0, p->anim, p->anim_frame, (p->status & 1) ^ a6, 0, &p->anim_frame_duration, d0, p->x_pos - p->Camera_X_pos, p->y_pos - p->Camera_Y_pos - p->y_radius-1);
	else
		DrawAnimation(&z, LayerH[frame-1], 0, p->anim, p->anim_frame, (p->status & 1) ^ a6, 0, &p->anim_frame_duration, d0, p->x_pos - p->Camera_X_pos, p->y_pos - p->Camera_Y_pos - p->y_radius-1);
	
	if(p->anim >= 0x43)
		p->anim = 1;
	else if(p->anim >= 0x40)
		p->anim = 0;
	
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}
int KillCharacter(){
	#ifdef ENABLE_LOGGING
	WriteLog("*** KillCharacter()");	TabLog(1);	RegLog();
	#endif
	if(Debug_placement_mode)
		goto loc_3F972;
	p->status_secondary = 0;
	p->routine = 6;
	Sonic_ResetOnFloor(1);
	p->status |= 2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_STATUS);
	#endif
	p->y_vel = -0x700;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	p->x_vel = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_VEL);
	#endif
	p->inertia = 0;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_INERTIA);
	#endif
	p->anim = 0x18;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_ANIM);
	#endif
	p->art_tile |= 0x80;
	d0 = 0xA3;
	// A2 is the address of object interacting with player
	//cmpi.b	#$36,(a2)
	//bne.s		loc_3F96C
	//move.w	#$A6,d0
	
loc_3F96C:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_3F96C");
	#endif
	//jsr (PlaySound).l
	PlayFM(0x23, 3, 0); 		// --- this will need correction ---
	
loc_3F972:
	#ifdef ENABLE_LOGGING
	WriteLog("loc_3F972");
	#endif
	d0 = -1;
	#ifdef ENABLE_LOGGING
	RegLog();	TabLog(-1);
	#endif
	return 0;
}
int DisplaySprite(){
	#ifdef ENABLE_LOGGING
	WriteLog("*** DisplaySprite()");	TabLog(1);	RegLog();
	RegLog();	TabLog(-1);
	#endif
	return 0; // IGNORING FOR NOW ////////////////
}
int ObjectMoveAndFall(){
	#ifdef ENABLE_LOGGING
	WriteLog("ObjectMoveAndFall()");	TabLog(1);	RegLog();
	#endif
	d2 = (p->x_pos << 16) + p->x_pos_pre;
	d3 = (p->y_pos << 16) + p->y_pos_pre;
	d0 = p->x_vel;
	d0 *= 256;
	d2 += d0;
	d0 = p->y_vel;
	p->y_vel += 0x38;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_VEL);
	#endif
	d0 *= 256;
	d3 += d0;
	p->x_pos = d2 >> 16;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS);
	#endif
	p->x_pos_pre = d2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS_PRE);
	#endif
	p->y_pos = d3 >> 16;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	p->y_pos_pre = d3;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS_PRE);
	RegLog();	TabLog(-1);
	#endif
	return 0;
}
int ObjectMove(){
	#ifdef ENABLE_LOGGING
	WriteLog("ObjectMove()");	TabLog(1);	RegLog();
	#endif
	d2 = (p->x_pos << 16) + p->x_pos_pre;
	d3 = (p->y_pos << 16) + p->y_pos_pre;
	d0 = p->x_vel;
	d0 <<= 8;
	d2 += d0;
	d0 = p->y_vel;
	d0 <<= 8;
	d3 += d0;
	p->x_pos = (d2 >> 16);
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS);
	#endif
	p->x_pos_pre = d2;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_X_POS_PRE);
	#endif
	p->y_pos = (d3 >> 16);
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS);
	#endif
	p->y_pos_pre = d3;
	#ifdef ENABLE_LOGGING
	VarLog(VAR_Y_POS_PRE);
	RegLog();	TabLog(-1);
	#endif
	return 0;
}
inline int TouchResponse(){
	#ifdef ENABLE_LOGGING
	WriteLog("*** TouchResponse()");	TabLog(1);	RegLog();
	RegLog();	TabLog(-1);
	#endif
	return 0;
}



inline void PositionCamera(short x, short y){
	int cam_offset_x = x - p->Camera_X_pos - (screen_resolution_x >> 1);
	int cam_offset_y = y - p->Camera_Y_pos - (screen_resolution_y >> 1) - (p->Camera_Y_pos_bias - 0x60);
	
	// if the screen is fading, return and keep the camera still
	if(fade_count != 0)
		return;
	
	// does camera need to scroll right?
	if(cam_offset_x > 0){
		// is player more than 16 pixels right of where camera needs to be?
		if(cam_offset_x > 0x10)
			p->Camera_X_pos += 0x10;
		else
			p->Camera_X_pos += cam_offset_x;
	}
	
	// does camera need to scroll left?
	if(cam_offset_x < -0x10){
		// is player more than 16 pixels left of where camera needs to be?
		if(cam_offset_x < -0x20)
			p->Camera_X_pos -= 0x10;
		else
			p->Camera_X_pos += (cam_offset_x + 0x10);
	}
	
	// is player rolling?
	if(p->status & 4)
		cam_offset_y -= 5;
	
	// is player in the air?
	if(p->status & 2){
		// is player facing left?
		if(p->status & 3){
			if(cam_offset_y > 0x15){
				if(cam_offset_y > 0x25)
					p->Camera_Y_pos += 0x10;
				else
					p->Camera_Y_pos += (cam_offset_y - 0x15);
			}
			
			if(cam_offset_y < -0x2B){
				if(cam_offset_y < -0x3B)
					p->Camera_Y_pos -= 0x10;
				else
					p->Camera_Y_pos += (cam_offset_y + 0x2B);
			}
		}
		// else, player is facing right
		else{
			if(p->y_vel > 0x600 || p->y_vel < -0x600){
				if(cam_offset_y > 0x10){
					if(cam_offset_y > 0x20)
						p->Camera_Y_pos += 0x10;
					else
						p->Camera_Y_pos += (cam_offset_y - 0x10);
				}
				
				if(cam_offset_y < -0x30){
					if(cam_offset_y < -0x40)
						p->Camera_Y_pos -= 0x10;
					else
						p->Camera_Y_pos += cam_offset_y + 0x30;
				}
			}
			else{
				if(cam_offset_y > 0x10){
					if(cam_offset_y > 0x16)
						p->Camera_Y_pos += 0x6;
					else
						p->Camera_Y_pos += (cam_offset_y - 0x10);
				}
				
				if(cam_offset_y < -0x30){
					if(cam_offset_y < -0x36)
						p->Camera_Y_pos -= 0x6;
					else
						p->Camera_Y_pos += cam_offset_y + 0x30;
				}
			}
		}
	}
	// else, player isn't in the air
	else{
		if(p->y_vel > 0x600 || p->y_vel < -0x600){
			if(cam_offset_y > 0x10){
				if(cam_offset_y > 0x20)
					p->Camera_Y_pos += 0x10;
				else
					p->Camera_Y_pos += (cam_offset_y - 0x10);
			}
			
			else if(cam_offset_y < 0x10){
				if(cam_offset_y < -0x20)
					p->Camera_Y_pos -= 0x10;
				else
					p->Camera_Y_pos += (cam_offset_y + 0x10);
			}
		}
		else{
			if(cam_offset_y > -0x10){
				if(cam_offset_y > -0xA)
					p->Camera_Y_pos += 0x6;
				else
					p->Camera_Y_pos += (cam_offset_y + 0x10);
			}
			
			else if(cam_offset_y < -0x10){
				if(cam_offset_y < -0x16)
					p->Camera_Y_pos -= 0x6;
				else
					p->Camera_Y_pos += (cam_offset_y + 0x10);
			}
		}
	}
	
	
	////////////////////
	// Camera correction
	////////////////////
	
	// for the X axis
	if(!camera_mode){
		if(p->Camera_Max_X_pos - p->Camera_X_pos <= 0x100)
			p->Camera_Min_X_pos = p->Camera_Max_X_pos - 0x100;
	}
	if(p->Camera_X_pos < p->Camera_Min_X_pos)
		p->Camera_X_pos = p->Camera_Min_X_pos;
	else if(p->Camera_X_pos > p->Camera_Max_X_pos - (screen_resolution_x-320))
		p->Camera_X_pos = p->Camera_Max_X_pos - (screen_resolution_x-320);
	
	// for the Y axis
	if(p->Camera_Y_pos <= p->Camera_Min_Y_pos){
		if(p->Camera_Min_Y_pos < 0){
			p->Camera_Y_pos &= z.Act[act].Stage[stage].WrapPoint-1;
		
			if(p->Camera_Y_pos >= 0)
				p->Camera_Y_pos += ((p->Camera_Max_Y_pos - (screen_resolution_y-224)) << 8);
			else
				p->Camera_Y_pos &= ((z.Act[act].Stage[stage].WrapPoint-1 << 8) + 0xFF);
		}
		else
			p->Camera_Y_pos = p->Camera_Min_Y_pos;
	}
	
	if(screen_resolution_y-224 >= 0){
		if(p->Camera_Y_pos >= p->Camera_Max_Y_pos
		 && p->Camera_Y_pos >= z.Act[act].Stage[stage].WrapPoint
		 && p->Camera_Min_Y_pos < 0){
			p->Camera_Y_pos &= z.Act[act].Stage[stage].WrapPoint-1;
			p->y_pos &= z.Act[act].Stage[stage].WrapPoint-1;
		}
		else if(p->Camera_Y_pos > p->Camera_Max_Y_pos + (screen_resolution_y-224))
			p->Camera_Y_pos = p->Camera_Max_Y_pos + (screen_resolution_y-224);
	}
	else{
		if(p->Camera_Y_pos >= p->Camera_Max_Y_pos
		 && p->Camera_Y_pos >= z.Act[act].Stage[stage].WrapPoint
		 && p->Camera_Min_Y_pos < 0){
			p->Camera_Y_pos &= z.Act[act].Stage[stage].WrapPoint-1;
			p->y_pos &= z.Act[act].Stage[stage].WrapPoint-1;
		}
		else if(p->Camera_Y_pos > p->Camera_Max_Y_pos - (screen_resolution_y-224))
			p->Camera_Y_pos = p->Camera_Max_Y_pos - (screen_resolution_y-224);
	}
	
	
	
	// Don't know what it's for, but BRIDGE.BIN depends on this to function.
	p->Camera_X_pos_coarse = (p->Camera_X_pos - 128) / 256;
}
