#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>


;#include "FASM.au3"
#AutoIt3Wrapper_UseX64=n

;Global $pASM_Sin = _FASM_StructCreateBCA16(_FASM_Compile("_ASM_Sin_32"))
Global $pASM_Sin = _StructCreateBCA16("0x538B5C24088D841B00000080C1F802F7E8C1FB1F8D8412000000908D8CD2000000DCF7EA31D98D84D20000A044F7E989D05BC20400")
;Global $pASM_Cos = _FASM_StructCreateBCA16(_FASM_Compile("_ASM_Cos_32"))
Global $pASM_Cos = _StructCreateBCA16("0x538B5C240881C3000000408D841B00000080C1F802F7E8C1FB1F8D8412000000908D8CD2000000DCF7EA31D98D84D20000A044F7E989D05BC20400")


#ASM _ASM_Sin_32
#	use32
#	push ebx

#	mov ebx, [esp+8]

#	lea  eax, [ebx*2+0x80000000]
#	sar  eax, 2
#	imul eax
#	sar  ebx, 31
#	lea  eax, [edx*2-0x70000000]
#	lea  ecx, [edx*9-0x24000000]
#	imul edx
#	xor  ecx, ebx
#	lea  eax, [edx*9+0x44A00000]
#	imul ecx

#	mov eax, edx

#	pop ebx
#	ret 4
#ASMEND



#ASM _ASM_Cos_32
#	use32
#	push ebx

#	mov ebx, [esp+8] ;Phase

#	add ebx, 0x40000000 ;SinToCos

#	lea  eax, [ebx*2+0x80000000]
#	sar  eax, 2
#	imul eax
#	sar  ebx, 31
#	lea  eax, [edx*2-0x70000000]
#	lea  ecx, [edx*9-0x24000000]
#	imul edx
#	xor  ecx, ebx
#	lea  eax, [edx*9+0x44A00000]
#	imul ecx

#	mov eax, edx

#	pop ebx
#	ret 4
#ASMEND


Global Const $cPI = ATan(1) * 4

Func _Sin($fX)
	Local $aResult = DllCallAddress("int", $pASM_Sin, "uint", $fX * 2 ^ 31 / $cPI)
	Return $aResult[0] / -0x9A68000
EndFunc   ;==>_Sin


Func _Cos($fX)
	Local $aResult = DllCallAddress("int", $pASM_Cos, "uint", $fX * 2 ^ 31 / $cPI)
	Return $aResult[0] / -0x9A68000
EndFunc   ;==>_Cos



Opt("MustDeclareVars", 1)
Opt("GUIOnEventMode", 1)

Global $iWidth = 1200
Global $iHeight = 600

_GDIPlus_Startup()
Global $hGui = GUICreate("ASM", $iWidth, $iHeight)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
Global $hBmp_Buffer = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics)
Global $hGfx_Buffer = _GDIPlus_ImageGetGraphicsContext($hBmp_Buffer)
_GDIPlus_GraphicsSetSmoothingMode($hGfx_Buffer, 2)
_GDIPlus_GraphicsClear($hGfx_Buffer, 0xFF000000)
GUIRegisterMsg($WM_PAINT, "WM_PAINT")
GUISetState()

_GDIPlus_GraphicsClear($hGfx_Buffer, 0xFF000000)
_PlotSin("Sin", 0xFF00FF00, "Sin(x)")
_PlotSin("_Sin", 0xFFFF0044, "Sin(x) 6th Order")
_PlotSin("Cos", 0xFF0066FF, "Cos(x)")
_PlotSin("_Cos", 0xFFFFFF00, "Cos(x) 6th Order")
_GDIPlus_GraphicsDrawImage($hGraphics, $hBmp_Buffer, 0, 0)

While Sleep(10)
WEnd

Func _PlotSin($sSinFunc, $iColor, $sInfo)
	Local Static $iY = 0
	$iY += 16
	Local $hBrush = _GDIPlus_BrushCreateSolid($iColor)
	Local $hFormat = _GDIPlus_StringFormatCreate()
	Local $hFamily = _GDIPlus_FontFamilyCreate("Arial")
	Local $hFont = _GDIPlus_FontCreate($hFamily, 10)
	_GDIPlus_GraphicsDrawStringEx($hGfx_Buffer, $sInfo, $hFont, _GDIPlus_RectFCreate(10, $iY, 0, 0), $hFormat, $hBrush)
	_GDIPlus_FontDispose($hFont)
	_GDIPlus_FontFamilyDispose($hFamily)
	_GDIPlus_StringFormatDispose($hFormat)
	_GDIPlus_BrushDispose($hBrush)

	Local $hPen = _GDIPlus_PenCreate($iColor, 2)
	Local $aCurve[$iWidth + 2][2] = [[$iWidth]]
	For $i = 0 To $iWidth
		$aCurve[$i + 1][0] = $i
		$aCurve[$i + 1][1] = $iHeight * 0.5 + Call($sSinFunc, $i /$iWidth * $cPI * 3) * $iHeight * 0.4
	Next
	_GDIPlus_GraphicsDrawCurve($hGfx_Buffer, $aCurve, $hPen)

	_GDIPlus_PenDispose($hPen)
EndFunc   ;==>_PlotSin

Func WM_PAINT($hWnd, $iMsg, $wParam, $lParam)
	_GDIPlus_GraphicsDrawImage($hGraphics, $hBmp_Buffer, 0, 0)
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_PAINT

Func _Exit()
	_GDIPlus_GraphicsDispose($hGfx_Buffer)
	_GDIPlus_BitmapDispose($hBmp_Buffer)
	_GDIPlus_GraphicsDispose($hGraphics)
	_GDIPlus_Shutdown()
	GUIDelete($hGui)
	Exit
EndFunc   ;==>_Exit


Func _StructCreateBCA16($bBinaryCode)
	Local $iSize = BinaryLen($bBinaryCode)
	Local $aResult = DllCall("kernel32.dll", "ptr", "VirtualAlloc", "ptr", 0, "ulong_ptr", $iSize + 16, "dword", 0x00001000, "dword", 0x00000040)
	If @error Or Not $aResult[0] Then Return SetError(1, 0, False)
	Local $pStruct = Number($aResult[0])
	$pStruct = $pStruct + 16 - Mod($pStruct, 16)
	Local $tStruct = DllStructCreate("byte[" & $iSize & "];", $pStruct)
	DllStructSetData($tStruct, 1, $bBinaryCode)
	Return $pStruct
EndFunc   ;==>_FASM_StructCreateBCA16