		.386p
		ASSUME	CS:CODE,DS:DATA

		PUBLIC	MulSin,MulCos,MulTan
		PUBLIC	MulSinHq,MulCosHq,MulTanHq
		PUBLIC	FxSinHq,FxCosHq,FxTanHq
		PUBLIC	FxAsin,FxAcos,FxAtan
		PUBLIC	FxAngle


CLIP		MACRO	CPP
;Y=(X-X1)(Y2-Y1)/(X2-X1)+Y1
		SUB	EDX,EBX		;EDX=Y2-Y1
		SUB	ECX,EAX		;ECX=X2-X1
		SUB	EAX,CPP		;EAX=(X1-X)*-1
		NEG	EAX		;   = X-X1
		IMUL	EDX		;EAX:EDX=(X-X1)(Y2-Y1)
		IDIV	ECX		;EAX=(X-X1)(Y2-Y1)/(X2-X1)
		ADD	EAX,EBX		;EAX=(X-X1)(Y2-Y1)/(X2-X1)+Y1
		ENDM

;EAX:angle  →  result  All Registers except ESI will be destroyed.
GETHQ		MACRO	TBL
		AND	EAX,0FFFFH
		MOV	EDI,EAX
		SHR	EAX,6
		MOV	ECX,[TBL+EAX*4]
		MOV	EDX,[TBL+EAX*4+4]
		SHL	EAX,6

		;X2-X1=64 → (Y2-Y1)*(X-X1)/64 +Y1
		SUB	EDX,ECX		;EDX=Y2-Y1
		SUB	EAX,EDI		;EAX=(X1-X)*-1
		NEG	EAX		;   = X-X1
		IMUL	EDX		;EAX:EDX=(X-X1)(Y2-Y1)
		SHRD	EAX,EDX,6	;EAX=(X-X1)(Y2-Y1)/64
		ADD	EAX,ECX		;EAX=(X-X1)(Y2-Y1)/64+Y1
		ENDM


YABS		MACRO	REG
		LOCAL	LBL
		AND	REG,REG
		JG	LBL
		NEG	REG
LBL:
		ENDM




DATA		SEGMENT
		EXTRN	FX_sintbl:DWORD,FX_costbl:DWORD,FX_tantbl:DWORD
		EXTRN	FX_asintbl:DWORD,FX_acostbl:DWORD,FX_atantbl:DWORD

ANGOFF		DD	0,64		;変更するべからず

DATA		ENDS


CODE		SEGMENT
		ALIGN	4
MulSin		PROC
#ANG		EQU	ESP+8
#A		EQU	ESP+4
#RETADR		EQU	ESP
		MOV	ECX,0
		MOV	EAX,[#A]
		MOV	EDX,[#ANG]
		AND	EDX,EDX
		SETL	CL
		ADD	EDX,[ANGOFF+ECX*4]
		SHR	EDX,6
		AND	EDX,1023
		MOV	EDX,[FX_sintbl+EDX*4]
		IMUL	EDX
		SHRD	EAX,EDX,16
		RET
MulSin		ENDP

		ALIGN	4
MulCos		PROC
#ANG		EQU	ESP+8
#A		EQU	ESP+4
#RETADR		EQU	ESP
		MOV	ECX,0
		MOV	EAX,[#A]
		MOV	EDX,[#ANG]
		AND	EDX,EDX
		SETL	CL
		ADD	EDX,[ANGOFF+ECX*4]
		SHR	EDX,6
		AND	EDX,1023
		MOV	EDX,[FX_costbl+EDX*4]
		IMUL	EDX
		SHRD	EAX,EDX,16
		RET
MulCos		ENDP

		ALIGN	4
MulTan		PROC
#ANG		EQU	ESP+8
#A		EQU	ESP+4
#RETADR		EQU	ESP
		MOV	ECX,0
		MOV	EAX,[#A]
		MOV	EDX,[#ANG]
		AND	EDX,EDX
		SETL	CL
		ADD	EDX,[ANGOFF+ECX*4]
		SHR	EDX,6
		AND	EDX,1023
		MOV	EDX,[FX_tantbl+EDX*4]
		IMUL	EDX
		SHRD	EAX,EDX,16
		RET
MulTan		ENDP


		ALIGN	4
MulSinHq	PROC
#ANG		EQU	ESP+12
#A		EQU	ESP+8
#RETADR		EQU	ESP+4
#EDI		EQU	ESP
		PUSH	EDI

		MOV	EAX,[#ANG]
		GETHQ	FX_sintbl
		MOV	EDX,[#A]
		IMUL	EDX
		SHRD	EAX,EDX,16

		POP	EDI
		RET
MulSinHq	ENDP


		ALIGN	4
MulCosHq	PROC
#ANG		EQU	ESP+12
#A		EQU	ESP+8
#RETADR		EQU	ESP+4
#EDI		EQU	ESP
		PUSH	EDI

		MOV	EAX,[#ANG]
		GETHQ	FX_costbl
		MOV	EDX,[#A]
		IMUL	EDX
		SHRD	EAX,EDX,16

		POP	EDI
		RET
MulCosHq	ENDP


		ALIGN	4
MulTanHq	PROC
#ANG		EQU	ESP+12
#A		EQU	ESP+8
#RETADR		EQU	ESP+4
#EDI		EQU	ESP
		PUSH	EDI

		MOV	EAX,[#ANG]
		GETHQ	FX_tantbl
		MOV	EDX,[#A]
		IMUL	EDX
		SHRD	EAX,EDX,16

		POP	EDI
		RET
MulTanHq	ENDP


		ALIGN	4
FxSinHq		PROC
#ANG		EQU	ESP+8
#RETADR		EQU	ESP+4
#EDI		EQU	ESP
		PUSH	EDI

		MOV	EAX,[#ANG]
		GETHQ	FX_sintbl

		POP	EDI
		RET
FxSinHq		ENDP


		ALIGN	4
FxCosHq		PROC
#ANG		EQU	ESP+8
#RETADR		EQU	ESP+4
#EDI		EQU	ESP
		PUSH	EDI

		MOV	EAX,[#ANG]
		GETHQ	FX_costbl

		POP	EDI
		RET
FxCosHq		ENDP


		ALIGN	4
FxTanHq		PROC
#ANG		EQU	ESP+8
#RETADR		EQU	ESP+4
#EDI		EQU	ESP
		PUSH	EDI

		MOV	EAX,[#ANG]
		GETHQ	FX_tantbl

		POP	EDI
		RET
FxTanHq		ENDP


		ALIGN	4
FxAsin		PROC
#A		EQU	ESP+8
#RETADR		EQU	ESP+4
#EDI		EQU	ESP
		PUSH	EDI

		MOV	EAX,[#A]
		CMP	EAX,10000H
		JGE	#DEG90
		ADD	EAX,10000H
		JLE	#DEG270
		SAR	EAX,1
		GETHQ	FX_asintbl

		POP	EDI
		RET

#DEG90:		MOV	EAX,16384
		POP	EDI
		RET
#DEG270:	MOV	EAX,-16384
		POP	EDI
		RET
FxAsin		ENDP


		ALIGN	4
FxAcos		PROC
#A		EQU	ESP+8
#RETADR		EQU	ESP+4
#EDI		EQU	ESP
		PUSH	EDI

		MOV	EAX,[#A]
		CMP	EAX,10000H
		JGE	#DEG0
		ADD	EAX,10000H
		JLE	#DEG180
		SAR	EAX,1
		GETHQ	FX_acostbl

		POP	EDI
		RET

#DEG0:		MOV	EAX,0
		POP	EDI
		RET
#DEG180:	MOV	EAX,8000H
		POP	EDI
		RET
FxAcos		ENDP



		ALIGN	4
FxAtan		PROC
#A		EQU	ESP+8
#RETADR		EQU	ESP+4
#EBX		EQU	ESP
		PUSH	EBX
		SUB	ECX,ECX
		MOV	EBX,[#A]
		AND	EBX,EBX
		JGE	#PLUS
		NEG	EBX
		MOV	ECX,1
#PLUS:		MOV	EAX,EBX
		CDQ
		SHLD	EDX,EAX,10
		SHL	EAX,10
		ADD	EBX,10000H
		IDIV	EBX
		MOV	EAX,[FX_atantbl+EAX*4]
		AND	ECX,ECX
		JE	#SETANGLE
		NEG	EAX
#SETANGLE:	POP	EBX
		RET
FxAtan		ENDP


		ALIGN	4
FxAngle		PROC
#Y		EQU	ESP+16
#X		EQU	ESP+12
#RETADR		EQU	ESP+8
#EBX		EQU	ESP+4
#EDI		EQU	ESP

;CH		X <-> Y Reverse Flag
;CL		Sign Of Y

		PUSH	EBX
		PUSH	EDI

		MOV	EDI,0

		MOV	EBX,[#X]	;後の計算のためにX>=Yに転置する
		MOV	EAX,[#Y]
		YABS	EBX
		YABS	EAX
		CMP	EBX,EAX
		JGE	#Normal

#Reverse:	MOV	EAX,[#X]
		MOV	EBX,[#Y]
		MOV	CH,1		;転置情報を保存
		JMP	#PointIsSet
#Normal:	MOV	EBX,[#X]
		MOV	EAX,[#Y]
		MOV	CH,0

#PointIsSet:	AND	EBX,EBX
		JE	#VectorZero
		JG	#SetOffset
		MOV	EDI,32768
		NEG	EBX
		NEG	EAX
#SetOffset:

		SUB	CL,CL
		AND	EAX,EAX
		JGE	#SgnIsSet
		NEG	EAX
		MOV	CL,1
#SgnIsSet:

		ADD	EBX,EAX
		SUB	EDX,EDX
		SHLD	EDX,EAX,10
		SHL	EAX,10

		IDIV	EBX
		MOV	EAX,[FX_atantbl+EAX*4]
		AND	CL,CL
		JE	#AngleIsSet
		NEG	EAX
#AngleIsSet:	ADD	EAX,EDI

		AND	CH,CH
		JE	#UnReversed

		SUB	EAX,16384
		NEG	EAX

#UnReversed:	MOVSX	EAX,AX
		POP	EDI
		POP	EBX
		RET

#VectorZero:	SUB	EAX,EAX
		POP	EDI
		POP	EBX
		RET
FxAngle		ENDP
CODE		ENDS
		END
