{ ------------------------------------------------------------------------ }
{ ----------- UNIDAD DE AVEN'95 -> Herramientas para gr ficos ------------ }
{ ------------------- Creado por Braulio D¡ez Botella -------------------- }
{ ------------------------- (c) Avalon Soft 1995 ------------------------- }
{ ------------------------------------------------------------------------ }

{ $G+} { --> Esto nos genera c¢digo en modo 286 -> Hace falta para PUTPIXEL }
unit graf256;
INTERFACE
const
     VGA = $A000; { Direcci¢n de la pantalla en modo 320x200 256 col. }


type

    t_pantalla=record
      imagen:pointer;
      direccion:pointer;
    end;

var
    DONDE:word; { Pantalla actual activa }


PROCEDURE SETVGA256; { Nos pone en modo 320x200 256 colores}
PROCEDURE MODOTEXTO; { Nos devuelve al modo texto }
PROCEDURE PUTPIXEL (X,Y : Integer; Col : Byte); { Pone un punto }
{ en pantalla, ... utiliza instrucciones de 286 }
PROCEDURE Cls (Col : Byte); { ... Para borrar una pantalla }
PROCEDURE SETVGAOUT (pantalla:pointer);
PROCEDURE RESTOREVGAOUT;
FUNCTION RESERVESCREEN (Var pantalla:pointer):word;
PROCEDURE FLIP (source,dest:Word);
PROCEDURE SAVESCREEN (Var pantalla:pointer);
PROCEDURE RESTORESCREEN (Var pantalla:pointer);
PROCEDURE DELETESCREEN (Var pantalla:pointer);
PROCEDURE WAITVBL; { Espera al retrazado del monitor... }
PROCEDURE Line(a,b,c,d:integer;col:byte);

{ ---- Fin de definici¢n de procedimientos ----}
{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}

IMPLEMENTATION

Procedure SETVGA256;  { Para inicializar el modo 320x200 256 colores }
begin
DONDE:=VGA;
  asm
     mov ax,0013h
     int 10h
  end;
end;
{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}

Procedure MODOTEXTO;ASSEMBLER;  { ... Para volver al modo texto }
asm
   mov ax,0003h
   int 10h
END;

{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
Procedure Putpixel (X,Y :Integer;Col:byte);
  { Rutina r pida para poner pixels, utiliza codigo de 286 }
BEGIN
  Asm
    mov     ax,[DONDE]
    mov     es,ax
    mov     bx,[X]
    mov     dx,[Y]
    mov     di,bx
    mov     bx, dx                  {; bx = dx}
    shl     dx, 8
    shl     bx, 6
    add     dx, bx                  {; dx = dx + bx (ie y*320)}
    add     di, dx                  {; finalise location}
    mov     al, [Col]
    stosb
  End;
END;

{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
Procedure Cls (Col : Byte);
   { Borra la pantalla que le indiquemos, con el color que queramos }
BEGIN
     asm
        push    es
        mov     cx, 32000;
        mov     es,[DONDE]
        xor     di,di
        mov     al,[col]
        mov     ah,al
        rep     stosw
        pop     es
     End;
END;
{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
PROCEDURE SETVGAOUT (pantalla:pointer);
begin
donde:=seg (pantalla^);
end;
{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
PROCEDURE RESTOREVGAOUT;
begin
donde:=VGA;
end;
{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
FUNCTION RESERVESCREEN (Var pantalla:pointer):word;
begin
GetMem (pantalla,64000);
reservescreen := seg (pantalla^);
end;
{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}

procedure flip(source,dest:Word);
  { This copies the entire screen at "source" to destination }
begin
  asm
    push    ds
    mov     ax, [Dest]
    mov     es, ax
    mov     ax, [Source]
    mov     ds, ax
    xor     si, si
    xor     di, di
    mov     cx, 32000
    rep     movsw
    pop     ds
  end;
end;


{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
PROCEDURE SAVESCREEN (Var pantalla:pointer);
begin
Move (mem [VGA:0],pantalla^,64000);

end;

{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}

PROCEDURE RESTORESCREEN (Var pantalla:pointer);
begin
Move (pantalla^,mem [VGA:0],64000);
end;

{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
Procedure DELETESCREEN (Var pantalla:pointer);
    { libera la memoria que ocupa en el Heap, la pantalla virtual }
BEGIN
  FreeMem (pantalla,64000);
END;
{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
procedure WaitVbl; assembler;
  { This waits until you are in a Verticle Retrace ... this means that all
    screen manipulation you do only appears on screen in the next verticle
    retrace ... this removes most of the "fuzz" that you see on the screen
    when changing the pallette. It unfortunately slows down your program
    by "synching" your program with your monitor card ... it does mean
    that the program will run at almost the same speed on different
    speeds of computers which have similar monitors. In our SilkyDemo,
    we used a WaitRetrace, and it therefore runs at the same (fairly
    fast) speed when Turbo is on or off. }

label
  l1, l2;
asm
    mov dx,3DAh
l1:
    in al,dx
    and al,08h
    jnz l1
l2:
    in al,dx
    and al,08h
    jz  l2
end;

{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}

Procedure Line(a,b,c,d:integer;col:byte);
  { This draws a solid line from a,b to c,d in colour col }
  function sgn(a:real):integer;
  begin
       if a>0 then sgn:=+1;
       if a<0 then sgn:=-1;
       if a=0 then sgn:=0;
  end;
var i,s,d1x,d1y,d2x,d2y,u,v,m,n:integer;
begin
     u:= c - a;
     v:= d - b;
     d1x:= SGN(u);
     d1y:= SGN(v);
     d2x:= SGN(u);
     d2y:= 0;
     m:= ABS(u);
     n := ABS(v);
     IF NOT (M>N) then
     BEGIN
          d2x := 0 ;
          d2y := SGN(v);
          m := ABS(v);
          n := ABS(u);
     END;
     s := m shr 1;
     FOR i := 0 TO m DO
     BEGIN
          putpixel(a,b,col);
          s := s + n;
          IF not (s<m) THEN
          BEGIN
               s := s - m;
               a:= a + d1x;
               b := b + d1y;
          END
          ELSE
          BEGIN
               a := a + d2x;
               b := b + d2y;
          END;
     end;
END;

{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
end.

{ ------------------------------------------------------------------------- }
{ ------------------------------ PUBLICIDAD ------------------------------- }
{ --> Si lo que te gusta es programar, ­ OYE !, este es tu fanzine: ------- }
{ ------------------------- Virtual Zone Magazine ------------------------- }
{ ------------------------- C/ Camino de Ronda 38, 1§D -------------------- }
{ ------------------------- 18004 - Granada ------------------------------- }
{ ------------------------------------------------------------------------- }
