program Test;

{ Program demonstrujici funkci realtimoveho programu.
}

uses
{$ifdef MCP}
  RtcTime,
{$endif}
  NumToStr,
  Crt,
  CrtWin,
  Dos,
  Kernel;


const
 {ukazatele na ladici okna}
  MakeWin   : PCrtWin = nil; {okno hlavniho procesu}
  StackWin  : PCrtWin = nil; {okno pro vypis Stack}
  Proc1Win  : PCrtWin = nil; {okno procesu 1}
  Proc2Win  : PCrtWin = nil; {okno procesu 2}

 {rozmery ladicich oken}
  cMakeWinSize  : tRect = (x: 2; Y: 5; W:78; H:16);
  cStackWinSize : tRect = (X: 2; Y:23; W:78; H: 9);
  cProc1WinSize : tRect = (X: 2; Y:34; W:38; H: 9);
  cProc2WinSize : tRect = (X:42; Y:34; W:38; H: 9);

 {barvy oken a tvary kurzoru}
  cColWinFrame  = (Black shl 4) or LightGray; {barva ramecku oken}
  cColWinHeader = (Black shl 4) or White;     {barva nadpisu okna}
  cColWinText   = (Black shl 4) or LightGray; {barva normalniho textu v oknech}
  cColWinTextZv = (Black shl 4) or White;     {barva zvyrazneneho textu v oknech}
  cColWinCur    = (LightGray shl 4) or White; {barva zvyrazneneho textu v oknech se zvyraznenym podkladem}
  cCur1         = $20;
  cCur2         = $00;



{-----------------------------------------------------------------------}
{ inicializace vypisoveho prostredi }
procedure InitDebVyp;
begin
  CrtInit;
  if MainWin=nil then exit;
  MainWin^.LockWin;
  MainWin^.HiddenCursor;
  TextAttr:=cColWinTextZv;
  ClrScr;
  writeln('Test protect modu - chyba na stack');
  TextAttr:=cColWinText;
  MainWin^.UnLockWin;

  { okno hlavniho procesu }
  MakeWin:=New(PCrtWin, Init(cMakeWinSize, ' Make ', FrameD,
             cColWinHeader,cColWinFrame,cColWinText,cCur1,cCur2));
  MakeWin^.LockWin;
  ClrScr;
  MakeWin^.UnLockWin;
  { okno Stack }
  StackWin:=New(PCrtWin,Init(cStackWinSize,' Stack ',FrameD,
             cColWinHeader,cColWinFrame,cColWinText,cCur1,cCur2));
  StackWin^.LockWin;
  ClrScr;
  StackWin^.UnLockWin;
  { okno procesu 1 }
  Proc1Win:=New(PCrtWin,Init(cProc1WinSize,' Process 1 ',FrameD,
             cColWinHeader,cColWinFrame,cColWinText,cCur1,cCur2));
  Proc1Win^.LockWin;
  ClrScr;
  Proc1Win^.UnLockWin;
  { okno procesu 2 }
  Proc2Win:=New(PCrtWin,Init(cProc2WinSize,' Process 2 ',FrameD,
             cColWinHeader,cColWinFrame,cColWinText,cCur1,cCur2));
  Proc2Win^.LockWin;
  ClrScr;
  Proc2Win^.UnLockWin;
end;


{$F+}
procedure Process1;
{$F-}
var
  a:integer;
begin
     Start('Process1', 2000, 80, 1);
     Exit;
     a:=0;
     repeat
       Proc1Win^.LockWin;
       writeln('Vypis:=', a);
       Proc1Win^.UnLockWin;

       StackWin^.LockWin;
       GotoXY(1,2);
       Writeln('Stack of process1: ', WordStrHex(Sseg),':',WordStrHex(SPtr));
       StackWin^.UnLockWin;

       Wait(1);
       Inc(a);
     until false;
end;


{$F+}
procedure Process2;
{$F-}
var
  a:integer;
begin
     Start('Process2', 2000, 80, 1);
     Exit;
     a:=0;
     repeat
       Proc2Win^.LockWin;
       writeln('Vypis:=', a);
       Proc2Win^.UnLockWin;

       StackWin^.LockWin;
       GotoXY(1,3);
       Writeln('Stack of process2: ', WordStrHex(Sseg),':',WordStrHex(SPtr));
       StackWin^.UnLockWin;

       asm
{         sub sp, 100}
         push ax
       end;
       Wait(2);
       Inc(a);
     until false;
end;


{$S-}
{$F+}
procedure UsrTerminateProc;
{$F-}
begin
  if TestKernel and (StackWin<>nil) then StackWin^.LockWin;
  gotoxy(1,5);
  writeln('ExitProc: ', ExitCode, ' - address: ', PtrToStr(ErrorAddr));
  if TestKernel then Writeln('Chyba v procesu: ', RunningProcess);
  if TestKernel and (StackWin<>nil) then StackWin^.UnLockWin;
end;


procedure MyExitProc; far;
begin
  if TestKernel and (StackWin<>nil) then StackWin^.LockWin;
  gotoxy(1,6);
  writeln('ExitProc: ', ExitCode, ' - address: ', PtrToStr(ErrorAddr));
  if TestKernel then Writeln('Chyba v procesu: ', RunningProcess);
  if TestKernel and (StackWin<>nil) then StackWin^.UnLockWin;
{$ifdef VerMC}
  repeat until false;
{$else}
  halt(ExitCode);
{$endif}
end;
{$S+}

var
  Counter:Integer;

begin
  ExitProc:=@MyExitProc;

  TextMode(Lo(LastMode)+Font8x8);
  ClrScr;
  Writeln('Spusteni jadra');

  { inicializace os ReTOS }
  StartMain(200, 254);
  InitInterruptStack(1,254);
  StartTimeSlicing(8);

  UserTerminate:=UsrTerminateProc;

  InitDebVyp;

  MakeWin^.LockWin;
  writeln('Creating of all processes');
  MakeWin^.UnLockWin;

  Process1;
  Process2;

  repeat
    MakeWin^.LockWin;
    Writeln('Make ', Counter);
    MakeWin^.UnLockWin;

    StackWin^.LockWin;
    GotoXY(1,1);
    Writeln('Stack of main process: ', WordStrHex(Sseg),':',WordStrHex(SPtr));
    StackWin^.UnLockWin;

    Inc(Counter);
    wait(1);
  until keypressed;

  { ukonceni vsech procesu }
  Abort('*');
  { ukonceni hlavniho procesu }
  TerminateMain;
end.