[Back to SCREEN SWAG index]  [Back to Main SWAG index]  [Original]

{
> I just let dos write something on the screen, I'm in the normal
> videomode, say that writes 100 lines to the screen. How can I read
> whatever that program wrote if the lines have scrolled of the screen ???
> I need to have the output in an array ... with the colors ... there might
> even be an animation in the output (ansi) ... I know how to put a normal
> 25x80 in an array or a 50x80 ... but how do you work with something
> that's 100 lines long ... I want to be able to scroll back after the
> display ...

You can use an Array to do it - or, you can program your graphic-card. :-)

Perhaps this little prog will give you a clue:
}

program BreakOut;

uses CRT, DOS;

const

 UP   = 0;   { Verschieberichtung fuer Bildschirm. }
 DOWN = 1;
 ST_X = 10;  { Steine nebeneinander. }
 ST_Y = 5;   { Steine uebereinander. }

type

 screen_params = record
  zeichen  : char;
  attribut : byte;
 end;

 Video_params = record
  mode, page     : byte;
  start_scanline : byte;
  end_scanline   : byte;
  row, column    : byte;
 end;

 stone_params = record
  spalte : byte;
  zeile  : byte;
 end;

 bouncer_params = record  { bouncer == schlaeger }
  spalte : shortint;
  zeile  : shortint;
  dir    : shortint;
  speed  : longint;
  count  : longint;
 end;

 ball_params = record
  spalte : real;
  zeile  : real;
  speed  : longint;
  count  : longint;
  dir_x  : real;
  dir_y  : real;
  next_x : real;
  next_y : real;
  last_x : real;
  last_y : real;
  flag   : byte;
 end;

 screen_type = array [1..2000] of screen_params;

var

 regs    : Registers;
 Video   : Video_params;
 bouncer : bouncer_params;
 ball    : ball_params;
 stone   : array [1..ST_X,1..ST_Y] of stone_params;
 screen  : ^screen_type;  { Zeiger auf aktuelle Seite. }
 screen0 : pointer;       { Zeiger auf Seite 0. }
 screen1 : pointer;       { Zeiger auf Seite 1. }
 screen2 : pointer;       { Zeiger auf Seite 2. }

procedure GetCurrentVideoMode;
{
 Procedure to get and store the current video mode settings.
}

begin
 regs.ah := $0F;
 intr($10, regs);
 Video.mode := regs.al;
 Video.page := regs.bh;
end;

procedure GetCurrentCursorSettings;
{
 Procedure to get and store the current cursor settings.
}

begin
 regs.ah := 3;
 regs.bh := Video.page;
 intr($10, regs);
 Video.start_scanline := regs.ch;
 Video.end_scanline := regs.cl;
 Video.row := regs.dh;
 Video.column := regs.dl;
end;

procedure SetVideoMode(mode : byte);
{
 Procedure to set a specific video mode.

 mode = new video mode.
}

begin
 regs.ah := 0;
 regs.al := mode;
 intr($10, regs);
end;

procedure HideCursor;
{
 Procedure to make the cursor invisible on the screen.
}

begin
 regs.ah := 1;
 regs.al := Video.mode;
 regs.cx := $FFFF;
 intr($10, regs);
end;

procedure RestoreCursor;
{
 Procedure to restore the old cursor.
}

begin
 regs.ah := 1;
 regs.al := Video.mode;
 regs.ch := Video.start_scanline;
 regs.cl := Video.end_scanline;
 intr($10, regs);
end;

procedure ClearScreen;

var

 i : integer;

begin
 for i := 1 to 2000 do
 begin
  screen^[i].zeichen := #32;
  screen^[i].attribut := 7;
 end;
end;

procedure DrawBorder;

var

 i : integer;

begin
 for i := 1 to 80 do
  screen^[i].attribut := $30;
 for i := 81 to 1920 do  { 1920 = 2000 - 80 }
 begin
  screen^[i].attribut := $30;
  i := i + 79;
  screen^[i].attribut := $30;
 end;
end;

procedure InitializeStones;

var

 i, j : byte;
 x, y : byte;  { x = Spalte; y = Zeile }

begin
 y := 4;
 for i := 1 to ST_Y do  { Zeilen }
 begin
  x := 7;
  for j := 1 to ST_X do  { Spalten }
  begin
   stone[j, i].spalte := x;
   stone[j, i].zeile := y;
   x := x + 7;
  end;
  y := y + 2;
 end;
end;

procedure DrawStones;

var

 pos     : integer;
 i, j, k : byte;

begin
 for i := 1 to ST_Y do  { Zeilen }
 begin
  for j := 1 to ST_X do  { Spalten }
  begin
   pos := stone[j, i].zeile * 80 + stone[j, i].spalte;
   for k := 0 to 4 do
    screen^[(pos + k)].attribut := $60;
  end;
 end;
end;

procedure DrawBouncer;

var

 i   : integer;
 pos : integer;

begin
 pos := bouncer.zeile * 80 + bouncer.spalte - 1;
 screen^[pos].attribut := 7;
 for i := 1 to 8 do
  screen^[(pos + i)].attribut := $70;
 screen^[(pos + 9)].attribut := 7;
end;

procedure DrawBall;

var

 pos : integer;

begin
 pos := integer(trunc(ball.last_y) * 80 + trunc(ball.last_x));
 screen^[pos].zeichen := #32;
 screen^[pos].attribut := 7;
 pos := integer(trunc(ball.zeile) * 80 + trunc(ball.spalte));
 screen^[pos].zeichen := 'o';
 screen^[pos].attribut := 5;
 ball.last_x := ball.spalte;
 ball.last_y := ball.zeile;
 ball.next_x := ball.spalte + ball.dir_x;
 ball.next_y := ball.zeile + ball.dir_y;
end;

procedure MovePicture(scr : pointer; direction : byte);

var

 dir     : integer;
 count   : word;
 zaehler : word;

begin
 zaehler := ofs(screen^) shr 1;
 port[$03D4] := $0C;
 port[$03D5] := hi(zaehler);
 port[$03D4] := $0D;
 port[$03D5] := lo(zaehler);
 if (direction = UP) then
  dir := 80
 else
  dir := (-80);
 count := 0;
 repeat
  inc(count);
  zaehler := zaehler + dir;
  port[$03D4] := $0C;
  port[$03D5] := hi(zaehler);
  port[$03D4] := $0D;
  port[$03D5] := lo(zaehler);
  delay(20);
 until (count = 25);
 screen := scr;
end;

function MoveBouncer : byte;

var

 c : char;

begin
 bouncer.count := bouncer.count - 1;
 if (bouncer.count = 0) then
 begin
  bouncer.count := bouncer.speed;
  if (keypressed) then
  begin
   c := readkey;
   case c of
    #0  : begin
           c := readkey;
           case c of
            #75 : bouncer.dir := (-1);
            #77 : bouncer.dir := 1;
           end;
          end;
    #27 : begin
           MoveBouncer := 1;
           exit;
          end;
    #32 : bouncer.dir := 0;
   end;
  end;
  bouncer.spalte := bouncer.spalte + bouncer.dir;
  if (bouncer.spalte < 2) then
  begin
   bouncer.spalte := 2;
   bouncer.dir := 0;
  end;
  if (bouncer.spalte = 73) then
  begin
   bouncer.spalte := 72;
   bouncer.dir := 0;
  end;
  if (bouncer.dir <> 0) then
   DrawBouncer;
 end;
 MoveBouncer := 0;
end;

procedure MoveBall;

var

 pos    : integer;

begin
 ball.count := ball.count - 1;
 if (ball.count = 0) then
 begin
  ball.count := ball.speed;

  { Linken und rechten Rand abfragen. }

  if ((trunc(ball.next_x) < 2) or (trunc(ball.next_x) > 79)) then
  begin
   ball.dir_x := ball.dir_x * (-1.0);
   ball.next_x := ball.spalte + ball.dir_x;
  end;

  { Oberen Rand abfragen. }

  if (trunc(ball.next_y) < 1) then
  begin
   ball.dir_y := ball.dir_y * (-1.0);
   ball.next_y := ball.zeile + ball.dir_y;
  end;

  { Unteren Rand abfragen. }

  if (trunc(ball.next_y) > 23) then
  begin
   pos := integer((trunc(ball.zeile) + 1) * 80 + trunc(ball.spalte));
   if (screen^[pos].attribut = $70) then
   begin
    ball.dir_y := ball.dir_y * (-1.0);
    ball.next_y := ball.zeile + ball.dir_y;
   end
   else
   begin
    ball.flag := 2;
    exit;
   end;
  end;
  ball.spalte := ball.next_x;
  ball.zeile := ball.next_y;
  DrawBall;
 end;
end;

procedure Play;

var

 erg : byte;

begin
 while (TRUE) do
 begin
  erg := MoveBouncer;
  if (erg = 1) then
   exit;
  MoveBall;
  if (ball.flag = 2) then
   exit;
 end;
end;

begin
 GetCurrentVideoMode;
 GetCurrentCursorSettings;
 if (Video.mode <> 3) then
  SetVideoMode(3);
 HideCursor;

 screen0 := ptr($B800, 0000);  { Bildschirmseite 0. }
 screen1 := ptr($B800, 4000);  { Bildschirmseite 1. }
 screen2 := ptr($B800, 8000);  { Bildschirmseite 2. }
 screen := screen0;
 ClearScreen;
 screen := screen2;
 ClearScreen;
 screen := screen1;
 ClearScreen;
 DrawBorder;
 InitializeStones;
 DrawStones;
 bouncer.spalte := 35;
 bouncer.zeile := 24;
 bouncer.dir := 0;
 bouncer.speed := 3000;
 bouncer.count := bouncer.speed;
 DrawBouncer;
 ball.spalte := 40.0;
 ball.zeile := 20.0;
 ball.speed := 8000;
 ball.count := ball.speed;
 ball.dir_x := 1.0;
 ball.dir_y := (-1.0);
 ball.last_x := 39.0;
 ball.last_y := 21.0;
 ball.flag := 0;
 DrawBall;
 screen := screen0;
 repeat
  MovePicture(screen1, UP);
  MovePicture(screen2, UP);
  MovePicture(screen1, DOWN);
  MovePicture(screen0, DOWN);
 until (keypressed);

 MovePicture(screen1, UP);
 Play;

 RestoreCursor;
 port[$03D4] := $0C;
 port[$03D5] := 0;
 port[$03D4] := $0D;
 port[$03D5] := 0;
 if (Video.mode <> 3) then
  SetVideoMode(Video.mode)
 else
  clrscr;
 textattr := LIGHTGRAY;
 writeln;
 writeln('Thank you for playing BreakOut!');
 writeln;
 writeln('Do have a nice day...');
 writeln; writeln;
end.

[Back to SCREEN SWAG index]  [Back to Main SWAG index]  [Original]