//////////////////////////////////////////////////////
//    Mini-Utils & Mini-Math Parts of JSM Engine    //
//////////////////////////////////////////////////////
//    Last Modify: 11/03/2011         //
//    John_Moff@yahoo.com             //
////////////////////////////////////////
unit Sys_U;

interface

uses
  Windows;

const
  SPi=3.141592653;
  FAng=360;
  HAng=180;


function  LowerCase(const S: string): string;

function  GetTime: DWORD;
function  IntToStr(Val: Integer): PChar; stdcall;
function  StrToInt(Str: PChar): Integer; stdcall;
function  StrToIntS(Str: String): Integer; stdcall;
function  FloatToStr(Val: Single): PChar; stdcall;
function  ArcTng(X,Y: Single): Integer; stdcall;
function  CalcAng(sX1,sY1,sX2,sY2: Integer): Integer; stdcall;
function  Sin360(A: Integer): Single; stdcall;
function  Cos360(A: Integer): Single; stdcall;
procedure InitCSTabs; stdcall;
procedure SinCosF(const Theta: Single; out Sin, Cos: Single); assembler; stdcall;
function  Round(Val: Single): Integer; stdcall;


var
  STab, CTab: array[0..FAng] of Single;
  FStr: String;


implementation


function LowerCase(const S: string): string;
var
  Ch: Char;
  L: Integer;
  Source, Dest: PChar;
begin
  L := Length(S);
  SetLength(Result, L);
  Source := Pointer(S);
  Dest := Pointer(Result);
  while L <> 0 do
  begin
    Ch := Source^;
    if (Ch >= 'A') and (Ch <= 'Z') then Inc(Ch, 32);
    Dest^ := Ch;
    Inc(Source);
    Inc(Dest);
    Dec(L);
  end;
end;


function ArcTng;
begin
  Result:=Abs( Round( ArcTan(Y/X )*(HAng/SPi) ) );
end;


function CalcAng;
var
  DstX, DstY : Single;
begin
// Modification by Poiree
// Thx a lot!
  DstX := (sX1-sX2);
  DstY := (sY1-sY2);

  if (DstX < 0) and (DstY > 0) then result := - ArcTng (DstX, DstY)          else
  if (DstX < 0) and (DstY < 0) then result :=   ArcTng (DstX, DstY)          else
  if (DstX > 0) and (DstY < 0) then result := 90 + (90 - ArcTng(DstX, DstY)) else
    Result := HAng + ArcTng(DstX, DstY);

  if (DstX < 0) and (DstY > 0) then result := HAng-ArcTng(DstX, DstY) else
  if (DstX < 0) and (DstY < 0) then result := HAng+ArcTng(DstX, DstY) else
  if (DstX > 0) and (DstY < 0) then result := FAng-ArcTng(DstX, DstY) else
    Result := ArcTng(DstX, DstY);
end;


procedure SinCosF;
asm
// maybe...
  FLD     Theta
  FSINCOS
  FSTP    tbyte ptr [edx]
  FSTP    tbyte ptr [eax]
  FWAIT
end;


function Round;
asm
  FLD Val
  FISTP DWORD PTR [Val]
  MOV EAX, [Val]
end;


function GetTime;
var
  T : LARGE_INTEGER;
  F : LARGE_INTEGER;
begin
  QueryPerformanceFrequency(Int64(F));
  QueryPerformanceCounter(Int64(T));
  Result := Trunc(1000 * T.QuadPart / F.QuadPart);
end;


function IntToStr;
begin
  Str(Val, FStr);
  Result:=PChar(FStr);
end;

function StrToInt;
var
  Num:Integer;
begin
  Val(Str,Result,Num);
end;

function StrToIntS;
var
  Num:Integer;
begin
  Val(Str,Result,Num);
end;

function FloatToStr;
begin
  Str(Val:3:7, FStr);
  Result:=PChar(FStr);
end;



function Sin360;
begin
  while A < 0 do A:= A+FAng;
  while A > FAng do A:=A-FAng;
  Result:=STab[A];
end;


function Cos360;
begin
  while A < 0 do A:=A+FAng;
  while A > FAng do A:=A-FAng;
  Result:=CTab[A];
end;


procedure InitCSTabs;
var
  i:integer;
  AR:Single;
begin
 for i := 0 to FAng do begin
   AR:=i*(SPi/HAng);
   STab[i]:=Sin(AR);
   CTab[i]:=Cos(AR);
 end;
end;

initialization
  InitCSTabs;

end.
