=====Using 32-bit floating point values===== //by Jon Ripley, August 2006//\\ \\ //BBC BASIC for Windows// stores floating point numbers in 40-bit and 64-bit resolutions and has no built-in support for 32-bit (single precision) floating point numbers. When using the Windows API and functions in third party DLLs it is sometimes necessary to use 32-bit floating point numbers. To ensure that single precision numbers are correctly passed to **SYS** calls they must be stored in integer variables which are also 32-bits wide.\\ \\ The following two functions are required to perform the necessary conversions:\\ \\ * **FN_ConvertToSingle** converts a number to a single precision floating point value * **FN_ConvertFromSingle** converts a number from a single precision floating point value \\ DEF FN_ConvertToSingle(A#) LOCAL A%,P% PRIVATE F% IF F%=0 THEN DIM P% 10 [OPT 2 .F% mov esi,[ebp+2] ; esi = pointer to A# mov edi,[ebp+7] ; edi = pointer to A% fld qword [esi] ; load indirect 64 bit real from esi fstp dword [edi] ; store indirect 32 bit real to edi ret ] ENDIF A#*=1.0# CALL F%,A#,A% =A% DEF FN_ConvertFromSingle(A%) LOCAL A#,P% PRIVATE F% IF F%=0 THEN DIM P% 10 [OPT 2 .F% mov esi,[ebp+2] ; esi = pointer to A% mov edi,[ebp+7] ; edi = pointer to A# fld dword [esi] ; load indirect 32 bit real from esi fstp qword [edi] ; store indirect 64 bit real to edi ret ] ENDIF CALL F%,A%,A# =A# \\ **Note:** **FN_ConvertToSingle** is the same routine as **FN_f4** from the supplied //D3DLIB// library, but the assembly language has been commented and the name has been changed for clarity.\\ ---- \\ //by Richard Russell, November 2006//\\ \\ The above routines use assembly language code to perform the conversion. An alternative is to use Windows API functions as follows:\\ \\ DEF FN_ConvertToSingle(A#) LOCAL A% PRIVATE F% IF F% = 0 THEN SYS "LoadLibrary", "OLEAUT32.DLL" TO F% SYS "GetProcAddress", F%, "VarR4FromR8" TO F% ENDIF A#*=1.0# SYS F%,!^A#,!(^A#+4),^A% =A% DEF FN_ConvertFromSingle(A%) LOCAL A# PRIVATE F% IF F% = 0 THEN SYS "LoadLibrary", "OLEAUT32.DLL" TO F% SYS "GetProcAddress", F%, "VarR8FromR4" TO F% ENDIF SYS F%,A%,^A# =A# If speed is critical, use this conversion function:\\ DEF FN_ConvertToSingle(A#)=USR(f4) where the routine **f4** has been assembled previously as follows:\\ .f4 mov ecx,[^A#+4] test ecx,&FFFFFF00 jnz f4d movzx ecx,cl jecxz f4i mov edx,[^A#] add ecx,895 rol edx,1 shld ecx,edx,21 shl edx,20 btr edx,20 rcr ecx,1 mov [^A#],edx mov [^A#+4],ecx .f4d push eax fld qword [^A#] fstp dword [esp] pop eax ret ; .f4i push eax fild dword [^A#] fstp dword [esp] pop eax ret Ensure there is at least a 2048-byte gap between the code and any writable data, to prevent thrashing of the instruction cache.