{ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ}
{Û                                                       Û}
{Û      Virtual Pascal for Linux                         Û}
{Û      Resource support layer                           Û}
{Û      ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÛ}
{Û      Copyright (C) 2000 vpascal.com                   Û}
{Û      Copyright (C) 1999 Veit Kannegieser              Û}
{Û                                                       Û}
{ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß}

{$IFNDEF Linux}
  Compile/Target Platform: Linux
{$ENDIF}
{$S-}

unit LnxRes;

interface

type
  TLinux_Resource_Anchor = packed record
    fPointer   : Pointer;
    fLength    : Longint;
    fSignature : Array[0..3] of Char;
  end;

  // PE2LE:RESKONV.PAS:d32_reso_kopf
  TLinux_Resource_Block = packed record
    fLength    : Longint;
    fType      : SmallWord;
    fId        : SmallWord;
  end;

  TLinux_Resource_Types = ( rt_ResourceString, rt_Binary );

  PLinux_Resource_String = ^TLinux_Resource_String;
  TLinux_Resource_String = packed record
    fLength    : SmallWord;
    fStr       : Array[0..High(SmallWord)] of Char;
  end;

const
  Linux_Resource_Anchor : TLinux_Resource_Anchor = (
    fPointer   : Ptr($b582cc18);
    fLength    : $467a1d0e;
    fSignature : 'RES?' );

function LnxGetResourceAddress(_Name, _Type: SmallWord): Pointer;
function LnxGetResourceStringAddress(_Name: SmallWord) : PLinux_Resource_String;

implementation

function LnxGetResourceAddress(_Name, _Type: SmallWord): Pointer;
  assembler; {$Frame-} {&Uses esi,edi}
asm
      sub   eax,eax // not found
      cmp   [Linux_Resource_Anchor.fSignature],'OSER' // 'RESO'
      jne   @Ret

      mov   esi,[Linux_Resource_Anchor.fPointer]
      mov   edi,[Linux_Resource_Anchor.fLength]
      add   edi,esi

      mov   dx,[_Name]
      shl   edx,16
      mov   dx,[_Type]

      jmp   @BeginSearch

    @ContinueSearch:
      add   esi,[esi+TLinux_Resource_Block.fLength]

    @BeginSearch:
      // End of Resource ?
      cmp   esi,edi
      je    @Ret

      // Longint containing both type and id
      cmp   edx,[esi+TLinux_Resource_Block.fType].Longint
      jne   @ContinueSearch

      // Found: Return address
      lea   eax,[esi+type TLinux_Resource_Block]

    @Ret:
end;

function LnxGetResourceStringAddress(_Name: SmallWord) : PLinux_Resource_String;
  assembler; {&Frame-} {&Uses None}
asm
      movzx eax,[_Name]
      shr   eax,4   // div 16
      push  eax
      push  rt_ResourceString
      call  LnxGetResourceAddress

      test  eax,eax
      jz    @Ret

      movzx ecx,[_Name]
      and   ecx,15  // mod 16
      test  ecx,ecx
      jmp   @@1

    @SearchLoop:

      movzx edx,[eax].SmallWord
      lea   eax,[eax+2+edx]
      sub   ecx,1
    @@1:
      jnz   @SearchLoop

      cmp [eax].SmallWord,0
      jne @ret

      // string with length 0 -> nil
      sub eax,eax

    @ret:
end;

initialization
  if Linux_Resource_Anchor.fSignature = 'RES?' then
    // Nothing; prevent smart linking
end.
