home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / MCGA#06.ZIP / LESSON06.TXT < prev   
Encoding:
Text File  |  1992-06-09  |  8.5 KB  |  432 lines

  1.                            MCGA Graphics Tutorial
  2.                                  Lesson #6
  3.                                 by Jim Cook
  4.  
  5. I am including the MCGALIB source we have developed so far in this
  6. tutorial.
  7.  
  8. Unit MCGALib;
  9.  
  10. interface
  11.  
  12. type
  13.   PCXHeaderPtr=  ^PCXHeader;
  14.   PCXHeader   =  record
  15.                    Signature      :  Char;
  16.                    Version        :  Char;
  17.                    Encoding       :  Char;
  18.                    BitsPerPixel   :  Char;
  19.                    XMin,YMin,
  20.                    XMax,YMax      :  Integer;
  21.                    HRes,VRes      :  Integer;
  22.                    Palette        :  Array [0..47] of byte;
  23.                    Reserved       :  Char;
  24.                    Planes         :  Char;
  25.                    BytesPerLine   :  Integer;
  26.                    PaletteType    :  Integer;
  27.                    Filler         :  Array [0..57] of byte;
  28.                  end;
  29.  
  30.   PointerType =  array [0..65500] of byte;
  31.   NewPointer  =  ^PointerType;
  32.  
  33. var
  34.   ScreenWide  :  Integer;
  35.  
  36. Procedure SetGraphMode (Num:Byte);
  37. Procedure SetPixel     (X,Y:Integer;Color:Byte);
  38. Function  GetPixel     (X,Y:Integer) : Word;
  39. Procedure ClearScreen  (Color:Byte);
  40. Procedure Line         (X1,Y1,X2,Y2:Integer;Color:Byte);
  41. Procedure Box          (X1,Y1,X2,Y2:Integer;Color:Byte);
  42.  
  43. Procedure DisplayPCX   (X,Y:Integer;Buf:Pointer);
  44.  
  45. Function  ImageSize    (X1,Y1,X2,Y2:Integer) : Word;
  46. Procedure GetImagePas  (X1,Y1,X2,Y2:Integer;P:Pointer);
  47. Procedure PutImagePas  (X1,Y1:Integer;P:Pointer);
  48.  
  49. implementation
  50.  
  51. var
  52.   ScreenAddr  :  Word;
  53.  
  54. Procedure SetGraphMode (Num:Byte);
  55. begin
  56.   asm
  57.     mov al,Num
  58.     mov ah,0
  59.     int 10h
  60.     end;
  61.   Case Num of
  62.     $13 : ScreenWide := 320;
  63.     end;
  64.   ScreenAddr := $A000;
  65. end;
  66.  
  67. Procedure SetPixel (X,Y:Integer;Color:Byte);
  68. begin
  69.   asm
  70.     push ds
  71.     mov  ax,ScreenAddr
  72.     mov  ds,ax
  73.  
  74.     mov  ax,Y
  75.     mov  bx,320
  76.     mul  bx
  77.     mov  bx,X
  78.     add  bx,ax
  79.  
  80.     mov  al,Color
  81.     mov  byte ptr ds:[bx],al
  82.     pop  ds
  83.     end;
  84. end;
  85.  
  86. Function GetPixel (X,Y:Integer) : Word;
  87. begin
  88.   asm
  89.     push ds
  90.     mov  ax,ScreenAddr
  91.     mov  ds,ax
  92.  
  93.     mov  ax,Y
  94.     mov  bx,320
  95.     mul  bx
  96.     mov  bx,X
  97.     add  bx,ax
  98.  
  99.     xor  ax,ax
  100.     mov  al,byte ptr ds:[bx]
  101.     mov  @Result,ax
  102.     pop  ds
  103.     end;
  104. end;
  105.  
  106. Procedure ClearScreen (Color:Byte);
  107. begin
  108.   asm
  109.     push es
  110.     mov  ax,ScreenAddr
  111.     mov  es,ax
  112.  
  113.     xor  di,di
  114.  
  115.     cld
  116.  
  117.     mov  al,Color
  118.     mov  cx,320*200
  119.  
  120.     rep  stosb
  121.  
  122.     pop  es
  123.     end;
  124. end;
  125.  
  126. Procedure HorzLine (X1,X2,Y1:Integer;Color:Byte);
  127. var
  128.   Temp   :  Integer;
  129. begin
  130.   If X1 > X2 then begin
  131.     Temp := X1;
  132.     X1   := X2;
  133.     X2   := Temp;
  134.     end;
  135.   asm
  136.     push es
  137.     mov  ax,ScreenAddr
  138.     mov  es,ax               { Point es to screen segment }
  139.  
  140.     mov  ax,Y1               { Calculate starting video memory location }
  141.     mov  di,ScreenWide
  142.     mul  di                  { Multiply row number by width of screen }
  143.     mov  di,X1
  144.     add  di,ax               { Add to that result the X value }
  145.                              { Result: es:di -> first pixel to draw }
  146.     mov  cx,X2
  147.     sub  cx,X1
  148.     inc  cx                  { cx = number of pixels to draw }
  149.  
  150.     cld
  151.     mov  al,Color            { put the color in al }
  152.  
  153.     rep  stosb               { use a fast 8088 instruction to store al }
  154.  
  155.     pop  es
  156.     end;
  157. end;
  158.  
  159. Procedure VertLine (X1,Y1,Y2:Integer;Color:Byte);
  160. var
  161.   Temp   :  Integer;
  162. begin
  163.   If Y1 > Y2 then begin
  164.     Temp := Y1;
  165.     Y1   := Y2;
  166.     Y2   := Temp;
  167.     end;
  168.   asm
  169.     push es
  170.     mov  ax,ScreenAddr
  171.     mov  es,ax               { Point es to screen segment }
  172.  
  173.     mov  ax,Y1               { Calculate starting video memory location }
  174.     mov  di,ScreenWide
  175.     mul  di                  { Multiply row number by width of screen }
  176.     mov  di,X1
  177.     add  di,ax               { Add to that result the X value }
  178.                              { Result: es:di -> first pixel to draw }
  179.     mov  cx,Y2
  180.     sub  cx,Y1
  181.     inc  cx                  { cx = number of pixels to draw }
  182.  
  183.     mov  al,Color            { put the color in al }
  184.  
  185. @Loop1:
  186.     mov  es:[di],al
  187.     add  di,ScreenWide
  188.     loop @Loop1
  189.  
  190.     pop  es
  191.     end;
  192. end;
  193.  
  194. Procedure Line (X1,Y1,X2,Y2:Integer;Color:Byte);
  195. var
  196.   I,
  197.   YIncr,
  198.   D,DX,DY,
  199.   AIncr,BIncr :  Integer;
  200.   Ofs         :  Word;
  201. begin                                  { uses Bresenham's algorithm for }
  202.   If X1 = X2 then begin                { drawing a line.  Very fast for }
  203.     VertLine (X1,Y1,Y2,Color);         { little ol' Pascal              }
  204.     Exit;
  205.     end;
  206.   If Y1 = Y2 then begin
  207.     HorzLine (X1,X2,Y2,Color);
  208.     Exit;
  209.     end;
  210.   If X1 > X2 then begin
  211.     D  := X1;
  212.     X1 := X2;
  213.     X2 := D;
  214.     D  := Y1;
  215.     Y1 := Y2;
  216.     Y2 := D;
  217.     end;
  218.   If Y2 > Y1 then YIncr :=  320
  219.              else YIncr := -320;
  220.   DX := X2 - X1;
  221.   DY := Abs (Y2-Y1);
  222.   D := 2 * DY - DX;
  223.   AIncr := 2 * (DY - DX);
  224.   BIncr := 2 * DY;
  225.  
  226.  
  227.   Ofs := Word(Y1) * 320 + Word(X1);
  228.  
  229.   Mem [$A000:Ofs] := Color;
  230.  
  231.   For I := X1 + 1 to X2 do begin
  232.     If D >= 0 then begin
  233.       Inc (Ofs,YIncr);
  234.       Inc (D,AIncr);
  235.       end
  236.     Else Inc (D,BIncr);
  237.     Inc (Ofs);
  238.     Mem [$A000:Ofs] := Color;
  239.     end;
  240. end;
  241.  
  242. Procedure Box (X1,Y1,X2,Y2:Integer;Color:Byte);
  243. var
  244.   Y :  Integer;
  245. begin
  246.   For Y := Y1 to Y2 do
  247.     HorzLine (X1,X2,Y,Color);
  248. end;
  249.  
  250. Procedure ExtractLineASM (BytesWide:Integer;Var Source,Dest:Pointer);
  251. var
  252.   DestSeg,
  253.   DestOfs,
  254.   SourceSeg,
  255.   SourceOfs   :  Word;
  256. begin
  257.   SourceSeg := Seg (Source^);
  258.   SourceOfs := Ofs (Source^);
  259.   DestSeg   := Seg (Dest^);
  260.   DestOfs   := Ofs (Dest^);
  261.  
  262.   asm
  263.     push  ds
  264.     push  si
  265.  
  266.     mov   ax,DestSeg
  267.     mov   es,ax
  268.     mov   di,DestOfs     { es:di -> destination pointer }
  269.     mov   ax,SourceSeg
  270.     mov   ds,ax
  271.     mov   si,SourceOfs   { ds:si -> source buffer }
  272.  
  273.     mov   bx,di
  274.     add   bx,BytesWide   { bx holds position to stop for this row }
  275.     xor   cx,cx
  276.  
  277.     cld
  278.  
  279.   @@GetNextByte:
  280.     cmp   bx,di          { are we done with the line }
  281.     jbe   @@ExitHere
  282.  
  283.     lodsb                { al contains next byte }
  284.  
  285.     mov   ah,al
  286.     and   ah,0C0h
  287.     cmp   ah,0C0h
  288.     jne   @@SingleByte
  289.                          { must be a run of bytes }
  290.     mov   cl,al
  291.     and   cl,3Fh
  292.     lodsb
  293.     rep   stosb
  294.     jmp   @@GetNextByte
  295.  
  296.   @@SingleByte:
  297.     stosb
  298.     jmp   @@GetNextByte
  299.  
  300.   @@ExitHere:
  301.     mov   SourceSeg,ds
  302.     mov   SourceOfs,si
  303.     mov   DestSeg,es
  304.     mov   DestOfs,di
  305.  
  306.     pop   si
  307.     pop   ds
  308.   end;
  309.  
  310.   If Odd(BytesWide) then Source := Ptr (SourceSeg,SourceOfs+2)
  311.                     else Source := Ptr (SourceSeg,SourceOfs);
  312.  
  313.   Dest := Ptr (DestSeg,DestOfs);
  314. end;
  315.  
  316. Procedure DisplayPCX (X,Y:Integer;Buf:Pointer);
  317. var
  318.   I,NumRows,
  319.   BytesWide   :  Integer;
  320.   Header      :  PCXHeaderPtr;
  321.   DestPtr     :  Pointer;
  322.   Offset      :  Word;
  323. begin
  324.   Header    := Ptr (Seg(Buf^),Ofs(Buf^));
  325.   Buf       := Ptr (Seg(Buf^),Ofs(Buf^)+128);
  326.   Offset    := Y * 320 + X;
  327.   NumRows   := Header^.YMax - Header^.YMin + 1;
  328.   BytesWide := Header^.XMax - Header^.XMin + 1;
  329.   If Odd (BytesWide) then Inc (BytesWide);
  330.  
  331.   For I := 1 to NumRows do begin
  332.     DestPtr := Ptr ($A000,Offset);
  333.     ExtractLineASM (BytesWide,Buf,DestPtr);
  334.     Inc (Offset,320);
  335.     end;
  336. end;
  337.  
  338. Function ImageSize (X1,Y1,X2,Y2:Integer) : Word;
  339. begin
  340.   ImageSize := Word(Y2 - Y1 + 1) * Word(X2 - X1 + 1) + 4;
  341. end;
  342.  
  343. Procedure GetImageAsm (X1,Y1,X2,Y2:Integer;P:Pointer); assembler;
  344. asm
  345.     mov  bx,ScreenWide
  346.     push ds
  347.     les  di,P
  348.  
  349.     cld
  350.  
  351.     mov  ax,0A000h
  352.     mov  ds,ax
  353.     mov  ax,Y1
  354.     mov  dx,320
  355.     mul  dx
  356.     add  ax,X1
  357.     mov  si,ax
  358.  
  359.     mov  ax,X2
  360.     sub  ax,X1
  361.     inc  ax
  362.     mov  dx,ax
  363.     stosw
  364.  
  365.     mov  ax,Y2
  366.     sub  ax,Y1
  367.     inc  ax
  368.     stosw
  369.     mov  cx,ax
  370.  
  371.   @@1:
  372.     mov  cx,dx
  373.  
  374.     shr  cx,1
  375.     rep  movsw
  376.  
  377.     test dx,1
  378.     jz   @@2
  379.     movsb
  380.   @@2:
  381.     add  si,bx
  382.     sub  si,dx
  383.  
  384.     dec  ax
  385.     jnz  @@1
  386.  
  387.     pop  ds
  388. end;
  389.  
  390. Procedure PutImageAsm (X1,Y1:Integer;P:Pointer); assembler;
  391. asm
  392.     mov  bx,ScreenWide
  393.     push ds
  394.     lds  si,P
  395.  
  396.     cld
  397.  
  398.     mov  ax,0A000h
  399.     mov  es,ax
  400.     mov  ax,Y1
  401.     mov  dx,320
  402.     mul  dx
  403.     add  ax,X1
  404.     mov  di,ax
  405.  
  406.     lodsw
  407.     mov  dx,ax
  408.  
  409.     lodsw
  410.  
  411.   @@1:
  412.     mov  cx,dx
  413.  
  414.     shr  cx,1
  415.     rep  movsw
  416.  
  417.     test dx,1
  418.     jz   @@2
  419.     movsb
  420.   @@2:
  421.     add  di,bx
  422.     sub  di,dx
  423.  
  424.     dec  ax
  425.     jnz  @@1
  426.  
  427.     pop  ds
  428. end;
  429.  
  430. Begin
  431. End.
  432.