[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]