(*
*******************************************************************************
*         Copyright (C) SofCon 2003 All Rights Reserved                       *
*******************************************************************************
*
*    project:     vizualizace
*
*    title:       AppDesc.pas
*
*******************************************************************************
*
*    description: definice typu, konstant a promennych pouzivanych v aplikaci
*                 Pri inicializaci se pouzivaji konstanty (xDesc) popisujici
*                 sdileny pametovy prostor mezi aplikaci a LOADER.
*
*    version:     1.06
*    language:    Borland Pascal
*
*    author:      Jan Hvozdovic
*    history:     date      sign   remark
*                 9.02      hv     zacatek vyvoje
*                11.02      hv     prvni release
*		 12.02	    hv 	   doplnena procedura fnAppDone
*		 12.02	    hv     opravena chyba pri ukoncovani a v ExitProc
*					pri praci s tabulkou LdrDesc a AppRstDesc
*		  3.03      hv     uprava konstanty cVer do stand. formatu
*				   pridani konstanty cVerNo obsahujici ciselne
*					verzi knihovny
*				   zruseni konstanty cName
*				   pridani konstanty cSwId
*                 9.03      hv     knihovna pouziva rozsirenou
*                                       standardni knihovnu Crc16
*                                  Pozn. Drivejsi verze pouzivala knihovnu ExCrc16
*                 1.04      hv     upravy spojene s prejmenovanim a upravami
*                                       deklaraci struktur
*                                           tAppRstDesc => tAppRstDesc1
*                                           tLdrDesc    => tLdrDesc3
*****************************************************************************
*)
unit AppDesc;
{$i sets.inc}

interface
uses
   HwSyst
  ,xDesc               { jednotka definujici konstanty a typy pouzivane
                         jak v aplikaci tak v LOADER
                         (castecne definuje rozlozeni pameti) }
  ,LibVer              { definice formatu verze }
  ,Xtking_1            { definice typu a konstant pro praci s vizualizaci }
  ;

const
  {-------------------------------------------------------------------------}
  {-------------------------------------------------------------------------}
  { cislo verze Aplikace (tj. tohoto prikladu) }
  cAplicationVer = $0201; {BCD format}

  { identifikacni retezec ve vizualizacnim programu - v inicializacni casti jednotky se doplni o verzi aplikace}
  strAppName: String[30] = 'KitKing v';


  { verze struktury xDesc.tAppRstDesc (ErrDescArray), ktera je pouzivana soucasnou
    aplikaci; verze se muze v budoucnu pri zmene aplikace zmenit vcetne upravy
    pouzivani teto struktury v ramci zminenych omezeni viz. zapis do struktury
    ErrDescArray
    LOADER tuto konstantu nepouziva !!!}
  cErrDescArrayVer    = $0100;              { VYZADOVANO }



const
  {-------------------------------------------------------------------------}
  {-------------------------------------------------------------------------}
  { hodnoty se vyplni pri alokaci pameti }
  { adresa struktury AppRstDesc - restart struktura, pocitadla Pfi atd. }
  laAppRstDesc   :LongInt    = 0;            { VYZADOVANO }
  { adresa struktury LdrDesc - pouziva LOADER pri spousteni aplikace,
           dale je mozne pomoci bParForApp, bParForLdr predavat ruzne flag }
  laLdrDesc      :LongInt    = 0;            { VYZADOVANO }


  {-------------------------------------------------------------------------}
  {-------------------------------------------------------------------------}
  { ukazatel na prostor tAppRstDesc }
  gpAppRstDesc : pAppRstDesc1 = nil;         { VYZADOVANO }

  { ukazatel na prostor tLdrDesc }
  gpLdrDesc : pLdrDesc3 = nil;               { VYZADOVANO }



{ Funkce provede inicializaci promennych popisujici rozlozeni
  pameti. Pri inicializaci se pouzivaji konstanty ze souboru xDesc.
  Po nastaveni rozlozeni pameti se provede kontrola verzi RstDescArray,
  viz. pozn. o kodovani a pouzivani RstDescArray. Dale se provede validace
  struktury LdrDesc, pri jejim poskozeni se provede inicializace.
  Vraci:
    True  - vse OK
    False - poskozena struktur LdrDesc. Doslo k jeji inicializaci. }
function fnAppInit:Boolean;


{ Procedura provede uvolneni promennych popisujicich rozlozeni pameti }
procedure fnAppDone;


implementation
uses
  Kernel,              { jadro os ReTOS }
  numToStr,            { prace s retezci }
  Crc16;               { prace s Crc16 }

var
  SaveExit:Pointer;


procedure MyExitProc; far; forward;




{ Funkce provede inicializaci promennych popisujicich rozlozeni
  pameti. Pri inicializaci se pouzivaji konstanty ze souboru xDesc.
  Po nastaveni rozlozeni pameti se provede kontrola verzi RstDescArray,
  viz. pozn. o kodovani a pouzivani RstDescArray. Dale se provede validace
  struktury LdrDesc, pri jejim poskozeni se provede inicializace.
  Vraci:
    True  - vse OK
    False - poskozena struktur LdrDesc. Doslo k jeji inicializaci. }
function fnAppInit:Boolean;
var
  theCrc:tCrc16;
begin
  fnAppInit:=True;

 { nastaveni posledni obsluhy ExitProc, aby se MyExitProc volala jako prvni }
  SaveExit:=ExitProc;
  ExitProc:=@MyExitProc;


 {$ifNdef VerMC}
  { alokace prostoru pro struktury aplikace a LOADER }
  GetMem(gpAppRstDesc, sizeof(tAppRstDesc1));
    FillChar(gpAppRstDesc^, sizeof(tAppRstDesc1), 0);
    laAppRstDesc:=(LongInt(Seg(gpAppRstDesc^)) shl 4) + Ofs(gpAppRstDesc^);

  GetMem(gpLdrDesc, sizeof(tLdrDesc3));
    FillChar(gpLdrDesc^, sizeof(tLdrDesc3), 0);
    laLdrDesc:=(LongInt(Seg(gpLdrDesc^)) shl 4) + Ofs(gpLdrDesc^);

   { nahrani dalsich struktur aplikace }
   if LoadAppRstDesc(gpAppRstDesc)<>0 then InitAppRstDesc(gpAppRstDesc);
   if LoadLdrDesc(gpLdrDesc)<>0 then InitLdrDesc(gpLdrDesc);

 {$else}
   { nastaveni linearnich adres dle rozlozeni pameti }
   laAppRstDesc:=_laAppRstDesc;
   laLdrDesc:=_laLdrDesc;

   {--}
   { nastaveni ukazovatelu na struktury aplikace a LOADER }
   gpAppRstDesc:=Ptr(laAppRstDesc shr 4, laAppRstDesc and $F);
   gpLdrDesc:=Ptr(laLdrDesc shr 4, laLdrDesc and $F);
   {--}

 {$endif}

   { kontrola prekryvu jednotlivych pametovych oblasti }
   if ((_laAppRstDesc + sizeof(tAppRstDesc1)) <= laMaxFixedMemory) and
      ((_laLdrDesc + sizeof(tLdrDesc3)) <= _laAppRstDesc) and
      (laMinFixedMemory <= _laLdrDesc)
  {$ifdef VerMC}
   and(PtrToAbsAddr(HeapEnd) <= laMinFixedMemory)
  {$endif}
   then
   begin
     { vse OK }
     { kontrola platnosti struktury LdrDesc - CRC }
     if gpLdrDesc^.wCrc<>theCrc.CalculateCrc(gpLdrDesc,
             cLdrDescCrcSize, cLdrResidue) then
     begin
       InitLdrDesc(gpLdrDesc);
       fnAppInit:=False;
     end;
   end
   else
   begin
     { chybne rozlozeni pameti }
     fnSetLastError(err_Alloc);
     fnAppInit:=False;
   end;
end;


{ Procedura provede uvolneni promennych popisujicich rozlozeni pameti }
procedure fnAppDone;
begin
 {$ifNdef VerMC}
  SaveAppRstDesc(gpAppRstDesc);
  SaveLdrDesc(gpLdrDesc);

  { uvolneni prostoru pro struktury aplikace a LOADER }
  if gpAppRstDesc<>nil then FreeMem(gpAppRstDesc, sizeof(tAppRstDesc1));
  gpAppRstDesc:=nil;
  if gpLdrDesc<>nil then FreeMem(gpLdrDesc, sizeof(tLdrDesc3));
  gpLdrDesc:=nil;
 {$endif}
end;


{****************************************************************************}
{$S-}
procedure MyExitProc;
begin
  ExitProc:=SaveExit;

  if ((ExitCode<>0) or (ErrorAddr<>nil)) then
  begin
    if gpAppRstDesc=nil then
    begin
     {$ifdef Deb_Crt}
      writeln('AppRstDesc je uz uvolnen, chybu nelze zapsat: ', ExitCode,
              ', Addr:', PtrToStr(ErrorAddr));
     {$endif}
    end
    else
      with gpAppRstDesc^ do
      begin
        { zvyseni poctu zachycenych RunError }
        if wRunErrCnt<High(wRunErrCnt) then Inc(wRunErrCnt);

        wVer:=cErrDescArrayVer;    { verze Restart struktury }
        wAppVer:=cAplicationVer;   { verze Aplikace }
        { zalozeni nove chyby }
        Inc(bIxWrittenAt); if bIxWrittenAt>MaxRst then bIxWrittenAt:=0;
        with ErrDescArray[bIxWrittenAt] do
        begin
          rErr := ExitCode;
          rAddr:= ErrorAddr;
          rPckTime:=GetPackTime;
          if TestKernel then rStr:=RunningProcess;
        end;
      end;
  end;

{$ifNdef VerMC}
  if gpAppRstDesc<>nil then SaveAppRstDesc(gpAppRstDesc);
  if gpLdrDesc<>nil then SaveLdrDesc(gpLdrDesc);
{$endif}
end;
{$S+}

{****************************************************************************}
{ funkce pro nastaveni posledni chyby }
procedure uSetLastError(ldrerr:Word); far;
begin
  if ldrerr<>err_Ok then
  begin
    RunError(ldrerr);
  end;
end;

{****************************************************************************}

begin
  strAppName:=strAppName + VerNoToStr(cAplicationVer);

  { nastaveni vlastni obsluhy nastavovani posledni chyby }
  fnSetLastError:=uSetLastError;

  { inicializace posledni chyby }
  fnSetLastError(err_Ok);
end.
