Sources PureBasic

Sources PureBasicConsultez toutes les sources
Nombre d'auteurs : 41, nombre de sources : 88, dernière mise à jour : 13 août 2011
Sommaire→AssembleurLes procédures ci dessous permettent de maintenir un angle dans un intervalle :
- WrapAngleSigned(angle.f) maintient un angle en radian entre [-Pi,Pi]
- WrapAngleDegSigned(angle.f) maintient un angle en degré entre [-180,180]
- WrapAngleUnsigned(angle.f) maintient un angle en radian entre [0,2*Pi]
- WrapAngleDegUnsigned(angle.f) maintient un angle en degré entre [0,360]
Procedure.f WrapAngleSigned(angle.f); <- wraps a value into [-Pi,Pi] fringe
!fldpi
!fadd st0,st0; <- now i have 2*pi into st0
!fld dword[p.v_angle]
!fprem1
!fstp st1
ProcedureReturn
EndProcedure
Procedure.f WrapAngleDegSigned(angle.f); <- wraps a value into [-180,180] fringe
!fild dword[@f] ; <- now i have 360 into st0
!fld dword[p.v_angle]
!fprem1
!fstp st1
ProcedureReturn
!@@:dd 360
EndProcedure
Procedure.f WrapAngleUnsigned(angle.f); <- wraps a value into [0,2*Pi) fringe
!fldpi; <- now i have pi into st0
!fadd st0,st0; <- now i have 2*pi into st0
!fld dword[p.v_angle]; <- now i have angle in st0, 2*pi into st1
!fprem; <- now i have the remainder of angle/(2*pi) division (i.e. angle%(2*pi)) in st0, 2*pi in st1
!fadd st1,st0;<- now i have angle%(2*pi) in st0, 2*pi+angle%(2*pi) into st1
!fldz;<- now i have 0 in st0, angle%(2*pi) in st1, 2*pi+angle%(2*pi) into st2
!fcomip st1; <- compare st0 and st1, and pop the stack, which means i have now angle%(2*pi) in st0, 2*pi+remainder into st1
!fcmovnbe st0,st1; <- transfer st1 to st0 if not below or equal.
!fstp st1; <- store st0 in st1 and pops stack, which means i have now the result in st0
ProcedureReturn; <- return the result with this last pop
EndProcedure
Procedure.f WrapAngleDegUnsigned(angle.f); <- wraps a value into [0,360) fringe
!fild dword[@f] ; <- now i have 360 into st0
!fld dword[p.v_angle]
!fprem
!fadd st1,st0
!fldz
!fcomip st1
!fcmovnbe st0,st1
!fstp st1
ProcedureReturn
!@@:dd 360
EndProcedure
;Exemples d'utilisation en degré:
angle.f=45
angleadd.f=-90
angle.f=WrapAngleDegUnsigned(angle.f+angleadd.f)
Debug angle
;
angle.f=45
angleadd.f=-90
angle.f=WrapAngleDegSigned(angle.f+angleadd.f)
Debug angle
;
;Exemples d'utilisation en radian:
angle.f=#PI/4.0
angleadd.f=-#PI/2.0
angle.f=WrapAngleUnsigned(angle.f+angleadd.f)
Debug angle
;
angle.f=#PI/4.0
angleadd.f=-#PI/2.0
angle.f=WrapAngleSigned(angle.f+angleadd.f)
Debug angle
Ce code permet de tester si une zone mémoire ne contient que des zéros pour par exemple détecter une collision.
La procédure est optimisée et renvoie #False si toutes les donnéees sont à zéro sinon #True.
; Thorium le 21/11/09
; PB 4.40
Procedure NoneZero(*DestBufStart, DestBufSize.i)
CompilerSelect #PB_Compiler_Processor
CompilerCase #PB_Processor_x86
!push edi
!push ebx
!mov edi,[p.p_DestBufStart+8]
!mov edx,[p.v_DestBufSize+8]
!mov ecx,edx
!mov ebx,ecx
!shr edx,4
!and ecx,15
!shr ecx,2
!and ebx,3
!test edx,edx
!je NoneZero_FirstEnd
!pxor xmm1,xmm1
!align 4
!NoneZero_FirstStart:
!movdqu xmm0,[edi]
!pcmpeqb xmm0,xmm1
!add edi,16
!pmovmskb eax,xmm0
!cmp eax,$0000FFFF
!jne NoneZero_EndTrueSse
!dec edx
!jne NoneZero_FirstStart
!emms
!align 4
!NoneZero_FirstEnd:
!test ecx,ecx
!je NoneZero_SecondEnd
!align 4
!NoneZero_SecondStart:
!mov eax,[edi]
!test eax,eax
!jne NoneZero_EndTrue
!add edi,4
!dec ecx
!jne NoneZero_SecondStart
!align 4
!NoneZero_SecondEnd:
!test ebx,ebx
!je NoneZero_ThirdEnd
!align 4
!NoneZero_ThirdStart:
!mov al,[edi]
!test al,al
!jne NoneZero_EndTrue
!inc edi
!dec ebx
!jne NoneZero_ThirdStart
!align 4
!NoneZero_ThirdEnd:
!pop ebx
!pop edi
ProcedureReturn #False
!NoneZero_EndTrue:
!pop ebx
!pop edi
ProcedureReturn #True
!NoneZero_EndTrueSse:
!pop ebx
!pop edi
!emms
ProcedureReturn #True
CompilerCase #PB_Processor_x64
!push rdi
!push rbx
!mov rdi,[p.p_DestBufStart+16]
!mov rdx,[p.v_DestBufSize+16]
!mov rcx,rdx
!mov rbx,rcx
!shr rdx,4
!and rcx,15
!shr rcx,2
!and rbx,3
!test rdx,rdx
!je NoneZero_FirstEnd
!pxor xmm1,xmm1
!align 8
!NoneZero_FirstStart:
!movdqu xmm0,[rdi]
!pcmpeqb xmm0,xmm1
!add rdi,16
!pmovmskb eax,xmm0
!cmp eax,$0000FFFF
!jne NoneZero_EndTrueSse
!dec rdx
!jne NoneZero_FirstStart
!emms
!align 8
!NoneZero_FirstEnd:
!test rcx,rcx
!je NoneZero_SecondEnd
!align 8
!NoneZero_SecondStart:
!mov eax,[rdi]
!test eax,eax
!jne NoneZero_EndTrue
!add rdi,4
!dec rcx
!jne NoneZero_SecondStart
!align 8
!NoneZero_SecondEnd:
!test rbx,rbx
!je NoneZero_ThirdEnd
!align 8
!NoneZero_ThirdStart:
!mov al,[rdi]
!test al,al
!jne NoneZero_EndTrue
!inc rdi
!dec rbx
!jne NoneZero_ThirdStart
!align 8
!NoneZero_ThirdEnd:
!pop rbx
!pop rdi
ProcedureReturn #False
!NoneZero_EndTrue:
!pop rbx
!pop rdi
ProcedureReturn #True
!NoneZero_EndTrueSse:
!pop rbx
!pop rdi
!emms
ProcedureReturn #True
CompilerEndSelect
EndProcedure
;- Test de la procédure
*Buffer = AllocateMemory(64000) ; Buffer de 64000 octets
*Ptr.Byte = *Buffer + 64000 - 1 ; On se place sur le dernier octet
*ptr\b = 5 ; Modifie le dernier octet du *Buffer
Debug NoneZero(*Buffer, MemorySize(*Buffer))
Atan2(y,x) est l'angle en radians entre la partie positive de l'axe des x d'un plan, et le point de ce plan aux coordonnées (x,y). (wikipédia)
Note : La commande Atan2() est ajoutée dans la bibliothèque Math depuis la version 4.50.
Procedure.d ATan2(y.d,x.d)
!fld qword[p.v_y]
!fld qword[p.v_x]
!fpatan
ProcedureReturn
EndProcedure
y.d = 70
x.d = 0
#RAD2DEG = 180.0/#PI ; Conversion Radians en degrés
Debug ATan2(y, x) * #RAD2DEG


